이번 글에서는 pod의 고가용성을 고려하기 위해 topologySpreadConstraints를 사용하고자 합니다. topologySpreadConstraints를 사용하게 되면 ap-northeast-2a와 ap-northeast-2b를 사용한다고 가정했을 때 deployment에서 pod를 2개를 띄우게 되면 각각 가용영역마다 하나씩 뜨게 됩니다.
Deployment 작성
아래와 같이 topologyKey에 node에 존재하는 label을 추가합니다. 여러 값들이 존재하지만 저는 고가용성으로 생성할 예정이기에 zone을 기준으로 생성하겠습니다.
# nginx-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 10
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: nginx
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
파일을 생성 후 저장하시고, 아래 명령어를 사용하여 배포합니다.
kubectl apply -f nginx-deploy.yaml
배포 후 아래 명령어를 사용하여 원하는 대로 생성되었는지 확인합니다.
NODE 부분에 보시면 정확히 5대씩 나눠졌습니다.
kubectl get pod -o wide
output:
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-deployment-6c7df77db4-78zg4 1/1 Running 0 18s 172.31.26.208 ip-172-31-25-59.ap-northeast-2.compute.internal <none> <none>
nginx-deployment-6c7df77db4-dgx24 1/1 Running 0 19s 172.31.24.59 ip-172-31-25-59.ap-northeast-2.compute.internal <none> <none>
nginx-deployment-6c7df77db4-fclnc 1/1 Running 0 19s 172.31.24.23 ip-172-31-25-59.ap-northeast-2.compute.internal <none> <none>
nginx-deployment-6c7df77db4-kbshz 1/1 Running 0 18s 172.31.17.179 ip-172-31-25-59.ap-northeast-2.compute.internal <none> <none>
nginx-deployment-6c7df77db4-nscvs 1/1 Running 0 19s 172.31.19.17 ip-172-31-25-59.ap-northeast-2.compute.internal <none> <none>
nginx-deployment-6c7df77db4-r6pwn 1/1 Running 0 19s 172.31.15.7 ip-172-31-14-2.ap-northeast-2.compute.internal <none> <none>
nginx-deployment-6c7df77db4-s9qlg 1/1 Running 0 19s 172.31.9.69 ip-172-31-14-2.ap-northeast-2.compute.internal <none> <none>
nginx-deployment-6c7df77db4-tw24z 1/1 Running 0 19s 172.31.4.162 ip-172-31-14-2.ap-northeast-2.compute.internal <none> <none>
nginx-deployment-6c7df77db4-x9vcv 1/1 Running 0 19s 172.31.6.49 ip-172-31-14-2.ap-northeast-2.compute.internal <none> <none>
nginx-deployment-6c7df77db4-xhv76 1/1 Running 0 18s 172.31.10.34 ip-172-31-14-2.ap-northeast-2.compute.internal <none> <none>
문제 발생
처음 apply를 하게 되면 정상적으로 작동하지만, 만약 deployment가 재시작이 된다면 아래와 같이 5대씩이 아닌 6대 4대로 생성될 수 있습니다.
kubectl get pod -o wide
output:
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-deployment-854cb85c4f-2wqck 1/1 Running 0 55s 172.31.5.183 ip-172-31-14-2.ap-northeast-2.compute.internal <none> <none>
nginx-deployment-854cb85c4f-2x9th 1/1 Running 0 52s 172.31.5.41 ip-172-31-14-2.ap-northeast-2.compute.internal <none> <none>
nginx-deployment-854cb85c4f-dn9qc 1/1 Running 0 55s 172.31.19.84 ip-172-31-14-2.ap-northeast-2.compute.internal <none> <none>
nginx-deployment-854cb85c4f-dsbxv 1/1 Running 0 55s 172.31.19.233 ip-172-31-25-59.ap-northeast-2.compute.internal <none> <none>
nginx-deployment-854cb85c4f-gq544 1/1 Running 0 52s 172.31.23.166 ip-172-31-25-59.ap-northeast-2.compute.internal <none> <none>
nginx-deployment-854cb85c4f-jclrt 1/1 Running 0 55s 172.31.10.152 ip-172-31-14-2.ap-northeast-2.compute.internal <none> <none>
nginx-deployment-854cb85c4f-vf9rl 1/1 Running 0 55s 172.31.25.57 ip-172-31-25-59.ap-northeast-2.compute.internal <none> <none>
nginx-deployment-854cb85c4f-wd825 1/1 Running 0 52s 172.31.5.216 ip-172-31-14-2.ap-northeast-2.compute.internal <none> <none>
nginx-deployment-854cb85c4f-wl48j 1/1 Running 0 52s 172.31.27.61 ip-172-31-25-59.ap-northeast-2.compute.internal <none> <none>
nginx-deployment-854cb85c4f-wtw6g 1/1 Running 0 51s 172.31.4.87 ip-172-31-14-2.ap-northeast-2.compute.internal <none> <none>
위 같은 상황을 방지하기 위해서 matchLabelKeys에 pod-template-hash라는 값을 넣어줍니다. 이 값은 생성되는 pod의 hash 값으로 바뀔 수 없으며 재생성시 변경됩니다. 이 값을 이용하게 되면 재생성이 되어도 완벽한 고가용성이 됩니다.
# nginx-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 10
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: nginx
matchLabelKeys:
- pod-template-hash
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
마무리
이렇게 해서 topologySpreadConstraints를 사용하여 완벽한 고가용성을 구성하였습니다. 어렵지 않은 내용이며 제가 구성한 방법 말고 여러 방법이 존재하니 공부를 하시면 좋을 거 같습니다. 제 글을 여기까지입니다 읽어주셔서 감사합니다.
'Kubernetes' 카테고리의 다른 글
| [Kubernetes] 여러 Kubernetes 네임스페이스에서 단일 ALB Ingress 사용하기 (0) | 2025.02.16 |
|---|---|
| [Kubernetes] Kubernetes Mutating Webhook을 이용한 Sidecar 자동 주입 가이드 (0) | 2025.02.14 |
| [Kubernetes] EKS 클러스터에 ReadOnly 및 Admin 권한 설정하기 (0) | 2025.02.14 |