您当前的位置:首页 > 电脑百科 > 程序开发 > 容器

Kubernetes中的优雅关闭和零停机时间部署

时间:2023-10-20 11:58:25  来源:微信公众号  作者:新钛云服

在Kube.NETes中,创建和删除Pod是最常见的任务之一。

当你执行滚动更新、扩展部署、发布新版本、执行作业和定时作业等操作时,都会创建Pod。

但是,在Pod被驱逐后,例如将节点标记为不可调度时,Pod也会被删除并重新创建。

如果这些Pod的性质是如此短暂,那么当一个Pod正在响应请求时,如果被告知关闭,会发生什么?在关闭之前,请求是否会完成?那么后续的请求呢?是否会被重定向到其他地方?

在讨论Pod被删除时会发生什么之前,有必要谈谈当Pod被创建时会发生什么。

假设你想在集群中创建以下Pod:

pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  contAIners:
    - name: web
      image: Nginx
      ports:
        - name: web
          containerPort: 80
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

你可以使用以下命令将YAML定义提交到集群中:

$ kubectl Apply -f pod.yaml
  • 1.

一旦你输入该命令,kubectl会将Pod定义提交给Kubernetes API。

在数据库中保存集群的状态

Pod的定义被API接收并进行检查,随后存储在数据库(etcd)中。

Pod也被添加到调度器的队列中。

调度器执行以下操作:

检查Pod的定义。

收集关于工作负载的详细信息,例如CPU和内存请求。

通过筛选器和判定的过程决定最适合运行该Pod的节点。

在此过程结束时:

  • Pod在etcd中被标记为已调度。
  • Pod被分配给一个节点。
  • Pod的状态被存储在etcd中。

然而,此时Pod仍然不存在。

  1. 当你使用kubectl apply -f命令提交一个Pod的YAML文件时,该YAML文件会被发送到Kubernetes API。

Kubernetes中的优雅关闭和零停机时间部署图片

  1. API将Pod保存在数据库(etcd)中。

Kubernetes中的优雅关闭和零停机时间部署图片

3. 调度器为该Pod分配了最适合的节点,Pod的状态变为Pending。此时,Pod只存在于etcd中。

Kubernetes中的优雅关闭和零停机时间部署图片

在控制平面中发生了前述任务,并且状态存储在数据库中。

**那么是谁在你的节点上创建Pod呢?

Kubelet-Kubernetes代理

Kubelet 的任务是轮询控制平面以获取更新。

你可以想象kubelet不断地向主节点发出请求:“我负责管理工作节点1,是否有新的Pod需要我处理?”

当有一个Pod需要处理时,kubelet会创建它,在某种程度上是这样的。

kubelet并不是直接创建Pod。相反,它将工作委托给其他三个组件:

  • 容器运行时接口(CRI):负责为Pod创建容器。
  • 容器网络接口(CNI):负责将容器连接到集群网络并分配IP地址。
  • 容器存储接口(CSI):负责在容器中挂载卷。

在大多数情况下,容器运行时接口(CRI)的工作类似于:

$ Docker run -d <my-container-image>
  • 1.

容器网络接口(CNI)更有趣,因为它负责以下任务:

  1. 为Pod生成有效的IP地址。
  2. 将容器连接到网络的其他部分。

正如你所想象的,连接容器到网络并分配有效的IP地址有多种方式(可以选择IPv4或IPv6,甚至可以分配多个IP地址)。

以Docker为例,它会创建虚拟以太网对并将其附加到一个桥接器上;而AWS-CNI会直接将Pod连接到虚拟私有云(VPC)的其余部分。

当容器网络接口完成其工作时,Pod将连接到网络的其余部分,并被分配一个有效的IP地址。

但是存在一个问题。

kubelet知道IP地址(因为它调用了容器网络接口),但控制平面不知道。

没有人告诉主节点Pod已被分配了IP地址,并且准备好接收流量。在控制平面的视角中,Pod仍在创建中。

kubelet的工作是收集Pod的所有细节,例如IP地址,并将其报告给控制平面。

你可以想象,检查etcd将不仅揭示Pod的运行位置,还会显示其IP地址。

1. Kubelet定期向控制平面轮询更新。

Kubernetes中的优雅关闭和零停机时间部署

