一、容器的初始化 init
⭐️ init c : init contariner
初始化容器,只是用来初始化,初始化完成就会死亡可以大于的等于一也可以没有,每个init只有在前一个 init
c执行完成后才可以执行下一个、init容器总是运行到成功完成为止,如果 init
运行失败 k8s
就会不断的重启该 Pod
,直到init容器成功为止,但是如果 Pod
对应的 restartPolicy
为 Nerver
,它就不会重启。
因为 Init
容器具有与应用程序容器分离的单独镜像,所以它们的启动相关代码具有如下优势:
- 它们可以包含并运行实用工具,但是出于安全考虑,是不建议在应用程序容器镜像中包含这些实用工具的
- 它们可 以包含使用工具和定制化代码来安装,但是不能出现在应用程序镜像中。例如,创建镜像没必要FROM 另-一个镜像,只需要在安装过程中使用类似
sed
、awk
、python
或dig
这样的工具。 - 应用程序镜像可以分离出创建和部署的角色,而没有必要联合它们构建-一个 单独的镜像。
Init
容器使用Linux Namespace
,所以相对应用程序容器来说具有不同的文件系统视图。因此,它们能够具有访问Secret 的权限,而应用程序容器则不能。- 它们必须在应用程序容器启动之前运行完成,而应用程序容器是并行运行的,所以
Init
容器能够提供了一种简单的阻塞或延迟应用容器的启动的方法,直到满足了一组先决条件。
二、主容器
Main C
: 主容器readiness
: 就绪检测,他会去判断容器能不能正常提供给外网访问,Liveiness
:生存检测
容器运行时接口
⭐️ 每种容器运行时各有所长,许多用户都希望
Kubernetes
支持更多的运行时。在Kubernetes 1.5
发布版里,我们引入了CRI
–一个能让kubelet
无需编译就可以支持多种容器运行时的插件接口。CRI
包含了一组protocol buffers
,gRPC API
,相关的库,以及在活跃开发下的额外规范和工具。
protocol buffers A
PI包含了两个gRPC
服务:ImageService
和RuntimeService
。ImageService
提供了从镜像仓库拉取、查看、和移除镜像RPC
。RuntimeSe
的rivce
包含了Pods和容器生命周期管理的RPC
,以及跟容器交互的调用(exec/attach/port-forward
)。一个单块的容器运行时能够管理镜像和容器(例如:Docker
和Rkt
),并且通过同一个套接字同时提供这两种服务。这个套接字可以在Kubelet
里通过标识–container-runtime-endpoint和–image-service-endpoint
进行设置。
Pending(悬决) | Pod 已被 Kubernetes 系统接受,但有一个或者多个容器尚未创建亦未运行。此阶段包括等待 Pod 被调度的时间和通过网络下载镜像的时间, |
---|---|
Running(运行中) | Pod 已经绑定到了某个节点,Pod 中所有的容器都已被创建。至少有一个容器仍在运行,或者正处于启动或重启状态。 |
Succeeded(成功) | Pod 中的所有容器都已成功终止,并且不会再重启。 |
Failed(失败) | Pod 中的所有容器都已终止,并且至少有一个容器是因为失败终止。也就是说,容器以非 0 状态退出或者被系统终止。 |
Unknown(未知) | 因为某些原因无法取得 Pod 的状态。这种情况通常是因为与 Pod 所在主机通信失败。 |
三、init实验
1️⃣我们来通过一个 yaml
模板定义一个Pod在定义两个 init
,init
操作是:
这个init容器的command是一个shell脚本,它执行以下操作:
- 使用
nslookup
命令检查testservice
和testdb
这两个服务是否可用。 - 如果
testservice
或testdb
服务不可用,它会输出"waiting for myservice
",然后等待2秒后再次尝试检查。 - 这个过程会一直重复,直到
testservice
和testdb
服务都变得可用为止。 Pod
内可以直接使用Service
的名字进行访问
[root@master ~]# cat pod/init.yaml
apiVersion: v1
kind: Pod
metadata:
name: test
labels:
version: v1
app: test-app
spec:
containers:
- name: mytest
image: busybox
command: ['sh','-c','echo runing && sleep 6000']
initContainers:
- name: init-service
image: busybox
imagePullPolicy: ifNotPresent
command: ['sh','-c','until nslookup testservice; do echo waiting for myservice; sleep 2; done;']
- name: init-db
image: busybox
imagePullPolicy: ifNotPresent
command: ['sh','-c','until nslookup testdb; do echo waiting for myservice; sleep 2; donel;']
上文的镜像是虽然没有带后缀但是默认就是latest,k8s中只要镜像后缀是latest就会从远程仓库拉去,可以设置
imagePullPolicy
有三种策略
Always
:总是从远程仓库拉去
Nerver
: 仅使用本地镜像
IfNotPresent
: 如果本地有就用,没有就从外部拉去
2️⃣使用编写号的 yaml
文档创建 pod
,此时 pod
正在等待 init
容器初始化完成
[root@master ~]# kubectl create -f pod/init.yaml
pod/test created
[root@master ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-6b48575596-bsdt2 1/1 Running 1 42h
nginx-6b48575596-fbdjf 1/1 Running 1 42h
nginx-6b48575596-wzmdp 1/1 Running 1 42h
test 0/1 Init:0/2 0 8s
website 1/1 Running 0 17h
3️⃣ 要使得 init
容器初始化完成,就需要我们来创建两个个 Service
,让 pod
可以解析到,这里先创建第一个
[root@master ~]# cat pod/service.yaml
apiVersion: v1
kind: Service
metadata:
name: testservice
spec:
ports:
- protocol: TCP
port: 80
targetPort: 9999
4️⃣ 创建好后如果init还没未启动就可以为容器配置域名解析信息
可以使用下面这条命令来修改pod的设置
kubectl edit pod [podname]
**打开后我们可以看见**
dnsPolicy: ClusterFirst
- “
Default
“:从节点继承DNS
相关配置,对节点依赖性强。 - “
ClusterFirst
“:如果DNS
查询与配置好的默认集群域名前缀不匹配,则将查询请求转发到从节点继承而来,作为查询的上游服务器。默认则是这个 - “
ClusterFirstWithHostNet
“:如果pod工作在主机网络,就将dnsPolicy
设置成“ClusterFirstWithHostNet
”,这样效率更高。 - “
None
“:1.9版本引入的新特性(Beta in v1.10)。完全忽略kubernetes
系统提供的DNS
,以pod Spec
中dnsConfig
配置取而代之。
当然也可以直接改 DNS
在 spec
中加入
dnsPolicy: "None"
dnsConfig:
nameservers:
- 1.2.3.4
5️⃣ 此时我们在查看就会发现 init
容器已经准备好一个了
[root@master ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
test 0/1 Init:1/2 0 29m
[root@master ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 2d18h
testservice ClusterIP 10.98.62.1 <none> 80/TCP 53m
6️⃣ 运行第二个service
[root@master ~]# cat pod/service2.yaml
apiVersion: v1
kind: Service
metadata:
name: testdb
spec:
ports:
- protocol: TCP
port: 3366
targetPort: 9998
[root@master ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 2d18h
testdb ClusterIP 10.97.182.149 <none> 3366/TCP 7s
testservice ClusterIP 10.98.62.1 <none> 80/TCP 55m
可以看见pod变running了
[root@master ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
test 1/1 Running 0 57m
⭐️ 特殊说明
- 在Pod启动过程中,
Init
容器会按顺序在网络和数据卷初始化之后启动(pause
)。每个容器必须在下-一个容器启动之前成功退出,也就是说init
容器不是先被启动的先被启动的是pause
容器 - 如果由于运行时或失败退出,将导致容器启动失败,它会根据Pod的
restartPolicy
指定的策略进行重试。然而,如果Pod的restartPolicy
设置为Always
,Init
容器失败时会使用RestartPolicy
策略 可以看上一章笔记 - 在所有的
Init
容器没有成功之前,Pod
将不会变成Ready
状态。Init
容器的端口将不会在Service
中进行聚集。正在初始化中的Pod
处于Pending
状态,但应该会将Initializing
状态设置为true
,ps:就是说你的mian
container
或者init container
都没有完成,那么他们的端口和ip
地址将不会出现在service
- 如果
Pod
重启,所有Init
容器必须重新执行 -
#对
Init
容器spec
的修改被限制在容器image
字段,修改其他字段都不会生效。更改Init
容器的image
字段,等价于重启该Pod ps
: Init
容器具有应用容器的所有字段。除了readinessProbe
, 因为Init
容器无法定义不同于完成(completion
)的就绪(readiness
) 之外的其他状态。这会在验证过程中强制执行,ps:也就是说container下面写入的字段,initcontainer
下面也可以写- 在Pod 中的每个
app
和Init
容器的名称必须唯一-; 与任何其它容器共享同一个名称,会在验证时抛出错误.