写点什么

Kubernetes 手记(6)- POD 配置清单

用户头像
雪雷
关注
发布于: 2021 年 06 月 09 日
Kubernetes手记(6)- POD 配置清单

六 POD 配置清单

6.1 pods.metadata POD 元数据

6.1.1 labels 标签

  • labels 定义标签,键值对组成的标签


  labels:    app: myapp    tier: frontend
复制代码

6.2 pods.spec 规范

6.2.1 nodeName 运行节点

  • 在使用资源清单定义 pod 时候,使用 nodeName 可以直接绑定资源对象在哪个 POD 运行的节点


apiVersion: v1kind: Podmetadata:  name: pod-deme  namespace: default  labels:    app: myapp    tier: frontendspec:  nodeName: node2                           # 直接指定 POD 运行的节点  containers:  - name: myapp    image: ikubernetes/myapp:v1    imagePullPolicy: IfNotPresent
复制代码

6.2.2 nodeSelector 节点选择

  • 在使用资源清单定义 pod 时候,使用 nodeSelector (节点标签选择器)字段,来定义节点的倾向性


apiVersion: v1kind: Podmetadata:  name: pod-deme  namespace: default  labels:    app: myapp    tier: frontendspec:  nodeSelector:                            # 在 spec 中定义这个 POD 的节点倾向性    disktype: ssd                         # 这个 POD 最终会运行在拥有 disktype 标签且值为 ssd 的 nodes 上  containers:  - name: myapp    image: ikubernetes/myapp:v1    imagePullPolicy: IfNotPresent    ports:
复制代码


  • 从文件启动 pod,观察 pod 运行的节点,会发现已经运行在有标签的 node 节点上了


kubectl create -f pod-demo.yaml
复制代码


kubectl get pods -o wide
复制代码


NAME       READY   STATUS    RESTARTS   AGE   IP            NODE    NOMINATED NODE   READINESS GATESpod-demo   1/1     Running   0          21s   10.244.2.29   node3   <none>           <none>
复制代码

6.2.3 restartPolicy POD 重启策略

Always:一旦容器挂了,那么总是重启它,k8s 每次重启策略为 30 秒的两倍,直到等待 300 秒重启。


OnFailure:只有其状态为错误的时候才去重启它


Never:从来不重启,挂了就挂了


一旦某个 POD 被调度到某个节点上,只要这个节点在,那么它就不会被重新调度,只能被重启,除非 POD 被删除才会被重新调度,或者 node 挂了,才会被重新调度,否则只要 node 在,那么 POD 就不会被重新调度,如果 POD 启动失败,那么将不断的重启 POD。
复制代码


当需要终止 POD ,k8s 发送 kill -15 信号,让容器平滑的终止,等待 30 秒的宽限期,如果没有终止,那么则发送 kill 信号
复制代码

6.2.4 hostNetwork 主机网络空间

使用布尔值指定是否让 POD 使用主机的网络名称空间

6.2.5 hostPID 主机 PID 空间

使用布尔值指定是否让 POD 使用主机的 PID 名称空间

6.2.6 containers 配置

kubectl explain pods.spec.containers


描述 POD 内所运行容器,语法:containers <[]Object>,表示它的值为数组,数组内使用对象的方式来描述一个容器,对象可以有以下参数:


  • 可用参数



  • 示例型配置


apiVersion: v1kind: Podmetadata:  name: pod-deme                     # pod 的名称  namespace: default  labels:    app: myapp    tier: frontendspec:  containers:    - name: myapp                      # 运行的容器名称      image: ikubernetes/myapp:v1      # 容器的镜像      imagePullPolicy: IfNotPresent    # 从仓库获取镜像的策略      ports:                           # 定义容器暴漏的端口    - name: busybox      image: busybox:latest      command:        - "/bin/sh"        - "-c"        - "sleep 10"
复制代码

6.2.6.1 imagePullPolicy 下载策略

  • imagePullPolicy 镜像获取的策略,详见:kubectl explain pods.spec.containers


Always            # 总是从仓库下载Never             # 从不下载,本地有就用,没有就失败IfNotPresent      # 如果本地存在就直接使用,如果不存在就下载
复制代码


