k8s基础-Pod

1.pod

1.1创建一个pod

使用命令kubectl run 创建一个pod:

1
2
3
4
5
# kubectl run nginx-run --image=registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:1.24.0
pod/nginx-run created

# --image=nginx:1.24.0默认从dockerhub拉取镜像,现在已经无法拉取
# --image=registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:1.24.0指定地址拉取

使用yaml文件创建一个pod:

1
2
#利用命令创建一个简单pod的yaml文件
kubectl run nginx-run --image=registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:1.24.0 --dry-run=client -oyaml >pod.yaml

下面是一个pod的yaml文件内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#一个pod如果管理多个容器,多个容器之间的端口不能相同,容器的名字也不能一样
apiVersion: v1 #apiVersion版本号
kind: Pod #指定资源的类型,告诉Kubernetes这个YAML文件创建的是一个Pod资源
metadata: #pod的元数据
labels: #标签
run: nginx-run #key=value的格式,可以根据标签筛选过滤出不同的pod
name: nginx-run # 指定pod的名称
spec: #用于指定期望pod的规格
containers: #定义配置容器,复数表示可以配置一个或多个容器
- image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:1.24.0 #指定容器的镜像
name: nginx-run #指定容器的名字
ports: #可选,容器需要暴露的端口号列表
- containerPort: 80 #指定了容器内部的 Nginx 服务监听 80 端口
- image: redis:6.0.0
name: redis

根据yaml文件创建pod:

1
2
[root@k8s-master01 pra]# kubectl create -f pod.yaml
pod/nginx-run created

小技巧:(使用kubectl explain pod 可以查看pod都可以使用哪些参数)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
[root@k8s-master01 pra]# kubectl explain pod
KIND: Pod
VERSION: v1

DESCRIPTION:
Pod is a collection of containers that can run on a host. This resource is
created by clients and scheduled onto hosts.

FIELDS:
apiVersion <string>
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources

kind <string>
Kind is a string value representing the REST resource this object
represents. Servers may infer this from the endpoint the client submits
requests to. Cannot be updated. In CamelCase. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds

metadata <ObjectMeta>
Standard object's metadata. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata

spec <PodSpec>
Specification of the desired behavior of the pod. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status

status <PodStatus>
Most recently observed status of the pod. This data may not be up to date.
Populated by the system. Read-only. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status

#一层一层的往下查看都有哪些参数可以配置,例如:
kubectl explain pod.spec.containers

查看pod状态,默认查看的是default命名空间下的pod,如果要查看其他命名空间下的pod加-n参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# kubectl get po
NAME READY STATUS RESTARTS AGE
nginx-run 1/1 Running 0 2m34s

##查看kube-system命名空间下的pod使用-n参数,kube-system是命名空间的名字
# kubectl get po -n kube-system
NAME READY STATUS RESTARTS AGE
calico-kube-controllers-75bdb5b75d-znr65 1/1 Running 2 (38m ago) 6d7h
canal-ht7kk 2/2 Running 2 (38m ago) 6d7h
canal-x28k7 2/2 Running 2 (38m ago) 6d7h
coredns-5c69dbb7bd-2hcjc 1/1 Running 1 (38m ago) 6d7h
coredns-5c69dbb7bd-wnfxj 1/1 Running 1 (38m ago) 6d7h
etcd-controlplane 1/1 Running 2 (38m ago) 6d7h
kube-apiserver-controlplane 1/1 Running 2 (38m ago) 6d7h
kube-controller-manager-controlplane 1/1 Running 2 (38m ago) 6d7h
kube-proxy-gbgj8 1/1 Running 2 (38m ago) 6d7h
kube-proxy-xcj62 1/1 Running 1 (38m ago) 6d7h
kube-scheduler-controlplane 1/1 Running 2 (38m ago) 6d7h


#获取pod的更多信息使用-o wide参数
# get表示获取某个资源
# pod表示获取的资源是pod
# -o(或--output)用于指定命令的输出格式
# wide 这是-o参数的一个可选值,表示以宽格式输出。
# kubectl get po -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-run 1/1 Running 0 9m26s 192.168.1.6 node01 <none> <none>

删除pod:

1
2
3
4
5
#删除以yaml文件创建的pod
[root@k8s-master01 pra]# kubectl delete -f pod.yaml

