什么是 Pod

Pod 是一个或多个容器的组合。这些容器共享存储、网络和命名空间,以及运行规范。在 Pod 中,所有容器都被统一安排和调度。对于具体应用而言,Pod 是它们的逻辑主机,Pod 包含业务相关的多个应用容器。所以,Pod 是一组具有共享命名空间、IP地址和端口的容器的集合

从使用的角度来看

在实际的使用时,单个容器是无法单独来支撑我们的应用的,往往需要很多微服务才能组成一个系统,并且还会存在A服务依赖B服务,B服务需要和C服务共用某个目录。另外,在使用裸容器时,很难实现对容器内进行健康检査以及横向扩容等操作,而 Pod 可以轻松解决这些问题

从 Kubernetes 的角度来看

Docker 只是容器 Runtime(运行时)的一种们还有很多容器 Runtime,比如 Rkt、CRI-0等,而Kuberetes 作为目前最流行的容器编排工具,需要支持各个 Runtime 并且不依赖于底层 Runtime 的实现技术,于是就抽象出了 Pod 这个概念,用于管理多个紧密相连的符合 CRI标准的容器

Pod 可以简单的理解为一组、一个或多个容器,每个 Pod 还包含一个 Pause 容器,Pause 容器是 Pod的父容器主要负责僵尸进程的回收管理。同时,通过 Pause 容器可以使同一个 Pod 里面的不同容器共享存储、网络、PID、IPC(进程间通信)等,容器之间可以使用 Localhost:Por 的方式相互访问,可以使用 volume 实现数据共享。根据 Docker 的构造,Pod 可以被创建为一组具有共享命名空间、IP 地址和端口的容器

Pod 有两个必须知道的特点:

网络:每一个 Pod 都会被指派一个唯一的 !p 地址,在 Pod 中的每一个容器共享网络命名空间,包括Ip 地址和网络端口。在同一个 Pod 中的容器可以同 1ocalhost 进行互相通信。当 Pod 中的容器需要与Pod 外的实体进行通信时,则需要通过端口等共享的网络资源

存储:Pod 能够被指定共享存储卷的集合,在 Pod 中所有的容器能够访问共享存储卷,允许这些容器共享数据。存诸卷也允许在一个 Pod 持久化数据,以防止其中的容器需要被重启

Pod 的状态

kubectl 命令创建 pod
[root@k8s-master ~]# ku run nginx --image=nginx:1.7.9 --labels="app=nginx"
查看 pod
[root@k8s-master ~]# ku get pods -n default
[root@k8s-master ~]# ku get pods -A
查看 Pod 的更多信息
[root@k8s-master ~]# ku get pods nginx -o wide
查看 Pod 日志
[root@k8s-master ~]# curl 10.244.85.193
[root@k8s-master ~]# ku logs nginx
以 yaml 格式显示 Pod 详细信息
[root@k8s-master ~]# ku get pod nginx -o yaml
显示资源的详细描述信息
[root@k8s-master ~]# ku describe pod nginx
命令含义
kubectl get常用于査看同一资源类型的一个或多个资源对象,可以使用-0 参数自定义输出格式
kubectl describe侧重于描述指定资源的各方面的详细信息,不仅会返回节点信息,还会返回在其上运行的 Pod 的摘要、节点事
-c指定 Pod 中容器的名字
kubectl exec it nginx-- bash如果登录的时候不指定容器,就登录到Pod 中的第一个容器中
在 Pod 的容器中执行命令
[root@k8s-master ~]# ku exec nginx -c nginx -- date
登录到 Pod 中的容器中
[root@k8s-master ~]# ku exec -it nginx -c nginx -- bash
在线编辑运行中的资源对象
[root@k8s-master ~]# ku edit pod nginx

请添加图片描述

将 Pod 的端口映射到宿主机
[root@k8s-master ~]# ku port-forward --address 0.0.0.0 pod/nginx 8080:80
在宿主机和 Pod 的容器之间拷贝文件
[root@k8s-master ~]# echo  "this is my k8sAndnginx" > index.html
[root@k8s-master ~]# ku cp index.html nginx:/usr/share/nginx/html
Pod 的状态
[root@k8s-master ~]# ku get pods -n default
状态说明
Pending(挂起)Pod 已经被 Kubernetes 系统接收,但是仍有一个或多个容器未被创建,可以通过kubectl describe 查看处于Pending 状态的原因
Running(运行中)Pod 已经被绑定到一个节点上,并且所有的容器都已经被创建,而且至少有一个是运行的状态、正在启动或者重启,可以通过 kubectl logs 査看 Pod 的日志
Succeeded所有容器执行成功,并终止,并且不会再次重启,可以通过kubectl logs 査看 Pod 的日志
Failed(失败)所有容器都已终止,并且至少一个容器以失败的方式终止,也就是说这个容器要么以非零状态退出,要么被系统终止可以通过 logs 和 describe 査看 Pod 的日志和状态
Unknown(未知)通常是由于通信问题造成的无法获得 Pod 的状态
ImagePullBackOff ErrImagePull镜像拉取失败,一般是由于镜像不存在、网络不通或者需要登录认证引起的,可以使用 describe 命令查看具体的原因
CrashLoopBackOff容器启动失败,可以通过 logs 命令查看具体的原因,一般为启动命令不正确、健康检查不通过等原因
OOMKilled容器内存溢出,一般是容器的内存 Limit 设置的过小,或者程序本身有内存溢出,可以通过 logs 查看程序的启动日志
TerminatingPod 正在被删除,可以通过 describe 查看状态
SysctlForbidenPod 自定义了内核配置,但 kubectl 没有添加内核配置或配置的内核参数不支持,可以通过 describe 查看具体原因
Completed容器内部主进程退出,一般计划任务执行结束会显示该该状态,此时可以通过 logs 查看容器日志
ContainercreatingPod 正在创建,一般正在下载镜像,或者有配置不当的地方,可以通过 describe 查看具体原因
删除 Pod
[root@k8s-master ~]# ku delete pods nginx

请添加图片描述

Pod 探针

在生产环境中,进程正常启动并不代表应用能正常处理请求,所以合理的设计应用的健康检査尤其重要。在使用裸机或裸容器部署时,一般很难对应用做很完善的健康检査,而 Pod 提供的探针可以很方便的用来检测容器的应用是否正常

Pod 探针的实现方式

目前探针有3种检测方式,可以根据不同的场景选择合适的健康检查方式,分别是ExecAction、TCPSocketAction 和 HTTPGetAction。具体实现方式如表所示

实现方式说明
ExecAction在容器内执行一个指定的命令,如果命令返回值为0,则认为容器健康
TCPSocketAction通过 TCP 连接检查容器指定的端口,如果端口开放,则认为容器健康
HTTPGetAction对指定的URL进行Get请求,如果状态码在200-400之间,则认为容器健康

容器状态

状态说明
Success(成功)容器检查成功
Failure(失败)容器检查失败
Unknown(未知)诊断失败,因此不采取任何措施

Pod 探针类型

Pod 探针有三类,分别是:livenessProbe(存活探针)、readinessProbe(就绪探针)、startupProbe(启动探针)

ivenessProbe(存活探针)

它被用来知道一个容器是否在正常运行。如果容器未能通过存活探针的检查,则系统会认为该容器已经进入了一个必须被重启的状态,从而自动重启这个容器。这种机制可以确保容器在出现问题后能够自动恢复到可用状态

存活探针支持以下几种类型:

类型说明
HTTP GET请求通过发送 HTTP 请求到容器内的某个 URL 来检测容器是否处于健康状态
Exec 执行命令在容器内执行一个自定义命令或可执行文件,并根据其退出码判断容器是否健康
Socket尝试打开一个 TCP socket 连接到容器上的指定端口,如果连接成功则认为容器是健TCP康的
readinessProbe(就绪探针)

判断容器是否能够进入 ready 状态,用于确定 Pod 中的容器是否已准备好接收流量。与1ivenessProbe 不同,readinessProbe 主要关注的是容器是否已经准备好为服务提供者处理请求。如果容器没有通过就绪探针的检査,Kubernetes 将不会把任何新的网络流量路由到这个容器上

当一个容器报告自己尚未准备好时,Kubernetes可能会采取以下行动:

  • 服务(service)不会将流量路由到未准备好的 Pod
  • 如果 Pod 是副本集(Replicaset)、部署(Deployment)、状态集(statefulset)等的一部分控制器会认为这个实例不可用
  • 对于使用 Pod 的滚动更新策略的情况,就绪探针可以帮助确保新版本的 Pod 在旧版本被终止之前就已经准备好了

就像 livenessProbe 一样,readinessProbe 也支持多种类型的探测方法:

类型说明
HTTP GET 请求发送 HTTP 请求到容器内的某个 URL
Exec执行命令在容器内执行一个自定义命令或可执行文件
TCP Socket尝试建立一个到容器上的指定端口的 TCP 连接
startupProbe(启动探针)

判断容器内的应用是否启动成功,在 success 状态前,其它探针都处于无效状态。它专门用于检测容器是否完成了初始化并进入了预期的运行状态。与 livenessProbe(存活探针)和 readinessProbe(就绪探针)不同,startupProbe专注于容器启动阶段,并且仅在容器启动过程中使用

startupProbe 的主要作用是在容器启动期间持续检査容器是否已经完成启动。一旦容器通过了startupProbe 的检査,Kubernetes 就会认为容器已经成功启动,并停止对该容器的启动探针检查。如果容器始终无法通过启动探针的检査,那么 Kubernetes 将会根据配置重试一定的次数,超过重试次数后可能会采取进一步的措施,如重启容器

Pod 镜像拉取策略和重启策略

镜像拉取策略

在发布应用或者更改控制器配置时,会触发 Pod 的滚动更新,此时针对容器的镜像有不同的拉取方式。如表所示

操作方式说明
Always总是拉取,无论镜像是否存在,总是拉取
Never无论是否存在都不会拉取
IfNotPressent镜像不存在时拉取镜像,是 k8s 默认的策略但是如果 tag为latest,则总是拉取
[root@k8s-master ~]# ku run nginx --image=nginx:1.7.9 --labels="app=nginx" --image-pull-policy=Never
Pod 重启策略

在 Kubernetes 中,Pod 的重启策略(Restart Policy)定义了当容器退出或失败时,kubelet 如何处理容器。重启策略是 Pod 级别的配置,适用于Pod 中的所有容器

在 Always 策略中,只要容器退出(无论退出码是什么),kubelet 都会自动重启容器。适用于需要持续运行的服务(如 web 服务器、数据库等)

在 onFailure 策略中,只有当容器以非零退出码退出时,kubelet 才会重启容器,如果容器正常退出(退出码为 ),则不会重启。适用于任务型 Pod(如批处理任务),任务完成后不需要重启

在 Never 策略中,无论容器以何种方式退出,kubelet 都不会重启容器。适用于一次性任务,任务完成后不需要重启

各个策略的简要说明如表:

操作方式说明
Always容器退出即重启,适用于长期运行的服务
OnFailure容器失败时重启,适用于任务型工作负载
Never容器退出后不重启,适用于一次性任务
[root@k8s-master ~]# ku delete pod nginx
[root@k8s-master ~]# ku run nginx --image=nginx:1.7.9 --labels="app=nginx" --restart=OnFailure

创建一个简单的 Pod

编写一个简单的 Pod

[root@k8s-master ~]# vim aaa.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    name: nginx
spec:
  containers:
  - name: nginx01
    image: nginx:1.7.9
    ports:
    - containerPort: 80
  - name: nginx02
    image: nginx:1.7.9
    ports:
    - containerPort: 8080
[root@k8s-master ~]# ku delete pods nginx
[root@k8s-master ~]# ku get pods
No resources found in default namespace.
[root@k8s-master ~]# ku create -f aaa.yaml 
pod/nginx created
[root@k8s-master ~]# ku get pods
NAME    READY   STATUS    RESTARTS   AGE
nginx   2/2     Running   0          2s

请添加图片描述

编写 Pod 配置文件 frontend-localredis-pod.yaml

[root@k8s-master ~]# vim frontend-localredis-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: redis-php
  labels:
    name: redis-php
spec:
  containers:
  - name: frontend
    image: kubeguide/guestbook-php-frontend:localredis
    imagePullPolicy: IfNotPresent
    livenessProbe:
      tcpSocket:
        port: 80
      initialDelaySeconds: 1
      periodSeconds: 3
      timeoutSeconds: 1
    ports:
    - containerPort: 80

  - name: redis
    image: kubeguide/redis-master
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 6379
  restartPolicy: OnFailure
[root@k8s-master ~]# ku create -f frontend-localredis-pod.yaml
[root@k8s-master ~]# ku get pods
NAME        READY   STATUS             RESTARTS       AGE
nginx       1/2     CrashLoopBackOff   10 (69s ago)   27m
redis-php   2/2     Running            0              7s

请添加图片描述

命令含义
apiVersion:v1必选,版本号
kind: Pod必选,资源类型
metadata必选,元数据
name:redis-php必选,Pod 名称
labels自定义的 pod 标签列表
name:redis-php标签值
spec必选,Pod 中容器的详细信息
containers必选,Pod 中的容器列表
name:frontend必选,自定义的容器名称
image:kubeguide/guestbook-php-frontend:localredis必选,容器的镜像名称
imagePullPolicy:IfNotPresent镜像拉取策略
livenessProbe设置存活探针
tcpsocket测试某端口是否可以连接
port:80指定要测试的端口
initialDelaySeconds:1指定 kubelet 在执行第一次探测前应该等待1秒,即第一次探测是#在容器启动后的第2秒才开始执行。默认是8秒,最小值是0
periodseconds:3指定了 kubelet 应该每 3 秒执行一次存活探测。默认是 10 秒。最小值是 1
timeoutseconds:1当探测失败时,Kubernetes 在超时之前等待的时间。存活探测情况下的放弃就意味着重新启动容器。就绪探测情况下的放弃Pod 会被打上未就绪的标签。默认值是 3。最小值是 1
ports需要暴露的端口号列表
-containerPort:80容器需要监听的端口号
name:redis另一个容器的名字
image: kubeguide/redis-master另一个容器的镜像
ports需要暴露的另一个容器的端口列表
- containerPort:6379容器需要监听的端口号
estartPolicy: onFailure重启策略
Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