如果标签是 latest 那么则始终从仓库下载

6.2.6.2 ports 端口信息

  • ports 定义容器保暴露的,详见:kubectl explain pods.spec.containers.ports


在此处暴露的端口可为系统提供有关容器的网络连接的信息,但主要是信息性的,此处没有指定的端口也不会阻止容器暴露该端口,容器中任何侦听 0.0.0.0 地址的端口都可以从网络访问


    ports:                    # 定义两个端口对象一个 http 一个 https    - name: http              # 定义这个端口的名称,方便别的对象取引用      containerPort: 80       # 端口号    - name: https             # 方便引用的名称      containerPort: 443      # 这个端口号仅仅是起到信息的作用,方便查看和使用名称引用
复制代码

6.2.6.3 env 传递环境变量

  • Use Pod fields


      env:        - name: MY_NODE_NAME          valueFrom:            fieldRef:              fieldPath: spec.nodeName        - name: MY_POD_NAME          valueFrom:            fieldRef:              fieldPath: metadata.name        - name: MY_POD_NAMESPACE          valueFrom:            fieldRef:              fieldPath: metadata.namespace        - name: MY_POD_IP          valueFrom:            fieldRef:              fieldPath: status.podIP        - name: MY_POD_SERVICE_ACCOUNT          valueFrom:            fieldRef:              fieldPath: spec.serviceAccountName
复制代码


  • Use Container fields


      env:        - name: MY_CPU_REQUEST          valueFrom:            resourceFieldRef:              containerName: test-container              resource: requests.cpu        - name: MY_CPU_LIMIT          valueFrom:            resourceFieldRef:              containerName: test-container              resource: limits.cpu        - name: MY_MEM_REQUEST          valueFrom:            resourceFieldRef:              containerName: test-container              resource: requests.memory        - name: MY_MEM_LIMIT          valueFrom:            resourceFieldRef:              containerName: test-container              resource: limits.memory
复制代码


在容器中获取 POD 的信息
可以使用环境变量可以使用 downwardAPIhttps://kubernetes.io/zh/docs/tasks/inject-data-application/downward-api-volume-expose-pod-information/
复制代码

6.2.6.4 command ENTRYPOINT

  • command 定义容器运行的程序,详见:


https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/


一个 entrypoint array 而 command 启动的程序是不会运行在 Shell 中的,如果想要运行在 Shell 中需要自己填写,如果没有提供这个指令,那么将运行 docker 镜像中的 ENTRYPOINT。


6.2.6.5 args CMD

  • args 向 command 传递参数的


如果你没有定义 args 而镜像中又存在 ENTRYPOINT 指令和 CMD 指令,那么镜像自己的 CMD 将作为参数传递给 ENTRYPOINT。如果手动指定了 args 那么镜像中的 CMD 字段不再作为参数进行传递。


如果在 args 中引用了变量,则需要使用 $(VAR_NAME),转义后在容器内使用。


env:- name: MESSAGE  value: "hello kaliarch"command: ["/bin/echo"]args: ["$(MESSAGE)"]
复制代码

6.2.6.6 annotations 注解信息

annotations 与 label 不同的地方在于,它不能用于挑选资源对象,仅为对象提供元数据,它的长度不受限制


apiVersion: v1kind: Podmetadata:  name: pod-deme  namespace: default  labels:    app: myapp    tier: frontend  annotations:                                      # 注解关键字    kaliarch/created-by: "xuel"                     # 添加键值对的资源注解spec:  containers:  - name: myapp    image: ikubernetes/myapp:v1    imagePullPolicy: IfNotPresent
复制代码

6.2.6.7 POD 生命周期

  • 一般状态


Pending:已经创建但是没有适合运行它的节点,已经调度,但是尚未完成Running:运行状态Failed: 启动失败Succeed:成功,这个状态很短Unkown: 未知的状态,如果 Apiserver 与 kubelet 通信失败则会处于这个状态
复制代码


  • 创建 POD 阶段


