2.k8s基础-基本概念Pod
1 Pod 1.1 创建一个 Pod 定义一个 Pod 创建 Pod: 查看 Pod 状态: 使用 kubectl run 创建一个 Pod: 1.2 更改 Pod 的启动命令和参数 1.3 Pod 状态及 Pod 故障排查命令 Pending(挂起) : Pod 已被 Kubernetes 系统接
1 Pod 1.1 创建一个 Pod 定义一个 Pod 创建 Pod: 查看 Pod 状态: 使用 kubectl run 创建一个 Pod: 1.2 更改 Pod 的启动命令和参数 1.3 Pod 状态及 Pod 故障排查命令 Pending(挂起) : Pod 已被 Kubernetes 系统接
定义一个 Pod
# vim nginx.yaml
apiVersion: v1 # 必选,API 的版本号
kind: Pod # 必选,类型 Pod
metadata: # 必选,元数据
name: nginx # 必选,符合 RFC 1035 规范的 Pod 名称
spec: # 必选,用于定义 Pod 的详细信息
containers: # 必选,容器列表
- name: nginx # 必选,符合 RFC 1035 规范的容器名称
image: nginx:1.15.12 # 必选,容器所用的镜像的地址
ports: # 可选,容器需要暴露的端口号列表
- containerPort: 80 # 端口号创建 Pod:
# kubectl create -f nginx.yaml
pod/nginx created查看 Pod 状态:
# kubectl get po nginx
NAME READY STATUS RESTARTS AGE
nginx 0/1 ContainerCreating 0 20s使用 kubectl run 创建一个 Pod:
# kubectl run nginx-run --image=nginx:1.15.12Pod 已被 Kubernetes 系统接收,但仍有一个或多个容器未被创建,可以通过 kubectl describe 查看处于 Pending 状态的原因
Pod 已经被绑定到一个节点上,并且所有的容器都已经被创建,而且至少有一个 是运行状态,或者是正在启动或者重启,可以通过 kubectl logs 查看 Pod 的日志
所有容器执行成功并终止,并且不会再次重启,可以通过 kubectl logs 查看 Pod 日志
所有容器都已终止,并且至少有一个容器以失败的方式终止,也就是说这个容器 要么以非零状态退出,要么被系统终止,可以通过 logs 和 describe 查看 Pod 日 志和状态
通常是由于通信问题造成的无法获得 Pod 的状态
镜像拉取失败,一般是由于镜像不存在、网络不通或者需要登录认证引起的,可 以使用 describe 命令查看具体原因
容器启动失败,可以通过 logs 命令查看具体原因,一般为启动命令不正确,健 康检查不通过等
容器内存溢出,一般是容器的内存 Limit 设置的过小,或者程序本身有内存溢出, 可以通过 logs 查看程序启动日志
Pod 正在被删除,可以通过 describe 查看状态
Pod 自定义了内核配置,但 kubelet 没有添加内核配置或配置的内核参数不支持, 可以通过 describe 查看具体原因
容器内部主进程退出,一般计划任务执行结束会显示该状态,此时可以通过 logs 查看容器日志
Pod 正在创建,一般为正在下载镜像,或者有配置不当的地方,可以通过 describe 查具体原因
注意:Pod 的 Phase 字段只有 Pending、Running、Succeeded、Failed、Unknown,其余的为处 于上述状态的原因,可以通过 kubectl get po xxx –o yaml 查看。
通过 spec.containers[].imagePullPolicy 参数可以指定镜像的拉取策略,目前支持的策略如下:
总是拉取,当镜像 tag 为 latest 时,且 imagePullPolicy 未配置,默认为 Always
不管是否存在都不会拉取
镜像不存在时拉取镜像,如果 tag 为非 latest,且 imagePullPolicy 未配置,默认为 IfNotPresent
更改镜像拉取策略为 IfNotPresent:
可以使用 spec.restartPolicy 指定容器的重启策略
默认策略。容器失效时,自动重启该容器
容器以不为 0 的状态码终止,自动重启该容器
无论何种状态,都不会重启
指定重启策略为 Never:
Kubernetes1.16 新加的探测方式,用于判断容器内的应用程序是否已经启动。如果 配置了 startupProbe,就会先禁用其他探测,直到它成功为止。如果探测失败,Kubelet 会杀死容器,之后根据重启策略进行处理,如果探测成功,或没有配置 startupProbe, 则状态为成功,之后就不再探测。
用于探测容器是否在运行,如果探测失败,kubelet 会“杀死”容器并根据重启策略 进行相应的处理。如果未指定该探针,将默认为 Success
一般用于探测容器内的程序是否健康,即判断容器是否为就绪(Ready)状态。如 果是,则可以处理请求,反之 Endpoints Controller 将从所有的 Service 的 Endpoints 中删除此容器所在 Pod 的 IP 地址。如果未指定,将默认为 Success
在容器内执行一个指定的命令,如果命令返回值为 0,则认为容器健康
通过 TCP 连接检查容器指定的端口,如果端口开放,则认为容器健康
对指定的 URL 进行 Get 请求,如果状态码在 200~400 之间,则认为容器健康
为什么要配置健康检查?
Kubernetes 中 Pod 是最小的计算单元,而一个 Pod 又由多个容器组成,相当于每个容器就是一个应用,应用在运行期间,可能因为某些意外情况致使程序挂掉。那么如何监控这些容器状态稳定性,保证服务在运行期间不会发生问题,发生问题后进行重启等机制,就成为了重中之重的事情,考虑到这点 kubernetes 推出了活性探针机制。有了存活性探针能保证程序在运行中如果挂掉能够自动重启,但是还有个经常遇到的问题,比如说,在Kubernetes 中启动Pod,显示明明Pod已经启动成功,且能访问里面的端口,但是却返回错误信息。还有就是在执行滚动更新时候,总会出现一段时间,Pod对外提供网络访问,但是访问却发生404,这两个原因,都是因为Pod已经成功启动,但是Pod容器中应用程序还在启动中导致的,考虑到这点Kubernetes推出了就绪性探针机制。
首先 创建一个没有探针的 Pod:
配置健康检查:
livenessProbe
exec
httpGet
tcpSocket
readinessProbe
exec
httpGet
tcpSocket
pod生命周期
pod从开始创建到终止退出的时间范围称为Pod生命周期1
生命周期包含以下几个重要流程
初始化容器(initContainers)
创建主容器(containers)是必须的操作
容器启动后钩子
pod在整个生命周期的过程中总会处于以下几个状态:
Pending:创建了pod资源并存入etcd中,但尚未完成调度。
ContainerCreating:Pod 的调度完成,被分配到指定 Node 上。处于容器创建的过程中。通常是在拉取镜像的过程中。
pod生命周期的重要行为
容器的重启策略
定义是否重启Pod对象
Always:但凡Pod对象终止就重启,默认设置
OnFailure:仅在Pod出现错误时才重启
Never:从不
注:一旦Pod绑定到一个节点上,就不会被重新绑定到另一个节点上,要么重启,要么终止pod的终止过程终止过程主要分为如下几个步骤
初始化容器(init)
spec字段下有个initContainers字段(初始化容器),Init容器就是做初始化工作的容器。可以有一个或多个,如果多个按照定义的顺序依次执行,先执行初始化容器1,再执行初始化容器2等,等初始化容器执行完具体操作之后初始化容器就退出了,只有所有的初始化容器执行完后,主容器才启动。
由于一个Pod里容器存储卷是共享的,所以Init Container里产生的数据可以被主容器使用到,Init Container可以在多种K8S资源里被使用到,如Deployment、DaemonSet, StatefulSet、Job等,但都是在Pod启动时,在主容器启动前执行,做初始化工作。
https://link.zhihu.com/?target=https%3A//kubernetes.io/docs/concepts/workloads/pods/init-containers/%23init-containers-in-use初始化容器与主容器区别是
1、初始化容器不支持 Readinessprobe,因为它们必须在Pod就绪之前运行完成
2、每个Init容器必须运行成功,下一个才能够运行初始化容器应用
创建pod并查看pod
测试pod
主容器
1、容器钩子
初始化容器启动之后,开始启动主容器,在主容器启动之后有一个post start hook(容器启动后钩子)和pre stop hook(容器结束前钩子),无论启动后还是结束前所做的事我们可以把它放到这两个钩子,这个钩子就表示用户可以用它来钩住一些命令,非必须选项容器钩子:postStart和preStop
postStart:容器创建之后立刻执行,用于资源部署、环境准备等。 preStop:在容器被终止前执行,用于优雅关闭应用程序、通知其他系统等
postStart和preStop用法
测试启动和停止钩子
查看pod
优雅的删除资源对象
当用户请求删除含有pod的资源对象时(如RC、deployment等),K8S为了让应用程序优雅关闭(即让应用程序完成正在处理的请求后,再关闭软件),K8S提供两种信息通知:
总结:
pod在整个生命周期中有非常多的用户行为:
1、初始化容器完成初始化
2、主容器启动后可以做启动后钩子
3、主容器结束前可以做结束前钩子
4、在主容器运行中可以做一些健康检测,如startupprobe、livenessprobe,readnessprobe
# vim nginx.yaml
apiVersion: v1 # 必选,API 的版本号
kind: Pod # 必选,类型 Pod
metadata: # 必选,元数据
name: nginx # 必选,符合 RFC 1035 规范的 Pod 名称
spec: # 必选,用于定义 Pod 的详细信息
containers: # 必选,容器列表
- name: nginx # 必选,符合 RFC 1035 规范的容器名称
image: nginx:1.15.12 # 必选,容器所用的镜像的地址
command: # 可选,容器启动执行的命令
- sleep
- "10"
ports: # 可选,容器需要暴露的端口号列表
- containerPort: 80 # 端口号# vim nginx.yaml
apiVersion: v1 # 必选,API 的版本号
kind: Pod # 必选,类型 Pod
metadata: # 必选,元数据
name: nginx # 必选,符合 RFC 1035 规范的 Pod 名称
spec: # 必选,用于定义 Pod 的详细信息
containers: # 必选,容器列表
- name: nginx # 必选,符合 RFC 1035 规范的容器名称
image: nginx:1.15.12 # 必选,容器所用的镜像的地址
imagePullPolicy: IfNotPresent # 可选,镜像拉取策略
ports: # 可选,容器需要暴露的端口号列表
- containerPort: 80 # 端口号apiVersion: v1 # 必选,API 的版本号
kind: Pod # 必选,类型 Pod
metadata: # 必选,元数据
name: nginx # 必选,符合 RFC 1035 规范的 Pod 名称
spec: # 必选,用于定义 Pod 的详细信息
containers: # 必选,容器列表
- name: nginx # 必选,符合 RFC 1035 规范的容器名称
image: nginx:1.15.12 # 必选,容器所用的镜像的地址
imagePullPolicy: IfNotPresent
command: # 可选,容器启动执行的命令
- sleep
- "10"
ports: # 可选,容器需要暴露的端口号列表
- containerPort: 80 # 端口号
restartPolicy: Never
探针主要字段解析:
(initialDelaySeconds: 5):初始化延迟时间,主要是告诉kubelet,容器启动需要的时间,当过了这个时间再进行探测,要不然容器可能还没启动就会删除了。
(periodSeconds: 5):探测周期间隔时间,主要是指定kubelet对容器进行探针的时间周期,也就是第一次探测结束后,等待多少时间后对容器进行探测。默认值为10秒,最小值为1秒。
(timeoutSeconds: 5):单次探测超时时间,指定kubelet对容器探测的最大时间,超过这个时间证明容器探测失败。默认为1秒,最小为1秒。
(successThreshold: 5):探测失败到成功的重试次数,当kubelet对某个容器第一次探测失败后,重新进行探测的次数,比如指定为1,那么就会直接将容器删除。如果使用的探针是livenessProbe,那么只能配置为1,最小值为1次。
(failureThreshold: 5):探测成功到失败的重试次数,当kubelet对某个容器进行探测过程中,允许失败的次数,当用于readinessProbe探针,默认是3次,最小值为1次。也就是说当3次探测失败后,容器会被删除。当用于startupProbe探针,如果还设置了periodSeconds时间,那么等待容器启动的时间为failureThreshold的时间乘以periodSeconds时间的值,在这段时间内,容器没有启动,那么就会删除容器。apiVersion: v1 # 必选,API 的版本号
kind: Pod # 必选,类型 Pod
metadata: # 必选,元数据
name: nginx # 必选,符合 RFC 1035 规范的 Pod 名称
spec: # 必选,用于定义 Pod 的详细信息
containers: # 必选,容器列表
- name: nginx # 必选,符合 RFC 1035 规范的容器名称
image: nginx:1.15.12 # 必选,容器所用的镜像的地址
imagePullPolicy: IfNotPresent
command: # 可选,容器启动执行的命令
- sh
- -c
- sleep 10; nginx -g "daemon off;"
ports: # 可选,容器需要暴露的端口号列表
- containerPort: 80 # 端口号
restartPolicy: Never
[root@k8s-master01 ~/hhh]#kubectl get pod nginx -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx 1/1 Running 0 3s 10.200.135.150 node-03 <none> <none>
[root@k8s-master01 ~/hhh]#curl 10.200.135.150
curl: (7) Failed to connect to 10.200.135.150 port 80 after 0 ms: Connection refused
如果不配置建康检查的话会出现:1.容器running ,端口访问失败apiVersion: v1 # 必选,API 的版本号
kind: Pod # 必选,类型 Pod
metadata: # 必选,元数据
name: nginx # 必选,符合 RFC 1035 规范的 Pod 名称
spec: # 必选,用于定义 Pod 的详细信息
containers: # 必选,容器列表
- name: nginx # 必选,符合 RFC 1035 规范的容器名称
image: nginx:1.15.12 # 必选,容器所用的镜像的地址
imagePullPolicy: IfNotPresent
command: # 可选,容器启动执行的命令
- sh
- -c
- sleep 30; nginx -g "daemon off;"
startupProbe:
tcpSocket: # 端口检测方式
port: 80
initialDelaySeconds: 10 # 初始化时间
timeoutSeconds: 2 # 超时时间
periodSeconds: 5 # 检测间隔
successThreshold: 1 # 检查成功为 2 次表示就绪
failureThreshold: 5 # 检测失败 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: # 可选,健康检查
exec: # 端口检测方式
command:
- sh
- -c
- pgrep nginx
initialDelaySeconds: 10 # 初始化时间
timeoutSeconds: 2 # 超时时间
periodSeconds: 5 # 检测间隔
successThreshold: 1 # 检查成功为 2 次表示就绪
failureThreshold: 2 # 检测失败 1 次表示未就绪
ports: # 可选,容器需要暴露的端口号列表
- containerPort: 80 # 端口号
restartPolicy: NeverapiVersion: v1 # 必选,API 的版本号
kind: Pod # 必选,类型 Pod
metadata: # 必选,元数据
name: nginx # 必选,符合 RFC 1035 规范的 Pod 名称
spec: # 必选,用于定义 Pod 的详细信息
containers: # 必选,容器列表
- name: nginx # 必选,符合 RFC 1035 规范的容器名称
image: nginx:1.15.12 # 必选,容器所用的镜像的地址
imagePullPolicy: IfNotPresent
command: # 可选,容器启动执行的命令
- sh
- -c
- sleep 30; nginx -g "daemon off;"
startupProbe:
tcpSocket: # 端口检测方式
port: 80
initialDelaySeconds: 10 # 初始化时间
timeoutSeconds: 2 # 超时时间
periodSeconds: 5 # 检测间隔
successThreshold: 1 # 检查成功为 2 次表示就绪
failureThreshold: 5 # 检测失败 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: # 可选,健康检查
exec: # 端口检测方式
command:
- sh
- -c
- pgrep nginx
initialDelaySeconds: 10 # 初始化时间
timeoutSeconds: 2 # 超时时间
periodSeconds: 5 # 检测间隔
successThreshold: 1 # 检查成功为 2 次表示就绪
failureThreshold: 2 # 检测失败 1 次表示未就绪
ports: # 可选,容器需要暴露的端口号列表
- containerPort: 80 # 端口号
restartPolicy: NeverapiVersion: v1 # 必选,API 的版本号
kind: Pod # 必选,类型 Pod
metadata: # 必选,元数据
name: nginx # 必选,符合 RFC 1035 规范的 Pod 名称
spec: # 必选,用于定义 Pod 的详细信息
containers: # 必选,容器列表
- name: nginx # 必选,符合 RFC 1035 规范的容器名称
image: nginx:1.15.12 # 必选,容器所用的镜像的地址
imagePullPolicy: IfNotPresent
lifecycle:
postStart: # 容器创建完成后执行的指令, 可以是 exec httpGet TCPSocket
exec:
command:
- sh
- -c
- 'mkdir /data/'
preStop:
exec:
command:
- sh
- -c
- sleep 10
ports: # 可选,容器需要暴露的端口号列表
- containerPort: 80 # 端口号
restartPolicy: Never
apiVersion: v1
kind: Pod
metadata:
name: etcd-with-grpc
spec:
containers:
- name: etcd
image: registry.cnhangzhou.aliyuncs.com/google_containers/etcd:3.5.1-0
command: [ "/usr/local/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: 10cat nginx.yml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx
name: nginx-deployment
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: docker.io/library/nginx:1.18.0-alpine
livenessProbe:
exec: #定义探测方式
command: #不断查看文件是否存在,文件必须是镜像原本存在的文件
- cat
- /usr/share/nginx/html/index.html
initialDelaySeconds: 5 #指定探针多少秒后启动
periodSeconds: 5 #指定探针探测周期时
[root@k8s-master01 ~/hhh]#kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-deployment-54755cb57c-fd4vx 1/1 Running 0 30s
连接容器
[root@k8s-master01 ~/hhh]#kubectl exec -it nginx-deployment-54755cb57c-fd4vx /bin/sh
/ # cd /usr/share/nginx/html/
/usr/share/nginx/html # ls
50x.html index.html
/usr/share/nginx/html # mv index.html index1.html #删除文件,这样探针就会被触发
/usr/share/nginx/html # exit
再次查看 证明容器重启过了
[root@k8s-master01 ~/hhh]#kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-deployment-54755cb57c-fd4vx 1/1 Running 1 (3s ago) 2m4s
[root@k8s-master01 ~/hhh]#kubectl exec -it nginx-deployment-54755cb57c-fd4vx /bin/sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # cd /usr/share/nginx/html/
/usr/share/nginx/html # ls
50x.html index.html
可以看到文件又存在了,证明容器被重建了cat nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx
name: nginx-deployment
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: docker.io/library/nginx:1.18.0-alpine
livenessProbe:
httpGet: #指定探针探测方式
path: /index.html #定义请求的URL
port: 80 #定义GET的端口
initialDelaySeconds: 3 #指定探针多少秒后启动
periodSeconds: 3 #指定探针的探测周期
kubectl apply -f nginx.yaml 创建容器
kubectl get pod 查看状态
[root@k8s-master01 ~/hhh]#kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-deployment-f7b4dcd5d-jnv2f 1/1 Running 0 21s
kubectl exec -it nginx-deployment-f7b4dcd5d-jnv2f /bin/sh 连接容器
cd /usr/share/nginx/html/ 进入目录,可以看到文件存在
ls
mv index.html index1.html 删除文件,这样探针就会被触发
ls
kubectl get pod 可以看到RESTARTS变成了1,证明容器重启过了
root@k8s-master01:~# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-deployment-f7b4dcd5d-jnv2f 1/1 Running 1 (19s ago) 107s
root@k8s-master01:~# kubectl exec -it nginx-deployment-f7b4dcd5d-jnv2f /bin/sh 再次连接容器
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # cd /usr/share/nginx/html/
/usr/share/nginx/html # ls
50x.html index.html
cd /usr/share/nginx/html/ 可以看到文件又存在了,证明容器被重建了。
ls
cat nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx
name: nginx-deployment
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: docker.io/library/nginx:1.18.0-alpine
ports:
- containerPort: 80
livenessProbe: #指定探针
tcpSocket: #指定探针探测方式
port: 80
initialDelaySeconds: 5
periodSeconds: 5
kubectl apply -f nginx.yaml 创建容器
kubectl get pod 查看pod
kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-deployment-f7b4dcd5d-jnv2f 1/1 Running 1 (5m21s ago) 6m49s
kubectl exec -it nginx-deployment-f7b4dcd5d-jnv2f /bin/sh 连接容器
vi /etc/nginx/conf.d/default.conf 修改配置文件
server {
listen 8080; #把80都改为8080
listen [::]:8080;
nginx -s reload 重新加载配置文件
kubectl get pod 查看pod,可以看到RESTARTS,证明容器重启过
root@k8s-master01:~/hhh# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-deployment-847f9655b6-htxtj 1/1 Running 1 (3s ago) 93s
kubectl exec -it nginx-deployment-f7b4dcd5d-jnv2f /bin/sh 连接容器
head -n 10 /etc/nginx/conf.d/default.conf 可以看到配置被还原了,证明容器重建了
/ # head -n 10 /etc/nginx/conf.d/default.conf
server {
listen 80;
listen [::]:80;
server_name localhost;
#charset koi8-r;
#access_log /var/log/nginx/host.access.log main;
location / {
root /usr/share/nginx/html;
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx
name: nginx
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: docker.io/library/nginx:1.18.0-alpine
ports
cat nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx
name: nginx
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: docker.io/library/nginx:1.18.0-alpine
cat nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx
name: nginx
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: docker.io/library/nginx:1.18.0-alpine
ports:
- containerPort: 80
readinessProbe: #指定探针
tcpSocket: #指定探测方式
port: 80
initialDelaySeconds: 5
periodSeconds: 5
---
apiVersion: v1
kind: Service
metadata:
labels:
svc: nginx-svc-nodeport
name: nginx-svc-nodeport
spec:
type: NodePort
ports:
- port: 80
targetPort: 80
nodePort: 30080
selector:
app: nginx
kubectl apply -f nginx.yaml创建容器
root@k8s-master01:~/hhh# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-6564d4996b-sn7l6 1/1 Running 0 11s 10.200.135.158 node-03 <none> <none>
curl -I http://10.200.135.158 和上面一样,访问网站成功
root@k8s-master01:~/hhh# curl -I http://10.200.135.158
HTTP/1.1 200 OK
Server: nginx/1.18.0
Date: Fri, 10 Nov 2023 08:44:49 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Thu, 29 Oct 2020 15:23:06 GMT
Connection: keep-alive
ETag: "5f9ade5a-264"
Accept-Ranges: bytes
kubectl get pod -A 查看pod
kubectl exec -it nginx-6564d4996b-sn7l6 /bin/sh 连接容器
vi /etc/nginx/conf.d/default.conf 修改配置文件
server {
listen 8080; #把80都改为8080
listen [::]:8080;
nginx -s reload 重新加载配置文件
kubectl get pod -A 可以看到READY变成了0/1,证明探针被触发了,容器没有被删除,也没有重建
curl -I http://10.200.135.158 可以看到因为探针触发,外网是访问不了容器了
0
root@k8s-master01:~/hhh# kubectl describe svc nginx-svc-nodeport
Name: nginx-svc-nodeport
Namespace: default
Labels: svc=nginx-svc-nodeport
Annotations: <none>
Selector: app=nginx
Type: NodePort
IP Family Policy: SingleStack
IP Families: IPv4
IP: 10.100.199.90
IPs: 10.100.199.90
Port: <unset> 80/TCP
TargetPort: 80/TCP
NodePort: <unset> 30089/TCP
Endpoints:
Session Affinity: None
External Traffic Policy: Cluster
Events: <none>
可以看到Endpoints没有值,证明探针把service和pod解除绑定了
1、在启动任何容器之前,先创建pause基础容器,它初始化Pod的环境并为后续加⼊的容器提供共享的名称空间。
2.初始化容器(initcontainer):
一个pod可以拥有任意数量的init容器。init容器是按照顺序以此执行的,并且仅当最后一个init容器执行完毕才会去启动主容器。
3.生命周期钩子:
pod允许定义两种类型的生命周期钩子,启动后(post-start)钩子和停止前(pre-stop)钩子
这些生命周期钩子是基于每个容器来指定的,和init容器不同的是,init容器是应用到整个pod。而这些钩子是针对容器的,是在容器启动后和停止前执行的。
4.容器探测:
对Pod健康状态诊断。分为三种: Startupprobe、Livenessprobe(存活性探测), Readinessprobe(就绪性检测)
Startup(启动探测):探测容器是否正常运行
Liveness(存活性探测):判断容器是否处于runnning状态,根据重启策略决定是否重启容器
Readiness(就绪性检测):判断容器是否准备就绪并对外提供服务,将容器设置为不可用,不接受service转发的请求
三种探针用于Pod检测:
ExecAction:在容器中执行一个命令,并根据返回的状态码进行诊断,只有返回0为成功
TCPSocketAction:通过与容器的某TCP端口尝试建立连接
HTTPGetAction:通过向容器IP地址的某指定端口的path发起HTTP GET请求(1)用户发出删除 pod 命令:kubectl delete pods ,kubectl delete -f yaml
(2)Pod 对象随着时间的推移更新,在宽限期(默认情况下30秒),pod 被视为“dead”状态
(3)将 pod 标记为“Terminating”状态
(4)第三步同时运行,监控到 pod 对象为“Terminating”状态的同时启动 pod 关闭过程
(5)第三步同时进行,endpoints 控制器监控到 pod 对象关闭,将pod与service匹配的 endpoints 列表中删除
(6)如果 pod 中定义了 preStop 钩子处理程序,则 pod 被标记为“Terminating”状态时以同步的方式启动执行;若宽限期结束后,preStop 仍未执行结束,第二步会重新执行并额外获得一个2秒的小宽限期
(7)Pod 内对象的容器收到 TERM 信号
(8)宽限期结束之后,若存在任何一个运行的进程,pod 会收到 SIGKILL 信号
(9)Kubelet 请求 API Server 将此 Pod 资源宽限期设置为0从而完成删除操作cat init1.yaml
apiVersion: v1
kind: Pod
metadata:
name: init-busybox
labels:
app: init-busybox
spec:
initContainers:
- name: install
image: busybox
imagePullPolicy: IfNotPresent
command:
- wget
- "-O"
- "/tmp/index.html"
- "https://www.baidu.com"
volumeMounts:
- name: workdir
mountPath: /tmp
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
volumeMounts:
- name: workdir
mountPath: /usr/share/nginx/html
dnsPolicy: Default
volumes:
- name: workdir
emptyDir: {}[root@k8s-master01 ~/hhh]#kubectl apply -f init1.yaml
[root@k8s-master01 ~/hhh]#kubectl get pod init-busybox -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
init-busybox 1/1 Running 0 88s 10.200.135.165 node-03 <none> <none>
[root@k8s-master01 ~/hhh]#curl 10.200.135.165
<!DOCTYPE html>
<!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link rel=stylesheet type=text/css href=https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/bdorz/baidu.min.css><title>百度一下,你就知道...</title></head> <body src=//www.baidu.com/img/gs.gif> </p> </div> </div> </div> </body> </html
kubectl exec -it init-busybox /bin/bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
Defaulted container "nginx" out of: nginx, install (init)
root@init-busybox:/# ls
bin dev docker-entrypoint.sh home lib64 mnt proc run srv tmp var
boot docker-entrypoint.d etc lib media opt root sbin sys usr
root@init-busybox:/# cd /usr/share/nginx
root@init-busybox:/usr/share/nginx# ls
html
root@init-busybox:/usr/share/nginx# cd html
root@init-busybox:/usr/share/nginx/html# ls
index.html......
containers:
- image: sample:v2
name: war
lifecycle:
postStart:
exec:
command:
- “cp”
- “/sample.war”
- “/app”
prestop:
httpGet:
host: monitor.com
path: /waring
port: 8080
scheme: HTTP
......
#以上示例中,定义了一个Pod,包含一个JAVA的web应用容器,其中设置了PostStart和PreStop回调函数。即在容器创建成功后,复制/sample.war到/app文件夹中。而在容器终止之前,发送HTTP请求到http://monitor.com:8080/waring,即向监控系统发送警告。cat >pre-start.yaml<<EOF
apiVersion: v1
kind: Pod
metadata:
name: pre-start-demo1
labels:
app: pre-start-demo1
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
lifecycle:
postStart:
exec:
command: ["/bin/bash","-c", "echo 'test' >/usr/share/nginx/html/index.html"]
preStop:
exec:
command: ["/bin/bash","-c","nginx -s stop"]
ports:
- containerPort: 80
name: http
EOF[root@k8s-master01 ~/hhh]#kubectl get pod pre-start-demo1 -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pre-start-demo1 1/1 Running 0 88s 10.200.58.208 node-02 <none> <none>
[root@k8s-master01 ~/hhh]#curl 10.200.58.208
test
1)、默认:K8S通知node执行docker stop命令,docker会先向容器中PID为1的进程发送系统信号SIGTERM,然后等待容器中的应用程序终止执行,如果等待时间达到设定的超时时间,或者默认超时时间(30s),会继续发送SIGKILL的系统信号强行kill掉进程。
2)、使用pod生命周期(利用PreStop回调函数),它执行在发送终止信号之前。
默认情况下,所有的删除操作的优雅退出时间都在30秒以内。kubectl delete命令支持--grace-period=的选项,以运行用户来修改默认值。0表示删除立即执行,并且立即从API中删除pod。在节点上,被设置了立即结束的的pod,仍然会给一个很短的优雅退出时间段,才会开始被强制杀死。如下:
......
spec:
containers:
- name: nginx-demo
image: centos:nginx
lifecycle:
preStop:
exec:
# nginx -s quit gracefully terminate while SIGTERM triggers a quick exit
command: ["/usr/local/nginx/sbin/nginx","-s","quit"]
ports:
- name: http
containerPort: 80
......