Kubernetes Pod控制器
Kubernetes Pod控制器
概述
Pod控制器是什么
Pod控制器就是帮助我们自动的调度管理Pod,并满足期望的Pod数量。
Pod控制器是用于实现管理pod的中间层,确保pod资源符合预期的状态,pod的资源出现故障时,会尝试进行重启,当根据重启策略无效,则会重新新建pod的资源。
创建为具体的控制器对象之后,每个控制器均通过API Server提供的接口持续监控相关资源对象的当前状态,并在因故障、更新或其他原因导致系统状态发生变化时,尝试让资源的当前状态想期望状态迁移和逼近。
Pod和Pod控制器
Pod控制器资源通过持续性地监控集群中运行着的Pod资源对象来确保受其管控的资源严格符合用户期望的状态,例如资源副本的数量要精确符合期望等。
通常,一个Pod控制器资源至少应该包含三个基本的组成部分:
- 标签选择器:匹配并关联Pod资源对象,并据此完成受其管控的Pod资源计数。
- 期望的副本数:期望在集群中精确运行着的Pod资源的对象数量。
- Pod模板:用于新建Pod资源对象的Pod模板资源。
控制器的必要性
自主式Pod对象由调度器调度到目标工作节点后即由相应节点上的kubelet负责监控其容器的存活状态,容器主进程崩溃后,kubelet能够自动重启相应的容器。但对出现非主进程崩溃类的容器错误却无从感知,这便依赖于pod资源对象定义的存活探测,以便kubelet能够探知到此类故障。但若pod被删除或者工作节点自身发生故障(工作节点上都有kubelet,kubelet不可用,因此其健康状态便无法保证),则便需要控制器来处理相应的容器重启和配置。
常见的控制器
Pod控制器由master的kube-controller-manager组件提供,常见的此类控制器有
ReplicaSet
代用户创建指定数量的pod副本数量,确保pod副本数量符合预期状态,并且支持滚动式自动扩容和缩容功能
Deployment
工作在ReplicaSet之上,用于管理无状态应用,目前来说最好的控制器。支持滚动更新和回滚功能,还提供声明式配置。
DaemonSet
用于确保集群中的每一个节点只运行特定的pod副本,常用于实现系统级后台任务。比如ELK服务
StatefulSet
管理有状态应用
Job
只要完成就立即退出,不需要重启或重建
CronJob
周期性任务控制,不需要持续后台运行
ReplicaSet控制器
ReplicaSet概述
ReplicaSet是取代早期版本中的ReplicationController控制器,其功能基本上与ReplicationController相同
ReplicaSet(简称RS)是Pod控制器类型的一种实现,用于确保由其管控的Pod对象副本数在任意时刻都能精确满足期望的数量。ReplicaSet控制器资源启动后会查找集群中匹配器标签选择器的Pod资源对象,当前活动对象的数量与期望的数量不吻合时,多则删除,少则通过Pod模板创建以补足。
ReplicaSet功能
ReplicaSet能够实现以下功能:
精确反应期望值
确保Pod资源对象的数量精确反映期望值:ReplicaSet需要确保由其控制运行的Pod副本数量精确吻合配置中定义的期望值,否则就会自动补足所缺或终止所余。
保证高可用
确保Pod健康运行:探测到由其管控的Pod对象因其所在的工作节点故障而不可用时,自动请求由调度器于其他工作节点创建缺失的Pod副本。
弹性伸缩
弹性伸缩:可通过ReplicaSet控制器动态扩容或者缩容Pod资源对象的数量。必要时还可以通过HPA控制器实现Pod资源规模的自动伸缩。
创建ReplicaSet
核心属性
spec字段一般嵌套使用以下几个属性字段:
ReplicaSet示例
创建资源清单
vi nginx-rs.yml
apiVersion: apps/v1 #api版本定义
kind: ReplicaSet #定义资源类型为ReplicaSet
metadata: #元数据定义
name: nginx-rs
namespace: default
spec: #ReplicaSet的规格定义
replicas: 2 #定义副本数量为2个
selector: #标签选择器,定义匹配Pod的标签
matchLabels:
app: nginx
template: #Pod的模板定义
metadata: #Pod的元数据定义
name: nginx-pod #自定义Pod的名称
labels: #定义Pod的标签,需要和上面的标签选择器内匹配规则中定义的标签一致,可以多出其他标签
app: nginx
spec: #Pod的规格定义
containers: #容器定义
- name: nginx #容器名称
image: nginx:1.12 #容器镜像
imagePullPolicy: IfNotPresent #拉取镜像的规则
ports: #暴露端口
- name: http #端口名称
containerPort: 80
创建rs控制器
kubectl apply -f nginx-rs.yaml
查看rs控制器
kubectl get rs
查看pod容器
通过查看pod可以看出pod命令是规则是前面是replicaset控制器的名称加随机生成的字符串
kubectl get pods -o wide -w
更新控制器
修改上面创建的replicaset示例文件,将镜像nginx:1.12改为1.20版本
vi nginx-rs.yml
apiVersion: apps/v1 #api版本定义
kind: ReplicaSet #定义资源类型为ReplicaSet
metadata: #元数据定义
name: nginx-rs
namespace: default
spec: #ReplicaSet的规格定义
replicas: 2 #定义副本数量为2个
selector: #标签选择器,定义匹配Pod的标签
matchLabels:
app: nginx
template: #Pod的模板定义
metadata: #Pod的元数据定义
name: nginx-pod #自定义Pod的名称
labels: #定义Pod的标签,需要和上面的标签选择器内匹配规则中定义的标签一致,可以多出其他标签
app: nginx
spec: #Pod的规格定义
containers: #容器定义
- name: nginx #容器名称
image: nginx:1.20 #容器镜像
imagePullPolicy: IfNotPresent #拉取镜像的规则
ports: #暴露端口
- name: http #端口名称
containerPort: 80
应用更新
kubectl apply -f nginx-rs.yaml
查看更新流程
kubectl get pods -o wide -w
我们发现pod没有任何更新变化
查看Pod版本号
kubectl get pods -o custom-columns=Name:metadata.name,Image:spec.containers[0].image
这里并没有更新pod的nginx版本号
删除pod应用
这里虽然重载了,但是已有的pod所使用的镜像仍然是1.12版本的,只是新建pod时才会使用1.20版本,这里测试先手动删除已有的pod。
kubectl delete pods -l app=nginx
查看版本
kubectl get pods -o custom-columns=Name:metadata.name,Image:spec.containers[0].image
现在我们发现pod的版本已经更新正确了
RS扩缩容
可以直接通过vim 编辑清单文件修改replicas字段,也可以通过kubect edit 命令去编辑
kubectl还提供了一个专用的子命令scale用于实现应用规模的伸缩,支持从资源清单文件中获取新的目标副本数量,也可以直接在命令行通过“–replicas”选项进行读取。
scale命令扩容
命令扩容一般用于短期的临时性扩容,应付完成后要记得缩容到原来水平
查看容量
可看到当前是两个节点
kubectl get pods -o wide
执行扩容
使用scale命令可以对集群进行扩缩容
kubectl scale replicasets nginx-rs --replicas=4
查看扩容过程
在更新前打开新窗口,监控pod的更新变化
kubectl get pods -o wide -w
在更新前打开新窗口,监控RS的更新变化
kubectl get rs -o wide -w
我们发现扩容后只是在原来的RS集群上面增加了两个节点
配置文件缩容
配置文件扩容一般用于初始容量变更,长期进行扩容
查看容量
可看到当前是四个节点
kubectl get pods -o wide
应用配置
因为没有变更配置文件可以直接应用配置文件
kubectl apply -f nginx-rs.yml
查看缩容容过程
在更新前打开新窗口,监控pod的更新变化
kubectl get pods -o wide -w
在更新前打开新窗口,监控RS的更新变化
kubectl get rs -o wide -w
我们发现扩容后只是在原来的RS集群上面减少了两个节点
删除rs控制器
使用Kubectl delete命令删除ReplicaSet对象时默认会一并删除其管控的各Pod对象,有时,考虑到这些Pod资源未必由其创建,或者即便由其创建也并非自身的组成部分,这时候可以添加“–cascade=false”选项,取消级联关系。
查看集群情况
查看RS集群
kubectl get rs -o wide
查看POD
kubectl get pods -o wide
删除rs
删除rs可以通过参数cascade=false设置不删除pod
kubectl delete replicasets nginx-rs --cascade=false
查看集群情况
查看RS集群
kubectl get rs -o wide
查看POD
kubectl get pods -o wide
删除Pod
kubectl delete pods nginx-rs-7rzz6
kubectl delete pods nginx-rs-c5zrs
Deployment控制器
Deployment概述
Deployment为Pod和Replica Set(下一代Replication Controller)提供声明式更新
只需要在 Deployment 中描述想要的目标状态是什么,Deployment controller 就会帮您将 Pod 和ReplicaSet 的实际状态改变到您的目标状态。也可以定义一个全新的 Deployment 来创建 ReplicaSet 或者删除已有的 Deployment 并创建一个新的来替换。
其他特性
Deployment控制器资源的主要职责是为了保证Pod资源的健康运行,其大部分功能均可通过调用ReplicaSet实现,同时还增添部分特性。
- 事件和状态查看:必要时可以查看Deployment对象升级的详细进度和状态。
- 回滚:升级操作完成后发现问题时,支持使用回滚机制将应用返回到前一个或由用户指定的历史记录中的版本上。
- 版本记录:对Deployment对象的每一个操作都予以保存,以供后续可能执行的回滚操作使用。
- 暂停和启动:对于每一次升级,都能够随时暂停和启动。
- 多种自动更新方案:一是Recreate,即重建更新机制,全面停止、删除旧有的Pod后用新版本替代;另一个是RollingUpdate,即滚动升级机制,逐步替换旧有的Pod至新的版本。
Deployment配置
编辑资源清单
vi nginx-deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
配置项说明
配置解释
- 我们定义了一个Deployment,名字叫nginx-deployment;
- 通过spec.replicas字段定义了Pod的副本数是2;
- 通过spec.selector字段定义了被打上app: nginx的标签的Pod才会被管理;
- tmplate字段定义了这个Deployment管理的Pod应该是怎样的,具有怎样的属性;
控制器描述
总的来说一个Deploymet控制器可以由两部分组成:
创建控制器
kubectl apply -f nginx-deployment.yml
kubectl get pods -o wide
查看replicaset
ReplicaSet是一个副本控制器,ReplicaSet可以用selector来控制Pod的数量,而Deployments是一个更高层次的概念,它管理ReplicaSets,并提供对pod的声明性更新以及许多其他的功能。
kubectl get replicaset -o wide
通过查看资源对象可以看出,Deployment会自动创建相关的ReplicaSet控制器资源,并以”[DEPLOYMENT-name]-[POD-TEMPLATE-HASH-VALUE]”格式为其命名,其中的hash值由Deployment自动生成。而Pod名则是以ReplicaSet控制器的名称为前缀,后跟5位随机字符。
更新策略
ReplicaSet控制器的应用更新需要手动分成多步并以特定的次序进行,过程繁杂且容易出错,而Deployment却只需要由用户指定在Pod模板中要改动的内容,(如镜像文件的版本),余下的步骤便会由其自动完成。Pod副本数量也是一样。
Deployment控制器支持两种更新策略:滚动更新(rolling updata)和 重建更新(recreate),默认情况下为滚动更新
重建更新
重建更新为:先删除所有的Pod再根据新的模板创建新的Pod,中间会导致服务的不可用,用户要么使用的是新版本,要么就是旧版本
滚动更新
滚动更新是默认的更新策略,它在删除一些旧版本的Pod的同时补充创建一些新的Pod,更新期间服务不会中断。
滚动更新期间,应用升级期间还要确保可用的Pod对象数量不低于某些阈值。确保可以持续处理客户端请求。变动的方式和Pod对象的数量范围将通过==spec.strategy.roollingUpdata.maxSurge和spec.strategy.roollingUpdata.maxunavailable两个属性协同进行定义。两个参数用法如下:
- maxSurge:指定升级期间存在的总Pod对象数量最多以超出期望值的个数,其值可以为0或者正整数,也可以是一个期望值的百分比:例如如果期望值是3,当前的属性值为1,则表示Pod对象的总数不能超过4个。
- maxUnavailable:升级期间正常可用的Pod副本数(包括新旧版本)最多不能低于期望的个数、其值可以是0或者正整数。也可以是一个期望值的百分比,默认值为1;该值意味着如果期望值是3,那么在升级期间至少要有两个Pod对象处于正常提供服务的状态
maxSurge和maxUnavailable的数量不能同时为0,否则Pod对象的复本数量在符合用户期望的数量后无法做出合理变动以进行滚动更新操作。
更新控制器
命令扩容一般用于短期的临时性扩容,应付完成后要记得缩容到原来水平
命令更新
查看版本
通过命令查看pod的版本号
kubectl get pods -o custom-columns=Name:metadata.name,Image:spec.containers[0].image
执行更新命令
kubectl set image deployment/nginx-deployment nginx=nginx:1.15
查看更新过程
在更新前打开新窗口,监控pod的更新变化
kubectl get pods -o wide -w
在更新前打开新窗口,监控RS的更新变化
kubectl get rs -o wide -w
我们发现更新后新建了一个RS,并且保留原来的RS但是节点数为0用来回滚
查看版本
通过命令查看pod的版本号
kubectl get pods -o custom-columns=Name:metadata.name,Image:spec.containers[0].image
配置更新
查看版本
通过命令查看pod的版本号
kubectl get pods -o custom-columns=Name:metadata.name,Image:spec.containers[0].image
编辑资源清单
vi nginx-deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.20 # 将nginx版本改为1.20
ports:
- containerPort: 80
应用更新
kubectl apply -f nginx-deployment.yml
查看更新过程
在更新前打开新窗口,监控pod的更新变化
kubectl get pods -o wide -w
在更新前打开新窗口,监控RS的更新变化
kubectl get rs -o wide -w
我们发现更新后新建了一个RS,并且保留原来的RS但是节点数为0用来回滚
查看版本
通过命令查看pod的版本号
kubectl get pods -o custom-columns=Name:metadata.name,Image:spec.containers[0].image
回滚更新
通过rollout命令进行回滚操作
查看版本
通过命令查看pod的版本号
kubectl get pods -o custom-columns=Name:metadata.name,Image:spec.containers[0].image
执行回滚命令
kubectl rollout undo deployment/nginx-deployment
查看更新过程
在更新前打开新窗口,监控pod的更新变化
kubectl get pods -o wide -w
在更新前打开新窗口,监控RS的更新变化
kubectl get rs -o wide -w
我们发现回滚没有创建新的rs而是将使用了原来的rs
查看版本
通过命令查看pod的版本号
kubectl get pods -o custom-columns=Name:metadata.name,Image:spec.containers[0].image
我们发现rollout回滚只在最近的两个版本之间来回回滚,不会回滚到在上一个版本。
回滚指定版本
查看历史版本
通过rollout history查看版本历史
kubectl rollout history deployment/nginx-deployment
历史版本内容
通过指定版本号来查看变更内容,找到需要回滚的版本,这里我会回滚到最早版本nginx:1.7.9
kubectl rollout history deployment/nginx-deployment --revision=1
我们找到了需要回滚的版本是1
查看版本
通过命令查看pod的版本号
kubectl get pods -o custom-columns=Name:metadata.name,Image:spec.containers[0].image
执行回滚命令
写入我们需要回滚到的指定版本1
kubectl rollout undo deployment/nginx-deployment --to-revision=1
查看版本
通过命令查看pod的版本号
kubectl get pods -o custom-columns=Name:metadata.name,Image:spec.containers[0].image
到此我们已经回滚到了指定版本
Deployment扩缩容
scale命令扩容
命令扩容一般用于短期的临时性扩容,应付完成后要记得缩容到原来水平
查看当前容量
当前是两个节点
kubectl get pods -o wide
执行扩容
使用scale命令可以对集群进行扩缩容,扩充到4个节点
kubectl scale deployment nginx-deployment --replicas=4
查看扩容过程
在更新前打开新窗口,监控pod的更新变化
kubectl get pods -o wide -w
在更新前打开新窗口,监控RS的更新变化
kubectl get rs -o wide -w
我们发现扩容后只是在原来的RS集群上面增加了两个节点
配置文件缩容
配置文件扩缩容一般用于初始容量变更,长期进行扩缩容
查看当前容量
当前是4个节点
kubectl get pods -o wide
应用配置文件
因为我们没有更改配置文件,直接应用配置文件即可
kubectl apply -f nginx-deployment.yml
查看扩容过程
在更新前打开新窗口,监控pod的更新变化
kubectl get pods -o wide -w
在更新前打开新窗口,监控RS的更新变化
kubectl get rs -o wide -w
我们发现扩容后只是在原来的RS集群上面减少了两个节点
删除Deployment
查看集群情况
查看Deployment
kubectl get deployments -o wide
查看POD
kubectl get pods -o wide
删除Deployment
执行删除命令删除Deployment
kubectl delete deployment nginx-deployment
查看Deployment
kubectl get deployments -o wide
查看POD
kubectl get pods -o wide
DaemonSet控制器
DaemonSet概述
DaemonSet用于在集群中的全部节点上同时运行一份指定Pod资源副本,后续新加入集群的工作节点也会自动创建一个相关的Pod对象,当从集群移除借点时,此类Pod对象也将被自动回收而无需重建。管理员也可以使用节点选择器及节点标签指定仅在具有特定特征的节点上运行指定的Pod对象。
应用场景
- 运行集群存储的守护进程,如在各个节点上运行glusterd或ceph。
- 在各个节点上运行日志收集守护进程,如fluentd和logstash。
- 在各个节点上运行监控系统的代理守护进程,如Prometheus Node Exporter、collectd、Datadog agent、New Relic agent和Ganglia gmond等。 创建DaemonSet
创建DaemonSet
DaemonSet控制器的spec字段中嵌套使用的相同字段selector、template和minReadySeconds,并且功能和用法基本相同,但它不支持replicas,因为毕竟不能通过期望值来确定Pod资源的数量,而是基于节点数量。
编辑资源清单
vi nginx-daemonset.yml
apiVersion: apps/v1 #api版本定义
kind: DaemonSet #定义资源类型为DaemonSet
metadata: #元数据定义
name: nginx-daemon-set #daemonset控制器名称
namespace: default #名称空间
labels: #设置daemonset的标签
app: daem-nginx
spec: #DaemonSet控制器的规格定义
selector: #指定匹配pod的标签
matchLabels: #指定匹配pod的标签
app: daem-nginx #注意:这里需要和template中定义的标签一样
template: #Pod的模板定义
metadata: #Pod的元数据定义
name: nginx
labels: #定义Pod的标签,需要和上面的标签选择器内匹配规则中定义的标签一致,可以多出其他标签
app: daem-nginx
spec: #Pod的规格定义
containers: #容器定义
- name: nginx-pod #容器名字
image: nginx:1.12 #容器镜像
ports: #暴露端口
- name: http #端口名称
containerPort: 80 #暴露的端口
创建应用
kubectl apply -f nginx-daemonset.yml
查看pod情况
我们发现只有node节点上创建了pod
kubectl get pods -o wide
通过上面验证查看,Node-Selector字段的值为空,表示它需要运行在集群中的每个节点之上。而当前的节点数是2个,所以其期望的Pod副本数(Desired Number of Nodes Scheduled)为2,而当前也已经创建了2个相关的Pod对象。
注意
对于特殊的硬件的节点来说,可能有的运行程序只需要在某一些节点上运行,那么通过Pod模板的spec字段中嵌套使用nodeSelector字段,并确保其值定义的标签选择器与部分特定工作节点的标签匹配即可。
更新DaemonSe
DaemonSet自Kubernetes1.6版本起也开始支持更新机制,相关配置嵌套在kubectl explain daemonset.spec.updateStrategy字段中。其支持RollingUpdate(滚动更新)和OnDelete(删除时更新)两种策略,滚动更新为默认的更新策略。
查看镜像版本
kubectl get pods -l app=daem-nginx -o custom-columns=NAME:metadata.name,NODE:spec.nodeName,Image:spec.containers[0].image
更新版本
kubectl set image daemonset/nginx-daemon-set nginx-pod=nginx:1.20
查看镜像版本
kubectl get pods -l app=daem-nginx -o custom-columns=NAME:metadata.name,NODE:spec.nodeName,Image:spec.containers[0].image
查看更新详情
kubectl describe daemonset nginx-daemon-set
通过上面查看可以看出,默认的滚动更新策略是一次删除一个工作节点上的Pod资源,待其最新版本Pod重建完成后再开始操作另一个工作节点上的Pod资源。
DaemonSet控制器的滚动更新机制也可以借助于minReadySeconds字段控制滚动节奏;必要时也可以执行暂停和继续操作。其也可以进行回滚操作。