当前位置: 首页 > 工具软件 > WPL/s > 使用案例 >

k8s-Deployment控制器

南宫嘉
2023-12-01

Pod资源控制器

一、控制器介绍

   在生产上面很少单独创建Pod资源,而是通过资源控制器来创建和管理Pod。资源的控制器能够处理副本的管理、上线,并在 Pod 失效时提供自愈能力。 例如,如果一个节点失败,控制器注意到该节点上的 Pod 已经停止工作, 就可以创建替换性的 Pod。调度器会将替身 Pod 调度到一个健康的节点执行。

  常用资源控制器如下:

    a.) ReplicaSet

    b.) Deployment

    c.) StatefulSet

    d.) DaemonSet

    f.) Jobs

二、ReplcaSet

  ReplicaSet(RS) 的主要作用就是维持一组 Pod 副本的运行,保证一定数量的 Pod 在集群中正常运行,ReplicaSet 控制器会持续监听它说控制的这些 Pod 的运行状态,在 Pod 发送故障数量减少或者增加时会触发调谐过程,始终保持副本数量一定(保证期望的相同Pod可用pod数量的)。

  RS举个栗@_@:

[root@yc k8s-test]# cat replicaSet.yaml 
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: replicaset-test
spec:
  replicas: 2  # pod数量
  selector:    # Label Selector,必须匹配 Pod 模板中的标签
    matchLabels:
      app: nginx
  template:   # Pod 模板
    metadata:
      labels:
        app: nginx  # 需要和replicaset.sepc.selector 匹配
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80

  此外,可以通过更新.spec.replicas 字段,轻松进行pod扩容缩容。。

  在缩容时,ReplicaSet 控制器通过对可用的 Pods 进行排序来优先选择 要被删除的 Pods。其一般性算法如下:

    1. 首先选择剔除Pending(且不可调度)的 Pods

     2.如果设置了 pod-deletion-cost注解,则注解值 较小的优先被裁减掉

    3. Pending所处节点上副本个数较多的 Pod 优先于所处节点上副本较少者

    4.如果 Pod 的创建时间不同,最近创建的 Pod 优先于早前创建的 Pod 被裁减。

    PS: 如果以上比较结果都相同,则随机选择。

三、Deploynent

  在实际使用的时候,我们不会去直接使用 RS,而是会使用更上层的控制器,比如 Deployment。Deployment 一个非常重要的功能就是实现了 Pod 的“水平扩展/收缩”,比如我们应用更新了,我们只需要更新我们的容器镜像,然后修改 Deployment 里面的 Pod 模板镜像,那么 Deployment 就会用滚动更新(Rolling Update)的方式来升级现在的 Pod,这个能力是非常重要的,因为对于线上的服务我们需要做到不中断服务,所以滚动更新就成了必须的一个功能。而 Deployment 这个能力的实现,依赖的就是面提到的 ReplicaSet 这个资源对象,可以通俗的理解就是每个 Deployment 就对应集群中的一次部署,这样就更好理解了.

3.1创建Deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-dev  # 创建名为 nginx-dev的 Deployment
  labels:
    app: nginx-dev
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx-dev
  template:
    metadata:
      labels:
        app: nginx-dev
    spec:
      containers:
      - image: nginx:1.19
        imagePullPolicy: IfNotPresent
        name: nginx
        resources:
          requests:
            cpu: 0.5

3.2 查看Deployment

kubectl get deployment
NAME        READY   UP-TO-DATE   AVAILABLE   AGE
nginx-dev   3/3     3            3           4m15s

  NAME: 列出了集群中 Deployment 的名称。

  READY: 显示应用程序的可用的 副本 数。显示的模式是“就绪个数/期望个数”。

  UP-TO-DATE: 显示为了达到期望状态已经更新的副本数。

  AVAILABLE: 显示应用可供用户使用的副本数。

  AGE: 显示应用程序运行的时间。

3.2 Deployment滚动更新

  当且仅当 Deployment Pod 模板(即 .spec.template)发生改变时,例如模板的标签或容器镜像被更新, 才会触发 Deployment 上线。 其他更新(如对 Deployment 执行扩缩容的操作)不会触发Pod更新。

  1.使用命令更新Pod

  [root@yc k8s-test]# kubectl set image deployment/nginx-dev nginx=nginx:1.20.1 --record
