Kubernetes基础 ( 5 ) - 控制器

一、概述

我们在前面概念章节提到了控制器以及常用控制器的职责。所谓可控制器就是用来控制容器的状态和行为,不过控制器并不都是同级别的,比如Deployment管理ReplicaSetHPA可以对RSDeployment设置扩容方案,但终归目的是用来控制容器。

编号 控制器 说明 应用场景
1 Deployment 部署无状态应用 Web应用
2 StatefulSet 部署有状态应用 数据库
3 DaemonSet 在每一个Node上面运行一个Pod;新加入的Node也同样会自动运行一个Pod Agent
4 Job/CronJob 一次性任务/周期任务 脚本、备份
5 ReplicaSet
ReplicationController
控制Pod的副本数量
6 Horizontal Pod Autoscaling Pod水平自动缩放 弹性收缩

概念在前面章节已经提到,所以本章节主要从示例维度来对控制器进行说明。

二、ReplicaSet

2.1 RS / RC区别

ReplicaSet/ReplicationController 确保系统中的Pod数量永远等于设置的个数。

在新版的Kubernetes中建议使用ReplicaSet (RS)来取代ReplicationController(RC)ReplicaSetReplicationController没有本质的不同,只是名字不一样,但ReplicaSet支持集合式selector,k8s里通过对资源对象打标签,然后可以按不同的规则来筛选这些标签。具体的用法在前一篇Label / Selector中有说到,到具体的差异可以从描述文档上看到:

$ kubectl explain rc.spec
KIND:     ReplicationController
VERSION:  v1

FIELDS:
   selector	<map[string]string>


$ kubectl explain rs.spec
KIND:     ReplicaSet
VERSION:  apps/v1

FIELDS:
   selector	<Object> -required-

$ kubectl explain rs.spec.selector
KIND:     ReplicaSet
VERSION:  apps/v1

FIELDS:
   matchExpressions	<[]Object>
     matchExpressions is a list of label selector requirements. The requirements
     are ANDed.

   matchLabels	<map[string]string>
     matchLabels is a map of {key,value} pairs. A single {key,value} in the
     matchLabels map is equivalent to an element of matchExpressions, whose key
     field is "key", the operator is "In", and the values array contains only
     "value". The requirements are ANDed.

对比它俩的文档,可以看到结果略有差异,RC的的selector是一个map,而RSselector为一个object,必填,下面有两个key: matchExpressionsmatchLabels。而matchExpressions支持的筛选规则似乎更灵活些,就是上面说到的集合式selector

apiVersion: v1
kind: ReplicationController
metadata:
  name: myapp
spec:
  selector:
      app: myapp



apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: myapp
spec:
  selector:
    matchLabels:
      app: myapp
    matchExpressions;
      - {key: tier, operator: In, values: [frontend]}
      - {key: environment, operator: NotIn, values: [dev]}

2.2 ReplicaSet示例

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: rsname
spec:
  replicas: 1
  selector:
    matchLabels:
      name: rspod
  template:
    metadata:
      labels: 
        name: rspod
    spec:
      containers: 
      - name: nginx
        image: nginx:1.19.2-alpine
        resources:
          limits:
            memory: "128Mi"
            cpu: "500m"
        ports:
        - containerPort: 80


$ kubectl apply -f rs-nginx.yaml
replicaset.apps/rsname created

$ kubectl scale rs rsname --replicas=2

可以看到ReplicaSet的定义和Deployment定义是一样的,而且也支持扩容,然后来看看Deployment

三、Deployment

3.1 Deployment 与 RS

定义Deployment会创建PodReplicaSet,创建关系大致是Deployment创建ReplicaSetReplicaSet创建Pod。文档上对它俩的描述:

Deployment不直接管理Pod,而是通过ReplicaSet来进行管理,他们的功能差不多,都支持自动扩容、缩容,但Deployment支持滚动更新和回滚,这个是ReplicaSet不支持的,所以一般建议是通过Deployment来管理Pod

3.2 资源清单

