Kubernetes Nginx 配置热加载

简介: Kubernetes Nginx 配置热加载


网络异常,图片无法展示
|

Nginx 本身是支持热更新的,通过 nginx -s reload 指令,实际通过向进程发送 HUB 信号实现不停服重新加载配置,然而在 Docker 或者 Kubernetes 中,每次都需要进容器执行 nginx -s reload 指令,单 docker 容器还好说,可以在外面通过 exec 指定容器执行该指令进行热加载,Kubernetes 的话,就比较难受了


今天介绍一下 Kubernetes 中 Nginx 热加载配置的处理方法——reloader


reloader 地址:https://github.com/stakater/Reloader


reloader 主要就是用来监测 ConfigMap 或 Secret 的变化,然后对相关 DeploymentConfig 的 Deployment、DaemonSet 执行滚动升级


reloader 需要 kubernetes1.9 以上的版本才支持

使用方法

首先是安装部署 reloader

# 直接通过官方yaml文件部署kubectl apply -f https://raw.githubusercontent.com/stakater/Reloader/master/deployments/kubernetes/reloader.yaml


默认情况下 reloader 是部署在 default 命名空间,但是它是监控所有命名空间的 configmaps 和 secrets


当然,如果不想监控某个 configmap 或 secret,可以通过--resources-to-ignore=configMaps/secrets 来忽略某个资源


网络异常,图片无法展示
|


部署成功后,就可以直接使用了,我提前部署了 nginx 和 configmap


网络异常,图片无法展示
|


这是目前的配置,看一下 Nginx 目前的配置

网络异常,图片无法展示
|


接着,我修改 Nginx 的 Deployment,添加 reloader,监听 nginx-config 这个 ConfigMap,执行

reload