deployment.apps/nginx-dev image updated

--record:记录下我们的每次操作所执行的命令,以方便后面查看
  2.查看Pod滚动更新状态

[root@yc k8s-test]# kubectl rollout status deployment/nginx-dev
Waiting for deployment "nginx-dev" rollout to finish: 1 out of 3 new replicas have been updated...
Waiting for deployment "nginx-dev" rollout to finish: 1 out of 3 new replicas have been updated...
Waiting for deployment "nginx-dev" rollout to finish: 1 out of 3 new replicas have been updated...
Waiting for deployment "nginx-dev" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "nginx-dev" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "nginx-dev" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "nginx-dev" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "nginx-dev" rollout to finish: 1 old replicas are pending termination...
deployment "nginx-dev" successfully rolled out

  Deployment可确保在更新时仅关闭一定数量的 Pod。默认情况下,它确保至少所需 Pods 75% 处于运行状态(最大不可用比例为 25%)。

  Deployment 还确保创建的Pod 数量只可能比期望 Pods 数高一点点。 默认情况下,它可确保启动的 Pod 个数比期望个数最多多出 25%(最大峰值 25%)。

  例如,如果仔细查看上述 Deployment ,将看到它首先创建了一个新的 Pod,然后删除了一些旧的 Pods, 并创建了新的 Pods。它不会杀死老 Pods,直到有足够的数量新的 Pods 已经出现。 在足够数量的旧 Pods 被杀死前并没有创建新 Pods。它确保至少 2 个 Pod 可用,同时 最多总共 4 个 Pod 可用。使用describe可以看到RollingUpdateStrategy: 25% max unavailable, 25% max surge

[root@yc k8s-test]# kubectl describe deployment nginx-dev
Name:                   nginx-dev
Namespace:              default
CreationTimestamp:      Thu, 05 Aug 2021 14:43:54 +0800
Labels:                 app=nginx-dev
Annotations:            deployment.kubernetes.io/revision: 2
                        kubernetes.io/change-cause: kubectl set image deployment/nginx-dev nginx=nginx:1.20.1 --record=true
Selector:               app=nginx-dev
Replicas:               3 desired | 3 updated | 3 total | 3 available | 0 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  25% max unavailable, 25% max surge
Pod Template:
  Labels:  app=nginx-dev
  Containers:
   nginx:
    Image:      nginx:1.20.1
    Port:       <none>
    Host Port:  <none>
    Requests:
      cpu:        500m
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>
Conditions:
  Type           Status  Reason
  ----           ------  ------
  Available      True    MinimumReplicasAvailable
  Progressing    True    NewReplicaSetAvailable
OldReplicaSets:  <none>
NewReplicaSet:   nginx-dev-58c688cc59 (3/3 replicas created)
Events:
  Type    Reason             Age    From                   Message
  ----    ------             ----   ----                   -------
  Normal  ScalingReplicaSet  39m    deployment-controller  Scaled up replica set nginx-dev-6bff568f4d to 3
  Normal  ScalingReplicaSet  10m    deployment-controller  Scaled up replica set nginx-dev-58c688cc59 to 1
  Normal  ScalingReplicaSet  8m37s  deployment-controller  Scaled down replica set nginx-dev-6bff568f4d to 2
  Normal  ScalingReplicaSet  8m37s  deployment-controller  Scaled up replica set nginx-dev-58c688cc59 to 2
  Normal  ScalingReplicaSet  8m31s  deployment-controller  Scaled down replica set nginx-dev-6bff568f4d to 1
  Normal  ScalingReplicaSet  8m30s  deployment-controller  Scaled up replica set nginx-dev-58c688cc59 to 3
  Normal  ScalingReplicaSet  8m25s  deployment-controller  Scaled down replica set nginx-dev-6bff568f4d to 0

  可以看到,当第一次创建 Deployment 时,它创建了一个 ReplicaSet(nginx-dev-6bff568f4d,PS:Deployment 控制器将 pod-template-hash 标签添加到 Deployment 所创建或收留的 每个 ReplicaSet 。此标签可确保 Deployment 的子 ReplicaSets 不重叠。 标签是通过对 ReplicaSet 的 PodTemplate 进行哈希处理。 所生成的哈希值被添加到 ReplicaSet 选择算符、Pod 模板标签,并存在于在 ReplicaSet 可能拥有的任何现有 Pod 中) 并将其直接扩容至 3 个副本。更新 Deployment 时,它创建了一个新的 ReplicaSet (nginx-dev-58c688cc59),并将其扩容为 1,然后将旧 ReplicaSet 缩容到 2, 以便至少有 2 个 Pod 可用且最多创建 4 个 Pod。 然后,它使用相同的滚动更新策略继续对新的 ReplicaSet 扩容并对旧的 ReplicaSet 缩容。 最后,有 3 个可用的副本在新的 ReplicaSet 中,旧 ReplicaSet 将缩容到 0。

  3.暂停及恢复滚动更新

