Kubernetes从零到精通(05-Pod)

Pod概念

上节研究了Docker Compose对容器的使用方法,有了一组容器的概念。而Kubernetes中的Pod是可以在Kubernetes中创建和管理的最小的可部署的计算单元。Pod也是一组(一个或多个)容器;这些容器共享存储(可以访问一个逻辑磁盘)、网络(可以通过localhost和端口互相访问)、以及Kubernetes提供的参数约束。同样的,除了应用容器,Pod 还可以包含在Pod启动期间运行的Init容器,也可以注入临时性容器来调试正在运行的 Pod。下面是创建Pod的示例,创建一个文件pod-demo.yaml,内容如下:

apiVersion: v1
kind: Pod
metadata:
  name: nginx-demo
  namespace: example
spec:
  containers:
  - name: nginx
    image: nginx:1.14.1
    ports:
    - containerPort: 80

要创建上面显示的Pod,只需要运行以下kubectl命令,就在example命名空间中创建了nginx-demo:

kubectl apply -f pod-demo.yaml

重要点:如果我们需要运行多个容器副本(类似于传统应用部署方式中,多台服务器部署同一个服务),由之前章节我们提到的,后面会介绍的工作负载控制器(Deployment、StatefulSet等)来实现。由此可见,通常我们不需要直接创建Pod,而是由工作负载控制器这个更高层次的抽象资源来定义和创建Pod。

Pod中的Pause容器

当创建运行一个Pod的时候,Kubernetes会在应用容器启动之前,自动注入一个Pause容器(非常轻量级,几百kb左右,永远处于Pause暂停状态),可以想到Pause容器的主要作用:
1.创建共享网络命名空间:Pause容器首先启动,并创建一个网络命名空间,所有该Pod内的其他业务容器都加入到这个共享的网络命名空间中。这意味着这些容器可以相互通信,如同它们在同一台主机上的进程一样,共享相同的网络栈和IP地址。
2.PID命名空间共享:Pod中的不同容器通过共享Pause容器的PID命名空间,使得容器间能够看到彼此的进程ID。
3.IPC命名空间共享:在同一Pod内的容器也可以通过Pause容器共享IPC命名空间,从而允许它们使用SystemV IPC或POSIX消息队列进行跨容器通信。
4.Pod生命周期管理:虽然Pause容器本身通常是一个非常小且不执行任何实际业务逻辑的镜像(仅包含一个无限循环或暂停进程),但它作为Pod内所有容器的父进程,有助于系统管理和跟踪容器生命周期。
5.存储卷挂载点共享:Pause容器也是负责挂载Pod级别Volume的实体,这样同一个Pod中的多个容器就可以访问相同的持久化存储资源。

Pod存储

一个Pod可以设置一组共享的存储卷。Pod中的所有容器都可以访问该共享卷,从而允许这些容器共享数据。 卷还允许Pod中的持久数据保留下来,即使其中的容器需要重新启动。存储相关的用法会在后面介绍。

Pod网络

在同一个Pod内,所有容器共享一个IP地址和端口空间,并且可以通过localhost发现对方。不同Pod中的容器的IP地址互不相同,如果想网络互通,需要借助更高层面的资源对象实现,例如Service,也会在后面介绍。

静态Pod

静态Pod,是在指定的节点上由kubelet守护进程直接管理,不需要apiserver监管的Pod。与由控制面管理的Pod(如Deployment)不同;kubelet组件会定时扫描配置文件中指定的staticPodPath目录,并在本机器上创建Pod.
静态Pod始终都会绑定到特定节点的Kubelet上,如果我们想在Kubernetes集群的每个节点上都运行一个同样的静态Pod,就需要考虑使用DaemonSet了。

Pod生命周期

Pod遵循预定义的生命周期,起始于Pending阶段, 如果至少其中有一个主要容器正常启动,则进入Running,之后取决于Pod中是否有容器以失败状态结束而进入Succeeded或者Failed阶段。在Pod运行期间,kubelet 能够重启容器以处理一些失效场景,在Pod内部,Kubernetes跟踪不同容器的状态并确定使Pod重新变得健康所需要采取的动作。
Pod的阶段(Phase)是Pod在其生命周期中所处位置的简单宏观概述:
Pending:Pod创建需求已被Kubernetes接收,但有一个或者多个容器尚未创建也未运行。此阶段包括等待Pod被调度的时间和通过网络下载镜像的时间(如果镜像下载不了,需要更改容器运行时的镜像源,或者手动导出导入镜像)。
Running:Pod已经绑定到了某个工作节点,Pod中所有的容器都已被创建。至少有一个容器仍在运行,或者正处于启动或重启状态。
Succeeded:Pod中的所有容器都已成功终止,并且不会再重启。
Failed:Pod中的所有容器都已终止,并且至少有一个容器是因为失败终止。也就是说,容器以非0状态退出或者被系统终止,且未被设置为自动重启。
Unknown:因为某些原因无法取得Pod的状态。这种情况通常是因为与Pod所在主机通信失败。

