k8s集群核心概念 Pod进阶

k8s集群核心概念 Pod进阶

一、场景

Pod在kubernetes集群中是核心资源对象之一,前期我们已经在《kubernetes极速入门》课程中讲解了Pod创建及Pod删除方法,但是实际企业应用中,Pod使用远比我们想像复杂,本次课程我们接着为大家讲解Pod进阶。

二、学习目标

  • 回顾Pod概念及其创建方法
  • 了解Pod中容器镜像下载策略
  • 掌握Pod中容器资源限制方法
  • 了解Pod中运行多个容器方法
  • 了解通过在Pod容器执行命令的方法
  • 掌握Pod生命周期管理
  • 掌握Pod生命周期事件
  • 掌握Pod调度约束方法
  • 掌握Pod故障排除方法

三、学习步骤

1回顾Pod概念及其创建方法
2Pod中容器镜像下载策略
3Pod中容器资源限制方法
4Pod中运行多个容器方法
5通过在Pod容器执行命令的方法
6Pod生命周期管理
7Pod生命周期事件
8Pod调度约束方法
9Pod故障排除方法

四、课程内容

4.1 Pod概念及创建方法回顾

4.1.1 Pod

  • kubernetes集群最小调度管理单元

  • 用于封装容器

  • 实际应用中我们很少直接在kubernetes中创建单个Pod。因为Pod的生命周期是短暂的,用后即焚的实体。

    Pod特征

  • Pod被创建后(不论是由你直接创建还是被其它Controller创建),都会被Kubernetes调度到集群的节点上。直到Pod的进程终止、被删掉、因为缺少资源而被驱逐,在Node故障之前这个Pod都会一直保持在那个Node上。

  • Pod不会自愈。如果Pod运行的Node故障,或者是调度器本身故障,这个Pod就会被删除。同样的,如果Pod所在Node缺少资源或者Pod处于维护状态,Pod也会被驱逐。

    Pod管理方法

  • Kubernetes使用更高级的称为Controller的抽象层,来管理Pod实例。虽然可以直接使用Pod,但是在Kubernetes中通常是使用Controller来管理Pod的。

  • Controller可以创建和管理多个Pod,提供副本管理、滚动升级和集群级别的自愈能力。例如,如果一个Node故障,Controller就能自动将该节点上的Pod调度到其他健康的Node上。

4.1.2 创建方法

4.1.2.1 命令中创建Pod

kubernetes版本1.18.0

命令行创建Pod
[root@master01 ~]# kubectl run nginxpod1 --image=harbor.wego.red/library/nginx:1.9.0 --image-pull-policy=IfNotPresent
4.1.2.2 使用资源清文件创建
创建Pod资源清单文件
[root@master01 ~]# cat 01-create-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod1
spec:
  containers:
  - name: c1
    image: harbar.wego.red/library/nginx:1.9.0

4.1.2.3 内嵌帮助方法
获取帮助方法
# kubectl explain pod

4.1.2.4 以yaml文件格式查看Pod资源清单文件
查看
# kubectl get pods -o yaml
或
# kubectl get pods -o json

4.2 Pod中容器镜像下载策略

4.2.1 策略类型

在kubernetes集群中提供镜像下载策略有三种方式

  • Always 每次运行pod都需要下载镜像

  • Never 每次运行pod只使用本地镜像

  • IfNotPresent 每次运行pod,本地有镜像就使用本地镜像,如果本地没有镜像,就去下载

4.2.2 策略类型应用

4.2.2.1 Always
[root@master01 ~]# cat 02-imagepullpolicy-pod2.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod2
spec:
  containers:
  - name: c1
    image: harbro.wego.red/library/nginx:1.9.0
    imagePullPolicy: Always #注意此处
    

4.2.2.2 Never
[root@master01 ~]# cat 04-imagepullpolicy-pod3.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod3
spec:
  containers:
  - name: c1
    image: harbro.wego.red/library/nginx:1.9.0
    imagePullPolicy: Never #注意此处
    

4.2.2.3 IfNotPresent
[root@master01 ~]# cat 05-imagepullpolicy-pod4.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod4
spec:
  containers:
  - name: c1
    image: harbro.wego.red/library/nginx:1.9.0s
    imagePullPolicy: IfNotPresent #注意此处
   

4.3 Pod中容器资源限制方法

4.3.1 资源限制的作用

  • 降低Pod大量使用主机资源风险,避免物理主机处于宕机状态

4.3.2 资源限制方法

  • resources

    • requests 请求资源

    • limits 限制资源

  • 本次实验所使用的物料

    • 镜像:stress:latest

    • 内存限制

4.3.2.1 使用的资源在限定范围内
[root@master01 ~]# cat 06-limit-mem.yaml
---
apiVersion: v1
kind: Namespace
metadata:
  name: mem-test
​
---
apiVersion: v1
kind: Pod
metadata:
  name: pod5
  namespace: mem-test
spec:
  containers:
  - name: c1
    image: harbro.wego.red/library/stress:latest
    imagePullPolicy: IfNotPresent
    resources:
      requests:
        memory: "100Mi"
      limits:
        memory: "200Mi"
    command: ["stress"]
    args: ["--vm","1","--vm-bytes","150M","--vm-hang","1"]

4.3.2.1 使用的资源超出限定范围
[root@master01 ~]# cat 07-limit-mem.yaml
---
apiVersion: v1
kind: Namespace
metadata:
  name: mem-test
​
---
apiVersion: v1
kind: Pod
metadata:
  name: smartgopod07
  namespace: mem-test
