zl程序教程

您现在的位置是:首页 >  .Net

当前栏目

pod(六):初始化容器Init Containers

2023-02-18 16:34:30 时间

一.系统环境

服务器版本 docker软件版本 Kubernetes(k8s)集群版本 CPU架构
CentOS Linux release 7.4.1708 (Core) Docker version 20.10.12 v1.21.9 x86_64

Kubernetes集群架构:k8scloude1作为master节点,k8scloude2,k8scloude3作为worker节点

服务器 操作系统版本 CPU架构 进程 功能描述
k8scloude1/192.168.110.130 CentOS Linux release 7.4.1708 (Core) x86_64 docker,kube-apiserver,etcd,kube-scheduler,kube-controller-manager,kubelet,kube-proxy,coredns,calico k8s master节点
k8scloude2/192.168.110.129 CentOS Linux release 7.4.1708 (Core) x86_64 docker,kubelet,kube-proxy,calico k8s worker节点
k8scloude3/192.168.110.128 CentOS Linux release 7.4.1708 (Core) x86_64 docker,kubelet,kube-proxy,calico k8s worker节点

二.前言

本文介绍初始化容器Init Containers,初始化容器Init Containers是一种特殊容器,在 Pod 内的应用容器启动之前运行。Init 容器可以包括一些应用镜像中不存在的实用工具和安装脚本。你可以在 Pod 的规约中与用来描述应用容器的 containers 数组平行的位置指定 Init 容器。

创建pod的前提是已经有一套可以正常运行的Kubernetes集群,关于Kubernetes(k8s)集群的安装部署,可以查看博客《Centos7 安装部署Kubernetes(k8s)集群》https://www.cnblogs.com/renshengdezheli/p/16686769.html

三.初始化容器Init Containers

3.1 何为初始化容器Init Containers

每个 Pod 中可以包含多个容器, 应用运行在这些容器里面,同时 Pod 也可以有一个或多个先于应用容器启动的 Init 容器。Init 容器与普通的容器非常像,除了如下两点:

  • 它们总是运行到完成。
  • 每个都必须在下一个启动之前成功完成。

如果 Pod 的 Init 容器失败,kubelet 会不断地重启该 Init 容器直到该容器成功为止。 然而,如果 Pod 对应的 restartPolicy 值为 "Never",并且 Pod 的 Init 容器失败, 则 Kubernetes 会将整个 Pod 状态设置为失败。

为 Pod 设置 Init 容器需要在 Pod 规约中添加 initContainers 字段, 该字段以 Container 类型对象数组的形式组织,和应用的 containers 数组同级相邻。 Init 容器的状态在 status.initContainerStatuses 字段中以容器状态数组的格式返回 (类似 status.containerStatuses 字段)。

3.2 Init Containers与普通容器的不同之处

Init 容器支持应用容器的全部字段和特性,包括资源限制、数据卷和安全设置。 然而,Init 容器对资源请求和限制的处理稍有不同,同时 Init 容器不支持 lifecycle、livenessProbe、readinessProbe 和 startupProbe, 因为它们必须在 Pod 就绪之前运行完成。

如果为一个 Pod 指定了多个 Init 容器,这些容器会按顺序逐个运行。 每个 Init 容器必须运行成功,下一个才能够运行。当所有的 Init 容器运行完成时, Kubernetes 才会为 Pod 初始化应用容器并像平常一样运行。

3.3 Init 容器优点

因为 Init 容器具有与应用容器分离的单独镜像,其启动相关代码具有如下优势:

  • Init 容器可以包含一些安装过程中应用容器中不存在的实用工具或个性化代码。 例如,没有必要仅为了在安装过程中使用类似 sed、awk、python 或 dig 这样的工具而去 FROM 一个镜像来生成一个新的镜像。

  • 应用镜像的创建者和部署者可以各自独立工作,而没有必要联合构建一个单独的应用镜像。

  • 与同一 Pod 中的多个应用容器相比,Init 容器能以不同的文件系统视图运行。因此,Init 容器可以被赋予访问应用容器不能访问的 Secret 的权限。

  • 由于 Init 容器必须在应用容器启动之前运行完成,因此 Init 容器提供了一种机制来阻塞或延迟应用容器的启动,直到满足了一组先决条件。 一旦前置条件满足,Pod 内的所有的应用容器会并行启动。

  • Init 容器可以安全地运行实用程序或自定义代码,而在其他方式下运行这些实用程序或自定义代码可能会降低应用容器镜像的安全性。 通过将不必要的工具分开,你可以限制应用容器镜像的被攻击范围。

3.4 创建初始化容器Init Containers

创建一个pod,initContainers指定初始化容器,command: ["sh","-c","sleep 15"]表示初始化容器需要休眠15秒

[root@k8scloude1 pod]# vim initcontainer.yaml 

[root@k8scloude1 pod]# cat initcontainer.yaml 
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: initc
  name: initc
spec:
  terminationGracePeriodSeconds: 0
  containers:
  - image: nginx
    imagePullPolicy: IfNotPresent
    name: n1
    resources: {}
  initContainers:
  - name: initc
    image: nginx
    imagePullPolicy: IfNotPresent
    command: ["sh","-c","sleep 15"]
  dnsPolicy: ClusterFirst
  restartPolicy: Never
