pod是k8s中最小的一个单元

Pod用法

通常不需要直接创建pod甚至单实例pod,可以使用 deployment或job这类工作负载资源来创建pod,如果pod需要有状态 可以考虑StatefulSet资源

  1. 运行单个容器的pod 每个pod一个容器 是最常见的k8s用例,在这种情况下,可以将Pod看作单个容器的包装器,kubernetes直接管理pod,而不是容器
  2. 运行多个协同工作的容器的Pod,pod可能封装由多个紧密耦合且需要共享资源的共处容器组成的应用程序,这些位于同一位置的容器可能形成单个内聚的服务单元——一个容器将文件从共享卷提供给公众,而另外一个单独的“边车”(sidecar)容器则刷新或更新这些文件,Pod将这些容器和存储资源打包成一个可管理的实体

    Pod 阶段

    Pod 的 status 字段是一个 PodStatus 对象,其中包含一个 phase 字段。
    Pod 的阶段(Phase)是 Pod 在其生命周期中所处位置的简单宏观概述。 该阶段并不是对容器或 Pod 状态的综合汇总,也不是为了成为完整的状态机。
    Pod 阶段的数量和含义是严格定义的。 除了本文档中列举的内容外,不应该再假定 Pod 有其他的 phase 值。
    下面是 phase 可能的值:
取值 描述
Pending(悬决) Pod 已被 Kubernetes 系统接受,但有一个或者多个容器尚未创建亦未运行。此阶段包括等待 Pod 被调度的时间和通过网络下载镜像的时间,
Running(运行中) Pod 已经绑定到了某个节点,Pod 中所有的容器都已被创建。至少有一个容器仍在运行,或者正处于启动或重启状态。
Succeeded(成功) Pod 中的所有容器都已成功终止,并且不会再重启。
Failed(失败) Pod 中的所有容器都已终止,并且至少有一个容器是因为失败终止。也就是说,容器以非 0 状态退出或者被系统终止。
Unknown(未知) 因为某些原因无法取得 Pod 的状态。这种情况通常是因为与 Pod 所在主机通信失败。

容器状态

Kubernetes 会跟踪 Pod 中每个容器的状态,就像它跟踪 Pod 总体上的阶段一样。 你可以使用容器生命周期回调 来在容器生命周期中的特定时间点触发事件。
一旦调度器将 Pod 分派给某个节点,kubelet 就通过 容器运行时 开始为 Pod 创建容器。 容器的状态有三种:Waiting(等待)、Running(运行中)和 Terminated(已终止)。
要检查 Pod 中容器的状态,你可以使用kubectl describe pod <pod 名称>。 其输出中包含 Pod 中每个容器的状态。

每种状态都有特定的含义:

  • Waiting (等待)

如果容器并不处在 Running 或 Terminated 状态之一,它就处在 Waiting 状态。 处于 Waiting 状态的容器仍在运行它完成启动所需要的操作:例如,从某个容器镜像 仓库拉取容器镜像,或者向容器应用 Secret 数据等等。 当你使用 kubectl 来查询包含 Waiting 状态的容器的 Pod 时,你也会看到一个 Reason 字段,其中给出了容器处于等待状态的原因。

  • Running(运行中)

Running 状态表明容器正在执行状态并且没有问题发生。 如果配置了 postStart 回调,那么该回调已经执行且已完成。 如果你使用 kubectl 来查询包含 Running 状态的容器的 Pod 时,你也会看到 关于容器进入 Running 状态的信息。

  • Terminated(已终止)

处于 Terminated 状态的容器已经开始执行并且或者正常结束或者因为某些原因失败。 如果你使用 kubectl 来查询包含 Terminated 状态的容器的 Pod 时,你会看到 容器进入此状态的原因、退出代码以及容器执行期间的起止时间。

如果容器配置了 preStop 回调,则该回调会在容器进入 Terminated 状态之前执行。

容器重启策略

Pod 的 spec 中包含一个 restartPolicy 字段,其可能取值包括 Always、OnFailure 和 Never。默认值是 Always。
restartPolicy 适用于 Pod 中的所有容器。restartPolicy 仅针对同一节点上 kubelet 的容器重启动作。
当 Pod 中的容器退出时,kubelet 会按指数回退 方式计算重启的延迟(10s、20s、40s、…),其最长延迟为 5 分钟。
一旦某容器执行了 10 分钟并且没有出现问题,kubelet 对该容器的重启回退计时器执行 重置操作

容器探针

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

  • ExecAction: 在容器内执行指定命令。如果命令退出时返回码为 0 则认为诊断成功。
  • TCPSocketAction: 对容器的 IP 地址上的指定端口执行 TCP 检查。如果端口打开,则诊断被认为是成功的。
  • HTTPGetAction: 对容器的 IP 地址上指定端口和路径执行 HTTP Get 请求。如果响应的状态码大于等于 200 且小于 400,则诊断被认为是成功的。

每次探测都将获得以下三种结果之一:

  • Success(成功):容器通过了诊断。
  • Failure(失败):容器未通过诊断。
  • Unknown(未知):诊断失败,因此不会采取任何行动。

针对运行中的容器,kubelet 可以选择是否执行以下三种探针,以及如何针对探测结果作出反应:

  • livenessProbe:指示容器是否正在运行。如果存活态探测失败,则 kubelet 会杀死容器, 并且容器将根据其重启策略决定未来。如果容器不提供存活探针, 则默认状态为 Success
  • readinessProbe:指示容器是否准备好为请求提供服务。如果就绪态探测失败, 端点控制器将从与 Pod 匹配的所有服务的端点列表中删除该 Pod 的 IP 地址。 初始延迟之前的就绪态的状态值默认为 Failure。 如果容器不提供就绪态探针,则默认状态为 Success
  • startupProbe: 指示容器中的应用是否已经启动。如果提供了启动探针,则所有其他探针都会被 禁用,直到此探针成功为止。如果启动探测失败,kubelet 将杀死容器,而容器依其 重启策略进行重启。 如果容器没有提供启动探测,则默认状态为 Success

