云原生高可用与容灾系列: 服务高可用 Pod 打散调度

云原生高可用与容灾系列: Pod 打散调度https://mp.weixin.qq.com/s/Kb6D-4vDHdoBBTAG3h1KtQ

服务高可用


为了提高服务容错能力,我们通常会设置 replicas 给服务创建多个副本,但这并不意味着服务就实现高可用了,下面来介绍服务高可用部署最佳实践。

 

使用反亲和性避免单点故障


k8s 的设计就是假设节点是不可靠的,节点越多,发生软硬件故障导致节点不可用的几率就越高,所以我们通常需要给服务部署多个副本,根据实际情况调整 replicas 的值,如果值为 1 就必然存在 单点故障,如果大于 1 但所有副本都调度到同一个节点,那还是有单点故障所以我们不仅要有合理的副本数量,还需要让这些不同副本调度到不同的节点,打散开来避免单点故障,这个可以利用反亲和性来实现,示例:

  • requiredDuringSchedulingIgnoredDuringExecution 调度时必须满足该反亲和性条件,如果没有节点满足条件就不调度到任何节点 (Pending)。如果不用这种硬性条件可以使用 preferredDuringSchedulingIgnoredDuringExecution 来指示调度器尽量满足反亲和性条件,如果没有满足条件的也可以调度到某个节点。
  • labelSelector.matchExpressions 写该服务对应 pod labels key value
  • topologyKey 这里用 kubernetes.io/hostname 表示避免 pod 调度到同一节点,如果你有更高的要求,比如避免调度到同一个可用区,实现异地多活,可以用 failure-domain.beta.kubernetes.io/zone 通常不会去避免调度到同一个地域,因为一般同一个集群 的节点都在一个地域,如果跨地域,即使用专线时延也会很大,所以 topologyKey 一般不至 于用 failure-domain.beta.kubernetes.io/region

 

驱逐节点是一种有损操作,驱逐的原理 :
1. 封锁节点 ( 设为不可调度,避免新的 Pod 调度上来 )
2. 将该节点上的 Pod 删除。
3. ReplicaSet 控制器检测到 Pod 减少,会重新创建一个 Pod ,调度到新的节点上。

 

我们再来下什么情况下驱逐会导致服务不可用 :
1. 服务存在单点故障,所有副本都在同一个节点,驱逐该节点时,就可能造成服务不可用。
2. 服务在多个节点,但这些节点都被同时驱逐,所以这个服务的所有服务同时被删,也可能造成服
务不可用。
针对第一点,我们可以 使用反亲和性避免单点故障
针对第二点,我们可以通过配置 PDB (PodDisruptionBudget) 来避免所有副本同时被删除,下面
给出示例。
示例一 ( 保证驱逐时 zookeeper 至少有两个副本可用 ):

 示例二 (保证驱逐时 zookeeper 最多有一个副本不可用,相当于逐个删除并在其它节点重建):

 

 

概述


将 Pod 打散调度到不同地方,可避免因软硬件故障、光纤故障、断电或自然灾害等因素导致服务不可用,以实现服务的高可用部署。

Kubernetes 支持两种方式将 Pod 打散调度:

  • Pod 反亲和 (Pod Anti-Affinity)

  • Pod 拓扑分布约束 (Pod Topology Spread Constraints)

本文介绍两种方式的用法示例与对比总结。

使用 podAntiAffinity


将 Pod 强制打散调度到不同节点上(强反亲和),以避免单点故障:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - topologyKey: kubernetes.io/hostname
            labelSelector:
              matchLabels:
                app: nginx
      containers:
      - name: nginx
        image: nginx
  • labelSelector.matchLabels 替换成选中 Pod 实际使用的 label。

  • topologyKey: 节点的某个 label 的 key,能代表节点所处拓扑域,可以用 Well-Known Labels,常用的是 kubernetes.io/hostname (节点维度)、topology.kubernetes.io/zone (可用区/机房 维度)。也可以自行手动为节点打上自定义的 label 来定义拓扑域,比如 rack (机架维度)、machine (物理机维度)、switch (交换机维度)。(PodAffinityPredicate 是有作用域的,比如上面这条规则,就仅对携带了 Key 是kubernetes.io/hostname标签的 Node 有效。这正是 topologyKey 这个关键词的作用。)

  • 若不希望用强制,可以使用弱反亲和,让 Pod 尽量调度到不同节点:

podAntiAffinity:
  preferredDuringSchedulingIgnoredDuringExecution:
  - podAffinityTerm:
      topologyKey: kubernetes.io/hostname
    weight: 100
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值