k8s学习-Init容器、临时容器

614 阅读3分钟

Init 容器

Init 容器用途

Init容器用来在应用容器启动之前,做一些初始化的工作。 因为 Init 容器具有与应用容器分离的单独镜像,其启动相关代码具有如下优势:

  • Init 容器可以包含一些安装过程中应用容器中不存在的实用工具或个性化代码。
  • 应用镜像的创建者和部署者可以各自独立工作,而没有必要联合构建一个单独的应用镜像。
  • 与同一 Pod 中的多个应用容器相比,Init 容器能以不同的文件系统视图运行。因此,Init 容器可以被赋予访问应用容器不能访问的的权限。
  • 由于 Init 容器必须在应用容器启动之前运行完成,因此 Init 容器提供了一种机制来阻塞或延迟应用容器的启动,直到满足了一组先决条件。 一旦前置条件满足,Pod 内的所有的应用容器会并行启动。
  • Init 容器可以安全地运行实用程序或自定义代码,而在其他方式下运行这些实用程序或自定义代码可能会降低应用容器镜像的安全性。 通过将不必要的工具分开,可以限制应用容器镜像的被攻击范围

Init 容器原理

在Pod启动过程中,每个Init容器会在网络和数据卷初始化之后按顺序启动。 依据Init容器在Pod spec配置中的出现顺序依次运行。由于Pod可能各种原因多次重启,所以Init容器中的操作,须具备幂等性。

Init容器示例

下面是一个init容器的例子:

apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app.kubernetes.io/name: MyApp
spec:
  containers:
  - name: myapp-container
    image: busybox:1.28
    command: ['sh', '-c', 'echo The app is running! && sleep 3600']
  initContainers:
  - name: init-myservice
    image: busybox:1.28
    command: ['sh', '-c', "until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done"]
  - name: init-mydb
    image: busybox:1.28
    command: ['sh', '-c', "until nslookup mydb.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for mydb; sleep 2; done"]

部署后,查看Pod日志:

C:\Users\Lenovo>kubectl logs myapp-pod
Error from server (BadRequest): container "myapp-container" in pod "myapp-pod" is waiting to start: PodInitializing

查看init容器状态:

C:\Users\Lenovo>kubectl get pod myapp-pod
NAME        READY   STATUS     RESTARTS   AGE
myapp-pod   0/1     Init:0/2   0          84s

以Init:开头的 Pod 状态汇总了Init容器执行的状态。可以看到有两个Init容器,目前都没有完成。以下表格是Init容器状态含义:

状态含义
Init:N/MPod 包含 M 个 Init 容器,其中 N 个已经运行完成。
Init:ErrorInit 容器已执行失败。
Init:CrashLoopBackOffInit 容器执行总是失败。
PendingPod 还没有开始执行 Init 容器。
PodInitializing or RunningPod 已经完成执行 Init 容器。

查看init-myservice容器日志:

C:\Users\Lenovo>kubectl logs myapp-pod -c init-myservice
Server:    10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local

waiting for myservice
nslookup: can't resolve 'myservice.default.svc.cluster.local'
nslookup: can't resolve 'myservice.default.svc.cluster.local'
Server:    10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local

waiting for myservice
nslookup: can't resolve 'myservice.default.svc.cluster.local'
Server:    10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local

init-myservice容器在等待myservice就绪。下面部署myservice

apiVersion: v1
kind: Service
metadata:
  name: myservice
spec:
  ports:
  - protocol: TCP
    port: 80
    targetPort: 9376

查看Init容器状态,可以看到2个Init容器,有1个已经完成。

C:\Users\Lenovo>kubectl get pod myapp-pod
NAME        READY   STATUS     RESTARTS   AGE
myapp-pod   0/1     Init:1/2   0          5m25s

继续部署mydb

apiVersion: v1
kind: Service
metadata:
  name: mydb
spec:
  ports:
  - protocol: TCP
    port: 80
    targetPort: 9377

查看Init容器状态,可以看到2个Init容器都已经成功完成。

C:\Users\Lenovo>kubectl get pod myapp-pod
NAME        READY   STATUS    RESTARTS   AGE
myapp-pod   1/1     Running   0          7m35s

此时再去查看pod日志:

C:\Users\Lenovo>kubectl logs -f myapp-pod
The app is running!

临时容器

临时容器:一种特殊的容器,该容器在现有 Pod中临时运行,以便完成用户发起的操作,例如故障排查。 你会使用临时容器来检查服务,而不是用它来构建应用程序。

当由于容器崩溃或容器镜像不包含调试工具而导致 kubectl exec 无用时, 临时容器对于交互式故障排查很有用。

临时容器使用与常规容器相同的 ContainerSpec 节来描述