kubernetes Pod控制器
常用字段
spec.containers <[]object>
spec.containers.name <string> 容器的名称,必须字段,名称唯一且对象创建后不可以被修改
spec.containers.image <string> 镜像仓库的路径/镜像的名称:镜像的标签
spec.containers.image.imagePullPolicy <string> 镜像的下载策略。有三种:Always(总是去仓库下载) ,Never(从不去仓库下载) , IfNotPresent(如果本地没有就去仓库下载)
默认是"IfNotPresent" 但是,如果镜像的标签是latest,则总会是"Always,并且对象一旦被创建,这个字段不允许被改变
spec.containers.ports: 容器公开的端口列表。在这里公开端口可以为系统提供关于容器使用的网络连接的额外信息,但主要是提供信息。在这里不指定端口不会阻止该端口被公开。任何监听容器内默认的“0.0.0.0”地址的端口都可以从网络访问
spec.containers.ports.containerPort <integer> -required- pod暴露的端口,此端口仅是额外的信息,对端口是否被暴露没有影响
spec.containers.ports.hostPort <integer> 主机上公开的端口
spec.containers.ports.protocol <string> 端口的协议
spec.containers.ports.hostIP <string> 指定要绑定的主机
spec.containers.command <[]string> 运行的程序,类似于docker中的entrypiont,并且这里的命令不会运行在shell中,如果没有这个字段docker镜像会运行自己entrypiont中的指令
spec.containers.args <[]string> 向docker镜像中传递参数 如果定义了这个字段,docker镜像中cmd命令不会被执行,如果引用变量使用$(VAR_NAME)格式引用,如果想使用命令引用的的方式,需要使用
$$(VAR_NAME)方式来引用
关于args和command的官方文档链接:
https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/
pod.spec.containers.volumeMounts
pod.spec.containers.volumeMounts.name
pod.spec.containers.volumeMounts.mountPath 可以被容器挂载的存储卷的路径,路径不能包含':' 符号
pod.spec.containers.volumeMounts.subPath 可以被容器挂载的存储卷的路径,并且不会覆盖挂载点中的文件
pod.spec.containers.volumeMounts.readOnly 是否只读,默认为false
pod.spec.containers.resources
spec.containers.resources.limits 资源限制
spec.containers.resources.limits.cpu : CPU 上限, 可以短暂超过, 容器也不会被停止
spec.containers.resources.limits.memory : 内存上限, 不可以超过; 如果超过, 容器可能会被终止或调度到其他资源充足的机器上
spec.containers.resources.requests 资源需求
spec.containers.resources.requests.cpu : CPU 请求, 也是调度 CPU 资源的依据, 可以超过
spec.containers.resources.requests.memory : 内存请求, 也是调度内存资源的依据, 可以超过; 但如果超过, 容器可能会在 Node 内存不足时清理
spec.nodeSelector <map[string]string>
pod.spec.nodeSelector: 指定对象的调度节点,节点必须存在
pod.spec.restartPolicy <string>
pod.spec.restartPolicy:#容器的重启策略。有三种Always(只有退出就重启),
OnFailure(失败退出时不重启),Never(只要退出就不重启),kubelet重新启动的已退出容器将以指数退避延迟(10秒,20秒,40秒......)重新启动,上限为五分钟,并在成功执行十分钟后重置
标签
标签是K8s极具特色之一,一个资源可以拥有多个标签,同一个标签可以贴到不同的对象上
key=value
- key:字符,数字 _ - .只能以字母数字开头
- value:可以为空,只能以字母数字开头和结尾
标签选择器:
等值关系:=,==,!=
集合关系:KEY notin(VALUE1,VALUE2)
KEY notin (VALUE1,VALUE2)
KEY
!KEY
许多资源支持内嵌字段使用标签选择器:
matchLabels:直接给定健值
matchExpressions:基于给定的表达式来使用标签选择器{key:"KEY",operator:"OPERATOR",values:[VAL1,VAL2,...]}
操作符:
- In, NotIn:value字段的值必须为非空列表
- Exists,NotExists:values字段的值必须为空列表
查看所有 pod 的标签
kubectl get pods --show-labels
给一个资源添加 标签
kubectl label -h
给pod(type)pod-demo 打上一个标签
kubectl label pods pod-demo release=canary
修改原有的标签
kubectl label pods pod-demo release=canary1 --overwrite
给定一个标签对一个资源进行筛选
kubectl get pods -l app --show-labels
查看 node 标签
kubectl get nodes --show-labels
给 ubuntu node 打上一个标签 disktype=ssd
kubectl label node ubuntu disktype=ssd
通过节点选择器把一个 pod 部署到 指定的节点上
spec:
..............
nodeSelector:
disktype: ssd
.......................
容器探测机制
ExecAction 探针在容器内执行任意命令,并检查状态码。状态码为0,则探测成功
TCPSockeAction 尝试与容器的指定端口建立TCP连接,成功建立,则探测成功
HTTPGetAction 对容器的IP地址执行 HTTP GET 请求,如果响应状态码不代表错误,则探测成功
以 ExecAction 方式对pod进行存活性探测
liveness-exec.yaml
apiVersion: v1 kind: Pod metadata: name: liveness-exec-pod spec: containers: - name: liveness-exec-pod image: busybox:latest imagePullPolicy: IfNotPresent command: ["/bin/sh","-c","touch /tmp/healthy;sleep 30;rm -rf /tmp/healthy;sleep 3600"] livenessProbe: exec: command: ["test","-e","/tmp/healthy"] initialDelaySeconds: 2 #容器启动后多长时间开始探测 periodSeconds: 5 #每次探测的间隔时间,单位为秒
以HttpGet方式对pod进行存活性性探测
liveness-httpget.yaml
apiVersion: v1 kind: Pod metadata: name: liveness-httpget-pod spec: containers: - name: liveness-httpget-pod image: ikubernetes/myapp:v1 imagePullPolicy: IfNotPresent livenessProbe: httpGet: port: 80 path: /index.html initialDelaySeconds: 2 periodSeconds: 5
使用httpget方式对pod进行就绪性探测
eadiness-httpget.yaml
apiVersion: v1 kind: Pod metadata: name: readiness-httpget-pod spec: containers: - name: readiness-httpget-pod image: ikubernetes/myapp:v1 imagePullPolicy: IfNotPresent readinessProbe: httpGet: port: 80 path: /index.html initialDelaySeconds: 2 periodSeconds: 5
定义pod postStart或preStop,即容器创建后和容器中止前需要做的操作
poststart-pod.yaml
apiVersion: v1 kind: Pod metadata: name: poststart-pod spec: containers: - name: buxybox-httpd image: busybox imagePullPolicy: IfNotPresent lifecycle: postStart: exec: command: ["mkdir", "-p"," /data/web/html"] command: ["/bin/sh","-c","sleep 3600"]
Pod控制器类别
ReplicaSet
ReplicaSet控制器用来管理无状态的Pod资源,核心作用在于代用户创建指定数量的Pod副本,并确保Pod副本数量一直等于用户期望的数量。而且还支持Pod滚动更新、及自动扩缩容等机制;它被称新一代的ReplicationCtroller。
ReplicaSet主要有三个组件组成:
- 用户期望的Pod副本数量;
- 标签选择器,用来选定由自己管理或控制的Pod副本,如果通过标签选择器挑选到的Pod少于定义的Pod副本数量,则会利用Pod资源模版来创建Pod副本,以达到规定的Pod数量;
- Pod资源模版。
但是Kubernetes却不建议用户直接使用ReplicaSet,而是应该使用Deployment。
Deployment
Deployment也是Pod控制器,但是它是工作在ReplicaSet之上的。Deployment是通过控制ReplicaSet,从而来控制Pod。Deployment能够提供比ReplicaSet更为强大的功能。比如:Pod版本回滚、声明式配置(声明式配置是已经创建的Pod可以随时更改配置并应用到Pod)。Deployment是目前管理无状态应用最好的控制器。
DaemonSet
DaemonSet用于确保集群中的每一个节点只运行一个特定的Pod副本,这种特定的Pod通常是用来实现系统级的后台任务。把这样的任务托管在Kubernetes之上的好处是:如果这个后台任务宕了以后,会由DaemonSet控制器自动重建一个Pod;新建一个Node节点,它也会在新节点上创建一个这样的Pod运行。
约束:我们也可以根据自己的需求,在K8S群集中的部分满足条件的节点上仅运行一个Pod副本。
总结: Deployment和DaemonSet管理的Pod中运行的服务都是无状态的,且是守护进程类的(必须始终持续运行在后台)。但是对于那种只希望运行一次就结束的任务,显然以上两种控制器是不能够使用的。例如:我们需要对数据库进行备份,备份结束后,任务就应该结束了,而不是让任务持续运行在后台。那么对于这种任务只运行一次,只要任务完成就正常退出,没有完成才会重建,这就应该选择使用Job这种控制器了。
Job
Job控制器控制只能执行一次作业的任务,它确保这个任务确实是正常完成而退出的,如果是异常退出,则Job控制器会重建任务再次执行直到任务正常完成。
那么对于周期性的任务呢?显然Job控制器也是无法胜任的。这就需要CronJob了。
CronJob
CronJob与Job类似,也是运行一次就退出。不同之处在于,Job是只运行一次,CronJob是周期性运行。但每次运行都会有正常退出的时间。如果前一次任务还没执行完成,又到了下一次任务执行的时间点了怎么办呢?CronJob也可以解决这种问题。
StatufulSet
StatufulSet控制器能够管理有状态的Pod副本,而且每一个Pod副本都是被单独管理的,它拥有自己独有的标志和独有的数据集。一旦这个副本故障了,在重建Pod之前会做许多初始化操作。以Redis群集为例:如果Redis集群中三个节点中的某一个节点宕机了,为了确保每个节点宕机后数据不丢失,我们传统的做法就是对每个节点做主从复制,当主节点宕机后,需要人为的把从节点提升为主节点,想要恢复从节点,就需要很多运维操作了。
但是利用StatufulSet去定义管理Redis或Mysql或者Zookeeper,它们的配置是不一样的。例如:配置管理Redis主从复制和配置管理Mysql主从复制中间的操作步骤是不一样的。所以这样的配置没有任何规律可循。StatufulSet给我们提供了一个封装,用户把需要人为操作的复杂的执行逻辑定义成脚本,放置在StatufulSet的Pod模板中。这样在每次Pod节点故障后,能通过脚本自动恢复过来。
CDR
Custom Defined Resources K8S 1.8+,用户自定义资源。
Helm
任何不把用户当傻瓜的应用,都难以取得成功。K8S资源清单定义起来,门槛过高,难度大。这就诞生了Helm,Helm对于Kubernetes来说,就相当于Linux系统中的yum。以后在再部署大型的应用,就可以用Helm直接安装部署。不过Helm到目前为止,诞生也不超过两年的时间。到目前为止,许多大型主流的应用,已经可以通过Helm去部署。
ReplicaSet资源清单
ReplicaSet资源清单定义时的一级字段:
apiVersion: apps/v1 kind: ReplicaSet metadata: spec:
spec下一级核心字段主要的有三个:
replicas <integer> # 定义Pod副本数量 selector <Object> # 选择器 template <Object> # 模板
template字段中嵌套的就是Pod资源清单定义的字段:
metadata <Object> # 这是定义Pod的元数据 spec <Object> # Pod的spec
rs-demo.yaml
apiVersion: apps/v1 kind: ReplicaSet metadata: name: myapp namespace: default spec: replicas: 2 selector: matchLabels: app: myapp release: canary template: metadata: name: myapp-pod labels: app: myapp release: canary environment: qa spec: containers: - name: myapp-container image: ikubernetes/myapp:v1 ports: - name: http containerPort: 80
利用上述清单创建一个名为myapp的ReplicaSet
kubectl create -f rs-demo.yaml
查看创建成功的ReplicaSet (ReplicaSet可以简写为rs)
kubectl get rs
值得注意的是,在Pod模板中定义的Pod名称(如上代码:name: myapp-pod
)实际上是不起作用的。因为通过控制器清单文件创建的Pod名称是由按照 控制器名称-随机字符串
这样的形式命名的。如上图
更新Pod容器的镜像后,新版本Pod更新示意图
Deployment资源清单
eployment管理保留的ReplicaSet版本数量可以由用户自定义,默认保留10个历史版本。Deployment能够使用声明式配置,声明式配置是使用kubectl apply -f demo.yaml
命令。对于声明式配置的资源,将来还可以在命令行使用patch
子命令去打补丁实现配置修改更新。
Deployment在控制Pod滚动更新时,还可以配置Pod的滚动更新逻辑。
Deployment、ReplicaSet、Pod三者之间的关系:
Deployment可以简写为deploy
接下来看看Deployment资源清单一级字段:
apiVersion: apps/v1 kind: Deployment metadata: spec:
Deployment的spec与ReplicaSet的spec区别不大。
Deployment中的spec字段:
replicas <integer> # Pod副本数量 selector <Object> # 标签选择器 template <Object> -required- # Pod模板 strategy <Object> # 定义Pod更新策略 paused <boolean> revisionHistoryLimit <integer>
strategy(Pod更新策略)
spec: strategy: type: # <string> rollingUpdate: # <Object>
strategy.type字段取值:
Recreate
: 重建更新,就是删除一个Pod,再重建一个Pod。当type
为recreate
时,与type同级的rollingUpdate字段就失效了。当type
为rollingUpdate
,与type同级的rollingUpdate
字段定义滚动更新的策略。RollingUpdate
:滚动更新
strategy.rollingUpdate字段:
maxSurge
:Pod滚动更新时,最多能超出replicas定义的Pod副本数的个数。有两种取值方式:1. 直接指定一个数字(ex: 5);2. 指定一个百分比(ex: 10%)。maxUnavailable
:Pod滚动更新时,最多有几个不可用。假设replicas
值为5,maxUnavailable
值为1,那么可用的Pod数量至少为5-1=4个。此字段同样可以指定一个百分比做为值。
例如:Pod滚动更新时,多则只能多2个,少则只能少1个,则可以这样定义:
spec: strategy: type: RollingUpdate rollingUpdate: maxSurge: 2 maxUnavailable: 1
revisionHistoryLimit
revisionHistoryLimit <integer>
表示要保留以允许回滚的旧ReplicaSet的数量。默认是10个。如果值为0,表示不保存旧版本。
paused
paused <boolean>
表示部署Pod时是否暂停,通常情况下是不暂停的,执行命令后会立即部署Pod。
template
template <Object> -required-
Pod模板与ReplicaSet中Pod模板定义一致。
Deployment资源清单示例
deploy-demo.yaml
apiVersion: apps/v1 kind: Deployment metadata: name: myapp-deploy namespace: default spec: replicas: 2 selector: matchLabels: app: myapp release: canary template: metadata: labels: app: myapp release: canary spec: containers: - name: myapp image: ikubernetes/myapp:v1 ports: - name: http containerPort: 80
声明式创建
kubectl apply -f deploy-demo.yaml kubectl get deploy
同时还会自动创建一个ReplicaSet
自动创建的ReplicaSet命名规则:deploy名称-Pod模板hash值
这时我们想要改变Pod副本数量,可以直接vim deploy-demo.yaml
修改replicas: 4
,然后再执行kubectl apply -f deploy-demo.yaml
。
注意:声明式创建,相同的yaml文件可以多次执行
kubectl apply
。而kubectl create
只能执行一次。
更新操作
修改deploy-demo.yaml,将容器的镜像版本修改为v2
再次部署
kubectl apply -f deploy-demo.yaml
访问新版本Pod,可以看到已经更新到v2版本了
查看滚动历史记录
kubectl rollout history deployment myapp-deploy
通过打补丁的方式更新资源清单配置
kubectl patch deployment myapp-deploy -p '{"spec": {"replicas": 5}}'
可以看到Pod副本个数立即更新到5个了
通过打补丁的方式修改滚动更新策略
kubectl patch deployment myapp-deploy -p '{"spec": {"strategy": {"type": "RollingUpdate", "rollingUpdate": {"maxSurge": 1, "maxUnavailable": 0}}}}'
查看一下滚动更新策略,已经应用修改
kubectl describe deploy myapp-deploy
DaemonSet资源清单
DaemonSet控制器能够在指定节点上运行能够实现系统级的管理功能的Pod,而且每个指定节点只运行一个这样的Pod副本。还可以把节点的目录挂载至Pod中,通过Pod实现某些管理功能。
DaemonSet定义资源清单时,不再需要用replicas
字段指定副本数量了。
DaemonSet资源清单文件中spec字段包含的子字段:
revisionHistoryLimit <integer> # rs历史版本保存个数,与Deployment中的此字段意义相同。 selector <Object> # 标签选择器 template <Object> -required- # Pod模板 updateStrategy <Object> # Pod更新策略
更新策略
spec updateStrategy: type: RollingUpdate rollingUpdate: maxUnavailable: 2
"RollingUpdate"
和"OnDelete"
,只有类型为RollingUpdate
时,与type同级的字段rollingUpdate
才生效。rollingUpdate
字段下只有maxUnavailable
一个字段。也就是说DaemonSet的Pod更新时,只能少,不能多。DaemonSet资源清单示例
apiVersion: apps/v1 kind: DaemonSet metadata: name: filebeat-ds namespace: default spec: selector: matchLabels: app: filebeat release: stable template: metadata: labels: app: filebeat release: stable spec: containers: - name: filebeat image: ikubernetes/filebeat:5.6.5-alpine env: - name: REDIS_HOST value: redis-svc - name: REDIS_LOG_LEVEL value: info
DaemonSet资源清单定义时,不用再指定replicas
了