k8s 容器生命周期 | 周末学习

这是我参与更文挑战的第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
复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享