#根据名称删除pod,nginx-run是pod的名称
[root@k8s-master01 pra]# kubectl delete pod nginx-run

1.1.2更改pod的启动命令和参数

在 Kubernetes 中,commandargs 是用来覆盖容器镜像中的默认命令和参数的。它们都可以在 spec.containers 字段下定义,分别用于设置容器启动时执行的命令和传递给该命令的参数。

1
2
3
4
5
6
command:
覆盖容器镜像中的默认命令。它可以是一个单独的命令(如 /bin/bash)或一个完整的命令路径(如 /usr/bin/env)
如果未指定,容器将使用镜像中的默认入口点(ENTRYPOINT)。如果指定了 command,它会覆盖默认的 ENTRYPOINT。
args:
传递给 command 的参数。
如果未指定,容器将使用镜像中的默认参数(CMD)。如果指定了 args,它会覆盖默认的 CMD。
1
2
3
4
5
6
7
8
9
10
11
12
[root@k8s-master01 pra]# cat pod.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
run: nginx-run
name: nginx
spec:
containers:
- image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:1.24.0
name: nginx-run
command: ["sleep","10"] #覆盖原有的容器启动命令,可选参数

1.1.3Pod状态以及pod故障排查命令

状态 说明
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 查看程序启动日志
Terminating Pod 正在被删除,可以通过 describe 查看状态
SysctlForbidden Pod 自定义了内核配置,但 kubelet 没有添加内核配置或配置的内核参数不支持,可以通过 describe 查看具体原因
Completed 容器内部主进程退出,一般计划任务执行结束会显示该状态,此时可以通过 logs查看容器日志
ContainerCreating Pod 正在创建,一般为正在下载镜像,或者有配置不当的地方,可以通过 describe查看具体原因

注意:Pod 的 Phase 字段只有 Pending、Running、Succeeded、Failed、Unknown,其余的为处于上述状态的原因,可以通过 kubectl get po xxx –o yaml 查看。

1.1.4Pod镜像拉取策略

通过 spec.containers[].imagePullPolicy 参数可以指定镜像的拉取策略,目前支持的策略如下:

操作方式 说明
Always 总是拉取,当镜像 tag 为 latest 时,且 imagePullPolicy 未配置,默认为 Always
IfNotPresent 镜像不存在时拉取镜像,如果 tag 为非 latest,且 imagePullPolicy 未配置,默认为 IfNotPresent
Never 不管是否存在都不会拉取

指定镜像的拉取策略为Always

1
2
3
4
5
6
7
8
9
10
11
12
vim pod.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
run: nginx-run
name: nginx
spec:
containers:
- image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:1.24.0
name: nginx-run
imagePullPolicy: Always

验证当tag不是latest是,不配置imagePullPolicy,默认是Always

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#pod的yaml文件如下:
[root@k8s-master01 pra]# cat pod.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
run: nginx-run
name: nginx
spec:
containers:
- image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:1.24.0
name: nginx-run

#创建pod
[root@k8s-master01 pra]# kubectl create -f pod.yaml
pod/nginx created

查看pod的yaml文件的imagePullPolicy是否为Always
[root@k8s-master01 pra]# kubectl get po nginx -oyaml|grep "imagePullPolicy"
imagePullPolicy: IfNotPresent

1.1.5Pod重启策略

在 Kubernetes 中,Pod 的重启策略(Restart Policy)定义了当容器崩溃或退出时,Kubernetes 如何处理该 Pod 中的容器。Pod 的重启策略可以帮助确保容器在运行期间的高可用性和稳定性。

可以使用 spec.restartPolicy 指定容器的重启策略

操作方式 说明
Always 默认策略。无论容器退出的原因是什么,都会重启容器。对于大多数控制器(如 Deployment、ReplicaSet),默认使用 Always
OnFailure 仅当容器以非零状态码退出时才重启。
Never 当容器无论以任何状态退出时,都不会重启。

