Pod 是 kubernetes 中最小的资源管理组件,Pod 也是最小化运行容器化应用的资源对象。一个 Pod 代表着集群中运行的一个进程。kubernetes 中其他大多数组件都是围绕着 Pod 来进行支撑和扩展 Pod 功能的,例如用于管理 Pod 运行的 StatefulSet 和 Deployment 等控制器对象,用于暴露 Pod 应用的 Service 和 Ingress 对象,为 Pod 提供存储的 PersistentVolume 存储资源对象等
每个 Pod 中一个容器的模式是最常见的用法,在这种使用方式中,你可以把 Pod想象成是单个容器的封装,kubernetes 管理的是 Pod 而不是直接管理容器
一个 Pod中也可以同时封装几个需要紧密耦合互相协作的容器,它们之间共享资源。这些在同一个 Pod 中的容器可以互相协作成为一个 service单位,比如一个容器共享文件,另一个 sidecar 容器来更新这些文件。Pod 将这些容器的存储资源作为一个实体来管理
namespace | 功能说明 |
---|---|
Mount(mnt) | 提供磁盘挂载点和文件系统的隔离能力 |
IPC | 提供进程间通信的隔离能力 |
Network(net) | 提供网络资源隔离能力 |
UTS | 提供主机和域名信息隔离能力 |
PID | 提供进程隔离能力 |
User | 提供用户和用户组隔离能力 |
Pod 资源中针对各容器提供网络命令空间等共享机制的是底层基础容器 pause,基础容器(也可称为父容器)pause 就是为了管理 Pod 容器间的共享操作,这个父容器需要能够准确地知道如何去创建共享运行环境的容器,还能管理这些容器的生命周期。为了实现这个父容器的构想,kubernetes 中,用 pause 容器来作为一个 Pod 中所有容器的父容器。这个 pause 容器有两个核心的功能,一是它提供整个 Pod 的 Linux 命名空间的基础。二来启用 PID 命名空间,它在每个 Pod 中都作为 PID 为 1 进程(init 进程),并回收僵尸进程
每个 Pod 都会被分配一个唯一的 IP 地址。Pod 中的所有容器共享网络空间,包括 IP 地址和端口。Pod 内部的容器可以使用 localhost 互相通信。Pod 中的容器与外界通信时,必须分配共享网络资源(例如使用宿主机的端口映射)
可以 Pod 指定多个共享的 Volume。Pod 中的所有容器都可以访问共享的 Volume。Volume 也可以用来持久化 Pod 中的存储资源,以防容器重启后文件丢失
小结:每个 Pod 都有一个特殊的被称为 “基础容器” 的 Pause 容器。Pause 容器对应的镜像属于 Kubernetes 平台的一部分,除了 Pause 容器,每个 Pod 还包含一个或者多个紧密相关的用户应用容器
kubernetes 中的 pause 容器主要为每个容器提供以下功能:
1.在 pod 中担任 Linux 命名空间(如网络命令空间)共享的基础
2.启用 PID 命名空间,开启 init 进程
这种Pod本身是不能自我修复的,当Pod被创建后(不论是由你直接创建还是被其他Contro1ler),都会被Kuberentes调度到集群的Node上。直到Pod的进程终止、被删掉、因为缺少资源而被驱逐、或者Node故障之前这个Pod都会一直保持在那个Node上。Pod不会自愈。如果Pod运行的Node故障,或者是调度器本身故障,这个Pod就会被删除。同样的,如果Pod所在Node缺少资源或者Pod处于维护状态,Pod也会被驱逐
Kubernetes使用更高级的称为Controller的抽象层,来管理Pod实例。Controller可以创建和管
理多个Pod,提供副本管理、滚动升级和集群级别的自愈能力。例如,如果一个Node故障,Controller就能自动将该节点上的Pod调度到其他健康的Node上。虽然可以直接使用Pod,但是在Kubernetes中通常是使用Controller:来管理Pod的
维护整个 Pod 网络和存储空间
node 节点中操作
启动一个容器(pod) 时,k8s会自动启动一个基础容器
Init 容器必须在应用程序容器启动之前运行完成,而应用程序容器是并行运行的,所以 Init 容器能够提供了一种简单的阻塞或延迟应用容器的启动的方法
Init 容器与普通的容器非常像,除了以下两点:
如果 Pod 的 Init 容器失败,k8s 会不断地重启该 Pod,直到 Init 容器成功为止。然而,如果 Pod 对应的重启策略(restartPolicy)为 Never,它不会重新启动
因为 init 容器具有与应用容器分离的单独镜像,其启动相关代码具有如下优势:
应用容器会在 init 容器完成并退出后并行启动
以上小结:
1.pod 是k8s 最小的创建和运行单位
2.一个pod 包含 一个根容器、父容器、基础容器也就是paues容器
3.pod 里的容器共享通过 net uts ipc 命名空间进行共享
4.k8s 创建 pod 分为两种:
- 自主式/静态Pod: 不被空制器管理的Pod,一旦挂掉了,不会被重新拉起,而且副本数量也不会因为达不到期望值二创建新的Pod
- 控制器管理的Pod:被控制器管理的Pod,一旦pod挂掉了,会被重新拉起,而且副本数量会因为达不到期望值而创建新的Pod
5.pause容器:给Pod中的所有应用容器提供网络和存储的共享,作为PID=1的进程(init进程),管理整个Pod中容器组的生命周期
6.初始化容器(init 容器):阻塞或者延迟应用容器启动,可以为应用容器事先提供好运行环境和工具,多 init 容器时是串行启动,每个 init 容器必须在下一个 init 容器启动前成功完成启动和退出
7.应用容器(main 容器):在所有 init 容器成功启动和退出后应用容器才会启动,并行启动,提供应用程序业务
[root@master ~]# vim myapp.yaml
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
spec:
containers:
- name: myapp-container
image: busybox:1.28
command: ['sh','-c','echo The app is running! && sleep 3600']
initContainers:
- name: init-myservice
image: busybox:1.28
command: ['sh','-c','until nslookup myservice;do echo waiting for myservice; sleep2; done;']
- name: init-mydb
image: busybox:1.28
command: ['sh','-c','until nslookup mydb; do echo waiting for mydb; sleep 2; done;']
#这个例子是定义了一个具有 2 个 Init 容器的简单 Pod。 第一个等待 myservice 启动, 第二个等待 mydb 启动。一旦这两个 Init 容器都启动完成,Pod 将启动 spec 中的应用容器
kubectl apply -f myapp.yaml
kubectl get pod #查看是否启动时发现pod 一直处于init:0/2的状态
kubectl describe pod myapp-pod #查看创建pod的详细信息在最底下发现开启 init-myservice 容器后,创建步骤停滞,查看 init-myservice 日志进一步查明原因
kubectl logs myapp-pod -c init-myservice #发现问题是服务器未能找到 myservice 域名所以无法跳出循环,编写一个 myservice.yaml即可
vim myservice.yaml
apiVersion: v1
kind: Service
metadata:
name: myservice
spec:
ports:
- protocol: TCP
port: 80
targetPort: 1070
kubectl create -f myservice.yaml
kubectl get svc
kubectl get pod
#myservice 生成后发现myapp-pod 状态变为Init:1/2 并再次停滞,停滞原因和上面一样
kubectl describe pod myapp-pod
kubectl logs myapp-pod -c init-mydb
vim mydb.yaml
apiVersion: v1
kind: Service
metadata:
name: mydb
spec:
ports:
- protocol: TCP
port: 80
targetPort: 1080
kubectl create -f mydb.yaml
kubectl get pod
kubectl get svc
#在生成 mydb.yaml myservice.yaml 后 myapp.yaml 成功创建
上述操作小结:
- 创建过程中第一次停滞,是 init-myservice 容器启动后,未能发现 myservice 域名,无法得到解析,因此陷入循环
- 第二次停滞,是 init-mydb 容器启动后,未能发现 mydb 域名,无法得到解析,因此再次陷入循环中
- 在上述两个 init 容器成功并退出后,myapp-pod 才开始创建,否则 pod 无法创建
Pod的核心是运行容器,必须指定容器引擎,比如Docker,启动容器时需要拉取镜像,k8s的镜像拉取策略可以由用户指定:
IfNotPresent: 在镜像已经存在的情况下,kubelet将不再去拉取镜像,仅当本地缺失时才会从仓库中拉取,默认的镜像拉取策略
Alaways: 每次创建Pod都会重新拉取一次镜像
Never: Pod不会主动拉取这个镜像,仅使用本地镜像
注意:对于标签为latest的镜像文件,其默认的镜像获取策略即为Always;而对于其他标签的镜像,其默认策略则为IfNotPresent
不指定版本号创建pod
kubectl run nginx-test1 --image=nginx
查看默认拉取策略
kubectl edit pod nginx-test1
#不指定版本号,即使用缺省值latest最新版本,默认拉取策略为Always
查看创建过程
kubectl describe pod nginx-test1
#由于拉取策略为Always,因此不管本地有没有对应镜像,kubectl都会前往共有仓库下载最新版本应用
创建测试案例mypod.yaml
vim mypod.yaml
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: Always
command: [ "echo","SUCCESS" ]
生成mypod配置资源
kubectl create -f mypod.yaml
kubectl get pods
#该pod状态为CrashLoopBackOff,说明pod进入异常循环状态。原因是echo执行完进程终止,容器声明周期也就结束了。
查看创建过程
kubectl describe pod mypod
#最下面可以看到因为重启策略为AlWays,因此成功之后依然重复拉取镜像,可以发现 Pod 中的容器在生命周期结束后,由于 Pod 的重启策略为 Always,容器再次重启了,并且又重新开始拉取镜像
修改mypod.yaml
失败的状态的原因是因为命令启动冲突
删除 command: [ “echo”, “SUCCESS” ]
同时更改一下版本
image: nginx:1.14
vim mypod.yaml
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: nginx
image: nginx:1.14 #指定版本
imagePullPolicy: Always
#command: [ "echo","SUCCESS" ] #注释掉
删除原有资源
kubectl delete -f mypod.yaml
更新资源
kubectl apply -f mypod.yaml
#查看分配节点
kubectl get pods -o wide #查看分到的了那个节点上,例如分配到了node1上
在node1节点使用curl查看头部信息
curl -I [分到的了那个节点上ip地址]
修改mypod.yaml
vim mypod.yaml
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: nginx
image: nginx #修改镜像版本为最新版本
imagePullPolicy: IfNotPresent #设置镜像拉取策略为 IfNotPresent
command: [ "sh","-c","while true;do echo SUCCESS;done" ] #设置循环命令,使得pod不会自动关闭
生成新的 mypod.yaml 配置资源
#删除原有资源
kubectl delete -f mypod.yaml
#生成新的资源
kubectl apply -f mypod.yaml
查看pod状态
kubectl get pod -o wide
查看创建过程
kubectl describe pod mypod
查看pod日志
kubectl logs mypod #发现无限循环
当Pod中的容器退出时通过节点上的kubelet重启容器。适用于Pod中的所有容器
1.Always:当容器终止退出后,总是“重启”容器,默认策略
2.OnFailure:当容器异常退出(退出状态码非0)时,重启容器
3.Never:当容器终止退出,从不“重启”容器。
(注意:k8s中不支持重启Pod资源,只有删除重建,重建)
示例:
vim dome.yaml
kubectl apply -f dome.yaml
#查看Pod状态,等容器启动后30秒后执行exit退出进程进入error状态,就会重启次数加1
kubectl delete -f dome2.yaml
kubectl apply -f dome2.yaml
#再次 kubectl get pod 查看就会报error 因为设置了退出返回值为2
注:上面设置了OnFailure:当容器异常退出(退出状态码非0)时,重启容器,所有会报错然后一直重启
当容器终止退出,从不“重启”容器。
(注意:k8s中不支持重启Pod资源,只有删除重建,重建)
示例:
vim dome.yaml
[外链图片转存中…(img-4nG30XI3-1665189102115)]
kubectl apply -f dome.yaml
[外链图片转存中…(img-PcWoqgYM-1665189102115)]
#查看Pod状态,等容器启动后30秒后执行exit退出进程进入error状态,就会重启次数加1
kubectl delete -f dome2.yaml
kubectl apply -f dome2.yaml
[外链图片转存中…(img-mOb0WHjy-1665189102116)]
#再次 kubectl get pod 查看就会报error 因为设置了退出返回值为2
注:上面设置了OnFailure:当容器异常退出(退出状态码非0)时,重启容器,所有会报错然后一直重启