Kubernetes 通常不会直接创建 Pod,而是通过 Controller 来管理 Pod 的。Controller 中定义了 Pod 的部署特性,比如有几个副本、在什么样的 Node 上运行等。通俗的说可以认为 Controller 就是用来管理 Pod 一个对象。其核心作用可以通过一句话总结: 通过监控集群的公共状态,并致力于将当前状态转变为期望的状态。
通俗定义: Controller 可以管理 Pod,让 Pod 更具有运维能力
常见的控制器
Deployment
:是最常用的 Controller。Deployment 可以管理 Pod 的多个副本,并确保 Pod 按照期望的状态运行。
- ReplicaSet:实现了 Pod 的多副本管理。使用 Deployment 时会自动创建 ReplicaSet,也就是说 Deployment 是通过 ReplicaSet 来管理 Pod 的多个副本的,我们通常不需要直接使用 ReplicaSet。
Daemonset
:用于每个 Node 最多只运行一个 Pod 副本的场景。正如其名称所揭示的,DaemonSet 通常用于运行 daemon(守护)。Statefuleset
:能够保证 Pod 的每个副本在整个生命周期中名称是不变的,而其他 Controller 不提供这个功能。当某个 Pod 发生故障需要删除并重新启动时,Pod 的名称会发生变化,同时 StatefuleSet 会保证副本按照固定的顺序启动、更新或者删除。Job
:用于运行结束就删除的应用,而其他 Controller 中的 Pod 通常是长期持续运行。
控制器如何管理 Pod
Controller 通过 label 关联起来 Pods
控制器 Deployment
官网:http://kubernetes.p2hp.com/docs/concepts/workloads/controllers/deployment.html
一个 Deployment 为 Pod 和 ReplicaSet 提供声明式的更新能力。
你负责描述 Deployment 中的目标状态,而 Deployment 控制器(Controller)以受控速率更改实际状态,使其变为期望状态。你可以定义 Deployment 以创建新的 ReplicaSet,或删除现有 Deployment, 并通过新的 Deployment 收养其资源。
创建
apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment # 控制器名称 labels: # 控制器自身的标签 app: nginx spec: replicas: 3 # 副本数量 selector: matchLabels: # 选择指定标签的 Pod 控制 app: nginx template: # Pod 的描述 metadata: labels: app: nginx # 注意 Pod 的标签和 matchLabels 必须对应 spec: containers: - name: nginx image: nginx:1.19 ports: - containerPort: 80
NAME
:列出了名字空间中 Deployment 的名称。READY
:显示应用程序的可用的副本
数。显示的模式是就绪个数/期望个数
。UP-TO-DATE
:显示为了达到期望状态已经更新的副本数。AVAILABLE
:显示应用可供用户使用的副本数。AGE
:显示应用程序运行的时间。
请注意期望副本数是根据
.spec.replicas
字段设置 3。
查看
# 部署 kubectl apply -f deployment.yaml # 查看 Deployment kubectl get deploy|deployment # 查看 Pod kubectl get pod -o wide # 查看 Pod 详情 kubectl describe pod <Pod名称> # 查看 Deployment 详细 kubectl describe deployment <Deployment名称> # 查看 Log kubectl logs <Pod名称> # 进入 Pod 容器终端, -c container-name 可以指定进入哪个容器。 kubectl exec -it <Pod名称> -c <容器名称> -- bash # 输出到文件 kubectl get deployment <Deployment名称> -o yaml >> test.yaml
扩缩
# 查询副本 kubectl get rs|replicaset # 伸缩扩展副本 kubectl scale deployment <Deployment名称> --replicas=<副本数量>
回滚
仅当 Deployment Pod 模板(.spec.template
)发生改变时,例如模板的标签或容器镜像被更新,才会触发 Deployment 上线。其他更新(如对 Deployment 执行扩缩容的操作)不会触发上线动作。
# 查看上线状态 kubectl rollout status deployment <Deployment名称> # 查看历史 kubectl rollout history deployment <Deployment名称> # 查看某次历史的详细信息 kubectl rollout history deployment <Deployment名称> --revision=2 # 回到上个版本 kubectl rollout undo deployment <Deployment名称> # 回到指定版本 kubectl rollout undo deployment <Deployment名称> --to-revision=2 # 重新部署 kubectl rollout restart deployment <Deployment名称> # 暂停运行,暂停后,对 Deployment 的修改不会立刻生效,恢复后才应用设置 kubectl rollout pause deployment <Deployment名称> # 恢复 kubectl rollout resume deployment <Deployment名称>
删除
# 删除 Deployment kubectl delete deployment <Deployment名称> kubect delete -f nginx-deployment.yml # 删除默认命名空间下全部资源 kubectl delete all --all # 删除指定命名空间的资源 kubectl delete all --all -n <命令空间>
推荐使用 kubect delete -f nginx-deployment.yml
这种方式删除控制器。
控制器 StatefulSet
官网:https://kubernetes.io/zh-cn/docs/concepts/workloads/controllers/statefulset/
StatefulSet 是用来管理 有状态应用
的工作负载 API 对象。
- 无状态应用: 应用本身不存储任何数据的应用称之为无状态应用。例如:Java、前端应用、Nginx 等。
- 有状态应用: 应用本身需要存储相关数据应用称之为有状态应用。例如:MySQL、Redis、RabbitMQ 等。
StatefulSet 用来管理某 Pod 集合的部署和扩缩,并为这些 Pod 提供持久存储和持久标识符。
和 Deployment 类似, StatefulSet 管理基于相同容器规约的一组 Pod。但和 Deployment 不同的是,StatefulSet 为它们的每个 Pod 维护了一个有粘性的 ID。这些 Pod 是基于相同的规约来创建的,但是不能相互替换:无论怎么调度,每个 Pod 都有一个永久不变的 ID。
如果希望使用存储卷为工作负载提供持久存储,可以使用 StatefulSet 作为解决方案的一部分。尽管 StatefulSet 中的单个 Pod 仍可能出现故障,但持久的 Pod 标识符使得将现有卷与替换已失败 Pod 的新 Pod 相匹配变得更加容易。
特点
StatefulSet 对于需要满足以下一个或多个需求的应用程序很有价值:
- 稳定的、唯一的网络标识符。
- 稳定的、持久的存储。
- 有序的、优雅的部署和扩缩。
- 有序的、自动的滚动更新。
在上面描述中,稳定的
意味着 Pod 调度或重调度的整个过程是有持久性的。如果应用程序不需要任何稳定的标识符或有序的部署、删除或扩缩,则应该使用由一组无状态的副本控制器提供的工作负载来部署应用程序,比如 Deployment 或者 ReplicaSet 可能更适用于你的无状态应用部署需要。
限制
- 给定 Pod 的存储必须由 PersistentVolume Provisioner 基于所请求的
storage class
来制备,或者由管理员预先制备。 - 删除或者扩缩 StatefulSet 并不会删除它关联的存储卷。这样做是为了保证数据安全,它通常比自动清除 StatefulSet 所有相关的资源更有价值。
- StatefulSet 当前需要无头服务来负责 Pod 的网络标识。你需要负责创建此服务。
- 当删除一个 StatefulSet 时,该 StatefulSet 不提供任何终止 Pod 的保证。为了实现 StatefulSet 中的 Pod 可以有序且体面地终止,可以在删除之前将 StatefulSet 缩容到 0。
- 在默认 Pod 管理策略(
OrderedReady
) 时使用滚动更新,可能进入需要人工干预才能修复的损坏状态。
使用
搭建 NFS 服务
一下教程适用于 CentOS7 系统。
#安装nfs-utils yum install -y rpcbind nfs-utils #创建nfs目录 mkdir -p /root/nfs/data #编辑/etc/exports输入如下内容 # insecure:通过 1024 以上端口发送 rw: 读写 sync:请求时写入共享 no_root_squash:root用户有完全根目录访问权限 echo "/root/nfs/data *(insecure,rw,sync,no_root_squash)" >> /etc/exports #启动相关服务并配置开机自启动 systemctl start rpcbind systemctl start nfs-server systemctl enable rpcbind systemctl enable nfs-server #重新挂载 使 /etc/exports生效 exportfs -r #查看共享情况 exportfs
客户端测试
NFS 客户端需要在每一个 K8s 节点上安装配置。
# 1.安装客户端 所有节点安装 yum install -y nfs-utils # 2.创建本地目录 mkdir -p /root/nfs # 3.挂载远程nfs目录到本地 mount -t nfs 192.168.95.11:/root/nfs /root/nfs # 4.写入一个测试文件 echo "hello nfs server" > /root/nfs/data/test.txt # 5.去远程 nfs 目录查看 cat /root/nfs/test.txt # 挂取消载 umount -f -l nfs目录
创建 nfs-client-provisioner
apiVersion: apps/v1 kind: Deployment metadata: name: nfs-client-provisioner labels: app: nfs-client-provisioner namespace: kube-system spec: replicas: 1 strategy: type: Recreate selector: matchLabels: app: nfs-client-provisioner template: metadata: labels: app: nfs-client-provisioner spec: serviceAccountName: nfs-client-provisioner containers: - name: nfs-client-provisioner image: chronolaw/nfs-subdir-external-provisioner:v4.0.2 volumeMounts: - name: nfs-client-root mountPath: /persistentvolumes env: - name: PROVISIONER_NAME value: k8s-sigs.io/nfs-subdir-external-provisioner - name: NFS_SERVER value: 192.168.95.11 - name: NFS_PATH value: /root/nfs/data volumes: - name: nfs-client-root nfs: server: 192.168.95.11 path: /root/nfs/data
Kubernetes控制器(二)https://developer.aliyun.com/article/1480850