参数名 字段类型 说明
spec.minReadySeconds Integer
spec.paused boolean
spec.progressDeadlineSeconds integer
spec.replicas integer 控制Pod的副本数量
spec.revisionHistoryLimit integer
spec.selector Object[required] Pod筛选
spec.selector.matchExpressions []Object
spec.selector.matchExpressions[].key string[required]
spec.selector.matchExpressions[].operator string[required] 可选值有:In, NotIn, Exists and DoesNotExist
spec.selector.matchExpressions.values []string
spec.selector.matchLabels map[string]string
spec.strategy Object
spec.strategy.rollingUpdate Object
spec.strategy.rollingUpdate.maxSurge string
spec.strategy.rollingUpdate.maxUnavailable string
spec.strategy.type string
spec.template Object[required] Pod模板
spec.template.metadata Object
spec.template.spec Object

3.3 Deployment示例

我们先来创建NginxDeployment,可能是本地的网络原因,需要创建service且指定typeLoadBalancer本机端口才能访问到,先忽略,后续在探究这个问题。多个资源清单可以写在一个文件,通过---进行分割即可。

apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
  labels:
    project: nginx
spec:
  selector:
    app: nginx-pod
  type: LoadBalancer
  ports:
  - port: 38000
    targetPort: 80
    protocol: TCP

---

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deploy
  labels:
    project: nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx-pod
  template:
    metadata:
      labels:
        app: nginx-pod
    spec:
      containers:
      - name: nginx
        image: nginx:1.19.2-alpine
        imagePullPolicy: IfNotPresent
        resources:
          limits:
            memory: "128Mi"
            cpu: "500m"
        ports:
        - containerPort: 80

通过apply创建,并且在最后增加了--record,用来记录历史版本号,可以回滚时指定某个版本。

–record=false: Record current kubectl command in the resource annotation. If set to false, do not record the command. If set to true, record the command. If not set, default to updating the existing annotation value only if one already exists.

$ kubectl apply -f nginx.yaml --record
service/nginx-svc created
deployment.apps/nginx-deploy created

这个配置前面也配过好几次了,接下来本机就可以访问http://localhost:38000/看到Nginx的欢迎页。命令行也可以看到deploymentrspod信息。

$ kubectl get deploy
NAME           READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deploy   2/2     2            2           25s

$ kubectl get rs
NAME                     DESIRED   CURRENT   READY   AGE
nginx-deploy-9bdb559b9   2         2         2       27s

$ kubectl get pod
NAME                           READY   STATUS    RESTARTS   AGE
nginx-deploy-9bdb559b9-hlrjq   1/1     Running   0          28s
nginx-deploy-9bdb559b9-rw2gh   1/1     Running   0          28s

3.4 滚动更新

既然DeploymentRS的主要差别在于滚动更新,我们来看看滚动更新操作。

3.3.1 版本更新

尝试更新nginx镜像到1.18.0-alpine版本。更新方式通资源清单中所讲,可以通过更新yaml文件,或者通过set image命令操作就会触发rollout。

$ kubectl set image deployment nginx-deploy nginx=nginx:1.18.0-alpine

再次查看资源信息,可以看到增加了一个rsDESIREDCURRENTREADY对应为1、1、0,也新增了一个pod,状态是ImagePullBackOff。但这里为啥是期望的DESIRED数量1呢?,猜测这是一个中间状态,跟滚动更新流程有关系,rs先启动一个,启动成功后再扩容一个,但由于第一个现在卡主了,所以看到了这个状态。

$ kubectl get deploy
NAME           READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deploy   2/2     1            2           3m8s

$ kubectl get rs
NAME                      DESIRED   CURRENT   READY   AGE
nginx-deploy-6d57fb5cfd   1         1         0       2m9s
nginx-deploy-9bdb559b9    2         2         2       3m11s


$ kubectl get pod
NAME                            READY   STATUS             RESTARTS   AGE
nginx-deploy-6d57fb5cfd-ktw6w   0/1     ImagePullBackOff   0          2m14s
nginx-deploy-9bdb559b9-hlrjq    1/1     Running            0          3m16s
nginx-deploy-9bdb559b9-rw2gh    1/1     Running            0          3m16s