指定pod的重启策略为Always

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#一个pod如果管理多个容器,多个容器之间的端口不能相同,容器的名字也不能一样
apiVersion: v1 #apiVersion版本号
kind: Pod #指定资源的类型,告诉Kubernetes这个YAML文件创建的是一个Pod资源
metadata: #pod的元数据
labels: #标签
run: nginx-run #key=value的格式,可以根据标签筛选过滤出不同的pod
name: nginx-run # 指定pod的名称
spec: #用于指定期望pod的规格
restartPolicy: Always #不配置也默认是Always策略
containers: #定义配置容器,复数表示可以配置一个或多个容器
- image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:1.24.0 #指定容器的镜像
name: nginx-run #指定容器的名字
ports: #可选,容器需要暴露的端口号列表
- containerPort: 80 #指定了容器内部的 Nginx 服务监听 80 端口
- image: redis:6.0.0
name: redis

指定pod的重启策略为OnFailure

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#一个pod如果管理多个容器,多个容器之间的端口不能相同,容器的名字也不能一样
apiVersion: v1 #apiVersion版本号
kind: Pod #指定资源的类型,告诉Kubernetes这个YAML文件创建的是一个Pod资源
metadata: #pod的元数据
labels: #标签
run: nginx-run #key=value的格式,可以根据标签筛选过滤出不同的pod
name: nginx-run # 指定pod的名称
spec: #用于指定期望pod的规格
restartPolicy: OnFailure #配置重启策略为OnFailure
containers: #定义配置容器,复数表示可以配置一个或多个容器
- image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:1.24.0 #指定容器的镜像
name: nginx-run #指定容器的名字
ports: #可选,容器需要暴露的端口号列表
- containerPort: 80 #指定了容器内部的 Nginx 服务监听 80 端口
- image: redis:6.0.0
name: redis

指定pod的重启策略为Never

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#一个pod如果管理多个容器,多个容器之间的端口不能相同,容器的名字也不能一样
apiVersion: v1 #apiVersion版本号
kind: Pod #指定资源的类型,告诉Kubernetes这个YAML文件创建的是一个Pod资源
metadata: #pod的元数据
labels: #标签
run: nginx-run #key=value的格式,可以根据标签筛选过滤出不同的pod
name: nginx-run # 指定pod的名称
spec: #用于指定期望pod的规格
restartPolicy: Never #配置重启策略为Never
containers: #定义配置容器,复数表示可以配置一个或多个容器
- image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:1.24.0 #指定容器的镜像
name: nginx-run #指定容器的名字
ports: #可选,容器需要暴露的端口号列表
- containerPort: 80 #指定了容器内部的 Nginx 服务监听 80 端口
- image: redis:6.0.0
name: redis

1.1.6Pod的三种探针

在 Kubernetes 中,探针(Probes)用于检测 Pod 中容器的健康状态和可用性。探针有三种类型:存活探针(Liveness Probe)、就绪探针(Readiness Probe)和启动探针(Startup Probe)。这些探针可以帮助 Kubernetes 自动恢复不健康的容器,并在应用启动或准备就绪时将流量引导到健康的实例。

健康检查是准对容器进行的,所以配置在spec.containers中的

三种探针类型:

  1. Liveness Probe(存活探针):检测容器是否处于健康状态。如果存活探针失败,Kubernetes 会重启该容器。
  2. Readiness Probe(就绪探针):检测容器是否准备好接受流量。如果就绪探针失败,Kubernetes 会将该容器从服务的负载均衡器中移除。
  3. Startup Probe(启动探针):检测容器是否已经成功启动。如果配置了启动探针,存活探针会被禁用,直到启动探针成功为止。适用于启动时间较长的应用。
种类 说明
startupProbe(只启动一次,适用于启动较慢的程序) Kubernetes1.16 新加的探测方式,用于判断容器内的应用程序是否已经启动。如果配置了 startupProbe,就会先禁用其他探测,直到它成功为止。如果探测失败,Kubelet会杀死容器,之后根据重启策略进行处理,如果探测成功,或没有配置 startupProbe,则状态为成功,之后就不再探测。
livenessProbe(循环探测) 用于探测容器是否在运行,如果探测失败,kubelet 会“杀死”容器并根据重启策略进行相应的处理。如果未指定该探针,将默认为 Success
readinessProbe 一般用于探测容器内的程序是否健康,即判断容器是否为就绪(Ready)状态。如果是,则可以处理请求,反之Endpoints Controller将从所有的 Service 的 Endpoints中删除此容器所在 Pod 的 IP 地址。如果未指定,将默认为 Success

1.1.7探针的检测方式

探测方式 说明
exec 在容器内执行一个指定的命令,如果命令执行成功,则返回值是 0,就认为容器健康(返回值是否为0 根据echo $?判断)
tcpSocket(程序可能存在假死状态) 通过 TCP 连接检查容器指定的端口,如果端口开放,则认为容器健康
httpGet(最可靠,但是需要开发提供一个接口) 对指定的 URL 进行 Get 请求,如果状态码在 200~400 之间,则认为容器健康
grpc

1.1.8liveness Probe(存活探针)和readinessProbe(就绪探针)

创建一个没有健康检查的pod:

场景说明:当一个程序启动很慢,又没有健康检查,容器创建完状态会立马变为Running状态,此时就会为该容器分配流量,但是由于程序实际没有成功启动,所以无法处理流量,就会拒绝服务。这种情况在生产环境很危险。

下面配置的pod使用sleep 10; 模拟程序启动慢

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#一个pod如果管理多个容器,多个容器之间的端口不能相同,容器的名字也不能一样
apiVersion: v1 #apiVersion版本号
kind: Pod #指定资源的类型,告诉Kubernetes这个YAML文件创建的是一个Pod资源
metadata: #pod的元数据
labels: #标签
run: nginx-run #key=value的格式,可以根据标签筛选过滤出不同的pod
name: nginx # 指定pod的名称
spec: #用于指定期望pod的规格
restartPolicy: Never #配置重启策略为Never
containers: #定义配置容器,复数表示可以配置一个或多个容器
- image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:1.24.0 #指定容器的镜像
name: nginx-run #指定容器的名字
ports: #可选,容器需要暴露的端口号列表
- containerPort: 80 #指定了容器内部的 Nginx 服务监听 80 端口
command: #可选,容器启动执行的命令
- sh
- -c
- sleep 10; nginx -g "daemon off;" #使用sleep 10 模拟程序启动慢

测试该pod

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#创建上述pod
[root@k8s-master01 pra]# kubectl create -f pod.yaml
pod/nginx created
[root@k8s-master01 pra]# kubectl get po -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
cluster-test-66bb44bd88-7kct4 1/1 Running 128 (7m38s ago) 17d 172.16.195.3 k8s-master03 <none> <none>
nginx 1/1 Running 0 5s 172.16.85.208 k8s-node01 <none> <none>

#10秒内访问该pod,无法访问
[root@k8s-master01 pra]# curl 172.16.85.208
curl: (7) Failed connect to 172.16.85.208:80; Connection refused

#10以后访问该pod,成功访问
[root@k8s-master01 pra]# curl 172.16.85.208
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

结论:当一个程序启动很慢,又没有健康检查,容器创建完状态会立马变为Running状态,此时就会为该容器分配流量,但是由于程序实际没有成功启动,所以无法处理流量,就会拒绝服务

创建一个有健康检查的pod:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#一个pod如果管理多个容器,多个容器之间的端口不能相同,容器的名字也不能一样
apiVersion: v1 #apiVersion版本号
kind: Pod #指定资源的类型,告诉Kubernetes这个YAML文件创建的是一个Pod资源
metadata: #pod的元数据
labels: #标签
run: nginx-run #key=value的格式,可以根据标签筛选过滤出不同的pod
name: nginx # 指定pod的名称
spec: #用于指定期望pod的规格
restartPolicy: Never #配置重启策略为Never
containers: #定义配置容器,复数表示可以配置一个或多个容器
- image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:1.24.0 #指定容器的镜像
name: nginx-run #指定容器的名字
restartPolicy: IfNotPresent
ports: #可选,容器需要暴露的端口号列表
- containerPort: 80 #指定了容器内部的 Nginx 服务监听 80 端口
command: #可选,容器启动执行的命令
- sh
- -c
- sleep 10; nginx -g "daemon off;" #使用sleep 10 模拟程序启动慢
#sartupProbe:
# tcpSocket: # 接口检测方式
# port: 80
# initialDelaySeconds: 10 # 初始化时间, 健康检查延迟执行时间
# timeoutSeconds: 2 # 超时时间
# periodSeconds: 5 # 检测间隔
# successThreshold: 1 # 检查成功为 2 次表示就绪
# failureThreshold: 2 # 检测失败 1 次表示未就绪
readinessProbe: # 可选,健康检查。注意4种检查方式同时只能使用一种,例如httpGet、tcpsocket只能选一种。
httpGet: # 接口检测方式
path: /index.html # 检查路径
port: 80
scheme: HTTP # HTTP or HTTPS
#httpHeaders: # 可选, 检查的请求头
#- name: end-user
# value: Jason
initialDelaySeconds: 10 # 初始化时间, 执行第一次健康检查前等待的事件
timeoutSeconds: 2 # 超时时间,两秒内得不到相应就认为超时
periodSeconds: 5 # 检测间隔,即每 periodSeconds(这里是5秒) 秒执行一次探针检查。
successThreshold: 2 # 检查成功为 2 次表示就绪,连续2次成功则认为合格
failureThreshold: 2 # 检测失败 2 次表示未就绪,连续2次失败则认为不合格,不会重启pod,只是不接受流量
livenessProbe: # 可选,健康检查
tcpSocket: # 端口检测方式
port: 80
initialDelaySeconds: 10 # 初始化时间
timeoutSeconds: 2 # 超时时间
periodSeconds: 5 # 检测间隔
successThreshold: 1 # 检查成功为 1次表示就绪
failureThreshold: 2 # 检测失败 2次表示未就绪,会重启pod

总结:livenessProbe当探测失败后会根据容器的重启策略对容器进行重启,readinessProbe当探测失败时不会对容器进行重启,只是该pod服务不可用,service不会给该pod分配流量。

1.1.9startupProbe(启动探针)

下面的配置模拟的场景是:当一个程序启动需要90秒(sleep 90;模拟启动慢),livenessProbe探测配置的periodSeconds是10秒,failureThreshold是9次,所以说连续探测9次都失败则会重启容器,但是如果程序出现问题,比如案例中nginx的首页被删除,那么该容器会在连续探测9次后重启,重启前90秒内该服务是无法提供服务的,这是不能容忍的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
apiVersion: v1  #apiVersion版本号
kind: Pod #指定资源的类型,告诉Kubernetes这个YAML文件创建的是一个Pod资源
metadata: #pod的元数据
labels: #标签
run: nginx-run #key=value的格式,可以根据标签筛选过滤出不同的pod
name: nginx # 指定pod的名称
spec: #用于指定期望pod的规格
restartPolicy: Always #配置重启策略为Never
containers: #定义配置容器,复数表示可以配置一个或多个容器
- image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:1.27-alpine #指定容器的镜像
name: nginx-run #指定容器的名字
ports: #可选,容器需要暴露的端口号列表
- containerPort: 80 #指定了容器内部的 Nginx 服务监听 80 端口
command: #可选,容器启动执行的命令
- sh
- -c
- sleep 90; nginx -g "daemon off;" #使用sleep 10 模拟程序启动慢
# startupProbe:
# tcpSocket: # 接口检测方式
# port: 80
# initialDelaySeconds: 10 # 初始化时间, 健康检查延迟执行时间
# timeoutSeconds: 2 # 超时时间
# periodSeconds: 5 # 检测间隔
# successThreshold: 1 # 检查成功为 2 次表示就绪
# failureThreshold: 2 # 检测失败 1 次表示未就绪
readinessProbe: # 可选,健康检查。注意三种检查方式同时只能使用一种。
httpGet: # 接口检测方式
path: /index.html # 检查路径
port: 80
scheme: HTTP # HTTP or HTTPS
#httpHeaders: # 可选, 检查的请求头
#- name: end-user
# value: Jason
initialDelaySeconds: 10 # 初始化时间, 健康检查延迟执行时间
timeoutSeconds: 2 # 超时时间
periodSeconds: 5 # 检测间隔
successThreshold: 1 # 检查成功为 1 次表示就绪
failureThreshold: 2 # 检测失败 2 次表示未就绪
livenessProbe: # 可选,健康检查
httpGet:
path: /index.html
port: 80
scheme: HTTP
initialDelaySeconds: 10 # 初始化时间
timeoutSeconds: 2 # 超时时间
periodSeconds: 10 # 检测间隔
successThreshold: 1 # 检查成功为 1 次表示就绪
failureThreshold: 9 # 检测失败 9 次表示未就绪

