Fork me on GitHub

Controller与Service系列(一) Controller基本概念

一、简介

  控制器(Controller)是集群上管理和运行容器的对象。Pod就是通过Controller实现应用的运维,如伸缩、滚动升级等,其中Pod与Controller之间通过标签(Label)以及标签选择器(Selector)建立关联。

控制器(Controller)对象有不同的类型,比较常用的有:

  • Deployment   使用它可以进行应用的部署、应用的升级回滚、弹性伸缩等。
  • StatefulSet  管理有状态应用,用来管理某 Pod集合的部署和扩缩, 并为这些 Pod 提供持久存储和持久标识符。
  • DaemonSet  确保全部(或者某些)节点上运行一个 Pod 的副本。
  • Job  一次性任务
  • CronJob 创建基于时隔重复调度的 Jobs

二、Deployment   

(一)应用部署

Deployment常用的场景就是应用的部署、升级、回滚、伸缩等。

1、部署准备

 在之前的操作中直接通过命令行的方式进行应用的部署:

[root@k8smaster ~]# kubectl create development web --image=nginx

但是这样不利于重用,所以可以采用yaml文件的方式:

# 导出yaml文件
[root@k8smaster ~]# kubectl create deployment web --image=nginx --dry-run -o yaml > web.yam

可以看到yaml文件中的内容:

apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: web
  name: web
spec:
  replicas: 1
  selector:
    matchLabels:
      app: web
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: web
    spec:
      containers:
      - image: nginx
        name: nginx
        resources: {}
status: {}

可以看到Deployment控制器中的selector中与Pod中的labels进行匹配,它们之间就是基于此进行关联。

2、yaml部署

[root@k8smaster ~]# kubectl apply -f web.yaml 
deployment.apps/web created

目前该应用只能集群内部访问,需要暴露端口到外部,这样外部才能访问。

3、应用发布(对外暴露端口)

# 导出yaml文件
[root@k8smaster ~]# kubectl expose deployment web --port=80 --type=NodePort --target-port=80 --name=webOut -o yaml > webOut.yaml
apiVersion: v1
kind: Service
metadata:
  creationTimestamp: "2021-06-18T18:11:36Z"
  labels:
    app: web
  managedFields:
  - apiVersion: v1
    fieldsType: FieldsV1
    fieldsV1:
      f:metadata:
        f:labels:
          .: {}
          f:app: {}
      f:spec:
        f:externalTrafficPolicy: {}
        f:ports:
          .: {}
          k:{"port":80,"protocol":"TCP"}:
            .: {}
            f:port: {}
            f:protocol: {}
            f:targetPort: {}
        f:selector:
          .: {}
          f:app: {}
        f:sessionAffinity: {}
        f:type: {}
    manager: kubectl
    operation: Update
    time: "2021-06-18T18:11:36Z"
  name: web1
  namespace: default
  resourceVersion: "393318"
  selfLink: /api/v1/namespaces/default/services/web1
  uid: 9cbe6be0-d147-43a4-812f-32ae6722fdf3
spec:
  clusterIP: 10.97.65.66
  externalTrafficPolicy: Cluster
  ports:
  - nodePort: 31681
    port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: web
  sessionAffinity: None
  type: NodePort
status:
  loadBalancer: {}
web1.yaml

进行部署:

[root@k8smaster ~]# kubectl apply -f web1.yaml 

# 查看
[root@k8smaster ~]# kubectl get pods,svc
NAME                       READY   STATUS    RESTARTS   AGE
pod/web-5dcb957ccc-j2pg4   1/1     Running   0          15m

NAME                 TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGE
service/kubernetes   ClusterIP   10.96.0.1     <none>        443/TCP        61d
service/web1         NodePort    10.97.65.66   <none>        80:31681/TCP   3m51s

(二)应用升级、回滚

1、应用升级

# 升级
[root@k8smaster ~]# kubectl set image deployment web nginx=nginx:1.15
deployment.apps/web image updated

# 查看升级状态
[root@k8smaster ~]# kubectl rollout status deployment web
deployment "web" successfully rolled out

2、应用回滚

# 查看回滚版本
[root@k8smaster ~]# kubectl rollout history deployment web
deployment.apps/web 
REVISION  CHANGE-CAUSE
1         <none>
2         <none>

# 回滚到上一个版本
[root@k8smaster ~]# kubectl rollout undo deployment web
deployment.apps/web rolled back

# 回滚到指定版本
[root@k8smaster ~]# kubectl rollout undo deployment web --to-revision=2

(三)弹性伸缩

# 伸缩前查看
[root@k8smaster ~]# kubectl get pods,svc
NAME                       READY   STATUS    RESTARTS   AGE
pod/web-5dcb957ccc-66txn   1/1     Running   0          3m5s

NAME                 TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGE
service/kubernetes   ClusterIP   10.96.0.1     <none>        443/TCP        61d
service/web1         NodePort    10.97.65.66   <none>        80:31681/TCP   40m

# 进行伸缩
[root@k8smaster ~]# kubectl scale deployment web --replicas=3
deployment.apps/web scaled

# 伸缩后查看
[root@k8smaster ~]# kubectl get pods,svc
NAME                       READY   STATUS              RESTARTS   AGE
pod/web-5dcb957ccc-66txn   1/1     Running             0          3m41s
pod/web-5dcb957ccc-jx4kl   0/1     ContainerCreating   0          2s
pod/web-5dcb957ccc-zvmcm   0/1     ContainerCreating   0          2s

NAME                 TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGE
service/kubernetes   ClusterIP   10.96.0.1     <none>        443/TCP        61d
service/web1         NodePort    10.97.65.66   <none>        80:31681/TCP   41m