查看Pod信息,可以到镜像获取失败。

$ kubectl describe pod nginx-deploy-6d57fb5cfd-ktw6w

Events:
  Type     Reason     Age                  From                     Message
  ----     ------     ----                 ----                     -------
  Normal   Scheduled  <unknown>            default-scheduler        Successfully assigned default/nginx-deploy-6d57fb5cfd-ktw6w to docker-desktop
  Warning  Failed     2m58s                kubelet, docker-desktop  Failed to pull image "nginx:1.18.0-alpine": rpc error: code = Unknown desc = Get https://registry-1.docker.io/v2/library/nginx/manifests/1.18.0-alpine: net/http: TLS handshake timeout
  Warning  Failed     2m12s                kubelet, docker-desktop  Failed to pull image "nginx:1.18.0-alpine": rpc error: code = Unknown desc = Get https://registry-1.docker.io/v2/: net/http: TLS handshake timeout
  Warning  Failed     63s                  kubelet, docker-desktop  Failed to pull image "nginx:1.18.0-alpine": rpc error: code = Unknown desc = Get https://registry-1.docker.io/v2/library/nginx/manifests/sha256:8853c7e938c2aa5d9d7439e698f0e700f058df8414a83134a09fcbb68bb0707a: net/http: TLS handshake timeout
  Warning  Failed     63s (x3 over 2m58s)  kubelet, docker-desktop  Error: ErrImagePull
  Normal   BackOff    33s (x4 over 2m58s)  kubelet, docker-desktop  Back-off pulling image "nginx:1.18.0-alpine"
  Warning  Failed     33s (x4 over 2m58s)  kubelet, docker-desktop  Error: ImagePullBackOff
  Normal   Pulling    22s (x4 over 3m37s)  kubelet, docker-desktop  Pulling image "nginx:1.18.0-alpine"

查看版本记录,需要前面开启--record,可以通过.spec.revisionHistoryLimit指定deployment最多保留多少revision记录。貌似这个版本记录并不太清晰,不同版本之间看不出区别。

$ kubectl rollout history deployment nginx-deploy
deployment.apps/nginx-deploy
REVISION  CHANGE-CAUSE
1         kubectl apply --filename=nginx.yaml --record=true
2         kubectl apply --filename=nginx.yaml --record=true

3.3.2 版本回滚

看起来这一次更新镜像异常,正好可以操作下回滚:

$ kubectl rollout undo deployment nginx-deploy
deployment.apps/nginx-deploy rolled back

也可以指定某个历史版本

$ kubectl rollout undo deployment nginx-deploy --to-revision=1

再来查看资源信息,状态已经恢复,Deployment增加了另一个rs用来做滚动升级。

$ kubectl get deploy
NAME           READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deploy   2/2     2            2           7m19s
pengbotao:k8s peng$ kubectl get rs
NAME                      DESIRED   CURRENT   READY   AGE
nginx-deploy-6d57fb5cfd   0         0         0       6m19s
nginx-deploy-9bdb559b9    2         2         2       7m21s
pengbotao:k8s peng$ kubectl get pod
NAME                           READY   STATUS    RESTARTS   AGE
nginx-deploy-9bdb559b9-hlrjq   1/1     Running   0          7m26s
nginx-deploy-9bdb559b9-rw2gh   1/1     Running   0          7m26s

3.3.3 版本更新

我们尝试手动下载镜像,然后再次升级看看。刷rs可以看到中间数量的变更。

$ kubectl get rs
NAME                      DESIRED   CURRENT   READY   AGE
nginx-deploy-6d57fb5cfd   2         2         1       8h
nginx-deploy-9bdb559b9    1         1         1       8h

$ kubectl get rs
NAME                      DESIRED   CURRENT   READY   AGE
nginx-deploy-6d57fb5cfd   2         2         2       8h
nginx-deploy-9bdb559b9    0         0         0       8h

