文章目录
一、pod基本介绍
pod是一组容器,一组容器可以是多个容器也可以是单个容器(不包括系统内置的容器),当一个pod包含多个容器时,多个容器运行在同一个工作节点上,一个pod中的多个容器绝不会跨多个节点。
1、pod的名称空间
pod中可以包含多个容器或单个容器,pod中包含多个容器时,多个容器是共享命名空间的,pod中多个容器可以进行进程通信,可以共享网络空间。但pod中每个容器的文件系统是相互隔离的,不过可以通过Volume进行文件系统共享。
2、pod的网络空间
pod中的容器共享网络命名空间,因此pod中容器共享相同的IP和端口,这就要求pod中的容器不能绑定到相同的端口,否则会导致端口冲突,对于不同的pod不会导致端口冲突。共享网络命名空间允许pod中的容器可以通过localhost进行通信。
k8s集群中pod共享网络地址地址空间,允许一个pod通过另一个pod的IP地址进行访问。
3、pod优点
-
有利于进程隔离
每个pod中运行一个容器,每个容器中只运行一个进程,当一个进程崩溃后不会影响到其它进程的执行。如果是以前的胖系统中,所有的应用都部署在一起,当其中的一个应用进程崩溃后导致整个系统崩溃,现在每个应用部署在一个pod的容器中,当一个应用崩溃后不会导致其它的pod中的应用崩溃。 -
有利于横向扩缩pod
像以前胖系统中,所有应用部署在一起,当修改其中的一个应用后就要对整个系统进行变更,有个pod后,每个应用部署在不同的pod中,当一个应用变更时,只需要修改相应pod的应用就可以,减小了整个系统的风险。另外对于胖系统,如果某个应用访问量大,如果要扩容就要对整个系统就行扩容,导致资源浪费,有了pod后,只需要对访问量大的pod进行横向扩展pod就可以了,减少了资源的浪费。
二、pod基本操作
1、创建pod
以nginx为例,通过yaml创建运行nginx的pod,下面建立niginx的yaml文件
pod_nginx.yaml
apiVersion: v1 #k8s的版本
kind: Pod #资源类型
metadata: #描述信息
name: nginxpod #pod的名称
spec: #pod的说明信息
containers: #定义pod中运行的容器
- image: nginx #运行容器的镜像
name: nginxcontainer #pod中运行的容器的名字
ports: #定义容器暴露的端口
- containerPort: 80 #容器端口
protocol: TCP #端口协议
创建完pod的yaml描述信息后,下面通过yaml描述的pod
kubectl create -f pod_nginx.yaml
表示创建pod成功。
2、查询pod
- 查看创建的pod
kubectl get pod
- 查看pod的节点等详细信息
kubectl get pod -o wide
- 获取pod的yaml完整描述
kubectl get pod -o yaml
- 查看pod日志
如果pod中只有一个容器,可以直接获取pod的日志
kubectl logs nginxpod
如果pod中有多个容器,可以用-c指定查看哪个容器中日志
kubectl logs nginxpod -c nginxcontainer
3、pod标签
k8s集群中有大规模的pod,通过pod的标签可以有效的获取、筛选、组织pod,pod标签在pod创建时进行添加。
- 创建带标签的pod
apiVersion: v1
kind: Pod
metadata:
name: nginxpod
labels:
app: nginx #pod的标签为app和sit,可以添加一个或多个标签
env: sit
spec:
containers:
- image: nginx
name: nginxcontainer
ports:
- containerPort: 80
protocol: TCP
- 查询带标签的pod
–show-labels表示查询显示pod时,带上标签信息
kubectl get pod --show-labels
查询pod时,按指定的app,env标签显示pod信息。
kubectl get pod -L app,env
- 修改标签
创建pod时未添加标签的,可以手动添加标签
kubectl label pod nginxpod2 app=nginxpod2
创建pod时带标签,后期想修改覆盖原标签
kubectl label pod nginxpod env=debug --overwrite
4、标签选择器
- 筛选出app=nginx的标签的pod
kubectl get pod -l app=nginx
- 筛选出所有含有app标签的pod
kubectl get pod -l app
- 筛选出不含有app标签的pod
kubectl get pod -l '!app' #注意添加引号
- 筛选出标签为app,但值不为nginx的pod
kubectl get pod -l app!=nginx
- 筛选出标签app等于nginx或者js的pod
kubectl get pod -l 'app in (nginx,js)'
- 筛选出标签app不等于nginx和js的pod
kubectl get pod -l 'app notin (nginx,js)'
- pod调度到指定标签的节点上
apiVersion: v1
kind: Pod
metadata:
name: nginxpod
labels:
app: nginx
env: sit
spec:
nodeSelector: #pod调度到含有标签nas=true的节点上
nas: "true"
containers:
- image: nginx
name: nginxcontainer
ports:
- containerPort: 80
protocol: TCP
5、对pod添加注解
pod中注解起到注释信息的作用,就想java程序中的注释信息一样。
下面为创建的pod添加注解信息
kubectl annotate pod nginxpod pod/author="lzj default"
为nginxpod添加了注解信息pod/author=“lzj default”,添加注解信息后,可以通过kubectl describe pod nginxpod 查看添加的注解信息。添加注解信息时也可以在yaml中配置。
6、删除pod
- 按名称删除pod
kubectl delete pod mypod #按pod名称删除pod
- 按标签选择器删除pod
kubectl delete pod -l app=nginx #删除标签为nginx的pod
- 删除名称空间中所有pod
kubectl delete namespace myspace #删除myspace名称空间中所有的pod
kubectl delete pod --all #删除默认名称空间中所有的pod
- 删除所有资源
kubectl delete all --all
三、pod生命周期
一般pod中运行一个应用容器,但除了主应用容器外还有其他容器,当一个pod被创建后,首先启动的是pause容器,也是每个pod都会默认创建的容器,用于初始pod中网络;其次pod也可以有一个或多个init初始化容器,也可没有,主要负责应用启动前的初始化工作,注意一点,不管有几个init容器,一定是一个init容器停止后,另一个init容器才会创建;等init容器创建并停止后,主应用容器被创建,主应用容器也可以由start和stop操作;最后主应用容器被创建后,也可以为应用容器添加探针容器,主要用于pod中主应用容器的健康检查。
四、Init容器
pod中可以有一个或多个先于主应用容器的Init容器,每一个Init容器都必须成功结束后才会启动下一个Init容器或者主应用容器。如果Init容器启动失败,k8s会不断的重启pod,如果restartPolicy为Never,则k8s不会重新启动pod。
Init应用场景:
- 为应用安装的工具;
- 应用之前的初始化工作;
- 可以访问系统的Secret权限;
- 提供了一种简单的阻塞或延迟应用容器启动的方法。
下面通过一个示例演示Init容器的用法,以pod_init.yaml为例:
metadata:
name: mypod
labels:
app: pod
env: sit
spec:
containers:
- image: busybox
imagePullPolicy: IfNotPresent
name: main-container
command: ['sh', '-c', 'echo main-container is successfully > /root/test.txt && sleep 3600']
initContainers:
- name: init-container
image: busybox
imagePullPolicy: IfNotPresent
command: ['sh', '-c', 'sleep 30']
首先在创建main-container主应用服务器之前创建了init-container初始化容器,镜像都为busybox,Init服务器创建后休眠30s,然后退出,Init容器成功退出后,main-container主应用容器才开始创建,主应用容器创建后,把日志写入/root/test.txt文件中,并休眠1小时。下面通过kubectl create -f pod_init.yaml创建pod,然后查看init容器和主容器运行情况
注意:
- Pod启动过程中,Init容器必须在pause容器启动后启动;
- Init容器如果启动失败,会根据pod的restartPolicy策略进行重启;
- Init容器没有成功之前,Pod不会变成ready状态,Init的端口也不会在service进行聚集;
- 如果pod重启,所有的Init容器都必须重启;
- 修改Init容器的镜像就会导致pod重启。
五、探针
有时候pod中容器进程没有崩溃,但容器中运行的程序崩溃,不会导致k8s重启pod,因此就不方便知道应用是否正常。通过探针对容器定期进行诊断,可实时了解容器内部运行情况,探针是由kubelet对容器进行的定期诊断。kubelet可以通过如下三种方式对对容器进行诊断:
- ExecAction: 在容器内执行命令,如果命令退出时返回码为0则认为诊断成功;
- TCPSocketAction: 对指定端口上的容器IP进行TCP检查,如果端口打开,则诊断成功;
- HTTPGetAction: 对指定的端口和路径上的IP执行http get请求,如果响应状态码大于等于200且小于400,则诊断成功。
每次探测结果都是如下情况:
- 成功:容器诊断成功;
- 失败:容器诊断失败,根据重启策略决定pod重启;
- 未知:不会采取任何行动
探针分两种形式:
- livenessProbe: 指示容器是否正在运行。如果存活检测失败,则kubelet会杀死容器,并将pod根据重启策略进行重启,如果容器不提供存活探针,默认状态为success,pod不会重启。
- readinessProbe: 指示容器是否准备好服务请求。如果ReadinessProbe探针检测到失败,则Pod的状态被修改。Endpoint Controller将从Service的Endpoint中删除包含该容器所在Pod的Endpoint。如果探测器失败,但主容器中的应用启动正常,pod的状态是未就绪状态,但应用可以正常访问。
两种探针用法相同,下面以livenessProbe探针为例
1、通过ExecAction形式进行诊断
创建yaml如下
apiVersion: v1
kind: Pod
metadata:
name: live-exec-pod
namespace: default
spec:
containers:
- name: live-exec-container
image: busybox
imagePullPolicy: IfNotPresent
command: ["/bin/sh", "-c", "echo hello > /tmp/hello.txt; sleep 10; rm /tmp/hello.txt; sleep 3600"]
livenessProbe:
exec:
command: ["test", "-e", "/tmp/hello.txt"]
initialDelaySeconds: 1 #容器启动后1s后开始探测
periodSeconds: 3 #每隔3秒钟探测一次
上面yaml定义了,当live-exec-container启动后,会有一个livenessProbe探测器,从容器启动后1s后开始通过[“test”, “-e”, “/tmp/hello.txt”]命令探测容器,如果返回0,探测成功,如果返回非0,探测失败,pod重启
[root@k8s-master01 work]# kubectl create -f pod_live_exec.yaml
pod/live-exec-pod created
[root@k8s-master01 work]# kubectl get pod -w
NAME READY STATUS RESTARTS AGE
live-exec-pod 1/1 Running 0 4s
live-exec-pod 1/1 Running 1 49s
live-exec-pod 1/1 Running 2 97s
live-exec-pod 1/1 Running 3 2m26s
..............
2、通过HTTPGetAction形式进行诊断
创建yaml如下
apiVersion: v1
kind: Pod
metadata:
name: live-http-pod
namespace: default
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
livenessProbe:
httpGet:
port: 80
path: /hello.html
initialDelaySeconds: 0 #nginx容器启动后开始执行探针
periodSeconds: 5 #探针每5秒钟探测一次
timeoutSeconds: 20 #20s后探针退出
创建nginx容器后,livenessProbe探针会对/hello.html路径和端口80进行http get请求,每5s进行探测一次,超时时间为20s。
[root@k8s-master01 work]# kubectl create -f pod_live_http.yaml
pod/live-http-pod created
[root@k8s-master01 work]# kubectl get pod -w
NAME READY STATUS RESTARTS AGE
live-http-pod 1/1 Running 0 11s
live-http-pod 1/1 Running 1 15s
live-http-pod 1/1 Running 2 30s
live-http-pod 1/1 Running 3 45s
live-http-pod 0/1 CrashLoopBackOff 3 59s
3、通过TCPSocketAction形式进行
创建yaml如下
apiVersion: v1
kind: Pod
metadata:
name: live-sock-pod
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
livenessProbe:
initialDelaySeconds: 2
timeoutSeconds: 1
tcpSocket:
port: 90
创建nginx容器后,探针会2s后对90端口进行探测,单次探测超时时间为1s,如果端口不通,会重启pod。
[root@k8s-master01 work]# kubectl create -f pod_live_sock.yaml
pod/live-sock-pod created
[root@k8s-master01 work]# kubectl get pod -w
NAME READY STATUS RESTARTS AGE
live-sock-pod 1/1 Running 0 8s
live-sock-pod 1/1 Running 1 27s
live-sock-pod 1/1 Running 2 57s
以上是livenessProbe的三种用法,readinessProbe用法完全相同。
六、主容器start/stop操作
pod中主容器启动启动后可以执行初始化内容,比如构建一些应用的环境变量等,或初始化数据库等;主容器结束前可以执行应用的清理工作、数据库清理工作等。可以通过postStart指定容器的初始化步骤,通过preStop指定容器的清理步骤。
创建yaml示例如下:
apiVersion: v1
kind: Pod
metadata:
name: start-stop-pod
spec:
containers:
name: start-stop-container
image: busybox
imagePullPolicy: IfNotPresent
command: ["/bin/sh", "-c", "sleep 20"]
lifecycle:
postStart: #执行初始化工作
exec:
command: ["/bin/sh", "-c", "echo start pod > /tmp/pod.txt"]
preStop: #执行清理工作
exec:
command: ["/bin/sh", "-c", "rm -rf /tmp/pod.txt"]
七、pod生命周期状态
通过pod的状态可以得知pod运行情况,pod从创建到死亡全部的声明周期状态如下所示
1. Pending(挂起)
pod已被k8s管理,但pod中容器尚未全部创建,pod调度花费时间以及网络下载镜像事前全部在该状态下完成。
2. Running(运行中)
Pod中所有容器已被创建,Running状态不表示所有容器已经创建成功,可以表示容器已经正常启动成功,也可以表示容器正处于启动或重启过程中。
3. Succeeded(成功)
pod中所有容器被成功终止,并且不会再重新启动。
4. Failed(失败)
Pod中所有已被终止,并且至少有一个容器因失败为终止,容器以非0状态退出。
5. Unknow(未知)
无法与pod取得联系,一般pod脱离了k8s管理,通常原因pod与主机通信失败。