【发布时间】:2021-05-11 02:43:49
【问题描述】:
我正在尝试在 k8s 上实现零停机部署。我的部署有一个副本。 pod 探针如下所示:
apiVersion: apps/v1
kind: Deployment
metadata:
name: app
namespace: ${KUBE_NAMESPACE}
spec:
selector:
matchLabels:
app: app
replicas: 1
template:
metadata:
labels:
app: app
spec:
containers:
- name: app-container
imagePullPolicy: IfNotPresent
image: ${DOCKER_IMAGE}:${IMAGE_TAG}
ports:
- containerPort: 80
livenessProbe:
httpGet:
path: /health
port: 80
initialDelaySeconds: 5
periodSeconds: 5
readinessProbe:
httpGet:
path: /health
port: 80
initialDelaySeconds: 5
periodSeconds: 10
terminationGracePeriodSeconds: 130
但是,每次kubectl rollout status 返回并报告部署完成后。我经历了bad gateway的一小段时间。
然后我添加一个测试,让 /health 在 prestop 返回 500,并在实际停止 pod 之前至少等待 20 秒。
# If the app test the /tmp/prestop file exists, it will return 500.
lifecycle:
preStop:
exec:
command: ["/bin/bash", "-c", "touch /tmp/prestop && sleep 20"]
然后我发现k8s停止pod后,流量仍然可以流到旧的pod(如果我访问/health可以得到500的结果)。
所以看起来负载均衡器决定了哪些 pod 可以仅由探测结果使用。由于探针有一段时间,因此总会有一个小窗口,其中 pod 停止但负载均衡器仍然不知道并且可以将流量引导到它,因此用户会遇到停机时间。
所以我的问题是:为了实现零停机部署,似乎必须在实际停止 Pod 之前让探针知道 Pod 正在停止。这是正确的吗?还是我做错了什么?
【问题讨论】:
-
你使用什么负载均衡器?
-
@Jonas 应用程序负载均衡器在 Amazon EKS 上。
-
通常要实现零停机,解决方案通常是让多个 Pod 服务于同一个应用程序,这样在推出时,一次重启一个 Pod,这意味着没有停机时间。如果有问题的应用程序是无状态的,这很容易做到。如果应用程序有状态,那就不太容易了
-
@AndD 我认为在这种情况下,吊舱的数量并不重要。只要 pod 停止但负载均衡器不知道,客户端就有可能直接访问停止的 pod,从而导致停机。我认为绿/蓝部署不会有这个问题。
-
ALB 是否将流量发送到 IP 或 NodePort? (两者都是可能的配置)
标签: kubernetes