赞
踩
参考链接: Pod | Kubernetes
Pod(豌豆荚) 是Kubernetes集群管理(创建、部署)与调度的最小计算单元,表示处于运行状态的一组容器。
Pod不是进程,而是容器运行的环境。
一个Pod可以封装一个容器或多个容器(主容器或sidecar边车容器)
一个pod内的多个容器之间共享部分命名空间,例如:Net Namespace,UTS Namespace,IPC Namespace及存储资源
用户pod默认会被调度运行在node节点之上(不运行在master节点上,但也有例外情况)
pod内的IP不是固定的,集群外不能直接访问pod
静态Pod 也称之为“无控制器管理的自主式pod”,直接由特定节点上的 kubelet
守护进程管理, 不需要API 服务器看到它们,尽管大多数 Pod 都是通过控制面(例如,Deployment) 来管理的,对于静态 Pod 而言,kubelet
直接监控每个 Pod,并在其失效时重启之。
控制器管理的pod 控制器可以控制pod的副本数,扩容与裁剪,版本更新与回滚等
pod是一种计算资源,可以通过kubectl get pod
来查看
[root@worker01 ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-test-7d95fb4447-6nfs2 1/1 Running 1 40h
nginx-test-7d95fb4447-mtkg8 1/1 Running 2 2d16h# pod或pods都可以,不指定namespace,默认是名为default的namespace
[root@k8s-master1 ~]# kubectl get pod -n kube-system
# yaml格式的pod定义文件完整内容:
apiVersion: v1 #必选,api版本号,例如v1
kind: Pod #必选,Pod
metadata: #必选,元数据
name: string #必选,Pod名称
namespace: string #Pod所属的命名空间,默认在default的namespace
labels: # 自定义标签
name: string #自定义标签名字
annotations: #自定义注释列表
name: string
spec: #必选,Pod中容器的详细定义(期望)
containers: #必选,Pod中容器列表
- name: string #必选,容器名称
image: string #必选,容器的镜像名称
imagePullPolicy: [Always | Never | IfNotPresent] #获取镜像的策略 Alawys表示下载镜像 IfnotPresent表示优先使用本地镜像,否则下载镜像,Nerver表示仅使用本地镜像
command: [string] #容器的启动命令列表,如不指定,使用打包时使用的启动命令
args: [string] #容器的启动命令参数列表
workingDir: string #容器的工作目录
volumeMounts: #挂载到容器内部的存储卷配置
- name: string #引用pod定义的共享存储卷的名称,需用volumes[]部分定义的的卷名
mountPath: string #存储卷在容器内mount的绝对路径,应少于512字符
readOnly: boolean #是否为只读模式
ports: #需要暴露的端口库号列表
- name: string #端口号名称
containerPort: int #容器需要监听的端口号
hostPort: int #容器所在主机需要监听的端口号,默认与Container相同
protocol: string #端口协议,支持TCP和UDP,默认TCP
env: #容器运行前需设置的环境变量列表
- name: string #环境变量名称
value: string #环境变量的值
resources: #资源限制和请求的设置
limits: #资源限制的设置
cpu: string #Cpu的限制,单位为core数,将用于docker run --cpu-shares参数
memory: string #内存限制,单位可以为Mib/Gib,将用于docker run --memory参数
requests: #资源请求的设置
cpu: string #Cpu请求,容器启动的初始可用数量
memory: string #内存清求,容器启动的初始可用数量
livenessProbe: #对Pod内个容器健康检查的设置,当探测无响应几次后将自动重启该容器,检查方法有exec、httpGet和tcpSocket,对一个容器只需设置其中一种方法即可
exec: #对Pod容器内检查方式设置为exec方式
command: [string] #exec方式需要制定的命令或脚本
httpGet: #对Pod内个容器健康检查方法设置为HttpGet,需要制定Path、port
path: string
port: number
host: string
scheme: string
HttpHeaders:
- name: string
value: string
tcpSocket: #对Pod内个容器健康检查方式设置为tcpSocket方式
port: number
initialDelaySeconds: 0 #容器启动完成后首次探测的时间,单位为秒
timeoutSeconds: 0 #对容器健康检查探测等待响应的超时时间,单位秒,默认1秒
periodSeconds: 0 #对容器监控检查的定期探测时间设置,单位秒,默认10秒一次
successThreshold: 0
failureThreshold: 0
securityContext:
privileged:false
restartPolicy: [Always | Never | OnFailure] # Pod的重启策略,Always表示一旦不管以何种方式终止运行,kubelet都将重启,OnFailure表示只有Pod以非0退出码退出才重启,Nerver表示不再重启该Pod
nodeSelector: obeject # 设置NodeSelector表示将该Pod调度到包含这个label的node上,以key:value的格式指定
imagePullSecrets: #Pull镜像时使用的secret名称,以key:secretkey格式指定
- name: string
hostNetwork: false #是否使用主机网络模式,默认为false,如果设置为true,表示使用宿主机网络
volumes: #在该pod上定义共享存储卷列表
- name: string #共享存储卷名称 (volumes类型有很多种)
emptyDir: {} #类型为emtyDir的存储卷,与Pod同生命周期的一个临时目录。为空值
hostPath: string #类型为hostPath的存储卷,表示挂载Pod所在宿主机的目录
path: string #Pod所在宿主机的目录,将被用于同期中mount的目录
secret: #类型为secret的存储卷,挂载集群与定义的secret对象到容器内部
scretname: string
items:
- key: string
path: string
configMap: #类型为configMap的存储卷,挂载预定义的configMap对象到容器内部
name: string
items:
- key: string
path: string
YAML格式查找帮助方法回顾
kubectl explain namespace
kubectl explain pod
kubectl explain pod.spec
kubectl explain pod.spec.containers
k8s之前版本中, kubectl run命令用于创建deployment控制器
在v1.18版本中, kubectl run命令改为创建pod
[root@worker01 ~]# kubectl run pod-nginx --image=nginx:last
pod/pod-nginx created
[root@worker01 ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-test-7d95fb4447-6nfs2 1/1 Running 1 40h
nginx-test-7d95fb4447-mtkg8 1/1 Running 2 2d16h
pod-nginx 0/1 ContainerCreating 0 12s
vim pod1.yml
# polinux/stress这个镜像用于压力测试,在启动容器时传命令与参数就是相当于分配容器运行时需要的压力
apiVersion: v1
kind: Pod
metadata:
name: pod-stress
spec:
containers:
- name: c1
image: polinux/stress
command: ["stress"]
args: ["--vm","1","--vm-bytes","150M","--vm-hang","1"]
[root@worker01 test]# kubectl apply -f pod1.yml
pod/pod-stress created
[root@master01 test]# kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-test-7d95fb4447-6nfs2 1/1 Running 1 40h
nginx-test-7d95fb4447-mtkg8 1/1 Running 2 2d17h
pod-nginx 1/1 Running 0 8m32s
pod-stress 1/1 Running 0 3m8s
[root@master01 test]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-test-7d95fb4447-6nfs2 1/1 Running 1 40h 10.244.30.82 worker02 <none> <none>
nginx-test-7d95fb4447-mtkg8 1/1 Running 2 2d17h 10.244.5.8 worker01 <none> <none>
pod-nginx 1/1 Running 0 11m 10.244.30.85 worker02 <none> <none>
pod-stress 1/1 Running 0 5m52s 10.244.5.10 worker01 <none> <none>
[root@master01 test]# kubectl describe pod pod-stress
Name: pod-stress
Namespace: default
Priority: 0
Node: worker01/192.168.80.201
Start Time: Sat, 06 Jan 2024 14:49:38 +0800
Labels: <none>
Annotations: cni.projectcalico.org/containerID: b1bd98d790cc5a5049f481c41e6a1bf70432027ae64ba7f6b81411132c830fd2
cni.projectcalico.org/podIP: 10.244.5.10/32
cni.projectcalico.org/podIPs: 10.244.5.10/32
Status: Running
IP: 10.244.5.10
IPs:
IP: 10.244.5.10
Containers:
c1:
Container ID: docker://5ade06f1171e9de7b1eb7c7f6c58f6508b38adf1d989b7f48a149a1066324cdf
Image: polinux/stress
Image ID: docker-pullable://polinux/stress@sha256:b6144f84f9c15dac80deb48d3a646b55c7043ab1d83ea0a697c09097aaad21aa
Port: <none>
Host Port: <none>
Command:
stress
Args:
--vm
1
--vm-bytes
150M
--vm-hang
1
State: Running
Started: Sat, 06 Jan 2024 14:49:46 +0800
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-4fnkk (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
kube-api-access-4fnkk:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 3607
ConfigMapName: kube-root-ca.crt
ConfigMapOptional: <nil>
DownwardAPI: true
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 6m26s default-scheduler Successfully assigned default/pod-stress to worker01
Normal Pulling 6m26s kubelet Pulling image "polinux/stress"
Normal Pulled 6m19s kubelet Successfully pulled image "polinux/stress" in 7.064047303s
Normal Created 6m19s kubelet Created container c1
Normal Started 6m19s kubelet Started container c1
[root@master01 test]# kubectl delete pod pod-stress
pod "pod-stress" deleted
或者
[root@master01 test]# kubectl delete -f pod1.yml
方法1: 后接多个pod名
[root@master01 test]# kubectl delete pod pod pod1 pod2
pod "pod" deleted
pod "pod1" deleted
pod "pod2" deleted
方法2: 通过awk截取要删除的pod名称,然后管道给xargs
[root@master01 test]# kubectl get pods -n test|awk 'NR>1 {print $1}'|xargs kubectl delete pod -n test
pod "pod1" deleted
pod "pod2" deleted
方法3: 如果要删除的pod都在同一个非default的命名空间,则可直接删除命名空间
kubectl delete ns xxxx
由imagePullPolicy参数控制
Always : 不管本地有没有镜像,都要从仓库中下载镜像
Never : 从来不从仓库下载镜像, 只用本地镜像,本地没有就算了
IfNotPresent: 如果本地存在就直接使用, 不存在才从仓库下载
默认的策略是:
当镜像标签版本是latest,默认策略就是Always
如果指定特定版本默认拉取策略就是IfNotPresent。
创建新的Pod
[root@master01 test]# kubectl apply -f pod1.yml
pod/pod-stress created
使用 kubectl describe pod pod-stress 观察,pod创建过程
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 53s default-scheduler Successfully assigned default/pod-stress to worker02
Normal Pulling 53s kubelet Pulling image "polinux/stress" #拉取镜像
Normal Pulled 50s kubelet Successfully pulled image "polinux/stress" in 3.227821228s #镜像拉取成功
Normal Created 49s kubelet Created container c1 #创建
Normal Started 49s kubelet Started container c1 #开始船舰
说明: 可以看到第二行信息还是
pulling image
下载镜像
apiVersion: v1
kind: Pod
metadata:
name: pod-stress
spec:
containers:
- name: c1
image: polinux/stress
command: ["stress"]
args: ["--vm","1","--vm-bytes","150M","--vm-hang","1"]
imagePullPolicy: IfNotPresent #增加拉取策略
删除之前的,重新创建
[root@master01 test]# kubectl delete -f pod1.yml
pod "pod-stress" deleted
[root@master01 test]# kubectl apply -f pod2.yml
pod/pod-stress created
使用 kubectl describe pod pod-stress,观察过程
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 34s default-scheduler Successfully assigned default/pod-stress to worker02
Normal Pulled 33s kubelet Container image "polinux/stress" already present on machine #镜像已经存在就不会去拉取了
Normal Created 33s kubelet Created container c1
Normal Started 33s kubelet Started container c1说明: 第二行信息是说镜像已经存在,直接使用了
为pod设置label,用于控制器通过label与pod关联
语法与前面学的node标签几乎一致
查看pod的标签
[root@k8s-master1 ~]# kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
pod-stress 1/1 Running 0 7m25s <none>
打标签,再查看
[root@k8s-master1 ~]# kubectl label pod pod-stress region=huanai zone=A env=test bussiness=game
pod/pod-stress labeled[root@k8s-master1 ~]# kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
pod-stress 1/1 Running 0 8m54s bussiness=game,env=test,region=huanai,zone=A
通过等值关系标签查询
[root@k8s-master1 ~]# kubectl get pods -l zone=A NAME READY STATUS RESTARTS AGE pod-stress 1/1 Running 0 9m22s
通过集合关系标签查询
[root@k8s-master1 ~]# kubectl get pods -l "zone in (A,B,C)" NAME READY STATUS RESTARTS AGE pod-stress 1/1 Running 0 9m55s
删除标签后再验证
[root@k8s-master1 ~]# kubectl label pod pod-stress region- zone- env- bussiness- pod/pod-stress labeled [root@k8s-master1 ~]# kubectl get pods --show-labels NAME READY STATUS RESTARTS AGE LABELS pod-stress 1/1 Running 0 16m <none>
小结:
pod的label与node的label操作方式几乎相同
node的label用于pod调度到指定label的node节点
pod的label用于controller关联控制的pod
创建两个Pod 文件
apiVersion: v1
kind: Namespace
metadata:
name: test-ns
---
---
apiVersion: v1
kind: Pod
metadata:
name: pod-stress2
namespace: test-ns
spec:
containers:
- name: c1
image: polinux/stress
imagePullPolicy: IfNotPresent
resources:
limits:
memory: "200Mi"
requests:
memory: "100Mi"
command: ["stress"] # 启动容器时执行的命令
args: ["--vm", "1", "--vm-bytes", "150M", "--vm-hang", "1"] # 产生1个进程分配150M内存1秒后释放
[root@master01 test]# kubectl apply -f pod3.yml
namespace/test-ns unchanged
pod/pod-stress2 created
[root@master01 test]# kubectl apply -f pod4.yml
namespace/test-ns unchanged
pod/pod-stress3 created
[root@master01 test]#
观察创建后的pod
[root@master01 test]# kubectl get pods -n test-ns
NAME READY STATUS RESTARTS AGE
pod-stress2 1/1 Running 0 2m14s
pod-stress3 0/1 OOMKilled 3 49s
发现 pod-stress3 的状态 为OOMKilled,意思是OOM了,因为程序申请的内存大于POD的上线,所以需要被kill
说明: 一旦pod中的容器挂了,容器会有重启策略, 如下:
Always:表示容器挂了总是重启,这是默认策略
OnFailures:表容器状态为错误时才重启,也就是容器正常终止时才重启
Never:表示容器挂了不予重启
对于Always这种策略,容器只要挂了,就会立即重启,这样是很耗费资源的。所以Always重启策略是这么做的:第一次容器挂了立即重启,如果再挂了就要延时10s重启,第三次挂了就等20s重启...... 依次类推
测试完后删除
kubectl delete ns test-ns
1. 创建yaml文件
vim pod-m.yml
apiVersion: v1
kind: Pod
metadata:
name: pod-stress4
spec:
containers:
- name: c1
image: polinux/stress
imagePullPolicy: IfNotPresent
resources:
limits:
memory: "200Mi"
requests:
memory: "100Mi"
command: ["stress"]
args: ["--vm", "1", "--vm-bytes", "150M", "--vm-hang", "1"]
- name: c2
image: polinux/stress
imagePullPolicy: IfNotPresent
resources:
limits:
memory: "200Mi"
requests:
memory: "100Mi"
command: ["stress"]
args: ["--vm", "1", "--vm-bytes", "150M", "--vm-hang", "1"]
创建pod
[root@master01 test]# kubectl apply -f pod-m.yml
pod/pod-stress4 created
查看pod在哪个节点
[root@master01 test]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-test-7d95fb4447-6nfs2 1/1 Running 1 41h 10.244.30.82 worker02 <none> <none>
nginx-test-7d95fb4447-mtkg8 1/1 Running 2 2d17h 10.244.5.8 worker01 <none> <none>
pod-stress 1/1 Running 0 22m 10.244.30.88 worker02 <none> <none>
pod-stress4 2/2 Running 0 39s 10.244.5.20 worker01 <none> <none>
可以看到有2个容器,运行在worker01 节点
在worker01上验证,确实产生了2个容器
您在 /var/spool/mail/root 中有新邮件
[root@worker01 kubenets]# docker ps -a |grep stress
cf2d4b50d59f df58d15b053d "stress --vm 1 --vm-…" 2 minutes ago Up 2 minutes k8s_c2_pod-stress4_default_83c5eb27-feb6-4af8-8c53-ba12ddeb3a17_0
91b843ad656d df58d15b053d "stress --vm 1 --vm-…" 2 minutes ago Up 2 minutes k8s_c1_pod-stress4_default_83c5eb27-feb6-4af8-8c53-ba12ddeb3a17_0
77f469d5e71b registry.aliyuncs.com/google_containers/pause:3.4.1 "/pause" 2 minutes ago Up 2 minutes k8s_POD_pod-stress4_default_83c5eb27-feb6-4af8-8c53-ba12ddeb3a17_0
或
[root@k8s-master1 ~]# crictl ps
CONTAINER IMAGE CREATED STATE NAME ATTEMPT POD ID
08cd23ac9b416 df58d15b053d1 2 hours ago Running c2 0 2dd084491f019
65f0ecba8dec3 df58d15b053d1 2 hours ago Running c1 0 2dd084491f019
kubectl exec pod名称 -c 指定容器 -- 命令
可以使用 kubectl exec -h 查看帮助
kubectl exec pod名称 -c 指定容器 -- 命令
注意:
-c 容器名为可选项,如果是1个pod中1个容器,则不用指定;
如果是1个pod中多个容器,不指定默认为第1个。
[root@master01 test]# kubectl exec pod-stress -- date
Sat Jan 6 07:49:04 UTC 2024
一个pod下如果有多个容器,不指定容器 ,默认使用第一个个容器
[root@master01 test]# kubectl exec pod-stress4 -- date
Defaulted container "c1" out of: c1, c2
Sat Jan 6 07:51:12 UTC 2024
[root@master01 test]#
和docker exec几乎一样
kubectl exec -it pod-stress -- /bin/bash
kubectl exec -it pod-stress -- /bin/sh
Step1
通过kubectl命令应用资源清单文件(yaml格式)向api server 发起一个create pod 请求Step2
api server接收到pod创建请求后,生成一个包含创建信息资源清单文件Step3
apiserver 将资源清单文件中信息写入etcd数据库Step4
Scheduler启动后会一直watch API Server,获取 podSpec.NodeName为空的Pod,即判断pod.spec.Node == null? 若为null,表示这个Pod请求是新的,需要创建,因此先进行调度计算(共计2步:1、过滤不满足条件的,2、选择优先级高的),找到合适的node,然后将信息在etcd数据库中更新分配结果:pod.spec.Node = nodeA (设置一个具体的节点)Step5
kubelet 通过watch etcd数据库(即不停地看etcd中的记录),发现有新的Node出现,如果这条记录中的Node与所在节点编号相同,即这个Pod由scheduler分配给自己,则调用node中的Container Runtime,进而创建container,并将创建后的结果返回到给api server用于更新etcd数据库中数据状态。
我们为了实现容器主机资源平衡使用, 可以使用约束把pod调度到指定的node节点
nodeName 用于将pod调度到指定的node名称上
nodeSelector 用于将pod调度到匹配Label的node上
编写YAML文件
[root@master01 test]# vim pod-nodename.yml
apiVersion: v1
kind: Pod
metadata:
name: pod-nodename
spec:
nodeName: worker01
containers:
- name: nginx
image: nginx:1.15-alpine
应用YAML文件创建POD
[root@master01 test]# kubectl apply -f pod-nodename.yml
验证
[root@master01 test]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-test-7d95fb4447-6nfs2 1/1 Running 1 43h 10.244.30.82 worker02 <none> <none>
nginx-test-7d95fb4447-mtkg8 1/1 Running 2 2d19h 10.244.5.8 worker01 <none> <none>
pod-nodename 1/1 Running 0 53s 10.244.5.22 worker01 <none> <none>
发现 pod-nodename 被分配到了 worker01 节点上
倒数第3行没有使用scheduler,而是直接给运行了,说明nodeName约束生效
[root@master01 test]# kubectl describe pod pod-nodename |tail -6
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Pulled 3m45s kubelet Container image "nginx:1.15-alpine" already present on machine
Normal Created 3m45s kubelet Created container nginx
Normal Started 3m44s kubelet Started container nginx
1. 创建YAML文件
vim pod-nodeselector.yml
apiVersion: v1
kind: Pod
metadata:
name: pod-nodeselect
spec:
nodeSelector: # nodeSelector节点选择器
bussiness: game # 指定调度到标签为bussiness=game的节点
containers:
- name: nginx
image: nginx:1.15-alpine
2. 给 worker02 节点打标签
[root@master01 test]# kubectl label node worker02 bussines=game
node/worker02 labeled
[root@master01 test]# kubectl get nodes --show-labels
NAME STATUS ROLES AGE VERSION LABELS
master01 Ready control-plane,master 2d21h v1.21.0 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=master01,kubernetes.io/os=linux,node-role.kubernetes.io/control-plane=,node-role.kubernetes.io/master=,node.kubernetes.io/exclude-from-external-load-balancers=
worker01 Ready <none> 2d20h v1.21.0 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=worker01,kubernetes.io/os=linux
worker02 Ready <none> 2d20h v1.21.0 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,bussines=game,kubernetes.io/arch=amd64,kubernetes.io/hostname=worker02,kubernetes.io/os=linux
3. 应用YAML文件创建Pod
[root@master01 test]# kubectl apply -f pod-nodeselector.yml
pod/pod-nodeselect created
4. 验证
[root@master01 test]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-test-7d95fb4447-6nfs2 1/1 Running 1 43h 10.244.30.82 worker02 <none> <none>
nginx-test-7d95fb4447-mtkg8 1/1 Running 2 2d19h 10.244.5.8 worker01 <none> <none>
pod-nodename 1/1 Running 0 13m 10.244.5.22 worker01 <none> <none>
pod-nodeselect 1/1 Running 0 4m22s 10.244.30.89 worker02 <none> <none>
仍然经过了scheduler,但确实分配到了worker02 上
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 4m44s default-scheduler 0/3 nodes are available: 1 node(s) had taint {node.kubernetes.io/disk-pressure: }, that the pod didn't tolerate, 2 node(s) didn't match Pod's node affinity/selector.
Warning FailedScheduling 4m42s default-scheduler 0/3 nodes are available: 1 node(s) had taint {node.kubernetes.io/disk-pressure: }, that the pod didn't tolerate, 2 node(s) didn't match Pod's node affinity/selector.
Normal Scheduled 91s default-scheduler Successfully assigned default/pod-nodeselect to worker02
Normal Pulled 90s kubelet Container image "nginx:1.15-alpine" already present on machine
Normal Created 90s kubelet Created container nginx
Normal Started 90s kubelet Started container nginx
有兴趣可以再删除后再创建,重复几次验证
有些pod(比如运行httpd服务),正常情况下会一直运行中,但如果手动删除它,此pod会终止
也有些pod(比如执行计算任务),任务计算完后就会自动终止
上面两种场景中,pod从创建到终止的过程就是pod的生命周期。
pod中的容器在创建前,有初始化容器(init container)来进行初始化环境
初化完后,主容器(main container)开始启动
主容器启动后,有一个post start的操作(启动后的触发型操作,或者叫启动后钩子)
post start后,就开始做健康检查
第一个健康检查叫存活状态检查(liveness probe ),用来检查主容器存活状态的
第二个健康检查叫准备就绪检查(readiness probe),用来检查主容器是否启动就
可以在容器终止前设置pre stop操作(终止前的触发型操作,或者叫终止前钩子)
当出现特殊情况不能正常销毁pod时,大概等待30秒会强制终止
终止容器后还可能会重启容器(视容器重启策略而定)。
restartPolicy
Always:表示容器挂了总是重启,这是默认策略
OnFailures:表示容器状态为错误时才重启,也就是容器正常终止时不重启
Never:表示容器挂了不予重启
对于Always这种策略,容器只要挂了,就会立即重启,这样是很耗费资源的。所以Always重启策略是这么做的:第一次容器挂了立即重启,如果再挂了就要延时10s重启,第三次挂了就等20s重启...... 依次类推
当Pod启动时,容器可能会因为某种错误(服务未启动或端口不正确)而无法访问等。
kubelet拥有两个检测器,它们分别对应不同的触发器(根据触发器的结构执行进一步的动作)
方式 | 说明 |
---|---|
Liveness Probe(存活状态探测) | 指示容器是否正在运行。如果存活态探测失败,则 kubelet 会杀死容器, 并且容器将根据其重启策略决定未来。如果容器不提供存活探针, 则默认状态为 Success 。 |
readiness Probe(就绪型探测) | 指示容器是否准备好为请求提供服务。如果就绪态探测失败, 端点控制器将从与 Pod 匹配的所有服务的端点列表中删除该 Pod 的 IP 地址。 初始延迟之前的就绪态的状态值默认为 Failure 。 如果容器不提供就绪态探针,则默认状态为 Success 。注:检查后不健康,将容器设置为Notready;如果使用service来访问,流量不会转发给此种状态的pod |
startup Probe | 指示容器中的应用是否已经启动。如果提供了启动探针,则所有其他探针都会被 禁用,直到此探针成功为止。如果启动探测失败,kubelet 将杀死容器,而容器依其 重启策略进行重启。 如果容器没有提供启动探测,则默认状态为 Success 。 |
方式 | 说明 |
---|---|
Exec | 执行命令 |
HTTPGet | http请求某一个URL路径 |
TCP | tcp连接某一个端口 |
gRPC | 使用 gRPC 执行一个远程过程调用。 目标应该实现 gRPC健康检查。 如果响应的状态是 "SERVING",则认为诊断成功。 gRPC 探针是一个 alpha 特性,只有在你启用了 "GRPCContainerProbe" 特性门控时才能使用。 |
1. 准备YAML文件
vim pod-liveness-exec.yml
apiVersion: v1
kind: Pod
metadata:
name: liveness-exce
namespace: default
spec:
containers:
- name: liveness
image: busybox
imagePullPolicy: IfNotPresent
args:
- /bin/sh
- -c
- touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy;sleep 600
livenessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 5 # pod启动延迟5秒后探测
periodSeconds: 5 # 每5秒探测1次
2. 应用配置文件,创建POD
[root@master01 test]# kubectl apply -f pod-liveness-exec.yml
pod/liveness-exce created
3. 观察变化
[root@master01 test]# kubectl get pods -w
NAME READY STATUS RESTARTS AGE
liveness-exce 1/1 Running 0 41s
nginx-test-7d95fb4447-6nfs2 1/1 Running 1 44h
nginx-test-7d95fb4447-mtkg8 1/1 Running 2 2d21h
liveness-exce 1/1 Running 1 76s
liveness-exce 1/1 Running 2 2m31s
liveness-exec 开始为正常,后来就重启
看到重启3次,慢慢地重启间隔时间会越来越长
[root@master01 test]# kubectl describe pod liveness-exce
....
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 98s default-scheduler Successfully assigned default/liveness-exce to worker02
Normal Pulling 97s kubelet Pulling image "busybox"
Normal Pulled 94s kubelet Successfully pulled image "busybox" in 2.862041971s
Warning Unhealthy 53s (x3 over 63s) kubelet Liveness probe failed: cat: can't open '/tmp/healthy': No such file or directory
Normal Killing 53s kubelet Container liveness failed liveness probe, will be restarted
Normal Created 23s (x2 over 94s) kubelet Created container liveness
Normal Started 23s (x2 over 94s) kubelet Started container liveness
Normal Pulled 23s kubelet Container image "busybox" already present on machine
4.2.3.1 liveness-exec案例-扩展
设置重启策略
apiVersion: v1
kind: Pod
metadata:
name: liveness-exce-restart
namespace: default
spec:
restartPolicy: Never
containers:
- name: liveness
image: busybox
imagePullPolicy: IfNotPresent
args:
- /bin/sh
- -c
- touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy;sleep 600
livenessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 5 # pod启动延迟5秒后探测
periodSeconds: 5 # 每5秒探测1次
验证结果
容器健康检查出现问题后,不再重启,也不会继续sleep 600秒,而是直接关闭了
1. 编写YAML文件
[root@master01 test]# vim pod-liveness-httpget.yml
apiVersion: v1
kind: Pod
metadata:
name: liveness-httpget
namespace: default
spec:
containers:
- name: liveness
image: nginx:1.15-alpine
imagePullPolicy: IfNotPresent
ports: # 指定容器端口,这一段不写也行,端口由镜像决定
- name: http # 自定义名称,不需要与下面的port: http对应
containerPort: 80 # 类似dockerfile里的expose 80
livenessProbe:
httpGet: # 使用httpGet方式
port: http # http协议,也可以直接写80端口
path: /index.html # 探测家目录下的index.html
initialDelaySeconds: 3 # 延迟3秒开始探测
periodSeconds: 5 # 每隔5s钟探测一次
2. 应用配置
[root@master01 test]# kubectl apply -f pod-liveness-httpget.yml
pod/liveness-httpget created
3. 查看结果
4. 交互删除nginx文件,造成服务异常
[root@master01 test]# kubectl exec -it liveness-httpget -- rm -rf /usr/share/nginx/html/index.html
5. 观察结果
pod liveness-httpget 被重启调用了
1. 编写YAML文件
[root@k8s-master1 ~]# vim pod-liveness-tcp.yml
apiVersion: v1
kind: Pod
metadata:
name: liveness-tcp
namespace: default
spec:
containers:
- name: liveness
image: nginx:1.15-alpine
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
livenessProbe:
tcpSocket: # 使用tcp连接方式
port: 80 # 连接80端口进行探测
initialDelaySeconds: 3
periodSeconds: 5
2. 应用配置文件
[root@master01 test]# kubectl apply -f pod-liveness-tcp.yml
pod/liveness-tcp created
3. 观察结果
4. 交互关闭nginx
kubectl exec -it liveness-tcp -- /usr/sbin/nginx -s stop
5. 观察
也只重启 ,重启后重新初始化了
1. 编写YMAL文件
vim pod-readiness-httpget.yml
apiVersion: v1
kind: Pod
metadata:
name: readiness-httpget
namespace: default
spec:
containers:
- name: readiness
image: nginx:1.15-alpine
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
readinessProbe: # 这里由liveness换成了readiness
httpGet:
port: http
path: /index.html
initialDelaySeconds: 3
periodSeconds: 5
2. 应用YAML文件
[root@master01 test]# kubectl apply -f pod-readiness-httpget.yml
pod/readiness-httpget created
3. 验证
pod正常启动
4. 交互删除nginx主页
kubectl exec -it readiness-httpget -- rm -rf /usr/share/nginx/html/index.html
5. 再次验证
6. 创建nginx主页文件后
kubectl exec -it readiness-httpget -- touch /usr/share/nginx/html/index.html
7。 观察服务
最后一i条,回复正常
[root@master01 test]# kubectl get pods -w
NAME READY STATUS RESTARTS AGE
nginx-test-7d95fb4447-6nfs2 1/1 Running 1 44h
nginx-test-7d95fb4447-mtkg8 1/1 Running 2 2d21h
readiness-httpget 1/1 Running 0 40s
readiness-httpget 0/1 Running 0 3m21s
readiness-httpget 1/1 Running 0 4m31s
4.2.4.5 readiness+ liveness 混合案例
1. 创建YAML文件
vim pod-readiness-liveiness.yml
apiVersion: v1
kind: Pod
metadata:
name: readiness-liveness-httpget
namespace: default
spec:
containers:
- name: readiness-liveness
image: nginx:1.15-alpine
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
livenessProbe:
httpGet:
port: http
path: /index.html
initialDelaySeconds: 1
periodSeconds: 3
readinessProbe:
httpGet:
port: http
path: /index.html
initialDelaySeconds: 5
periodSeconds: 5
2. 应用文件
[root@master01 test]# kubectl apply -f pod-readiness-liveiness.yml
3. 观察结果
4. 交互删除nginx文件
kubectl exec -it readiness-liveness-httpget -- rm -rf /usr/share/nginx/html/index.html
1. 编写YAML文件
vim pod-poststart.yml
apiVersion: v1
kind: Pod
metadata:
name: poststart
namespace: default
spec:
containers:
- name: poststart
image: nginx:1.15-alpine
imagePullPolicy: IfNotPresent
lifecycle: # 生命周期事件
postStart:
exec:
command: ["mkdir","-p","/usr/share/nginx/html/haha"]
3. 查看结果
kubectl exec -it poststart -- ls /usr/share/nginx/html -l
容器终止前执行的命令
1, 编写YAML文件
[root@k8s-master1 ~]# vim prestop.yml apiVersion: v1 kind: Pod metadata: name: prestop namespace: default spec: containers: - name: prestop image: nginx:1.15-alpine imagePullPolicy: IfNotPresent lifecycle: # 生命周期事件 preStop: # preStop exec: command: ["/bin/sh","-c","sleep 60000000"] # 容器终止前sleep 60000000秒
2, 应用YAML文件创建pod
[root@k8s-master1 ~]# kubectl apply -f prestop.yml pod/prestop created
3, 删除pod验证
[root@k8s-master1 ~]# kubectl delete -f prestop.yml pod "prestop" deleted 会在这一步等待一定的时间(大概30s-60s左右)才能删除,说明验证成功结论: 当出现特殊情况不能正常销毁pod时,大概等待30秒会强制终止
状态 | 描述 |
---|---|
Pending(悬决) | Pod 已被 Kubernetes 系统接受,但有一个或者多个容器尚未创建亦未运行。此阶段包括等待 Pod 被调度的时间和通过网络下载镜像的时间。 |
Running(运行中) | pod已经绑定到一个节点,并且已经创建了所有容器。至少有一个容器正在运行中,或正在启动或重新启动。 |
completed(完成) | Pod中的所有容器都已成功终止,不会重新启动。 |
Failed(失败) | Pod的所有容器均已终止,且至少有一个容器已在故障中终止。也就是说,容器要么以非零状态退出,要么被系统终止。 |
Unknown(未知) | 由于某种原因apiserver无法获得Pod的状态,通常是由于Master与Pod所在主机kubelet通信时出错。 |
CrashLoopBackOff | 多见于CMD语句错误或者找不到container入口语句导致了快速退出,可以用kubectl logs 查看日志进行排错 |
kubectl describe pod pod名
kubectl logs pod [-c CONTAINER]
kubectl exec POD [-c CONTAINER] --COMMAND [args...]
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。