当前位置: 首页 > news >正文

k8s 读书笔记 - 初始化容器 Init Conatiner

Init Conatiner 概述

Init Conatiner(Init 容器) 是一种特殊容器,在 Pod 内的应用容器启动之前运行,执行相关的初始化操作。Init 容器可以包括一些应用镜像中不存在的 实用工具安装脚本

每个 Pod 中可以包含一个或多个容器, App 应用运行在这些 Container 容器里面,同样 Pod 中的 Init 容器 也可以有一个或多个(先于应用容器启动),用于完成应用容器所需的预置条件,如下图所示:
pod生命周期

Init 容器与 应用容器非常像(在本质上是一样的),除了以下特点:

  • 它们仅运行一次就结束的任务,总是运行到成功完成。
  • 每个 Init Conatiner 都必须在下一个启动之前成功完成才能继续执行。

说明:多个 Init 容器 存在的情况,这些 Init 容器 会按先后顺序 线性执行,并且每个 Init 容器 必须成功完成,下一个 Init 容器 才能执行;而多个应用容器可 并行执行

依据 Pod 的重启策略(RestartPolicy),如果 Pod 的 Init 容器失败,并且Pod 设置了 RestartPolicy=Never 时,则 Kubernetes 会将整个 Pod 状态设置为失败。而设置了 RestartPolicy=Always 时,kubelet 会不断地重启该 Init 容器直到该容器成功为止。

Init Conatiner 应用场景

讲解了 Init Conatiner 的使用,接下来介绍 Init Conatiner 有哪些应用场景。

在很多的应用场景中,应用在启动之前都需要执行如下初始化操作:

  • 等待其他关联组件运行(例如:数据库或某个后台服务)。
  • 基于环境变量(env)或者配置模板生成配置文件。
  • 从远程数据库获取本地所需的配置信息(类似配置中心),或者将自身注册到某个中央数据库中(类似服务注册)。
  • 下载相关依赖包,或者对系统进行一些预配置操作。
  • 应用 Init Conatiner 对集群环境进行故障排查。与其他几种应用场景相比较特殊。

关于这些应用场景的示例,这里不再详述,生产环境中依据自己的实际情况按照示例配置使用即可。

  • 《应用 Init Conatiner 故障排查》:https://kubernetes.io/zh-cn/docs/tasks/debug/debug-application/debug-init-containers/

如何使用 Init Container ?

为 Pod 设置 Init Conatiner 需要在 Pod spec 规约 中添加 initContainers 字段, 该字段以 Container 类型对象数组的形式组织,和应用的 containers 数组同级相邻。

Init Conatiner 的状态在 status.initContainerStatuses 字段中以容器状态数组的格式返回 (类似 status.containerStatuses 字段)。

示例一

举例:定义一个具有 2 个 Init Conatiner 的简单 Pod。 第一个等待 myservice 启动, 第二个等待 mydb 启动。 一旦这两个 Init Conatiner 都启动完成,Pod 将启动 spec 节中的应用容器。 myapp-pod.yaml 文件定义如下所示:

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:

kubectl apply -f myapp-pod.yaml
pod/myapp-pod created

检查该 Pod 状态信息:

kubectl get -f  myapp-pod.yaml

输出信息:

NAME        READY     STATUS     RESTARTS   AGE
myapp-pod   0/1       Init:0/2   0          6m

查看 Pod 更多详细信息:

kubectl describe -f myapp-pod.yaml

查看 Pod 内 Init 容器的日志:

kubectl logs myapp-pod -c init-myservice # 查看第一个 Init 容器
kubectl logs myapp-pod -c init-mydb      # 查看第二个 Init 容器

通过查看 Pod 状态、详细信息或者内部的 Init 容器日志,可以进一步的排查 Pod 异常的原因。

从上面输出的信息中,可以看到 STATUS 的值为 Init:0/2 ,说明该 Pod 内有 2 个 Init Container,并且 Pod 的 READY 0/1 未就绪态,原因是由于我们定义的 2 个 Init Container 需要对应的 Service 依赖,接下来我们继续创建对应的 Servicemyapp-pod-initc-svc.yaml 文件定义如下:

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

执行命令 创建 mydb 和 myservice 服务:

kubectl create -f myapp-pod-initc-svc.yaml

输出信息:

service "myservice" created
service "mydb" created

然后我们再次查看 Pod 状态信息:

