我正在尝试使用零停机时间进行kubernetes nginx部署。该过程的一部分是启动rollingUpdate,确保至少有一个pod始终在运行nginx。这非常有效。
当旧的nginx pod正在终止时,我遇到了错误。 根据{{3}}上的kubernetes文档,kubernetes将:
我知道命令nginx -s quit
应该通过在主服务器终止之前等待所有工作者完成请求来优雅地终止nginx。它优雅地响应SIGQUIT命令,而SIGTERM导致暴力终止。其他论坛说它就像在部署中添加以下preStop挂钩一样简单:
lifecycle:
preStop:
exec:
command: ["/usr/sbin/nginx", "-s", "quit"]
但是,通过测试此命令,我发现nginx -s quit
立即返回,而不是等待工作人员完成。它也不会返回主进程的PID,这就是我希望D:
发生的事情是,kubernetes调用nginx -s quit
,它会向工作人员发送一个正确的SIGQUIT,但不要等待他们完成。相反,它会直接跳到第3步,而SIGTERM会转而采用这些流程,导致暴力终止,从而失去连接。
问题:有没有人想出一个在滚动部署期间优雅地关闭他们的nginx控制器并且没有停机时间的好方法? sleep
解决方法不够好,我正在寻找更强大的功能。
以下是完整部署yaml:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nginx-ingress-controller
spec:
replicas: 1
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 0
template:
metadata:
labels:
app: nginx-ingress-lb
spec:
terminationGracePeriodSeconds: 60
serviceAccount: nginx
containers:
- name: nginx-ingress-controller
image: gcr.io/google_containers/nginx-ingress-controller:0.9.0-beta.8
imagePullPolicy: Always
readinessProbe:
httpGet:
path: /healthz
port: 10254
scheme: HTTP
livenessProbe:
httpGet:
path: /healthz
port: 10254
scheme: HTTP
initialDelaySeconds: 10
timeoutSeconds: 5
args:
- /nginx-ingress-controller
- --default-backend-service=$(POD_NAMESPACE)/default-backend
- --v=2
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
ports:
- containerPort: 80
lifecycle:
preStop:
exec:
command: ["/usr/sbin/nginx", "-s", "quit"]
答案 0 :(得分:5)
我讨厌回答我自己的问题,但是在涂了一点之后,这就是我到目前为止所拥有的。
我创建了一个半阻塞的bash脚本,名为killer
:
#!/bin/bash
sleep 3
PID=$(cat /run/nginx.pid)
nginx -s quit
while [ -d /proc/$PID ]; do
sleep 0.1
done
我发现在nginx pod中有一个文件/run/nginx.pid
,它有主进程的PID。如果你打电话给nginx -s quit
并开始等待,直到该过程消失,你基本上已经退出命令"阻止"。
请注意,在发生任何事情之前都会有sleep 3
。这是由于竞争条件导致Kubernetes将一个吊舱标记为终止,但需要一点时间(<1s)将该吊舱从指向其的流量的服务中移除。
我已将此脚本安装到我的pod中,并通过preStop
指令调用它。它主要起作用,但在测试过程中仍然会偶尔出现一些问题,我发现卷曲错误表明连接是由同行重置的。&#34;但这是朝着正确方向迈出的一步。