由于节点亲和性和Pod亲和性,无法部署更新的部署文件。

3

我有4个节点:一个是系统(System),一个是开发(Dev),一个是测试(Qa),一个是用户验收测试(UAT)。

我的亲和性设置如下:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: auth
  namespace: dev
  labels:
    app: auth
    environment: dev
    app-role: api
    tier: backend
spec:
  replicas: 1
  selector:
    matchLabels:
      app: auth
  template:
    metadata:
      labels:
        app: auth
        environment: dev
        app-role: api
        tier: backend
      annotations:
        build: _{Tag}_
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - auth
            topologyKey: kubernetes.io/hostname
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: environment
                operator: In
                values:
                - dev
      containers:
        - name: companyauth
          image: company.azurecr.io/auth:_{Tag}_
          imagePullPolicy: Always
          env:
            - name: ConnectionStrings__DevAuth
              value: dev
          ports:
            - containerPort: 80
      imagePullSecrets:
        - name: ips

我的意图是确保在我的生产集群上,有3个节点位于3个不同的可用区。所有的pod都将被调度到不同的节点/可用区。然而,如果我已经在一个节点上安排了pod,那么当我进行部署时,它不会覆盖已经存在的pod。

0/4个节点可用:1个节点与pod偏好设置/反偏好设置不匹配,3个节点与节点选择器不匹配。

然而,如果我删除podAffinity,它就能正常工作,并使用部署中的新pod覆盖当前节点。正确的方法是什么,以确保我的生产集群上的部署始终在不同的节点和不同的可用区上安排pod并更新现有节点?


你能分享一下你的部署/ Pod清单和节点配置(标签等)吗?贴近Pod、部署,还有其他什么吗?看起来你的Pod没有带有“app:auth”的标签,而且你的节点中也没有带有“environment:dev”的标签。请提供以上信息以便进一步调查。 - PjoterS
@PjoterS 我已更新至完整的部署文件。第一次部署可以正常工作,但是除非我删除 Pod 亲和性,否则后续的部署将无法正常工作。 - James
2个回答

2
您可以仅使用 PodAntiAffinity来实现您的目标。
我已经在我的GKE测试集群中进行了测试,但在Azure上应该类似。
当前问题:
在您当前的设置中,您已经使用nodeAffinity设置了podAntiAffinity

Pod anti-affinity可以防止调度程序将新的Pod定位在具有相同标签的Pod相同节点上,如果新的Pod上的标签选择器与当前Pod上的标签匹配。

在您的Deployment设置中,新的Pod将具有如下标签
  • app: auth
  • environment: dev
  • app-role: api
  • tier: backend
PodAntiAffinity被配置为,如果已经有标签为app: auth的pod存在,则不允许部署新的pod。
NodeAffinity被配置为,仅在具有标签environment: dev的节点上部署。
总之,您的错误是:
0/4 nodes are available: 1 node(s) didn't match pod affinity/anti-affinity, 3 node(s) didn't match node selector.

“1个节点与Pod亲和性/反亲和性不匹配。您的设置仅允许在具有标签'environment:dev'的节点上部署,并且仅允许具有标签'app:auth'的一个Pod。正如您提到的那样,如果我已经在节点上安排了Pod,那么当我进行部署时,它将不会覆盖已经存在的Pod。 PodAntiAffinity行为生效,并且不允许部署具有标签'app:auth'的新Pod,因为已经有一个。3个节点与节点选择器不匹配。NodeAffinity仅允许在具有标签'environment:dev'的节点上部署Pod。其他节点可能具有类似'environment:system'、'environment:uat'、'environment:qa'的标签,这些标签不符合'environment:dev'标签,因此不符合节点选择器。”
“解决方案:最简单的方法是删除NodeAffinity。”
在PodAntiAffinity中,如果将TolpologyKey设置为kubernetes.io/hostname,则足够了。
引用块中的topologyKey使用默认标签附加到节点上,以动态过滤节点名称。
更多信息,请查看this article
如果您描述了您的节点并使用kubernetes.io/hostname对它们进行grep,您将获得唯一的值:
$ kubectl describe node | grep kubernetes.io/hostname
                    kubernetes.io/hostname=gke-affinity-default-pool-27d6eabd-vhss
                    kubernetes.io/hostname=gke-affinity-default-pool-5014ecf7-5tkh
                    kubernetes.io/hostname=gke-affinity-default-pool-c2afcc97-clg9

测试

apiVersion: apps/v1
kind: Deployment
metadata:
  name: auth
  labels:
    app: auth
    environment: dev
    app-role: api
    tier: backend
spec:
  replicas: 3
  selector:
    matchLabels:
      app: auth
  template:
    metadata:
      labels:
        app: auth
        environment: dev
        app-role: api
        tier: backend
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - auth
            topologyKey: kubernetes.io/hostname
      containers:
        - name: nginx
          image: nginx
          imagePullPolicy: Always
          ports:
            - containerPort: 80

部署这个 YAML 之后。
$ kubectl get po -o wide
NAME                    READY   STATUS    RESTARTS   AGE   IP         NODE                                      NOMINATED NODE   READINESS GATES
auth-7fccf5f7b8-4dkc4   1/1     Running   0          9s    10.0.1.9   gke-affinity-default-pool-c2afcc97-clg9   <none>           <none>
auth-7fccf5f7b8-5qgt4   1/1     Running   0          8s    10.0.2.6   gke-affinity-default-pool-5014ecf7-5tkh   <none>           <none>
auth-7fccf5f7b8-bdmtw   1/1     Running   0          8s    10.0.0.9   gke-affinity-default-pool-27d6eabd-vhss   <none>           <none>

如果您将副本数增加到7,将不会部署更多的Pod。所有新的Pod都将停留在“Pending”状态,因为“antiPodAffinity”生效了(每个节点已经有带有标签“app:dev”的Pod)。
$ kubectl get po -o wide
NAME                    READY   STATUS    RESTARTS   AGE    IP         NODE                                      NOMINATED NODE   READINESS GATES
auth-7fccf5f7b8-4299k   0/1     Pending   0          79s    <none>     <none>                                    <none>           <none>
auth-7fccf5f7b8-4dkc4   1/1     Running   0          2m1s   10.0.1.9   gke-affinity-default-pool-c2afcc97-clg9   <none>           <none>
auth-7fccf5f7b8-556h5   0/1     Pending   0          78s    <none>     <none>                                    <none>           <none>
auth-7fccf5f7b8-5qgt4   1/1     Running   0          2m     10.0.2.6   gke-affinity-default-pool-5014ecf7-5tkh   <none>           <none>
auth-7fccf5f7b8-bdmtw   1/1     Running   0          2m     10.0.0.9   gke-affinity-default-pool-27d6eabd-vhss   <none>           <none>
auth-7fccf5f7b8-q4s2c   0/1     Pending   0          79s    <none>     <none>                                    <none>           <none>
auth-7fccf5f7b8-twb9j   0/1     Pending   0          79s    <none>     <none>                                    <none>           <none>

类似的解决方案在多区域工作节点上部署Pod的高可用性博客中有描述。

0

您的节点亲和规则要求只有 Dev 节点才会被考虑进行调度。结合您的 podAntiAffinityRule,这意味着只能调度一个 Pod(即在 Dev 节点上的 Pod)。

为了实现节点间的均匀调度,您需要添加额外的 Dev 节点或删除 nodeAffinity 规则。


那么,我如何确保在我的生产集群中,节点池始终以均匀的方式进行调度(即在不同的可用区域中为每个Pod安排调度)?但同时也要确保除第一个部署之外的每个后续部署都能够覆盖/更新原始部署? - James

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接