【K8s】如果工作节点Node挂掉了,Pod 如何处理?

1,091 阅读4分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第2天,点击查看活动详情

使用副本集 ReplicaSet 或部署 Deployment 来创建并管理 Pod

这样部署可以自动运行、保持健康、工作节点挂掉之后 Pod 会自动迁移到新的节点,所以几乎不会手动创建 Pod

(1)副本集(RS)

副本集 ReplicaSet 是一种 Kubernetes 资源对象,它可以保证 Pod 始终处于运行状态。

如果 Pod 因任何原因消失,ReplicaSet 会注意到缺少了 Pod 并创建新的 Pod 进行替代。

ReplicaSet 主要用于创建和管理一个 Pod 的多个副本(replicas),核心标准是确保 Pod 的数量始终与其标签选择器匹配,它会持续监控正在运行的 Pod 列表,并保证带有对应标签的 Pod 数量与期望相符,如果运行的 Pod 太少会根据 Pod 模板创建新的副本;如果运行的 Pod 太多就会删除多余的副本。

ReplicaSet 由 3 个部分组成:

  • 标签选择器(label selector): 确定 ReplicaSet 作用域中有哪些 Pod
  • 副本个数(replica count): 指定应运行的 Pod 数量
  • Pod 模板(pod template): 用于创建新的 Pod 副本

上述的 3 个部分都可以随时修改,只有副本个数的变更会影响到现有的 Pod,更改标签选择器和 Pod 模板对现有的 Pod 没有影响。

如果更改标签选择器会使现有的 Pod 脱离 ReplicaSet 的范围,ReplicaSet 会停止关注它们;如果更改模板,只会对新创建的 Pod 应用新的模板,并不会影响现在存在的 Pod

使用 ReplicaSet 有以下 3 大好处:

  • 保证 Pod 持续运行,如果现有 Pod 数量不符合预期将会自动调整 Pod 的数量;
  • 当集群节点发生故障时,在故障节点受 ReplicaSet 控制的所有 Pod 会被创建新的替代副本;
  • 可以轻松实现 Pod 的水平伸缩。

注意, 这里的标签选择器可以匹配如下的标签:

  • 具有某个特定标签名和值的 Pod
  • 缺少某个标签的 Pod
  • 包含特定标签名,不管其值为多少的 Pod
  • 匹配多个标签,只要符合其中一个标签就认为是符合标准的

1)操作

创建一个 ReplicaSet

  1. nginx-replicaset.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: registry.cn-hangzhou.aliyuncs.com/chenshi-kubernetes/nginx:1.9.1
  1. 执行创建 kubectl create -f nginx-replicaset.yaml

  2. 查看创建的 podreplicaSet

$ kubectl get pods
$ kubectl get rs
  1. 查看详细描述 kubectl describe rs

  2. 删除定义的ReplicaSet

删除 ReplicaSet同时,会删除对应匹配的所有 Pod

kubectl delete rs nginx

(2)后台支撑服务集(DaemonSet

ReplicaSet 用于在 Kubernetes 集群上运行部署特定数量的 Pod,如果你希望在集群的每个 Node 上都运行某个 Pod,这个时候就需要使用到 DaemonSet 了,当有节点加入集群时,会为它们新增一个 Pod

当有节点从集群移除时,这些 Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有 Pod。

DaemonSet 的使用情况分为两种:

  • 在每个节点上运行一个 Pod
  • 在特定的节点上运行一个 Pod

1)在每个节点上运行一个

  1. 创建yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: mysql-ds
spec:
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
        - name: mysql
          image: mysql:5.7
          env:
            - name: MYSQL_ROOT_PASSWORD
              value: "123456"
  1. 执行创建
$ docker pull mysql:5.7
$ kubectl create -f mysql-ds.yaml
  1. 观察 Pod 是否分布到了每个节点上
$ kubectl get nodes
$ kubectl get pods -o wide

2)在特定的节点上运行一个

只需要在模板中的nodeSelector属性中指明即可。

  1. 先给节点打个标签
$ kubectl label node kube-node-1 disk1=ssd1
node/kube-node-1 labeled
  1. 创建yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: tomcat-ssd
spec:
  selector:
    matchLabels:
      app: tomcat
  template:
    metadata:
      labels:
        app: tomcat
    spec:
      nodeSelector:
        disk1: ssd1
      containers:
        - name: tomcat
          image: kubeguide/tomcat-app:v1
  1. 执行创建
$ kubectl create -f tomcat-ssd.yaml
daemonset.apps/tomcat-ssd created
  1. 更改标签,观察 DaemonSet 创建的 Pod是否还存在?
$ kubectl label node kube-node-1 disk1=hdd --overwrite
node/kube-node-1 labeled
  1. 查看节点上的 pod kubectl get pod

pod已经终止了。

(3)任务(Job

ReplicaSetDaemonSet 监控管理的 Pod 会持续不断的运行任务,这样的任务是没有完成态的,如果其中的进程退出了 Pod 会重新启动。

如果想要执行一个可完成的任务,当进程终止后 Pod 不再重新启动,那么就需要使用任务 (Job)。

当节点发生故障的时候,该节点上由 Job 管理的 Pod 会按照 ReplicaSetPod 的方式,重新安排到其它节点;如果进程异常退出,可以将 Job 配置为重新启动容器。

(1)模拟

模拟一个任务,有一个构建在 busybox 上的容器,该容器会调用 sleep 命令休息两分钟,然后就正常退出。

  1. 创建yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: batch-job
spec:
  template:
    metadata:
      labels:
        app: batch-job
    spec:
      # 当容器中的进程运行结束时,kubernetes会如何做
      restartPolicy: OnFailure
      containers:
        - name: main
          image: luksa/batch-job
  1. 执行创建
$ kubectl create -f sleep.yaml
job.batch/batch-job created
  1. 查看 JobPod
$ kubectl get jobs
$ kubectl get po

如果想让一项任务按顺序一次执行 10 次,可以使用 completions属性

spec:
  completions: 10
  template: ...

如果想要一项任务总共运行 10 次,每次可以并行执行 3个 Pod,可以使用 parallelism属性

spec:
  completions: 10
  parallelism: 3
  template: ...