spec:
  containers:
  - name: c1
    image: harbro.wego.red/library/stress:latest
    imagePullPolicy: IfNotPresent
    resources:
      requests:
        memory: "100Mi"
      limits:
        memory: "200Mi"
    command: ["stress"]
    args: ["--vm","1","--vm-bytes","250M","--vm-hang","1"]

4.4 Pod中运行多个容器方法

4.4.1 一个Pod中运行一个Container

[root@master01 ~]# cat 02-create-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod1
spec:
  containers:
  - name: c1
    image: harbor.wego.red/library/nginx:1.9.0

4.4.2 一个pod中运行多个Container

Pod中可以同时运行多个进程(作为容器运行)协同工作。同一个Pod中的容器会自动的分配到同一个node上。同一个Pod中的容器共享资源、网络环境和依赖,它们总是被同时调度。

注意在一个Pod中同时运行多个容器是一种比较高级的用法。只有当你的容器需要紧密配合协作的时候才考虑用这种模式。例如,你有一个容器作为web服务器运行,需要用到共享的volume,有另一个“sidecar”容器来从远端获取资源更新这些文件,如下图所示:

Pod中可以共享两种资源:网络和存储

网络:每个pod都会被分配一个唯一的IP地址。Pod中的所有容器共享网络空间,包括IP地址和端口。Pod内部的容器可以使用localhost互相通信。Pod中的容器与外界通信时,必须分配共享网络资源(例如使用宿主机的端口映射)。

存储:可以为一个Pod指定多个共享的VolumePod中的所有容器都可以访问共享的volumeVolume也可以用来持久化Pod中的存储资源,以防容器重启后文件丢失。

[root@master01 ~]# cat 08-one-pod-multi-container.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod7ss
  namespace: default
spec:
  containers:
  - name: c1
    image:harbor.wego.red/library/stress:latest
    imagePullPolicy: IfNotPresent
    
  - name: c2
    image: harbor.wego.red/library/stress:latest
    imagePullPolicy: IfNotPresent

4.5 进入Pod中容器的方法

  • 由于Pod是用后即焚的,不建议进入Pod中,如果进入基本上属于测试使用。

4.5.1 一个pod中运行一个Container

创建资源单文件
[root@master01 ~]# cat 02-create-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod1
spec:
  containers:
  - name: c1
    image: harbor.wego.red/library/stress:latest
    command: ["stress"]
    args: ["--vm","1","--vm-bytes","150M","--vm-hang","1"]
​
​
应用资源清单文件
[root@master01 ~]# kubectl apply -f 02-create-pod.yaml
pod/pod1 created
​
​
查看已创建的pod
[root@master01 ~]# kubectl get pods
NAME     READY   STATUS    RESTARTS   AGE
pod1     1/1     Running   0          16s
​
​
​
进入pod中的容器
[root@master01 ~]# kubectl exec -it pod1 bash
bash-4.3# ls
bin    etc    lib    mnt    root   sbin   sys    usr
dev    home   media  proc   run    srv    tmp    var
bash-4.3# touch /root/123.txt
bash-4.3# exit
​
直接在当前主机命令行操作pod中容器目录
[root@master01 ~]# kubectl exec -it pod1 -- ls /root
123.txt

4.5.2 一个pod中运行多个Container

创建资源清单文件
​
[root@master01 ~]# cat 08-one-pod-multi-container.yaml
apiVersion: v1
kind: Pod
metadata:
  name: onepodmultic
  namespace: default
spec:
  containers:
  - name: c1
    image: harbor.wego.red/library/stress:latest
    imagePullPolicy: IfNotPresent
    resources:
      limits:
        memory: "200Mi"
      requests:
        memory: "100Mi"
    command: ["stress"]
    args: ["--vm","1","--vm-bytes","150M","--vm-hang","1"]
  - name: c2
    image: polinux/stress:latest
    imagePullPolicy: IfNotPresent
    resources:
      limits:
        memory: "200Mi"
      requests:
        memory: "100Mi"
    command: ["stress"]
    args: ["--vm","1","--vm-bytes","150M","--vm-hang","1"]
​
​
应用资源清单文件
[root@master01 ~]# kubectl apply -f 08-one-pod-multi-container.yaml
​
查看已创建pod
[root@master01 ~]# kubectl get pods
NAME     READY   STATUS    RESTARTS   AGE
onepodmultic   2/2     Running   0          21m
​
进入onepodmultic第一个容器
-C 选项为了指定需要进入容器
[root@master01 ~]# kubectl exec -it -c c1 onepodmultic bash
bash-4.3# ls
bin    etc    lib    mnt    root   sbin   sys    usr
dev    home   media  proc   run    srv    tmp    var
bash-4.3# exit
​
进入onepodmultic第二个容器
[root@master01 ~]# kubectl exec -it -c c2 onepodmultic bash
bash-4.3# ls
bin    etc    lib    mnt    root   sbin   sys    usr
dev    home   media  proc   run    srv    tmp    var
bash-4.3# exit
​
​
直接在当前主机命令行操作pod中容器目录
[root@master01 ~]# kubectl exec -it -c c1 onepodmultic -- ls /root
[root@master01 ~]# kubectl exec -it -c c2 onepodmultic -- ls /root

4.6 Pod创建过程

Podkubernetes集群最小调度管理单元,下图描述了一个Pod资源对象的典型创建过程。

