0x00 Controller介绍
///
Q:什么是资源控制器?
A:k8s内建了很多控制器,控制Pod的具体状态和行为
Q:为什么要使用控制器?
A:Pod作为k8s部署的最小单元,而如果需要创建批量的Pod副本并进行扩容以及Pod的回退就需要controller进行实现
Q:有哪些类型的控制器?
A:1,Replication Controller 和 ReplicaSet;2,Deployment;3,DaemonSet;4,Job/CronJob;5,StatefulSet;6,Horizontal Pod Autoscaling;
0x01 Controller详细介绍
Replication Controller
Q:什么是Replication Controller(RC)?
A:Replication Controller是一个基本的控制类型,即是我们所说的RC(副本控制器),用于确保任意时间都有指定数量的Pod副本在运行
Q:RC的作用?
A:确保容器应用的副本数始终保持在用户定义的副本数,即如果有容器异常退出,会自动创建新的Pod来替代,而如果容器由异常恢复到正常,那么多出来的容器也会自动回收
Q:RC工作原理是什么?
A:创建RC之后k8s Master节点上的Controller Manager组件接到创建RC的通知进行创建满足与副本数相应的Pod,然后它会定期巡视系统当中存活的目标Pod,然后进行标签匹配来监视对应的Pod,并确保目标Pod实例刚好等于RC中定义的副本数期望值,而目标Pod数超过副本期望值时,将会销毁多余的Pod
Q:RC组成部分?
A:1,Pod期待的副本数Replicas;2,用于筛选目标Pod的Label Selector,对应Pod模版(Template);3,Pod数量小于副本期望值时根据Pod模版创建相应的Pod
/RC示例//
# rc-demo.yaml
apiVersion: v1
kind: ReplicationController
metadata:
name: rc-demo
spec:
replicas: 3
selector:
app: nginx
template:
metadata:
name: nginx
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
# 操作实践
# 1,创建
kubectl apply -f rc-demo.yaml
# 2,获取创建好的信息
kubectl get rc/rc-demo
kubectl describe rc/rc-demo
# 3,获取Pod信息
kubectl get pod -l app=nginx
# 4,删除RC创建的Pod
kubectl delete pod nginx-*
# 5,删除RC
kubectl delete -f rc-demo.yaml
/RC Tips//
# 我们可以在删除RC时不删除其构建的Pod进行更新修改RC,可以采用delete命令子参数cascade=false。原RC被删除后可以创建一个新的RC来替换它,前提是旧的和新的spec.selector相匹配,那么新的RC将会接管旧的Pod
# 官方建议舍弃RC,切换使用功能更强的RS
ReplicaSet
Q:什么是ReplicaSet?
A:ReplicaSet(RS)副本集,RC的升级版本,区别在于名字不同而且RS支持集合式标签选择。这使得RS在资源选择上更加灵活
Q:ReplicaSet有什么作用?
A:和RC一样可以保持Pod副本数量。虽然RS可以独立使用,但是它主要用于协调Deployment对Pod的创建,删除和更新,当使用Deployment的时候不需要担心RS的功能,因为可以直接通过Deployment对其进行管理
Q:快速查看控制器的版本?
A:kubectl api-version | grep $(kubectl api-resources | grep "ReplicaSet" | awk -F " " '{print $3}')
//ReplicaSet示例
# replicaset-demo.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: replicaset-demo
labels:
app: replicaset-demo
spec:
replicas: 3
selector:
matchLabels:
app: replicaset-demo
matchExpressions:
- {key: tier, operator: In, values: {frontend}}
template:
metadata:
labels:
app: replicaset-demo
spec:
containers:
- name: nginx-replicaset-demo
image: nginx:latest
command: ["sh", "-c", "java -jar nginx-app-${RELASE_VER}.jar"]
env:
- name: GET_HOSTS_FROM
value: dns
- name: RELASE_VER
value: 1.3.5
ports:
- containerPort: 80
EOF
# 操作流程
# 1,部署Rs-Pod
kubectl apply -f replicaset-demo.yaml
# 2,查看Pod
kubectl get pod --show-labels -o wide
# 3,查看Pod中的信息
kubectl exec replicaset-demo-xxxx -it -- env
# 4,删除所有Pod后,RS管理的Pod将会重启
kubectl delete pod --all
kubectl get pod --show-labels -o wide
# 5,删除RS,再删除Pod才算是真删除
kubectl delete rs replicaset-demo
Deployment
/
Q:什么是Deployment?
A:通过RS创建和管理对应的Pod,以及使用不同的RS交替完成滚动更新
Q:为什么要使用Deployment?
A:支持更新,回滚,可以简化部署流程。并且是全部在Deployment配置文件中完成。
Q:Deployment组成部分?
A:1,RS,Deployment生成RS并完成满足Pod副本数量的Pod创建;2,通过Deployment方便升级和回滚Pod应用;3,通过Deployment方便暂停或者恢复发布;4,通过Deployment方便扩容和缩容
Q:Pod,ReplicationController,ReplicaSet,Deployment的关系说明?
A:ReplicationController->Pod(一直满足Pod副本数除非RC被删除);ReplicaSet->Pod(一直满足pod副本数除非RS被删除,比RC的主要的特点是支持集合标签);Deployment->ReplicaSet->Pod(在RS的基础上快速完成更新回滚扩容和收缩)
Deployment如何完成更新,回滚,扩容和缩容
Deployment示例/
# nginx-deployment-demo.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment-demo
spec:
replicas: 3
selector:
matchLabels:
app: nginx-deployment
template:
metadata:
labels:
app: nginx-deployment
spec:
containers:
- name: nginx-deployment
image: nginx:latest
ports:
- containerPort: 80
# 操作流程
# 1,部署,--record可以记录命令,可以查看每次reversion的变化
kubectl apply -f nginx-deployment-demo.yaml --record
# 2,查看
kubectl get deploy -o wide
kubectl get rs (rs也可以查看到Pod,以此证明Deployment并不是直接创建和管理Pod)
kubectl get pod -o wide --show-labels
# 3,访问nginx的html目录下的index.html
curl http://IP:Port
# 4,关于Deployment的扩容
kubectl scale deployment nginx-deployment-demo --replicas 5
kubectl autoscale deployment nginx-deployment-demo --min=10 --max=15 --cpu-percent # 如果集群支持horizontal pod autoscaling,可以设置自动扩容
# 5,关于更新容器中的镜像
kubectl set image deployment/nginx-deployment-demo nginx-deployment=redis:latest
kubectl get rs -o wide # 查看rs替换历史,可以看出已经替换了镜像
# 6,关于回滚和历史版本的控制
kubectl rollout undo deployment/nginx-deployment-demo # 执行回滚
kubectl rollout status deployment/nginx-deployment-demo # 查看回滚执行状态
kubectl rollout history deployment/nginx-deployment-demo # 查看回滚历史
# 7,编辑Deployment
kubectl edit deployment/nginx-deployment-demo
# 8,收缩
kubectl scale deployment nginx-deployment-demo --replicas 0
# 9,删除deployment
kubectl delete deploy nginx-deployment-demo
# 10,Terminating代表正在终结
Deployment命名规则/
Deployment Name: [Name]
ReplicaSet Name: [deployment-name]-[随机字符串]
Pod Name: [replicaset-name]-[随机字符串]
Deployment更新策略/
# 更新时,创建两个RS,其中旧的RS一次减少25%的Pod而新的RS一次创建25%的Pod
# 1,Deployment可以保证升级时只有一定数量的Pod是down的。默认的他会确保最多有一个Pod不可用
# 2,Deployment同时会创建超出期望数量的Pod,最多一个surge
# 3,随着k8s的版本升级,Deployment升级策略改变,由1-1转变为25%-25%
# 4,只要Deployment的rollout被触发,就会创建一个revision。当Deployment的Pod.template被更改,例如labels和容器镜像
# 5,扩容,缩容不会创建revision。意味着回退到历史revision时,只有Deployment中的Pod template部分回退
# 6,可以使用kubectl rollout status 查看Deployment的更改版本是否完成,rollout完成,kubectl rollout status将返回一个0值的code
# 7,通过.spec.revisionHistoryLimit来指定deployment最多保留多少revision历史记录,默认为10,设置为0就代表无法回退
DaemonSet
描述:如果需要在每台Node上运行同一个容器应用,可以采用k8s提供的DaemonSet控制器满足我们的需求,即DaemonSet,它类似于守护进程,可以在所有或者部分机器上运行同一个Pod
功能:1,当一个新节点加入到k8s集群中时DaemonSet创建的Pod将会被自动调度到该节点;2,当一个节点从k8s集群移除,DaemonSet创建的Pod也会被移除;3,如果删除DaemonSet,所有的与这个DaemonSet相关的Pod都会被删除
场景:1,在每个Node上运行集群存储Daemon,例如ceph,glusterd;2,在每个Node上运行日志收集daemon,例如fluentd,logstash;3,在每个Node上运行监控Daemon,例如Pormetheus,collectd,datadog,New Relic代理,或者Ganglia gmond
///DaemonSet示例
# DaemonSet控制器资源清单
# daemonset-example.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: daemonset-example
labels:
app: daemonset
spec:
selector:
matchLabels:
name: daemonset-example
template:
metadata:
labels:
name: daemonset-example
spec:
#tolerations:
# - key: node-role.kubernetes.io/master
# effect: NoShedule
containers:
- name: daemonset-example
image: nginx:latest
imagePullPolicy: IfNotPresent
resources:
limits:
cpu: 200m
memory: 200Mi
requests:
cpu: 100m
memory: 100Mi
terminationGracePeriodSeconds: 30
# 操作流程
# 1,部署
kubectl apply -f daemonset-example.yaml
# 2,查看
kubectl get ds -o wide
kubectl get pod -o wide --show-labels
# 3,验证daemonset的作用。我们将master节点的污点去除
kubectl describe node k8s-master-1 | grep "Taints"
# Taints: node-role.kubernetes.io/master:NoShedule
kubectl taint nodes k8s-master-1 node-role.kubernetes.io/master:NoShedule- # 去除污点
kubectl describe node k8s-master-1 | grep "Taints"
# Taints: <none>
# 4,检测去除污点后的DaemonSet
kubectl get ds -o wide # 此时daemonset已经将pod生成到master
kubectl get pod -o wide --show-labels # master节点上已经存在了Daemonset的Pod
# 5,再次向master节点增加污点
kubectl taint node k8s-master-1 node-role.kubernetes.io/master:NoShedule
# 此时daemonset管理的Pod只剩一个了
kubectl get ds
#
kubectl get pod -o wide --show-labels # 此时运行在Master上的Pod已经是自助式Pod
# 删除后,由于已经不属于DaemonSet管理,所以不会再去管理
kubectl delete pod daemonset-example-xxx
# 6,删除daemonset控制器创建的Pod,--cascade=false不删除Pod
kubectl -cascade=true delete ds daemonset-example
Job
描述:Job控制器资源对象有自身的纠错能力,如果job运行的脚本没有以0状态码退出,Job将会重新执行直到至少有一个成功
///Job示例
# job-demo.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: job-demo-pi
spec:
template:
metadata:
name: job-demo-pi
spec:
containers:
- name: nginx-test
image: nginx:latest
command: ["/bin/sh", "-c", "date;echo Job Controller Demo!"]
imagePullPolicy: IfNotPresent
restartPolicy: Never
# 操作示例
# 1,创建Job-Pod
kubectl apply -f job-demo.yaml
# 2,查看
kubectl get jobs -o wide --show-labels
kubectl get pod -o wide --show-labels
# 3,结果
kubectl describe pod job-demo-pi-xxxx
# 4,删除Job资源
kubectl delete -f job-demo.yaml
kubectl delete jobs --all
kubectl get jobs
kubectl get pod
CronJob
描述:管理基于时间的Job,周期性的在给定时间点运行。
//特殊字段/
.spec
template 格式类似Pod
RestartPolicy Never/OnFailure,单个Pod时,Pod成功运行后Job结束
completions Job结束需要运行的Pod个数,默认1个
parallelism 标志并行运行的Pod的个数,默认1个
activeDeadlineSeconds Pod重试最大时间,超过不会再重试
schedule 调度周期 分时年月周
jobTemplate Job模版,指定需要运行的任务,格式同job
startingDeadlineSeconds 表示如果Job因为某种原因无法按调度准时启动,在spec.startingDeadlineSeconds时间段之内,CronJob仍然试图重新启动Job,如果在.spec.startingDeadlineSeconds时间之内没有启动成功,则不再试图重新启动。如果spec.startingDeadlineSeconds的值没有设置,则没有按时启动的任务不会被尝试重新启动。
concurrencyPolicy:并发策略.“Allow” (允许,default):
“Forbid”(禁止): forbids;前个任务没执行完,要并发下一个的话,下一个会被跳过
“Replace”(替换): 新任务,替换当前运行的任务
failedJobsHistoryLimit:记录失败数的上限,Defaults to 1.
successfulJobsHistoryLimit: 记录成功任务的上限。 Defaults to 3.
#指定了 CronJob 应该保留多少个 completed 和 failed 的 Job 记录。将其设置为 0,则 CronJob 不会保留已经结束的 Job 的记录。
suspend 暂停定时任务,对已经执行了的任务,不会生效; Defaults to false.
//CronJob示例/
# cronjob-demo.yaml
apiVersion: batch/v1
kind: CronJob
metadata:
name: cronjob-demo
spec:
schedule: "*/1 * * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: cronjob-demo
image: nginx
args:
- /bin/sh
- -c
- date;echo Hello from the Kubernetes cluster,This is cronjob-demo;
imagePullPolicy: IfNotPresent
restartRolicy: OnFailure
# 操作流程
# 1,Help文档格式
kubectl explain CronJob.spec.jobTemplate.spec.template.spec.containers
# 2,创建
kubectl apply -f cronjob-demo.yaml
# 3,查看
kubectl get cj -o wide --show-labels
kubectl get jobs -o wide
kubectl get pod -o wide --show-labels
# 4,反馈结果
kubectl get pod | grep "cronjob" | cut -d " " -f1
# 5,删除cj
kubectl delete cronjob --all
kubectl delete -f cronjob-demo.yaml
StatefulSet
描述:有状态服务的应用程序
Q:有状态服务和无状态服务的区别?
A:服务所维护的与客户交互活动的信息称为状态信息。stateless Service,无状态服务,在应用程序运行过程中不保存任何数据和状态信息的服务;stateful Service,有状态服务,在应用程序运行过程中保存的数据或状态的服务
///特征///
1,稳定的网络标识,即Pod重新调度后其PodName和HostName不变,基于Headless Service来实现。
2,有序部署和有序扩展,基于init containers实现,在第n个Pod启动之前,前一个Pod必须处于Ready和Running状态
3,稳定的持久化存储,Pod重新调度后还是能访问到相同的持久化数据,基于PV/PVC,以及StorageClass实现
4,有序删除和停止,从N-1到0依次销毁
///启停顺序///
1,有序部署:部署stateful时,如果有多个Pod副本,会被顺序的创建
2,有序删除:当Pod被删除时,被终止的顺序是从N-1到0
3,有序扩展:扩展时,与部署一样,他前面的Pod必须都处于Running和Ready状态
///DNS域名格式///
1,stateful除了需要采用PV/PVC持久化Pod状态数据之外,还需要使用到Headless Service,该Service为StatefulSet控制的每个Pod创建一个DNS域名,格式为PodName.HeadlessServiceName
///Stateful Set示例///
# statefulset-demo.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-statefulset-service
labels:
app: nginx
spec:
clusterIP: None
selector:
app: nginx-sfs
ports:
- name: web
port: 80
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
selector:
matchLabels:
app: nginx-sfs
serviceName: "nginx-statefulset-service" # 与上面的Service名称要一致,是绑定的作用
replicas: 3
template:
metadata:
labels:
app: nginx-sfs
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
name: web
volumnMounts:
- name www
mountPath: /usr/share/nginx/html
volumnClaimTemplates:
- metadata:
name: www
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: "managed-nfs-storage"
resources:
requests:
storage: 200Mi
# 操作流程
# 创建
kubectl apply -f statefulset-demo.yaml
# 查看StatrfulSet控制器,SVC,PVC
kubectl get sts,pvc -o wide | egrep "web"
kubectl get svc | grep "nginx-statefulset-service"
kubectl get ep -o wide | grep "nginx-statefulset-service"
Horizontal Pod Autoscaling
描述:自动扩展。它根据当前Pod资源的使用率,进行副本数的动态扩容和缩容,以便减轻pod的压力。当pod负载达到一定的阈值后,会根据扩缩容的策略生成更多新的Pod来分担压力,当Pod的使用比较空闲时,在稳定空闲一段时间后,还会自动减少Pod的副本数量
HPA的作用以及部署建议///
1,HPA的起始作用是Pod按照一定的策略进行自动扩容缩容,例如根据CPU利用率自动伸缩一个RC,Deploy,RS中管理的Pod副本数量;可以简单的理解为他不是控制器而是一个控制器的附属品,可以使用它去控制其他的控制器,从而使其他的控制器具有自动扩展的能力
2,如果要实现扩容缩容的功能,还需要部署heapster服务,用来收集和统计资源的利用率,支持kubectl top命令,heapster服务集成在prometheus MetricServer服务中
3,scale手动伸缩k8s资源对象的升级回滚扩容缩容,autoscale自动伸缩
4,k8s autoscale两种方式:水平扩展,实例数目的增减;垂直扩展,示例资源的增减,CPU或者内存
HPA实例///
# 1,构建测试的镜像,运行构建Deployment的HPA资源,名称为php-apache,并设置请求CPU的资源为200M,并暴露一个80端口
# hpa-demo.yaml
kind: Deployment
apiVersion: apps/v1
metadata:
name: php-apache-deployment
labels:
app: php-apache-deploy
spec:
replicas: 1
selector:
matchLabels:
app: nginx-apache
matchExpressions:
- key: app
operator: In
values: [php-apache]
template:
metadata:
labels:
app: php-apache
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
resources:
requests:
cpu: 128M
memory: 128Mi
limits:
cpu: 200m
memory: 200Mi
imagePullPolicy: IfNotPresent
---
kind: Service
apiVersion: v1
metadata:
name: php-apache
spec:
type: ClusterIP
selector:
app: php-apache
ports:
- protocol: TCP
port: 80
targetPort: 80
# 2,创建以及查看
kubectl apply -f hpa-demon.yaml
kubectl get deployment -o wide
kubectl get svc
kubectl get replicasets.apps -o wide
# 3,创建HPA控制器,当HPA控制的deployment资源对象的CPU使用率达到50%时,就进行扩容最多可以到10个
# 方式1
kubectl autoscale deployment php-apache-deployment --cpu-percent=50 --min=1 --max=10
# 方式2,资源清单模式,文件名:HorizontalPodAutoscaler.yaml
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
name: php-apache-deployment
namespace: default
spec:
minReplicas: 1
maxReplicas: 10
scaleTargetRef:
kind: Deployment
name: php-apache-deployment
apiVersion: apps/v1
targetCPUUtilizationPercentage: 50
操作:kubectl apply -f HorizontalPodAutoscaler.yaml
# 4,模拟消耗php-apache的资源,并且验证Pod是否会自动扩容与缩容
# 使用压测工具ab
ab -c 5000 -n 2000000 http://host:port/
# 5,查看HPA的CPU占用情况和扩容缩容
watch -n 2 `kubectl get deployment | grep "php-apache-deployment" && kubectl get hpa && kubectl top pod -l app=php-apache`
# 6,停止死循环后,并不会立即减少Pod数量,会等一段时间后减少Pod数量,防止流量再次激增
watch -c -t -n 2 `kubectl get deployments | grep "php-apache-deployment" && kubectl get hpa && kubectl get pod -l app=php-apache`
# 7,删除
kubectl delete horizontalpodautoscalers.autoscaling php-apache-deployment
HPA Tips///
1,HPA只针对Deployment,RS,RC,StatefulSet创建的Pod资源