一、pod的原理
Pod是Kubernetes中最小的可部署对象,其生命周期包括创建、运行、就绪、终止等几个阶段。具体来说,Pod从创建开始,会被赋予一个唯一的ID并被调度到一个节点上运行。在此期间,如果节点出现故障,那么调度到该节点的Pod也会在超时期限结束后被删除。
Pod的运行过程包括初始化容器(init container)、Pod Hook和健康检查三个主要部分。Pod在其生命周期内可能会经历多次重启,这由Pod的重启策略决定。需要注意的是,Pod本身不具有自愈能力,如果需要实现高可用性,可能需要依赖于Kubernetes中的其他机制。
Pod的状态定义为PodStatus对象中的phase字段,它反映了Pod当前的生命周期阶段。
在k8s集群中,在一个容器启动之前,首先会拉起pause的根容器,然后进行初始化容器,探测等,直到runing。
初始化容器可以有多个,该动作是在容器三大探测之前产生的。
二、初始化容器举列子
vim init.yaml
apiVersion: v1
kind: Pod
metadata:
name: my-init-pod
labels:
app: my-init-app
spec:
initContainers:
- name: init-box
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"]
containers:
- name: myapp-container
image: busybox:1.28
command: ['sh', '-c', 'echo The app is running! && sleep 3600']
kubectl apply -f init.yaml
实验结果
[root@master elk]# kubectl get pod -w
NAME READY STATUS RESTARTS AGE
nfs-provisioner-57cdd589d4-nqzsf 1/1 Running 0 60m
my-init-pod 0/1 Pending 0 0s
my-init-pod 0/1 Pending 0 0s
my-init-pod 0/1 Init:0/2 0 0s
my-init-pod 0/1 Init:0/2 0 2s
my-init-pod 0/1 Init:0/2 0 2s
容器一直不会run,一只在init,由于初始化的域名解析不了,而主容器在初始化容器完成才启动,所以一直没起来。
[root@master ~]# kubectl describe pod my-init-pod
Name: my-init-pod
Namespace: default
Priority: 0
Node: node2/172.17.100.152
Start Time: Thu, 07 Dec 2023 16:14:40 +0800
Labels: app=my-init-app
Annotations: cni.projectcalico.org/podIP: 192.168.104.7/32
cni.projectcalico.org/podIPs: 192.168.104.7/32
Status: Pending
IP: 192.168.104.7
IPs:
IP: 192.168.104.7
Init Containers:
init-box:
Container ID: docker://a5a90dd6ad808da8614e3175047fb9f1be4ecf6c8142015f4d9f91cda6860a57
Image: busybox:1.28
Image ID: docker-pullable://busybox@sha256:141c253bc4c3fd0a201d32dc1f493bcf3fff003b6df416dea4f41046e0f37d47
Port: <none>
Host Port: <none>
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
State: Running
Started: Thu, 07 Dec 2023 16:14:42 +0800
Ready: False
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-tcmx5 (ro)
init-mydb:
Container ID:
Image: busybox:1.28
Image ID:
Port: <none>
Host Port: <none>
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
State: Waiting
Reason: PodInitializing
Ready: False
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-tcmx5 (ro)
Containers:
myapp-container:
Container ID:
Image: busybox:1.28
Image ID:
Port: <none>
Host Port: <none>
Command:
sh
-c
echo The app is running! && sleep 3600
State: Waiting
Reason: PodInitializing
Ready: False
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-tcmx5 (ro)
Conditions:
Type Status
Initialized False
Ready False
ContainersReady False
PodScheduled True
Volumes:
default-token-tcmx5:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-tcmx5
Optional: false
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 115s default-scheduler Successfully assigned default/my-init-pod to node2
Normal Pulled 113s kubelet Container image "busybox:1.28" already present on machine
Normal Created 113s kubelet Created container init-box
Normal Started 113s kubelet Started container init-box
You have new mail in /var/spool/mail/root
如何让主容器起来呢?
让初始化容器完成就行!
那我们修改配置文件,使得初始化容器能够起来!!
删除原本的pod
[root@master ~]# kubectl delete pod my-init-pod
修改配置,我们去echo一句话
apiVersion: v1
kind: Pod
metadata:
name: my-init-pod
labels:
app: my-init-app
spec:
initContainers:
- name: init-box
image: busybox:1.28
command: ['sh', '-c', "echo this is init1 && sleep 2"]
- name: init-mydb
image: busybox:1.28
command: ['sh', '-c', "echo this is inint2 && sleep 2"]
containers:
- name: myapp-container
image: busybox:1.28
command: ['sh', '-c', 'echo The app is running! && sleep 3600']
查看
my-init-pod 0/1 Pending 0 0s
my-init-pod 0/1 Pending 0 0s
my-init-pod 0/1 Init:0/2 0 0s
my-init-pod 0/1 Init:0/2 0 1s
my-init-pod 0/1 Init:0/2 0 2s
my-init-pod 0/1 Init:1/2 0 4s
my-init-pod 0/1 Init:1/2 0 5s
my-init-pod 0/1 PodInitializing 0 7s
my-init-pod 1/1 Running 0 8s
[root@master ~]# kubectl delete pod my-init-pod
pod "my-init-pod" deleted
You have new mail in /var/spool/mail/root
[root@master ~]# kubectl apply -f init.yaml
pod/my-init-pod created
[root@master ~]# kubectl delete -f init.yaml
pod "my-init-pod" deleted
You have new mail in /var/spool/mail/root
[root@master ~]# kubectl apply -f init.yaml
pod/my-init-pod created
[root@master ~]# vim init.yaml
You have new mail in /var/spool/mail/root
[root@master ~]# kubectl describe pod my-init-pod
Name: my-init-pod
Namespace: default
Priority: 0
Node: node1/172.17.100.151
Start Time: Thu, 07 Dec 2023 16:25:38 +0800
Labels: app=my-init-app
Annotations: cni.projectcalico.org/podIP: 192.168.166.138/32
cni.projectcalico.org/podIPs: 192.168.166.138/32
Status: Running
IP: 192.168.166.138
IPs:
IP: 192.168.166.138
Init Containers:
init-box:
Container ID: docker://d19369f478307a4ccd9a97b9f2868a9b74d1d9a9922d00281ad3e128c7a9de9a
Image: busybox:1.28
Image ID: docker-pullable://busybox@sha256:141c253bc4c3fd0a201d32dc1f493bcf3fff003b6df416dea4f41046e0f37d47
Port: <none>
Host Port: <none>
Command:
sh
-c
echo this is init1 && sleep 2
State: Terminated
Reason: Completed
Exit Code: 0
Started: Thu, 07 Dec 2023 16:25:39 +0800
Finished: Thu, 07 Dec 2023 16:25:41 +0800
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-tcmx5 (ro)
init-mydb:
Container ID: docker://8d4b8c63ab7d98805842ff4578f0dc0c839c8df9e9b5f5689574671e69d489b3
Image: busybox:1.28
Image ID: docker-pullable://busybox@sha256:141c253bc4c3fd0a201d32dc1f493bcf3fff003b6df416dea4f41046e0f37d47
Port: <none>
Host Port: <none>
Command:
sh
-c
echo this is inint2 && sleep 2
State: Terminated
Reason: Completed
Exit Code: 0
Started: Thu, 07 Dec 2023 16:25:42 +0800
Finished: Thu, 07 Dec 2023 16:25:44 +0800
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-tcmx5 (ro)
Containers:
myapp-container:
Container ID: docker://244a09c29c2387f415b1b7ed2ca0fde6dde59198b3c3353172a6980f4f91bb6f
Image: busybox:1.28
Image ID: docker-pullable://busybox@sha256:141c253bc4c3fd0a201d32dc1f493bcf3fff003b6df416dea4f41046e0f37d47
Port: <none>
Host Port: <none>
Command:
sh
-c
echo The app is running! && sleep 3600
State: Running
Started: Thu, 07 Dec 2023 16:25:45 +0800
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-tcmx5 (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
default-token-tcmx5:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-tcmx5
Optional: false
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 76s default-scheduler Successfully assigned default/my-init-pod to node1
Normal Pulled 75s kubelet Container image "busybox:1.28" already present on machine
Normal Created 75s kubelet Created container init-box
Normal Started 75s kubelet Started container init-box
Normal Pulled 72s kubelet Container image "busybox:1.28" already present on machine
Normal Created 72s kubelet Created container init-mydb
Normal Started 72s kubelet Started container init-mydb
Normal Pulled 69s kubelet Container image "busybox:1.28" already present on machine
Normal Created 69s kubelet Created container myapp-container
Normal Started 69s kubelet Started container myapp-container
基于上面的初始化容器部署一个nginx服务,使用L4的代理
vim init.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
labels:
app: my-nginx-app
spec:
initContainers:
- name: init-box
image: busybox:1.28
command: ['sh', '-c', "echo this is init1 && sleep 2"]
- name: init-mydb
image: busybox:1.28
command: ['sh', '-c', "echo this is inint2 && sleep 2"]
containers:
- name: nginx-test
image: nginx
ports:
- containerPort: 80
name: nginx
---
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
spec:
selector:
app: my-nginx-app
ports:
- protocol: TCP
port: 80
targetPort: 80
type: LoadBalancer
kubectl apply -f init.yaml
root@master ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 6h17m
nginx-svc LoadBalancer 10.96.221.202 <pending> 80:30291/TCP 5s
访问测试
初始化容器用途,可以在容器启动前做一些动作,如注入环境变量,测试api接口等。