Skip to content

云原生05-Pod高级

  1. nodeName: 在 Kubernetes 中,NodeName 是每个 Node 节点的唯一标识符,它是一个字符串,通常是节 点的主机名(hostname)。在创建 Pod 时,可以通过指定 nodeName 字段来将 Pod 调度到特定的 Node 节点上。

pod-node.yaml

apiVersion: v1
kind: Pod
metadata:
  name: demo-pod
  namespace: default
  labels:
    app: busybox-tomcat
    env: pro
spec:
  nodeName: xuegod64
  containers:
    - name: tomcat
      image: tomcat:8.5-jre8-alpine
      ports:
        - containerPort: 8080
      imagePullPolicy: IfNotPresent
    - name: busybox
      image: busybox
      imagePullPolicy: IfNotPresent
      command: ["/bin/sh", "-c", "sleep 3600"]
$ kubectl apply -f pod-node.yaml
# 查看调度是否在  xuegod64 节点上
$ kubectl get pod -owide
  1. nodeSelector: 在 Kubernetes 中,Node 节点选择器(NodeSelector)是用来将 Pod 调度到特定节点的一种机 制。它基于 Node 节点的标签(Node·Labels)来进行筛选和匹配,从而使 Pod 能够被分配到满足其要 求的节点上。 具体来说,Node 节点选择器允许用户为 Node 节点打上一组键值对标签,例如: nodeType=compute、diskType=ssd 等等。当用户在创建 Pod 时指定一个或多个 Node·Selector 时,Kubernetes 调度器会根据这些选择器的键值对与 Node 节点的标签进行匹配,最终将 Pod 分配到 匹配的节点上。 例如,如果用户定义了一个 Pod 需要一个节点具有标签“nodeType=compute”,那么 Kubernetes 调度器将只会将该 Pod 调度到具有此标签的节点上。如果没有节点具有该标签,则 Pod 将 保持处于 Pending 状态直到有符合条件的节点出现。

  2. 例子展示:给 node 节点打标签打个具有 diskType=ssd 的标签

$ kubectl label nodes xuegod62 diskType=ssd

vim pod-1.yaml

apiVersion: v1
kind: Pod
metadata:
  name: demo-pod-1
  namespace: default
  labels:
    app: busybox-tomcat
    env: pro
spec:
  nodeSelector:
    diskType: ssd
  containers:
    - name: tomcat
      image: tomcat:8.5-jre8-alpine
      ports:
        - containerPort: 8080
      imagePullPolicy: IfNotPresent

Pod 高级用法:亲和性 affinity

  • 在 Kubernetes 中,亲和性(Affinity)是一种机制,用于控制 Pod 调度器将 Pod 调度到与其最匹 配的节点上。亲和性机制允许用户定义一组规则,以便将 Pod 调度到具有指定特征的节点上,这些特征 可以是节点的标签(Labels)、污点(Taints)或其他属性。
  • 亲和性有两种类型:节点亲和性(Node·Affinity)和 Pod 亲和性(Pod·Affinity)。节点亲和性指 定了节点和 Pod 之间的关系,而 Pod 亲和性指定了 Pod 和其他 Pod 之间的关系。

node 节点亲和性

node 节点亲和性:: nodeAffinity

kubectl explain pods.spec.affinity

  • preferredDuringSchedulinglgnoredDuringExecution : preferredDuringSchedulinglgnoredDuringExecution 是 Kubernetes 中节点亲和性(Node· Affinity)的一种规则类型,它允许用户指定Pod调度器尽可能将Pod调度到与指定节点亲和的节点 上,但如果没有可用的这样的节点,Pod也可以调度到其他节点上

  • requiredDuringSchedulinglgnoredDuringExecution:这个字段指定了一个节点选择器,Pod 只能被调度到满足这个节点选择器的节点上。如果没有节点满足这个要求,Pod·就无法被调度。

  • 例 1:使用 requiredDuringSchedulinglgnoredDuringExecution

docker.io/ikubernetes/myapp:v1

nodeAffinity.yaml

apiVersion: v1
kind: Pod
metadata:
  name: nodeaffinity-1
  namespace: default
  labels:
    app: myapp
    item: pro
spec:
  containers:
    - name: myapp
      image: ikubernetes/myapp:v1
      imagePullPolicy: IfNotPresent
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
          - matchExpressions:
              - key: a
                operator: In
                values:
                  - b

