pod是一组容器,一组容器可以是多个容器也可以是单个容器(不包括系统内置的容器),当一个pod包含多个容器时,多个容器运行在同一个工作节点上,一个pod中的多个容器绝不会跨多个节点。
pod中可以包含多个容器或单个容器,pod中包含多个容器时,多个容器是共享命名空间的,pod中多个容器可以进行进程通信,可以共享网络空间。但pod中每个容器的文件系统是相互隔离的,不过可以通过Volume进行文件系统共享。
pod中的容器共享网络命名空间,因此pod中容器共享相同的IP和端口,这就要求pod中的容器不能绑定到相同的端口,否则会导致端口冲突,对于不同的pod不会导致端口冲突。共享网络命名空间允许pod中的容器可以通过localhost进行通信。
k8s集群中pod共享网络地址地址空间,允许一个pod通过另一个pod的IP地址进行访问。
有利于进程隔离
每个pod中运行一个容器,每个容器中只运行一个进程,当一个进程崩溃后不会影响到其它进程的执行。如果是以前的胖系统中,所有的应用都部署在一起,当其中的一个应用进程崩溃后导致整个系统崩溃,现在每个应用部署在一个pod的容器中,当一个应用崩溃后不会导致其它的pod中的应用崩溃。
有利于横向扩缩pod
像以前胖系统中,所有应用部署在一起,当修改其中的一个应用后就要对整个系统进行变更,有个pod后,每个应用部署在不同的pod中,当一个应用变更时,只需要修改相应pod的应用就可以,减小了整个系统的风险。另外对于胖系统,如果某个应用访问量大,如果要扩容就要对整个系统就行扩容,导致资源浪费,有了pod后,只需要对访问量大的pod进行横向扩展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成功。
kubectl get pod
kubectl get pod -o wide
kubectl get pod -o yaml
kubectl logs nginxpod
如果pod中有多个容器,可以用-c指定查看哪个容器中日志
kubectl logs nginxpod -c nginxcontainer
k8s集群中有大规模的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
kubectl get pod --show-labels
查询pod时,按指定的app,env标签显示pod信息。
kubectl get pod -L app,env
kubectl label pod nginxpod2 app=nginxpod2
创建pod时带标签,后期想修改覆盖原标签
kubectl label pod nginxpod env=debug --overwrite
kubectl get pod -l app=nginx
kubectl get pod -l app
kubectl get pod -l '!app' #注意添加引号
kubectl get pod -l app!=nginx
kubectl get pod -l 'app in (nginx,js)'
kubectl get pod -l 'app notin (nginx,js)'
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
pod中注解起到注释信息的作用,就想java程序中的注释信息一样。
下面为创建的pod添加注解信息
kubectl annotate pod nginxpod pod/author="lzj default"
为nginxpod添加了注解信息pod/author=“lzj default”,添加注解信息后,可以通过kubectl describe pod nginxpod 查看添加的注解信息。添加注解信息时也可以在yaml中配置。
kubectl delete pod mypod #按pod名称删除pod
kubectl delete pod -l app=nginx #删除标签为nginx的pod
kubectl delete namespace myspace #删除myspace名称空间中所有的pod
kubectl delete pod --all #删除默认名称空间中所有的pod
kubectl delete all --all
一般pod中运行一个应用容器,但除了主应用容器外还有其他容器,当一个pod被创建后,首先启动的是pause容器,也是每个pod都会默认创建的容器,用于初始pod中网络;其次pod也可以有一个或多个init初始化容器,也可没有,主要负责应用启动前的初始化工作,注意一点,不管有几个init容器,一定是一个init容器停止后,另一个init容器才会创建;等init容器创建并停止后,主应用容器被创建,主应用容器也可以由start和stop操作;最后主应用容器被创建后,也可以为应用容器添加探针容器,主要用于pod中主应用容器的健康检查。
pod中可以有一个或多个先于主应用容器的Init容器,每一个Init容器都必须成功结束后才会启动下一个Init容器或者主应用容器。如果Init容器启动失败,k8s会不断的重启pod,如果restartPolicy为Never,则k8s不会重新启动pod。
Init应用场景:
下面通过一个示例演示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中容器进程没有崩溃,但容器中运行的程序崩溃,不会导致k8s重启pod,因此就不方便知道应用是否正常。通过探针对容器定期进行诊断,可实时了解容器内部运行情况,探针是由kubelet对容器进行的定期诊断。kubelet可以通过如下三种方式对对容器进行诊断:
每次探测结果都是如下情况:
探针分两种形式:
两种探针用法相同,下面以livenessProbe探针为例
创建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
..............
创建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
创建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用法完全相同。
pod中主容器启动启动后可以执行初始化内容,比如构建一些应用的环境变量等,或初始化数据库等;主容器结束前可以执行应用的清理工作、数据库清理工作等。可以通过postStart指定容器的初始化步骤,通过preStop指定容器的清理步骤。
创建yaml示例如下:
apiVersion: v1
kind: Pod
metadata:
name: start-stop-pod
spec:
containers:
1. 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从创建到死亡全部的声明周期状态如下所示
1. Pending(挂起)
pod已被k8s管理,但pod中容器尚未全部创建,pod调度花费时间以及网络下载镜像事前全部在该状态下完成。
2. Running(运行中)
Pod中所有容器已被创建,Running状态不表示所有容器已经创建成功,可以表示容器已经正常启动成功,也可以表示容器正处于启动或重启过程中。
3. Succeeded(成功)
pod中所有容器被成功终止,并且不会再重新启动。
4. Failed(失败)
Pod中所有已被终止,并且至少有一个容器因失败为终止,容器以非0状态退出。
5. Unknow(未知)
无法与pod取得联系,一般pod脱离了k8s管理,通常原因pod与主机通信失败。