通过describe可以看到现在的版本以及日志信息

  $ kubectl describe deploy nginx-deploy
  ...
  Pod Template:
  Labels:  app=nginx-pod
  Containers:
   nginx:
    Image:      nginx:1.18.0-alpine

  ...
  
  Events:
  Type    Reason             Age                  From                   Message
  ----    ------             ----                 ----                   -------
  Normal  ScalingReplicaSet  63s (x3 over 8h)     deployment-controller  Scaled up replica set nginx-deploy-6d57fb5cfd to 1
  Normal  ScalingReplicaSet  62s (x2 over 4m23s)  deployment-controller  Scaled down replica set nginx-deploy-9bdb559b9 to 1
  Normal  ScalingReplicaSet  61s (x2 over 4m23s)  deployment-controller  Scaled up replica set nginx-deploy-6d57fb5cfd to 2
  Normal  ScalingReplicaSet  59s (x2 over 4m21s)  deployment-controller  Scaled down replica set nginx-deploy-9bdb559b9 to 0

通过Events中ScalingReplicaSet看到流程是:

3.3.4 kubectl操作

# 暂停
$ kubectl rollout pause deployment nginx-deploy

# 查看状态
$ kubectl rollout status deployment nginx-deploy
deployment "nginx-deploy" successfully rolled out

# 恢复
$ kubectl rollout resume deployment nginx-deploy

# 扩容
$ kubectl scale deployment nginx-deploy --replicas 3

# 删除
$ kubectl delete service,deploy -l project=nginx

四、DaemonSet

4.1 关于DaemonSet

DaemonSet控制有下面特征:

所以使用场景上一般为日志收集、监控等。查看系系统中已有的DaemonSet可以看到,kube-proxy就是通过DS在配置。

$ kubectl get ds -n kube-system
NAME         DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR                 AGE
kube-proxy   1         1         1       1            1           beta.kubernetes.io/os=linux   6d22h

4.2 资源清单

参数名 字段类型 说明
spec.minReadySeconds Integer
spec.revisionHistoryLimit integer
spec.selector Object[required] Pod筛选
spec.template Object[required] Pod模板
spec.updateStrategy Object
spec.updateStrategy.rollingUpdate Object
spec.updateStrategy.rollingUpdate.maxUnavailable string
spec.updateStrategy.type string 更新方式,可选值:RollingUpdate、OnDelete,默认RollingUpdate.

4.3 DaemonSet示例

@todo

五、Job

5.1 关于Job

负责处理一次性任务。

5.2 资源清单

参数名 字段类型 说明
spec.activeDeadlineSeconds integer
spec.backoffLimit integer
spec.completions integer
spec.manualSelector boolean
spec.parallelism integer
spec.selector Object
spec.template Object
spec.ttlSecondsAfterFinished integer

5.3 Job示例

apiVersion: batch/v1
kind: Job
metadata:
  name: job-demo
spec:
  template:
    spec:
      restartPolicy: OnFailure
      containers:
      - name: box
        image: busybox
        command:
        - "/bin/sh"
        - "-c"
        - "date"

创建后查看

$ kubectl apply -f job.yaml
job.batch/job-demo created

$ kubectl get job
NAME       COMPLETIONS   DURATION   AGE
job-demo   1/1           3s         11s

$ kubectl get pod
NAME                           READY   STATUS      RESTARTS   AGE
job-demo-8rl4c                 0/1     Completed   0          20s

$ kubectl logs job-demo-8rl4c
Thu Sep  3 07:19:11 UTC 2020

六、 CronJob

6.1 关于CronJob

CronJob就是在Job的基础上变成周期性的任务,可以周期性执行。周期设置的schedulecrontab一样。在后续可以看到,执行CronJob会产生Job

6.2 资源清单

参数名 字段类型 说明
spec.concurrencyPolicy string
spec.failedJobsHistoryLimit integer 保留是失败的Job记录,默认为1
spec.jobTemplate Object Job模板,格式同Job
spec.schedule string[required] Job运行周期,格式同Crontab
spec.startingDeadlineSeconds integer
spec.successfulJobsHistoryLimit integer 保留完成的Job记录,默认为3
spec.suspend boolean

