下面包括了pod的常用特性配置,让我们一一解答吧。
apiVersion: v1 #必选,版本号,例如v1
kind: Pod #必选,资源类型,例如 Pod
metadata: #必选,元数据
name: string #必选,Pod名称
namespace: string #Pod所属的命名空间,默认为"default"
labels: #自定义标签列表
- name: string
spec: #必选,Pod中容器的详细定义
containers: #必选,Pod中容器列表
- name: string #必选,容器名称
image: string #必选,容器的镜像名称
imagePullPolicy: [ Always|Never|IfNotPresent ] #获取镜像的策略
command: [string] #容器的启动命令列表,如不指定,使用打包时使用的启动命令
args: [string] #容器的启动命令参数列表
workingDir: string #容器的工作目录
volumeMounts: #挂载到容器内部的存储卷配置
- name: string #引用pod定义的共享存储卷的名称,需用volumes[]部分定义的的卷名
mountPath: string #存储卷在容器内mount的绝对路径,应少于512字符
readOnly: boolean #是否为只读模式
ports: #需要暴露的端口库号列表
- name: string #端口的名称
containerPort: int #容器需要监听的端口号
hostPort: int #容器所在主机需要监听的端口号,默认与Container相同
protocol: string #端口协议,支持TCP和UDP,默认TCP
env: #容器运行前需设置的环境变量列表
- name: string #环境变量名称
value: string #环境变量的值
resources: #资源限制和请求的设置
limits: #资源限制的设置
cpu: string #Cpu的限制,单位为core数,将用于docker run --cpu-shares参数
memory: string #内存限制,单位可以为Mib/Gib,将用于docker run --memory参数
requests: #资源请求的设置
cpu: string #Cpu请求,容器启动的初始可用数量
memory: string #内存请求,容器启动的初始可用数量
lifecycle: #生命周期钩子
postStart: #容器启动后立即执行此钩子,如果执行失败,会根据重启策略进行重启
preStop: #容器终止前执行此钩子,无论结果如何,容器都会终止
livenessProbe: #对Pod内各容器健康检查的设置,当探测无响应几次后将自动重启该容器
exec: #对Pod容器内检查方式设置为exec方式
command: [string] #exec方式需要制定的命令或脚本
httpGet: #对Pod内个容器健康检查方法设置为HttpGet,需要制定Path、port
path: string
port: number
host: string
scheme: string
HttpHeaders:
- name: string
value: string
tcpSocket: #对Pod内个容器健康检查方式设置为tcpSocket方式
port: number
initialDelaySeconds: 0 #容器启动完成后首次探测的时间,单位为秒
timeoutSeconds: 0 #对容器健康检查探测等待响应的超时时间,单位秒,默认1秒
periodSeconds: 0 #对容器监控检查的定期探测时间设置,单位秒,默认10秒一次
successThreshold: 0
failureThreshold: 0
securityContext:
privileged: false
restartPolicy: [Always | Never | OnFailure] #Pod的重启策略
nodeName: <string> #设置NodeName表示将该Pod调度到指定到名称的node节点上
nodeSelector: obeject #设置NodeSelector表示将该Pod调度到包含这个label的node上
imagePullSecrets: #Pull镜像时使用的secret名称,以key:secretkey格式指定
- name: string
hostNetwork: false #是否使用主机网络模式,默认为false,如果设置为true,表示使用宿主机网络
volumes: #在该pod上定义共享存储卷列表
- name: string #共享存储卷名称 (volumes类型有很多种)
emptyDir: {} #类型为emtyDir的存储卷,与Pod同生命周期的一个临时目录。为空值
hostPath: string #类型为hostPath的存储卷,表示挂载Pod所在宿主机的目录
path: string #Pod所在宿主机的目录,将被用于同期中mount的目录
secret: #类型为secret的存储卷,挂载集群与定义的secret对象到容器内部
scretname: string
items:
- key: string
path: string
configMap: #类型为configMap的存储卷,挂载预定义的configMap对象到容器内部
name: string
items:
- key: string
path: string
下面定义了一个比较简单Pod的配置,里面有一个nginx容器。
apiVersion: v1
kind: Pod
metadata:
name: pod-base
namespace: dev
labels:
user: zhanggang
spec:
containers:
- name: nginx
image: nginx:1.17.1
imagePullPolicy,用于设置镜像拉取策略,k8s支持配置三种拉取策略:
镜像拉取策略默认值说明
1、如果镜像tag为具体版本号, 默认策略是:IfNotPresent
2、如果镜像tag为:latest(最新版本) ,默认策略是always
command,用于在pod中的容器初始化完毕之后运行一个命令。
command: ["/bin/sh","-c","touch /tmp/hello.txt;while true;do /bin/echo $(date +%T) >> /tmp/hello.txt; sleep 3; done;"]
"/bin/sh","-c", 使用sh执行命令
touch /tmp/hello.txt; 创建一个/tmp/hello.txt 文件
while true;do /bin/echo $(date +%T) >> /tmp/hello.txt; sleep 3; done; 每隔3秒向文件中写入当前时间
env,环境变量,用于在pod中的容器设置环境变量。
这种方式不是很推荐,推荐将这些配置单独存储在配置文件中,这种方式将在后面介绍。
apiVersion: v1
kind: Pod
metadata:
name: pod-env
namespace: dev
spec:
containers:
- name: nginx
image: nginx:1.17.1
command: ["/bin/sh","-c","while true;do /bin/echo $(date +%T);sleep 60; done;"]
env: # 设置环境变量列表
- name: "username"
value: "admin"
- name: "password"
value: "123456"
容器的端口,也就是设置该容器暴露的端口。
apiVersion: v1
kind: Pod
metadata:
name: pod-ports
namespace: dev
spec:
containers:
- name: nginx
image: nginx:1.17.1
ports: # 设置容器暴露的端口列表
- name: nginx-port
containerPort: 80
protocol: TCP
容器中的程序要运行,肯定是要占用一定资源的,比如cpu和内存等,如果不对某个容器的资源做限制,那么它就可能吃掉大量资源,导致其它容器无法运行。针对这种情况,kubernetes提供了对内存和cpu的资源进行配额的机制,这种机制主要通过resources选项实现。
limits:用于限制运行时容器的最大占用资源,当容器占用资源超过limits时会被终止,并进行重启。
requests :用于设置容器需要的最小资源,如果环境资源不够,容器将无法启动。
cpu:core数,可以为整数或小数。
memory: 内存大小,可以使用Gi、Mi、G、M等形式。
apiVersion: v1
kind: Pod
metadata:
name: pod-resources
namespace: dev
spec:
containers:
- name: nginx
image: nginx:1.17.1
resources: # 资源配额
limits: # 限制资源(上限)
cpu: "2" # CPU限制,单位是core数
memory: "10Gi" # 内存限制
requests: # 请求资源(下限)
cpu: "1" # CPU限制,单位是core数
memory: "10Mi" # 内存限制
我们一般将pod对象从创建至终的这段时间范围称为pod的生命周期,它主要包含下面的过程:
容器启动后钩子(post start)、容器终止前钩子(pre stop)。
容器的存活性探测(liveness probe)、就绪性探测(readiness probe)。
在整个生命周期中,Pod会出现5种状态(相位),分别如下:
1、挂起(Pending):apiserver已经创建了pod资源对象,但它尚未被调度完成或者仍处于下载镜像的过程中
2、运行中(Running):pod已经被调度至某节点,并且所有容器都已经被kubelet创建完成
3、成功(Succeeded):pod中的所有容器都已经成功终止并且不会被重启
4、失败(Failed):所有容器都已经终止,但至少有一个容器终止失败,即容器返回了非0值的退出状态
5、未知(Unknown):apiserver无法正常获取到pod对象的状态信息,通常由网络通信失败所导致
1、用户通过kubectl或其他api客户端提交需要创建的pod信息给apiServer
2、apiServer开始生成pod对象的信息,并将信息存入etcd,然后返回确认信息至客户端
3、apiServer开始反映etcd中的pod对象的变化,其它组件使用watch机制来跟踪检查apiServer上的变动
4、scheduler发现有新的pod对象要创建,开始为Pod分配主机并将结果信息更新至apiServer
5、node节点上的kubelet发现有pod调度过来,尝试调用docker启动容器,并将结果回送至apiServer
6、apiServer将接收到的pod状态信息存入etcd中
1、用户向apiServer发送删除pod对象的命令
2、apiServcer中的pod对象信息会随着时间的推移而更新,在宽限期内(默认30s),pod被视为dead
3、将pod标记为terminating状态
4、kubelet在监控到pod对象转为terminating状态的同时启动pod关闭过程
5、端点控制器监控到pod对象的关闭行为时将其从所有匹配到此端点的service资源的端点列表中移除
6、如果当前pod对象定义了preStop钩子处理器,则在其标记为terminating后即会以同步的方式启动执行
7、pod对象中的容器进程收到停止信号
8、宽限期结束后,若pod中还存在仍在运行的进程,那么pod对象会收到立即终止的信号
9、kubelet请求apiServer将此pod资源的宽限期设置为0从而完成删除操作,此时pod对于用户已不可见
pod中引入了初始化容器概念,初始化容器是在pod的主容器启动之前要运行的容器,主要是做一些主容器的前置工作,它具有两大特征:
1、初始化容器必须运行完成直至结束,若某初始化容器运行失败,那么kubernetes需要重启它直到成功完成
2、初始化容器必须按照定义的顺序执行,当且仅当前一个成功之后,后面的一个才能运行
列举初始化容器使用场景:
1、提供主容器镜像中不具备的工具程序或自定义代码
2、初始化容器要先于应用容器串行启动并运行完成,因此可用于延后应用容器的启动直至其依赖的条件得到满足。
初始化容器案例
假设要以主容器来运行nginx,但是要求在运行nginx之前先要能够连接上mysql和redis所在服务器。
创建pod-initcontainer.yaml,内容如下:
下面两个初始化容器所连接的IP都不存在,可以发现Pod是起不来的。
apiVersion: v1
kind: Pod
metadata:
name: pod-initcontainer
namespace: dev
spec:
containers:
- name: main-container
image: nginx:1.17.1
ports:
- name: nginx-port
containerPort: 80
initContainers:
- name: test-mysql
image: busybox:1.30
command: ['sh', '-c', 'until ping 192.168.90.14 -c 1 ; do echo waiting for mysql...; sleep 2; done;']
- name: test-redis
image: busybox:1.30
command: ['sh', '-c', 'until ping 192.168.90.15 -c 1 ; do echo waiting for reids...; sleep 2; done;']
什么是钩子函数呢?就是在主容器的启动之后和停止之前提供的两个函数。
钩子处理器支持使用下面三种方式定义动作:
1、Exec命令:在容器内执行一次命令
lifecycle:
postStart:
exec:
command:
- cat
- /tmp/healthy
2、TCPSocket:在当前容器尝试访问指定的socket
lifecycle:
postStart:
tcpSocket:
port: 8080
3、HTTPGet:在当前容器中向某url发起http请求
lifecycle:
postStart:
httpGet:
path: / #URI地址
port: 80 #端口号
host: 127.0.0.1 #主机地址
scheme: HTTP #支持的协议,http或者https
接下来,以exec方式为例,演示下钩子函数的使用,创建pod-hook-exec.yaml文件,内容如下:
apiVersion: v1
kind: Pod
metadata:
name: pod-hook-exec
namespace: dev
spec:
containers:
- name: main-container
image: nginx:1.17.1
ports:
- name: nginx-port
containerPort: 80
lifecycle:
postStart:
exec: # 在容器启动的时候执行一个命令,修改掉nginx的默认首页内容
command: ["/bin/sh", "-c", "echo postStart... > /usr/share/nginx/html/index.html"]
preStop:
exec: # 在容器停止之前停止nginx服务
command: ["/usr/sbin/nginx","-s","quit"]
容器探测用于检测容器中的应用实例是否正常工作,是保障业务可用性的一种传统机制。如果经过探测,实例的状态不符合预期,那么k8s就会把该问题实例" 摘除 ",不承担业务流量。k8s提供了两种探针来实现容器探测,分别是:
1、liveness probes: 存活性探针,用于检测应用实例当前是否处于正常运行状态,如果不是,k8s会重启容器。
2、readiness probes: 就绪性探针,用于检测应用实例当前是否可以接收请求,如果不能,k8s不会转发流量。
区别:livenessProbe 决定是否重启容器,readinessProbe 决定是否将请求转发给容器。
上面两种探针目前均支持下面三种探测方式:
1、Exec命令:在容器内执行一次命令,如果命令执行的退出码为0,则认为程序正常,否则不正常。
livenessProbe:
exec:
command:
- cat
- /tmp/healthy
2、TCPSocket:将会尝试访问一个用户容器的端口,如果能够建立这条连接,则认为程序正常,否则不正常。
livenessProbe:
tcpSocket:
port: 8080
3、HTTPGet:调用容器内Web应用的URL,如果返回的状态码在200和399之间,则认为程序正常,否则不正常。
livenessProbe:
httpGet:
path: / #URI地址
port: 80 #端口号
host: 127.0.0.1 #主机地址
scheme: HTTP #支持的协议,http或者https
举例探测失败重启
apiVersion: v1
kind: Pod
metadata:
name: pod-liveness-httpget
namespace: default
spec:
containers:
- name: nginx
image: nginx:1.17.1
ports:
- name: nginx-port
containerPort: 80
livenessProbe:
httpGet: # 其实就是访问http://127.0.0.1:80/hello
scheme: HTTP #支持的协议,http或者https
port: 80 #端口号
path: /hello #URI地址
initialDelaySeconds: 30 # 容器启动后30s开始探测
timeoutSeconds: 5 # 探测超时时间为5s
创建pod,观察效果
发现pod一直在重启,说明接口http://127.0.0.1:80/hello 是不存在的。
kubectl describe pod pod-liveness-httpget
查看pod的详细信息,发现报的是livenessprobe失败,访问404找不到接口。
在上面容器探测出现了问题,kubernetes就会对容器所在的Pod进行重启,其实这是由pod的重启策略决定的,pod的重启策略有 3 种,分别如下:
重启策略适用于pod对象中的所有容器,首次需要重启的容器,将在其需要时立即进行重启,随后再次需要重启的操作将由kubelet延迟一段时间后进行,且反复的重启操作的延迟时长以此为10s、20s、40s、80s、160s和300s,300s是最大延迟时长。
创建pod-restartpolicy.yaml:
apiVersion: v1
kind: Pod
metadata:
name: pod-restartpolicy
namespace: dev
spec:
containers:
- name: nginx
image: nginx:1.17.1
ports:
- name: nginx-port
containerPort: 80
livenessProbe:
httpGet:
scheme: HTTP
port: 80
path: /hello
restartPolicy: Never # 设置重启策略为Never
Pod是k8s的最小管理单元,在k8s中,按照pod的创建方式可以将其分为两类:
1、自主式pod:kubernetes直接创建出来的Pod,这种pod删除后就没有了,也不会重建。
2、控制器创建的pod:kubernetes通过控制器创建的pod,这种pod删除了之后还会自动重建。项目中基本都用第二种。
什么是Pod控制器?
Pod控制器是管理pod的中间层,使用Pod控制器之后,只需要告诉Pod控制器,想要多少个什么样的Pod就可以了,它会创建出满足条件的Pod并确保每一个Pod资源处于用户期望的目标状态。如果Pod资源在运行中出现故障,它会基于指定策略重新编排Pod。
在k8s中,有很多类型的pod控制器,每种都有自己的适合的场景,常见的有下面这些:
1、ReplicationController:比较原始的pod控制器,已经被废弃,由ReplicaSet替代
2、ReplicaSet:保证副本数量一直维持在期望值,并支持pod数量扩缩容,镜像版本升级
3、Deployment:通过控制ReplicaSet来控制Pod,并支持滚动升级、回退版本
4、Horizontal Pod Autoscaler:可以根据集群负载自动水平调整Pod的数量,实现削峰填谷
5、DaemonSet:在集群中的指定Node上运行且仅运行一个副本,一般用于守护进程类的任务
6、Job:它创建出来的pod只要完成任务就立即退出,不需要重启或重建,用于执行一次性任务
7、Cronjob:它创建的Pod负责周期性任务控制,不需要持续后台运行
8、StatefulSet:管理有状态应用。
项目中经常用的控制器是Deployment。
为了更好的解决服务编排的问题,k8s在V1.2版本开始,引入了Deployment控制器。值得一提的是,这种控制器并不直接管理pod,而是通过管理ReplicaSet来简介管理Pod,即:Deployment管理ReplicaSet,ReplicaSet管理Pod。所以Deployment比ReplicaSet功能更加强大。
Deployment主要功能有下面几个:
1、支持ReplicaSet的所有功能
2、支持发布的停止、继续
3、支持滚动升级和回滚版本。
创建pc-deployment.yaml,内容如下:
apiVersion: apps/v1
kind: Deployment
metadata:
name: pc-deployment
namespace: default
spec:
replicas: 3
selector:
matchLabels:
app: nginx-pod
template:
metadata:
labels:
app: nginx-pod
spec:
containers:
- name: nginx
image: nginx:1.17.1
//介绍两种扩缩容的方式
//如果指定namespace的话,需要加-n 参数
1、直接命令修改
kubectl scale deploy deploy名称 --replicas=5
2、编辑deployment的副本数量,修改spec:replicas即可
kubectl edit deploy deploy名称
deployment支持两种更新策略:重建更新和滚动更新,可以通过strategy指定策略类型,支持两个属性:
strategy:指定新的Pod替换旧的Pod的策略, 支持两个属性:
type:指定策略类型,支持两种策略
Recreate:在创建出新的Pod之前会先杀掉所有已存在的Pod
RollingUpdate:滚动更新,就是杀死一部分,就启动一部分,在更新过程中,存在两个版本Pod
rollingUpdate:当type为RollingUpdate时生效,用于为RollingUpdate设置参数,支持两个属性:
maxUnavailable:用来指定在升级过程中不可用Pod的最大数量,默认为25%。
max违规词汇: 用来指定在升级过程中可以超过期望的Pod的最大数量,默认为25%。
只需要在deploy的yaml文件中加入下面配置即可
spec:
strategy: # 策略
type: RollingUpdate # 滚动更新策略
rollingUpdate:
max违规词汇: 25%
maxUnavailable: 25%
Deployment控制器支持控制更新过程中的控制,如“暂停(pause)”或“继续(resume)”更新操作。
比如有一批新的Pod资源创建完成后立即暂停更新过程,此时,仅存在一部分新版本的应用,主体部分还是旧的版本。然后,再筛选一小部分的用户请求路由到新版本的Pod应用,继续观察能否稳定地按期望的方式运行。确定没问题之后再继续完成余下的Pod资源滚动更新,否则立即回滚更新操作。这就是所谓的金丝雀发布,我们平常基本用不到金丝雀发布,就不在这举例了。
在k8s中,pod是应用程序的载体,我们可以通过pod的ip来访问应用程序,但是pod的ip地址不是固定的,这也就意味着不方便直接采用pod的ip对服务进行访问。
为了解决这个问题,kubernetes提供了Service资源,Service会对提供同一个服务的多个pod进行聚合,并且提供一个统一的入口地址。通过访问Service的入口地址就能访问到后面的pod服务。
apiVersion: v1
kind: Service
metadata:
name: service-clusterip
namespace: dev
spec:
selector:
app: nginx-pod
clusterIP: 10.97.97.97 # service的ip地址,如果不写,默认会生成一个
type: ClusterIP
ports:
- port: 80 # Service端口
targetPort: 80 # pod端口
对于yaml中的port、targetPort、nodePort和containerPort等理解,大家看port、targetPort、nodePort和containerPort区别。
clusterIP 创建的Service的ip地址只有集群内部才可以访问。
NodePort 就是将service的端口映射到Node的一个端口上,然后就可以通过NodeIp:NodePort来访问service。
apiVersion: v1
kind: Service
metadata:
name: service-nodeport
namespace: dev
spec:
selector:
app: nginx-pod
type: NodePort # service类型
ports:
- port: 80
nodePort: 30002 # 指定绑定的node的端口(默认的取值范围是:30000-32767), 如果不指定,会默认分配
targetPort: 80
k8s学习链接:
一、Kubernetes详解-(对k8s里面概念和名词的解释理解)
二、Kubernetes详解-(对k8s里namespace、pod、deployment、service的简单使用)
三、K8s详解-Pod、Pod控制器、Service特性详解