{  "kind": "Deployment",  "apiVersion": "extensions/v1beta1",  "metadata": {    "name": "nginx",    "namespace": "default",    "selfLink": "/apis/extensions/v1beta1/namespaces/default/deployments/nginx",    "uid": "7eee5fa8-7514-11ec-a916-0210d5e9ca3b",    "resourceVersion": "286141",    "generation": 10,    "creationTimestamp": "2022-01-14T08:32:23Z",    "labels": {      "k8s-app": "nginx"    },    "annotations": {      "deployment.kubernetes.io/revision": "9",      "description": "nginx应用"      # 主要是这行      "reloader.stakater.com/reload": "nginx-config"    }  },  "spec": {    "replicas": 1,    "selector": {      "matchLabels": {        "k8s-app": "nginx"      }    }    ……


然后 apply 该 Deployment,之后我们去更新 ConfigMap,更新 nginx 配置文件


网络异常,图片无法展示
|

更新完成,去掉 proxy_redirect,然后去看 nginx 容器是否执行滚动更新


网络异常,图片无法展示
|


可以看到,nginx 执行了滚动更新,接着看下 nginx 配置文件是否更新


网络异常,图片无法展示
|

这样很简单的通过 reloader 就可以实现 Nginx 的配置热加载


除了这种方法,常见的方法还有使用 sidecar,通过 sidecar 去做的话,需要自己写监听脚本,比较麻烦,但是有时候也相对灵活,这里也附一个 sidecar 的 python 脚本


#!/usr/bin/env python# -*- encoding: utf8 -*-"""需求:nginx配置文件变化,自动更新配置文件,类似nginx -s reload实现:    1、用pyinotify实时监控nginx配置文件变化    2、如果配置文件变化,给系统发送HUP来reload nginx"""import osimport reimport pyinotifyimport loggingfrom threading import Timer
# ParamLOG_PATH = "/root/python/log"CONF_PATHS = [  "/etc/nginx",]DELAY = 5SUDO = FalseRELOAD_COMMAND = "nginx -s reload"if SUDO:  RELOAD_COMMAND = "sudo " + RELOAD_COMMAND
# Loglogger = logging.getLogger(__name__)logger.setLevel(level = logging.INFO)log_handler = logging.FileHandler(LOG_PATH)log_handler.setLevel(logging.INFO)log_formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')log_handler.setFormatter(log_formatter)logger.addHandler(log_handler)
# Reloaderdef reload_nginx():  os.system(RELOAD_COMMAND)  logger.info("nginx is reloaded")
t = Timer(DELAY, reload_nginx)
def trigger_reload_nginx(pathname, action):  logger.info("nginx monitor is triggered because %s is %s" % (pathname, action))  global t  if t.is_alive():    t.cancel()    t = Timer(DELAY, reload_nginx)    t.start()  else:    t = Timer(DELAY, reload_nginx)    t.start()
events = pyinotify.IN_MODIFY | pyinotify.IN_CREATE | pyinotify.IN_DELETE
watcher = pyinotify.WatchManager()watcher.add_watch(CONF_PATHS, events, rec=True, auto_add=True)
class EventHandler(pyinotify.ProcessEvent):  def process_default(self, event):    if event.name.endswith(".conf"):      if event.mask == pyinotify.IN_CREATE:        action = "created"      if event.mask == pyinotify.IN_MODIFY:        action = "modified"      if event.mask == pyinotify.IN_DELETE:        action = "deleted"      trigger_reload_nginx(event.pathname, action)
handler = EventHandler()notifier = pyinotify.Notifier(watcher, handler)
# Startlogger.info("Start Monitoring")notifier.loop()

如果喜欢用 go 的,这里也提供 go 脚本


package main
import (    "log"    "os"    "path/filepath"    "syscall"
    "github.com/fsnotify/fsnotify"    proc "github.com/shirou/gopsutil/process")
const (    nginxProcessName = "nginx"    defaultNginxConfPath = "/etc/nginx"    watchPathEnvVarName = "WATCH_NGINX_CONF_PATH")
var stderrLogger = log.New(os.Stderr, "error: ", log.Lshortfile)var stdoutLogger = log.New(os.Stdout, "", log.Lshortfile)
func getMasterNginxPid() (int, error) {    processes, processesErr := proc.Processes()    if processesErr != nil {        return 0, processesErr    }
    nginxProcesses := map[int32]int32{}
    for _, process := range processes {        processName, processNameErr := process.Name()        if processNameErr != nil {            return 0, processNameErr        }
        if processName == nginxProcessName {            ppid, ppidErr := process.Ppid()
            if ppidErr != nil {                return 0, ppidErr            }
            nginxProcesses[process.Pid] = ppid        }    }
    var masterNginxPid int32
    for pid, ppid := range nginxProcesses {        if ppid == 0 {            masterNginxPid = pid
            break        }    }
    stdoutLogger.Println("found master nginx pid:", masterNginxPid)
    return int(masterNginxPid), nil}
func signalNginxReload(pid int) error {    stdoutLogger.Printf("signaling master nginx process (pid: %d) -> SIGHUP\n", pid)    nginxProcess, nginxProcessErr := os.FindProcess(pid)
    if nginxProcessErr != nil {        return nginxProcessErr    }
    return nginxProcess.Signal(syscall.SIGHUP)}
func main() {    watcher, watcherErr := fsnotify.NewWatcher()    if watcherErr != nil {        stderrLogger.Fatal(watcherErr)    }    defer watcher.Close()
    done := make(chan bool)    go func() {        for {            select {            case event, ok := <-watcher.Events:                if !ok {                    return                }
                if event.Op&fsnotify.Create == fsnotify.Create {                    if filepath.Base(event.Name) == "..data" {                        stdoutLogger.Println("config map updated")
                        nginxPid, nginxPidErr := getMasterNginxPid()                        if nginxPidErr != nil {                            stderrLogger.Printf("getting master nginx pid failed: %s", nginxPidErr.Error())
                            continue                        }
                        if err := signalNginxReload(nginxPid); err != nil {                            stderrLogger.Printf("signaling master nginx process failed: %s", err)                        }                    }                }            case err, ok := <-watcher.Errors:                if !ok {                    return                }                stderrLogger.Printf("received watcher.Error: %s", err)            }        }    }()
    pathToWatch, ok := os.LookupEnv(watchPathEnvVarName)    if !ok {        pathToWatch = defaultNginxConfPath    }
    stdoutLogger.Printf("adding path: `%s` to watch\n", pathToWatch)
    if err := watcher.Add(pathToWatch); err != nil {        stderrLogger.Fatal(err)    }    <-done}



相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。 &nbsp; &nbsp; 相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
相关文章
|
应用服务中间件 Linux 网络安全
Centos 8.0中Nginx配置文件和https正书添加配置
这是一份Nginx配置文件,包含HTTP与HTTPS服务设置。主要功能如下:1) 将HTTP(80端口)请求重定向至HTTPS(443端口),增强安全性;2) 配置SSL证书,支持TLSv1.1至TLSv1.3协议;3) 使用uWSGI与后端应用通信(如Django);4) 静态文件托管路径设为`/root/code/static/`;5) 定制错误页面(404、50x)。适用于Web应用部署场景。
1109 87
|
11月前
|
编解码 应用服务中间件 Linux
centos配置nginx-rtmp实现ffmpeg转码rtsp为rtmp视频流
centos配置nginx-rtmp实现ffmpeg转码rtsp为rtmp视频流
742 1
|
负载均衡 应用服务中间件 nginx
Nginx配置与命令
Nginx 是一款高性能的 HTTP 和反向代理服务器,其配置文件灵活且功能强大。本文介绍了 Nginx 配置的基础结构和常用指令,包括全局块、Events 块、HTTP 块及 Server 块的配置方法,以及静态资源服务、反向代理、负载均衡、HTTPS 和 URL 重写等功能实现。此外,还提供了常用的 Nginx 命令操作,如启动、停止、重载配置和日志管理等,帮助用户高效管理和优化服务器性能。
1205 14
|
11月前
|
Ubuntu 安全 应用服务中间件
详细指南:配置Nginx服务器在Ubuntu平台上
以上步骤涵盖了基本流程:从软件包管理器获取 Ngnix, 设置系统服务, 调整UFW规则, 创建并激活服务器块(也称作虚拟主机), 并进行了初步优化与加固措施。这些操作都是建立在命令行界面上,并假设用户具有必要权限(通常是root用户)来执行这些命令。每个操作都有其特定原因:例如,设置开机启动确保了即使重启后也能自动运行 Ngnix;而编辑server block则定义了如何处理进入特定域名请求等等。
530 18
|
11月前
|
Ubuntu 安全 应用服务中间件
详细指南:配置Nginx服务器在Ubuntu平台上
以上步骤涵盖了基本流程:从软件包管理器获取 Ngnix, 设置系统服务, 调整UFW规则, 创建并激活服务器块(也称作虚拟主机), 并进行了初步优化与加固措施。这些操作都是建立在命令行界面上,并假设用户具有必要权限(通常是root用户)来执行这些命令。每个操作都有其特定原因:例如,设置开机启动确保了即使重启后也能自动运行 Ngnix;而编辑server block则定义了如何处理进入特定域名请求等等。
903 17
|
人工智能 缓存 Kubernetes
ACK GIE配置建议
Gateway with Inference Extension是基于Kubernetes社区Gateway API及其扩展规范实现的增强型组件,支持四层/七层路由服务,并面向生成式AI推理场景提供负载均衡优化、服务管理简化等能力,适用于AI推理服务的高可用部署与性能优化。在不同的场景使用ACK Gateway with Inference Extension时,可能需要根据业务需求和高可用需要对网关和推理扩展进行不同的配置调整。本文主要介绍在实际业务场景中针对ACK GIE的配置建议,以获得更好的使用效果。
890 23
|
12月前
|
数据建模 应用服务中间件 PHP
配置nginx容器和php容器协同工作成功,使用ip加端口的方式进行通信
本示例演示如何通过Docker挂载同一宿主目录至Nginx与PHP容器,实现PHP项目运行环境配置。需注意PHP容器中监听地址修改为0.0.0.0:9000,并调整Nginx配置中fastcgi_pass指向正确的IP与端口。同时确保Nginx容器中/var/www/html权限正确,以避免访问问题。
配置nginx容器和php容器协同工作成功,使用ip加端口的方式进行通信
|
应用服务中间件 网络安全 nginx
配置Nginx以支持Websocket连接的方法。
通过上述配置,Nginx将能够理解WebSocket协议的特殊要求,代理Websocket流量到合适的后端服务器。注意,Websocket并不是HTTP,尽管它最初是通过HTTP请求启动的连接升级,因此保证Nginx了解并能够妥善处理这种升级流程是关键。
2437 10
|
12月前
|
Ubuntu 应用服务中间件 Linux
在Ubuntu上配置Nginx实现开机自启功能
至此,Nginx应该已经被正确地设置为开机自启。在Ubuntu中利用 `systemd`对服务进行管理是一种高效的方式,为系统管理员提供了强大的服务管理能力,包括但不限于启动、停止、重启服务,以及配置服务的开机自启动。通过这些简洁的命令,即使是对Linux不太熟悉的用户也能轻松地进行配置。
523 0
|
安全 应用服务中间件 网络安全
Nginx SSL/TLS协议栈中配置深度解析与实践指南-优雅草卓伊凡
Nginx SSL/TLS协议栈中配置深度解析与实践指南-优雅草卓伊凡
887 0
Nginx SSL/TLS协议栈中配置深度解析与实践指南-优雅草卓伊凡

推荐镜像

更多