用户的创建请求提交给 apiserver ,而 apiserver 会将请求的目标状态保存在 etcd 中,而后 apiserver 会请求 schedule 进行调度,并且把调度的结果更新在 etcd 的 pod 状态中,随后一旦保存在 etcd 中,并完成 schedule 更新后目标节点的 kubelet 就会从 etcd 的状态变化得知有新任务给自己,所以此时会拿到用户所希望的资源清单目标状态,根据清单在当前节点运行这个 POD,如果创建成功或者失败,则将结果发回给 apiserver ,apiserver 再次保存在 etcd 中。

6.2.6.8 livenessProbe 存活性探测

详细见:kubectl explain pods.spec.containers.livenessProbe


  • livenessProbe / readinessProbe 是 k8s 两个生命周期,这两个生命周期都可以定义探针来探测容器状态做出不同反应


livenessProbe     # 指示容器是否正在运行。如果存活探测失败,则依据 restartPolicy 策略来进行重启readinessProbe    # 指示容器是否准备好服务请求。如果就绪探测失败端点控制器将从与 Pod 匹配的所有 Service 的端点中删除该 Pod 的 IP 地址
复制代码


  • livenessProbe / readinessProbe 可用的探针和探针特性,探针只能定义一种类型,例如:HTTPGetAction


exec          # 在容器内执行指定命令。如果命令退出时返回码为 0 则认为诊断成功。tcpSocket     # 对指定端口上的容器的 IP 地址进行 TCP 检查。如果端口打开,则诊断被认为是成功的。httpGet       # HTTP GET 请求指定端口和路径上的容器。如果响应码大于等于200 且小于 400,则诊断被认为是成功的。
复制代码


failureThreshold    # 探测几次才判定为探测失败,默认为 3 次。periodSeconds       # 每次探测周期的间隔时长。timeoutSeconds      # 每次探测发出后等待结果的超时时间,默认为 1 秒。initalDelaySeconds  # 在容器启动后延迟多久去进行探测,默认为启动容器后立即探测。
复制代码


  • 使用 exec 探针,实验结果应该为 39 秒后 POD 显示 ERROR ,但不自动重启 POD


apiVersion: v1kind: Podmetadata:  name: execlive  namespace: default  labels:    app: myapp    tier: frontendspec:  containers:    - name: busybox      image: busybox      command:        - "/bin/sh"        - "-c"        - "touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 3600"    # 创建一个文件等待 30 秒,这个时间探针应该是成功的,30 秒后则失败      livenessProbe:                                   # 容器的存活性检测,如果失败则按照 restartPolicy 策略来重启 POD        exec:                                          # exec 类型探针,进入容器执行一条命令          command: ["test", "-e" ,"/tmp/healthy"]      # 执行的命令为测试文件存在性        initialDelaySeconds: 2                         # 容器启动后延迟多久进行探测        periodSeconds: 3                               # 每次探测周期的间隔时长为 3 秒        failureThreshold: 3                            # 3 次失败后则判定为容器探测存活性失败  restartPolicy: Never                                 # 当探测到容器失败是否重启 POD
复制代码


  • 使用 httpGet 探针,实验结果应该大约 40 秒后探测存活性失败,自动重启 POD,第一次重启会立即进行,随后是 30 秒的 2 倍直到 300 秒。


apiVersion: v1kind: Podmetadata:  name: httpgetlive  namespace: default  labels:    app: myapp    tier: frontendspec:  containers:    - name: nginx      image: ikubernetes/myapp:v1      ports:        - name: http          containerPort: 80        - name: https          containerPort: 443      livenessProbe:                   # 容器的存活性检测,如果失败则按照 restartPolicy 策略来重启 POD        httpGet:                       # httpget 探针          path: /error.html            # 探测的页面,为了效果这个页面不存在          port: http                   # 探测的端口,使用名称引用容器的端口          httpHeaders:                 # httpget 时候设置请求头            - name: X-Custom-Header              value: Awesome        initialDelaySeconds: 15        # 容器启动后延迟多久进行探测        timeoutSeconds: 1              # 每次探测发出等待结果的时长  restartPolicy: Always                # 当探测到容器失败是否重启 POD
复制代码

6.2.6.9 readinessProbe 就绪性检测

