pod组成:
Pod是kubernetes最重要的基本概念,每一个pod都有一个一个称之为根容器的Pause容器,除了Pause容器,每个pod还包含一个或多个紧密相关的用户业务容器。
pod组成示意图:
Pause容器介绍:
Pause 容器,又叫 Infra 容器,是pod的基础容器,镜像体积只有几百KB 左右,配置在kubelet中,主要的功能是一个pod中多个容器的网络通信。
Infra 容器被创建后会初始化 Network Namespace,之后其它容器就可以加入到 Infra 容器中共享Infra 容器的网络了,主要特点有:
- pod中容器之间通过localhost直接通信。
- pod删除后,Pause创建的ip地址也将被回收。
- Pause容器的状态代表整个容器组的状态。
- pod里的多个业务容器共享Pasue容器的IP,共享Pause容器挂载的Volume
Pause容器共享的Namespace:
1.NET Namespace:Pod中的多个容器共享同一个网络命名空间,即使用相同的IP和端口信息。
2.IPC Namespace:Pod中的多个容器可以使用System V IPC或POSIX消息队列进行通信。其中 System V IPC 对象包含共享内存、信号量和消息队列
3.UTS Namespace:pod中的多个容器共享一个主机名。
注意:MNT Namespace【文件系统的隔离】、PID Namespace、User Namespace未共享。
Init容器介绍:
init容器的作用:
- 可以为业务容器提前准备好业务容器的运行环境,比如将业务容器需要的配置文件提前生成并放在指定位置、检查数据权限或完整性、软件版本等基础运行环境。
- 可以在运行业务容器之前准备好需要的业务数据,比如从OSS下载、或者从其它位置copy。
- 检查依赖的服务是否能够访问。
init容器的特点:
- 一个pod可以有多个业务容器还能在有多个init容器,但是每个init容器和业务容器的运行环境都是隔离的。
- init容器会比业务容器先启动。
- init容器运行成功之后才会继续运行业务容器。
- 如果一个pod有多个init容器,则需要从上到下逐个运行并且全部成功,最后才会运行业务容器。
- init容器不支持探针检测(因为初始化完成后就退出再也不运行了)。
Pod生命周期探针介绍:
pod的生命周期,当一个容器启动后,Kubernetes 将立即发送 postStart 事件;运行期间可以配置livenessProbe和readinessProbe检查,在容器被终结之前, Kubernetes 将发送一个 preStop 事件。容器可以为每个事件指定一个处理程序。
探针简介:
探针是由 kubelet 对容器执行的定期诊断,以保证Pod的状态始终处于运行状态,要执行诊断,kubelet 调用由容器实现的Handler(处理程序),也称为Hook(钩子),有三种类型的处理程序:
ExecAction:
在容器内执行指定命令,如果命令退出时返回码为0则认为诊断成功。
TCPSocketAction:
对指定端口上的容器的IP地址进行TCP检查,如果端口打开,则诊断被认为是成功的。
HTTPGetAction:
对指定的端口和路径上的容器的IP地址执行HTTPGet请求,如果响应的状态码大于等于200且小于 400,则诊断被认为是成功的。
Pod重启策略:
Pod一旦配置了探针,在检测失败的时候,会依旧重启策略对pod执行操作
restartPolicy【容器重启策略】:
Always: 当容器异常时,k8s会自动重启该容器,通过控制器来实现,默认为always。
OnFailure: 当容器失败时【容器停止运行且退出码不为0】,k8s自动重启该容器。
Never: 无论容器处于那种运行状态,都不会对该容器重启,一般Job或CronJob使用此种重启策略。
imagePullPolicy【镜像拉取策略】:
IfNotPresent: node节点上没有此镜像就去指定的仓库拉取,如果node节点上有就使用本地的镜像。
Always:pod重建时总是从仓库中拉取镜像,即使本地有该镜像。
Never: 从来不到镜像仓库中拉取镜像,只使用本地镜像。
探针类型:
startupProbe【启动探针】:
kubernetes v1.16引入
判断容器内的应用程序是否已启动完成,如果配置了启动探测,则会先禁用所有其它的探测,直到startupProbe检测成功为止,如果startupProbe探测失败,则kubelet将杀死容器,容器将按照重启策略进行下一步操作,如果容器没有提供启动探测,则默认状态为成功。
livenessProbe【存活探针】:
检测容器容器是否正在运行,如果存活探测失败,则kubelet会杀死容器,并且容器将受到其重启策略的影响,如果容器不提供存活探针,则默认状态为 Success,livenessProbe用于控制是否重启pod。
readinessProbe【就绪探针】:
如果就绪探测失败,端点控制器将从与Pod匹配的所有Service的端点中(endpoint)删除该Pod的IP地址,初始延迟之前的就绪状态默认为Failure(失败),如果容器不提供就绪探针,则默认状态为 Success,readinessProbe用于控制pod是否添加至service。
探针通用参数配置
参数名称 | 参数描述 |
---|---|
initialDelaySeconds: 120 | 初始化延迟时间,告诉kubelet在执行第一次探测前应该等待多少秒,默认是0秒,最小值是0 |
periodSeconds: 60 | 探测周期间隔时间,指定了kubelet应该每多少秒秒执行一次存活探测,默认是 10 秒。最小值是 1 |
timeoutSeconds: 5 | 单次探测超时时间,探测的超时后等待多少秒,默认值是1秒,最小值是1。 |
successThreshold: 1 | 从失败转为成功的重试次数,探测器在失败后,被视为成功的最小连续成功数,默认值是1,存活探测的这个值必须是1,最小值是 1。 |
failureThreshold: 3 | 从成功转为失败的重试次数,当Pod启动了并且探测到失败,Kubernetes的重试次数,存活探测情况下的放弃就意味着重新启动容器,就绪探测情况下的放弃Pod 会被打上未就绪的标签,默认值是3,最小值是1。 |
pod终止流程
创建pod:
- 完成调度流程
- 启动postStart事件
- startupProble启动探测
- livenessProble存活探测
- 状态为running
- readinessProbe就绪探测
- service关联pod
- 加入service的endpoint中
- 接受客户端请求
删除pod:
- pod状态由running状态变为Terminating状态,从service的endpoint中移除该podIP,次pod不在接受客户端请求
- 执行preStop事件
- k8s向pod中容器发送SIGTERM信号终止pod里面的主进程,这个信号让容器知道自己很快要关闭
- terminationGracePeriodSeconds:60 可选终止等待期,如果有设置删除宽限时间,则等待宽限时间到期,否则最多等待30s,k8s等待指定的时间称为优雅终止宽限期,默认情况下是30秒,值得注意的是等待期与preStop Hook和SIGTERM信号并行执行,即k8s可能不会等待preStop Hook完成(最长30秒之后主进程还没有结束就就强制终止pod)。
- SIGKILL信号被发送到Pod,并删除Pod
实战案例
创建configmap
kubectl create configmap nginx-config --from-file=mysite.conf
创建pvc,采用storageclass动态创建pv
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: nginx-pv-claim
namespace: application
spec:
storageClassName: managed-nfs-storage #调用的storageclass 名称
accessModes:
- ReadWriteMany #访问权限
resources:
requests:
storage: 500Mi #空间大小
创建工作负载pod
apiVersion: apps/v1
kind: Deployment
metadata:
name: application-nginx
namespace: application
spec:
replicas: 2
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
selector:
matchLabels:
app: aplication-nginx
template:
metadata:
labels:
app: aplication-nginx
spec:
terminationGracePeriodSeconds: 60
restartPolicy: Always
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- application-nginx
topologyKey: kubernetes.io/hostname
weight: 100
volumes:
- name: nginx-pv-storage
persistentVolumeClaim:
claimName: nginx-pv-claim
- name: nginx-config
configMap:
name: nginx-config
- name: workdir
emptyDir: {}
initContainers:
- name: install
image: busybox:1.28
command:
- wget
- "-O"
- "/work-dir/index.html"
- http://info.cern.ch
volumeMounts:
- name: workdir
mountPath: "/work-dir"
containers:
- name: aplication-nginx
image: nginx:1.20.2
ports:
- containerPort: 80
imagePullPolicy: IfNotPresent
lifecycle:
postStart:
exec:
command: ["/bin/sh", "-c", "echo Hello from the postStart handler > /usr/share/message"]
preStop:
exec:
command: ["/bin/sh","-c","nginx -s quit; while killall -0 nginx; do sleep 1; done"]
env:
- name: username
value: "zhangjw"
volumeMounts:
- name: nginx-pv-storage
mountPath: "/usr/share/nginx/html/myapp"
- name: nginx-config
mountPath: /etc/nginx/conf.d
- name: workdir
mountPath: /usr/share/nginx/html
resources:
requests:
memory: "256Mi"
cpu: "500m"
limits:
memory: "512Mi"
cpu: "1000m"
startupProbe:
httpGet:
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: application-nginx-service
namespace: application
spec:
ports:
- name: http
port: 81
targetPort: 80
nodePort: 40013
protocol: TCP
type: NodePort
selector:
app: aplication-nginx