Pod中的容器状态

Kubernetes也会跟踪Pod中每个容器的状态,就像它跟踪Pod上的阶段一样。我们可以使用容器生命周期回调来在容器生命周期中的特定时间点触发事件。一旦调度器将Pod分派给某个节点,kubelet就通过容器运行时开始为 Pod创建容器。容器的状态有三种:
Waiting:容器仍在运行它完成启动所需要的操作(例如下载容器需要的镜像,或者向容器挂载Secret数据)。
Running:容器正在执行状态并且没有问题发生。如果配置了postStart回调,那么该回调已经执行且已完成。
Terminated:容器已经开始执行,并且正常结束或者因为某些原因失败。如果配置了preStop回调,则该回调会在容器进入Terminated状态之前执行。
使用kubectl查询Pod详细信息时,也能看到如上三种状态容器的一些信息,如异常状态原因等。

Pod中的容器回调

如上提到的PostStart和PreStop是Kubernetes中用于在容器生命周期的特定时间点执行自定义操作的机制,简单介绍下:
PostStart
触发时机:容器创建后立即执行。
用途:可以用于在容器启动后立即执行一些初始化操作,例如配置环境变量、启动辅助进程等。
注意事项:PostStart回调不保证在容器的ENTRYPOINT之前执行,因此需要确保回调操作不会依赖于容器的主进程。
PreStop
触发时机:在容器被终止之前执行。
用途:用于在容器终止前执行清理操作,例如保存状态、关闭连接、释放资源等。
注意事项:PreStop回调必须在容器接收到终止信号之前完成。如果回调执行时间过长,可能会导致容器无法正常终止。
容器可以通过实现和注册回调处理程序来访问这些回调。主要有以下几种类型:
1.Exec:在容器的cgroups和名字空间中执行特定的命令。
2.HTTP:对容器上的特定端点执行HTTP请求。
3.Sleep:将容器暂停一段指定的时间(这是一个Beta级特性)。
以下是一个容器回调的简单示例,这个配置在容器启动后会执行echo Hello from the PostStart handler,在容器终止前会执行echo Goodbye from the PreStop handler

apiVersion: v1
kind: Pod
metadata:
  name: lifecycle-demo
spec:
  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: ["/bin/sh", "-c", "echo Goodbye from the PreStop handler > /usr/share/message"]

Pod中的容器探针 

Kubernetes如何监测容器运行状况,除了生命周期之外,还有探针机制(例如传统的负载均衡上有7层协议健康检查,我们在自己的应用中开发/healthz接口,让负载均衡定期检查接口是否返回200,确保应用没有假死等),主要有三种类型的探针:
1.启动探针(Startup Probe)
用途:检测容器内的应用是否已经成功启动并完成初始化任务。
作用:延缓其他探针生效,在容器启动初期,启动探针先于存活探针和就绪探针生效,确保应用完全启动后再进行其他检查;防止频繁重启,避免在应用启动过程中因未及时响应而被误判为不健康,从而触发不必要的重启。
2.存活探针(Liveness Probe)
用途:检测容器内主进程或服务是否仍然运行正常且响应健康检查。
作用:自动恢复,当存活探针检测失败时,Kubernetes会根据Pod重启策略重新启动容器,帮助实现故障自愈。
3.就绪探针(Readiness Probe)
用途:检测容器是否已经准备好对外提供服务。
作用:流量路由控制,当就绪探针成功时,表示容器已准备好接受请求,Kubernetes会将其IP地址添加到服务的后端列表中;避免无效请求,如果就绪探针失败,Kubernetes会将容器从服务的后端池中移除,确保不会向其发送请求,避免错误响应。
探针可以通过以下三种方式实现:
1.HTTP GET请求:向容器内应用发送HTTP GET请求,检查响应状态码是否在200-399范围内。
2.TCP Socket检查:尝试与容器上的指定端口建立TCP连接,成功建立连接则探测成功。
3.Exec执行命令:在容器内部执行命令,根据命令的退出状态码判断容器是否正常运行。
如下的示例,容器启动30秒后,每10秒检查一次 /healthz路径的响应状态码,以确定容器是否存活;在容器启动5秒后,每10秒检查一次/ready路径的响应状态码,以确定容器是否准备好接受请求(healthz和ready接口当然是在probe-demo-container镜像的应用程序里,由开发和运维根据统一规划进行创建的)。

