본문 바로가기
Development/Docker&Kubernetes

[K8S] affinity 를 이용해서 노드 중복 피하기.

by 폴피드 2020. 11. 20.
728x90
반응형

현재 시스템의 구성은 다음과 같다

 

MasterNode, Worker1, Worker2

 

여기에 테스트를 위해서 mysql 을 열려놨다. 해당 yaml 은 다음과 같다. 

apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: spring
  name: deploy-mysql
  labels:
    app: mysql
spec:
  replicas: 2
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - name: mysql
        image: mysql:5.7
        env:
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-secret
              key: MYSQL_ROOT_PASSWORD
        - name: MYSQL_DATABASE
          valueFrom:
            secretKeyRef:
              name: mysql-secret
              key: MYSQL_DATABASE
        - name: MYSQL_USER
          valueFrom:
            secretKeyRef:
              name: mysql-secret
              key: MYSQL_USER
        ports:
        - containerPort: 3306
          name: mysql
          protocol: TCP
        volumeMounts:
        - mountPath: "/var/lib/mysql"
          name: mysql-volume
          subPath: dbdata
      volumes:
      - name: mysql-volume
        persistentVolumeClaim:
          claimName: mysql-pvc

그런데 한가지 문제가 생겼다. 

나는 K8S 를 사용하기 위해 virtual box 에서 master, worker1, worker2 이렇게 순서대로 헤드리스로 기동을 시킨다.

그런데 가끔 worker2 가 Ready 가 되기 전에 deployment 의 replicaset 이 같은 노드에 할당 되는 상황이 발생했다.

그러다 보니 pod 가 정상적으로 뜨지 않게 되었다. 

 

그냥 Pod 를 실행시키는 거라면 nodeselector 를 설정하면 될텐데 Deployment는 어떻게 하는지 몰라서 찾아보니 다음과 같이 spec 에 affinity 를 추가하는 방법을 찾을 수 있었다. 

      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - mysql
            topologyKey: "kubernetes.io/hostname"

 

위 설정에는 affinity 설정중 podAntiAffinity 설정을 추가하였다. 설정을 차례대로 해석하면 다음과 같다.

 

podAntiAffinity : 이 pod 가 실행될때 다음 값이 참이면 안된다.

requiredDuringSchedulingIgnoredDuringExecution : 반드시 만족해야 한다. (또다른 설정으로는 preffered 가 있다.)

matchExpressions: label 이 key 는 app 이고 값은 mysql 인 label을 찾는다.

 

결과적으로 label 이 app 이고 값이 mysql 인 pod 가 존재하는 node 에서는 pod 가 실행되지 않는다.

그래서 replicas 가 2로 설정되어있기 때문에 각각의 pod 는 각각의 node 에 위치하게 된다. 

 

master01@master01-VirtualBox:~/k8s/mysql$ kubectl get po -n spring -o wide
NAME                           READY   STATUS    RESTARTS   AGE   IP            NODE                  NOMINATED NODE   READINESS GATES
deploy-mysql-84f7bb885-rn9tz   1/1     Running   1          27h   10.244.1.80   worker01-virtualbox   <none>           <none>
deploy-mysql-84f7bb885-zqlmw   1/1     Running   1          26h   10.244.2.64   worker02-virtualbox   <none>           <none>

 

이거 이외에도 다양한 표현식으로 컨트롤이 가능하다. 

더 자세한 것은 아래 도큐먼트 참고하길 바란다.

 

v1-18.docs.kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/

728x90
반응형