2. 当一个新的Pod被分配给它所在的节点时,kubelet会获取该Pod的详细信息。

Kubernetes中的优雅关闭和零停机时间部署

3. kubelet本身不会创建Pod,它依赖于三个组件:容器运行时接口(Container Runtime Interface)、容器网络接口(Container Network Interface)和容器存储接口(Container Storage Interface)。

Kubernetes中的优雅关闭和零停机时间部署

4. 一旦这三个组件都成功完成,Pod就会在你的节点上运行,并分配了一个IP地址。

Kubernetes中的优雅关闭和零停机时间部署

5. kubelet将IP地址报告给控制平面。

Kubernetes中的优雅关闭和零停机时间部署

如果Pod不是任何服务的一部分,这就是任务的结束。Pod已创建并准备好使用。

当Pod是服务的一部分时,还需要进行一些额外的步骤。

Pods和服务

创建服务时,通常需要注意两个关键信息:

  1. 选择器(selector):用于指定接收流量的Pod。
  2. 目标端口(targetPort):Pod用于接收流量的端口。

一个典型的服务的YAML定义如下:

service.yaml

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  ports:
  - port: 80
    targetPort: 3000
  selector:
    name: app
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.

当你使用kubectl apply将服务提交到集群时,Kubernetes会查找所有具有与选择器(name: app)相同标签的Pod,并收集它们的IP地址,但前提是它们通过了就绪探针(Readiness probe)。

然后,对于每个IP地址,Kubernetes会将IP地址和端口连接起来。

如果IP地址是10.0.0.3,目标端口是3000,Kubernetes会将这两个值连接起来,并称其为一个端点(endpoint)。

IP address + port = endpoint
---------------------------------
10.0.0.3   + 3000 = 10.0.0.3:3000
  • 1.
  • 2.
  • 3.

这些端点将以另一个名为Endpoint的对象形式存储在etcd中。

有点困惑吗?

在Kubernetes中,以下术语适用:

endpoint(本文和Learnk8s材料中以小写字母e表示)是IP地址和端口对的组合(10.0.0.3:3000)。 Endpoint(本文和Learnk8s材料中以大写字母E表示)是一组端点的集合。 Endpoint对象是Kubernetes中的一个真实对象,对于每个服务,Kubernetes会自动创建一个Endpoint对象。

你可以使用以下命令进行验证:

$ kubectl get services,endpoints
NAME                   TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)
service/my-service-1   ClusterIP   10.105.17.65   <none>        80/TCP
service/my-service-2   ClusterIP   10.96.0.1      <none>        443/TCP


NAME                     ENDPOINTS
endpoints/my-service-1   172.17.0.6:80,172.17.0.7:80
endpoints/my-service-2   192.168.99.100:8443
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.

Endpoint会收集来自Pod的所有IP地址和端口。

但不仅如此。当发生以下情况时,Endpoint对象会使用新的端点列表进行刷新:

  1. 创建一个Pod。
  2. 删除一个Pod。
  3. 在Pod上修改标签。

因此,你可以想象,每当你创建一个Pod,并且kubelet将其IP地址提交给主节点后,Kubernetes会更新所有的端点以反映这种变化:

$ kubectl get services,endpoints
NAME                   TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)
service/my-service-1   ClusterIP   10.105.17.65   <none>        80/TCP
service/my-service-2   ClusterIP   10.96.0.1      <none>        443/TCP


NAME                     ENDPOINTS
endpoints/my-service-1   172.17.0.6:80,172.17.0.7:80
endpoints/my-service-2   192.168.99.100:8443
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.

很好,端点被存储在控制平面中,并且Endpoint对象已被更新。

1. 在这张图片中,你的集群中部署了一个单独的Pod。该Pod属于一个服务。如果你要检查etcd,你会发现Pod的详细信息以及服务的信息。

Kubernetes中的优雅关闭和零停机时间部署

2. 当部署新的Pod时会发生什么?

Kubernetes中的优雅关闭和零停机时间部署

3. Kubernetes需要跟踪Pod及其IP地址。服务应该将流量路由到新的端点,因此IP地址和端口应该被传播。

Kubernetes中的优雅关闭和零停机时间部署

4. 当另一个Pod被部署时会发生什么?

Kubernetes中的优雅关闭和零停机时间部署