apiVersion: v1
kind: Pod
metadata:
  name: probe-demo
spec:
  containers:
  - name: probe-demo-container
    image: nginx
    livenessProbe:
      httpGet:
        path: /healthz
        port: 8080
      initialDelaySeconds: 30
      periodSeconds: 10
    readinessProbe:
      httpGet:
        path: /ready
        port: 8080
      initialDelaySeconds: 5
      periodSeconds: 10

Pod重启策略

如上提到的Pod重启策略是用于在Kubernetes中定义容器在不同情况下的重启行为,默认是Always:
1.Always
用途:无论容器退出状态如何,Kubernetes都会自动重启该容器。
适用场景:适用于需要持续运行的服务,例如Web服务器或数据库。
2.OnFailure
用途:仅当容器以非零状态码退出时,Kubernetes才会重启该容器。
适用场景:适用于需要在失败时自动恢复的任务,例如Job批处理作业或数据处理任务。
3.Never
用途:无论容器退出状态如何,Kubernetes都不会重启该容器。
适用场景:适用于一次性任务或不需要自动重启的容器。

Downward API

在Kubernetes中,Downward API允许容器在不直接与Kubernetes API服务器交互的情况下,获取有关自身或集群的信息。这对于保持应用程序的低耦合性非常有用。通过Downward API,容器可以访问Pod和容器级别的元数据和资源信息。
Downward API的方式
1.环境变量:将Pod和容器的字段作为环境变量暴露给容器。
2.Downward API卷:将这些字段作为文件暴露在特殊的卷中。

Pod级可用字段示例(通过fieldRef)
metadata.name:Pod的名称
metadata.namespace:Pod的命名空间
metadata.uid:Pod 的唯一 ID
metadata.annotations[‘<KEY>’]:Pod的注解
metadata.labels[‘<KEY>’]:Pod的标签
spec.serviceAccountName:Pod 的服务账号名称
status.hostIP:Pod所在节点的主IP地址
status.podIP:Pod的主IP地址
容器级可用字段示例(通过resourceFieldRef)
resource:limits.cpu:容器的CPU限制值
resource:limits.memory:容器的内存限制值

以下是一个示例,展示如何使用Downward API将Pod名称和命名空间作为环境变量暴露给容器:

apiVersion: v1
kind: Pod
metadata:
  name: downward-api-demo
spec:
  containers:
  - name: downward-api-container
    image: nginx
    env:
    - name: POD_NAME
      valueFrom:
        fieldRef:
          fieldPath: metadata.name
    - name: POD_NAMESPACE
      valueFrom:
        fieldRef:
          fieldPath: metadata.namespace

 以下是一个示例,展示如何使用Downward API卷将Pod的标签和注解暴露给容器,在这个示例中,Pod的标签和注解将分别被写入到/etc/podinfo/labels和/etc/podinfo/annotations文件中。容器可以读取这些文件来获取相应的信息:

apiVersion: v1
kind: Pod
metadata:
  name: downward-api-volume-demo
  labels:
    app: demo
  annotations:
    description: "This is a demo pod"
spec:
  containers:
  - name: downward-api-container
    image: nginx
    volumeMounts:
    - name: podinfo
      mountPath: /etc/podinfo
  volumes:
  - name: podinfo
    downwardAPI:
      items:
      - path: "labels"
        fieldRef:
          fieldPath: metadata.labels
      - path: "annotations"
        fieldRef:
          fieldPath: metadata.annotations

Pod容器资源限制

通常我们会限制Pod可以使用的CPU和内存资源限制,如果我们没有指定资源限制,Kubernetes自动设置以下规则之一:
1.容器可无限制地使用CPU和内存。容器可以使用其所在节点所有的可用内资源。
2.如果运行的容器所在命名空间有默认的资源限制,那么该容器会被自动分配默认限制。
如下是一个简单示例,cpu-example命名空间中创建了一个具有一个容器的Pod,容器将会请求1个CPU,而且最多限制使用2个CPU:

apiVersion: v1
kind: Pod
metadata:
  name: cpu-demo
  namespace: cpu-example
spec:
  containers:
  - name: cpu-demo-ctr
    image: vish/stress
    resources:
      limits:
        cpu: "2"
      requests:
        cpu: "1"

  • 26
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

炸裂狸花猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值