启动该pod:

1
[root@k8s-master01 pra]# kubectl create -f pod.yaml

查看pod状态:

1
2
3
4
[root@k8s-master01 pra]# kubectl get po -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
cluster-test-66bb44bd88-7kct4 1/1 Running 133 (44m ago) 17d 172.16.195.3 k8s-master03 <none> <none>
nginx 1/1 Running 0 3m42s 172.16.85.211 k8s-node01 <none> <none>

模拟容器出现故障:(进入容器,删除nginx的首页文件index.html)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
[root@k8s-master01 pra]# kubectl exec -it nginx -- sh
#nginx表示pod的名字
#没有指定容器名字,默认进入第一个容器(如果这个pod有多个容器的话)

#删除nginx首页文件
[root@k8s-master01 pra]# kubectl exec -ti nginx -c nginx-run -- /bin/sh
/ # cd /usr/share/nginx/html/

/usr/share/nginx/html # ls -l
total 8
-rw-r--r-- 1 root root 497 May 29 17:56 50x.html
-rw-r--r-- 1 root root 615 May 29 17:56 index.html
/usr/share/nginx/html # rm -rf index.html

#执行describe命令查看pod,提示Readiness probe failed: HTTP probe failed with statuscode: 404
[root@k8s-master01 pra]# kubectl describe po nginx
Warning Unhealthy 42s (x3 over 47s) kubelet Readiness probe failed: HTTP probe failed with statuscode: 404

#pod的READY0/1,STATUS还是Running,但是由于livenessProbe的配置要很长时间才会重启pod,所以此时服务一直不可用。
[root@k8s-master01 pra]# kubectl get po
NAME READY STATUS RESTARTS AGE
cluster-test-66bb44bd88-7kct4 1/1 Running 133 (57m ago) 17d
nginx 0/1 Running 0 16m


#时间过了很久,再次查看,pod才被重启,READY正常了,才能接受流量
[root@k8s-master01 pra]# kubectl get po
NAME READY STATUS RESTARTS AGE
cluster-test-66bb44bd88-7kct4 1/1 Running 134 (32s ago) 17d
nginx 1/1 Running 1 (2m38s ago) 19m

#补充知识点:进入容器内部

1
2
3
4
5
6
7
8
9
#如果想进入容器的 shell 以便进行交互式操作,可以使用以下命令:
kubectl exec -it <pod-name> -c <container-name> -- /bin/sh
# -it:表示以交互模式运行,-i 表示交互模式,-t 表示分配一个伪终端。
#<pod-name>:指定 Pod 的名称。
#-c <container-name>:指定容器的名称(如果 Pod 中有多个容器)。
#-- /bin/sh:指定要执行的命令。在大多数容器中,/bin/sh 是可用的 shell,如果容器使用的是其他 shell(如 bash),你可以相应地替换它。

#案例:如果你有一个名为 nginx 的 Pod,容器名称为 nginx-run,并且想进入 bash 环境(如果容器中安装了 bash),可以使用:
[root@k8s-master01 pra]# kubectl exec -ti nginx -c nginx-run -- /bin/sh