5. 是的,完全相同的过程。在数据库中创建了新的“行”来表示新的Pod,并将端点进行传播。

Kubernetes中的优雅关闭和零停机时间部署

6. 当删除一个Pod时会发生什么?

Kubernetes中的优雅关闭和零停机时间部署

7. 服务立即移除该端点,最终该Pod也会从数据库中删除。

Kubernetes中的优雅关闭和零停机时间部署

8. Kubernetes对你的集群中的每一个小变化都做出反应。

Kubernetes中的优雅关闭和零停机时间部署

在Kubernetes中使用端点

端点在Kubernetes中被多个组件使用。

Kube-proxy使用端点来在节点上设置iptables规则。

因此,每当端点(Endpoint对象)发生变化时,kube-proxy会获取新的IP地址和端口列表,并编写新的iptables规则。

  1. 让我们考虑一个由三个节点组成的集群,其中有两个Pod,并且没有服务。Pod的状态被存储在etcd中。

Kubernetes中的优雅关闭和零停机时间部署

2. 当你创建一个服务(Service)时会发生什么?

Kubernetes中的优雅关闭和零停机时间部署

3. Kubernetes创建了一个Endpoint对象,并收集了来自Pod的所有端点(IP地址和端口对)。

Kubernetes中的优雅关闭和零停机时间部署

4. kube-proxy守护程序订阅对Endpoint的更改。

Kubernetes中的优雅关闭和零停机时间部署

5. 当Endpoint被添加、删除或更新时,kube-proxy会获取新的端点列表。

Kubernetes中的优雅关闭和零停机时间部署

6. kube-proxy使用端点来在集群的每个节点上创建iptables规则。

Kubernetes中的优雅关闭和零停机时间部署

Ingress控制器也使用相同的端点列表。

Ingress控制器是集群中将外部流量路由到集群内的组件。

当你设置一个Ingress配置文件时,通常会指定Service作为目标:

入口.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
spec:
  rules:
  - http:
      paths:
      - backend:
          service:
            name: my-service
            port:
              number: 80
        path: /
        pathType: Prefix
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.

实际上,流量并不会直接路由到Service。

相反,Ingress控制器建立了一个订阅,以便在Service的端点发生变化时收到通知。

Ingress直接将流量路由到Pods,跳过了Service。

正如你所想象的那样,每当Endpoint(对象)发生变化时,Ingress会获取新的IP地址和端口列表,并重新配置控制器以包括新的Pods。

  1. 在这张图片中,有一个带有两个副本的Ingress控制器和一个Service的部署(Deployment)。

Kubernetes中的优雅关闭和零停机时间部署

2. 如果你想通过Ingress将外部流量路由到Pods,你应该创建一个Ingress配置文件(一个YAML文件)。

Kubernetes中的优雅关闭和零停机时间部署

3. 一旦你运行kubectl apply -f ingress.yaml命令,Ingress控制器就会从控制平面中获取配置文件。

Kubernetes中的优雅关闭和零停机时间部署

4. Ingress的YAML文件中有一个serviceName属性,用于描述应该使用哪个Service。

Kubernetes中的优雅关闭和零停机时间部署

5. Ingress控制器从Service中检索端点列表,并跳过该Service。流量直接流向端点(Pods)。

Kubernetes中的优雅关闭和零停机时间部署

6. 当创建一个新的Pod时会发生什么?

Kubernetes中的优雅关闭和零停机时间部署

7. 你已经知道Kubernetes如何创建Pod并传播端点信息了。

Kubernetes中的优雅关闭和零停机时间部署

8. Ingress控制器订阅对端点的更改。由于有一个新的变化,它会获取新的端点列表。

Kubernetes中的优雅关闭和零停机时间部署

9. Ingress控制器将流量路由到新的Pod上。

Kubernetes中的优雅关闭和零停机时间部署

还有其他订阅端点更改的Kubernetes组件的示例。

集群中的DNS组件CoreDNS就是其中之一。

如果你使用Headless类型的Service,CoreDNS将需要订阅端点的更改,并在每次添加或删除端点时重新配置自身。

同样,服务网格(如Istio或Linkerd)、云服务提供商用于创建类型为LoadBalancer的服务,以及无数的操作员都会使用这些端点。

你必须记住,有多个组件订阅端点的更改,它们可能在不同的时间接收到关于端点更新的通知。