三、StatefulSet  

  StatefulSet 用来管理某 Pod 集合的部署和扩缩, 并为这些 Pod 提供持久存储和持久标识符。所以相对于Deployment而言它是有状态的,需要考虑下面的情况:

  • 保持每个Pod独立、启动顺序、唯一性
  • 唯一的网络标识、持久存储

创建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: nginx-statefulset
  namespace: default
spec:
  serviceName: nginx
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80

  它创建了一个 Headless Service nginx用来发布 StatefulSet web中的 Pod 的 IP 地址,表现形式就是clusterIP为None。执行上面的yaml文件:

[root@k8smaster ~]# kubectl apply -f statefulset.yaml 
service/nginx created

上面创建两个Pod的副本,但是它是按照{0,N-1}的顺序来创建Pod的,也就是Pod是有顺序的。

其次查看创建的两个Pod:

[root@k8smaster ~]# kubectl get pods
NAME                  READY   STATUS    RESTARTS   AGE
nginx-statefulset-0   1/1     Running   0          15m
nginx-statefulset-1   1/1     Running   0          14m

每个都是有唯一的名称,最后看一下网络标识,每个 Pod 都拥有一个基于其顺序索引的稳定的主机名。使用kubectl exec在每个 Pod 中执行hostname。

[root@k8smaster ~]# for i in 0 1; do kubectl exec "nginx-statefulset-$i" -- sh -c 'hostname'; done
nginx-statefulset-0
nginx-statefulset-1

四、DaemonSet  

DaemonSet 确保全部(或者某些)节点上运行一个 Pod 的副本。 当有节点加入集群时, 也会为他们新增一个 Pod 。 当有节点从集群移除时,这些 Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有 Pod

DaemonSet 的一些应用场景:

  • 在每个节点上运行集群守护进程
  • 在每个节点上运行日志收集守护进程
  • 在每个节点上运行监控守护进程

创建 一个日志收集工具的DaemonSet:

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: ds-test 
  labels:
    app: filebeat
spec:
  selector:
    matchLabels:
      app: filebeat
  template:
    metadata:
      labels:
        app: filebeat
    spec:
      containers:
      - name: logs
        image: nginx
        ports:
        - containerPort: 80
        volumeMounts:
        - name: varlog
          mountPath: /tmp/log
      volumes:
      - name: varlog
        hostPath:
          path: /var/log

执行该yaml文件:

[root@k8smaster ~]# kubectl apply -f ds.yaml 
daemonset.apps/ds-test created

可以看到在各个node节点上已经部署了Pod:

[root@k8smaster ~]# kubectl get pods -o wide
NAME            READY   STATUS    RESTARTS   AGE   IP            NODE       NOMINATED NODE   READINESS GATES
ds-test-6qdwg   1/1     Running   0          84s   10.244.1.23   k8snode1   <none>           <none>
ds-test-m79px   1/1     Running   0          84s   10.244.2.20   k8snode2   <none>           <none>

进入到某个Pod中进行查看:

[root@k8smaster ~]# kubectl exec -it ds-test-6qdwg bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl kubectl exec [POD] -- [COMMAND] instead.
root@ds-test-6qdwg:/# ls /tmp/log/
anaconda  btmp-20210617  dmesg        maillog           pods    secure-20210617     tuned
audit      containers     dmesg.old  maillog-20210617   ppp     spooler         vmware-vmsvc.log
boot.log  cron         firewalld  messages           rhsm    spooler-20210617  wtmp
btmp      cron-20210617  lastlog    messages-20210617  secure  tallylog         yum.log

五、Job  

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

下面是一个 Job 配置示例。它负责计算 π 到小数点后 2000 位,并将结果打印出来。

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

执行:

[root@k8smaster ~]# kubectl apply -f job.yaml 
job.batch/pi created

查看Pod状态:

# 因为是一次性任务,所以执行后即结束
[root@k8smaster ~]# kubectl get pods
NAME            READY   STATUS      RESTARTS   AGE
pi-vbmwk        0/1     Completed   0          4m26s

查看结果:

[root@k8smaster ~]# kubectl logs pi-vbmwk 
3.14159265358979323846264338327950...

六、CronJob 

CronJobs 对于创建周期性的、反复重复的任务很有用,例如执行数据备份或者发送邮件。 CronJobs 也可以用来计划在指定时间来执行的独立任务,例如计划当集群看起来很空闲时 执行某个 Job。如下实例:

apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: hello
spec:
  schedule: "*/1 * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: hello
            image: busybox
            args:
            - /bin/sh
            - -c
            - date; echo Hello from the Kubernetes cluster
          restartPolicy: OnFailure

执行:

[root@k8smaster ~]# kubectl apply -f cronjob.yaml 
cronjob.batch/hello created

可以看到周期性的调用:

[root@k8smaster ~]# kubectl get pods
NAME                     READY   STATUS              RESTARTS   AGE
hello-1624090140-w8xcn   0/1     Completed           0          2m57s
hello-1624090200-m2lng   0/1     ContainerCreating   0          2m21s
hello-1624090260-bwhjj   0/1     ContainerCreating   0          80s
hello-1624090320-bcd7b   0/1     ContainerCreating   0          20s

查看某个Pod里面的内容:

[root@k8smaster ~]# kubectl logs hello-1624090140-w8xcn
Sat Jun 19 08:11:44 UTC 2021
Hello from the Kubernetes cluster

 

posted @ 2021-06-19 11:33  iveBoy  阅读(1122)  评论(0编辑  收藏  举报
TOP