# kubectl rollout pause deployment/nginx-dev 
deployment.apps/nginx-dev paused
#kubectl rollout resume deployment/nginx-dev
deployment.apps/nginx-dev resumed

3.3 回滚

# kubectl get rs
NAME                   DESIRED   CURRENT   READY   AGE
nginx-dev-58c688cc59   4         4         4       86m
nginx-dev-6bff568f4d   0         0         0       116m

  可以看到之前的RS依然保留着,

# kubectl rollout history deployment nginx-dev
deployment.apps/nginx-dev 
REVISION  CHANGE-CAUSE
1         <none>
2         kubectl set image deployment/nginx-dev nginx=nginx:1.20.1 --record=true
3         kubectl set image deployment/nginx-dev nginx=nginx:1.21.1 --record=true

   rollout history 中记录的 revision 是和 ReplicaSets 一一对应。如果我们手动删除某个 ReplicaSet,对应的rollout history就会被删除,也就是说我们无法回滚到这个revison了,同样我们还可以查看其中某个revison的详细信息。

# kubectl rollout history deployment nginx-dev --revision=3
deployment.apps/nginx-dev with revision #3
Pod Template:
  Labels:	app=nginx-dev
	pod-template-hash=bb9fbdd4b
  Annotations:	kubernetes.io/change-cause: kubectl set image deployment/nginx-dev nginx=nginx:1.20.1 --record=true
  Containers:
   nginx:
    Image:	nginx:1.21.1
    Port:	<none>
    Host Port:	<none>
    Requests:
      cpu:	500m
    Environment:	<none>
    Mounts:	<none>
  Volumes:	<none>

  执行命令开始回滚,不带--to-revision,则会回退到当前版本的上一个版本:

# kubectl rollout undo deployment.v1.apps/nginx-dev --to-revision=1
deployment.apps/nginx-dev rolled back

# kubectl rollout history deployment.v1.apps/nginx-dev
deployment.apps/nginx-dev 
REVISION  CHANGE-CAUSE
3         kubectl set image deployment/nginx-dev nginx=nginx:1.20.1 --record=true
4         <none>
5         kubectl set image deployment/nginx-dev nginx=nginx:1.20.1 --record=true

# kubectl get rs
NAME                   DESIRED   CURRENT   READY   AGE
nginx-dev-58c688cc59   3         3         3       126m
nginx-dev-6bff568f4d   0         0         0       155m
nginx-dev-bb9fbdd4b    0         0         0       31m

  小结:回滚后revision数字是递增的

3.5 水平伸缩

  通过Deployment 控制器去修改它控制的 ReplicaSet 的 Pod 副本数量就实现了水平伸缩。比如现在我们把 Pod 的副本调整到 4 个,那么 Deployment 所对应的 ReplicaSet 就会自动创建一个新的 Pod 出来,这样就水平扩展了,我们可以使用一个新的命令 kubectl scale 命令来完成这个操作

# kubectl scale deployment nginx-dev --replicas=4
deployment.apps/nginx-dev scaled
# kubectl get deplyment
error: the server doesn't have a resource type "deplyment"
# kubectl get deployment
NAME        READY   UP-TO-DATE   AVAILABLE   AGE
nginx-dev   4/4     4            4           63m

3.6 HPA

  kubectl scale 命令可以来实现 Pod 的扩缩容功能,但是这个毕竟是完全手动操作的,要应对线上的各种复杂情况,我们需要能够做到自动化去感知业务,来自动进行扩缩容。为此,Kubernetes 提供了这样的一个资源对象:Horizontal Pod Autoscaling(Pod 水平自动伸缩),简称HPA,HPA 通过监控分析一些控制器控制的所有 Pod 的负载变化情况来确定是否需要调整 Pod 的副本数量,这是 HPA 最基本的原理。

  可以通过 kubectl autoscale 命令来创建一个 HPA 资源对象,HPA Controller默认30s轮询一次(可通过 kube-controller-manager 的–horizontal-pod-autoscaler-sync-period 参数进行设置),查询指定的资源中的 Pod 资源使用率,并且与创建时设定的值和指标做对比,从而实现自动伸缩的功能。

3.6.1 Metrics Server

  Metrics Server是一个集群范围的资源使用情况的数据聚合器。作为一
个应用部署在集群中。Metric server从每个节点上Kubelet API收集指
标,通过Kubernetes聚合器注册在Master APIServer中。
  通过命令创建 metrics server.

# wget https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
# vim components.yaml
hostNetwork: true  # 使用hostNetwork模式
containers:
- name: metrics-server
  image: registry.aliyuncs.com/google_containers/metrics-server-amd64
 ......
 args:
- --cert-dir=/tmp
- --secure-port=4443
- --kubelet-preferred-address-types=InternalIP
  
# kubectl apply -f components.yaml
# kubectl top pod  nginx-dev-58c688cc59-b9xm9 
NAME                         CPU(cores)   MEMORY(bytes)   
nginx-dev-58c688cc59-b9xm9   0m           5Mi   

3.6.2 举栗:

需要注意的要想使得配置的HPA生效需要配置资源限制。
# vim hpa.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hpa-demo
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80
        resources:
          requests:
            memory: 50Mi
            cpu: 50m
          limits:
            memory: 500Mi
            cpu: 500m

# kubectl apply -f hpa.yaml
deployment.apps/hpa-demo created

# kubectl get pod -l app=nginx
NAME                        READY   STATUS    RESTARTS   AGE
hpa-demo-58b9b8ff79-fwprv   1/1     Running   0          8s

# kubectl autoscale deployment hpa-demo --cpu-percent=5 --min=1 --max=10  #创建HPA
horizontalpodautoscaler.autoscaling/hpa-demo autoscaled

# kubectl get hpa hpa-demo
NAME       REFERENCE             TARGETS        MINPODS   MAXPODS   REPLICAS   AGE
hpa-demo   Deployment/hpa-demo   <unknown>/5%   1         10        1          56s

使用wget命令增加cpu使用率
# while true;do wget -q -O- http://10.255.0.81/index.html;done

# kubectl top pod hpa-demo-7d49cd4d69-tw6bw
NAME                        CPU(cores)   MEMORY(bytes)   
hpa-demo-7d49cd4d69-tw6bw   45m          5Mi 

kubectl get pod -l app=nginx
NAME                        READY   STATUS    RESTARTS   AGE
hpa-demo-7d49cd4d69-2hfwv   1/1     Running   0          105s
hpa-demo-7d49cd4d69-6dr6g   1/1     Running   0          90s
hpa-demo-7d49cd4d69-9pvtl   1/1     Running   0          90s
hpa-demo-7d49cd4d69-dkxqf   1/1     Running   0          90s
hpa-demo-7d49cd4d69-fnzbn   1/1     Running   0          105s
hpa-demo-7d49cd4d69-hw45r   1/1     Running   0          74s
hpa-demo-7d49cd4d69-tw6bw   1/1     Running   0          8m37s
hpa-demo-7d49cd4d69-v4g7x   1/1     Running   0          90s
hpa-demo-7d49cd4d69-wpl75   1/1     Running   0          105s
hpa-demo-7d49cd4d69-zcq54   1/1     Running   0          74s

  autoscaling/v1 #只支持通过cpu为参考依据,来改变pod副本数,可使用命令创建

  autoscaling/v2beta1 #支持通过cpu、内存、连接数以及用户自定义的资源指标数据为参考依据。

  autoscaling/v2beta2 #同上,小的变动

apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
  name: hpa-demo
  namespace: default
spec:
  maxReplicas: 10
  minReplicas: 1
  scaleTargetRef:
      apiVersion: apps/v1
      kind: Deployment
      name: hpa-demo
  metrics:
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 10

四、StatefulSet 控制器

4.1 什么是有状态服务,什么是无状态服务?

  无状态服务(Stateless Service):该服务运行的实例不会在本地存储需要持久化的数据,并且多个实例对于同一个请求响应的结果是完全一致的,可以同时启动多个实例,但是我们访问任意一个实例得到的结果都是一样的。但是 MySQL 数据库就不是了,因为他需要把数据持久化到本地。

  有状态服务(Stateful Service):就和上面的概念是对立的了,该服务运行的实例需要在本地存储持久化数据,比如上面的 MySQL 数据库,你现在运行在节点 A,那么他的数据就存储在节点 A 上面的,如果这个时候你把该服务迁移到节点 B 去的话,那么就没有之前的数据了,因为他需要去对应的数据目录里面恢复数据,而此时没有任何数据。

  常见的 WEB 应用,是通过 Session 来保持用户的登录状态的,如果将 Session 持久化到节点上,那么该应用就是一个有状态的服务了,因为我现在登录进来你把我的 Session 持久化到节点 A 上了,下次我登录的时候可能会将请求路由到节点 B 上去了,但是节点 B 上根本就没有我当前的 Session 数据,就会被认为是未登录状态了,这样就导致我前后两次请求得到的结果不一致了。所以一般为了横向扩展,我们都会把这类 WEB 应用改成无状态的服务。将 Session 数据存入一个公共的地方,比如 Redis 里面,对于一些客户端请求 API 的情况,我们就不使用 Session 来保持用户状态,改成用 Token 也是可以的。

5.2 StatefulSet特点

  StatefulSet 为管理的每个 Pod 维护了一个有粘性的 ID。这些 Pod 是基于相同的规约来创建的, 但是不能相互替换:无论怎么调度,每个 Pod 都有一个永久不变的 ID。

  StatefulSets特点:

    稳定的、唯一的网络标识符。

    稳定的、持久的存储。

    有序的、优雅的部署和缩放。

    有序的、自动的滚动更新。

5.3 Headless Service(稳定的网络 ID)

  有时不需要或不想要负载均衡(service的cluster ip),以及单独的 Service IP。 遇到这种情况,可以通过指定 Cluster IP(spec.clusterIP)的值为 “None” 来创建 Headless Service。
使用无头 Service 与其他服务发现机制进行接口,而不必与 Kubernetes 的实现捆绑在一起。对这无头 Service 并不会分配 Cluster IP,kube-proxy 不会处理它们, 而且平台也不会为它们进行负载均衡和路由。 DNS 如何实现自动配置,依赖于 Service 是否定义了选择算符。

apiVersion: v1
kind: Service
metadata:
  name: nginx
  namespace: default
  labels:
    app: nginx
spec:
  ports:
  - name: http
    port: 80
  clusterIP: None  # Service 被创建后并不会被分配一个 cluster IP,而是会以 DNS 记录的方式暴露出它所代理的 Pod,而且还有一个非常重要的特性,对于 Headless Service 所代理的所有 Pod 的 IP 地址都会绑定一个如<pod-name>.<svc-name>.<namespace>.svc.cluster.local的DNS,这个 DNS 记录正是 Kubernetes 集群为 Pod 分配的一个唯一标识,只要我们知道 Pod 的名字,以及它对应的 Service 名字,就可以组装出这样一条 DNS 记录访问到 Pod 的 IP 地址
  selector:
    app: nginx

  PS:StatefulSet 中的每个 Pod 根据 StatefulSet 的名称和 Pod 的序号派生出它的主机名。 组合主机名的格式为$(StatefulSet 名称)-$(序号)。 上例将会创建三个名称分别为 web-0、web-1、web-2 的 Pod。 StatefulSet 可以使用 无头服务 控制它的 Pod 的网络域。管理域的这个服务的格式为: $(服务名称).$(命名空间).svc.cluster.local,其中 cluster.local 是集群域。 一旦每个 Pod 创建成功,就会得到一个匹配的 DNS 子域,格式为: $(pod 名称).$(所属服务的 DNS 域名),其中所属服务由 StatefulSet 的 serviceName 域来设定。

5.4 稳定的存储

  StatefulSet的存储卷使用VolumeClaimTemplate创建,称为卷申请模板,当StatefulSet使用
VolumeClaimTemplate创建一个PersistentVolume时,同样也会为每个Pod分配并创建一个编号的PVC。

# mkdir /tmp/pv{1,2}
# vim pv.yaml 

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv1
spec:
  capacity:
    storage: 1Gi
  accessModes:
  - ReadWriteOnce
  hostPath:
    path: /tmp/pv1

---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv2
spec:
  capacity:
    storage: 1Gi
  accessModes:
  - ReadWriteOnce
  hostPath:
    path: /tmp/pv2


# kubectl apply -f pv.yaml
persistentvolume/pv1 created
persistentvolume/pv2 created

# kubectl get pv
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
pv1    1Gi        RWO            Retain           Available                                   29s
pv2    1Gi        RWO            Retain           Available                                   29s

5.5 创建statefulset

apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  serviceName: "nginx"
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: www
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 1Gi

  上面资源清单中和 volumeMounts 进行关联的不是 volumes 而是一个新的属性:volumeClaimTemplates,该属性会自动创建一个 PVC 对象,其实这里就是一个 PVC 的模板,和 Pod 模板类似,PVC 被创建后会自动去关联当前系统中和他合适的 PV 进行绑定。除此之外,还多了一个 serviceName: “nginx” 的字段,serviceName 就是管理当前 StatefulSet 的服务名称,该服务必须在 StatefulSet 之前存在,并且负责该集合的网络标识,Pod 会遵循以下格式获取 DNS/主机名:pod-specific-string.serviceName.default.svc.cluster.local,其中 pod-specific-string 由 StatefulSet 控制器管理。

# kubectl apply -f statefulset.yaml
service/nginx created
statefulset.apps/web created

# kubectl get pods -w -l app=nginx
NAME    READY   STATUS              RESTARTS   AGE
web-0   0/1     ContainerCreating   0          3s
web-0   1/1     Running             0          12s
web-1   0/1     Pending             0          0s
web-1   0/1     Pending             0          0s
web-1   0/1     ContainerCreating   0          0s
web-1   1/1     Running             0          12s

  对于一个拥有 N 个副本的 StatefulSet,Pod 被部署时是按照 {0 …… N-1} 的序号顺序创建的。

# for i in 0 1; do kubectl exec "web-$i" -- sh -c 'hostname'; done
web-0
web-1

# kubectl run -i --tty --image busybox dns-test --restart=Never --rm

六、Daemonset

  DaemonSet用于在每个 Kubernetes 节点中将守护进程的副本作为后台进程运行,说白了就是在每个节点部署一个 Pod副本,当节点加入到 Kubernetes 集群中,Pod 会被调度到该节点上运行,当节点从集群只能够被移除后,该节点上的这个 Pod 也会被移除,当然,如果我们删除 DaemonSet,所有和这个对象相关的 Pods都会被删除。那么在哪种情况下我们会需要用到这种业务场景呢?其实这种场景还是比较普通的,比如:

    
节点监控守护进程,如 Prometheus 监控集群,可以在每个节点上运行一个 node-exporter 进程来收集监控节点的信息;

    日志收集守护程序,如 filebeat 或 logstash,在每个节点上运行以收集容器的日志

    节点网络插件,比如 flannel、calico,在每个节点上运行为 Pod 提供网络服务。
在每个节点上运行集群守护进程
在每个节点上运行日志收集守护进程

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd-elasticsearch
  namespace: kube-system
  labels:
    k8s-app: fluentd-log