这就足够了,或者还有在创建Pod后发生的事情吗?

创建Pod时发生的主要步骤的简要回顾:

  1. Pod被存储在etcd中。
  2. 调度器分配一个节点,并将该节点写入etcd。
  3. kubelet收到新的已调度Pod的通知。
  4. kubelet将创建容器的任务委托给容器运行时接口(CRI)。
  5. kubelet将容器连接到容器网络接口(CNI)的任务委托给它。
  6. kubelet将容器中的挂载卷的任务委托给容器存储接口(CSI)。
  7. 容器网络接口分配一个IP地址。
  8. kubelet将IP地址报告给控制平面。
  9. IP地址被存储在etcd中。

如果你的Pod属于一个Service:

  1. kubelet等待成功的就绪探针(Readiness probe)。
  2. 所有相关的端点(对象)都会收到变更的通知。
  3. 端点将新的端点(IP地址+端口对)添加到它们的列表中。
  4. Kube-proxy收到端点变更的通知。Kube-proxy在每个节点上更新iptables规则。
  5. Ingress控制器收到端点变更的通知。控制器将流量路由到新的IP地址上。
  6. CoreDNS收到端点变更的通知。如果Service的类型是Headless,DNS条目将被更新。
  7. 云服务提供商收到端点变更的通知。如果Service的类型是LoadBalancer,新的端点将作为负载均衡池的一部分进行配置。
  8. 集群中安装的任何服务网格都会收到端点变更的通知。
  9. 任何订阅端点变更的其他操作员也会收到通知。

对于一个看似普通的任务——创建一个Pod来说,这个列表确实很长。

Pod已经运行起来了。现在是时候讨论一下当你删除Pod时会发生什么了。

删除Pod

你可能已经猜到了,但是当删除Pod时,你需要按照相同的步骤但是逆序进行操作。

首先,应该从Endpoint(对象)中移除端点。

这次Readiness probe会被忽略,并且端点会立即从控制平面中删除。

这反过来会触发kube-proxy、Ingress控制器、DNS、服务网格等所有事件。

这些组件将更新其内部状态,并停止将流量路由到该IP地址。

由于这些组件可能正在执行其他操作,无法保证从其内部状态中删除IP地址需要多长时间。对于某些组件来说,可能只需要不到一秒的时间;而对于其他组件来说,可能需要更长的时间。

对一些来说,这可能只需要不到一秒钟;对其他来说,这可能需要更多。

1. 如果你使用kubectl delete pod删除一个Pod,该命令首先会发送到Kubernetes API。

Kubernetes中的优雅关闭和零停机时间部署

2. 该消息会被控制平面中的特定控制器——Endpoint控制器所拦截。

Kubernetes中的优雅关闭和零停机时间部署

3. Endpoint控制器向API发送命令,将IP地址和端口从Endpoint对象中移除。

Kubernetes中的优雅关闭和零停机时间部署

4. 谁会监听Endpoint的更改?kube-proxy、Ingress控制器、CoreDNS等组件会收到关于这一变更的通知。

Kubernetes中的优雅关闭和零停机时间部署

5. 一些组件,如kube-proxy,可能需要额外的时间来进一步传播这些更改。

Kubernetes中的优雅关闭和零停机时间部署

与此同时,etcd中的Pod状态被更改为Terminating(终止中)。

kubelet收到此变更的通知,并进行以下操作:

  1. 将容器中的任何挂载卷从容器存储接口(CSI)卸载。
  2. 将容器从网络中分离,并释放IP地址给容器网络接口(CNI)。
  3. 将容器销毁给容器运行时接口(CRI)。

换句话说,Kubernetes按照与创建Pod完全相同的步骤来进行反向操作。

1. 如果你使用kubectl delete pod删除一个Pod,该命令首先会发送到Kubernetes API。

Kubernetes中的优雅关闭和零停机时间部署

2. 当kubelet轮询控制平面以获取更新时,它会注意到Pod已被删除。

Kubernetes中的优雅关闭和零停机时间部署

3. kubelet将销毁Pod的任务委托给容器运行时接口(Container Runtime Interface)、容器网络接口(Container Network Interface)和容器存储接口(Container Storage Interface)。

Kubernetes中的优雅关闭和零停机时间部署

