1. 闲不住的人首页
  2. Kubernetes

Kubernetes Pod 资源对象入门

什么是 Pod

以下内容摘抄自 Kubernetes 官方文档:


Pod 是 Kubernetes 最基本的组成块,它是 Kubernetes 最小、最简单的可用来创建和部署的单元。 一个 Pod 代表了一个运行在集群里的进程。

Pod 里封装了一个(或者多个)应用容器,存储资源,以及惟一的网络 IP。

Docker 是 Kubernetes Pod 里最常见的运行环境, 当然 Pod 也支持其他的容器环境。

Kubernetes 运用 pod 的方式:

  • Pod 里只运行一个单独容器 “one-container-per-Pod” 模式是 Kubernetes 最常见的使用场景;在这种情况下,可以把 Pod 看做是一个单独容器的连接器, Kubernetes 通过 Pod 去管理容器。
  • Pod 中运行多个相互作用容器。 Pod 封装了一组紧耦合、共享资源、协同寻址的容器。 这些协同寻址的容器可能来自一组粘性很强的服务 – 比如说:在用容器的共享卷提供对外文件服务的同时用 “sidecar” 容器刷新、更新这些文件。Pod 将这些容器和存储资源打包成一个管理实体。

Pod 是标准的 Kubernetes 资源,它也遵循资源定义清单的基本格式:apiVersion、kind、metadata、spec、status(只读,它是由 Kubernetes 系统提供和更新)

本文主要整理里了 Pod.spec 字段可以内嵌的常用字段,重点在 Pod.spec.containers 字段中可定义的众多字段;

1. spec.containers 可内嵌的字段

containers 是 Pod.spec 内嵌字段中唯一一个带有 -required- 标记的字段,而 containers 是一个对象列表,下面说明一下 containers 可内嵌的各字段的作用:

1.1 name

name <String> -required- 必须给出的字段,定义具有唯一性的容器的名称;

举例演示:

containers:
- name: myapp

1.2 image

image <String> 指明容器要运行的镜像;

举例演示:

containers:
- name: myapp
  image: nginx:1.14-alpine

1.3 imagePullPolicy

imagePullPolicy <String> 定义镜像的拉取策略,可定义的值有三个:

  • Always:无论本地有或者没有这个镜像,都去镜像仓库中获取;
  • Never:从不,如果本地仓库有就用,没有也不会下载。需要手动去获取镜像;
  • IfNotPresent:如果本地存在就使用,如果没有就去远程仓库获取;

注意:如果标签是 latest 那么默认策略就是 Always;

举例演示:

containers:
- name: myapp
  image: nginx:1.14-alpine
  imagePullPolicy: IfNotPresent

1.4 ports

ports <[]Object> 定义容器内要暴露的端口,可以暴露多个端口,而且每一个端口都可以有多个属性:

  • containerPort -required- :暴露的端口
  • name :自定义一个名字
  • protocol :协议,TCP或UDP,默认为TCP

举例演示:

containers:
- name: myapp
  image: nginx:1.14-alpine
  imagePullPolicy: IfNotPresent
  ports:
  - name: http
    containerPort: 80
  - name: https
    containerPort: 443

1.5 command 和 args

command 和 args 用来修改镜像中的默认应用;

args <[]string>:作用等同于,Dockerfile中的 CMD,向 ENTRYPOINT 传递参数的,如果这里没有给出 args 参数,而镜像内即有 CMD 又有 ENTRYPOINT 则镜像内 CMD 的参数将传递给 ENTRYPOINT 作为参数;如果这里给了 args 那么,镜像内的 CMD 的参数就不会传递给 ENTRYPOINT,而是用 args 传递的参数;

command <[]string>:作用等同于,Dockerfile中的 ENTRYPOINT 指令,用于运行程序的默认命令;如果没有给出 command 则默认运行镜像制作时的默认程序

在 K8S 文档中给出了 args 和 command 的关系:https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell

举例演示:

apiVersion: v1
kind: Pod
metadata:
  name: command-demo
  labels:
    purpose: demonstrate-command
spec:
  containers:
  - name: command-demo-container
    image: debian
    command: ["printenv"]
    args: ["HOSTNAME", "KUBERNETES_PORT"]

1.6 livenessProbe 和 readinessProbe 探针

探针 是由 kubelet 对容器执行的定期诊断。要执行诊断,kubelet 调用由容器实现的 Handler。有三种类型的处理程序:

ExecAction:在容器内执行指定命令。如果命令退出时返回码为 0 则认为诊断成功。

TCPSocketAction:对指定端口上的容器的 IP 地址进行 TCP 检查。如果端口打开,则诊断被认为是成功的。

