三、kubernetes之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 仅支持等式)

有三个主要组成模块:

  1. replicas:指定用户期望的副本数
  2. selector:标签选择器,判定哪些Pod接受管理控制
  3. 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也会清空。
常用于节点级的应用例如:

  1. 运行集群存储 daemon,例如在每个节点上运行 glusterd、ceph。
  2. 在每个节点上运行日志收集daemon,例如fluentd、logstash。
  3. 在每个节点上运行监控 daemon,例如 Prometheus Node、Exporter、collectd

两个模块:
selector:标签选择器,判定哪些Pod接受管理控制
template:Pod资源模板,用于创建新的Pod,该模板定义方式参见pod资源定义

仅在某些节点运行Pod

  1. 指定 .spec.template.spec.nodeSelector字段,DaemonSet Controller 将在能够与 Node
    Selector 匹配的节点上创建 Pod。
  2. 指定 .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由以下几个部分组成:

  1. Headless Service(无头服务)用于为Pod资源标识符生成可解析的DNS记录,让域名直接解析到pod。如此,关于域名的流量直接打在pod。
  2. volumeClaimTemplates存储卷申请模板(pvc创建模板,为每个pod生成一个pvc存储卷),基于静态或动态PV供给方式为Pod资源提供专有的固定存储(分布式应用的Pod,彼此使用不同的存储卷)。 而在pod模板中只能使用同一个存储卷。
  3. StatefulSet,用于管控Pod资源。

注意:StatefulSet并不能简单的适用于所有有状态的应用,仍需要用户自定义脚本处理相应的应用

删除statefulset 并不会删除掉pvc,重启statefulset时其管理的Pod会根据volumeClaimTemplates和pvc的名字重新建立关联关系。

在k8s集群中域名的格式如下:
pod_name.service_name.ns_name.svc.cluster.local 标红部分为固定

分区更新,指定分区号N,则在sts中的序号大于等于N的pod会进行更新

发布了40 篇原创文章 · 获赞 2 · 访问量 2100

猜你喜欢

转载自blog.csdn.net/weixin_42155272/article/details/90210336