pod创建过程
1. 用户通过kubectl或其它API客户端提交了Pod Spec给API Server。
2. API Server尝试着将Pod对象的相关信息存入etcd中,待写入操作执行完成,API Server即会返回确认信息至客户端。
3. API Server开始反馈etcd中的状态变化。
4. 所有的kubernetes组件均使用watch机制来跟踪检查API Server上的相关的变化。
5. kube-scheduler(调度器)通过其watcher觉察到API Server创建了新的Pod对象但尚未绑定至任何工作节点。
6. kube-scheduler为Pod对象挑选一个工作节点并将结果信息更新至API Server。
7. 调度结果信息由API Server更新至etcd存储系统,而且API Server也开始反映此Pod对象的调度结果。
8. Pod被调度到的目标工作节点上的kubelet尝试在当前节点上调用Docker启动容器,并将容器的结果状态返回送至API Server。
9. API Server将Pod状态信息存入etcd系统中。
10. 在etcd确认写入操作成功完成后,API Server将确认信息发送至相关的kubelet告之其Pod状态。

4.7 Pod生命周期

Pod对象自从其创建开始至其终止退出的时间范围称为其生命周期。

在这段时间中,Pod会处于多种不同的状态,并执行一些操作;其中,创建主容器(main container)为必需的操作,其他可选的操作还包括运行初始化容器(init container)、容器启动后钩子(post start hook)、容器的存活性探测(liveness probe)、就绪性探测(readiness probe)以及容器终止前钩子(pre stop hook)等,这些操作是否执行则取决于Pod的定义。如下图所示:

4.7.1 Pod启动

  1. pod中的容器在创建前,有初始化容器(init container)来进行初始化环境

  2. 初化完后,主容器(main container)开始启动

  3. 主容器启动后,有一个post start的操作(启动后的触发型操作,或者叫启动后钩子)

  4. post start后,就开始做健康检查

    • 第一个健康检查叫存活状态检查(liveness probe ),用来检查主容器存活状态的

    • 第二个健康检查叫准备就绪检查(readiness probe),用来检查主容器是否启动就绪

4.7.2 Pod终止

  1. 可以在容器终止前设置pre stop操作(终止前的触发型操作,或者叫终止前钩子)

  2. 如果容器重启策略允许,则会终止容器。

  3. 当出现特殊情况不能正常销毁pod时,大概等待30秒会强制终止

4.7.3 pod启动时HealthCheck方式

  • HealthCheck

当Pod启动时,容器可能会因为某种错误(服务未启动或端口不正确)而无法访问等。

  • Health Check方式

kubelet拥有两个检测器,它们分别对应不同的触发器(根据触发器的结构执行进一步的动作)

方式说明
Liveness Probe(存活状态探测)检查后不健康,重启pod
readiness Probe(就绪型探测)检查后不健康,将容器设置为Notready;如果使用service来访问,流量不会转发给此种状态的pod

4.7.4 pod启动时HealthCheck Probe控制方式

  • Probe探测方式

方式说明
Exec执行命令
HTTPGethttp请求某一个URL路径
TCPtcp连接某一个端口

4.7.5 Pod中容器重启策略

Pod.Spec中有一个restartPolicy字段,可能的值为AlwaysOnFailureNever。默认为AlwaysrestartPolicy适用于Pod中的所有容器。而且它仅用于控制在同一节点上重新启动Pod对象的相关容器。首次需要重启的容器,将在其需要时立即进行重启,随后再次需要重启的操作将由kubelet延迟一段时间后进行,且反复的重启操作的延迟时长依次为10秒、20秒、40秒... 300秒是最大延迟时长。事实上,一旦绑定到一个节点,Pod对象将永远不会被重新绑定到另一个节点,它要么被重启,要么终止,直到节点发生故障或被删除。

  • Always:表示容器挂了总是重启,这是默认策略

  • OnFailure:表容器状态为错误时才重启,也就是容器正常终止时不重启

  • Never:表示容器挂了不予重启

  • 对于Always这种策略,容器只要挂了,就会立即重启,这样是很耗费资源的。所以Always重启策略是这么做的:第一次容器挂了立即重启,如果再挂了就要延时10s重启,第三次挂了就等20s重启...... 依次类推

4.8 Pod状态(相位 phase)

Podstatus字段是一个PodStatus的对象,PodStatus中有一个phase字段。

无论是手动创建还是通过Deployment等控制器创建,Pod对象总是应该处于其生命进程中以下几个相位(phase)之一。

  • 挂起(Pending):API Server创建了pod资源对象已存入etcd中,但它尚未被调度完成,或者仍处于从仓库下载镜像的过程中。

  • 运行中(Running):Pod已经被调度至某节点,并且所有容器都已经被kubelet创建完成。

  • 成功(Succeeded):Pod中的所有容器都已经成功终止并且不会被重启

  • 失败(Failed):Pod中的所有容器都已终止了,并且至少有一个容器是因为失败终止。即容器以非0状态退出或者被系统禁止。

  • 未知(Unknown):Api Server无法正常获取到Pod对象的状态信息,通常是由于无法与所在工作节点的kubelet通信所致。

4.9 Pod生命周期中重要行为

4.9.1 初始化容器

初始化容器(init container)即应用程序的主容器启动之前要运行的容器,常用于为主容器执行一些预置操作,它们具有两种典型特征。

1)初始化容器必须运行完成直至结束,若某初始化容器运行失败,那么kubernetes需要重启它直到成功完成。(注意:如果podspec.restartPolicy字段值为“Never”,那么运行失败的初始化容器不会被重启。)

2)每个初始化容器都必须按定义的顺序串行运行。

4.9.2 容器探测

