Kubernetes Pod 控制器

在机器人技术和自动化中,控制环是一个控制系统状态的不终止的循环

这是一个控制环的例子:"房间里的温度自动调节器"
当你设置了温度,告诉了温度自动调节器你的"期望状态",房间的实际温度是"当前状态"。通过对设备的开关控制,温度自动调节器让其当前状态无限接近于期望状态。
控制器通过 k8s的apiserver 去监控集群的公共状态,并致力于将当前状态转变为所期望的状态。

kubernetes 之Pod控制器(Controller)

Controller是kubernetes中用于对Pod进行管理的控制器,通过该控制器可以让Pod始终维持在一个用户原本设定或期望的状态下。如节点宕机或Pod因其他原因死亡,则在其他节点起一个相同的Pod来替代该Pod。

  • 常用的内置控制器类型,它通常与集群API服务器进行交互:
    ReplicaSet:是Replication Controller 升级版本,区别是对选择器的支持;
    Deployments:管理RS并提供对Pod的更新等功能,建议使用它管理RS,除非自定义更新编排;
    DaemonSet:用于确保集群中的每一个节点只运行一个Pod副本,通常用来实现系统级的后台任务;
    StatefulSets:通常用来管理有状态应用;
    Job:一次性任务执行;
    Crontab:定时任务执行;
    任意控制器学习方法可参考中文官方站点:Kubernetes 内置控制器
  • 举个例子:
    运行Pod之前,尽量把镜像给先下载到本地,依据Pod调度结果使用docker save load导入导出
[ controllers]# cat replicaset-demo.yaml 
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: myapp
  namespace: default
spec:
  replicas: 1
  selector: 
    matchLabels:
      app: myapp
      release: canary
  template:
    metadata:
      name: myapp-httpd
      labels:
        app: myapp
        release: canary
        environment: qa
    spec:
      containers:
      - name: myapp-container
        image: httpd
                imagePullPolicy: IfNotPresent
        ports:
        - name: http
          containerPort: 80
[ controllers]#

Kubernetes 最小运行单元 Pod,了解Pod是什么你需要了解容器

容器本质实际上是一个进程,是一个视图被隔离,资源受限的进程。
容器的设计本身是"单进程"模型,不是容器里只能起一个进程,因为容器的应用等于进程,只能管理PID=1的进程。(Linux 容器的"单进程"模型,指的是容器的生命周期等同于 PID=1 的进程的生命周期,而不是说容器里不能创建多进程),也可以启动多个进程,但是只有PID=1的进程被容器所管理,这时其它进程则处于tuoguan状态。如果这个时候PID=1的这个进程出问题了被kill掉了或者是fail了没人知道,然后其它的进程资源怎么办呢?就没人管,没人回收......
所以往往在容器当中运行一个复杂程序是比较苦难的,但kubernetes的控制器的脱引而出,为它奠定了其在容器当中运行多个应用的历史地位,至少现阶段是的。

Pod 是什么

让Kubernetes集群能跑起来的基础组件就叫 Pod。

  • Pod 是 Kubernetes 应用程序的基本执行单元,即它是 Kubernetes 对象模型中创建或部署的最小和最简单的单元。Pod 表示在 集群 上运行的一个进程。
  • Pod 可以是封装了单个应用程序的容器(或多个)、存储资源、唯一网络 IP 以及控制容器应该如何运行的选项。 Pod 表示部署单元:"Kubernetes 中应用程序的单个实例",它可能由单个 容器 或少量紧密耦合并共享资源的容器组成。
  • Docker 是 Kubernetes Pod 中最常用的容器运行时,但 Pod 也能支持其他的容器运行。

Pod = "进程组"

在 Kubernetes 里面,Pod 实际上正是 Kubernetes 项目为你抽象出来的一个可以类比为进程组的概念。
简单点就是在kubernets当中会把多个应用定义为多个容器,然后把多个容器运行在一个Pod资源里面,你也可以说是多个容器的组合就叫做 Pod。当Kubernetes把定义在一个Pod组合里的容器运行起来后,你会看到多个容器在运行。它们会同时去共享系统底层的某些资源(共享同一个底层的net、uts、ipc、等...),而这些资源都属于 Pod。
Pod 在 Kubernetes 里面只有一个逻辑单位,Pod 是 Kubernetes 分配资源的一个单位。因为里面的容器要共享某些资源,所以Pod 它也是 Kubernetes 的原子调度单位。

Pod 的工作特点

  • 自主式Pod,自主式管理;
  • 将多个容器连接起来,给容器做成抽象封装;
  • 一个Pod包含多个容器,共享同一个底层的 UTS、IPC、Network、等......;
  • Pod模拟传统虚拟机,一个Pod建议只运行一个容器;
  • 共享存储卷,不再属于容器而属于Pod;
  • Pod在各node上运行,取决其节点容忍度;
  • Pod控制器:Replication Controller、ReplicaSet、DeployMent、StatefulSet、DaemonSet、Job;

Kubernetes 中Pod 的运行方式

  • 运行单个容器的 Pod
    "每个 Pod 一个容器"的模型是最常见的 Kubernetes 用例,即one-container-per-Pod模式。在这种情况下可以将 Pod 看作单个容器的包装器,并且 Kubernetes 直接管理 Pod,而不是容器。
  • 运行多个协同工作的容器的 Pod
    Pod 可能封装由多个紧密耦合且需要共享资源的共处容器组成的应用程序。即sidecar模式,Pod 封装了一组紧耦合、共享资源、协同寻址的容器,将这组容器作为一个管理单元作为一个可管理的实体。
    举个例子:
    自包含式容器设计Sidecar示例,镜像可私有仓库创建打包并上传至github
[ controllers]# cat pod-tomcat-demo.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: web-2
  namespace: default