6.3 CronJob示例

apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: cronjob-demo
spec:
  schedule: "*/1 * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          restartPolicy: OnFailure
          containers:
          - name: box
            image: busybox
            command:
            - "/bin/sh"
            - "-c"
            - "date"

创建后查看

$ kubectl apply -f cronjob.yaml
cronjob.batch/cronjob-demo created

$ kubectl get cronjob
NAME           SCHEDULE      SUSPEND   ACTIVE   LAST SCHEDULE   AGE
cronjob-demo   */1 * * * *   False     0        <none>          16s

$ kubectl get job
NAME                      COMPLETIONS   DURATION   AGE
cronjob-demo-1599117660   1/1           3s         76s
cronjob-demo-1599117720   1/1           4s         16s
job-demo                  1/1           3s         3m7s

$ kubectl get pod
NAME                            READY   STATUS      RESTARTS   AGE
cronjob-demo-1599117660-hf6cs   0/1     Completed   0          95s
cronjob-demo-1599117720-pwrbj   0/1     Completed   0          35s
job-demo-8rl4c                  0/1     Completed   0          3m26s

$ kubectl logs cronjob-demo-1599117660-hf6cs
Thu Sep  3 07:21:02 UTC 2020


$ kubectl describe cronjob cronjob-demo
...
Events:
  Type    Reason            Age    From                Message
  ----    ------            ----   ----                -------
  Normal  SuccessfulCreate  7m34s  cronjob-controller  Created job cronjob-demo-1599117660
  Normal  SawCompletedJob   7m24s  cronjob-controller  Saw completed job: cronjob-demo-1599117660, status: Complete
  Normal  SuccessfulCreate  6m34s  cronjob-controller  Created job cronjob-demo-1599117720
  Normal  SawCompletedJob   6m24s  cronjob-controller  Saw completed job: cronjob-demo-1599117720, status: Complete
  Normal  SuccessfulCreate  5m34s  cronjob-controller  Created job cronjob-demo-1599117780
  Normal  SawCompletedJob   5m24s  cronjob-controller  Saw completed job: cronjob-demo-1599117780, status: Complete
  Normal  SuccessfulCreate  4m34s  cronjob-controller  Created job cronjob-demo-1599117840
  Normal  SawCompletedJob   4m24s  cronjob-controller  Saw completed job: cronjob-demo-1599117840, status: Complete
  Normal  SuccessfulDelete  4m24s  cronjob-controller  Deleted job cronjob-demo-1599117660
  Normal  SuccessfulCreate  3m34s  cronjob-controller  Created job cronjob-demo-1599117900
  Normal  SuccessfulDelete  3m24s  cronjob-controller  Deleted job cronjob-demo-1599117720
  Normal  SawCompletedJob   3m24s  cronjob-controller  Saw completed job: cronjob-demo-1599117900, status: Complete
  Normal  SuccessfulCreate  2m34s  cronjob-controller  Created job cronjob-demo-1599117960
  Normal  SawCompletedJob   2m24s  cronjob-controller  Saw completed job: cronjob-demo-1599117960, status: Complete
  Normal  SuccessfulDelete  2m24s  cronjob-controller  Deleted job cronjob-demo-1599117780

七、StatefulSet

7.1 关于StatefulSet

StatefulSet主要解决的是有状态服务的部署问题,前面使用Deployment+Service创建的是无状态的Pod。就好比Nginx的,通过反向代理后面可以挂多个节点,每个节点都是平等的,更换机器只需要调整反向代理的服务即可。但有些服务不行,比如Redis,他涉及到数据的存储,数据之间是有状态的,如果切换机器需要将对应的数据存储同步迁移关联上才行,所以一般有状态的服务会配合PVC使用。

StatefulSet应用特点:

所以StatefulSet的核心功能在于解决稳定的网络表示和持久的存储、服务启停顺序也是确定的,通常包含以下几部分:

7.2 资源清单

