三、kubernetes之pod的调度(一)
Pod控制器的作用上一文中直接创建的Pod是不受Pod控制器管理,也就很难实现K8S的一些特性。kubelet是K8s集群节点代理程序,它在每个工作节点上都运行着一个实例。当工作节点发生故障时,kubelet也将不可用,pod无法再由kubelet重启。此时Pod的存活性一般由工作节点之外的Pod控制器来保证。在K8S中理想的工作模式应当是Pod控制器管理Pod,保障Pod资源能按用户所定义...
pod的调度有两种方式,一种是通过Pod的控制器,另一种通过设置Pod自身的资源属性
Pod控制器的作用
上一文中直接创建的Pod是不受Pod控制器管理,也就很难实现K8S的一些特性。
kubelet是K8s集群节点代理程序,它在每个工作节点上都运行着一个实例。当工作节点发生故障时,kubelet也将不可用,pod无法再由kubelet重启。此时Pod的存活性一般由工作节点之外的Pod控制器来保证。
在K8S中理想的工作模式应当是Pod控制器管理Pod,保障Pod资源能按用户所定义的要求工作着。
Pod控制器类型详解
ReplicaSet(简写rs)
是replicationController的改善款,能保障Pod正常工作(出现故障后重启或重建)、保障Pod的正常数量(多退少补),并支持Pod扩缩容。
ReplicaSet 支持集合式的 selector(ReplicationController 仅支持等式)
有三个主要组成模块:
- replicas:指定用户期望的副本数
- selector:标签选择器,判定哪些Pod接受管理控制
- template:Pod资源模板,用于创建新的Pod,该模板定义方式参见pod资源定义
创建ReplicaSet
ngx-relicatSet-yaml内容如下
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: frontend
labels:
app: ngx-rs
tier: frontend
spec:
replicas: 3 ##指定总共需要3个pod
selector: ##通过label选择接受管理的pod
matchLabels:
tier: frontend
template: ##依据此模板生成Pod
metadata:
labels:
tier: frontend
spec:
containers:
- name: ngxv2
image: 192.168.80.146:5000/my_ngx:v2
将此文件提交给kubernetes集群, 生成相应的pod管理器ReplicaSet及其管理的Pod
[root@k8s-master k8s-yaml]# kubectl create -f ngx-relicatSet-yaml
查看Pod管理器的状态
[root@k8s-master k8s-yaml]# kubectl get rs frontend
NAME DESIRED CURRENT READY AGE
frontend 3 3 3 10m
[root@k8s-master k8s-yaml]# kubectl describe rs/frontend
Name: frontend
Namespace: default
Selector: tier=frontend
Labels: app=ngx-rs
tier=frontend
Annotations: <none>
Replicas: 3 current / 3 desired
Pods Status: 3 Running / 0 Waiting / 0 Succeeded / 0 Failed
Pod Template:
Labels: tier=frontend
Containers:
ngxv2:
Image: 192.168.80.146:5000/my_ngx:v2
Port: <none>
Host Port: <none>
Environment: <none>
Mounts: <none>
Volumes: <none>
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfulCreate 13m replicaset-controller Created pod: frontend-6z7wn
Normal SuccessfulCreate 13m replicaset-controller Created pod: frontend-dp9xv
Normal SuccessfulCreate 11m replicaset-controller Created pod: frontend-v8dkp
验证非模板创建的Pod和Pod管理器的关系
之前已经创建了控制器replicaSet(frontend),现在建立一个Pod1(其label符合管理器的selectot),观察Pod1情况。
Pod1的yaml清单如下:
apiVersion: v1
kind: Pod
metadata:
name: pod1
labels:
tier: frontend ##此label符合管理器replicaSet中的selector要求,故会受控制
spec:
containers:
- name: hello1
image: 192.168.80.146:5000/my_ngx:v2
新的Pod将被ReplicaSet获取,并接受管理;因为Pod数量将超过其所需,故将终止新的Pod1。
[root@k8s-master k8s-yaml]# kubectl get pod -w
NAME READY STATUS RESTARTS AGE
frontend-6z7wn 1/1 Running 0 24m
frontend-dp9xv 1/1 Running 0 24m
frontend-v8dkp 1/1 Running 0 23m
pod1 0/1 Terminating 0 5s
注意:如果是先创建Pod1,再创建ReplicaSet;那么Pod1会保留运作,创建ReplicaSet时就只依据模板生成两个Pod
从ReplicaSet中删除一个Pod
方法就是修改Pod的label;管理器会自动新建一个Pod替代。
[root@k8s-master k8s-yaml]# kubectl label pods frontend-6z7wn tier=test --overwrite
pod/frontend-6z7wn labeled
[root@k8s-master k8s-yaml]# kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
frontend-6z7wn 1/1 Running 0 2h tier=test
frontend-c9h5l 0/1 ContainerCreating 0 5s tier=frontend
frontend-dp9xv 1/1 Running 0 2h tier=frontend
frontend-v8dkp 1/1 Running 0 2h tier=frontend
修改副本集数量
只需更新清单文件中.spec.replicas字段即可扩展或缩小ReplicaSet 。
[root@k8s-master k8s-yaml]# kubectl apply -f ngx-relicatSet-yaml
Warning: kubectl apply should be used on resource created by either kubectl create --save-config or kubectl apply
replicaset.apps/frontend configured
[root@k8s-master k8s-yaml]# kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
frontend-6z7wn 1/1 Running 0 2h tier=test
frontend-dp9xv 1/1 Running 0 2h tier=frontend
frontend-v8dkp 1/1 Running 0 2h tier=frontend
除非需要自定义更新编排或根本不需要更新,否则我们建议使用Deployment;而不是直接使用ReplicaSet。
Deployment
建立在ReplicaSet控制器之上,通过控制RepilicaSet实现对Pod的管理;为Pod和ReplicaSet提供声明式更新。
在Deployment中描述了所需的状态,Deployment控制器会逐渐将实际状态更新为所需状态。通过定义Deployment以创建新的ReplicaSet,或者删除现有的Deployment并使用新的Deployment接管所有资源。
创建Deployment
一个deployment清单
apiVersion: apps/v1
kind: Deployment
metadata:
name: ngx-deployment ##定义一个名为ngx-deployment的deployment
labels:
app: ngx
spec:
replicas: 3 ##定义有三个Pod
selector:
matchLabels: ##定义找到label为app:ngx的pod
app: ngx
template: ##定义pod的模板
metadata:
labels:
app: ngx ##定义pod的label为app:ngx
spec:
containers:
- name: ngxv2
image: 192.168.80.146:5000/my_ngx:v2
创建此deployment
[root@k8s-master k8s-yaml]# kubectl apply -f ngx-deployment.yaml
deployment.apps/ngx-deployment created
[root@k8s-master k8s-yaml]# kubectl get deployments
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
ngx-deployment 3 3 3 3 28s
[root@k8s-master k8s-yaml]# kubectl get rs
NAME DESIRED CURRENT READY AGE
ngx-deployment-559486d8fd 3 3 3 12m
[root@k8s-master k8s-yaml]# kubectl get pods
NAME READY STATUS RESTARTS AGE
ngx-deployment-559486d8fd-4c49k 1/1 Running 0 13m
ngx-deployment-559486d8fd-hfht7 1/1 Running 0 13m
ngx-deployment-559486d8fd-pk967 1/1 Running 0 13m
由deployment创建的rs其名字,以deployment的名字为头部。
更新Pod中容器
当且仅当deployment的pod模板(即.spec.template)更改时,才会触发Deployment的滚动更新
例如修改pod中容器版本,由v2降为v1
[root@k8s-master k8s-yaml]# kubectl edit deployment.v1.apps/ngx-deployment
"/tmp/kubectl-edit-ltme5.yaml" 69L, 2277C written
注意:不会改变ngx-deployment.yaml,而是生成一个新的临时文件交于kubectl应用
观察滚动更新进度
[root@k8s-master k8s-yaml]# kubectl rollout status deployment.v1.apps/ngx-deployment
Waiting for deployment "ngx-deployment" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "ngx-deployment" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "ngx-deployment" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "ngx-deployment" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "ngx-deployment" rollout to finish: 1 old replicas are pending termination...
deployment "ngx-deployment" successfully rolled out
观察更新后的变化,旧的rs被保留但只运行新的rs和新的pod
[root@k8s-master k8s-yaml]# kubectl get rs
NAME DESIRED CURRENT READY AGE
ngx-deployment-559486d8fd 0 0 0 35m
ngx-deployment-58d847f49c 3 3 3 13m
[root@k8s-master k8s-yaml]# kubectl get deployment
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
ngx-deployment 3 3 3 3 35m
[root@k8s-master k8s-yaml]# kubectl get pods
NAME READY STATUS RESTARTS AGE
ngx-deployment-58d847f49c-fjsgr 1/1 Running 0 15m
ngx-deployment-58d847f49c-sjqrq 1/1 Running 0 15m
ngx-deployment-58d847f49c-znw5d 1/1 Running 0 15m
deployment可以确保在更新时只有一定数量的Pod可能会关闭。默认情况下,它确保最多不可用Pod为所需数量的25%;还确保在所需数量的Pod之上只能创建一定数量的Pod。默认情况下,它确保最多比所需数量的Pod多25%
例如,如果仔细查看上面的部署,您将看到它首先创建了一个新的Pod,然后删除了一些旧的Pod并创建了新的Pod。在有足够数量的新Pod出现之前,它不会杀死旧的Pod,并且在足够数量的旧Pod被杀之前不会创建新的Pod。它确保可用Pod的数量至少为2,并且Pod的总数最多为4
滚动更新
首先查看之前滚动更新的历史,和具体更新内容
[root@k8s-master k8s-yaml]# kubectl rollout history deployment.v1.apps/ngx-deployment
deployments "ngx-deployment"
REVISION CHANGE-CAUSE
3 <none>
4 <none>
[root@k8s-master k8s-yaml]# kubectl rollout history deployment.v1.apps/ngx-deployment --revision=3
deployments "ngx-deployment" with revision #3
Pod Template:
Labels: app=ngx
pod-template-hash=1150428498
Containers:
ngxv2:
Image: 192.168.80.146:5000/my_ngx:v2
Port: <none>
Host Port: <none>
Environment: <none>
Mounts: <none>
Volumes: <none>
[root@k8s-master k8s-yaml]# kubectl rollout history deployment.v1.apps/ngx-deployment --revision=4
deployments "ngx-deployment" with revision #4
Pod Template:
Labels: app=ngx
pod-template-hash=1484039057
Containers:
ngxv2:
Image: 192.168.80.146:5000/my_ngx:v1
Port: <none>
Host Port: <none>
Environment: <none>
Mounts: <none>
Volumes: <none>
回滚至指定版本
[root@k8s-master k8s-yaml]# kubectl rollout undo deployment.v1.apps/ngx-deployment --to-revision=3
deployment.apps/ngx-deployment
扩展更新
命令扩展部署
kubectl scale deployment.v1.apps/ngx-deployment --replicas=6
启用自动扩缩
kubectl autoscale deployment.v1.apps/nginx-deployment --min=5 --max=10 --cpu-percent=80
暂停和恢复deployment
可以暂停deployment,然后恢复它。在暂停期间,对deployment的更新将不会被立马执行,需等待恢复deployment。
kubectl rollout pause deployment.v1.apps/ngx-deployment
kubectl set image deployment.v1.apps/ngx-deployment nginx=nginx:1.9.1
kubectl rollout resume deployment.v1.apps/ngx-deployment
deployment其他常用字段说明
.spec.revisionHistoryLimit
以指定要保留此部署的旧ReplicaSet数。其余的将在后台进行垃圾收集。默认情况下,它是10。将此字段显式设置为0将导致清理部署的所有历史记录,从而部署将无法回滚。
.spec.strategy
指定用于替换旧Pod的策略;Recreate则所有现有的Pod都会在创建新的Pod之前被杀死;RollingUpdate则滚动更新Pod,可以指定maxUnavailable并maxSurge控制滚动更新过程。
maxUnavailable,更新过程中为最多不可用数量,该值可以是绝对数(例如,5)或所需Pod的百分比(例如,10%
maxSurge,更新过程中可以创建的最大Pod数。该值可以是绝对数(例如,5)或所需Pod的百分比(例如,10%)
deployment管理多个rs控制,但只保证一个rs存在工作状态,其他的存在冷备状态。其灰度更新的逻辑顺序如下:
DaemonSet
确保所有节点(或指定的一些节点)都运行一个指定Pod。新加入的节点也会自动运行指定的pod;节点退出则所有Pod被回收;删除一个DaemonSet,那他创建的Pod也会清空。
常用于节点级的应用例如:
- 运行集群存储 daemon,例如在每个节点上运行 glusterd、ceph。
- 在每个节点上运行日志收集daemon,例如fluentd、logstash。
- 在每个节点上运行监控 daemon,例如 Prometheus Node、Exporter、collectd
两个模块:
selector:标签选择器,判定哪些Pod接受管理控制
template:Pod资源模板,用于创建新的Pod,该模板定义方式参见pod资源定义
仅在某些节点运行Pod
- 指定 .spec.template.spec.nodeSelector字段,DaemonSet Controller 将在能够与 Node
Selector 匹配的节点上创建 Pod。 - 指定 .spec.template.spec.affinity字段, DaemonSet Controller 将在能够与 Node Affinity
匹配的节点上创建 Pod。
如果根本就没有指定,则 DaemonSet Controller 将在所有节点上创建 Pod。
更新策略
DaemonSet有两种更新策略类型:
OnDelete:这是向后兼容性的默认更新策略。使用 OnDelete更新策略,在更新DaemonSet模板后,只有在手动删除旧的DaemonSet pod时才会创建新的DaemonSet pod。这与Kubernetes 1.5或更早版本中DaemonSet的行为相同。
RollingUpdate:使用RollingUpdate更新策略,在更新DaemonSet模板后,旧的DaemonSet pod将被终止,并且将以受控方式自动创建新的DaemonSet pod。
Job
用于管理执行一次性任务的Pod,正常完成任务就Pod正常退出,不会发生自我修复
apiVersion: batch/v1
kind: Job
metadata:
name: pi
spec:
template:
spec:
containers:
- name: pi
image: perl
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
restartPolicy: Never
backoffLimit: 4
Cronjob
在给定时间点只运行一次或周期性地运行任务的Pod
StatefullSet
适用于管理有状态的Pod,有一段初始化的过程。Deployment创建的pod是无状态的,当挂载了Volume之后,如果该pod挂了,RS会重建一个pod,因为Deployment是无状态的原因将无法再次挂载volume。
为了解决此类问题,引入了StatefulSet用于保留Pod的状态信息,应用场景包括:
- 1、稳定的持久化存储,即Pod重新调度后还是能访问到相同的持久化数据,基于PVC来实现
2、稳定的网络标志,即Pod重新调度后其PodName和HostName不变,基于Headless Service(即没有ClusterIP的Service)来实现
3、有序部署,有序扩展,即Pod是有顺序的,在部署或者扩展的时候要依据定义的顺序依次依次进行(即从0到N-1,在下一个Pod运行之前所有之前的Pod必须都是Running和Ready状态),基于initcontainers来实现
4、有序收缩,有序删除(即从N-1到0)
5、有序的滚动更新(版本能兼容,先更新从节点)
StatefulSet由以下几个部分组成:
- Headless Service(无头服务)用于为Pod资源标识符生成可解析的DNS记录,让域名直接解析到pod。如此,关于域名的流量直接打在pod。
- volumeClaimTemplates存储卷申请模板(pvc创建模板,为每个pod生成一个pvc存储卷),基于静态或动态PV供给方式为Pod资源提供专有的固定存储(分布式应用的Pod,彼此使用不同的存储卷)。 而在pod模板中只能使用同一个存储卷。
- StatefulSet,用于管控Pod资源。
注意:StatefulSet并不能简单的适用于所有有状态的应用,仍需要用户自定义脚本处理相应的应用
删除statefulset 并不会删除掉pvc,重启statefulset时其管理的Pod会根据volumeClaimTemplates和pvc的名字重新建立关联关系。
在k8s集群中域名的格式如下:
pod_name.service_name.ns_name.svc.cluster.local
标红部分为固定
分区更新,指定分区号N,则在sts中的序号大于等于N的pod会进行更新
更多推荐
所有评论(0)