然而,这里存在一个微妙但关键的区别。

当你终止一个Pod时,移除端点和向kubelet发送的信号同时发出。

当你首次创建一个Pod时,Kubernetes会等待kubelet报告IP地址,然后开始端点传播。

然而,当你删除一个Pod时,事件会并行发生。

这可能导致多种竞争条件的出现。

如果在端点传播之前删除了Pod会怎样呢?

1. 删除端点和删除Pod同时进行。

Kubernetes中的优雅关闭和零停机时间部署

2. 因此,在kube-proxy更新iptables规则之前,你可能会先删除端点。

Kubernetes中的优雅关闭和零停机时间部署

3. 或者你可能更幸运,只有在端点完全传播之后才删除Pod。

Kubernetes中的优雅关闭和零停机时间部署

优雅关闭

当一个Pod在从kube-proxy或Ingress控制器中移除端点之前被终止时,你可能会遇到停机时间。

如果仔细思考一下,这是有道理的。

Kubernetes仍然将流量路由到该IP地址,但Pod已经不存在了。

Ingress控制器、kube-proxy、CoreDNS等组件没有足够的时间将IP地址从其内部状态中移除。

理想情况下,Kubernetes应该在删除Pod之前等待集群中的所有组件都具有更新的端点列表。

但是Kubernetes并不是这样工作的。

Kubernetes提供了强大的原始组件来分发端点(例如Endpoint对象和更高级的抽象,如Endpoint Slices)。

然而,Kubernetes并不验证订阅端点变更的组件是否与集群状态保持同步。

那么,为了避免这种竞争条件并确保在端点传播后删除Pod,你可以做些什么呢?

你应该等待。当Pod即将被删除时,它会收到一个SIGTERM信号。

你的应用程序可以捕获该信号并开始关闭。

由于在Kubernetes中不太可能立即从所有组件中删除端点,你可以:

  1. 在退出之前等待更长的时间。
  2. 尽管收到SIGTERM信号,仍然处理传入的流量。
  3. 最后,关闭现有的长连接(例如数据库连接或WebSockets)。
  4. 关闭进程。

你应该等待多长时间呢?默认情况下,Kubernetes会发送SIGTERM信号,并在强制终止进程之前等待30秒钟。

因此,你可以在最初的15秒内继续正常运行。

希望这个时间间隔足够将端点移除的更改传播到kube-proxy、Ingress控制器、CoreDNS等组件。

随着时间的推移,越来越少的流量会到达你的Pod,直到最终停止。

在15秒之后,可以安全地关闭与数据库(或任何持久连接)的连接并终止进程。

如果你认为需要更多时间,可以在20或25秒时停止进程。

但是,请记住,Kubernetes将在30秒后强制终止进程(除非你在Pod定义中更改了terminationGracePeriodSeconds)。

如果无法更改代码以等待更长时间怎么办?你可以调用一个脚本等待固定的时间,然后让应用程序退出。

在调用SIGTERM之前,Kubernetes在Pod中提供了一个preStop钩子。你可以将preStop钩子设置为等待15秒钟。

让我们看一个示例:

pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
    - name: web
      image: nginx
      ports:
        - name: web
          containerPort: 80
      lifecycle:
        preStop:
          exec:
            command: ["sleep", "15"]
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.

preStop钩子是Pod生命周期钩子之一。

15秒的延迟是推荐的时间吗?这取决于情况,但这可能是开始测试的合理方式。

以下是你可以选择的选项的总结:

1. 你已经知道,当一个Pod被删除时,kubelet会收到这一变更的通知。

Kubernetes中的优雅关闭和零停机时间部署图片

2. 如果Pod具有preStop钩子,它会首先被调用。

Kubernetes中的优雅关闭和零停机时间部署

3. 当preStop钩子完成后,kubelet会向容器发送SIGTERM信号。从那时起,容器应该关闭所有长连接并准备终止。

Kubernetes中的优雅关闭和零停机时间部署

4. 默认情况下,进程有30秒的时间退出,其中包括preStop钩子的执行时间。如果进程在此期间未退出,kubelet将发送SIGKILL信号并强制终止进程。

Kubernetes中的优雅关闭和零停机时间部署

5. kubelet通知控制平面成功删除了该Pod。

Kubernetes中的优雅关闭和零停机时间部署

