K8S 支持多副本部署,但不代表应用的高可用,因为多个副本可能部署到同一个节点上。
早上发现应用的某一个功能有一半的请求失败,排查之后发现,原来容器服务中节点未设置反亲和性,导致 Pod 部署到同一个节点中,影响 API 网关请求后端服务。
先 review 以下架构图
在页面中使用页面功能时,发现有一半的请求失败,API 返回为空。
于是想到可能和 API 网关请求后端接口有关,下图为 API 网关对应后端通道的配置,有 2 个节点。
查看容器服务对应 Pod,发现两个副本都运行在同一个节点上,问题找到了。
副本跑在同一个节点的原因:随着集群的变化,一开始部署在两个节点上的 Pod, 因为其中一个节点的资源被占满, 导致 Pod 优先调度到另一个闲置的节点上。
解决问题的思路是让 Pod 不能调度在同一台服务器上,需要打散调度到所有节点中。
ChatGPT 助手的 QA 详见附录,也可以查看文本的帮助文档(是通过关键字
Anti-Affinity
检索到的 )
容器服务虽然有 调度策略
功能,但无法满足当前的场景, 于是编辑 Deployment 的 YAML 配置,在 Pod 上新增 spec.template.spec.topologySpreadConstraints
segment。
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 分布到多个节点上,问题解决。
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 分散到不同的节点上:
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 的分布,这可以通过设置 maxSkew
、topologyKey
和 whenUnsatisfiable
等参数来实现。
以下是一个使用 Pod Topology Spread Constraints 的 Deployment 示例:
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 删除。