参数名 字段类型 说明
spec.podManagementPolicy string
spec.replicas integer
spec.revisionHistoryLimit integer
spec.selector Object[required] Pod筛选
spec.serviceName string[required] Service 名称
spec.template Object[required] Pod模板
spec.updateStrategy Object
spec.updateStrategy.rollingUpdate Object
spec.updateStrategy.rollingUpdate.partition integer
spec.updateStrategy.type string 默认值RollingUpdate.
spec.volumeClaimTemplates []Object

7.3 StatefulSet示例

1. 创建Headless Service

只是将Service中的clusterIP指定为None,不会分配VIP

apiVersion: v1
kind: Service
metadata:
  name: ss-nginx-svc
spec:
  ports:
  - port: 38002
    targetPort: 80
  clusterIP: None
  selector:
    app: ss-nginx-pod

2. 创建pv

这里是存储在本机,也可以通过nfs挂载,用来持久化存储数据。

apiVersion: v1
kind: PersistentVolume
metadata:
  name: nginx-pv001
spec:
  capacity:
    storage: 2Gi
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: pv-nginx
  hostPath:
    path: /Users/peng/k8s/pv-data/pv001
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nginx-pv002
spec:
  capacity:
    storage: 2Gi
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: pv-nginx
  hostPath:
    path: /Users/peng/k8s/pv-data/pv002
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nginx-pv003
spec:
  capacity:
    storage: 2Gi
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: pv-nginx
  hostPath:
    path: /Users/peng/k8s/pv-data/pv003

3. 创建StatefulSet应用

这里为尽量简单,先以Nginx做测试。其中serviceName关联Headless Service。其他的配置同Deployment一样。

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: ss-nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: ss-nginx-pod
  serviceName: ss-nginx-svc
  template:
    metadata:
      labels:
        app: ss-nginx-pod
    spec:
      containers:
      - name: nginx
        image: nginx:1.19.2-alpine
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
        volumeMounts:
        - name: pvc-nginx
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: pvc-nginx
    spec:
      accessModes: ["ReadWriteOnce"]
      storageClassName: pv-nginx
      resources:
        requests:
          storage: 1Gi

查看statefulsetpvpvcpodsvc的状态

$ kubectl get statefulset -o wide
NAME       READY   AGE    CONTAINERS   IMAGES
ss-nginx   3/3     2m4s   nginx        nginx:1.19.2-alpine

$ kubectl get pv
NAME          CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM                          STORAGECLASS   REASON   AGE
nginx-pv001   2Gi        RWO            Recycle          Bound       default/pvc-nginx-ss-nginx-0   pv-nginx                2m28s
nginx-pv002   2Gi        RWO            Recycle          Bound       default/pvc-nginx-ss-nginx-1   pv-nginx                2m28s
nginx-pv003   2Gi        RWO            Recycle          Bound       default/pvc-nginx-ss-nginx-2   pv-nginx                2m28s

$ kubectl get pvc
NAME                   STATUS   VOLUME        CAPACITY   ACCESS MODES   STORAGECLASS   AGE
pvc-nginx-ss-nginx-0   Bound    nginx-pv001   2Gi        RWO            pv-nginx       6m18s
pvc-nginx-ss-nginx-1   Bound    nginx-pv002   2Gi        RWO            pv-nginx       2m24s
pvc-nginx-ss-nginx-2   Bound    nginx-pv003   2Gi        RWO            pv-nginx       2m21s

$ kubectl get pod -o wide
ss-nginx-0                      1/1     Running   0          6m59s   10.1.2.100   docker-desktop   <none>           <none>
ss-nginx-1                      1/1     Running   0          6m56s   10.1.2.101   docker-desktop   <none>           <none>
ss-nginx-2                      1/1     Running   0          6m53s   10.1.2.102   docker-desktop   <none>           <none>

$ kubectl get svc
ss-nginx-svc   ClusterIP      None            <none>        38002/TCP         8m41s

