Pod 是 kubernetes 系统的基础单元,是由用户创建或部署的最小组件,也是 kubernetes 系统上运行容器化应用的资源对象。
Kubernetes 集群中其他资源对象都是为 pod 这个资源对象做支撑来实现 kubernetes 管理应用服务的目的。
Pod 可以包含多个容器,应用运行在这些容器里面,同时 Pod 也可以有一个或多个先于应用容器启动的 Init 容器。
Init 容器与普通的容器非常像,除了如下两点:
如果 Pod 的 Init 容器失败,Kubernetes 会不断地重启该 Pod,直到 Init 容器成功为止。然而,如果 Pod 对应的 restartPolicy 值为 Never,它不会重新启动。
Init 容器能做什么?
初始化容器即 pod 内主容器启动之前要运行的容器,主要是做一些前置工作,初始化容器具有以下特征:
1.初始化容器必须首先执行,若初始化容器运行失败,集群会一直重启初始化容器直至完成,注意,如果 pod 的重启策略为 Never,那初始化容器启动失败后就不会重启。
2.初始化容器必须按照定义的顺序执行,初始化容器可以通过 pod 的 spec.initContainers
进行定义。
一个pod中的init容器就是在主容器运行之前,做一些初始化的校验,它必须是按 照顺序走的,运行到结束,必须是完整的。一个pod中可以没有init容器,也可以有多个init容器。当所有的init 容器运行结束后,才开始运行主容器。
主容器有自己的开始和结束点。开始和结束中间有一些探针,readness就绪探针探测主容器可不可以用,访问下服务是否可用。liveness是存活探针,可以一直探测主容器的活动状态,当检测到容器出现问题时,会调用restartPolicy
init容器运行结束后就会消失
我们先写一个简单的资源清单,不定义init容器:
vim pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: myapp
spec:
containers:
- name: myapp
image: myapp:v1
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
hostPort: 80
resources:
limits:
memory: 100M
requests:
memory: 50M
nodeSelector:
kubernetes.io/hostname: server3
hostNetwork: true
运行,查看到这个资源清单里只运行了一个容器
把pod信息的输出转化为一个yaml文件:
kubectl get pod -o yaml
当我们创建测试pod的资源清单时发现格式混乱,是因为里面含有缩进
所以我们使用纯vi不缩进的形式来编写:
\vi init.yaml
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: 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"]
init容器会一直做DNS解析,除非解析成功,否则不会启动主容器pod,因为init程序并不会退出
创建pod并查看状态:
kubectl create -f init.yaml
kubectl get pod
我们可以看到它处于init容器初始化状态
进入pod中的init容器
创建一个service
apiVersion: v1
kind: Service
metadata:
name: myservice
spec:
ports:
- protocol: TCP
port: 80
targetPort: 9376
service是为了暴露pod,可以让集群外部节点取访问它
[kubeadm@server1 manifest]$ kubectl create -f service.yaml
service/myservice created
[kubeadm@server1 manifest]$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
app NodePort 10.109.54.133 <none> 80:31453/TCP 142m
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 22h
myservice ClusterIP 10.96.137.66 <none> 80/TCP 8s
[kubeadm@server1 manifest]$
init容器初始化成功,退出
可以看到,init容器成功运行后退出,myapp-pod容器正常运行
进入容器,查看dns解析
[kubeadm@server1 manifest]$ kubectl run test -it --image=reg.westos.org/k8s/busyboxplus
If you don't see a command prompt, try pressing enter.
/ # nslookup myservice.default.svc.cluster.local
Server: 10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local
Name: myservice.default.svc.cluster.local
Address 1: 10.96.137.66 myservice.default.svc.cluster.local
/ #
/ # Session ended, resume using 'kubectl attach test -c test -i -t' command when the pod is running
[kubeadm@server1 manifest]$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
app NodePort 10.109.54.133 <none> 80:31453/TCP 150m
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 22h
myservice ClusterIP 10.96.137.66 <none> 80/TCP 8m32s
[kubeadm@server1 manifest]$
什么是探针?
探针是由 kubelet 对容器执行的定期诊断。要执行诊断,kubelet 调用由容器实现的 Handler。
探针 是由 kubelet 对容器执行的定期诊断:
ExecAction
:在容器内执行指定命令。如果命令退出时返回码为 0 则认为诊断成功。TCPSocketAction
:对指定端口上的容器的 IP 地址进行 TCP 检查。如果端口打开,则诊断被认为是成功的。HTTPGetAction
:对指定的端口和路径上的容器的 IP 地址执行 HTTP Get 请求。如果响应的状态码大于等于200 且小于400,则诊断被认为是成功的。每次探测都将获得以下三种结果之一:
Kubelet 可以选择是否执行在容器上运行的三种探针执行和做出反应:
livenessProbe
:指示容器是否正在运行。如果存活探测失败,则 kubelet 会杀死容器,并且容器将受到其 重启策略的影响。如果容器不提供存活探针,则默认状态为Success。readinessProbe
:指示容器是否准备好服务请求。如果就绪探测失败,端点控制器将从与 Pod 匹配的所有 Service的端点中删除该 Pod 的 IP 地址。初始延迟之前的就绪状态默认为 Failure。如果容器不提供就绪探针,则默认状态为 Success。startupProbe
: 指示容器中的应用是否已经启动。如果提供了启动探测(startupprobe),则禁用所有其他探测,直到它成功为止。如果启动探测失败,kubelet将杀死容器,容器服从其重启策略进行重启。如果容器没有提供启动探测,则默认状态为成功Success。重启策略
PodSpec 中有一个 restartPolicy
字段,可能的值为 Always
、OnFailure
和 Never
,默认为 Always。
Pod 的生命
三种可用的控制器:
首先删除之前实验时创建的myservice服务:
kubectl get all
kubectl delete -f init.yaml
kubectl delete pod test
kubectl delete service myservice
apiVersion: v1
kind: Pod
metadata:
name: myapp
spec:
containers:
- name: myapp
image: reg.westos.org/k8s/myapp:v1
imagePullPolicy: IfNotPresent
livenessProbe:
tcpSocket:
port: 8080
initialDelaySeconds: 1
periodSeconds: 2
timeoutSeconds: 2
说明:
initialDelaySeconds: 1
- - -pod起动后1秒开始检测
periodSeconds: 2
- - -每隔两秒检测
timeoutSeconds: 2
- - -监测的超时时间(如果超过这个时长,则认为监测失败)
[kubeadm@server1 manifest]$ kubectl get pod
NAME READY STATUS RESTARTS AGE
myapp 0/1 CrashLoopBackOff 6 4m10s
myapp-pod 1/1 Running 0 50m
test 1/1 Running 1 15m
[kubeadm@server1 manifest]$
因为myapp默认打开的端口是80,但是在文件中指定的访问端口为8080,所以就会 不停的restart.
解决:我们只需要将端口改为80即可
将 端口修改为80
apiVersion: v1
kind: Pod
metadata:
name: myapp
spec:
containers:
- name: myapp
image: reg.westos.org/k8s/myapp:v1
imagePullPolicy: IfNotPresent
livenessProbe:
tcpSocket:
port: 80
initialDelaySeconds: 1
periodSeconds: 2
timeoutSeconds: 2
就绪探针用法被检测容器是否能真正被访问
apiVersion: v1
kind: Pod
metadata:
name: nginx1
spec:
containers:
- name: nginx1
image: reg.westos.org/k8s/nginx
imagePullPolicy: IfNotPresent
readinessProbe:
httpGet:
path: /test.html
port: 80
initialDelaySeconds: 1
periodSeconds: 2
timeoutSeconds: 1
kubectl create -f pod.yaml
kubectl get pod
此时服务是running的,但是没有就绪,就绪探针检测没有通过
查看pod的日志时
kubuctl logs nginx1
可以看到原因是:在nginx的默认发布目录里找不到test.html文件
查看pod的详细信息,发现404报错:
describe pod nginx1
此时我们创建test.html,将test文件写入,通过探针的就绪检测
kubectl exec -it nginx1 -- sh
cd /uar/share/nginx/html
echo westos.org > test.html
当删除test.html文件,此时就绪检测又显示没有就绪,由此可以看出,就绪探针会在主pod运行过程中, 一直做检测
apiVersion: v1
kind: Pod
metadata:
name: myapp
spec:
containers:
- name: myapp
image: reg.westos.org/k8s/nginx
imagePullPolicy: IfNotPresent
readinessProbe:
httpGet:
path: /index.html
port: 80
initialDelaySeconds: 1
periodSeconds: 2
timeoutSeconds: 1
livenessProbe:
tcpSocket:
port: 80
initialDelaySeconds: 1
periodSeconds: 2
timeoutSeconds: 1
[kubeadm@server1 manifest]$ vim pod.yaml
[kubeadm@server1 manifest]$ kubectl create -f pod.yaml
pod/myapp created
[kubeadm@server1 manifest]$ kubectl get pod
NAME READY STATUS RESTARTS AGE
myapp 1/1 Running 0 6s
myapp-pod 1/1 Running 0 75m
test 1/1 Running 1 40m
[kubeadm@server1 manifest]$