我正在尝试使用 Kubernetes 实现零停机部署。但是每次我使用新映像升级部署时,我都会看到 2-3 秒的停机时间。我正在使用 Hello-World 类型的应用程序对此进行测试,但仍然无法实现。我正在使用 Helm 图表部署我的应用程序。
根据在线博客和资源,我在 Deployment.yaml 文件中使用了就绪探测和滚动更新策略。但这没有给我任何成功。我创建了一个/health
端点,它简单地返回200
状态代码作为准备探测的检查。我希望在 Kubernetes 中使用就绪探针和 RollingUpdate 策略后,当我升级容器的映像时,我将能够实现服务的零停机。对我的服务的请求通过 Amazon ELB。
Deployment.yaml 文件如下:
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: wine-deployment
labels:
app: wine-store
chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 0
maxSurge: 1
selector:
matchLabels:
app: wine-store
replicas: 2
template:
metadata:
labels:
app: wine-store
spec:
containers:
- name: {{ .Chart.Name }}
resources:
limits:
cpu: 250m
requests:
cpu: 200m
image: "my-private-image-repository-with-tag-and-version-goes-here-which-i-have-hidden-here"
imagePullPolicy: Always
env:
- name: GET_HOSTS_FROM
value: dns
ports:
- containerPort: 8089
name: testing-port
readinessProbe:
httpGet:
path: /health
port: 8089
initialDelaySeconds: 3
periodSeconds: 3
Run Code Online (Sandbox Code Playgroud)
Service.yaml 文件:
apiVersion: v1
kind: Service
metadata:
name: wine-service
labels:
app: wine-store
spec:
ports:
- port: 80
targetPort: 8089
protocol: TCP
selector:
app: wine-store
Run Code Online (Sandbox Code Playgroud)
Ingress.yaml 文件:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: wine-ingress
annotations:
kubernetes.io/ingress.class: public-nginx
spec:
rules:
- host: my-service-my-internal-domain.com
http:
paths:
- path: /
backend:
serviceName: wine-service
servicePort: 80
Run Code Online (Sandbox Code Playgroud)
当我使用helm upgrade
命令升级映像时,我希望停机时间为零。同时,在升级过程中,我不断使用 curl 命令访问我的服务。这个 curl 命令给了我503-service Temporarily un-available
2-3 秒的错误,然后服务再次启动。我希望这种停机时间不会发生。
此问题是由 Service VIP 使用 iptables 引起的。你没有做错任何事——这是当前 Kubernetes 的一个限制。
当新 Pod 上的就绪探测通过时,旧 Pod 终止,kube-proxy 重写服务的 iptables。但是,在旧 pod 终止之后但在 iptables 更新之前,请求可能会命中服务,从而导致 503。
一个简单的解决方法是使用preStop
生命周期钩子延迟终止:
lifecycle:
preStop:
exec:
command: ["/bin/bash", "-c", "sleep 10"]
Run Code Online (Sandbox Code Playgroud)
在这种情况下它可能不相关,但在您的应用程序中实现优雅终止是一个好主意。拦截 TERM 信号并等待您的应用程序完成处理它已经收到的任何请求,而不是立即退出。
或者,更多的副本,低maxUnavailable
和高maxSurge
都会降低请求命中终止 pod 的可能性。
更多信息:https : //kubernetes.io/docs/concepts/services-networking/service/#proxy-mode-iptables https://kubernetes.io/docs/concepts/workloads/pods/pod/#termination-of -豆荚
另一个答案错误地表明您需要进行活性探测。虽然进行活性探测是个好主意,但它不会影响您遇到的问题。没有定义活性探针,默认状态是成功。
在滚动部署的情况下,活性探针将无关紧要 - 一旦新 pod 上的就绪探针通过,旧 pod 将被发送 TERM 信号并且 iptables 将被更新。现在旧的 pod 正在终止,任何活性探针都无关紧要,因为它的唯一功能是在活性探针失败时重新启动 pod。
新 Pod 上的任何活性探测都是无关紧要的。当 pod 首次启动时,默认情况下它被认为是活动的。只有在initialDelaySeconds
活性探针结束后才会开始检查,如果失败,pod 将被终止。
https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes
您描述的问题表明就绪探针存在问题。了解活性探针和就绪探针之间的差异非常重要。首先,您应该实现并配置两者!
\n\n存活探针用于检查容器是否已启动且存活。如果不是\xe2\x80\x99t这种情况,kubernetes最终将重新启动容器。
\n\n就绪探针还会检查容器所依赖的数据库连接或其他服务等依赖关系,以完成它\xe2\x80\x99 的工作。作为开发人员,您必须在实施上投入更多的时间,而不仅仅是活性探针。您必须公开一个端点,该端点在查询时也会检查提到的依赖关系。
\n\n您当前的配置使用通常由活性探测器使用的运行状况端点。它可能不会检查您的服务是否真的准备好接受流量。
\n\nKubernetes 依赖于就绪探针。在滚动更新期间,它将保持旧容器的启动和运行,直到新服务声明它已准备好接收流量。因此,必须正确实施就绪探测。
\n 归档时间: |
|
查看次数: |
1804 次 |
最近记录: |