没打 a=b 标签的此 pod 会在 pending 状态

# 打完后其会自动调度到对应节点,状态会变出 running
$ kubectl label nodes xuegod64 a=b
  1. 例 1:使用 preferredDuringSchedulingIgnoredDuringExecution

nodeAffinity-1.yaml

apiVersion: v1
kind: Pod
metadata:
  name: nodeaffinity-2
  namespace: default
  labels:
    app: myapp1
    item: pro1
spec:
  containers:
    - name: myapp
      image: ikubernetes/myapp:v1
      imagePuLlPolicy: IfNotPresent
  affinity:
    nodeAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
        - preference:
            matchExpressions:
              - key: a1
                operator: In
                values:
                  - b1
          weight: 80

备注:yaml 文件解释:微软雅黑 BIUA 式捐定权重”定义(D)“来新建和段落居中段落 批注 使用·weight·字段来指定权重。weight·字段是一个整数值,表示优先级,取值范围为·1·到 100。如果多个节点满足软亲和性的要求,那么·Kubernetes·会根据节点的权重来决定 pod 最终调度的 节点。在这个例子中,weight=80·表示这个软亲和性的优先级为 80。

具体案例分享: 假设我们有一个·Kubernetes·集群,其中有多个节点,每个节点都有不同的标签。现在有一个 Pod,需要运行在·CPU·性能较好的节点上,同时如果有多个节点都满足要求,优先选择具有更多内存的 节点。此时,我们可以使用节点亲和性和软亲和性来指定·Pod·的调度。

首先,我们可以在节点上添加标签,例如,我们可以给性能较好的节点打上·cpu=high·的标签,给 内存较大的节点打上·memory=large 的标签。

其次,我们可以在·Pod·的配置文件中,使用 requiredDuringSchedulinglgnoredDuringExecution·字段来指定硬亲和性,让·Pod·只能调度到具 有·cpu=high·标签的节点上。

最后,我们可以使用·preferredDuringScheilinglgnoreddDuringExecution·字段来指定软亲和 性,同时设置权重值,让·Kubernetes·在有多个节点满足软亲和性时,优先选择具有更多内存的节点。 例如,我们可以设置节点亲和性为:

在这个配置中,requiredDuringSchedulinglgnoredDuringExecution·字段指定·Pod·只能调度 到具有·cpu=high·标签的节点上,preferredDuringSchedulinglgnoredDuringExecution·字 段指定软亲和性,表示优先选择具有更多内存的节点进行调度。

xuegod64、xuegod65、xuegod66、xuegod67 cpu=high. · cpu=high..· cpu=high.· cpu=high memory=large·· memory1=large1

所以上面可以看到,软亲和性定义了两个,要优先找到具有 memory=large 标签的节点,或者具有 memory1=large1 标签的节点,但是 memory=large·这歌标签的 weight 值大,权重高,就会优先 调度到具有 memory=large 标签的节点 xuegod64 上

Pod 和 Pod 亲和性

Kubernetes·中的·Pod·亲和性可以用来控制将一个·Pod·调度到与其它·Pod·具有特定关系的节点上。这可以实现多种不同的需求,例如:

  • 通过 pod 亲和性提高服务的性能和可靠性:通通过将相关服务部署在同一个节点上,可以降低网络延迟和提高服务响应速度。此外,如果某个节点出现故障,只会影响到部署在该节点上的服务,不会影响到其它服务。通过 pod 反亲和性分离敏感数据
  • 通过将处理敏感数据的·Pod·与其它·Pod·隔离开来,不调度到同一个节点上可以提高系统的安全性

podAffinity:表示 Pod 与其它 Pod 的亲和性。可以使用 requiredDuringSchedulinglgnoredDuringExecution, preferredDuringSchedulinglgnoredDuringExecution 等字段来指定 Pod 与其它 Pod 的亲和性规则。这些字段中可以使用topologyKeylabelSelector字段来指定 Pod 之间的关系。

