深入剖析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。
相关推荐
程序那点事儿1 小时前
k8s 之安装busybox
云原生·容器·kubernetes
weixin_453965002 小时前
master节点k8s部署]33.ceph分布式存储(四)
分布式·ceph·kubernetes
是芽芽哩!2 小时前
【Kubernetes】常见面试题汇总(五十八)
云原生·容器·kubernetes
福大大架构师每日一题13 小时前
22.1 k8s不同role级别的服务发现
容器·kubernetes·服务发现
莹雨潇潇13 小时前
Docker 快速入门(Ubuntu版)
java·前端·docker·容器
weixin_4539650014 小时前
[单master节点k8s部署]30.ceph分布式存储(一)
分布式·ceph·kubernetes
weixin_4539650014 小时前
[单master节点k8s部署]32.ceph分布式存储(三)
分布式·ceph·kubernetes
tangdou36909865514 小时前
1分钟搞懂K8S中的NodeSelector
云原生·容器·kubernetes
Lansonli15 小时前
云原生(四十一) | 阿里云ECS服务器介绍
服务器·阿里云·云原生
Dylanioucn16 小时前
【分布式微服务云原生】掌握分布式缓存:Redis与Memcached的深入解析与实战指南
分布式·缓存·云原生