小知识: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

?
1
2
# 直接通过官方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配置热加载的全过程-1猿站网-插图

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

%小知识:Kubernetes中Nginx配置热加载的全过程-2猿站网-插图

接着,我修改nginx的deployment,添加reloader,监听nginx-config这个configmap,执行reload

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
{
“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配置热加载的全过程-3猿站网-插图

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

%小知识:Kubernetes中Nginx配置热加载的全过程-4猿站网-插图

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

%小知识:Kubernetes中Nginx配置热加载的全过程-5猿站网-插图

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#!/usr/bin/env python
# -*- encoding: utf8 -*-
“””
需求:nginx配置文件变化,自动更新配置文件,类似nginx -s reload
实现:
1、用pyinotify实时监控nginx配置文件变化
2、如果配置文件变化,给系统发送hup来reload nginx
“””
import os
import re
import pyinotify
import logging
from threading import timer
# param
log_path = “/root/python/log”
conf_paths = [
“/etc/nginx”,
]
delay = 5
sudo = false
reload_command = “nginx -s reload”
if sudo:
reload_command = “sudo ” + reload_command
# log
logger = 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)
# reloader
def 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)
# start
logger.info(“start monitoring”)
notifier.loop()

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
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
}

ok,今天的内容就到这里

总结

到此这篇关于kubernetes中nginx配置热加载的文章就介绍到这了,更多相关kubernetes中nginx配置热加载内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://mp.weixin.qq.com/s/dcqprANA0m6gGEvnF2l4uQ

声明: 猿站网有关资源均来自网络搜集与网友提供,任何涉及商业盈利目的的均不得使用,否则产生的一切后果将由您自己承担! 本平台资源仅供个人学习交流、测试使用 所有内容请在下载后24小时内删除,制止非法恶意传播,不对任何下载或转载者造成的危害负任何法律责任!也请大家支持、购置正版! 。本站一律禁止以任何方式发布或转载任何违法的相关信息访客发现请向站长举报,会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。本网站的资源部分来源于网络,如有侵权烦请发送邮件至:2697268773@qq.com进行处理。
建站知识

小知识:Nginx可视化配置工具NginxWebUI的使用

2023-3-19 1:27:51

建站知识

小知识:Nginx 代理解决跨域问题多种情况分析

2023-3-19 1:46:52

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索