优雅期限和滚动更新

优雅关闭适用于被删除的Pod。

但如果你不删除Pod呢?即使你不删除Pod,Kubernetes也会定期删除Pod。

特别是,每当你部署应用程序的新版本时,Kubernetes会创建和删除Pod。

当你在部署中更改镜像时,Kubernetes会逐步推出变更。

pod.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: app
spec:
  replicas: 3
  selector:
    matchLabels:
      name: app
  template:
    metadata:
      labels:
        name: app
    spec:
      containers:
      - name: app
        # image: nginx:1.18 OLD
        image: nginx:1.19
        ports:
          - containerPort: 3000
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.

如果你有三个副本,并且在提交新的YAML资源给Kubernetes后,Kubernetes会:

  • 创建一个包含新容器镜像的Pod。
  • 销毁一个现有的Pod。
  • 等待Pod就绪。

然后它会重复上述步骤,直到所有的Pod都迁移到新版本。

Kubernetes只有在新的Pod准备好接收流量(也就是通过了就绪性检查)后才会重复每个周期。

Kubernetes在继续处理下一个Pod之前是否等待Pod被删除?

不会。

如果你有10个Pod,并且每个Pod需要2秒钟准备就绪和20秒钟关闭,情况如下:

  1. 首先创建一个新的Pod,并终止一个之前的Pod。
  2. 新的Pod需要2秒钟准备就绪,然后Kubernetes创建一个新的Pod。
  3. 与此同时,正在终止的Pod保持终止状态20秒钟。

在20秒钟之后,所有新的Pod都处于活动状态(10个Pod,在2秒钟后准备就绪),而之前的10个Pod都处于终止状态(第一个终止的Pod即将退出)。

总体而言,在短时间内你将拥有两倍数量的Pod(10个运行中,10个终止中)。

Kubernetes中的优雅关闭和零停机时间部署

与就绪探针相比,宽限期限越长,你将同时拥有更多的运行中(以及终止中)的Pod。

这是一件坏事吗?不一定,因为你要小心地确保不丢失连接。

终止长时间运行的任务

那对于长时间运行的作业呢?

如果你正在转码一个大型视频,有没有办法延迟停止Pod的操作?

想象一下,你有一个包含三个副本的部署。

每个副本被分配了一个视频进行转码,并且这个任务可能需要几个小时才能完成。

当你触发滚动更新时,Pod在被终止之前有30秒的时间来完成任务。

你如何避免延迟关闭Pod的操作?你可以将terminationGracePeriodSeconds增加到几个小时。

然而,在那个时间点上,Pod的端点是无法访问的。

Kubernetes中的优雅关闭和零停机时间部署

如果你将指标暴露用以监控Pod,你的监控工具将无法访问你的Pod。

为什么会这样?

像Prometheus这样的工具依赖于端点来抓取集群中的Pod。

然而,一旦你删除Pod,端点删除的信息会在集群中传播,甚至传递给Prometheus!

与其增加宽限期限,你应该考虑为每个新版本创建一个全新的部署。

当你创建一个全新的部署时,现有的部署将保持不变。

长时间运行的作业可以继续正常处理视频。一旦它们完成,你可以手动删除它们。

如果你希望自动删除它们,你可以设置一个自动缩放器,当任务用尽时,它可以将部署的副本数缩减为零。

这种 Pod 自动缩放器的一个例子是 Osiris——一个 Kubernetes 的通用、缩放到零的组件。

这种技术有时被称为Rainbow Deployments,在需要保持先前的Pod运行时间长于宽限期限的情况下非常有用。

另一个很好的例子是WebSockets。如果你正在向用户实时传输更新,你可能不希望每次发布时都终止WebSockets。

如果你在一天内频繁发布,这可能会导致实时数据流中断多次。

为每个发布创建一个新的部署是一个不太直观但更好的选择。

现有用户可以继续传输更新,而最新的部署为新用户提供服务。

随着用户从旧的Pod断开连接,你可以逐渐减少副本并淘汰过去的部署。

总结

你应该注意从集群中删除的Pod,因为它们的IP地址可能仍然被用于路由流量。

与立即关闭Pod不同,你应该考虑在应用程序中等待更长时间,或设置一个preStop钩子。