例如有一个容器运行的是 tomcat ,而 tomcat 展开 war 包,部署完成的时间可能较长,而默认 k8s 会在容器启动就标记为 read 状态,接收 service 的调度请求,但是容器启动不代表 tomcat 已经成功运行,所以需要 readinessProbe 进行就绪性探测,来决定是否可以接入 service 上。


  • livenessProbe / readinessProbe 可用的探针和探针特性基本一样,探针只能定义一种类型,例如:HTTPGetAction


livenessProbe     # 指示容器是否正在运行。如果存活探测失败,则依据 restartPolicy 策略来进行重启readinessProbe    # 指示容器是否准备好服务请求。如果就绪探测失败端点控制器将从与 Pod 匹配的所有 Service 的端点中删除该 Pod 的 IP 地址
复制代码


  • 使用 httpGet 探针,实验结果应该大约 40 秒后探测存活性失败,自动重启 POD,第一次重启会立即进行,随后是 30 秒的 2 倍直到 300 秒。


apiVersion: v1kind: Podmetadata:  name: httpgetread  namespace: default  labels:    app: myapp    tier: frontendspec:  containers:    - name: nginx      image: ikubernetes/myapp:v1      ports:        - name: http          containerPort: 80        - name: https          containerPort: 443      livenessProbe:                   # 容器的存活性检测,如果失败则按照 restartPolicy 策略来重启 POD        httpGet:                       # httpget 探针          path: /error.html            # 探测的页面,为了效果这个页面不存在          port: http                   # 探测的端口,使用名称引用容器的端口          httpHeaders:                 # httpget 时候设置请求头            - name: X-Custom-Header              value: Awesome        initialDelaySeconds: 15        # 容器启动后延迟多久进行探测        timeoutSeconds: 1              # 每次探测发出等待结果的时长  restartPolicy: Always                # 当探测到容器失败是否重启 POD
复制代码


  • 手动进入容器,删除 index.html 以触发就绪性探针的检测


kubectl exec -it httpgetread -- /bin/sh$ rm -f /usr/share/nginx/html/index.html
复制代码


  • 结果这个 POD 的 READY 状态已经变成非就绪了,此时 service 不会再调度到这个节点了


[root@node1 ~]# kubectl get pods -wNAME                            READY   STATUS    RESTARTS   AGEhttpgetread                     0/1     Running   0          2m50s
复制代码


  • 在容器内再创建一个文件,以触发就绪性探针的检测


kubectl exec -it httpgetread -- /bin/sh$ echo "hello worlld" >>/usr/share/nginx/html/index.html
复制代码


  • 结果这个 POD 的的 READY 状态已经编程就绪了,此时 service 会调度到这个节点了


[root@node1 ~]# kubectl get pods -wNAME                            READY   STATUS    RESTARTS   AGEhttpgetread                     1/1     Running   0          8m15s
复制代码

6.2.6.10 lifecycle 生命周期钩子

详见:kubectl explain pods.spec.containers.lifecycle


postStart           # 在容器启动后立即执行的命令,如果这个操作失败了,那么容器会终止,且根据 restartPolicy 来决定是否重启preStop             # 在容器终止前立即执行的命令
复制代码


  • postStart / preStop 的基本使用


apiVersion: v1kind: Podmetadata:  name: lifecycle-demospec:  containers:  - name: lifecycle-demo-container    image: nginx
lifecycle: postStart: exec: command: ["/bin/sh", "-c", "echo Hello from the postStart handler > /usr/share/message"] preStop: exec: command: ["/usr/sbin/nginx","-s","quit"]
复制代码


POD 控制器


控制器管理的 POD 可以实现,自动维护 POD 副本数量,它能实现 POD 的扩容和缩容,但是不能实现滚动更新等高级功能。


其他

自己将手记发在:https://github.com/redhatxl/awesome-kubernetes-notes欢迎一键三连

发布于: 2021 年 06 月 09 日阅读数: 6
用户头像

雪雷

关注

stay hungry stay foolish 2019.08.16 加入

Devops,python,shell,云原生,云架构,kubernetes https://github.com/redhatxl

评论

发布
暂无评论
Kubernetes手记(6)- POD 配置清单