4 pod的状态以及探针类型和方式
一 Pod的常见状态、pause容和init容器
1 pod常见的状态
Unschedulable #pod不能被调度,kube-scheduler没有匹配到合适的node节点
PodScheduled #pod正处于调度中,在kube-schedulerg刚开始调度的时候,还没有将pod分配到指定的node,在筛选出合适的节点后就会更新etcd数据,将pod分配到指定的node
Pending #正在创建的pod,但是pod中的容器还诶呦完全被创建完成(处于此状态的pod应该检查pod依赖的存储是否有权限挂载等)
Failed #pod中有容器启动失败而导致pod工作异常
Unknown #由于某种原因无法获得Pod的当前状态,通常是由于pod所在的node节点通信错误
initialized #所有的pod中的初始化容器已经完成了
imagePullBackOff #pod所在的node节点下载镜像失败
Running # pod内部的容器已经被创建并且启动
Ready #表示pod中的容器已经可以提供访问服务
Error # 启动过程中发生错误
NodeLost #pod所在节点失联
waiting #pod等待启动
Terminating # pod正在被销毁
CrashLoopBackOff #pod停止,但是kubelet正在将他重启
invalidlmagename # node节点无法解析镜像名称,导致无法下载
ImageinspectError #无法校验镜像,镜像不完整导致
ErrimageNeverPull #策略禁止拉取镜像,镜像中心权限是私有
RegistryUnavailable #镜像服务器不可用,网络原因或者harbor宕机
ErrimagePull #镜像拉取出错,超时或者下载被强制终止
createcontainerconfigerror #不能创建kubelet使用的容器配置
createcontainerError #创建容器失败
RuncontainerError # pod运行失败,容器中没有初始化pid为1的守护进程等
containersNotlnitialized #pod没有初始化完毕
containerNotReady #pod 没有准备完毕
containerCreating #pod正在创建中
podinitializing #pod初始化中
DockerDaemonNotReady #node节点docker服务没有启动
NetworkPluginNotReady #网络插件没有启动
2 pause容和init容器
2.1 pause 容器
pause 容器,又叫infra容器,是Pod的基础容器,镜像体积只有几百kb左右,配置在kubelet中,主要功能是一个pod中多个容器的网络通信。
infra容器被创建后会初始化network namespace,之后其他容器剧可以加入的infra容器中共享infra容器的网络了。
一个pod中的两个容器A和bB,那么关系如下:
1 a容器和B容器能够直接使用localhost通信
2 a容器和b容器可以看到网卡,ip和端口监听信息。
3 pod只有一个ip地址,也就是改pod的network,namespace对应的ip地址(由infra容器初始化并创建)
4 k8s环境中的每个pod有一个独立的ip地址,并且此ip被当前pod中所有容器在内部共享使用。
5 pod删除后infra容器随机被删除,其ip被回收。
pause-宿主机的namespace
然后到Pod所在的宿主机验证网卡
查看一个pod的Ip,然后去宿主机找到对应的ip
然后在node节点运行如下命令
[root@k8s-node1 pause-test-case]# nsenter --net=/run/docker/netns/e8097040db3f ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.100.36.125 netmask 255.255.255.255 broadcast 10.100.36.125
ether 0a:e4:27:eb:50:44 txqueuelen 0 (Ethernet)
RX packets 5 bytes 446 (446.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
e8097040db3f 这个就是namespace
2.2 演示实例:通过docker演示pause,需要准备一个nginx.conf和index.html
[root@k8s-node1 pause-test-case]# cat nginx.conf
error_log stderr;
events { worker_connections 1024; }
http {
access_log /dev/stdout;
server {
listen 80 default_server;
server_name www.mysite.com;
location / {
index index.html index.php;
root /usr/share/nginx/html;
}
location ~ \.php$ {
root /usr/share/nginx/html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
}
index.html和index.php
1 启动一个pause容器
docker run -d -p80:80 --name pause-container-1 easzlab/pause:3.6
2 启动一个nginx容器,网络使用pause的网络
docker run -d --name nginx-container-test -v `pwd`/nginx.conf:/etc/nginx/nginx.conf -v `pwd`/html:/usr/share/nginx/html/ --net=container:pause-container-1 nginx:1.20.0
3启动一个php容器,网络也使用pause的
docker run -d --name php-test --net=container:pause-container-1 -v `pwd`/html:/usr/share/nginx/html/ php:5.6.40-fpm
访问效果
2.3 init容器
2.3.1 init 容器的作用:
1 可以为业务容器提前准备好业务容器的运行环境,
2 可以在卞业务容器之前准备好需要的业务数据
3 检查依赖的服务是否可以访问
2.3.2 init容器的特点:
1 一个pod可以有多个业务网容器,还能在有多个init容器,但是每个init容器和业务容器的运行环境都是隔离的
2 init容器会比业务容器先启动
3 init 容器运行成功后,才运行业务容器
4如果一个pod有多个init容器,那么需要从上到下逐个运行并且全部成功,最后才会运行业务容器。
5 init 容器不支持探针检测,因为初始化完成后退出就再也不运行了
举例:创建一个nginx的pod,需要初始化网站的数据,这里用centos:7.9.2009 这个镜像来做init的容器
[root@k8s-master1 init]# cat 1-init-container.yaml
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
metadata:
labels:
app: myserver-myapp
name: myserver-myapp-deployment-name
namespace: myserver
spec:
replicas: 1
selector:
matchLabels:
app: myserver-myapp-frontend
template:
metadata:
labels:
app: myserver-myapp-frontend
spec:
containers:
- name: myserver-myapp-container
image: nginx:1.20.0
#imagePullPolicy: Always
volumeMounts:
- mountPath: "/usr/share/nginx/html/myserver"
name: myserver-data
initContainers:
- name: init-web-data
image: centos:7.9.2009
command: ['/bin/bash','-c',"for i in `seq 1 10`;do echo '<h1>'$i web page at $(date +%Y%m%d%H%M%S) '<h1>' >> /data/nginx/html/myserver/index.html;sleep 1;done"]
volumeMounts:
- mountPath: "/data/nginx/html/myserver"
name: myserver-data
- name: change-data-owner
image: busybox:1.28
command: ['/bin/sh','-c',"/bin/chmod 644 /data/nginx/html/myserver/* -R"]
volumeMounts:
- mountPath: "/data/nginx/html/myserver"
name: myserver-data
volumes:
- name: myserver-data
hostPath:
path: /tmp/data/html
---
kind: Service
apiVersion: v1
metadata:
labels:
app: myserver-myapp-service
name: myserver-myapp-service-name
namespace: myserver
spec:
type: NodePort
ports:
- name: http
port: 80
targetPort: 80
nodePort: 30080
selector:
app: myserver-myapp-frontend
效果如下:
二 pod的声明周期和探针
2.1 生命周期
pod的声明周期,从start后可以配置poststart检查,运行过程中可以配置livenessprobe和readlinessprobe ,最后在stop前可以配置prestop配置
2.2 探针简介
探针是由kubelet对容器执行的定期诊断,以保证pod的状态始终处于运行状态,要执行诊断,kubelet调用由容器实现的handler,也称为钩子,有是那种类型的处理程序
1 Execaction
在容器内部执行指定命令,如果命令退出时,返回码为0,则认为诊断成功
2 TcpSocketaction
对指定端口上的容器ip地址进行tcp检查,如果端口打开,则认为是成功的
3 HTTPGetAction
对指定的端口和路径上的容器的ip地址执行httpget请求,如果相应状态码大于等于200且小于400,则认为是成功的。
HTTP 探针 允许针对 httpGet 配置额外的字段:
host:连接使用的主机名,默认是 Pod 的 IP。也可以在 HTTP 头中设置 “Host” 来代替。
scheme :用于设置连接主机的方式(HTTP 还是 HTTPS)。默认是 "HTTP"。
path:/index.html #访问 HTTP 服务的路径。默认值为 "/"。
httpHeaders:请求中自定义的 HTTP 头。HTTP 头字段允许重复。
port:80 #访问容器的端口号或者端口名。如果数字必须在 1~65535 之间。
探针最终的三种结果
成功
失败
未知:诊断失败,因此不会采取任何行动
2.3 探针类型
1 startupProbe #启动探针,v1.16引入
判断容器内的应用程序是否已启动完成。如果配置了启动探测,则会先禁用所有其他的探测,直到startupprobe检查成功为止,如果startupprobe,检查失败,则kubelet将杀死容器,
2 livenssprobe #存活探针
检查容器是否正在运行,如果存活探测失败,则kublet会杀死容器,并且容器将受到其重启策略的影响,如果容器不提供存活探针,则默认状态为success,livessprobe用户控制是否重启pod
3 readinessprobe # 就绪探针
如果就绪探针检测失败,端点控制器将从与pod匹配的所有的service的端点中删除该pod的ip地址,初始延迟之前的就绪状态默认为failure 失败,如果容器不提供就绪探针,则默认为success,
readinessprobe用于控制pod是否添加到service里。
2.3.1 strtupProbe实例
[root@k8s-master1 probe]# cat 4-startupProbe.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myserver-myapp-frontend-deployment
namespace: myserver
spec:
replicas: 1
selector:
matchLabels: #rs or deployment
app: myserver-myapp-frontend-label
#matchExpressions:
# - {key: app, operator: In, values: [myserver-myapp-frontend,ng-rs-81]}
template:
metadata:
labels:
app: myserver-myapp-frontend-label
spec:
containers:
- name: myserver-myapp-frontend-label
image: nginx:1.20.2
ports:
- containerPort: 80
startupProbe:
httpGet:
path: /index.html
port: 80
initialDelaySeconds: 5 #首次检测延迟5s
failureThreshold: 3 #从成功转为失败的次数
periodSeconds: 3 #探测间隔周期
---
apiVersion: v1
kind: Service
metadata:
name: myserver-myapp-frontend-service
namespace: myserver
spec:
ports:
- name: http
port: 81 # k8s之间访问的端口
targetPort: 80 #容器里的端口
nodePort: 40012
protocol: TCP
type: NodePort
selector:
app: myserver-myapp-frontend-label
2.3.2 三种探针全部加上
[root@k8s-master1 probe]# cat 5-startupProbe-livenessProbe-readinessProbe.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myserver-myapp-frontend-deployment
namespace: myserver
spec:
replicas: 1
selector:
matchLabels: #rs or deployment
app: myserver-myapp-frontend-label
#matchExpressions:
# - {key: app, operator: In, values: [myserver-myapp-frontend,ng-rs-81]}
template:
metadata:
labels:
app: myserver-myapp-frontend-label
spec:
terminationGracePeriodSeconds: 60
containers:
- name: myserver-myapp-frontend-label
image: nginx:1.20.2
ports:
- containerPort: 80
startupProbe:
httpGet:
#path: /monitor/index.html
path: /index.html
port: 80
initialDelaySeconds: 5 #首次检测延迟5s
failureThreshold: 3 #从成功转为失败的次数
periodSeconds: 3 #探测间隔周期
readinessProbe:
httpGet:
#path: /monitor/monitor.html
path: /index.html
port: 80
initialDelaySeconds: 5
periodSeconds: 3
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 3
livenessProbe:
httpGet:
#path: /monitor/monitor.html
path: /index.html
port: 80
initialDelaySeconds: 5
periodSeconds: 3
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 3
---
apiVersion: v1
kind: Service
metadata:
name: myserver-myapp-frontend-service
namespace: myserver
spec:
ports:
- name: http
port: 81
targetPort: 80
nodePort: 40012
protocol: TCP
type: NodePort
selector:
app: myserver-myapp-frontend-label
2.4 探针通用配置参数
initialDelaySeconds:120 # 容器启动后要等待多少秒后才启动存活和就绪探测器, 默认是 0 秒,最小值是 0。
periodSeconds:60 #执行探测的时间间隔(单位是秒)。默认是 10 秒。最小值是 1。
timeoutSeconds:5 #探测的超时后等待多少秒。默认值是 1 秒。最小值是 1。
successThreshold:1 # 探测器在失败后,被视为成功的最小连续成功数。默认值是 1。 存活和启动探测的这个值必须是 1。最小值是 1。
failureThreshold:3 #当探测失败时,Kubernetes 的重试次数。 对存活探测而言,放弃就意味着重新启动容器。 对就绪探测而言,放弃意味着 Pod 会被打上未就绪的标签。默认值是 3。最小值是 1。
2.5 探针检测方式演示
1 http类型探针
[root@k8s-master1 probe]# kubectl apply -f 1-http-Probe.yaml
deployment.apps/myserver-myapp-frontend-deployment created
service/myserver-myapp-frontend-service created
[root@k8s-master1 probe]# cat 1-http-Probe.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myserver-myapp-frontend-deployment
namespace: myserver
spec:
replicas: 1
selector:
matchLabels: #rs or deployment
app: myserver-myapp-frontend-label
#matchExpressions:
# - {key: app, operator: In, values: [myserver-myapp-frontend,ng-rs-81]}
template:
metadata:
labels:
app: myserver-myapp-frontend-label
spec:
containers:
- name: myserver-myapp-frontend-label
image: nginx:1.20.2
ports:
- containerPort: 80
#readinessProbe:
livenessProbe:
httpGet:
#path: /monitor/monitor.html
path: /index.html
port: 80
initialDelaySeconds: 5
periodSeconds: 3
timeoutSeconds: 3
successThreshold: 1
failureThreshold: 3
readinessProbe:
httpGet:
#path: /monitor/monitor.html
path: /index.html
port: 80
initialDelaySeconds: 5
periodSeconds: 3
timeoutSeconds: 3
successThreshold: 1
failureThreshold: 3
---
apiVersion: v1
kind: Service
metadata:
name: myserver-myapp-frontend-service
namespace: myserver
spec:
ports:
- name: http
port: 80
targetPort: 80
nodePort: 40018
protocol: TCP
type: NodePort
selector:
app: myserver-myapp-frontend-label
2 tcp检查
[root@k8s-master1 probe]# cat 2-tcp-Probe.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myserver-myapp-frontend-deployment
namespace: myserver
spec:
replicas: 1
selector:
matchLabels: #rs or deployment
app: myserver-myapp-frontend-label
#matchExpressions:
# - {key: app, operator: In, values: [myserver-myapp-frontend,ng-rs-81]}
template:
metadata:
labels:
app: myserver-myapp-frontend-label
spec:
containers:
- name: myserver-myapp-frontend-label
image: nginx:1.20.2
ports:
- containerPort: 80
livenessProbe:
#readinessProbe:
tcpSocket:
#port: 80
port: 80
initialDelaySeconds: 5
periodSeconds: 3
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 3
---
apiVersion: v1
kind: Service
metadata:
name: myserver-myapp-frontend-service
namespace: myserver
spec:
ports:
- name: http
port: 80
targetPort: 80
nodePort: 40012
protocol: TCP
type: NodePort
selector:
app: myserver-myapp-frontend-label
3 exec-自定义命令
[root@k8s-master1 probe]# cat 3-exec-Probe.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myserver-myapp-redis-deployment
namespace: myserver
spec:
replicas: 1
selector:
matchLabels: #rs or deployment
app: myserver-myapp-redis-label
#matchExpressions:
# - {key: app, operator: In, values: [myserver-myapp-redis,ng-rs-81]}
template:
metadata:
labels:
app: myserver-myapp-redis-label
spec:
containers:
- name: myserver-myapp-redis-container
image: redis
ports:
- containerPort: 6379
livenessProbe:
#readinessProbe:
exec:
command:
#- /apps/redis/bin/redis-cli
- /usr/local/bin/redis-cli
- quit
initialDelaySeconds: 5
periodSeconds: 3
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 3
---
apiVersion: v1
kind: Service
metadata:
name: myserver-myapp-redis-service
namespace: myserver
spec:
ports:
- name: http
port: 6379
targetPort: 6379
nodePort: 40016
protocol: TCP
type: NodePort
selector:
app: myserver-myapp-redis-label
2.6 如何优雅的终止pod(prestop)
poststart:
pod被创建后立即执行检查,及不等的pod中的服务启动
如果poststart执行失败pod不会被继续创建
prestop:
在pod被停止之前执行一些操作
通俗的讲就是等待一定时间,才会执行prestop的操作,在等待的时间,可以把pod从注册中心移走,或者让pod下线,这样当执行prestop的之后,避免用户发送访问请求,造成页面打不开的故障。
演示:
[root@k8s-master1 probe]# cat 1-myserver-myapp1-postStart-preStop.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myserver-myapp1-lifecycle
labels:
app: myserver-myapp1-lifecycle
namespace: myserver
spec:
replicas: 1
selector:
matchLabels:
app: myserver-myapp1-lifecycle-label
template:
metadata:
labels:
app: myserver-myapp1-lifecycle-label
spec:
terminationGracePeriodSeconds: 60 #终止等待期就是说等待60秒之后,才会执行prestop里的命令
containers:
- name: myserver-myapp1-lifecycle-label
image: tomcat:7.0.94-alpine
lifecycle:
postStart:
exec:
#command: 把自己注册到注册在中心
command: ["/bin/sh", "-c", "echo 'Hello from the postStart handler' >> /usr/local/tomcat/webapps/ROOT/index.html"]
#httpGet:
# #path: /monitor/monitor.html
# host: www.magedu.com
# port: 80
# scheme: HTTP
# path: index.html
preStop:
exec:
#command: 把自己从注册中心移除
command: ["/usr/local/tomcat/bin/catalina.sh","stop"]
ports:
- name: http
containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: myserver-myapp1-lifecycle-service
namespace: myserver
spec:
ports:
- name: http
port: 80
targetPort: 8080
nodePort: 30012
protocol: TCP
type: NodePort
selector:
app: myserver-myapp1-lifecycle-label
大致流程: