深入剖析k8s-控制器思想

引言

本文是《深入剖析Kubernetes》学习笔记------《深入剖析Kubernetes》

正文

控制器都遵循K8s的项目中一个通用的编排模式------控制循环

go 复制代码
for {
  实际状态 := 获取集群中对象X的实际状态
  期望状态 := 获取集群中对象X的期望状态
  if 实际状态 == 期望状态 {
     // do nothing
  } else {
     执行编排动作,将实际状态调整为期望状态
  }
}

作业副本与水平扩展

如果更新了Deployment的Pod模版,那么Deployment就需要遵循滚动更新的方式,来升级现有容器 → ReplicaSet.

DeployController 只需要修改它所控制的ReplicaSet的Pod副本个数就可以了。

相关命令

bash 复制代码
k scale deployment nginx-deployment --replicas=4 # 调整replicas数量

k rollout status deployment nginx-deployment # 实时查看Deployment对象的状态变化

k edit deployment/nginx-deployment # 通过修改yaml文件调整deployment状态

滚动更新,要求一定使用Pod的健康检查机制检查应用的运行状态,而不是简单地依赖容器的Running状态。

在控制器在滚动更新过程中永远会确保2个Pod处于可用状态,至多只有4个Pod同时存在于集群中,由RollingUpdateStrategy进行控制。

yaml 复制代码
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1 # 除了DESIRED数量外,在一次滚动更新中Deplyment控制气还可以创建多个新Pod
      maxUnavailable: 1 # 可以删除多少旧Pod

上述案例

yaml 复制代码
k set image deployment/nginx-deployment nginx=nginx:1.91 # 设置deployment nginx版本
bash 复制代码
k rollout undo deployment/nginx-deployment # 错误回滚,rs仍然保存

k rollout history deployment/nginx-deployment --revision=2 # 查看API对象的细节

k rollout undo deployment/nginx-deployment --to-revision=2 # 最后加上目标版本号,来回滚指定版本

每一次操作都会生成rs,是否造成资源浪费?

解决方案1:

bash 复制代码
k rollout pause deployment/nginx-deployment

... k edit / k set image

k rollout resume deploy/nginx-deployment

解决方案2:

spec.revisionHistoryLimit=0 再也不能进行回滚操作

问题

应用的发布流程往往千差万别,可能有很多定制化的需求。例如:会有会话粘连(session sticky),这就意味着更新时哪个Pod能下线不是随便选择的。

StatefulSet :拓扑状态

有些实例之间有不对等关系,以及实例对外部数据有依赖关系的应用,就称为有状态应用。

StatefulSet将应用状态抽象为两种情况

  1. 拓扑状态:应用的多个实例之间不是完全对等的。
  2. 存储状态:应用的多个实例分别绑定了不同的存储数据。

Headless Service

Services是K8s用来将一组Pod暴露给外界访问的一个机制。

  1. 以Service的VIP(virtual IP的方式):当访问10.0.23.1这个Service IP地址时,会把请求转发到该Service所代理的Pod上。
  2. 以Service的DNS方式:访问my-svc-namespace.svc.cluster.local这条DNS记录,就可以访问my-svc所代理的Pod上
    1. Normal Servcie:解析DNS时,返回的是VIP
    2. Headless Service:解析DNS时,直接返回的是Pod IP

创建Healess Service

yaml 复制代码
apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  selector:
    app: nginx
  ports:
    - name: web
      port: 80
  clusterIP: None # 不同点

创建一个Healess Service之后,所代理的所有Pod的IP都会被绑定到<pod-name>.<svc-name>.<namespace>.svc.cluster.local上。

StatefulSet如何使用这个DNS记录为维持Pod的拓扑状态

StatefulSet让其所有Pod都有唯一的网络标识,即使Pod被删除,重新创建的容器网络标识与原先 相同 (IP不同)

StatefulSet:存储状态

PVC和PV的设计,实际上类似于"接口"和"实现"的思想。

开发者只要知道并会使用PVC;运维人员负责给"接口"绑定具体的实现,即PV;

yaml 复制代码
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  serviceName: nginx-service
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:1.9.1
          ports:
            - containerPort: 80
              name: web
          volumeMounts:
            - mountPath: /usr/share/nginx/html
              name: www
  volumeClaimTemplates:
    - metadata:
        name: www
      spec:
        accessModes:
          - ReadWriteOnce
        resources:
          requests:
            storage: 1Gi

使用volumeClaimTemplate进行PV和PVC的绑定

总结

  1. StatefulSet的控制器直接管理的是Pod。
  2. K8s通过Headless Service为这些编号的Pod,在DNS服务器中生成有相同编号的DNS记录。
  3. StatefulSet为每一个Pod分配并创建一个相同编号的PVC。
相关推荐
努力搬砖的咸鱼2 小时前
容器之间怎么通信?Docker 网络全解析
网络·docker·云原生·容器
liming4954 小时前
Ubuntu18.04部署k8s
云原生·容器·kubernetes
YC运维6 小时前
Kubernetes资源管理全解析
java·容器·kubernetes
Leinwin7 小时前
微软发布Azure Kubernetes Service Automatic国际版
microsoft·kubernetes·azure
不爱笑的良田8 小时前
从零开始的云原生之旅(六):DaemonSet 实战日志采集器
云原生
chinesegf8 小时前
Docker篇6-项目app.py和flask_app.service配置和映射到docker中
docker·容器·flask
退役小学生呀8 小时前
二十二、DevOps:基于Tekton的云原生平台落地(三)
linux·云原生·容器·kubernetes·k8s·devops·tekton
橙色云-智橙协同研发8 小时前
PLM实施专家宝典:离散制造企业跨域协同与数字化审核方案
云原生·解决方案·数字化转型·plm·国产plm·工程方案·专家总结
维尔切8 小时前
搭建 k8s
云原生·容器·kubernetes
不爱笑的良田8 小时前
从零开始的云原生之旅(七):ConfigMap 和 Secret 配置管理
云原生