前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >利用 K8S 的反亲和性构建高可用应用

利用 K8S 的反亲和性构建高可用应用

原创
作者头像
SRE扫地僧
发布2024-02-26 11:07:50
2840
发布2024-02-26 11:07:50
举报
文章被收录于专栏:k8s_istiok8s_istio

K8S 支持多副本部署,但不代表应用的高可用,因为多个副本可能部署到同一个节点上。

早上发现应用的某一个功能有一半的请求失败,排查之后发现,原来容器服务中节点未设置反亲和性,导致 Pod 部署到同一个节点中,影响 API 网关请求后端服务。

架构图

先 review 以下架构图

  • Web 应用:Vue 框架,运行在 容器服务
  • 腾讯云 API 网关
  • 业务 API:Golang 框架,运行在容器服务上,使用 NodePort 方式对外暴露服务

1. 问题

在页面中使用页面功能时,发现有一半的请求失败,API 返回为空。

于是想到可能和 API 网关请求后端接口有关,下图为 API 网关对应后端通道的配置,有 2 个节点。

查看容器服务对应 Pod,发现两个副本都运行在同一个节点上,问题找到了。

副本跑在同一个节点的原因:随着集群的变化,一开始部署在两个节点上的 Pod, 因为其中一个节点的资源被占满, 导致 Pod 优先调度到另一个闲置的节点上。

2. 解决问题:设置反亲和性

解决问题的思路是让 Pod 不能调度在同一台服务器上,需要打散调度到所有节点中。

ChatGPT 助手的 QA 详见附录,也可以查看文本的帮助文档(是通过关键字 Anti-Affinity 检索到的 )

容器服务虽然有 调度策略 功能,但无法满足当前的场景, 于是编辑 Deployment 的 YAML 配置,在 Pod 上新增 spec.template.spec.topologySpreadConstraints segment。

代码语言:yaml
复制
      topologySpreadConstraints:
      - labelSelector:
          matchLabels:
            k8s-app: XXX
            qcloud-app: XXX
        maxSkew: 1
        topologyKey: kubernetes.io/hostname
        whenUnsatisfiable: ScheduleAnyway

解读: maxSkew 设置为 1 表示允许的最大偏差为 1,即任一节点上的 Pod 数量不会比其他节点多 1 个以上。topologyKey"kubernetes.io/hostname",意味着在不同的节点上分布 Pods。

部署后,Pod 分布到多个节点上,问题解决。

3. 事后思考

  • 开启 API 网关的健康检查,当 API 网关探测节点失效时从后端通道中剔除
  • 了解 K8S 资源调度的基本概念

附录:ChatGPT 助手

Q: TKE 如何设置让 Deployment 的 2 个 Pod 分配到两个节点上,目前 两个 Pod 分配到同一个 节点中。

A(ChatGPT-4-turbo): TKE(Tencent Kubernetes Engine)是腾讯云提供的托管 Kubernetes 服务。在 Kubernetes 中,如果希望让 Deployment 的 Pods 分布在不同的节点上,可以使用几种策略,主要包括:

1.亲和性(Affinity)和反亲和性(Anti-Affinity)规则

使用 Pod 反亲和性规则可以指定 Kubernetes 调度器不要将属于同一 Deployment 的 Pods 调度到同一节点上。

例如,以下是一个 Deployment 配置的示例,它使用了 Pod 反亲和性来确保 Pods 分散到不同的节点上:

代码语言:yaml
复制
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - name: myapp-container
        image: myapp:1.0
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: "app"
                operator: In
                values:
                - myapp
            topologyKey: "kubernetes.io/hostname"

在这个例子中,requiredDuringSchedulingIgnoredDuringExecution 确保调度器在调度时遵循这些规则,而 topologyKey 设置为 "kubernetes.io/hostname" 表示 Pods 不能在拥有相同主机名的节点上运行。

2.使用 Pod Topology Spread Constraints

Pod Topology Spread Constraints 允许你更细粒度地控制 Pods 的分布,这可以通过设置 maxSkewtopologyKeywhenUnsatisfiable 等参数来实现。

以下是一个使用 Pod Topology Spread Constraints 的 Deployment 示例:

代码语言:yaml
复制
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - name: myapp-container
        image: myapp:1.0
      topologySpreadConstraints:
      - maxSkew: 1
        topologyKey: "kubernetes.io/hostname"
        whenUnsatisfiable: "ScheduleAnyway"
        labelSelector:
          matchLabels:
            app: myapp

在这个配置中,maxSkew 设置为 1 表示允许的最大偏差为 1,即任一节点上的 Pod 数量不会比其他节点多 1 个以上。topologyKey 同样设置为 "kubernetes.io/hostname",意味着在不同的节点上分布 Pods。

确保你的 Kubernetes 集群有足够的不同节点来支持这些分布策略。如果集群中只有一个可用节点,或者其他节点因为资源限制(如 CPU、内存不足)无法调度 Pods,那么这些策略可能不会有效。

参考文档

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 架构图
  • 1. 问题
  • 2. 解决问题:设置反亲和性
  • 3. 事后思考
  • 附录:ChatGPT 助手
  • 参考文档
相关产品与服务
API 网关
腾讯云 API 网关(API Gateway)是腾讯云推出的一种 API 托管服务,能提供 API 的完整生命周期管理,包括创建、维护、发布、运行、下线等。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
http://www.vxiaotou.com