在当今世界,由于需求的原因,服务可以在一天中频繁部署,并且可以为特定服务实施新开发。有时这些服务可能是短暂中断不成问题的服务,而有时它们可能是即使一个请求中断也会对客户产生负面影响的服务。在本文中,我将讨论如何消除这种中断,无论是对于 Kubernetes 还是使用 ASP.NET 开发的服务。
您可以访问这篇 文章 的土耳其语版本
内容
-
Kubernetes 端 Pod 的终止、创建和更新策略
-
.Net 端
Host
结构的检查 -
IHostedLifecycleService
、IHostedService
和IHostApplicationLifetime
接口的检查 -
Host 的关闭过程检查
-
使用
Kind
创建 Kubernetes 集群 -
创建一个示例
.Net
项目、Dockerfile
和Deployment
清单 -
将服务部署到 Kubernetes 集群并进行测试
-
Kubernetes Ingress 和 Kubernetes 控制平面之间的延迟
Kubernetes 更新策略
在 Kubernetes 端,更新策略在部署对象的清单中的 .spec.strategy.type
下指定。如果未指定此策略,则默认为 RollingUpdate
。
本文假设应用程序以 Deployment 对象发布。对于 StatefulSets 和 DaemonSets 对象,这些策略在
.spec.updateStrategy.type
规范下确定,这些策略为OnDelete
和RollingUpdate
。
重建 (Recreate)
yaml复制代码spec: replicas: 10 strategy: type: Recreate
在 Recreate
更新策略中,首先终止所有 pod,然后启动新版本的 pod。根据上述清单,Kubernetes 将首先杀死所有 10 个 pod,然后启动新 pod。此策略可能会导致停机(中断)。这是因为 Kubernetes 在创建新 pod 并取代之前终止了所有 pod。
滚动更新 (RollingUpdate)
yaml复制代码spec: replicas: 4 strategy: type: RollingUpdate rollingUpdate: maxUnavailable: 25% maxSurge: 25%
在 RollingUpdate
更新策略中,pod 会逐渐被新版本镜像替换。首先,创建一个带有新镜像编号的 pod,然后终止带有旧镜像编号的 pod。此操作会持续进行,直到所有 pod 都被替换。
在 RollingUpdate
策略中指定了 maxSurge
和 maxUnavailable
参数。
-
maxUnavailable
:指定更新阶段中可以不可用的 pod 数量。该值可以是百分比或直接的 pod 数量。这是一个可选字段,默认值为25%
。 -
maxSurge
:表示可以超过 Deployment 清单中指定的副本数量的 pod 数量。与maxUnavailable
类似,可以是百分比或直接的 pod 数量。这是一个可选字段,默认值为25%
。
当为上述字段指定百分比值时,如果 pod 数量不是整数,则
maxUnavailable
向下取整,maxSurge
向上取整。例如,当指定 1 个副本时,maxSurge
值通过向上取整对应于1,maxUnavailable
值通过向下取整对应于0。在这种情况下,首先创建一个 pod,在其转换为运行状态后,终止现有 pod。
通过滚动更新策略,Kubernetes 确保应用程序以最小的中断部署。以下是针对单个副本部署进行滚动更新操作时的阶段,以及示例部署清单:
yaml复制代码apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment labels: app: nginx spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.14.2 ports: - containerPort: 80 resources: limits: cpu: "0.3" memory: "75Mi" requests: cpu: "0.1" memory: "50Mi" strategy: type: RollingUpdate
当运行 kubectl set image deployment/nginx-deployment nginx=nginx:1.14.1
命令以更新镜像版本时,将执行以下阶段:
-
由于
maxSurge
值为1,首先启动一个带有新镜像编号的 pod。 -
在 pod 状态转换为
Running
后,Kubernetes 向旧 Pod 发送SIGTERM
信号。停止对 Pod 的新请求路由,并在spec.terminationGracePeriodSeconds
的持续时间内等待已进行的请求完成。 -
如果 Pod 的终止时间超过
spec.terminationGracePeriodSeconds
,Kubernetes 发送SIGKILL
信号并终止 pod。
对于上述部署,更新镜像版本时的 pod 状态按顺序如下:
sql复制代码kubectl get pods -n default -w NAME READY STATUS RESTARTS AGE nginx-deployment-59994fb97c-5j4fv 1/1 Running 0 8m8s nginx-deployment-59994fb97c-g789c 1/1 Running 0 8m9s nginx-deployment-59994fb97c-nddlf 1/1 Running 0 8m9s nginx-deployment-5fffc966ff-8crmb 0/1 Pending 0 1s nginx-deployment-5fffc966ff-8crmb 0/1 Pending 0 1s nginx-deployment-5fffc966ff-8crmb 0/1 ContainerCreating 0 1s nginx-deployment-5fffc966ff-8crmb 1/1 Running 0 1s nginx-deployment-59994fb97c-5j4fv 1/1 Terminating 0 8m16s nginx-deployment-5fffc966ff-52knq 0/1 Pending 0 0s nginx-deployment-5fffc966ff-52knq 0/1 Pending 0 0s nginx-deployment-5fffc966ff-52knq 0/1 ContainerCreating 0 0s nginx-deployment-59994fb97c-5j4fv 0/1 Terminating 0 8m16s nginx-deployment-5fffc966ff-52knq 1/1 Running 0 1s nginx-deployment-59994fb97c-g789c 1/1 Terminating 0 8m18s nginx-deployment-5fffc966ff-jwmtt 0/1 Pending 0 0s nginx-deployment-5fffc966ff-jwmtt 0/1 Pending 0 0s nginx-deployment-5fffc966ff-jwmtt 0/1 ContainerCreating 0 0s nginx-deployment-59994fb97c-5j4fv 0/1 Terminating 0 8m17s nginx-deployment-59994fb97c-5j4fv 0/1 Terminating 0 8m17s nginx-deployment-59994fb97c-5j4fv 0/1 Terminating 0 8m17s nginx-deployment-59994fb97c-g789c 0/1 Terminating 0 8m18s nginx-deployment-5fffc966ff-jwmtt 1/1 Running 0 1s nginx-deployment-59994fb97c-g789c 0/1 Terminating 0 8m19s nginx-deployment-59994fb97c-g789c 0/1 Terminating 0 8m19s nginx-deployment-59994fb97c-g789c 0/1 Terminating 0 8m19s nginx-deployment-59994fb97c-nddlf 1/1 Terminating 0 8m19s nginx-deployment-59994fb97c-nddlf 0/1 Terminating 0 8m19s nginx-deployment-59994fb97c-nddlf 0/1 Terminating
spec.terminationGracePeriodSeconds
值是在每个 Pod 的基础上定义的。默认值是 30秒。在发送
SIGTERM
信号到 sidecar 容器之前,首先会终止同一 Pod 中的主容器,然后按照定义的逆序发送SIGTERM
信号到 sidecar 容器。这样确保了在 Pod 中的 sidecar 容器在不再需要时被终止。在部署中的 nginx 应用程序在接收到
SIGTERM
信号时会迅速终止进程,包括开放的连接。因此,为了 优雅关闭,应在接收到SIGTERM
信号时进行跟踪,并发送SI