我正在尝试使用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
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
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
当我使用helm upgrade
命令升级映像时,我希望停机时间为零。同时,在进行升级时,我使用curl命令持续打我的服务。此curl命令在2-3秒内给我503-service Temporarily un-available
错误,然后服务再次启动。我希望这种停机时间不会发生。
答案 0 :(得分:0)
您描述的问题表明准备就绪探针存在问题。重要的是要了解活跃性和准备情况探针之间的差异。首先,您应该同时实现和配置两者!
活动性探针将检查容器是否已启动且仍处于活动状态。如果不是这种情况,kubernetes最终将重新启动容器。
准备情况探测还会依次检查依赖关系,例如数据库连接或您的容器要完成其工作所依赖的其他服务。作为开发人员,您需要在这里花更多的时间在实施上,而不仅仅是活动性探针。您必须公开一个端点,该端点在查询时还要检查提到的依赖项。
您当前的配置使用运行状况探针,通常由活动性探针使用。它可能不会检查您的服务是否真的准备好吸引流量。
Kubernetes依赖于准备情况探针。在滚动更新过程中,它将使旧容器保持运行状态,直到新服务声明已准备好接受流量为止。因此,准备情况探针必须正确实施。
答案 1 :(得分:0)
进行蓝绿色部署,因为即使Pod已启动,kube-proxy仍可能需要一些时间才能将请求转发到新的POD IP。
因此,在所有Pod都更新服务selector
至新的POD标签之后,设置新的部署。
跟随:https://kubernetes.io/blog/2018/04/30/zero-downtime-deployment-kubernetes-jenkins/
答案 2 :(得分:0)
此问题是由使用iptables的Service VIP引起的。您没有做错任何事情-这是当前Kubernetes的局限性。
当新Pod上的就绪探针通过并且旧Pod终止时,kube-proxy将重写该服务的iptables。但是,在旧的Pod终止之后,但在iptables更新之前,请求可以触发该服务,从而导致503。
在这种情况下可能无关紧要,但是在您的应用程序中实现优雅终止是个好主意。拦截TERM信号,并等待您的应用程序完成对它已经收到的所有请求的处理,而不是立即退出。
或者,更多的副本,较低的maxUnavailable
和较高的maxSurge
都将减少请求到达终止容器的可能性。
有关更多信息: https://kubernetes.io/docs/concepts/services-networking/service/#proxy-mode-iptables https://kubernetes.io/docs/concepts/workloads/pods/pod/#termination-of-pods
另一个答案错误地建议您需要一个活力探针。虽然有一个活跃的探针是一个好主意,但它不会影响您遇到的问题。没有定义活动探针,默认状态为成功。
在滚动部署的情况下,活动性探针将是无关紧要的-一旦新Pod上的就绪性探针通过旧Pod,就将发送TERM信号,并更新iptables。现在,旧的Pod即将终止,任何活动性探针都不再重要,因为它的唯一功能是在活动性探针失败时使Pod重新启动。
在新吊舱上再次进行任何活动探测均无关紧要。首次启动Pod时,默认情况下将其视为活动状态。仅在活动性探针的initialDelaySeconds
之后,才开始检查它,如果失败,则将终止该容器。
https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes