50、Kubernetes 中 Pod 亲和性、反亲和性及应用开发最佳实践

Kubernetes 中 Pod 亲和性、反亲和性及应用开发最佳实践

1. Pod 亲和性与反亲和性调度

在 Kubernetes 中,通过 Pod 亲和性(Pod Affinity)和反亲和性(Pod Anti - Affinity)可以控制 Pod 的调度位置,以满足不同的业务需求。

1.1 Pod 调度评分示例

在调度后端 Pod 时,会根据不同的优先级规则为节点打分。例如:

... backend-qhqj6 -> node1.k8s: Taint Toleration Priority, Score: (10)
... backend-qhqj6 -> node2.k8s: InterPodAffinityPriority, Score: (10)
... backend-qhqj6 -> node1.k8s: InterPodAffinityPriority, Score: (0)
... backend-qhqj6 -> node2.k8s: SelectorSpreadPriority, Score: (10)
... backend-qhqj6 -> node1.k8s: SelectorSpreadPriority, Score: (10)
... backend-qhqj6 -> node2.k8s: NodeAffinityPriority, Score: (0)
... backend-qhqj6 -> node1.k8s: NodeAffinityPriority, Score: (0)
... Host node2.k8s => Score 100030
... Host node1.k8s => Score 100022
... Attempting to bind backend-257820-qhqj6 to node2.k8s

从上述输出可以看出,由于 Pod 间亲和性,node2 在调度后端 Pod 时获得了比 node1 更高的分数,最终 Pod 会被绑定到 node2 上。

1.2 在同一区域部署 Pod
  • 同一可用区 :若要将前端 Pod 部署到与后端 Pod 相同的可用区,只需将 topologyKey 属性设置为 failure - domain.beta.kubernetes.io/zone
  • 同一地理区域 :若要将 Pod 部署到同一地理区域而非同一可用区,可将 topologyKey 设置为 failure - domain.beta.kubernetes.io/region
1.3 topologyKey 工作原理

topologyKey 的工作原理较为简单。例如,你可以自定义 topologyKey ,如 rack ,前提是要为节点添加相应的标签。假设你有 20 个节点,10 个在一个机架,10 个在另一个机架,你可以将前 10 个节点标记为 rack = rack1 ,后 10 个标记为 rack = rack2 。在定义 Pod 的 podAffinity 时,将 topologyKey 设置为 rack 。调度器在决定 Pod 部署位置时,会检查 Pod 的 podAffinity 配置,找到匹配标签选择器的 Pod,查找它们所在的节点,并根据 topologyKey 选择具有相同标签值的节点。

1.4 表达 Pod 亲和性偏好而非硬性要求

与节点亲和性类似,Pod 亲和性也可以表达偏好而非硬性要求。以下是一个使用 preferredDuringSchedulingIgnoredDuringExecution Pod 亲和性规则的 Deployment 示例:

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: frontend
spec:
  replicas: 5
  template:
    ...
    spec:
      affinity:
        podAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:  
          - weight: 80                                        
            podAffinityTerm:                                  
              topologyKey: kubernetes.io/hostname             
              labelSelector:                                  
                matchLabels:                                  
                  app: backend                                
      containers: ...

在这个示例中,调度器会优先将前端 Pod 调度到与后端 Pod 相同的节点,但如果无法满足,也可以调度到其他节点。

1.5 使用 Pod 反亲和性调度 Pod 远离彼此

Pod 反亲和性用于让调度器避免将 Pod 调度到运行着匹配 podAntiAffinity 标签选择器的 Pod 的节点上。以下是一个强制前端 Pod 调度到不同节点的示例:

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: frontend
spec:
  replicas: 5
  template:
    metadata:
      labels:                  
        app: frontend          
    spec:
      affinity:
        podAntiAffinity:                                      
          requiredDuringSchedulingIgnoredDuringExecution:     
          - topologyKey: kubernetes.io/hostname            
            labelSelector:                                 
              matchLabels:                                 
                app: frontend                              
      containers: ...

创建这个 Deployment 后,只有部分 Pod 会被调度,因为调度器不允许将 Pod 调度到同一节点。在某些情况下,使用 preferredDuringSchedulingIgnoredDuringExecution 这样的软要求可能更合适。

2. 典型应用中的 Kubernetes 资源

一个典型的 Kubernetes 应用包含多种资源,它们相互协作以确保应用的正常运行。以下是这些资源的概述:
|资源类型|说明|
| ---- | ---- |
|Deployment/StatefulSet|包含 Pod 模板,其中包含一个或多个容器,每个容器有存活探针和就绪探针。|
|Service|用于暴露提供服务的 Pod,可配置为 LoadBalancer 或 NodePort 类型,或通过 Ingress 资源暴露。|
|Secret|分为用于从私有镜像仓库拉取容器镜像的 Secret 和供 Pod 内进程直接使用的 Secret,通常由运维团队配置。|
|ConfigMap|用于初始化环境变量或作为配置卷挂载到 Pod 中。|
|PersistentVolumeClaim|用于需要持久存储的 Pod,其引用的 StorageClass 由系统管理员预先创建。|
|Job/CronJob|在某些应用中需要使用。|
|DaemonSet|通常由系统管理员创建,用于在所有或部分节点上运行系统服务。|
|HorizontalPodAutoscaler|可由开发人员包含在清单中,也可由运维团队后期添加。|
|LimitRange/ResourceQuota|由集群管理员创建,用于控制单个 Pod 和所有 Pod 的计算资源使用。|

以下是这些资源之间关系的 mermaid 流程图:

graph LR
    classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;

    A(Deployment/StatefulSet):::process --> B(Pod Template):::process
    B --> C(Container):::process
    C --> D(Liveness Probe):::process
    C --> E(Readiness Probe):::process
    B --> F(Volume):::process
    A --> G(ReplicaSet):::process
    G --> H(Pod):::process
    H --> I(Service):::process
    I --> J(Endpoints):::process
    H --> K(Secret):::process
    H --> L(ConfigMap):::process
    H --> M(PersistentVolumeClaim):::process
    M --> N(PersistentVolume):::process
    N --> O(StorageClass):::process
    A --> P(Job/CronJob):::process
    Q(DaemonSet):::process --> R(Pod):::process
    S(HorizontalPodAutoscaler):::process --> A
    T(LimitRange/ResourceQuota):::process --> H

通过对这些资源的合理配置和使用,可以构建出高效、稳定的 Kubernetes 应用。

3. 理解 Pod 的生命周期

在 Kubernetes 中,Pod 的生命周期与传统虚拟机中的应用有所不同,应用开发者需要充分理解这些差异,以确保应用能够适应 Kubernetes 环境。

3.1 应用必须预期被杀死和迁移

在 Kubernetes 之外,运行在虚拟机中的应用很少从一台机器迁移到另一台机器,并且迁移时可以手动重新配置和检查应用状态。但在 Kubernetes 中,应用会更频繁且自动地被迁移,这就要求应用开发者确保应用能够相对频繁地被移动。

  • 预期本地 IP 和主机名更改 :当 Pod 被杀死并在其他地方重新运行时,它会有新的 IP 地址、名称和主机名。大多数无状态应用通常可以处理这种变化,但有状态应用通常需要通过 StatefulSet 来运行,以确保在重新调度后启动时仍能看到相同的主机名和持久状态。不过,Pod 的 IP 地址仍然会改变,因此应用开发者不应基于成员的 IP 地址来确定集群应用的成员身份,如果基于主机名,则应始终使用 StatefulSet。
  • 预期写入磁盘的数据消失 :如果应用将数据写入磁盘,除非挂载了持久存储,否则这些数据在应用在新 Pod 中启动后可能不可用。即使在单个 Pod 的生命周期内,由于容器可能因各种原因(如进程崩溃、存活探针失败、节点内存不足等)重启,写入容器文件系统的数据也会丢失。因为新容器会以全新的可写层启动。
3.2 使用卷来跨容器重启保留数据

为了确保在容器重启时数据不丢失,可以使用至少一个 Pod 作用域的卷。由于卷与 Pod 共存亡,新容器可以重用前一个容器写入卷的数据。以下是使用卷的示意图:

graph LR
    classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;

    A(Container):::process --> B(Process):::process
    B --> C(Writes to):::process
    C --> D(Filesystem):::process
    D --> E(volumeMount):::process
    E --> F(Volume):::process
    A --> G(Container crashes or is killed):::process
    G --> H(New Container):::process
    H --> I(New Process):::process
    I --> J(Can read the same files):::process
    J --> F

4. 总结

通过对 Pod 亲和性、反亲和性以及 Pod 生命周期的理解,我们可以更好地在 Kubernetes 中调度和管理应用。以下是关键要点总结:
1. Taint 和 Toleration :给节点添加 Taint 后,除非 Pod 容忍该 Taint,否则不会被调度到该节点。有 NoSchedule、PreferNoSchedule 和 NoExecute 三种类型的 Taint。
2. Node Affinity :可以指定 Pod 应调度到哪些节点,分为硬要求和节点偏好。
3. Pod Affinity :使调度器将 Pod 部署到与另一个 Pod 相同的节点(基于 Pod 的标签), topologyKey 指定了 Pod 部署的接近程度。
4. Pod Anti - Affinity :用于使某些 Pod 相互远离,也可以指定硬要求或偏好。
5. Pod 生命周期 :应用需要预期被杀死和迁移,包括 IP 和主机名的变化以及写入磁盘数据的丢失,可使用卷来保留数据。

合理运用这些知识,可以构建出更高效、稳定且适应 Kubernetes 环境的应用。在实际开发中,开发者应根据具体的业务需求和场景,灵活配置和使用这些特性,以充分发挥 Kubernetes 的优势。

本 PPT 介绍了制药厂房中供配电系统的总体概念与设计要点,内容包括: 洁净厂房的特点及其对供配电系统的特殊要求; 供配电设计的一般原则与依据的国家/行业标准; 从上级电网到工厂变电所、终端配电的总体结构与模块化设计思路; 供配电范围:动力配电、照明、通讯、接地、防雷与消防等; 动力配电中电压等级、接地系统形式(如 TN-S)、负荷等级与可靠性、UPS 配置等; 照明的电源方式、光源选择、安装方式、应急与备用照明要求; 通讯系统、监控系统在生产管理与消防中的作用; 接地与等电位连接、防雷等级与防雷措施; 消防设施及其专用供电(消防泵、排烟风机、消防控制室、应急照明等); 常见高压柜、动力柜、照明箱等配电设备案例及部分设计图纸示意; 公司已完成的典型项目案例。 1. 工程背景与总体框架 所属领域:制药厂房工程的公用工程系统,其中本 PPT 聚焦于供配电系统。 放在整个公用工程中的位置:与给排水、纯化水/注射用水、气体与热力、暖通空调、自动化控制等系统并列。 2. Part 01 供配电概述 2.1 洁净厂房的特点 空间密闭,结构复杂、走向曲折; 单相设备、仪器种类多,工艺设备昂贵、精密; 装修材料与工艺材料种类多,对尘埃、静电等更敏感。 这些特点决定了:供配电系统要安全可靠、减少积尘、便于清洁和维护。 2.2 供配电总则 供配电设计应满足: 可靠、经济、适用; 保障人身与财产安全; 便于安装与维护; 采用技术先进的设备与方案。 2.3 设计依据与规范 引用了大量俄语标准(ГОСТ、СНиП、SanPiN 等)以及国家、行业和地方规范,作为设计的法规基础文件,包括: 电气设备、接线、接地、电气安全; 建筑物电气装置、照明标准; 卫生与安全相关规范等。 3. Part 02 供配电总览 从电源系统整体结构进行总览: 上级:地方电网; 工厂变电所(10kV 配电装置、变压
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值