原理说明

k8s cm在不配置subpath的情况下,当你更新挂载的文件内容的时候,也会同步更新到容器内部的文件(会有时延)类似prometheus等应用可以在文件更新后自动热加载新配置文件,但是诸如nginx\apache等应用并不会自己去加载文件reload,但这类应用往往支持通过信号的形式来控制,这时可以为其配一个sidecar容器以帮助其实现自动更新

参考文档:https://blog.fleeto.us/post/refresh-cm-with-signal/
https://www.jianshu.com/p/57e3819a2e7c
https://jimmysong.io/kubernetes-handbook/usecases/sidecar-pattern.html
https://izsk.me/2020/05/10/Kubernetes-deploy-hot-reload-when-configmap-update/

sidecar:全称sidecar proxy,为某种为了给应用程序提供补充功能而运行的单独的进程,通常以容器的形式和应用容器处于同一pod内,它可以在无需为应用程序添加额外的第三方组件的情况下为应用程序添加功能或者修改程序的代码和配置,目前已有较多成功的使用示例,如prometheus的社区开源高可用方案thaos

原理:使用inotify去监控config的变化,当发生改变的时候,使用信号去通知nginx加载配置文件,对于nginx来说可以使用nginx -s或kill来实现,需要注意两者之间信号相互的映射关系
http://io.upyun.com/2017/08/19/nginx-signals/
http://www.wuditnt.com/775/

-s signal      Send a signal to the master process.  The argument signal can be one of: stop, quit, reopen, reload.
                    The following table shows the corresponding system signals:
                    stop    SIGTERM
                    quit    SIGQUIT
                    reopen  SIGUSR1
                    reload  SIGHUP
SIGNALS
     The master process of nginx can handle the following signals:
     SIGINT, SIGTERM  Shut down quickly.
     SIGHUP           Reload configuration, start the new worker process with a new configuration, and gracefully shut
                      down old worker processes.
     SIGQUIT          Shut down gracefully.
     SIGUSR1          Reopen log files.
     SIGUSR2          Upgrade the nginx executable on the fly.
     SIGWINCH         Shut down worker processes gracefully.

示例

准备监听脚本

#!/bin/sh
while :
do
  # 获取文件名称
  REAL=`readlink -f ${FILE}`
  # 监控指定事件
  inotifywait -e delete_self "${REAL}"
  # 获取特定进程名称的 PID
  PID=`pgrep ${PROCESS} | head -1`
  # 发送信号
  kill "-${SIGNAL}" "${PID}"
  #nginx -s reload
done

准备sidecar

FROM alpine
RUN apk add --update inotify-tools
ENV FILE="/etc/nginx/conf.d/" PROCESS="nginx" SIGNAL="hup"
COPY inotifynginx.sh /usr/local/bin
CMD ["/usr/local/bin/inotifynginx.sh"]

准备yaml

apiVersion: apps/v1 
kind: Deployment
metadata: 
  name: nginx-test
spec: 
  replicas: 1
  selector: 
    matchLabels: 
      app: nginx-test
  template: 
    metadata: 
      labels: 
        app: nginx-test
    spec:
      shareProcessNamespace: true
      containers: 
      - name: "nginx-test"
        image: nginx
        ports: 
        - name: httpd  
          containerPort: 8888
          protocol: TCP 
        volumeMounts: 
          - mountPath: /etc/nginx/conf.d/
            name: nginx-config
            readOnly: true
          - mountPath: /usr/share/nginx/
            name: nginx-file
      - name: "inotify"
        image: inotify:v1
        imagePullPolicy: IfNotPresent
        volumeMounts: 
        - name: nginx-config
          mountPath: /etc/nginx/conf.d/
          readOnly: true
      volumes: 
      - name: nginx-config
        configMap: 
          name: nginx-config
      - name: nginx-file
        hostPath: 
          path: /tmp/nginx       
---

apiVersion: v1
kind: Service
metadata:
  name: nginx-service-test
spec: 
  selector: 
    app: nginx-test
  type: NodePort
  ports: 
    - port: 8888
      targetPort: 8888
      nodePort: 31111 

---
apiVersion: v1
kind: ConfigMap
metadata: 
  name: nginx-config
  labels: 
    app: nginx-test
data:
  test1.conf: | 
    server{
        listen *:8888;
        server_name www.test1.xyz;
        location  /
        {
                root /usr/share/nginx/;
                index test1.html;
        }
    }

pod中的容器间共享进程命名空间https://kubernetes.io/zh-cn/docs/tasks/configure-pod-container/share-process-namespace/,需要注意的是并不是所有的容器都适合这样的方法来实现,具体详情可以参考连接

测试

[root@worker-node01 ~]# curl 10.99.31.106:8888
test1
#修改cm中的index
[root@worker-node01 ~]# kubectl get cm
NAME               DATA   AGE
confnginx          1      4d1h
kube-root-ca.crt   1      24d
nginx-config       1      48s
[root@worker-node01 ~]# kubectl edit nginx-config
error: the server doesn't have a resource type "nginx-config"
[root@worker-node01 ~]# kubectl edit cm nginx-config
configmap/nginx-config edited
#可以发现nginx完成了自动热加载
[root@worker-node01 ~]# curl 10.99.31.106:8888
test2

标签: none

评论已关闭