HTTPGetAction:对指定的端口和路径上的容器的 IP 地址执行 HTTP Get 请求。如果响应的状态码大于等于200 且小于 400,则诊断被认为是成功的。

每个容器都可以运行两个探针:

  • livenessProbe 存活性探测,用来探测容器内主进程是否活着;
  • readinessProbe 就绪性探测,用来探测容器内主进程是否能够正常提供服务,比如容器内 nginx 主进程是活的,但是网页文件已经不再了,服务是不可用的;

下面我以 livenessProbe 为例演示三种类型的探测方式,readinessPorbe 使用方法相同。

exec 方式

用于在容器内执行命令,如果命令返回的状态码为 0 则认为是成功的;

举例演示:

apiVersion: v1
kind: Pod
metadata:
  name: liveness-exec
  namespace: default
spec:
  containers:
  - name: liveness-exec-container
    image: busybox:latest
    imagePullPolicy: IfNotPresent
    command: ["/bin/sh","-c","touch /tmp/healthy; sleep 30; rm -f /tmp/healthy; sleep 3600"]
    livenessProbe:
      exec:
        command: ["test","-e","/tmp/healthy"]
      initialDelaySeconds: 5
      periodSeconds: 3

上面的 exec 执行命令 test -e 如果探测 /tmp/healthy 文件存在则成功,否则就失败;

httpGet 方式

对指定的端口和路径上的容器的 IP 地址执行 HTTP Get 请求。如果响应的状态码大于等于 200 且小于 400,则诊断被认为是成功的。

apiVersion: v1
kind: Pod
metadata:
  name: liveness-httpget-demo
  namespace: default
spec:
  containers:
  - name: myapp
    image: nginx:1.14-alpine
    ports:
    - name: http
      containerPort: 80
    livenessProbe:
      httpGet:
        port: 80
        path: /index.html
      periodSeconds: 3
      timeoutSeconds: 3

上面对容器内 nginx 服务的 /index.html 页面进行请求,返回 200 就说明成功的;

tcpSocket 方式

对指定端口上的容器的 IP 地址进行 TCP 检查。如果端口打开,则诊断被认为是成功的。

apiVersion: v1
kind: Pod
metadata:
  name: liveness-tcpsocket-demo
  namespace: default
spec:
  containers:
  - name: myapp
    image: nginx:1.14-alpine
    ports:
    - name: http
      containerPort: 80
    livenessProbe:
      tcpSocket:
        port: 80
      periodSeconds: 3
      timeoutSeconds: 3

在 livenessProbe 和 readinessProbe 中还有其它比较重要的参数也需要了解,具体如下:

  • initialDelaySeconds:容器启动后第一次执行探测是需要等待多少秒。
  • periodSeconds:执行探测的频率。默认是10秒,最小1秒。
  • timeoutSeconds:探测超时时间。默认1秒,最小1秒。
  • successThreshold:探测失败后,最少连续探测成功多少次才被认定为成功。默认是 1。对于 liveness 必须是 1。最小值是 1。
  • failureThreshold:探测成功后,最少连续探测失败多少次才被认定为失败。默认是 3。最小值是 1。

1.7 lifecycle

lifecycle <Object> 用于定义容器启动后和容器终止前所执行的两个钩子:

  • postStart <Object> 启动后执行的钩子
  • preStop <Object> 终止前执行的钩子

举例演示:运行一个 nginx 镜像,启动后创建一个 index.html 结束前停止nginx 服务

apiVersion: v1
kind: Pod
metadata:
  name: lifecycle-demo
  namespace: default
spec:
  containers:
  - name: lifecycle-demo-container
    image: nginx:1.14-alpine
    imagePullPolicy: IfNotPresent
    lifecycle:
      postStart:
        exec:
          command: ["/bin/sh", "-c", "echo Hello from the postStart handler > /usr/share/nginx/html/index.html"]
      preStop:
        exec:
          command: ["/usr/sbin/nginx", "-s", "quit"]

创建 Pod 对象,验证 index.html 是否是 postStart 钩子创建的内容

root@k8s-master-opsbj:~/manifests # kubectl apply -f lifecycle-demo.yaml
pod/lifecycle-demo created

root@k8s-master-opsbj:~/manifests # kubectl get pods -o wide
NAME             READY   STATUS    RESTARTS   AGE   IP            NODE                   NOMINATED NODE   READINESS GATES
lifecycle-demo   1/1     Running   0          9s    10.244.2.35   k8s-node02-opsbj.com   <none>           <none>

root@k8s-master-opsbj:~/manifests # curl 10.244.2.35
Hello from the postStart handler

2. spec.nodeName

spec.nodeName <String>:节点选择器,直接指明运行在哪个节点上;

举例演示:pod-demo.yaml

apiVersion: v1
kind: Pod
metadata:
  name: pod-demo
  namespace: default
spec:
  nodeName: k8s-node01-opsbj.com
  containers:
  - name: myapp
    image: nginx:1.14-alpine
    imagePullPolicy: IfNotPresent
    ports:
    - name: http
      containerPort: 80

创建 Pod 对象,验证是否被调度到 k8s-node01-opsbj.com 节点上

root@k8s-master-opsbj:~/manifests # kubectl apply -f pod-demo.yaml
pod/pod-demo created
root@k8s-master-opsbj:~/manifests # kubectl get pods -o wide
NAME       READY   STATUS    RESTARTS   AGE   IP            NODE                   NOMINATED NODE   READINESS GATES
pod-demo   1/1     Running   0          2s    10.244.1.32   k8s-node01-opsbj.com   <none>           <none>

3. spec.nodeSelector

spec.nodeSelector <map[String]String> :节点标签选择器,调度资源运行在持有某个标签的节点上;

举例演示:将 Pod 调度到带有 disktype=ssd 标签的节点上;

模拟环境给其中一个 Node 节点打上标签 disktype=ssd

root@k8s-master-opsbj:~/manifests # kubectl label node k8s-node02-opsbj.com disktype=ssd
node/k8s-node02-opsbj.com labeled

查看 node 节点的标签

查看node节点标签
查看node节点标签

定义资源清单 pod-demo.yaml

apiVersion: v1
kind: Pod
metadata:
  name: pod-demo
  namespace: default
spec:
  nodeSelector:
    disktype: ssd
  containers:
  - name: myapp
    image: nginx:1.14-alpine
    imagePullPolicy: IfNotPresent
    ports:
    - name: http
      containerPort: 80

创建 Pod 对象,验证是否被调度到 k8s-node02-opsbj.com 节点上

验证nodeSelector
验证nodeSelector

4. spec.hostNetwork

spec.hostNetwork <boolean>:直接使用节点的网络名称空间,通过 node IP就可以直接访问 Pod 资源;

举例演示:

apiVersion: v1
kind: Pod
metadata:
  name: pod-demo
  namespace: default
spec:
  hostNetwork: true
  containers:
  - name: myapp
    image: nginx:1.14-alpine
    imagePullPolicy: IfNotPresent
    ports:
    - name: http
      containerPort: 80

创建 Pod 对象,然后通过被调度节点的 IP 访问服务

root@k8s-master-opsbj:~/manifests # kubectl apply -f pod-demo.yaml
pod/pod-demo created

root@k8s-master-opsbj:~/manifests # kubectl get pods -o wide
NAME       READY   STATUS    RESTARTS   AGE   IP             NODE                   NOMINATED NODE   READINESS GATES
pod-demo   1/1     Running   0          10s   10.100.4.182   k8s-node02-opsbj.com   <none>           <none>

在浏览器输入 node 节点的 IP 地址

验证hostNetwork
验证hostNetwork

5. spec.restartPolicy

restartPolicy <String> 定义容器的重启策略,值有三个如下:

  • Always:总是重启
  • OnFailure:只有退出状态为错误时,才重启
  • Never:从不重启

6. Pod 声明周期中的几种状态

  • 挂起(Pending):Pod 已被 Kubernetes 系统接受,但有一个或者多个容器镜像尚未创建。等待时间包括调度 Pod 的时间和通过网络下载镜像的时间,这可能需要花点时间。
  • 运行中(Running):该 Pod 已经绑定到了一个节点上,Pod 中所有的容器都已被创建。至少有一个容器正在运行,或者正处于启动或重启状态。
  • 成功(Succeeded):Pod 中的所有容器都被成功终止,并且不会再重启。
  • 失败(Failed):Pod 中的所有容器都已终止了,并且至少有一个容器是因为失败终止。也就是说,容器以非0状态退出或者被系统终止。
  • 未知(Unknown):因为某些原因无法取得 Pod 的状态,通常是因为与 Pod 所在主机通信失败。

如果觉得文章不错,不妨给个『打赏』写作不易,各位的支持,能激发和鼓励我更大的写作热情。谢谢

原创文章,作者:恩志,如若转载,请注明出处:https://www.xbzdr.com/667.html

发表评论

电子邮件地址不会被公开。 必填项已用*标注

联系我们

在线咨询:点击这里给我发消息

邮件:510749025@qq.com

工作时间:周一至周五,9:30-18:30,节假日休息

QR code