只有在集群中的所有端点都被传播并从kube-proxy、Ingress控制器、CoreDNS等中删除后,才应该删除Pod。

如果你的Pod运行长时间的任务,例如视频转码或使用WebSockets提供实时更新,请考虑使用Rainbow Deployments。在Rainbow Deployments中,你为每个发布创建一个新的部署,并在连接(或任务)耗尽时删除先前的部署。

你可以在长时间运行的任务完成后手动删除旧的部署。或者,你可以自动将部署的副本数缩减为零,以自动化该过程。



Tags:Kubernetes   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
Kubernetes 究竟有没有 LTS?
从一个有趣的问题引出很多人都在关注的 Kubernetes LTS 的问题。有趣的问题2019 年,一个名为 apiserver LoopbackClient Server cert expired after 1 year[1] 的 issue 中提...【详细内容】
2024-03-15  Search: Kubernetes  点击:(6)  评论:(0)  加入收藏
Kubernetes 集群 CPU 使用率只有 13% :这下大家该知道如何省钱了
作者 | THE STACK译者 | 刘雅梦策划 | Tina根据 CAST AI 对 4000 个 Kubernetes 集群的分析,Kubernetes 集群通常只使用 13% 的 CPU 和平均 20% 的内存,这表明存在严重的过度...【详细内容】
2024-03-08  Search: Kubernetes  点击:(12)  评论:(0)  加入收藏
聊聊 Kubernetes 网络模型综合指南
这篇详细的博文探讨了 Kubernetes 网络的复杂性,提供了关于如何在容器化环境中确保高效和安全通信的见解。译自Navigating the Network: A Comprehensive Guide to Kubernete...【详细内容】
2024-02-19  Search: Kubernetes  点击:(37)  评论:(0)  加入收藏
Kubernetes是什么?主要特点是什么?
Kubernetes是什么?Kubernetes,也称为K8s,是一个开源的容器编排系统,由Google首次开发和维护。它允许容器化的应用程序在集群中自动部署、扩展和管理。Kubernetes提供了一种容器...【详细内容】
2024-02-01  Search: Kubernetes  点击:(153)  评论:(0)  加入收藏
开发者的Kubernetes懒人指南
你可以将本文作为开发者快速了解 Kubernetes 的指南。从基础知识到更高级的主题,如 Helm Chart,以及所有这些如何影响你作为开发者。译自Kubernetes for Lazy Developers。作...【详细内容】
2024-02-01  Search: Kubernetes  点击:(50)  评论:(0)  加入收藏
Kubernetes Informer基本原理,你明白了吗?
本文分析 k8s controller 中 informer 启动的基本流程不论是 k8s 自身组件,还是自己编写 controller,都需要通过 apiserver 监听 etcd 事件来完成自己的控制循环逻辑。如何高...【详细内容】
2024-01-30  Search: Kubernetes  点击:(37)  评论:(0)  加入收藏
Kubernetes 100个常用命令!
这篇文章是关于使用 Kubectl 进行 Kubernetes 诊断的指南。列出了 100 个 Kubectl 命令,这些命令对于诊断 Kubernetes 集群中的问题非常有用。这些问题包括但不限于:&bull; 集...【详细内容】
2024-01-03  Search: Kubernetes  点击:(76)  评论:(0)  加入收藏
一文读懂Kubernetes部署策略
在这篇文章中,我们将深入研究 Kubernetes 部署概念和一些常见策略,了解每种策略的优缺点。合适的部署策略使我们能够在发布应用程序时最大限度地减少停机时间、增强客户体验并...【详细内容】
2024-01-03  Search: Kubernetes  点击:(59)  评论:(0)  加入收藏
从Kubernetes的探针到DevOps
今天在群里又看有人问如何设置 Kubernetes 的探针,感觉要补充的话太多了,结合我们在一些 DevOps 项目中痛苦的体验,今天一劳永逸的全部说完,此外,也为大家展现一下为什么 DevOps...【详细内容】
2023-12-27  Search: Kubernetes  点击:(114)  评论:(0)  加入收藏
如何基于Kubernetes运行Nacos高可用集群
Nacos(Namings and Configuration Management)是阿里巴巴开源的一个易于构建云原生应用的动态服务发现、配置管理和服务管理平台。以下是Nacos的一些主要功能和特点: 服务发现...【详细内容】
2023-12-18  Search: Kubernetes  点击:(69)  评论:(0)  加入收藏
▌简易百科推荐
Docker 和传统虚拟机有什么区别?
我有一个程序员朋友,他每年情人节都要送女朋友一台服务器。他说:“谁不想在过节当天收到一台 4核8g 的服务器呢?”“万一对方不要,我还能留着自己用。” 给他一次过节的机会,他能...【详细内容】
2024-03-26  小白debug  微信公众号  Tags:Docker   点击:(12)  评论:(0)  加入收藏
掌握Docker网络驱动程序:优化容器通信
Docker为在容器内包装、交付和运行应用程序提供了一个强大的平台,从而彻底改变了容器化。网络是容器化的重要组成部分,Docker提供了各种网络驱动程序来支持容器之间的通信以...【详细内容】
2024-03-22    51CTO  Tags:Docker   点击:(10)  评论:(0)  加入收藏
Containerd容器管理
Nginx 指定容器名称 使用 ctr container create 命令创建容器后,容器并没有处于运行状态,其只是一个静态的容器。容器基本操作容器基本操作主要是 ctr image 命令,查看命令帮...【详细内容】
2024-03-20  云原生运维圈  微信公众号  Tags:容器   点击:(13)  评论:(0)  加入收藏
如何基于Docker镜像逆向生成Dockerfile
引言你是否曾经遇到过一个想要使用的 Docker 镜像,但却无法修改以适应你的特定需求?或者你可能发现了一个喜欢的 Docker 镜像,但想要了解它是如何构建的?在这两种情况下,将 Docke...【详细内容】
2024-03-07  云原生运维圈  微信公众号  Tags:Docker   点击:(22)  评论:(0)  加入收藏
Kubernetes是什么?主要特点是什么?
Kubernetes是什么?Kubernetes,也称为K8s,是一个开源的容器编排系统,由Google首次开发和维护。它允许容器化的应用程序在集群中自动部署、扩展和管理。Kubernetes提供了一种容器...【详细内容】
2024-02-01    简易百科  Tags:Kubernetes   点击:(153)  评论:(0)  加入收藏
我们一起聊聊容器资源自愈
在企业实际在使用容器这类资源的时候,除了技术本身,要考虑的其他问题也会很多。企业管理的容器有千千万万,出于效率考虑,对于有特殊需求的容器如何进行批量创建和管理呢,这就需要...【详细内容】
2024-01-30  匠心独运维妙维效  微信公众号  Tags:容器   点击:(47)  评论:(0)  加入收藏
Docker与Docker Compose入门:释放你应用部署的威力
今天给大家介绍一项强大而有趣的技能,那就是使用 Docker 和 Docker Compose 来释放你的应用部署的威力!无论你是一名开发人员还是系统管理员,掌握这个技能都将为你的工作带来巨...【详细内容】
2024-01-17  waynblog  微信公众号  Tags:Docker   点击:(65)  评论:(0)  加入收藏
Docker镜像与容器的交互及在容器内部执行代码的原理与实践
Docker作为一种流行的容器技术,已经成为现代应用程序开发和部署的重要工具。在Docker中,镜像是构建和运行容器的基础,而容器则是基于镜像创建的可执行实例。Docker镜像与容器的...【详细内容】
2024-01-10  编程技术汇  今日头条  Tags:Docker   点击:(76)  评论:(0)  加入收藏
如何在 Ubuntu 上安装 Docker
使用 Docker 意味着开启一个新的计算领域,但如果你刚刚开始使用 Docker,安装可能看起来是一项艰巨的任务。在 Ubuntu 上安装 Docker 有两种推荐的方法: 从 Ubuntu 的仓库安装 D...【详细内容】
2024-01-04    Linux中国  Tags:Docker   点击:(124)  评论:(0)  加入收藏
从Kubernetes的探针到DevOps
今天在群里又看有人问如何设置 Kubernetes 的探针,感觉要补充的话太多了,结合我们在一些 DevOps 项目中痛苦的体验,今天一劳永逸的全部说完,此外,也为大家展现一下为什么 DevOps...【详细内容】
2023-12-27  云云众生s  微信公众号  Tags:Kubernetes   点击:(114)  评论:(0)  加入收藏
站内最新
站内热门
站内头条