👩‍💻👨‍💻 我们将延续上一章的操作环境:登陆私有云 KubeSphere 平台,进入 drillground 项目;从“应用负载”面板中,选择 my-nginx 工作负载。

image.png

容器分配 CPU 和内存资源

配置容器的资源预留及配额

💡 Kubernetes Documentations: Assign Memory Resources to Containers and Pods, Assign CPU Resources to Containers and Pods

Kubernetes 通过 cgroups 限制容器的 CPU 和内存等计算资源,包括 requests(请求,调度器保证调度到资源充足的 Node 上,如果无法满足会调度失败)和 limits(上限)等。

同“滚动更新”的配置类似,通过 KubeSphere 部署的容器组默认是可以自带 CPU 和内存资源配置的,这是怎么做到的呢?其实原理也很简单,在 KubeSphere 中创建项目(即 Kubernetes Namespace)时可以配置“容器资源默认请求”的配合,如下图所见即为 drillground 项目的配置情况,而次配置将被作为默认值由项目中的容器组继承。

image.png

:::info

🍮 CPU 和内存资源配置的单位


  • CPU 的单位是 CPU 个数,可以用 millicpu (m) 表示少于 1 个 CPU 的情况,如 500m = 500millicpu = 0.5cpu,而一个 CPU 相当于:
    • AWS 上的一个 vCPU
    • GCP 上的一个 Core
    • Azure 上的一个 vCore
    • 物理机上开启超线程时的一个超线程
  • 内存的单位则包括 E, P, T, G, M, K, Ei, Pi, Ti, Gi, Mi, Ki 等。 :::

如果需要对容器进行定制化的资源配置,可以回到工作负载内的“编辑配置模版”界面,进入 nginx 容器的配置界面。

image.png

image.png

image.png

在“编辑容器”面板,打开“容器设置”中的“高级设置”,即可对容器的 CPU 和内存的资源预留和限制进行滑动或手动配置

:::warning

⚠️ 如果 CPU 或内存超出配置的限制会发生什么?

  • CPU 上限,可以短暂超过,容器也不会被停止
  • 内存上限,不可以超过;如果超过,容器可能会被终止或调度到其他资源充足的机器上。 :::

基于资源配置形成的 QoS 等级说明

💡 Kubernetes Documentations: Configure Quality of Service for Pods

Kubernetes 为每个节点分配了可用资源,那么每个容器组(Pod)的级别是相同的吗?答案是否定的,Kubernetes 为 Pod 会分配不同级别的角色,像一个国王会分一等公民、二等公民、自由人,如果发生饥荒,比如资源短缺,Kubernetes 会先把资源分配给最优先的公民,保证它可用。Kubernetes 中 Pod 的级别具体划分为:GuaranteedBurstableBestEffort 三种。

  • Guaranteed(一等公民):这类 Pod 是有保证的,也是最优先的,在资源不足的情况下,Kubernetes 优先保证 Guaranteed 级别的 Pod,驱逐低优先级别的 Pod
    • Pod 中的每个容器必须指定内存请求和内存限制,并且两者要相等
    • Pod 中的每个容器必须指定 CPU 请求和 CPU 限制,并且两者要相等
  • Burstable(二等公民):这类 Pod 可能是比较常见的,它的级别高于 BestEffort 但低于 Guaranteed它尽量的节省资源同时也保证在资源不足的时候可以优先存活
    • Pod 不符合 Guaranteed QoS 类的标准;
    • Pod 中至少一个容器具有内存或 CPU 请求
  • BestEffort(自由民):这类 Pod 是级别最低的,它的定义是不对内存或者 CPU 做任何限制,在资源充足的情况下尽可能的使用资源,如果在资源不足的情况下,这类 Pod 会优先被驱逐,保证其他高级别的 Pod 存活

根据 CPU 和内存使用情况水平伸缩副本

💡 Kubernetes Documentations: Horizontal Pod Autoscaler

除了配置容器的资源请求和限制量,Kubernetes 还支持根据容器组 CPU 和内存的实际使用情况自动伸缩一个工作负载的副本数量,其在 KubeSphere 中的配置也非常方便。

image.png

my-nginx 部署的“更多操作”中选择“弹性伸缩”即可进入容器组水平伸缩参数配置窗口👇

image.png

:::info