所以当容器启动时间很长时需要配置startupProbe:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
cat pod.yaml
#以下是pod的配置
apiVersion: v1 #apiVersion版本号
kind: Pod #指定资源的类型,告诉Kubernetes这个YAML文件创建的是一个Pod资源
metadata: #pod的元数据
labels: #标签
run: nginx-run #key=value的格式,可以根据标签筛选过滤出不同的pod
name: nginx # 指定pod的名称
spec: #用于指定期望pod的规格
restartPolicy: Always #配置重启策略为Never
containers: #定义配置容器,复数表示可以配置一个或多个容器
- image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:1.27-alpine #指定容器的镜像
name: nginx-run #指定容器的名字
ports: #可选,容器需要暴露的端口号列表
- containerPort: 80 #指定了容器内部的 Nginx 服务监听 80 端口
command: #可选,容器启动执行的命令
- sh
- -c
- sleep 30; nginx -g "daemon off;" #使用sleep 10 模拟程序启动慢
startupProbe:
tcpSocket: # 接口检测方式
port: 80
initialDelaySeconds: 10 # 初始化时间, 健康检查延迟执行时间
timeoutSeconds: 2 # 超时时间
periodSeconds: 5 # 检测间隔
successThreshold: 1 # 检查成功为 2 次表示就绪
failureThreshold: 20 # 检测失败 1 次表示未就绪
readinessProbe: # 可选,健康检查。注意三种检查方式同时只能使用一种。
httpGet: # 接口检测方式
path: /index.html # 检查路径
port: 80
scheme: HTTP # HTTP or HTTPS
#httpHeaders: # 可选, 检查的请求头
#- name: end-user
# value: Jason
initialDelaySeconds: 10 # 初始化时间, 健康检查延迟执行时间
timeoutSeconds: 2 # 超时时间
periodSeconds: 5 # 检测间隔
successThreshold: 1 # 检查成功为 2 次表示就绪
failureThreshold: 2 # 检测失败 1 次表示未就绪
livenessProbe: # 可选,健康检查
httpGet:
path: /index.html
port: 80
scheme: HTTP
initialDelaySeconds: 10 # 初始化时间
timeoutSeconds: 2 # 超时时间
periodSeconds: 5 # 检测间隔
successThreshold: 1 # 检查成功为 2 次表示就绪
failureThreshold: 2 # 检测失败 1 次表示未就绪

启动pod:

1
[root@k8s-master01 pra]# kubectl create -f pod.yaml

查看pod状体:

1
2
3
4
[root@k8s-master01 pra]# kubectl get po
NAME READY STATUS RESTARTS AGE
cluster-test-66bb44bd88-7kct4 1/1 Running 134 (19m ago) 17d
nginx 1/1 Running 0 2m49s

在次模拟pod故障,删除nginx的首页文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#进入容器删除index.html文件
[root@k8s-master01 pra]# kubectl exec -ti nginx -- /bin/sh
/ # cd /usr/share/nginx/html/
/usr/share/nginx/html # ls
50x.html index.html
/usr/share/nginx/html # rm -rf index.html

#查看pod发现很快会被重启,RESTARTS是1
[root@k8s-master01 pra]# kubectl get po
NAME READY STATUS RESTARTS AGE
cluster-test-66bb44bd88-7kct4 1/1 Running 134 (26m ago) 17d
nginx 0/1 Running 1 (35s ago) 9m16s


#容器很快被恢复READY状态1/1,可以接受流量
[root@k8s-master01 pra]# kubectl get po
NAME READY STATUS RESTARTS AGE
cluster-test-66bb44bd88-7kct4 1/1 Running 134 (29m ago) 17d
nginx 1/1 Running 1 (4m1s ago) 12m

总结:当使用的kubernetes版本>1.16,程序启动时间超过30,要配置startupProbe,而不是用livenessProbe(存活探针)和readinessProbe配置等待时间。

1.1.10postStart和preStop

在 Kubernetes 中,preStoppostStart 是容器生命周期钩子,用于在容器启动和终止时执行特定的操作。这些钩子可以帮助你在容器生命周期的关键时刻执行一些重要的任务,从而确保应用程序的平滑运行和关闭。

preStop和postStart都支持exec、httpGet、tcpSocket三种配置方式。需要注意的是这三种配置方式需要容器中有相关的命令。