何时该使用启动探针?**

对于所包含的容器需要较长时间才能启动就绪的 Pod 而言,启动探针是有用的。 你不再需要配置一个较长的存活态探测时间间隔,只需要设置另一个独立的配置选定, 对启动期间的容器执行探测,从而允许使用远远超出存活态时间间隔所允许的时长。

如果你的容器启动时间通常超出 initialDelaySeconds + failureThreshold × periodSeconds 总值,你应该设置一个启动探测,对存活态探针所使用的同一端点执行检查。 periodSeconds 的默认值是 10 秒。你应该将其 failureThreshold 设置得足够高, 以便容器有充足的时间完成启动,并且避免更改存活态探针所使用的默认值。 这一设置有助于减少死锁状况的发生。

创建一个nginx pod

创建一个yaml文件 my-nginx.yaml
如果创建pod,最好不要使用hostPort

  1. apiVersion: v1
  2. # Pod类型的资源
  3. kind: Pod
  4. metadata:
  5. name: my-nginx
  6. labels:
  7. name: my-nginx
  8. spec:
  9. containers:
  10. - name: my-nginx
  11. # 要拉取的镜像
  12. image: nginx
  13. resources:
  14. # 给容器设定限制 内存分配128m cpu分配500ms
  15. limits:
  16. memory: "128Mi"
  17. cpu: "500m"
  18. ports:
  19. # 容器端口
  20. - containerPort: 80
  21. # 对外暴露端口
  22. hostPort: 30300

指定yaml文件创建资源

此命令不止是创建pod还可以创建job等

kubectl create -f my-nginx.yaml

查看pod详细描述

kubectl describe pod my-nginx

可以看到容器已经启动成功,将my-nginx分配到node1节点上
image.png
直接使用node1ip和端口即可在页面上访问nginx

进入容器内部

kubectl exec -it my-nginx sh

使用job创建pod

apiVersion: batch/v1
kind: Job
metadata:
  name: hello
spec:
 # 完成5次
  completions: 5
  # Pod模板
  template:
    spec:
      # 这个pod模板就是拉一个Nginx的容器然后执行命令
      containers:
        - name: hello
          image: nginx
          # 执行的命令
          command: ['sh','-c','echo "hello world!"&& sleep 2']
      # 容器重启策略
      restartPolicy: OnFailure

查看job

kubectl get job

已经完成五次
image.png
查看一下job创建的Pod
已经创建了5个pod 而且都状态都是执行完成
image.png

监控pod

kubectl get po -w

删除job

kubectl delete job hello

job一旦删除 由此job创建的pod也会一并删除

为容器生命周期提供事件处理

把上面的nginx pod yaml做一些修改
在容器启动后和关闭前执行一些命令

apiVersion: v1
# Pod类型的资源
kind: Pod
metadata:
  name: my-nginx
  labels:
    name: my-nginx
spec:
  containers:
    - name: my-nginx
    # 要拉取的镜像
      image: nginx
      lifecycle:
        postStart:
          exec: 
          # 容器启动后执行
            command: ['sh','-c','echo "started!"']
        preStop:
          exec: 
          # 容器关闭前执行
            command: ['sh','-c','echo "stop!"']
      resources:
      # 给容器设定限制 内存分配128m cpu分配500ms
        limits:
          memory: "128Mi"
          cpu: "500m"
      ports:
        # 容器端口
        - containerPort: 80 
        # 对外暴露端口
          hostPort: 30300

使用exec命令进入容器后 可以在 /usr/share/message看到命令输出的信息

使用HTTP请求探针

每隔三秒检测一次

apiVersion: v1
kind: Pod
metadata:
  name: liveness-http
  labels:
    test: liveness
spec:
  containers:
    - name: liveness
      image: mirrorgooglecontainers/liveness
      args:
        - /server
      livenessProbe:
        httpGet:
          path: /healthz
          port: 8080
          httpHeaders:
            - name: Custom-Header
              value: Awesome
        initialDelaySeconds: 3
        periodSeconds: 3

mirrorgooglecontainers/liveness镜像对应的是一个go写的程序 /healthz处理程序返回一个200状态码,之后处理程序会返回500状态码,这时探针就会检测到失败 kubelet就会杀死容器然后重启容器
可以观察到容器的重启
image.png

为容器设置启动时要执行的命令

apiVersion: v1
kind: Pod
metadata:
  name: myapp
  labels:
    name: myapp
spec:
  containers:
    - name: myapp
      image: debian
      command: ['printenv']
      args: ['HOSTNAME']
  restartPolicy: OnFailure

使用环境变量来设置参数

apiVersion: v1
kind: Pod
metadata:
  name: myapp
  labels:
    name: myapp
spec:
  containers:
    - name: myapp
      image: debian
      env: 
        - name: MESSAGE
          value: "hello world"
      command: ["/bin/echo"]
      args: ["$(MESSAGE)"]

  restartPolicy: OnFailure

环境变量需要加上括号,类似于”$(VAR)” 这是在command或args字段使用变量的格式要求 变量和引用要注意先后顺序,先定义了才能引用

通过日志可以看到输出的hello world

kubectl logs myapp