spec:
  selector:
    matchLabels:
      name: fluentd-elasticsearch
  template:
    metadata:
      labels:
        name: fluentd-elasticsearch
    spec:
      tolerations:
      - key: node-role.kubernetes.io/master
        operator: Exists
        effect: NoSchedule
      containers:
      - name: fluentd-elasticsearch
        image: quay.azk8s.cn/fluentd_elasticsearch/fluentd:v2.5.2
        resources:
          limits:
            memory: 200Mi
          requests:
            cpu: 100m
            memory: 200Mi
        volumeMounts:
        - name: varlog
          mountPath: /var/log
        - name: varlibdockercontainers
          mountPath: /var/lib/docker/containers
          readOnly: true
      terminationGracePeriodSeconds: 30
      volumes:
      - name: varlog
        hostPath:
          path: /var/log
      - name: varlibdockercontainers
        hostPath:
          path: /var/lib/docker/containers

    DaemonSet 控制器是如何保证每个 Node 上有且只有一个被管理的 Pod 呢?首先,控制器从 Etcd 获取到所有的 Node 列表,然后遍历所有的 Node。
根据资源对象定义是否有调度相关的配置,然后分别检查 Node 是否符合要求。然后,在可运行 Pod 的节点上检查是否已有对应的 Pod,如果没有,则在这个 Node 上创建该 Pod;如果有,并且数量大于 1,那就把多余的 Pod 从这个节点上删除;如果有且只有一个 Pod,那就说明是正常情况。

七、Job

  Job 会创建一个或者多个 Pods,并将继续重试 Pods 的执行,直到指定数量的 Pods 成功终止。 随着 Pods 成功结束,Job 跟踪记录成功完成的 Pods 个数。 当数量达到指定的成功个数阈值时,任务(即 Job)结束。 删除 Job 的操作会清除所创建的全部 Pods。 挂起 Job 的操作会删除 Job 的所有活跃 Pod,直到 Job 被再次恢复执行。

  一种简单的使用场景下,你会创建一个 Job 对象以便以一种可靠的方式运行某 Pod 直到完成。 当第一个 Pod 失败或者被删除(比如因为节点硬件失效或者重启)时,Job 对象会启动一个新的 Pod。

  你也可以使用 Job 以并行的方式运行多个 Pod

apiVersion: batch/v1
kind: Job
metadata:
  name: job1
spec:
  template:
    spec:
      containers:
      - name: job1
        image: busybox
        command: ["/bin/sh",  "-c",  "for i in {1..10}; do echo $i; sleep 1; done"]
      restartPolicy: Never # Job 中 Pod 的 RestartPolicy 只能设置为 Never 或 OnFailure
  backoffLimit: 4 # 失败之前的重试次数。 失效回退的限制值默认为 6。 与 Job 相关的失效的 Pod 会被 Job 控制器重建,回退重试时间将会按指数增长 (从 10 秒、20 秒到 40 秒)最多至 6 分钟。 当 Job 的 Pod 被删除时,或者 Pod 成功时没有其它 Pod 处于失败状态,失效回退的次数也会被重置(为 0)

  完成的 Job 通常不需要留存在系统中Job 可以被 CronJob控制器 基于特定的根据容量裁定的清理策略清理掉。

  CronJob 创建基于时间间隔重复调度的 Jobs。一个 CronJob 对象就像 crontab (cron table) 文件中的一行。 它用 Cron 格式进行编写, 并周期性地在给定的调度时间执行 Job。

apiVersion: batch/v1
kind: CronJob
metadata:
  name: hello
spec:
  schedule: "*/1 * * * *" #必须填写字段,用来指定任务运行的周期,格式就和 crontab 一样
  jobTemplate: # 格式和Job一致
    spec:
      template:
        spec:
          containers:
          - name: hello
            image: busybox
            imagePullPolicy: IfNotPresent
            command:
            - /bin/sh
            - -c
            - date; echo Hello from the Kubernetes cluster
          restartPolicy: OnFailure

PS: 删除Cronjob将只会终止正在创建的 Job,但是运行中的 Job 将不会被终止,不会删除 Job 或 它们的 Pod。

 类似资料: