5.k8s控制器-Replicaset-Deployment、pod 反亲和性
Deployment 官方文档:
https://kubernetes.io/zh-cn/docs/concepts/workloads/controllers/deployment/
Pods 是 Kubernetes 中最基本的资源单位,它包含了一个或多个容器,并提供了一个隔离的环境来运行这些容器。但是,在生产环境中,通常需要运行多个 Pod 实例来提供服务,并需要对这些实例进行管理。这时候就需要使用 Deployment 和 ReplicaSet 这两种资源。
Replicaset 控制器:概念、原理解读
Replicaset 概述
1.假设你有一个容器应用程序,需要在 Kubernetes 集群中运行。这个应用程序需要多个相同的 Pod 实例来处理用户请求,以确保应用程序的高可用性和性能。但是,由于 Pod 可能会因为各种原因而停止运行(例如,节点故障、资源不足、应用程序崩溃等),因此你需要一种机制来确保始终有足够数量的 Pod 实例在运行。
2. 这时候,就可以使用 ReplicaSet 来管理这些 Pod 实例。ReplicaSet 可以定义应该运行多少个相同的 Pod 实例,以及在某个 Pod 实例失败时如何自动创建新的 Pod 实例来替代。ReplicaSet 还可以根据资源利用率自动调整 Pod 实例的数量,以确保应用程序始终够处理用户请求。
3.简单来说,ReplicaSet 可以帮助你确保你的应用程序始终能够提供足够的容量和可用性,而无需手动管理多个 Pod 实例。
Replicaset 工作原理:如何管理Pod?
1.ReplicaSet 的工作原理可以简单概括为:它不断地检查当前集群中的 Pod 副本数量是否符合用户定义的期望数量,如果数量不足,则会自动创建新的 Pod 副本来满足期望数量,如果数量过多,则会删除一些 Pod 副本以满足期望数量。
2.具体来说,当创建一个 ReplicaSet 时,需要定义以下参数:1、模板(template):指定了要创建的 Pod 的规格和属性;
2、副本数量(replicas):指定了要创建的 Pod 的副本数量;
3、选择器(selector):指定了要选择哪些 Pod 实例,以确保它们的标签与ReplicaSet 的标签相匹配。
1.一旦 ReplicaSet 创建完成,它会不断地监控集群中符合选择器要求的 Pod 实例数量,如果实际数量小于期望数量,则会自动创建新的 Pod 实例,如果实际数量多于期望数量,则会自动删除一些 Pod 实例。
2.总之,ReplicaSet 是 Kubernetes 中用来管理 Pod 实例数量的核心组件,它通过自动创建和删除 Pod 实例来确保应用程序的高可用性和可伸缩性。简写成rs。
Replicaset 资源清单文件编写技巧
查看定义Replicaset资源需要的字段有哪些?,在命令行,Replicaset可以简写成rs,显示结果如下:
root@ubuntu0:~/matedata/pod# kubectl explain Replicaset
root@ubuntu0:~/matedata/pod# kubectl explain rs
KIND: ReplicaSet
VERSION: apps/v1DESCRIPTION:ReplicaSet ensures that a specified number of pod replicas are running atany given time.
FIELDS:
apiVersion <string>
kind <string>
metadata <Object>
spec <Object>
status <Object>
1)apiVersion:表示当前资源使用的 API 版本,通常为 "apps/v1"。
2)kind:表示资源类型,即 "ReplicaSet"。
3)metadata:包括 name、namespace、labels、annotations 等字段,用于定义
Replicaset 的元数据信息。
4)spec:包括 replicas、selector、template 等字段,用于定义 Replicaset 的规格,包括副本数、标签选择器和 Pod 模板等。
5)status:包括 replicas、available、Replicas、readyReplicas 等字段,用于记录当前 Replicaset 的状态信息,例如副本数、可用副本数和就绪副本数等。
注意:status 字段是只读的,不能手动修改。查看replicaset 资源的spec字段如何定义?
root@ubuntu0:~/matedata/pod# kubectl explain rs.spec
KIND: ReplicaSet
VERSION: apps/v1FIELDS: minReadySeconds <integer> replicas <integer> selector <Object> -required- template <Object> 1)replicas:表示需要创建的 Pod 副本数。
2)selector:用于匹配要管理的 Pod 的标签选择器,通常是一个 key-value 对,例如 matchLabels: {app: nginx}。
3)template:定义 Pod 的模板,基于该模板创建的所有 Pod 都是相同的。模板中包含了 Pod 的元数据和规格信息,例如 Pod 的名称、标签、容器镜像、容器端口等。 #查看replicaset资源的spec下的template字段如何定义?
root@ubuntu0:~/matedata/pod# kubectl explain rs.spec.template
KIND: ReplicaSet
VERSION: apps/v1FIELDS: metadata <Object> #metadata 描述了 Pod 的元数据,例如名称和标签 spec <Object> #例如名称和标签 #查看template下spec字段下有哪些字段
root@ubuntu0:~/matedata/pod# kubectl explain rs.spec.template.spec
显示如下:
• activeDeadlineSeconds: 定义Pod的运行时间限制(秒)。
• affinity: 用于定义Pod如何调度到节点上的规则,可指定nodeSelector、nodeAffinity和podAffinity/podAntiAffinity。
• automountServiceAccountToken: 是否自动挂载Service Account的token到Pod中。
• containers: 定义Pod中的容器列表,该字段是必需的。
• dnsConfig: 定义Pod中的DNS配置,如DNS服务器的IP地址和搜索域。
• dnsPolicy: 定义Pod中的DNS策略,如使用ClusterFirst或Default。
• enableServiceLinks: 是否启用service account到相邻容器的自动服务链接。
• ephemeralContainers: 定义Pod中的临时容器列表,这些容器具有短暂的生命周期,例如用于调试或临时的数据处理。
• hostAliases: 定义Pod中的hosts文件条目。
• hostIPC: 是否允许容器共享IPC命名空间。
• hostNetwork: 是否将Pod的网络命名空间与主机共享。
• hostPID: 是否允许容器共享主机PID命名空间。
• hostUsers: 是否允许容器共享主机用户命名空间。
• hostname: 定义Pod的主机名。
• imagePullSecrets: 定义从私有仓库中拉取镜像所需的身份验证信息。
• initContainers: 定义Pod中的初始化容器列表,这些容器在主容器启动之前运行。
• nodeName: 定义Pod所在的节点名称。
• nodeSelector: 用于定义Pod应该调度到哪些节点上。
• os: 定义Pod所在的操作系统类型和版本。
• overhead: 定义Pod需要的CPU、内存和存储资源之外的其他资源。
• preemptionPolicy: 定义Pod被抢占的行为,如Never、PreemptLowerPriority或PreemptNever。
• priority: 定义Pod的调度优先级。
• priorityClassName: 定义Pod使用的调度优先级类名称。
• readinessGates: 定义Pod的就绪探针列表,这些探针用于检查容器是否已准备好接受流量。
• resourceClaims: 定义Pod使用的资源声明列表。
• restartPolicy: 定义Pod的重启策略,如Always、OnFailure或Never。
• runtimeClassName: 定义Pod使用的容器运行时类名称。
• schedulerName: 定义Pod使用的调度器名称。
• schedulingGates: 定义Pod的调度探针列表,这些探针用于检查节点是否已准备好接受Pod。
• securityContext: 定义Pod的安全上下文。
• serviceAccount: 定义Pod使用的Service Account的名称。
• serviceAccountName: 定义Pod使用的Service Account的名称。
• setHostnameAsFQDN: 是否将Pod的主机名设置为完全限定域名。
• shareProcessNamespace: 是否允许容器共享主机命名空间。如果将此字段设置为true,则在同一Pod中的容器可以共享主机的PID命名空间、IPC命名空间和UTS命名空间。这使得容器之间可以相互查看和访问进程、共享进程、文件系统和其他资源。通常情况下,建议不要将此设置为true,以提高容器之间的安全性和隔离性。
实战:Replicaset使用案例-部署Guestbook留言板
1.计算节点解压镜像
root@ubuntu1:~# docker load -i frontend.tar.gz
root@ubuntu2:~# docker load -i frontend.tar.gz
2.
root@ubuntu1:~# docker load -i myapp-blue-v1.tar.gz
Loaded image: janakiramm/myapp:v1
root@ubuntu1:~# docker load -i myapp-blue-v2.tar.gz
Loaded image: janakiramm/myapp:v2root@ubuntu0:~/matedata/rs# cat replicaset.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata: name: frontend labels: #上面这个标签是用于管理ReplicaSet 资源的app: guestbook tier: frontend
spec: replicas: 3 selector: #必须字段matchLabels: tier: frontend #要和template.metadata.labels下保持一致,就通过这个去找具有tier: frontend这个标签的pod,这样即使删了一个pod他能检测到,再给你创建一个让他pod始终保持在3个template: metadata: labels: tier: frontend #下面这个标签是用来管理pod资源的spec: containers: - name: php-redis image: yecc/gcr.io-google_samples-gb-frontend:v3 imagePullPolicy: IfNotPresent
#上述YAML文件详细说明
• apiVersion: 定义了使用的Kubernetes API版本,这里是apps/v1,用于创建ReplicaSet 对象。
• kind: 定义了创建的对象类型,这里是ReplicaSet。
• metadata: 定义了ReplicaSet对象的元数据,包括名称和标签。标签是用来标识这个ReplicaSet 对象的,方便后续的管理和查找。
• spec: 定义了ReplicaSet对象的规格,包括管理的pod副本数量和选择器,以及定义pod的模板。其中:
• replicas: 定义了 ReplicaSet 要管理的pod副本数量,这里是3个。
• selector: 定义了 ReplicaSet 要管理的pod的标签选择器,这里是选择带有tier=frontend 标签的 pod。
• template: 定义了ReplicaSet创建pod时所使用的模板,包括pod的元数据和容器的规格。
• metadata: 定义了pod的标签,这里是tier=frontend。
• spec: 定义了pod的容器规格,包括容器名称、镜像和端口。这里只有一个容器,容器名称是php-redis,镜像是yecc/gcr.io-google_samples-gb
frontend:v3,容器暴露的端口是80。
综上,这个资源清单是用来创建一个名为frontend的ReplicaSet对象,用于管理3个带有tier=frontend标签的pod,每个pod只有一个名为php-redis的容器,容器镜像为yecc/gcr.io-google_samples-gb-frontend:v3,容器暴露的端口是80。root@ubuntu0:~/matedata/rs# kubectl apply -f replicaset.yaml
replicaset.apps/frontend created
root@ubuntu0:~/matedata/rs# kubectl get pods -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
frontend-9p6gc 1/1 Running 0 4s 10.244.25.150 ubuntu1 <none> <none>
frontend-lqpsc 1/1 Running 0 4s 10.244.25.149 ubuntu1 <none> <none>
frontend-nznrc 1/1 Running 0 4s 10.244.152.85 ubuntu2 <none> <none>
root@ubuntu0:~/matedata/rs# kubectl get pods -owide --show-labels
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES LABELS
frontend-9p6gc 1/1 Running 0 9s 10.244.25.150 ubuntu1 <none> <none> tier=frontend
frontend-lqpsc 1/1 Running 0 9s 10.244.25.149 ubuntu1 <none> <none> tier=frontend
frontend-nznrc 1/1 Running 0 9s 10.244.152.85 ubuntu2 <none> <none> tier=frontend
root@ubuntu0:~/matedata/rs# kubectl get rs --show-labels
NAME DESIRED CURRENT READY AGE LABELS
frontend 3 3 3 34m app=guestbook,tier=frontend
DESIRED 希望管理的pod
CURRENT 当前的pod有几个
READY 就绪的pod有几个
#pod的名字是由控制器的名字-随机数组成的
Replicaset 管理pod-扩容、缩容、更新
Replicaset 实现 pod的扩容1.#动态查看带有tier=frontend 标签的 pod
root@ubuntu0:~/matedata/rs# kubectl get pods -l tier=frontend -w
NAME READY STATUS RESTARTS AGE
frontend-9p6gc 1/1 Running 0 10h
frontend-lqpsc 1/1 Running 0 10h
frontend-nznrc 1/1 Running 0 10h
ReplicaSet 最核心的功能是可以对pod进行扩容和缩容,如果我们觉得三个副本太少了,想要
增加pod副本数量,只需要修改配置文件replicaset.yaml里的replicas的值即可,原来
replicas: 3,现在变成replicaset: 4,修改之后,执行如下命令更新:1.更改为4个
root@ubuntu0:~/matedata/rs# grep replicas replicaset.yaml replicas: 4
root@ubuntu0:~/matedata/rs# kubectl apply -f replicaset.yaml
replicaset.apps/frontend configured或者直接edit修改
root@ubuntu0:~/matedata/rs# kubectl edit rs frontend
replicaset.apps/frontend edited3.再次查看,就有4个了
root@ubuntu0:~/matedata/rs# kubectl get pods -l tier=frontend -w
NAME READY STATUS RESTARTS AGE
frontend-9p6gc 1/1 Running 0 10h
frontend-lqpsc 1/1 Running 0 10h
frontend-nznrc 1/1 Running 0 10h
frontend-xzb7p 0/1 Pending 0 0s
frontend-xzb7p 0/1 Pending 0 0s
frontend-xzb7p 0/1 ContainerCreating 0 0s
frontend-xzb7p 0/1 ContainerCreating 0 1s
frontend-xzb7p 1/1 Running 0 2s#Replicaset 实现 pod的缩容
如果我们觉得5个Pod副本太多了,想要减少,只需要修改配置文件replicaset.yaml里的
replicas 的值即可,把replicaset:5变成replicas: 2,修改之后,执行如下命令更新:
1.两种方法人选其一即可1.1 edit直接修改root@ubuntu0:~/matedata/rs# kubectl edit rs frontend replicaset.apps/frontend edited1.2 修改yaml文件root@ubuntu0:~/matedata/rs# grep replicas replicaset.yaml replicas: 2
root@ubuntu0:~/matedata/rs# kubectl get pods -l tier=frontend -w
NAME READY STATUS RESTARTS AGE
frontend-lqpsc 1/1 Running 0 10h
frontend-nznrc 1/1 Running 0 10hReplicaset 实现 pod的更新
root@ubuntu0:~/matedata/rs# vim replicaset.yaml
#修改镜像
image: yecc/gcr.io-google_samples-gb-frontend:v3
变成
image: ikubernetes/myapp:v2
root@ubuntu0:~/matedata/rs# kubectl apply -f replicaset.yaml
replicaset.apps/frontend configured
基于上面YAML文件更新replicaset资源之后,pod不会自动重新创建,也不会用的新的镜
像,需要把pod手动删除,重新创建pod之后才会用新的镜像。
Deployment控制器:概念、原理解读
Deployment 概述
1.虽然ReplicaSet 已经可以用来控制Pod的副本数量和自动重启,但是ReplicaSet仅仅是Pod的一个管理器,它只能保证有一定数量的Pod在运行,但是对于如何更新Pod、回滚到历史版本、扩容缩容等操作,ReplicaSet并不支持或者说不够方便。
2.而Deployment则在ReplicaSet的基础上增加了更多的功能,它可以用来部署应用程序,并且支持更方便的应用程序更新、回滚和扩容缩容操作。Deployment通过定义副本控制器的方式来管理Pod的副本,它可以方便地进行版本控制,而且支持自动更新和回滚,能够保证应用程序的高可用性。另外,Deployment还支持滚动升级和滚动回滚,可以在不影响应用程序运行的情况下,实现无缝升级和回滚操作。
Deployment 工作原理:如何管理rs和Pod?
1.Deployment 通过创建和管理ReplicaSet和Pod来实现对应用的部署和管理。当
Pod 需要更新时,Deployment会根据新的Pod模板创建新的ReplicaSet,并逐步增加
新的Pod副本,同时逐渐减少旧的ReplicaSet的Pod副本数量,直到新的ReplicaSet
中所有Pod副本都处于运行状态。
2.具体来说,Deployment包括以下几个步骤:
- 创建初始的ReplicaSet和Pod:Deployment根据指定的Pod模板创建初始的ReplicaSet 和 Pod,同时设置Pod的标签。
- 更新Pod模板:当需要更新Pod模板时,Deployment会根据新的Pod模板创建一个新的ReplicaSet,并逐渐增加新的Pod副本,同时逐渐减少旧的ReplicaSet的Pod 副本数量,直到新的ReplicaSet中所有Pod副本都处于运行状态。
- 回滚操作:如果新的Pod模板存在问题,需要回滚操作时,Deployment会根据旧的Pod模板创建一个ReplicaSet,并逐渐增加旧的ReplicaSet的Pod副本数量,同时逐渐减少新的ReplicaSet的Pod副本数量,直到旧的ReplicaSet中所有Pod用。 副本都处于运行状态。
- 扩容和缩容:Deployment可以通过修改ReplicaSet的副本数量来扩容和缩容应
通过这些步骤,Deployment实现了对应用的部署、更新、回滚、扩容和缩容等操作,同时保证了应用的高可用性。
Deployment资源清单文件编写技巧
Deployment使用案例-创建一个web站点
deployment 是一个三级结构,deployment管理replicaset,replicaset管理pod,
例子:用deployment创建一个pod 1.创建一个新的命名空间root@ubuntu0:~/matedata/pod# kubectl create namespace blue-greennamespace/blue-green created
2.编写资源清单
root@ubuntu0:~/matedata/deploy# cat deploy-demo.yaml
apiVersion: apps/v1 #deployment对应的api版本
kind: Deployment #创建的资源是deployment
metadata:name: myapp-v1 #deployment的名字namespace: blue-green labels:myapp: v1
spec:replicas: 2 #deployment管理的pod副本数 selector: #标签选择器matchLabels: # matchLabels下定义的标签需要跟template.metadata.labels定的标签一致 myapp: v1template:metadata:labels:myapp: v1spec: #定义容器的属性containers:- name: myappimage: janakiramm/myapp:v1 imagePullPolicy: IfNotPresentports:- containerPort: 80startupProbe:initialDelaySeconds: 3timeoutSeconds: 10periodSeconds: 5httpGet:scheme: HTTPport: 80path: /livenessProbe:initialDelaySeconds: 3timeoutSeconds: 10periodSeconds: 5httpGet:scheme: HTTPport: 80path: /readinessProbe:failureThreshold: 2successThreshold: 1initialDelaySeconds: 3timeoutSeconds: 10periodSeconds: 5httpGet:scheme: HTTPport: 80path: /
root@ubuntu0:~/matedata/deploy# kubectl apply -f deploy-demo.yaml
deployment.apps/myapp-v1 created
root@ubuntu0:~/matedata/deploy# kubectl get pods -o wide -w -n blue-green
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
myapp-v1-65dc6df7c-wfq8d 1/1 Running 0 71s 10.244.152.87 ubuntu2 <none> <none>
myapp-v1-65dc6df7c-wkvlh 1/1 Running 0 71s 10.244.25.152 ubuntu1 <none> <none>• ports: 定义容器的端口列表。
• containerPort: 80: 指定容器监听的端口为80。
• startupProbe: 定义容器的启动探针。
• periodSeconds: 5: 设置探针的检查周期为5秒。
• initialDelaySeconds: 20: 设置探针在容器启动后20秒后开始进行检查。
• timeoutSeconds: 10: 设置探针的超时时间为10秒。
• httpGet: 定义HTTP请求方式的探针。
• scheme: HTTP: 指定使用HTTP协议进行请求。
• port: 80: 指定请求的端口为80。
• path: /: 指定请求的路径为根路径。
• livenessProbe: 定义容器的存活性探针。root@ubuntu0:~/matedata/deploy# kubectl get deployments.apps -n blue-green --show-labels
NAME READY UP-TO-DATE AVAILABLE AGE LABELS
myapp-v1 2/2 2 2 3m46s myapp=v1
• NAME: 表示Deployment的名称。
• READY: 表示当前就绪状态的Pod数量。在这里,myapp-v1的Deployment有2个Pod,都处于就绪状态,因此显示为2/2。
• UP-TO-DATE: 表示当前与Deployment所期望的Pod副本数匹配的副本数量。在这里,myapp-v1的Deployment期望有2个Pod副本,因此显示为2。
• AVAILABLE: 表示当前可用的Pod副本数量。在这里,myapp-v1的Deployment有2个可用的Pod副本,因此显示为2。
• AGE: 表示Deployment的创建时间,即其存在的时间。在这里,myapp v1的Deployment创建了60秒(1分钟)。 此外,当创建一个Deployment时,Kubernetes还会同时创建一个与之关联的ReplicaSet。ReplicaSet负责确保Deployment指定的Pod副本数目与实际运行的Pod副本数目保持一致。在这里,RS的名称中的67fd9fc9c8是根据引用的Pod模板的名字生成的哈希值,以确保唯一性和关联性。查看Deployment资源对象由哪几部分组成
root@ubuntu0:~/matedata/deploy# kubectl explain deployment
KIND: Deployment
VERSION: apps/v1
DESCRIPTION: Deployment enables declarative updates for Pods and ReplicaSets.
FIELDS: apiVersion <string> #该资源使用的api版本 kind <string> #创建的资源是什么? metadata <Object> #元数据,包括资源的名字和名称空间 spec <Object> #定义容器的 status <Object> #状态,不可以修改
Deployment管理pod-扩容、缩容、滚动更新、回滚
#通过deployment管理应用,实现扩容,把副本数变成3
1.把replicas 换成3即可
root@ubuntu0:~/matedata/deploy# grep replicas deploy-demo.yaml replicas: 3
root@ubuntu0:~/matedata/deploy# kubectl apply -f deploy-demo.yaml
deployment.apps/myapp-v1 configured
root@ubuntu0:~/matedata/deploy# kubectl get pods -n blue-green
NAME READY STATUS RESTARTS AGE
myapp-v1-65dc6df7c-96mfq 1/1 Running 0 10s
myapp-v1-65dc6df7c-wfq8d 1/1 Running 0 36m
myapp-v1-65dc6df7c-wkvlh 1/1 Running 0 36m
pod 反亲和性
基于 k8s 的 deployment 控制器运行 nginx 服务,指定 pod 副本数是 2,根据 pod 反亲和性让两个 pod 调度到不同的工作节点使用背景和场景:业务中的某个关键服务,配置了多个 replicas 副本数,结果在部署时,发现多个相同的副本同时部署在同一个主机上,结果主机故障时,所有副本同时漂移了,导致服务间断性中断基于以上背景,实现一个服务的多个副本分散到不同的主机上,使每个主机有且只能运行服务的
一个副本,这里用到的是 Pod 反亲和性,特性是根据已经运行在 node 上的 pod 的 label,不再将相同 label 的 pod 也调度到该 node,实现每个 node 上只运行一个副本的 podpod 亲和性和反亲和性的区别
亲和性(podAffinity):和指定 label 的 pod 部署在相同 node 上
反亲和性(podAntiAffinity):不想和指定 label 的 pod 的服务部署在相同 node 上podAntiAffinity 实战部署反亲和性分软性要求和硬性要求requiredDuringSchedulingIgnoredDuringExecution:硬性要求,必须满足条件,保证分散部署的效果最好使用用此方式preferredDuringSchedulingIgnoredDuringExecution:软性要求,可以不完全满足,即有可能同一 node 上可以跑多个副本[root@xuegod63~]# cat deployment-nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:name: nginxlabels:app: nginx
spec:replicas: 2selector:matchLabels:app: nginxtemplate:metadata:labels:app: nginx #pod都具有app: nginx标签呀spec:affinity:podAntiAffinity:requiredDuringSchedulingIgnoredDuringExecution:- labelSelector:matchExpressions:- key: appoperator: Invalues:- nginx #pod和pod之间做反亲和性,一个调度到ubuntu2 另一个就会调度到ubuntu1上topologyKey: "kubernetes.io/hostname"containers:- name: nginximage: nginximagePullPolicy: "IfNotPresent"ports:- containerPort: 80name: httpprotocol: TCP备注:配置说明
# 如果节点上的 pod 标签存在满足 app=nginx,则不能部署到节点上
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- nginx