kubectl get -f  myapp-pod.yaml

输出信息:

NAME        READY     STATUS    RESTARTS   AGE
myapp-pod   1/1       Running   0          9m

看到 Pod 的 STATUS 的值为 Running 并且 READY1/1 ,此时说明该 Pod 创建成功,就绪态可提供服务了。

理解 Pod 的状态

Init: 开头的 Pod 状态汇总了 Init 容器 执行的状态。 下表介绍调试 Init 容器时可能看到的一些状态值示例。

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

示例二

以 Nginx 为例,在启动 Nginx 之前,通过初始化容器 busybox 为 Nginx 创建一个 index.html 主页文件。

说明:
此处 init container 和 Nginx 设置了一个共享的 Volume,提供 Nginx 访问 init container 设置的 index.html 文件。

nginx-initc.yaml 文件定义如下:

apiVersion: v1
kind: Pod
metadata:
  name: myNginx
  labels:
    app.kubernetes.io/name: myNginx
spec:
  initContainers:
  - name: init-install
    image: busybox:1.34.1
    command: 
    - wget
    - "-O"
    - "/work-dir/index.html"
    - http://kubernetes.io
    volumeMounts:
    - mountPath: "/workdir"
      name: workdir
  containers:
  - name: myNginx-container
    image: nginx:1.23.1-alpine
    ports: 
    - containerPort: 80
    volumeMounts:
    - mountPath: "/usr/share/nginx/html"
      name: workdir
    dnsPolicy: Default
  volumes:
  - name: workdir
    emptyDir: {}

创建 nginx-initc.yaml 文件定义的 Pod:

kubectl create -f nginx-initc.yaml

输出信息:

pod "myNginx" created

查看 Pod 信息:

kubectl get pods

查看 Pod 详细信息:

kubectl describe pod myNginx

启动成功后,登录 Nginx 容器,可以看到 /usr/share/nginx/html 目录下的 index.html 文件为 init container 所生成,其内容为(如下伪代码)Kubernetes 的官网首页:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Kubernetes</title>
</head>
<body>
    <H1>Production-Grade Container Orchestration</H1>
    <script src="/js/xxx.js"></script>
</body>
</html>

与普通容器的区别

Init 容器 支持应用容器的全部字段和特性,包括资源限制、数据卷和安全设置。 然而,Init 容器对资源请求和限制的处理稍有不同,在下面资源节有说明。

同时 Init 容器 不支持 lifecycle、livenessProbe、readinessProbestartupProbe, 因为它们必须在 Pod 就绪之前运行完成。

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

Init Container 与 普通应用容器他们之间的区别总结如下:

(1) init container 的 运行方式 与 应用容器不同,它们必须先于应用容器执行完成,当 Pod 设置了多个 init container 时,将按顺序逐个运行(线性执行),并且只有前一个 init container 运行成功才能运行后一个 init container。当所有 init container 都成功运行后,Kubernetes 才会初始化 Pod 的各种信息,并开始创建和运行应用容器。

(2) 在 init container 的定义中也可以设置资源限制、Volume 的使用和 安全策略 等等。但 资源限制 的设置与应用容器略有不同。

  • 如果多个 init container 都定义了资源请求/资源限制,则取最大的值作为所有 init container 的资源请求值/资源限制值。

  • Pod 的有效(effective) 资源请求值/资源限制值取以下二者中的较大值。
    a) 所有应用容器的资源请求值/资源限制值之和。
    b) init container 的有效资源请求值/资源限制值。

  • 调度算法将基于 Pod 的有效资源请求值/资源限制值进行计算,也就是说 init container 可以为初始化操作预留系统资源,即使后续应用容器无须使用这些资源,Pod 的有效 Qos(Quality of Service,服务等级) 等级适用于 init container 和应用容器。

  • 资源配额和限制将根据 Pod 的有效资源请求值/资源限制值计算生效。

  • Pod 级别的 cgroup 将基于 Pod 的有效资源请求/限制,与调度机制一致。

(3) init container 不能设置 readinessProbe 探针,因为必须在它们成功运行后才能继续运行在 Pod 中定义的普通容器。

在Pod重新启动时,init container 将会重新运行,常见的 Pod 重启场景如下:

  • init container 的镜像被更新时,init container 将会重新运行,导致 Pod重启。仅更新应用容器的镜像只会使得应用容器被重启。
  • Pod 的 infrastructure 容器更新时,Pod 将会重启。
  • 若 Pod 中的所有应用容器都终止了,并且设置了 RestartPolicv=Alwavs 时,则 Pod 会重启。