pod 亲和性分两种:

  • podaffinity(pod 亲和性):Pod·亲和性是指一组·Pod·可以被调度到同一节点上,即它们互相吸引,倾向于被调度在同一台节点上。例如,假设我们有一组具有相同标签的·Pod,通过使用·Pod·亲和性规则,我们可以让它们在同一节点上运行,以获得更高的性能和更好的可靠性。

  • podunaffinity(pod 反亲和性):Pod·反亲和性是指一组·Pod·不应该被调度到同一节点上,即它们互相排斤,避免被调度在同一台节点上。例如,如果我们有一组应用程序·Pod,我们可以使用·Pod·反亲和性规则来避免它们被调度到同一节点上,以减少单点故障的风险和提高可靠性。。·

例 1:pod 节点亲和性定义两个 pod,调度到同一个位置

podaffinity-require.yaml

apiVersion: v1
kind: Pod
metadata:
  name: first
  labels:
    app: first
spec:
  containers:
    - name: myapp
      image: ikubernetes/myapp:v1
      imagePullPolicy: IfNotPresent

podaffinity-require-1.yaml

apiVersion: v1
kind: Pod
metadata:
  name: second
  labels:
    app: second
spec:
  containers:
    - name: myapp
      image: ikubernetes/myapp:v1
      imagePullPolicy: IfNotPresent
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        - labelSelector:
            matchExpressions:
              - { key: app, operator: In, values: ["first"] }
          topologyKey: kubernetes.io/hostname

topologyKey:kubernetes.io/hostname:这个是·Kubernetes·中一个用于指定节点位置拓扑的关键字,kubernetes.io/hostname 是一个节点标签的 key 值,不同的节点这个 key 对应的 value 值是节点主机名,它表示·Pod·应该与具有相同的主机名的节点进行亲和性或反亲和性调度。也就是两个 pod 调度到同一个 node 节点或者不同的 node 节点上。

$ ubectl get pod -owide --show-labels
NAME     READY   STATUS    RESTARTS   AGE   IP               NODE       NOMINATED NODE   READINESS GATES   LABELS
first    1/1     Running   0          11m   10.250.209.141   xuegod64   <none>           <none>            app=first
second   1/1     Running   0          6s    10.250.209.142   xuegod64   <none>           <none>            app=second

例 2:pod 节点反亲和性: 定义两个 pod,第一个 pod 做为基准,第二个 pod 跟它调度到不同的节点上

podunaffinity-1.yaml

apiVersion: v1
kind: Pod
metadata:
  name: first-1
  labels:
    app: first-1
spec:
  containers:
    - name: myapp
      image: ikubernetes/myapp:v1
      imagePullPolicy: IfNotPresent

podunaffinity-2.yaml

apiVersion: v1
kind: Pod
metadata:
  name: second-1
  labels:
    app: second-1
spec:
  containers:
    - name: myapp
      image: ikubernetes/myapp:v1
      imagePullPolicy: IfNotPresent
  affinity:
    podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        - labelSelector:
            matchExpressions:
              - { key: app, operator: In, values: ["first-1"] }
          topologyKey: kubernetes.io/hostname

例 3 topologyKey

# 62 64 打标签
$ kubectl label node xuegod64 type=disk
$ kubectl label node xuegod62 type=disk

podantiaffinity-disk-1.yaml

apiVersion: v1
kind: Pod
metadata:
  name: first-2
  labels:
    app: first-2
spec:
  containers:
    - name: myapp
      image: ikubernetes/myapp:v1
      imagePullPolicy: IfNotPresent

`podantiaffinity-disk-2.yaml

apiVersion: v1
kind: Pod
metadata:
  name: second-3
  labels:
    app: second-3
spec:
  containers:
    - name: myapp
      image: ikubernetes/myapp:v1
      imagePullPolicy: IfNotPresent
  affinity:
    podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        - labelSelector:
            matchExpressions:
              - { key: app, operator: In, values: ["first-2"] }
          topologyKey: type

Pod 高级用法:污点和容忍度

  • 在·k8s·集群中,节点可能:这此间。新娃和上运行的 pod。为了解决这些问题,k8s·提供了污点和容忍度机制。
  • 污点(Taint)是一种节点上的属性,它表示该节点存在某种问题,如磁盘空间不足、内存不足等。如果一个节点被标记了污点,那么默认情况下,k8s·不会在该节点上调度新的·Pod。这是因为·k8s·希望确保·Pod·在运行时能够获得足够的资源,并且不会因为节点问题而意外终止。
  • 容忍度(Toleration)是一种·Pod·的属性,容忍度只是告诉·Kubernetes,这个·Pod·可以容忍特定的污点,但是并不意味着·Pod·必须被调度到拥有这个污点的节点上。实际上,Pod·仍然可以被调度到没有对应污点的节点上。
  • 使用容忍度的主要目的是允许某些·Pod·能够运行在一些不符合正常调度要求的节点上,例如由于节点故障或维护等原因导致节点暂时不可用时,一些·Pod 定义容忍度之后可以被调度到其他节点上,以确保应用程序的高可用性。

假设我们有一个·k8s·集群,其中有两个节点:xuegod62 和·xuegod64。我们想要在·xuegod62 上运行一个特定的应用程序·Pod,但是·xuegod62 节点有一个特定的污点,需要通过容忍度来容忍。

eg: 62 打污点,

# 打上不调度污点,只影响新的pod,老的pod调度不变
$ kubectl taint nodes xuegod62 a=b:NoSchedule

podtaint.yaml

apiVersion: v1
kind: Pod
metadata:
  name: example-pod
  labels:
    app: taint
spec:
  containers:
    - name: example-container
      image: ikubernetes/myapp:v1
      imagePullPolicy: IfNotPresent
  tolerations:
    - key: "a"
      operator: "Equal"
      value: "b"
      effect: "NoSchedule"

定义了容忍度(tolerations),可能在 62 和 64 上

podtaint-1.yaml

apiVersion: v1
kind: Pod
metadata:
  name: taint-1
  labels:
    app: taint-1
spec:
  containers:
    - name: example-container
      image: ikubernetes/myapp:v1
      imagePullPolicy: IfNotPresent

没定义容忍度,只能在 64 上

  • 取消污点
$ kubectl taint nodes xuegod62 a-

容忍度

  • key:表示污点的键,必须与节点上的污点键相匹配才能容忍此污点。
  • value:表示污点的值,必须与节点上的污点值相匹配才能容忍此污点。如果未指定,则默认为空字符串。 operator:表示匹配操作符。可以是·Equal、Exists·。在·Equal·操作符下,如果·key、value 和·effect·都与节点上的污点匹配,则该容忍度规则会被视为匹配。因此,key、value·和·effect·都需要匹配才能算作是匹配的容忍度规则。"Exists"·表示只要节点上存在·key·字段指定的污点,无论其对应的·value·是什么,都将被视为匹配的容忍度规则。
  • effect:表示容忍度的作用效果。跟 node 节点上的 effect 匹配即可。
  • tolerationSeconds:要想在 pod 容忍度中指定 tolerationSeconds·参数,effect·字段必须设置为·NoExecute·才可以。如果一个节点上出现了被标记为·NoExecute·的污点,所有已经运行在该节点上的·Pod 不能容忍这个污点,将会被终止并且删除。如果当 pod 定义容忍度时候容忍 node 节点排斥等级是 Noexecute 污点时,Pod·会等待·tolerationSeconds·指定的时间,如果在这段时间内污点被删除,则·Pod·将可以继续在该节点上运行。·否则过了这个时间 pod 就被删除了。

  • 案例:假如 k8s 集群有三个节点,xuegod63、xuegod64、xuegod62,xuegod63 默认是控制节点,把 xuegod62 和 xuegod64 都打污点,测试让 pod 调度到 xuegod62 上

a. 打污点

$ kubectl taint nodes xuegod62 key=value:NoSchedule
$ kubectl taint nodes xuegod64 key=value:NoSchedule

b. pod 文件

pod-toleration-1.yaml

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
  labels:
    app: my-pod
spec:
  containers:
    - name: nginx
      image: nginx
      imagePullPolicy: IfNotPresent

b. 未定义容忍度,会处于 pending 状态

$ kubectl apply -f pod-toleration-1.yaml
$ kubectl get pods
NAME     READY   STATUS    RESTARTS   AGE
my-pod   0/1     Pending   0          3s

c. pod 文件 2

pod-toleration-2.yaml

apiVersion: v1
kind: Pod
metadata:
  name: my-pod-1
  labels:
    app: my-pod-1
spec:
  containers:
    - name: nginx
      image: nginx
      imagePullPolicy: IfNotPresent
  tolerations:
    - key: "key"
      operator: "Exists"
      effect: "NoSchedule"
  nodeSelector:
    kubernetes.io/hostname: xuegod62

d. 定义了容忍度,且满足容忍度条件

$ kubectl apply -f pod-toleration-2.yaml
$ kubectl get pod -owide
NAME       READY   STATUS    RESTARTS   AGE     IP              NODE       NOMINATED NODE   READINESS GATES
my-pod     0/1     Pending   0          3m12s   <none>          <none>     <none>           <none>
my-pod-1   1/1     Running   0          10s     10.250.158.25   xuegod62   <none>           <none>
  • 再看一个案例,演示 tolerationSeconds 实战场景

a. pod-toleration-3.yaml

apiVersion: v1
kind: Pod
metadata:
  name: my-pod-2
  labels:
    app: my-pod-2
spec:
  containers:
    - name: nginx
      image: nginx
      imagePullPolicy: IfNotPresent
  tolerations:
    - key: "key"
      operator: "Exists"
      effect: "NoExecute"
      tolerationSeconds: 300

b. 运行

$ kubectl apply -f pod-toleration-3.yaml
$ kubectl get pod -owide
kubectl get pod -owide
NAME       READY   STATUS    RESTARTS   AGE   IP              NODE       NOMINATED NODE   READINESS GATES
my-pod-2   1/1     Running   0          3s    10.250.158.27   xuegod62   <none>           <none>
# 打上污点,让其被撵走
$ kubectl taint nodes xuegod62 key=value:NoExecute
# 等5分钟后,其被移走

综上,我们可以总结出来 node 节点亲和性、node 节点选择器、node 节点污点分别适用什么场景:

  • 节点亲和性(Node·Affinity)适合用于将·Pod·部署在特定的节点上的场景,比如需要特定硬件或软件配置的节点,或者需要将某些·Pod·部署在与其他相关服务相同的节点上。通过使用节点亲和性,可以确保·Pod·在运行时可以获得所需的资源,并提高应用程序的性能和可靠性。
  • 节点选择器(Node·Selector)是一种简单的调度策略,它允许在·Pod·中指定一个节点标签,使得 pod 只能调度到拥有该标签的节点上。如果没有节点满足条件,则该·Pod·无法调度。
  • 污点(Taints)是一种用于标记节点的机制,可以在节点上设置污点来阻止不应该在该节点上运行的·Pod·调度到该节点上。只有带有相应容忍污点(Tolerations)的·Pod·才能被调度到该节点上。例如,可以在节点上设置污点来阻止一些敏感应用程序运行在该节点上.

在生产环境中,这些调度策略可以用于以下场景:

  • 节点亲和性:在多节点集群中,通过将某些·Pod·调度到拥有特定硬件或软件配置的节点上,以最大化应用程序性能。例如,可以将需要·GPU·计算能力的机器学习任务调度到拥有·GPU·的节点上,以提高计算速度。
  • 节点选择器:在多租户环境中,可以使用节点选择器将不同的·Pod·部署在不同的节点上,以隔离应用程序并避免资源竞争。例如,可以将测试环境的·Pod·调度到专用的测试节点上,而将生产环境的 Pod·调度到专用的生产节点上。
  • 污点和容忍:在生产环境中,可以使用污点和容忍来确保敏感应用程序不会运行在错误的节点上。例如,可以在拥有机密数据的节点上设置污点,并将只允许在经过身份验证的容器内运行的应用程序的容忍添加到·Pod·中,以确保敏感数据得到保护。

pod 状态、生命周期、健康检测

pod 常见的状态

在 K8s 集群中,Pod 常见的状态如下:

Pending

例如,当你创建一个 Pod 时,如果你指定了一个特定的节点,但是该节点上已经有其他的 Pod 运行,并且没有足够的资源来满足你的 Pod 请求,那么你的 Pod 将一直处于 Pending 状态,直到有足够的资源被释放或者你重新指定一个节点。

Running

例如,当你创建一个 Pod 时,如果你指定了一个 Docker 容器镜像,并且该镜像已经被下载到节点上,那么你的 Pod 将会开始运行,容器会在其中运行,并且 Pod 将会处于 Running 状态。

Succeeded

例如,当你创建一个 Pod 时,如果你指定了一个具体的任务并且该任务已经成功完成,那么 Pod 将会进入 Succeeded 状态,并且容器将会退出。

Failed

例如,当你创建一个 Pod 时,如果你指定了一个具体的任务并且该任务在执行期间失败了,那么 Pod 将会进入 Failed 状态,并且容器将会退出。

Unknown

例如,当你删除一个 Pod 的控制器时,Kubernetes 将会失去对该Pod的监视,Pod的状态将会变为Unknown。另外,如果Kubernetes系统出现故障或者网络问题,也有可能导致Pod的状态无法被监视到。

ContainerCreating

Pod已经被Kubernetes调度到了某个节点上,但是容器还没有开始创建。

Terminating

Pod 正在被删除。

CrashLoopBackOff

当一个容器启动失败,并且已经尝试了指定的重启次数(通常是3次),但是每次都失败了,Kubernetes就会将这个Pod的状态设置为CrashLoopBackOff。这个状态通常意味着有一些问题需要解决,例如容器配置错误、依赖项缺失等。需要修复这些问题才能让Pod重新正常运行。

ImagePullBackOff

Pod中的某个容器无法拉取镜像。这通常是因为镜像不存在、认证失败或者无法连接到镜像仓库。

CreateContainerConfigError

Pod中的某个容器无法创建,通常是因为容器配置错误导致的。

CreateContainerError

Pod中的某个容器无法创建,通常是因为资源不足、权限不足等原因导致的。

Podlnitializing

Pod 正在初始化,包括下载镜像、创建容器等。

Error

pod重启策略

Kubernetes 提供了三种Pod 重启策略,分别是:

Always

无论什么情况下,只要容器退出,或者终止,就会自动重启Pod里的容器。这是默认的重启策略。

always-restart-pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: always-restart-pod
spec:
  restartPolicy: Always
  containers:
  - name: always-restart-container
    image: nginx:latest
    imagePullPolicy: IfNotPresent
$ kubectl apply -f always-restart-pod.yaml
$ kubectl get pod
NAME                 READY   STATUS    RESTARTS      AGE
always-restart-pod   1/1     Running   1 (13s ago)   98s
$ kubectl exec -it always-restart-pod -- bash
root@always-restart-pod:/# nginx -s stop
2025/01/23 08:19:53 [notice] 39#39: signal process started
root@always-restart-pod:/# command terminated with exit code 137
# RESTARTS 可以看到已重启
$ kubectl get pod
NAME                 READY   STATUS      RESTARTS      AGE
always-restart-pod   0/1     Completed   1 (25s ago)   110s

OnFailure

只有当容器以非零状态终止时才会自动重启Pod里的容器,只有当某个容器因为错误或异常而以非零状态终止时,Kubernetes才会触发Pod的自动重启。如果容器以零状态(也就是正常状态)终止,Kubernetes不会进行自动重启。

onfailure-restart-pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: onfailure-restart-pod
spec:
  restartPolicy: OnFailure
  containers:
  - name: onfailure-restart-container
    image: nginx:latest
    imagePullPolicy: IfNotPresent
$ kubectl apply -f onfailure-restart-pod.yaml
$ kubectl get pod
NAME                    READY   STATUS    RESTARTS   AGE
onfailure-restart-pod   1/1     Running   0          4m58s
# 进入容器 kill -9 0 但测试其非异常退出还是运行状态

Never

Pod里的容器不会被自动重启,除非显式地进行手动操作。

never-restart-pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: never-restart-pod
spec:
  restartPolicy: Never
  containers:
  - name: always-restart-container
    image: nginx:latest
    imagePullPolicy: IfNotPresent
$ apply -f never-restart-pod.yaml 
pod/never-restart-pod created
$ kubectl get pod
NAME                READY   STATUS    RESTARTS   AGE
never-restart-pod   1/1     Running   0          3s
$ kubectl exec -it never-restart-pod -- bash
root@never-restart-pod:/# nginx -s stop
2025/01/23 08:23:44 [notice] 39#39: signal process started
root@never-restart-pod:/# command terminated with exit code 137
# 正常停止,不会重启了
$ kubectl get pod
NAME                READY   STATUS      RESTARTS   AGE
never-restart-pod   0/1     Completed   0          21s

Pod高级用法:Pod生命周期

  1. 初始化容器(Init·Container)阶段:·初始化容器是在Pod启动之前运行的一组容器多它们负责执行一些必要的初始化任务,例如设置环境变量、检查依赖关系、执行数据库迁移等等。只有当所有的初始化容器都成功完成后,主容器才会启动。
  2. 主容器(Main·Container)阶段:·主容器是Pod中的核心容器,它们负责实际运行应用程序或服务。在启动时,Kubernetes会创建一个或多个主容器,并将它们放置在同一个Pod中。主容器可以是应用程序容器、数据库容器、Web服务器容器等等。
  3. 运行时状态(Running·State)阶段:·一旦 Pod 中的所有容器都成功启动,它们会进入 Running状态。在这个阶段,容器可以相互通信,并与集群中的其他容器和服务进行交互。
  4. 容器重启(Container·Restart)阶段:·在Pod运行期间,容器可能会出现故障或崩溃。当容器重新启动时,Kubernetes会记录重启次数,并在出现频繁重启时采取相应的措施,例如自动停止Pod或报警通知管理员。
  5. 终止(Termination)阶段:·当Pod不再需要时,Kubernetes 会将其终止。在终止阶段,Kubernetes会向Pod中的所有容器发送终止信号,并等待它们完成正在进行的工作。一旦所有容器都已经停止,Pod 就会被彻底删除。

1) 案例1:演示初始化容器和主容器假设我们有一个Web应用程序,它需要一个Redis数据库来存储数据。为了确保Web应用程序正常运行,我们需要在Pod启动之前先启动一个初始化容器,它会检查Redis是否已经准备好,并在必要时等待其准备就绪。一旦Redis准备就绪,初始化容器就会退出,然后主容器开始运行Web应用程序。个以下是一个简单的Pod配置示例,其中包含了一个初始化容器和一个主容器:

init.yaml

apiVersion: v1
kind: Pod
metadata:
  name: my-webapp
  labels:
    app: redis
spec:
  containers:
  - name: webapp
    image: nginx
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 80
  initContainers:
  - name: init-redis
    image: busybox
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c', 'until nslookup redis; do echo waiting for redis sleep 2; done;']
kubectl apply -f init.yaml 
pod/my-webapp created
# 其会一直创建,因为没启动redis相关容器
$ kubectl get pod
NAME        READY   STATUS     RESTARTS   AGE
my-webapp   0/1     Init:0/1   0          11s
# 会看到日志一直刷新
$ kubectl logs my-webapp -c init-redis
  • 修改让等 10s 起来

init-1.yaml

apiVersion: v1
kind: Pod
metadata:
  name: my-nginx
  labels: 
    app: init-nginx
spec:
  containers:
  - name: web
    image: nginx
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 80
    command: ["/bin/sh"]
    args: ["-c","echo '<h1>Hello Kubernetes!</h1>' > /usr/share/nginx/html/index.html && nginx -g 'daemon off;'"] 
  initContainers:
  - name: init-web
    image: busybox
    imagePullPolicy: IfNotPresent
    command: ["sh", "-c", "echo waiting...&& sleep 10" ]
$ kubectl apply -f init-1.yaml 
pod/my-nginx created
$ kubectl get pod -owide
NAME        READY   STATUS     RESTARTS   AGE   IP               NODE       NOMINATED NODE   READINESS GATES
my-nginx    0/1     Init:0/1   0          6s    10.250.209.154   xuegod64   <none>           <none>
# 初始化容器好了就启动成功了
$ kubectl get pod -owide
NAME        READY   STATUS     RESTARTS   AGE   IP               NODE       NOMINATED NODE   READINESS GATES
my-nginx    1/1     Running    0          14s   10.250.209.154   xuegod64   <none>           <none>
# 测试
$ curl 10.250.209.154
<h1>Hello Kubernetes!</h1>

Pod高级用法:对Pod内的容器做健康探测

  • 在k8s集群中,可以使用健康探测来监测·Pod·的状态,并根据探测结果来实现自动化容器的重启或故障切换等操作,从而提高应用的可靠性和可用性。下面介绍几种常用的健康探测方式及其应用场景:

  • Liveness·Probe(存活探测):·Liveness·Probe·用于监测pod 内的容器是否处于运行状态。当Liveness·Probe·探测失败时,Kubernetes·根据重启策略决定是否重启该容器。适用于需要在容器发生故障时立即进行重启的应用场景,比如·Web·服务器和数据库等应用。

  • Readiness·Probe(就绪探测):·Readiness·Probe·用于监测pod内的容器是否已经准备好接受流量,即容器是否已经完成初始化并已经启动了应用程序。当容器的·Readiness·Probe·探测失败时,Kubernetes·将停止将新的流量转发到该容器。适用于需要应用程序启动较长时间的应用场景,比如大型·Web·应用程序。

1) livenessprobe 案例分享

  • Liveness·Probe·用于检查pod内的容器是否在运行,并在容器出现故障时重新启动容器。Liveness·Probe·支持三种探针:httpGet、exec·和·tcpSocket

eg: 类似探测 http://localhost:80/index.html

live-http.yaml

apiVersion: v1
kind: Pod
metadata:
  name: liveness-http
spec:
  containers:
  - name: liveness
    image: nginx
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 80
    livenessProbe:
      httpGet:
        path: /index.html
        port: 80
      initialDelaySeconds: 15
      periodSeconds: 20

2) readinessprobe案例分享

readiness-http.yaml

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
  - name: liveness
    image: nginx
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 80
    readinessProbe:
      httpGet:
        path: /index.html
        port: 80
      initialDelaySeconds: 1
      periodSeconds: 2
      failureThreshold: 3
      successThreshold: 1
$ kubectl apply -f readiness-http.yaml
$ kubectl exec -ti my-pod -- bash
root@my-pod:/# rm /usr/share/nginx/html/index.html 
# 等待一会就绪变成0, ps: service 代理的都是就绪pod
$ kubectl get pod -w
NAME     READY   STATUS    RESTARTS   AGE
my-pod   1/1     Running   0          2m21s
my-pod   0/1     Running   0          4m43s

3) startupprobe 案例分享 Startup·Probe·用于检查容器是否已经启动完成。Startup·Probe·支持三种探针:httpGet、exec·和·tcpSocket。我们使用了·exec·探针。具体步骤如下

start-pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: my-pod-start
spec:
  containers:
  - name: nginx-controller
    image: nginx
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 80
    startupProbe:
      exec:
        command:
        - /bin/sh
        - -c
        - /usr/sbin/nginx -t
      initialDelaySeconds: 10
      periodSeconds: 10
      failureThreshold: 10
$ kubectl apply -f start-pod.yaml
# 启动探测完了,才会就绪探测
$ kubectl get pod -w
NAME           READY   STATUS    RESTARTS   AGE
my-pod-start   0/1     Running   0          13s
my-pod-start   0/1     Running   0          21s
my-pod-start   1/1     Running   0          21s

3) startupprobe、livenessprobe、readinessprobe 混合实用案例分享

apiVersion: v1
kind: Pod
metadata:
  name: myapp
spec:
  containers:
  - name: app
    image: nginx
    imagePullPolicy: IfNotPresent
    readinessProbe:
      httpGet:
        path: /index.html
        port: 80
      initialDelaySeconds: 10
      periodSeconds: 5
      successThreshold: 1
      failureThreshold: 3
    livenessProbe:
      httpGet:
        path: /index.html
        port: 80
      initialDelaySeconds: 15
      periodSeconds: 10
      failureThreshold: 3
    startupProbe:
      httpGet:
        path: /index.html
        port: 80
      initialDelaySeconds: 5
      periodSeconds: 10
      failureThreshold: 10
$ kubectl apply -f hunhe.yaml
$ kubectl get pod -w
NAME           READY   STATUS    RESTARTS   AGE
myapp          0/1     Running   0          5s
myapp          0/1     Running   0          11s
myapp          1/1     Running   0          11s

pod 启动探测、就绪探测、存活探测先后顺序: 1、启动探测:在容器启动之后,立即进行启动探测,如果启动探测失败,则·Kubernetes·认为该容器启动失败,不会再进行后续的探测。 2、就绪探测:如果启动探测成功,就会进行就绪探测。在容器运行期间,Kubernetes·会定期进行就绪探测,以检查容器是否已经准备好接收请求。如果就绪探测失败,则·Kubernetes·认为该容器还没有准备好接收请求,不会将流量转发到该容器。 3、存活探测:在容器运行期间,Kubernetes·会定期进行存活探测,以检查容器是否处于健康状态。如果存活探测失败,则·Kubernetes·认为该容器已经出现了故障,需要进行重启或者进行其他的处理。

Comments