容器探测(container probe)是Pod对象生命周期中的一项重要的日常任务,它是kubelet对容器周期性执行的健康状态诊断,诊断操作由容器的处理器(handler)进行定义。Kubernetes支持三种处理器用于Pod探测:

  • ExecAction:在容器内执行指定命令,并根据其返回的状态码进行诊断的操作称为Exec探测,状态码为0表示成功,否则即为不健康状态。

  • TCPSocketAction:通过与容器的某TCP端口尝试建立连接进行诊断,端口能够成功打开即为正常,否则为不健康状态。

  • HTTPGetAction:通过向容器IP地址的某指定端口的指定path发起HTTP GET请求进行诊断,响应码为2xx3xx时即为成功,否则为失败。

任何一种探测方式都可能存在三种结果:“Success”(成功)“Failure”(失败)“Unknown”(未知),只有success表示成功通过检测。

容器探测分为两种类型:

  • 存活性探测(livenessProbe):用于判定容器是否处于“运行”(Running)状态;一旦此类检测未通过,kubelet将杀死容器并根据重启策略(restartPolicy)决定是否将其重启;未定义存活检测的容器的默认状态为“Success”。

  • 就绪性探测(readinessProbe):用于判断容器是否准备就绪并可对外提供服务;未通过检测的容器意味着其尚未准备就绪,端点控制器(如Service对象)会将其IP从所有匹配到此Pod对象的Service对象的端点列表中移除;检测通过之后,会再将其IP添加至端点列表中

4.9.3 使用探针(liveness和readiness)的时机

如果容器中的进程能够在遇到问题或不健康的情况下自行崩溃,则不一定需要存活探针,kubelet将根据PodrestartPolicy自动执行正确的操作。

如果希望容器在探测失败时被杀死并重新启动,那么请指定一个存活探针,并指定restartPolicyAlwaysOnFailure

如果要仅在探测成功时才开始向Pod发送流量,请指定就绪探针。在这种情况下,就绪探针可能与存活探针相同,但是spec中的就绪探针的存在意味着Pod将在没有接收到任何流量的情况下启动,并且只有在探针探测成功才开始接收流量。

如果希望容器能够自行维护,可以指定一个就绪探针,该探针检查与存活探针不同的端点。

如果只想在Pod被删除时能够排除请求,则不一定需要使用就绪探针;在删除Pod时,Pod会自动将自身置于未完成状态,无论就绪探针是否存在。当等待Pod中的容器停止时,Pod仍处于未完成状态。

4.10 Pod中容器探针应用案例

4.10.1 liveness

4.10.1.1 livenessProbe行为属性
[root@master01 ~]# kubectl explain pods.spec.containers.livenessProbe
KIND:     Pod
VERSION:  v1
​
RESOURCE: livenessProbe <Object>
​
exec   command 的方式探测,例如 ps 一个进程是否存在
​
failureThreshold    探测几次失败 才算失败, 默认是连续三次
​
initialDelaySeconds  初始化延迟探测,即容器启动多久之后再开始探测,默认为0秒
​
periodSeconds  每隔多久探测一次,默认是10秒
​
successThreshold  处于失败状态时,探测操作至少连续多少次的成功才算通过检测,默认为1秒
​
timeoutSeconds  存活性探测的超时时长,默认为1秒
​
httpGet   http请求探测
​
tcpSocket    端口探测

4.10.1.2 liveness-exec案例
  • 准备YAML文件

[root@master01 ~]# vim 01_pod_liveness_exec.yaml
apiVersion: v1
kind: Pod
metadata:
  name: liveness-exec
  namespace: default
spec:
  containers:
  - name: liveness
    image: harbor.wego.red/library/busyboxplus:latest
    imagePullPolicy: IfNotPresent
    args:
    - /bin/sh
    - -c
    - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
    livenessProbe:
      exec:
        command:
        - cat
        - /tmp/healthy
      initialDelaySeconds: 5                # pod启动延迟5秒后探测
      periodSeconds: 5                      # 每5秒探测1次

说明:
上面的资源清单中定义了一个pod对象,基于busyboxplus镜像启动一个运行touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600命令的容器,此命令在容器启动时创建了/tmp/healthy文件,并于30秒之后将其删除。
​
存活性探针运行cat /tmp/healthy命令检查/tmp/healthy文件的存在性,若文件存在则返回状态码0,表示成功通过测试。
​
在30秒内使用kubectl describe pods/liveness-exec-pod查看其详细信息,其存活性探测不会出现错误。
​
而超过30秒之后,再执行该命令查看详细信息,可以发现存活性探测出现了故障,并且还可通过kubectl get pods查看该pod的重启的相关信息。

  • 应用YAML文件

[root@master01 ~]# kubectl apply -f 01_pod_liveness_exec.yaml

  • 通过下面的命令观察

[root@master01 ~]# kubectl describe pod liveness-exec
......
Events:
  Type     Reason     Age   From               Message
  ----     ------     ----  ----               -------
  Normal   Scheduled  40s   default-scheduler  Successfully assigned default/liveness-exec to node1
  Normal   Pulled     38s   kubelet, node1     Container image "busybox" already present on machine
  Normal   Created    37s   kubelet, node1     Created container liveness
  Normal   Started    37s   kubelet, node1     Started container liveness
  Warning  Unhealthy  3s    kubelet, node1     Liveness probe failed: cat: can't open '/tmp/healthy': No such file or directory
​
看到40s前被调度以node1节点,3s前健康检查出问题

  • 过几分钟再观察

