目录
一、Pod控制器类别
1、ReplicaSet
2、Deployment
3、DaemonSet
4、Job
5、CronJob
6、StatufulSet
7、CDR
8、Helm
二、ReplicaSet资源清单
三、Deployment资源清单
1、strategy(Pod更新策略)
2、revisionHistoryLimit
3、paused
4、template
5、Deployment资源清单示例
5.1、更新操作
5.2、通过打补丁的方式更新资源清单配置
5.3、暂停Pod更新
5.4、恢复Pod更新
5.5、回滚操作
四、DaemonSet资源清单
ReplicaSet控制器用来管理无状态的Pod资源,核心作用在于代用户创建指定数量的Pod副本,并确保Pod副本数量一直等于用户期望的数量。而且还支持Pod滚动更新、及自动扩缩容等机制;它被称新一代的ReplicationCtroller。
ReplicaSet主要有三个组件组成:
但是Kubernetes却不建议用户直接使用ReplicaSet,而是应该使用Deployment。
Deployment也是Pod控制器,但是它是工作在ReplicaSet之上的。Deployment是通过控制ReplicaSet,从而来控制Pod。Deployment能够提供比ReplicaSet更为强大的功能。比如:Pod版本回滚、声明式配置(声明式配置是已经创建的Pod可以随时更改配置并应用到Pod)。Deployment是目前管理无状态应用最好的控制器。
DaemonSet用于确保集群中的每一个节点只运行一个特定的Pod副本,这种特定的Pod通常是用来实现系统级的后台任务。把这样的任务托管在Kubernetes之上的好处是:如果这个后台任务宕了以后,会由DaemonSet控制器自动重建一个Pod;新建一个Node节点,它也会在新节点上创建一个这样的Pod运行。
约束:我们也可以根据自己的需求,在K8S群集中的部分满足条件的节点上仅运行一个Pod副本。
总结: Deployment和DaemonSet管理的Pod中运行的服务都是无状态的,且是守护进程类的(必须始终持续运行在后台)。但是对于那种只希望运行一次就结束的任务,显然以上两种控制器是不能够使用的。例如:我们需要对数据库进行备份,备份结束后,任务就应该结束了,而不是让任务持续运行在后台。那么对于这种任务只运行一次,只要任务完成就正常退出,没有完成才会重建,这就应该选择使用Job这种控制器了。
Job控制器控制只能执行一次作业的任务,它确保这个任务确实是正常完成而退出的,如果是异常退出,则Job控制器会重建任务再次执行直到任务正常完成。
那么对于周期性的任务呢?显然Job控制器也是无法胜任的。这就需要CronJob了。
CronJob与Job类似,也是运行一次就退出。不同之处在于,Job是只运行一次,CronJob是周期性运行。但每次运行都会有正常退出的时间。如果前一次任务还没执行完成,又到了下一次任务执行的时间点了怎么办呢?CronJob也可以解决这种问题。
StatufulSet控制器能够管理有状态的Pod副本,而且每一个Pod副本都是被单独管理的,它拥有自己独有的标志和独有的数据集。一旦这个副本故障了,在重建Pod之前会做许多初始化操作。
以Redis群集为例:如果Redis集群中三个节点中的某一个节点宕机了,为了确保每个节点宕机后数据不丢失,我们传统的做法就是对每个节点做主从复制,当主节点宕机后,需要人为的把从节点提升为主节点,想要恢复从节点,就需要很多运维操作了。
但是利用StatufulSet去定义管理Redis或Mysql或者Zookeeper,它们的配置是不一样的。例如:配置管理Redis主从复制和配置管理Mysql主从复制中间的操作步骤是不一样的。所以这样的配置没有任何规律可循。StatufulSet给我们提供了一个封装,用户把需要人为操作的复杂的执行逻辑定义成脚本,放置在StatufulSet的Pod模板中。这样在每次Pod节点故障后,能通过脚本自动恢复过来。
总结:真正想把有状态的应用托管在Kubernetes之上,还是有相当的难度。
Custom Defined Resources K8S 1.8+,用户自定义资源。
任何不把用户当傻瓜的应用,都难以取得成功。K8S资源清单定义起来,门槛过高,难度大。这就诞生了Helm,Helm对于Kubernetes来说,就相当于Linux系统中的yum。以后在再部署大型的应用,就可以用Helm直接安装部署。不过Helm到目前为止,诞生也不超过两年的时间。到目前为止,许多大型主流的应用,已经可以通过Helm去部署。
ReplicaSet资源清单定义时的一级字段:
apiVersion: apps/v1
kind: ReplicaSet
metadata:
spec:
spec下一级核心字段主要的有三个:
replicas # 定义Pod副本数量
selector
template字段中嵌套的就是Pod资源清单定义的字段:
metadata # 这是定义Pod的元数据
spec # Pod的spec
接下来,我们来定义一个ReplicaSet的资源清单: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。
值得注意的是,在Pod模板中定义的Pod名称(如上代码:
name: myapp-pod
)实际上是不起作用的。因为通过控制器清单文件创建的Pod名称是由按照控制器名称-随机字符串
这样的形式命名的。如下图:
获取创建的Pod:
更新Pod容器的镜像后,新版本Pod更新示意图:
Deployment管理保留的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 # Pod副本数量
selector # 标签选择器
template -required- # Pod模板
strategy # 定义Pod更新策略
paused
revisionHistoryLimit
spec:
strategy:
type: #
rollingUpdate: #
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
表示要保留以允许回滚的旧ReplicaSet的数量。默认是10个。如果值为0,表示不保存旧版本。
paused
表示部署Pod时是否暂停,通常情况下是不暂停的,执行命令后会立即部署Pod。
template
Pod模板与ReplicaSet中Pod模板定义一致。
编辑yaml文件: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
这里我们用声明式创建:
[root@k8s-master manifests]# kubectl apply -f deploy-demo.yaml
deployment.apps/myapp-deploy created
看一下创建的结果:
同时还会自动创建一个ReplicaSet,如下图:
自动创建的ReplicaSet命名规则:
deploy名称-Pod模板hash值
。
查看创建的Pod,如下图:
Pod的命令规则:
deploy名称-Pod模板hash值-随机字符串
。
这时我们想要改变Pod副本数量,可以直接vim deploy-demo.yaml
修改replicas: 4
,然后再执行kubectl apply -f deploy-demo.yaml
。
注意:声明式创建,相同的yaml文件可以多次执行
kubectl apply
。而kubectl create
只能执行一次。
上述示例清单中,有很多字段我们都没有定义。Kubernetes会自动填充默认值。可以通过命令:kubectl get deploy myapp-deploy -o yaml
查看。
我们先修改deploy-demo.yaml,将容器的镜像版本修改为v2:vim deploy-demo.yaml
再次部署:
[root@k8s-master manifests]# kubectl apply -f deploy-demo.yaml
deployment.apps/myapp-deploy configured
访问新版本Pod,可以看到已经更新到v2版本了。
查看滚动历史记录:
[root@k8s-master manifests]# kubectl rollout history deployment myapp-deploy
deployments "myapp-deploy"
REVISION CHANGE-CAUSE
1
2
[root@k8s-master manifests]# kubectl patch deployment myapp-deploy -p '{"spec": {"replicas": 5}}'
deployment.extensions/myapp-deploy patched
可以看到Pod副本个数立即更新到5个了。
通过打补丁的方式修改滚动更新策略:
[root@k8s-master manifests]# kubectl patch deployment myapp-deploy -p '{"spec": {"strategy": {"type": "RollingUpdate", "rollingUpdate": {"maxSurge": 1, "maxUnavailable": 0}}}}'
deployment.extensions/myapp-deploy patched
查看一下滚动更新策略,已经应用修改:
为了做这个示例,我们可以先修改镜像版本,然后立即暂停滚动更新。
修改镜像版本除了使用vim
命令直接编辑yaml文件或使用kubectl patch
打补丁外,还可以使用kubectl set image
直接修改镜像。示例:kubectl set image deployment/nginx busybox=busybox nginx=nginx:1.9.1
命令如下:
[root@k8s-master ~]# kubectl set image deployment myapp-deploy myapp=ikubernetes/myapp:v3 && kubectl rollout pause deployment myapp-deploy
deployment.extensions/myapp-deploy image updated
deployment.extensions/myapp-deploy paused
另开启一个终端,监控label为app=myapp
的Pod:
通过上图可以看到,滚动更新暂停命令执行后,会先创建一个新Pod并运行,然后就暂停住了,旧Pod也没有删除一个。此时有6个Pod,如下图:
通过命令:kubectl rollout status deployment myapp-deploy
可以看到滚动更新的状态,如下图:
图中提示信息告诉我们:等待部署“myapp-deploy”部署完成:5个新副本中的1个已更新...
接下来我们恢复Pod更新...
恢复Pod更新使用命令:
[root@k8s-master ~]# kubectl rollout resume deployment myapp-deploy
deployment.extensions/myapp-deploy resumed
查看一下滚动更新的状态:
从图中可以看出,滚动更新完成。
看一下ReplicaSet的状态:
从上图中可以看到镜像已经更新到v3版了,而且有5个Pod已经准备就绪了。
接下来执行回滚操作。。。
假如新版本的应用Pod有问题,想要回滚,就要使用命令:kubectl rollout undo
kubectl rollout undo deployment myapp-deploy --to-revision=1
--to-revision=1
表示回滚到第1版,如果不指定--to-revision选项,则默认是回滚到前一个版本。可以通过命令kubectl rollout history deployment myapp-deploy
查看。回滚后,原来的第1版变成第4版,所以第4版的前一版就是第3版了。如果在第4版的基础上向前回滚一个版本,就会回滚到第3版。
再来看看ReplicaSet状态:
从上图中可以看到,已经回滚到v1版了,v1版有5个Pod准备就绪了。而v3版的Pod数为0 。
DaemonSet控制器能够在指定节点上运行能够实现系统级的管理功能的Pod,而且每个指定节点只运行一个这样的Pod副本。还可以把节点的目录挂载至Pod中,通过Pod实现某些管理功能。
DaemonSet定义资源清单时,不再需要用replicas
字段指定副本数量了。
DaemonSet资源清单文件中spec字段包含的子字段:
revisionHistoryLimit # rs历史版本保存个数,与Deployment中的此字段意义相同。
selector # 标签选择器
template -required- # Pod模板
updateStrategy # Pod更新策略
更新策略:
spec
updateStrategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 2
DaemonSet的Pod更新策略有两种:
"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
了。