spec:
  initContainers:
  - image: ik8s.io/sample:v2
    imagePullPolicy: IfNotPresent
    name: war
    command: [ "cp", "/sample.war", "/app" ]
    volumeMounts:
    - mountPath: /app
      name: app-volume
  containers:
  - image: ik8s.io/tomcat:8.0
    imagePullPolicy: IfNotPresent
    name: tomcat8
    command: [ "sh", "-c", "/root/apache-tomcat-8.0.5/bin/start.sh" ]
    volumeMounts:
    - mountPath: /root/apache-tomcat-8.0.5/webapps
      name: app-volume
    ports:
    - containerPort: 8080
      hostPort: 8008
  volumes:
  - name: app-volume
    emptyDir: {}
[ controllers]#

利用DeployMents控制器实现滚动更新及灰度应用发布

  • 任意应用程序创建必须满足三个核心组件:
    用户期望的Pod副本、标签选择器、Pod模版(现有Pods数量不够副本中所定义的期望Pod)
    命令帮助:
[ controllers]# kubectl explain deploy
[ controllers]# kubectl explain deploy.spec
[ controllers]# kubectl explain deploy.spec.strategy

此示例中会告诉您怎么实现一组应用的滚动更新,版本回退,Pod数量更新等。

[ controllers]# cat deployment-myapp-demo.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deployment
  namespace: default
spec:
  replicas: 2
  selector: 
    matchLabels:
      app: myapp
      release: canary
  template:
    metadata:
      labels:
        app: myapp
        release: canary
    spec:
      containers:
      - name: myapp
        image: nginx
        imagePullPolicy: IfNotPresent
        ports:
        - name: http
          containerPort: 80
[ controllers]#
[ controllers]# kubectl apply -f deployment-myapp-demo.yaml 
deployment.apps/myapp-deployment created
[ controllers]# 
[ controllers]# kubectl delete -f deployment-myapp-demo.yaml 
deployment.apps "myapp-deployment" deleted
[ controllers]# 
[ controllers]# kubectl get pods
NAME                                READY   STATUS    RESTARTS   AGE
myapp-deployment-5b776d9cf7-29s7b   1/1     Running   0          9m26s
myapp-deployment-5b776d9cf7-8hb8c   1/1     Running   0          9m26s
[ controllers]# 
[ controllers]# kubectl logs myapp-deployment-5b776d9cf7-8hb8c
[ controllers]# 
[ controllers]# kubectl describe pods myapp-deployment-5b776d9cf7-8hb8c
.............
Events:
Type    Reason     Age        From               Message
    ----    ------     ----       ----               -------
    Normal  Scheduled  <unknown>  default-scheduler  Successfully assigned default/myapp-deployment-5b776d9cf7-8hb8c to node2
    Normal  Pulled     10h        kubelet, node2     Container image "nginx" already present on machine
    Normal  Created    10h        kubelet, node2     Created container myapp
    Normal  Started    10h        kubelet, node2     Started container myapp
[ controllers]#
  • 更新Pod数量,滚动更新
    通过打补丁的方式进行更新,也可直接编辑文件进行更新,其值默认为1
# 更新当前副本集为5个
[ controllers]# kubectl patch deployment myapp-deploy -p ‘{"spec":{"relicas":5}}‘ 
# 实时查看更新状态
[ controllers]# kubectl get pods -w
  • 更新image版本号,滚动更新
    所运用到的命令:kubectl set、kubectl edit、kubectl apply、kubectl rollout
# 更新容器镜像版本至最新
[ controllers]# kubectl set image deployment/myapp-deployment nginx=nginx:latest 
# 查看滚动更新历史
[ controllers]# kubectl rollout history deployment myapp-deployment 
# 查看ReplicaSet空间image版本号状态
[ controllers]# kubectl get rs -l app=myapp -o wide
# 查看image字段
[ controllers]# kubectl describe pods myapp-deployment-5b776d9cf7-8hb8c | grep ‘Image‘ 
# 查看其更新的过程是怎么更新的,做了什么
[ controllers]# kubectl describe deployment/myapp-deployment
  • 模拟金丝雀发布
    更改maxSurge和maxUnavailable更新策略
# 命令帮助
[ controllers]# kubectl explain deploy.spec.strategy.rollingUpdate
# 先打补丁,更改当前更新策略,以模拟金丝雀发布
[ controllers]# kubectl patch deployment myapp-deployment -p ‘{"spec":{"strategy":{"rollingUpdate":{"maxSurge":1,"maxUnavailable":0}}}}‘
# 查看
[ controllers]# kubectl describe deploy myapp-deployment
# 再更新(金丝雀发布)
[ controllers]# kubectl set image deployment myapp-deployment myapp=nginx:v1  && kubectl rollout pause deployment myapp-
Waiting for deployment "myapp-deployment" rollout to finish: 1 out of 3 new replicas have been updated...
# 查看历史版本,使用 "--record" 参数可看到每个版本所使用的命令
[ controllers]# kubectl rollout history deployment myapp-deployment 
# 回滚不加版本号,默认回退到上一个版本
[ controllers]# kubectl rollout undo deployment myapp-deployment
# 使用 "--to-reversion=[N]" 回滚到指定版本
[ controllers]# kubectl rollout undo deploy myapp-deployment --to-reversion=1
# 如以上没问题,再次执行更新操作
[ controllers]# kubectl rollout resume deploy myapp-deployment

更多DeployMents控制器的Pod和ReplicaSet使用可参考 ---> 中文官方 DeployMnet 控制器使用

利用DaemonSet 运行指定一个Pod副本,把系统某个目录作为存储卷

更多 "DaemonSet" 控制器的使用可参考官网 ---> 中文官方 DaemonSet 控制器使用

再补充......

相关推荐