这是我参与更文挑战的第5天,活动详情查看:
本文已参与 周末学习计划,点击查看详情
步骤
1 首先kubectl和api server交互,然后到etcd,再到对应node的kubelet
2 然后kubelet和node上的CRI,也就是docker交互,开始图中得初始化流程
3 首先创建好pod内容器公用得pause网络栈,然后进行一系列得Init C流程
4 初始化工作完成后每个容器都会有自己的start初始化脚本要跑
5 可以设定一个探针,在初始化脚本一段时间后检测容器是否可提供服务,如果可以提供服务显示为running状态。也就是上面得readiness状态
6 同时还有另一个探针,不停检测容器是否有异常,并根据restartPolicy决定是否要重启。也就是上面得Liveness状态
7 最后在销毁容器之前,还可以运行一段结尾的stop脚本
下面我们就用实例对这些流程一个个的深入了解一下。这一节先看看第一个步骤Init C。
Init C
Init C是专门用作初始化的容器,其具有如下两个特点:
Init容器总是运行到成功退出为止,如果Init容器失败,k8s会不停重启该Pod,直到成功为止
每个Init容器必须在上一个Init容器成功完成后才能运行
注意,如果restartPolicy是never的话,Init容器失败不会重新启动。
因为Init是区别于业务容器的单独容器,所以其可以完成如下工作:
可以安装某些可以被业务容器使用的工具,这些工具如果封装在业务镜像中会增加业务镜像的冗余
对业务容器的代码进行分离为创建和部署两阶段,将创建阶段放入Init容器中
Init容器属于Linux命名空间,相对业务容器具有更高的文件系统权限,例如Secret权限。敏感文件处理在Init阶段完成使得业务容器安全性更高
针对某些有严重顺序依赖的两个Pod来说,可以再需要后启动的Pod的Init中去做判断,一直等到先启动的Pod成功完成,再退出Init,启动后一个Pod
说了这么多,下面来实际上手操作看看。
Init容器实际操作
下面创建一个带Init容器的yaml配置文件test-init-main.yaml如下
apiVersion: v1
kind: Pod
metadata:
name: test-init-main
labels:
app: myapp
version: v1
spec:
containers:
- name: my-busybox
image: busybox
command: ['sh','-c','echo Main app is running && sleep 3600']
initContainers:
- name: init-myservice
image: busybox
command: ['sh','-c','until nslookup myservice; do echo waiting for myservice; sleep 2; done;']
- name: init-mydb
image: busybox
command: ['sh','-c','until nslookup mydb; do echo waiting for mydb; sleep 2; done;']
复制代码
busybox是用在嵌入式中的轻量级linux系统,这里用busybox做为容器的镜像。containers下配置了一个主容器,功能只是启动后会打印一条记录,因为是从字符串获取shell命令,所以这里要用-c选项。initContainers下配置了两个Init容器,分别是等待myservice和mydb这两个服务起来后退出Init。service起来后,coreDNS里面就会有对应的解析IP,其余pod进行域名解析的话会自动获取到
运行kubectl apply -f test-init-main.yaml可以看到容器停在了Init阶段,并且两个Init容器只完成了0个
[root@k8s-master k8s-test]# kubectl apply -f test-init-main.yaml
pod/test-init-main created
[root@k8s-master k8s-test]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
curl-6bf6db5c4f-kljp4 1/1 Running 1 40h 10.244.1.2 k8s-node1 <none> <none>
hellok8s 2/2 Running 0 21h 10.244.1.6 k8s-node1 <none> <none>
test-init-main 0/1 Init:0/2 0 12s 10.244.1.8 k8s-node1 <none> <none>
复制代码
可以看到init-myservice这个Init容器还处于running状态,所以无法向下继续。
这时候我们通过yaml文件test-init-myservice.yaml去创建一个叫myservice的服务
apiVersion: v1
kind: Service
metadata:
name: myservice
spec:
ports:
- protocol: TCP
port: 80
targetPort: 6666
复制代码
这里是服务IP的80端口对应着容器的6666端口,这里先暂时不用管。确保服务正常起来
再去看pod的状态,发现第一个Init容器已经退出了
同样再通过yaml文件test-init-mydb.yaml去创建mydb服务
apiVersion: v1
kind: Service
metadata:
name: mydb
spec:
ports:
- protocol: TCP
port: 80
targetPort: 7777
复制代码
同样确保服务已经起来
再看pod的状态,所有Init容器都已经退出,主容器处于running状态
查看一下日志,正好是我们想要打印的内容
[root@k8s-master k8s-test]# kubectl logs test-init-main
Main app is running
复制代码