Kubernetes - Node Affinity 추가

상황

Kubernetes 이용해서 MySQL 서비스하는 중 서버들을 재부팅함

현상

재부팅 이후 데이터베이스가 비어있음 …..

원인은 원래 2번 노드에서 실행되던 pod가 재부팅과 동시에 1번 노드로 할당되어서 기존 데이터에 접근이 불가능한 것으로 추정

해결

해결을 위해 특정 pod가 특정 node에만 할당되도록 constraint 추가 필요 -> Node Affinity

먼저 현재 pod의 할당 상태 확인

1
2
3
4
hhr-master@hhrmaster:~/Desktop/MySQL$ kubectl get pods -o wide
NAME                     READY   STATUS    RESTARTS   AGE     IP          NODE               NOMINATED NODE   READINESS GATES
mysql-5694b666f7-zdcc5   1/1     Running   0          3d18h   10.44.0.1   hhrworker1   <none>           <none>
mysql-client             0/1     Error     0          2d16h   10.36.0.1   hhrworker2   <none>           <none>

(mysql-client의 Error는 무시하자. 내가 내부 데이터베이스 접근을 위해 임시로 생성했던 pod임)

현재 mysql-569… 가 내가 서비스중인 mysql인데, hhrworker1에서 돌아가는 중. 재부팅 이전에는 hhrworker2였음.

node affinity를 추가해서 hhrworker2에서만 돌아가도록 할 예정

node affinity는 node의 label을 key로 삼아 pod를 할당할 수 있는 것 같음.

현재 기본으로 설정되어 있는 label을 확인하기 위해서 다음 명령어 실행

1
2
3
4
5
hhr-master@hhrmaster:~/Desktop/MySQL$ kubectl get nodes --show-labels
NAME               STATUS   ROLES                  AGE   VERSION   LABELS
hhrmaster    Ready    control-plane,master   94d   v1.22.2   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=hhrmaster,linux,node-role.kubernetes.io/control-plane=,node-role.kubernetes.io/master=,node.kubernetes.io/exclude-from-external-load-balancers=
hhrworker1   Ready    <none>                 90d   v1.22.3   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=hhrworker1=linux
hhrworker2   Ready    <none>                 68d   v1.22.3   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=hhrworker2=linux

‘hostname=hhrworker2’ 가 이미 지정되어 있고, node name을 따라가는 고유한 값으로 보이지만, 직관성과 연습을 위해 새로운 레이블을 추가해보자

1
2
hhr-master@hhrmaster:~/Desktop/MySQL$ kubectl label nodes hhrworker2 nodetype=db
node/hhrworker2 labeled

이후 추가된 레이블 확인

1
2
3
4
5
hhr-master@hhrmaster:~/Desktop/MySQL$ kubectl get nodes --show-labels
NAME               STATUS   ROLES                  AGE   VERSION   LABELS
hhrmaster    Ready    control-plane,master   94d   v1.22.2   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=hhrmaster,linux,node-role.kubernetes.io/control-plane=,node-role.kubernetes.io/master=,node.kubernetes.io/exclude-from-external-load-balancers=
hhrworker1   Ready    <none>                 90d   v1.22.3   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=hhrworker1=linux
hhrworker2   Ready    <none>                 68d   v1.22.3   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=hhrworker2=linux,nodetype=db

hhrworker2 끝부분에 nodetype=db 가 추가된 것을 확인할 수 있음

이제 pod로 넘어가서 mysql-deployment.yaml 을 수정하자

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
spec:
  ports:
  - port: 3306
  selector:
    app: mysql
  clusterIP: None
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql
spec:
  selector:
    matchLabels:
      app: mysql
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - image: mysql:5.6
        name: mysql
        env:
          # Use secret in real usage
        - name: MYSQL_ROOT_PASSWORD
          value: password
        ports:
        - containerPort: 3306
          name: mysql
        volumeMounts:
        - name: mysql-persistent-storage
          mountPath: /var/lib/mysql
      volumes:
      - name: mysql-persistent-storage
        persistentVolumeClaim:
          claimName: mysql-pv-claim
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
              - matchExpressions:
                - key: nodetype
                  operator: In
                  values:
                  - db

spec-template-spec 하위의 containers, volumes는 기존에 있던 내용들이고, 그 아래에 affinity를 추가해 준다.

(최상위 spec가 아니다. template 내의 spec 하위에 추가해야 한다)

matchExpressions에 nodetype, 그리고 value에 db를 지정해주면 끝

1
2
3
4
5
6
7
hhr-master@hhrmaster:~/Desktop/MySQL$ kubectl apply -f mysql-deployment.yaml
service/mysql unchanged
deployment.apps/mysql configured
hhr-master@hhrmaster:~/Desktop/MySQL$ kubectl get pods -o wide
NAME                     READY   STATUS    RESTARTS   AGE     IP          NODE               NOMINATED NODE   READINESS GATES
mysql-64794b64d4-kzv9t   1/1     Running   0          8s      10.36.0.1   hhrworker2   <none>           <none>
mysql-client             0/1     Error     0          2d18h   10.36.0.1   hhrworker2   <none>           <none>

바뀐 정보를 apply해준 뒤 확인해보면 다시 hhrworker2 노드에 할당되었다!