[root@master01 ~]# kubectl describe pod liveness-exec
......
Events:
  Type     Reason     Age                  From               Message
  ----     ------     ----                 ----               -------
  Normal   Scheduled  3m42s                default-scheduler  Successfully assigned default/liveness-exec to node1
  Normal   Pulled     70s (x3 over 3m40s)  kubelet, node1     Container image "busybox" already present on machine
  Normal   Created    70s (x3 over 3m39s)  kubelet, node1     Created container liveness
  Normal   Started    69s (x3 over 3m39s)  kubelet, node1     Started container liveness
  Warning  Unhealthy  26s (x9 over 3m5s)   kubelet, node1     Liveness probe failed: cat: can't open '/tmp/healthy': No such file or directory
  Normal   Killing    26s (x3 over 2m55s)  kubelet, node1     Container liveness failed liveness probe, will be restarted

[root@master01 ~]# kubectl get pod
NAME            READY   STATUS    RESTARTS   AGE
liveness-exec   1/1     Running   3          4m12s
​
看到重启3次,慢慢地重启间隔时间会越来越长

4.10.1.3: liveness-httpget案例

基于HTTP的探测(HTTPGetAction)向目标容器发起一个HTTP请求,根据其响应码进行结果判定,响应码如2xx或3xx时表示测试通过。
​
通过该命令”`# kubectl explain pod.spec.containers.livenessProbe.httpGet`“查看`httpGet`定义的字段

host    <string>:请求的主机地址,默认为Pod IP,也可以在httpHeaders中使用“Host:”来定义。
httpHeaders    <[]Object>:自定义的请求报文首部。
port    <string>:请求的端口,必选字段。
path    <string>:请求的HTTP资源路径,即URL path。
scheme    <string>:建立连接使用的协议,仅可为HTTP或HTTPS,默认为HTTP。

  • 编写YMAL文件

[root@master01 ~]# vim 02_pod_liveness_httpget.yaml
apiVersion: v1
kind: Pod
metadata:
  name: liveness-httpget
  namespace: default
spec:
  containers:
  - name: liveness
    image: harbor.wego.red/library/nginx:latest
    imagePullPolicy: IfNotPresent
    ports:
    - name: http
      containerPort: 80
    livenessProbe:
      httpGet:                          # 使用httpGet方式
        port: http                      # http协议
        path: /index.html               # 探测家目录下的index.html
      initialDelaySeconds: 3            # 延迟3秒开始探测
      periodSeconds: 5                  # 每隔5s钟探测一次

  • 应用YAML文件

[root@master01 ~]# kubectl apply -f pod-liveness-httpget.yml

  • 验证查看

[root@master01 ~]# kubectl get pods
NAME               READY   STATUS             RESTARTS   AGE
liveness-httpget   1/1     Running            0          9s

  • 交互删除nginx里的主页文件

[root@master01 ~]# kubectl exec -it liveness-httpget -- rm -rf /usr/share/nginx/html/index.html

  • 验证查看会发现

[root@master01 ~]# kubectl get pod
NAME               READY   STATUS    RESTARTS   AGE
liveness-httpget   1/1     Running   1          11m

4.10.1.4 liveness-tcpSocket案例

  • 编写YAML文件

[root@master01 ~]# vim 03_pod_liveness_tcp.yaml
apiVersion: v1
kind: Pod
metadata:
  name: liveness-tcp
  namespace: default
spec:
  containers:
  - name: c1
    image: harbor.wego.red/library/nginx:latest
    imagePullPolicy: IfNotPresent
    ports:
    - name: http
      containerPort: 80
    livenessProbe:
      tcpSocket:                        # 使用tcp连接方式
        port: 80                        # 连接80端口进行探测
      initialDelaySeconds: 3
      periodSeconds: 5

  • 应用YAML文件创建pod

[root@master01 ~]# kubectl apply -f pod-liveness-tcp.yml
pod/liveness-tcp created

  • 查看验证

[root@master01 ~]# kubectl get pod
NAME               READY   STATUS             RESTARTS   AGE
liveness-tcp       1/1     Running            0          14s

  • 交互关闭nginx

[root@master01 ~]# kubectl exec -it liveness-tcp -- /usr/sbin/nginx -s stop

  • 再次验证查看

[root@master01 ~]# kubectl get pod
NAME               READY   STATUS    RESTARTS   AGE
liveness-tcp       1/1     Running   1          5m13s
​
也只重启1次,重启后重新初始化了

4.10.2 readiness

Pod对象启动后,容器应用通常需要一段时间才能完成其初始化过程,例如加载配置或数据,甚至有些程序需要运行某类的预热过程,若在这个阶段完成之前即接入客户端的请求,势必会等待太久。因此,这时候就用到了就绪性探测(readinessProbe)。

与存活性探测机制类似,就绪性探测是用来判断容器就绪与否的周期性(默认周期为10秒钟)操作,它用于探测容器是否已经初始化完成并可服务于客户端请求,探测操作返回”success“状态时,即为传递容器已经”就绪“的信号。

就绪性探测也支持ExecHTTPGetTCPSocket三种探测方式,且各自的定义机制也都相同。但与存活性探测触发的操作不同的是,探测失败时,就绪探测不会杀死或重启容器以保证其健康性,而是通知其尚未就绪,并触发依赖于其就绪状态的操作(例如,从Service对象对应的端点列表中移除此Pod对象)以确保不会有客户端请求接入此Pod对象。

4.10.2.1: readiness案例

  • 编写YAML文件

[root@master01 ~]# vim 04_pod_readiness_httpget.yaml
apiVersion: v1
kind: Pod
metadata:
  name: readiness-httpget
  namespace: default