🍮 Kubernetes Autoscaling 的几种类型

  • Horizontal Pod Autoscaler(HPA)
    • HPA 会在集群中缩放 Pod 副本的数量。该操作由 CPU 或内存触发,以根据需要向上或向下扩展。
    • 但是,也可以根据各种外部的和自定义指标(metrics.k8s.ioexternal.metrics.k8s.iocustom.metrics.k8s.io)来配置 HPA 以扩展 Pod。
  • Vertical Pod Autoscaler(VPA)
    • VPA 主要用于有状态服务,它可根据需要为 Pod 添加 CPU 或内存 — 它也适用于无状态的 Pod。
    • 为了应用这些更改,VPA 重新启动 Pod 以更新新的 CPU 和内存资源,这些资源可以配置为响应 OOM(内存不足)事件而启动。重新启动 Pod 的时候,VPA 始终确保根据 Pod 分配预算(PDB)确定最小数量,可以设置该资源分配最大和最小速率。
  • Cluster Autoscaler(CA)
    • 第二层的自动缩放涉及 CA,它在以下情况下自动调整集群的大小:
      • 由于集群中的容量不足,任何 Pod/s 都无法运行并进入挂起状态(在这种情况下,CA 将向上扩展)。
      • 集群中的节点在一段时间内未得到充分利用,并且有可能迁移节点上的 Pod(在这种情况下,CA 将缩小)。
    • CA 进行例行检查以确定是否有任何 Pod 因等待额外资源处于待定状态,或者集群节点是否未得到充分利用。如果需要更多资源,会相应地调整 Cluster 节点的数量。
    • CA 与云提供商交互以请求其他节点或关闭空闲节点,并确保按比例放大的集群保持在用户设置的限制范围内。它适用于 AWS,Azure 和 GCP。 :::

为容器组配置持久化数据

将配置文件挂载至指定目录

💡 Kubernetes Documentations: Configure a Pod to Use a ConfigMap

应用程序的运行可能会依赖一些配置,而这些配置又是可能会随着需求产生变化的,如果我们的应用程序架构不是应用和配置分离的,那么就会存在当我们需要去修改某些配置项的属性时需要重新构建镜像文件的窘境。现在,ConfigMap组件可以很好的帮助我们实现应用和配置分离,避免因为修改配置项而重新构建镜像。

ConfigMap 用于保存配置数据的键值对,可以用来保存单个属性,也可以用来保存配置文件。在 KubeSphere 中创建、管理和挂载 ConfigMap 都是非常便捷的。

image.png

返回项目面板,通过左侧的“配置中心”中的“配置”,可以进入配置集面板执行“创建配置”


image.png

image.png

创建一个名为 nginx-conf 的配置集,添加一个 default.conf 的键并填写如上内容,用于覆盖现有的 Nginx 默认配置文件


image.png**

完成创建后,可以在配置面板看到已经创建的 nginx-conf 配置集,及其所含的一个配置项 default.conf

image.png

接下来返回 my-nginx 的部署面板,再次进入“编辑配置模版”,这次需要进入左侧“存储卷”标签页,选择“挂载配置文件或密钥”,开始绑定前面创建的配置集


image.png**

⚠️ 注意这里配置需要这容器路径这边一定需要“点击添加子路径”,否则无法将配置项作为文件挂载!


image.png**

完成如上配置并保存,即可实现:将 default.conf 配置项的内容作为文件挂载到 /etc/nginx/conf.d/default.conf (即覆盖原配置文件)

:::success 完成如上所有操作后,会触发容器组的滚动更新,更新成功后重新访问 Nginx(本部署的访问地址为 10.0.162.5:31917),即可发现页面会自动跳转到指定页面。🎉 :::

添加并挂载持久化存储卷

💡 Kubernetes Documentations: Configure a Pod to Use a PersistentVolume for Storage

我们知道默认情况下容器的数据都是非持久化的,在容器消亡以后数据也跟着丢失,所以 Docker 提供了 Volume 机制以便将数据持久化存储。类似的,Kubernetes 提供了更强大的 Volume 机制和丰富的插件,解决了容器数据持久化和容器间共享数据的问题。

与 Docker 不同,Kubernetes Volume 的生命周期与 Pod 绑定

  • 容器挂掉后 Kubelet 再次重启容器时,Volume 的数据依然还在;
  • 而 Pod 删除时,Volume 才会清理。数据是否丢失取决于具体的 Volume 类型,比如 **emptyDir**(临时存储)的数据会丢失,而 PersistentVolume(持久化存储)则不会丢
    • 持久化存储有时也用于容器内的日志落盘,默认容器的 stdoutstderr 输出的日志在 Node 节点落盘并会自动循环,默认大小只有 10 M 空间

在 KubeSphere 中配置使用临时或持久化存储的方式也是很直接的,下面给出一个示例介绍创建并挂载一个 Ceph 块存储的过程。

image.png

返回项目面板,从左侧面板的“存储卷”进入,开始“创建存储卷”

image.png

创建一个名为 nginx-pv 的存储卷,然后完成如图的配置后,“下一步”跳过高级设置,直接“创建”存储卷

image.png

创建完成后等待存储卷进入“准备就绪”状态即可开始后续挂载操作

image.png

再次进入 my-nginx 的“编辑配置模版“,选择“添加存储卷”

image.png

如上图所示,选取先前创建的 nginx-pv 持久化存储卷,并将它绑定到 Nginx 容器的 /var/www 目录节点上,而后保存配置


image.png**

确认配置后,容器组会再次滚动更新,更新完成后可以得到类似如上图的“容器组”和“存储设备”视图

** :::success 现在 1 GB 的持久化存储已经绑定到了 Nginx 容器到 /var/www 目录下,可以通过终端进入目录任何写入内容后,重新部署容器组以验证写入的内容是否仍然存在。👀 :::