文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Kubernetes中Nginx配置热加载的过程是怎样的

2023-06-26 06:55

关注

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来忽略某个资源

Kubernetes中Nginx配置热加载的过程是怎样的

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

Kubernetes中Nginx配置热加载的过程是怎样的

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

Kubernetes中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配置文件

Kubernetes中Nginx配置热加载的过程是怎样的

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

Kubernetes中Nginx配置热加载的过程是怎样的

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

Kubernetes中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_DELETEwatcher = 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 mainimport (    "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}

ok,今天的内容就到这里

看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注编程网行业资讯频道,感谢您对编程网的支持。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