Pod 知识扩展

关于Pod 的其他属性配置,如上面的【Pod 生命周期】图中的更多信息请查看:

  • 《Init 容器》,https://kubernetes.io/zh-cn/docs/concepts/workloads/pods/init-containers/
  • 《调试 Init 容器》,https://kubernetes.io/zh-cn/docs/tasks/debug/debug-application/debug-init-containers/
  • 《配置存活、就绪和启动探针》,https://kubernetes.io/zh-cn/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/
  • 《为容器的生命周期事件设置处理函数,定义 postStart 和 preStop 处理函数》,https://kubernetes.io/zh-cn/docs/tasks/configure-pod-container/attach-handler-lifecycle-event/

关于家的憧憬

相关文章:

  • ES8(Java API Client)查询详解
  • 内置单片机的433无线模块高速连传典型运用
  • SpringBoot学习_day7
  • 【项目】小帽课堂(一)
  • [JavaScript]_[初级]_[不使用JQuery原生Ajax提交表单文件并监听进度]
  • 笔记整体梳理
  • 【题解】同济线代习题一.6.3
  • MATLAB算法实战应用案例精讲-【智能优化算法】黑寡妇算法-BWO(附matlab代码)
  • 云原生之容器编排实践-minikube传递秘钥使用阿里云私有镜像仓库
  • 【React Scheduler源码第一篇】哪些API适合用于任务调度
  • 【笔记:模拟MOS集成电路】偏置电路(基本原理+结构分析)
  • 【第六章 final、abstract】
  • 【JavaEE初阶】文件操作 和 IO (上篇)
  • Spring教程-01-IOC控制反转
  • Spring Cloud Gateway过滤器配置
  • 【Leetcode】101. 对称二叉树
  • 分享一款快速APP功能测试工具
  • 【跃迁之路】【519天】程序员高效学习方法论探索系列(实验阶段276-2018.07.09)...
  • 11111111
  • 5分钟即可掌握的前端高效利器:JavaScript 策略模式
  • AzureCon上微软宣布了哪些容器相关的重磅消息
  • create-react-app做的留言板
  • JavaScript标准库系列——Math对象和Date对象(二)
  • JavaScript工作原理(五):深入了解WebSockets,HTTP/2和SSE,以及如何选择
  • Mac转Windows的拯救指南
  • node-glob通配符
  • Python_网络编程
  • Spring Cloud中负载均衡器概览
  • tensorflow学习笔记3——MNIST应用篇
  • 翻译 | 老司机带你秒懂内存管理 - 第一部(共三部)
  • 飞驰在Mesos的涡轮引擎上
  • 浅谈web中前端模板引擎的使用
  • 深度学习在携程攻略社区的应用
  • 吐槽Javascript系列二:数组中的splice和slice方法
  • 微信端页面使用-webkit-box和绝对定位时,元素上移的问题
  • 微信小程序--------语音识别(前端自己也能玩)
  • ​软考-高级-系统架构设计师教程(清华第2版)【第1章-绪论-思维导图】​
  • ​学习一下,什么是预包装食品?​
  • ### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTr
  • (Redis使用系列) SpringBoot中Redis的RedisConfig 二
  • (ZT) 理解系统底层的概念是多么重要(by趋势科技邹飞)
  • (附源码)ssm旅游企业财务管理系统 毕业设计 102100
  • (论文阅读22/100)Learning a Deep Compact Image Representation for Visual Tracking
  • (实战)静默dbca安装创建数据库 --参数说明+举例
  • (转载)PyTorch代码规范最佳实践和样式指南
  • .NET NPOI导出Excel详解
  • .NET 动态调用WebService + WSE + UsernameToken
  • .Net 路由处理厉害了
  • .NET6使用MiniExcel根据数据源横向导出头部标题及数据
  • .NET文档生成工具ADB使用图文教程
  • .NET与 java通用的3DES加密解密方法
  • .Net转前端开发-启航篇,如何定制博客园主题
  • @JSONField或@JsonProperty注解使用
  • @ModelAttribute使用详解
  • [ HTML + CSS + Javascript ] 复盘尝试制作 2048 小游戏时遇到的问题