$ kubectl describe svc ss-nginx-svc
Name:              ss-nginx-svc
Namespace:         default
Labels:            <none>
Annotations:       kubectl.kubernetes.io/last-applied-configuration:
                     {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"ss-nginx-svc","namespace":"default"},"spec":{"clusterIP":"None","...
Selector:          app=ss-nginx-pod
Type:              ClusterIP
IP:                None
Port:              <unset>  38002/TCP
TargetPort:        80/TCP
Endpoints:         10.1.2.100:80,10.1.2.101:80,10.1.2.102:80
Session Affinity:  None
Events:            <none>

3个Pod都创建成功了,每个Pod都可以通过以下域名进行访问,通信方式都是通过此域名来访问而非IP

<PodName>.<ServiceName>.<NamespaceName>.svc.cluster.local

Pod故障后可能飘逸到其他节点上,PodIP可能会变,但StatefulSet会确保PodName以及这个域名不变。进入容器之后可以访问及查看。

# more /etc/hosts
# Kubernetes-managed hosts file.
127.0.0.1       localhost
::1     localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
fe00::0 ip6-mcastprefix
fe00::1 ip6-allnodes
fe00::2 ip6-allrouters
10.1.2.103      ss-nginx-0.ss-nginx-svc.default.svc.cluster.local       ss-nginx-0

/ # curl ss-nginx-0.ss-nginx-svc.default.svc.cluster.local
pv001
/ # curl ss-nginx-1.ss-nginx-svc.default.svc.cluster.local
pv002
/ # curl ss-nginx-2.ss-nginx-svc.default.svc.cluster.local
pv003

/ # curl ss-nginx-svc.default.svc.cluster.local
pv002
/ # curl ss-nginx-svc.default.svc.cluster.local
pv002
/ # curl ss-nginx-svc.default.svc.cluster.local
pv003
/ # curl ss-nginx-svc.default.svc.cluster.local
pv001

当我们删掉ss-nginx-0后,pod会重建,此时名称会和之前一样,pvc会关联同一个。实现原Pod相同的功能,达到有状态服务重启后保持相同状态的目的。

$ kubectl get pod
ss-nginx-0                      1/1     Running   0          3s
ss-nginx-1                      1/1     Running   0          24m
ss-nginx-2                      1/1     Running   0          24m

八、Horizontal Pod Autoscaling

8.1 关于HPA

应用在日常运行过程中会有高峰也会有低谷的情况,如何做到削峰填谷,提高集群资源的可利用率?HPA就是为了解决此问题。类似阿里云的弹性收缩功能。

8.2 资源清单

参数名 字段类型 说明
spec.maxReplicas integer[required] 最大副本数量,不能小于最小副本数量
spec.minReplicas integer 最小副本数量,默认值为1.
spec.targetCPUUtilizationPercentage integer 平均CPU使用率,百分比
spec.scaleTargetRef Object[required] 关联的资源对象
spec.scaleTargetRef.apiVersion string 关联资源的api版本
spec.scaleTargetRef.kind string[required] 关联资源的类型
spec.scaleTargetRef.name string[required] 关联资源的名称

8.3 HPA示例

对前一节的StatefulSet应用增加一个HPA控制

apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
  name: hpa-demo
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: StatefulSet
    name: ss-nginx
  minReplicas: 3
  maxReplicas: 10
  targetCPUUtilizationPercentage: 80

设定副本数量最小3个,最大10个,定义CPU指标达到80%触发。

$ kubectl apply -f hpa.yaml
horizontalpodautoscaler.autoscaling/hpa-demo created
$ kubectl get hpa
NAME           REFERENCE                 TARGETS         MINPODS   MAXPODS   REPLICAS   AGE
hpa-demo       StatefulSet/ss-nginx      <unknown>/80%   3         10        0          4s

当前从文档上看到只定义了CPU字段,但很显然后续还有会内存、请求数等等指标。创建起来不复杂,但需要配合监控收集数据。这个留待后面在做整体测试。

九、小结

本章对Pod以及常用的控制器做一些演示及资源清单配置方式进行说明,初步了解各个控制器的作用,能进行日常配置。


-- EOF --
发表于: 2020-10-01 06:24
标签: Kubernetes 容器化