spec:
  containers:
  - name: c1
    image: harbor.wego.red/library/nginx:latest
    imagePullPolicy: IfNotPresent
    ports:
    - name: http
      containerPort: 80
    readinessProbe:                     # 这里由liveness换成了readiness
      httpGet:
        port: http
        path: /index.html
      initialDelaySeconds: 3
      periodSeconds: 5
---
apiVersion: v1
kind: Service
metadata:
  name: readiness-svc
spec:
  type: ClusterIP
  ports:
  - port: 80
    targetPort: 80
  selector:
    app: nginx

  • 应用YAML文件

[root@master01 ~]# kubectl apply -f pod-readiness-httpget.yaml
pod/readiness-httpget created

  • 验证查看

[root@master01 ~]# kubectl get pod
NAME                READY   STATUS             RESTARTS   AGE
readiness-httpget   1/1     Running            0          10s

  • 交互删除nginx主页

[root@master01 ~]# kubectl exec -it readiness-httpget -- rm -rf /usr/share/nginx/html/index.html

  • 再次验证

[root@master01 ~]# kubectl get pod
NAME                READY   STATUS    RESTARTS   AGE
readiness-httpget   0/1     Running   0          2m49s
​
READY状态为0/1

  • 交互创建nginx主页文件再验证

[root@master01 ~]# kubectl exec -it readiness-httpget -- touch /usr/share/nginx/html/index.html
[root@master01 ~]# kubectl get pod
NAME                READY   STATUS             RESTARTS   AGE
readiness-httpget   1/1     Running            0          3m10s
​
READY状态又为1/1了

通过上面测试可以看出,当我们删除了nginx主页文件后,readinessProbe发起的测试就会失败,此时我们再查看pod的状态会发现并不会将pod删除重新启动,只是在READY字段可以看出,当前的Pod处于未就绪状态。

4.10.3 liveness+readiness综合案例

  • 第一种方法:liveness+readiness

  • 第二种方法:readiness+liveness

  • 编写YAML文件

[root@master01 ~]# vim 05_Pod_liveness_readiness.yaml
apiVersion: v1
kind: Pod
metadata:
  name: liveness-readiness-httpget
  namespace: default
spec:
  containers:
  - name: liveness-readiness
    image: harbor.wego.red/library/nginx:latest
    imagePullPolicy: IfNotPresent
    ports:
    - name: http
      containerPort: 80
      
    livenessProbe:
      httpGet:
        port: http
        path: /index.html
      initialDelaySeconds: 1
      periodSeconds: 3
      
    readinessProbe:
      httpGet:
        port: http
        path: /index.html
      initialDelaySeconds: 5
      periodSeconds: 5  

  • 应用YAML文件

[root@master01 ~]# kubectl apply -f 05_pod_liveness_readiness.yaml
pod/liveness-readiness-httpget created

  • 验证

[root@master01 ~]# kubectl get pod
NAME                         READY   STATUS             RESTARTS   AGE
liveness-readiness-httpget   0/1     Running            0          6s
​
[root@master01 ~]# kubectl get pod
NAME                         READY   STATUS             RESTARTS   AGE
​
liveness-readiness-httpget   1/1     Running            0          11s
​

4.11 Pod生命周期事件

Pod生命周期事件是在Pod中容器启动后及容器关闭前所执行的事件。

4.11.1 pod生命周期事件 post start

  • 编写YAML文件

[root@master01 ~]# vim 07_Pod_poststart.yaml
apiVersion: v1
kind: Pod
metadata:
  name: poststart
  namespace: default
spec:
  containers:
  - name: poststart
    image: harbor.wego.red/library/nginx:latest
    imagePullPolicy: IfNotPresent
    lifecycle:                                       # 生命周期事件
      postStart:
        exec:
          command: ["/bin/sh","-c","echo  'hello post start' > /usr/share/nginx/html/index.html"]

  • 应用YMAL文件

[root@master01 ~]# kubectl apply -f 07_Pod_poststart.yaml

  • 验证

[root@master01 ~]# kubectl get pods
NAME                         READY   STATUS             RESTARTS   AGE
poststart                    1/1     Running            0          25s

[root@master01 ~]# kubectl exec -it poststart -- cat /usr/share/nginx/html/index.html
hello post start

4.11.2 pod生命周期事件 pre stop

  • 容器终止前执行的命令

  • 编写YAML文件

[root@master01 ~]# vim 08_Pod_prestop.yaml
apiVersion: v1
kind: Pod
metadata:
  name: prestop
  namespace: default
spec:
  containers:
  - name: prestop
    image: harbor.wego.red/library/nginx:latest
    imagePullPolicy: IfNotPresent
    volumeMounts:
    - name: message
      mountPath: /usr/share/nginx/html/
    lifecycle:
      preStop: 
        exec:
          command: ["/bin/sh","-c","echo 'Web Server stopped' > /usr/share/nginx/html/index.html"]
          
  volumes:
  - name: message
    hostPath:
      path: /tmp

  • 应用YAML文件创建pod

[root@master01 ~]# kubectl apply -f 08_Pod_prestop.yaml
pod/prestop created

  • 删除pod验证

[root@master01 ~]# kubectl delete -f 08_Pod_prestart.yml
pod "prestop" deleted               

  • 查看文件

[root@master01 ~]# kubectl get pods -o wide
NAME      READY   STATUS    RESTARTS   AGE   IP             NODE       NOMINATED NODE   READINESS GATES
prestop   1/1     Running   0          21s   10.224.19.90   worker03   <none>           <none>
​
[root@master01 ~]# ssh worker03.wego.red                                      
[root@worker03 ~]# ls /tmp
index.html
​
[root@worker03 ~]# cat /tmp/index.html
Web Server stopped

4.12 pod调度约束方法

我们为了实现容器主机资源平衡使用, 可以使用约束把pod调度到指定的worker节点

  • nodeName 用于将pod调度到指定的worker名称上

  • nodeSelector 用于将pod调度到匹配Label的worker上

4.12.1 nodeName

  • 编写YAML文件

[root@master01 ~]# vim 09_Pod_nodename.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-nodename
spec:
  nodeName: worker01                       # 通过nodeName调度到worker01节点
  containers:
  - name: nginx
    image: harbor.wego.red/library/nginx:latest

  • 应用YAML文件创建pod

[root@master01 ~]# kubectl apply -f 09_Pod_nodename.yaml
pod/pod-nodename created

  • 验证

[root@master01 ~]# kubectl describe pod pod-nodename |tail -6
Events:
  Type    Reason   Age   From            Message
  ----    ------   ----  ----            -------
  Normal  Pulled   40s   kubelet, worker01  Container image "harbor.wego.red/library/nginx:latest" already present on machine
  Normal  Created  40s   kubelet, worker01  Created container nginx
  Normal  Started  39s   kubelet, worker01  Started container nginx
​
倒数第3行没有使用scheduler,而是直接给worker01了,说明nodeName约束生效

4.12.2 nodeSelector

  • 为worker02打标签

[root@master01 ~]# kubectl label nodes worker02 app=webserver
node/worker02 labeled

  • 编写YAML文件

[root@master01 ~]# vim 10_Pod_nodeselector.yml
apiVersion: v1
kind: Pod
metadata:
  name: pod-nodeselect
spec:
  nodeSelector:                         # nodeSelector节点选择器
    app: webserver                    # 指定调度到标签为app=webserver的节点
  containers:
  - name: nginx
    image: harbor.wego.red/library/nginx:latest

  • 应用YAML文件创建pod

[root@master01 ~]# kubectl apply -f 10_Pod_nodeselector.yaml
pod/pod-nodeselect created

  • 验证

[root@master01 ~]# kubectl describe pod pod-nodeselect |tail -6
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  10s   default-scheduler  Successfully assigned default/pod-nodeselect to worker02
  Normal  Pulled     8s    kubelet, worker02     Container image "nginx:1.15" already present on machine
  Normal  Created    8s    kubelet, worker02     Created container nginx
  Normal  Started    7s    kubelet, worker02     Started container nginx
​
仍然经过了scheduler,但确实分配到了worker02上

4.13 pod故障排除方法

状态描述
Pendingpod创建已经提交到Kubernetes。但是,因为某种原因而不能顺利创建。例如下载镜像慢,调度不成功。
Runningpod已经绑定到一个节点,并且已经创建了所有容器。至少有一个容器正在运行中,或正在启动或重新启动。
completedPod中的所有容器都已成功终止,不会重新启动。
FailedPod的所有容器均已终止,且至少有一个容器已在故障中终止。也就是说,容器要么以非零状态退出,要么被系统终止。
Unknown由于某种原因apiserver无法获得Pod的状态,通常是由于Master与Pod所在主机kubelet通信时出错。
CrashLoopBackOff多见于CMD语句错误或者找不到container入口语句导致了快速退出,可以用kubectl logs 查看日志进行排错

排错命令作用
kubectl describe pod pod名查看Pod描述
kubectl logs pod [-c CONTAINER]查看Pod日志
kubectl exec POD [-c CONTAINER] --COMMAND [args...]在Pod中执行命令

五、学习总结

六、课程预约

深入学习kubernetes,可以预约《kubernetes集群从入门到企业应用实战》相关课程。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/259666.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

stack刷题

最小栈 最小栈 设计一个支持 push &#xff0c;pop &#xff0c;top 操作&#xff0c;并能在常数时间内检索到最小元素的栈。 实现 MinStack 类: MinStack() 初始化堆栈对象。void push(int val) 将元素val推入堆栈。void pop() 删除堆栈顶部的元素。int top() 获取堆栈顶部…

C#文件操作(一)

一、前言 学习心得&#xff1a;C# 入门经典第8版书中的第20章《文件》 二、操作文件的相关类 在C#应用程序中Syste.IO名称空间包含用于在文件中读写数据的类。在此我列举一下File、Directory、Path、FileInfo、DirectoryInfo、FileSystemInfo、FileSystemWatcher。其中在Syste…

解决Android studio 创建虚拟机时提示a system image must be selected continue问题

在使用android studio的时候&#xff0c;很多新手在创建虚拟机的时候回出现 a system image must be selected continue错误。 里明显是缺少了systemImage,解决方法如下 打开SDK MANAGER,然后把右下角的show package details勾上,把对应的system image下载下来即可

mysql:查看服务端为了处理连接而创建的线程数量

使用命令show global status like Threads_created;可以查看服务端为了处理连接而创建的线程数量。 例如&#xff1a;

5G+云渲染技术:将如何快速推进XR和元宇宙?

XR&#xff08;扩展现实&#xff09;领域正在以惊人的速度增长。目前&#xff0c;到 2024 年&#xff0c;一些专家表示这个行业的价值将达到 3000 亿美元。 这个行业发展如此迅速的部分原因是 XR 将在商业环境中的带来巨大利益。近年来&#xff0c;很多企业遇到了将增强现实和…

【lesson18】MySQL内置函数(1)日期函数和字符串函数

文章目录 日期函数函数使用具体使用案例建表插入数据建表插入数据 字符串函数函数使用具体使用案例建表插入数据测试 日期函数 函数使用 获得年月日&#xff1a; 获得时分秒&#xff1a; 获得时间戳&#xff1a; 获得现在的时间&#xff1a; 在日期的基础上加日期&#xf…

Unity中URP下的半透明效果实现

文章目录 前言一、实现半透明的步骤1、修改Blend模式&#xff0c;使之透明2、打开深度写入&#xff0c;防止透明对象穿模3、在Tags中&#xff0c;修改渲染类型和渲染队列为半透明 Transparent 二、对透明效果实现从下到上的透明渐变1、 我们在 Varying 中&#xff0c;定义一个v…

vue3表格导入导出.xlsx

在这次使用时恰好整出来了&#xff0c;希望大家也能学习到&#xff0c;特此分享出来 使用前确保安装以下模块&#xff0c;最好全局配置element-plus ### 展示一下 ### ###导出选项 ### ###导入de数据 ### 安装的模块 npm install js-table2excel // 安装js-table2excel n…

翻译: LLMs离通用人工智能AGI有多远 20个小时学会开车 Artificial General Intelligence

AGI&#xff0c;即人工通用智能&#xff0c;是一个令人兴奋的概念。我认为围绕它的一些混淆源于“通用”这个词的使用。正如您所知&#xff0c;人工智能是一种通用技术&#xff0c;意味着它对许多不同的事情都有用。大型语言模型的崛起导致了像ChatGPT这样的单一模型可以用于许…

Java发起SOAP请求代码参考

目录 Java发起SOAP请求代码参考 代码1.组装参数2.加密参数3.发起连接4.解析返回数据 参考 文章所属专区 超链接 代码 1.组装参数 <?xml version"1.0" encoding"UTF-8"?> <beans xmlns"http://www.springframework.org/schema/beans&qu…

AUTOSAR CanTSyn模块配置与代码实现(二)

AUTOSAR CanTSyn模块配置与代码实现 1、FUP message处理 CanTSyn_process_FUP_message 先比较和SYNC报文的Sequence是否相等&#xff0c;如果不相等则不接受该报文。 然后调用CanTSyn_unpack_store_fup处理fup报文。 获取接收到FUP时的本地时间&#xff0c;并与接收到的SYNC…

虚拟机无法进入系统问题

概述 客户在华为云平台上创建了两台虚拟机并部署aarch64 V10 OS&#xff0c;2021-10-28其中一台虚拟机业务出现异常&#xff0c;运维重启虚拟机后系统进不去&#xff0c;左上角光标闪烁&#xff0c;接着重启另一台虚拟机同样起不来&#xff0c;现象一致。 分析 通过分析现场…

天眼销使用指南

刚做销售的你&#xff0c;打电话是不是总是被客户拒决&#xff1f;要不打过去就是空号错号、找不着人&#xff1f;更甚者连客户电话都不知道&#xff1f; 如何快~速找到目标客户准确的联系方式呢&#xff1f;赶紧把这份使用指南请收好&#xff0c;客户不用愁。 1、进入【天眼…

0. Java简介与安装配置

0. Java简介与安装配置 文章目录 0. Java简介与安装配置1.1 Java简介1.2 Java特性1.2 Linux环境安装1.3 Windows环境安装1.3.1 下载JDK安装包1.3.2 安装JDK3. 配置JAVA环境4. 检验安装是否成功 1.3 开发工具参考文献 1.1 Java简介 Java是一门面向对象]编程语言&#xff0c;不仅…

部分常用算法笔记

一、简单易考 1、冒泡排序 https://www.nowcoder.com/practice/2baf799ea0594abd974d37139de27896 for i:0;i<length;i { for j:0;j<length-i-1;j { if array[j] > array[j1] { array[j1],array[j] array[j],array[j1] } } } 2、求数组最大最小值。 1&#xff09;O(…

Hudi 表类型和查询类型

数据湖hudi的表类型定义了数据在DFS上如何组织布局&#xff0c;同时实现一些timeline等操作&#xff08;表类型定定义数据是如何写入的&#xff09;&#xff1b;查询类型则是定义如何读取DFS上的数据。 Table typequery typeCopy-On-Write 快照查询&#xff1b; 增量查询&…

若依系列框架RuoYi(104集),RuoYi-Vue(121集)、RuoYi-Cloud(134集)最新完整视频.txt

若依系列框架RuoYi(104集),RuoYi-Vue&#xff08;121集&#xff09;、RuoYi-Cloud&#xff08;134集&#xff09;最新完整视频.txt

C/C++ BM1反转链表

文章目录 前言题目1.解决方案一1.1 思路阐述1.2 源码 2. 解决方案二2.1 思路阐述2.2 源码 总结 前言 这题是牛客网的BM1&#xff0c;主要涉及到链表的操作以及栈数据结构的使用。 题目 给定一个单链表的头结点pHead(该头节点是有值的&#xff0c;比如在下图&#xff0c;它的…

Arduino开发实例-液体流量测量

液体流量测量 文章目录 液体流量测量1、流量传感器介绍2、硬件准备及接线3、代码实现在本文中,将介绍如何流量传感器进行测量液体流量。 流量传感器用于测量液体流速。 市场上有不同类型的流量传感器,在本文中,我们将使用霍尔效应流量传感器。 这些类型的流量传感器是非侵入…

不是私域难做,是我们做私域的方法该换了!

最近&#xff0c;有一些声音在不断变多&#xff1a;私域越来越难做了&#xff01;许多过去做私域的成功经验&#xff0c;今天好像都不奏效了。 在业绩层面上&#xff0c;很多企业一开始还能通过大量拉新、信息轰炸这种“博概率”的方式获得销量&#xff0c;但时间一长&#xf…
最新文章