创建postStart和preStop的pod:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
apiVersion: v1  #apiVersion版本号
kind: Pod #指定资源的类型,告诉Kubernetes这个YAML文件创建的是一个Pod资源
metadata: #pod的元数据
labels: #标签
run: nginx-run #key=value的格式,可以根据标签筛选过滤出不同的pod
name: nginx # 指定pod的名称
spec: #用于指定期望pod的规格
restartPolicy: Always #配置重启策略为Never
containers: #定义配置容器,复数表示可以配置一个或多个容器
- image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:1.27-alpine #指定容器的镜像
name: nginx-run #指定容器的名字
ports: #可选,容器需要暴露的端口号列表
- containerPort: 80 #指定了容器内部的 Nginx 服务监听 80 端口
# command: #可选,容器启动执行的命令
# - sh
# - -c
# - nginx -g "daemon off;" #使用sleep 10 模拟程序启动慢
lifecycle:
postStart:
exec:
command:
- sh
- -c
- mkdir /data/postStart -p
preStop:
exec:
command:
- sh
- -c
- sleep 20 #生产场景可能根据开发提供的接口配置
startupProbe:
tcpSocket: # 接口检测方式
port: 80
initialDelaySeconds: 10 # 初始化时间, 健康检查延迟执行时间
timeoutSeconds: 2 # 超时时间
periodSeconds: 5 # 检测间隔
successThreshold: 1 # 检查成功为 2 次表示就绪
failureThreshold: 2 # 检测失败 1 次表示未就绪
readinessProbe: # 可选,健康检查。注意三种检查方式同时只能使用一种。
httpGet: # 接口检测方式
path: /index.html # 检查路径
port: 80
scheme: HTTP # HTTP or HTTPS
#httpHeaders: # 可选, 检查的请求头
#- name: end-user
# value: Jason
initialDelaySeconds: 10 # 初始化时间, 健康检查延迟执行时间
timeoutSeconds: 2 # 超时时间
periodSeconds: 5 # 检测间隔
successThreshold: 1 # 检查成功为 2 次表示就绪
failureThreshold: 2 # 检测失败 1 次表示未就绪
livenessProbe: # 可选,健康检查
httpGet:
path: /index.html
port: 80
scheme: HTTP
initialDelaySeconds: 10 # 初始化时间
timeoutSeconds: 2 # 超时时间
periodSeconds: 5 # 检测间隔
successThreshold: 1 # 检查成功为 2 次表示就绪
failureThreshold: 2 # 检测失败 1 次表示未就绪

创建pod:

1
[root@k8s-master01 pra]# kubectl create -f pod.yaml

进入容器内部检查/data/postStart是否被创建:

1
2
3
4
5
6
7
8
[root@k8s-master01 pra]# kubectl exec -ti nginx -c nginx-run -- /bin/sh
/ # ls -l /data/
total 0
drwxr-xr-x 2 root root 6 Jul 13 07:04 postStart

#nginx是pod的名字
#-c 指定要进入容器的名字,这里要进入的容器是nginx-run
#/data/postStart目录已经存在

删除pod:

1
2
3
4
[root@k8s-master01 pra]# kubectl delete -f pod.yaml
pod "nginx" deleted

#删除该pod的时候前根据preStop的策略执行,比如案例中的sleep 20表示在删除该pod前等待20秒在进行删除操作

1.1.11gRPC探测(1.24版本就默认开启)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[root@k8s-master01 pra]# cat grpc-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: etcd-with-grpc
spec:
containers:
- name: etcd
image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/etcd:3.5.14
command: [ "/opt/bitnami/etcd/bin/etcd", "--data-dir", "/var/lib/etcd", "--listen-client-urls", "http://0.0.0.0:2379", "--advertise-client-urls", "http://127.0.0.1:2379", "--log-level", "debug"]
ports:
- containerPort: 2379
livenessProbe:
grpc:
port: 2379
initialDelaySeconds: 10
volumeMounts:
- name: etcd-data
mountPath: /var/lib/etcd # 将 emptyDir 挂载到容器内的 /var/lib/etcd 目录
volumes:
- name: etcd-data
emptyDir: {} # 使用 emptyDir 类型的卷,生命周期与 Pod 相同

pod启动成功后查看日志会看到请求健康检查的日志:

1
2
3
4
5
[root@k8s-master01 pra]# kubectl logs -f etcd-with-grpc
#以下是日志输出
{"level":"debug","ts":"2024-07-13T09:13:34.414727Z","caller":"v3rpc/interceptor.go:182","msg":"request stats","start time":"2024-07-13T09:13:34.414699Z","time spent":"12.948µs","remote":"192.168.0.203:55386","response type":"/grpc.health.v1.Health/Check","request count":-1,"request size":-1,"response count":-1,"response size":-1,"request content":""}
{"level":"info","ts":"2024-07-13T09:13:34.415292Z","caller":"zapgrpc/zapgrpc.go:174","msg":"[transport] [server-transport 0xc000956000] Closing: EOF"}
{"level":"info","ts":"2024-07-13T09:13:34.415466Z","caller":"zapgrpc/zapgrpc.go:174","msg":"[transport] [server-transport 0xc000956000] loopyWriter exiting with error: connection error: desc = \"transport is closing\""}