status: {}

[root@k8scloude1 pod]# kubectl apply -f initcontainer.yaml    
pod/initc created

查看pod可以发现,初始化容器休眠了15秒之后,才执行应用容器。

[root@k8scloude1 pod]# kubectl get pod
NAME    READY   STATUS     RESTARTS   AGE
initc   0/1     Init:0/1   0          1s

[root@k8scloude1 pod]# kubectl get pod
NAME    READY   STATUS     RESTARTS   AGE
initc   0/1     Init:0/1   0          15s

[root@k8scloude1 pod]# kubectl get pod
NAME    READY   STATUS            RESTARTS   AGE
initc   0/1     PodInitializing   0          17s

[root@k8scloude1 pod]# kubectl get pod
NAME    READY   STATUS    RESTARTS   AGE
initc   1/1     Running   0          18s

3.5 使用初始化容器,修改内核参数

在容器里修改内核参数,实际上修改的就是物理机的内核参数,为了安全性,一般不允许在容器里修改内核参数,seccom控制了容器能做哪些操作,添加securityContext参数之后就可以修改内核参数了。

创建一个pod,initContainers初始化容器里的securityContext:privileged: true表示该容器具有特权,可以执行命令"sh","-c","/sbin/sysctl -w vm.swappiness=0",vm.swappiness设置为0表示尽量少使用swap内存。

[root@k8scloude1 pod]# vim initcontainer2.yaml 

[root@k8scloude1 pod]# cat initcontainer2.yaml 
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: initc
  name: initc
spec:
  terminationGracePeriodSeconds: 0
  containers:
  - image: nginx
    imagePullPolicy: IfNotPresent
    name: n1
    resources: {}
  initContainers:
  - name: initc
    image: alpine
    imagePullPolicy: IfNotPresent
    command: ["sh","-c","/sbin/sysctl -w vm.swappiness=0"]
    securityContext:
      privileged: true
  dnsPolicy: ClusterFirst
  restartPolicy: Never
status: {}

[root@k8scloude1 pod]# kubectl apply -f initcontainer2.yaml 
pod/initc created

[root@k8scloude1 pod]# kubectl get pods
NAME    READY   STATUS    RESTARTS   AGE
initc   1/1     Running   0          7s

#可以看到pod运行在k8scloude2节点
[root@k8scloude1 pod]# kubectl get pods -o wide
NAME    READY   STATUS    RESTARTS   AGE   IP               NODE         NOMINATED NODE   READINESS GATES
initc   1/1     Running   0          22s   10.244.112.147   k8scloude2   <none>           <none>

查看k8scloude2机器的swappiness ,此时k8scloude2机器上的swappiness变为了0,swappiness修改为0之后,nginx容器才可以运行

[root@k8scloude2 ~]# cat /proc/sys/vm/swappiness 
0

注意:在k8s中,每一个pod都会有一个掩藏的初始化容器pause

创建一个普通的Nginx pod

[root@k8scloude1 pod]# vim nginx.yaml 

#kind: Pod表示资源类型为Pod   labels指定pod标签   metadata下面的name指定pod名字   containers下面全是容器的定义   
#image指定镜像名字  imagePullPolicy指定镜像下载策略   containers下面的name指定容器名
#resources指定容器资源(CPU,内存等)   env指定容器里的环境变量   dnsPolicy指定DNS策略
#restartPolicy容器重启策略    ports指定容器端口
[root@k8scloude1 pod]# cat nginx.yaml 
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: nginx
  name: nginx
spec:
  containers:
  - image: nginx
    imagePullPolicy: IfNotPresent
    name: nginx
    resources: {}
    ports:
    - name: http
      containerPort: 80
      protocol: TCP
    env:
    - name: xx
      value: "12"
    - name: yy
      value: "21"
    - name: zz
      value: hello
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

[root@k8scloude1 pod]# kubectl apply -f nginx.yaml 
pod/nginx created

#pod运行在k8scloude2机器
[root@k8scloude1 pod]# kubectl get pod -o wide
NAME    READY   STATUS    RESTARTS   AGE   IP               NODE         NOMINATED NODE   READINESS GATES
nginx   1/1     Running   0          10s   10.244.112.148   k8scloude2   <none>           <none>

通过在k8scloude2机器上执行docker ps | grep nginx,可以看到初始化容器pause

#这是pause镜像
[root@k8scloude2 ~]# docker images | grep pause
registry.aliyuncs.com/google_containers/pause        3.4.1     0f8457a4c2ec   12 months ago   683kB

[root@k8scloude2 ~]# docker ps | grep nginx
d00a5991dd5b   605c77e624dd                                          "/docker-entrypoint.…"   27 seconds ago   Up 27 seconds             k8s_nginx_nginx_pod_8aaab455-5e27-4c65-815d-2a23f76e758b_0
595918a44478   registry.aliyuncs.com/google_containers/pause:3.4.1   "/pause"                 28 seconds ago   Up 27 seconds             k8s_POD_nginx_pod_8aaab455-5e27-4c65-815d-2a23f76e758b_0