AKS 클러스터 상에서 Bookinfo 샘플 애플리케이션을 배포하여 다음 테스트를 진행하고자 한다.
- Ingress Add-on 방식의 외부 노출 테스트
- Topology Spread Constraints 적용 및 zone 장애 대응 실험
구성 요소
Namespace | bookinfo | 앱 리소스를 분리 배포하기 위한 전용 네임스페이스 |
Service | productpage, reviews, ratings, details | 각 마이크로서비스 간 통신용 클러스터 내부 서비스 |
Deployment | 각 서비스별 버전 (v1~v3) | 실제 실행되는 앱 Pod를 정의 |
Ingress | bookinfo-ingress | productpage를 외부에 노출 (webapprouting.kubernetes.azure.com) |
Ingress Host | bookinfo.xxx.nip.io | .nip.io 도메인을 활용한 외부 접근 URL |
외부 접근 방법
Ingress Type | AKS Web App Routing Add-on (nginx) |
External IP | xxx |
Hostname | bookinfo.xxx.nip.io |
테스트 명령어 | curl http://bookinfo.xxx.nip.io |
공식 문서(Topology Spread Constraints - Kubernetes)를 기반으로, 지금 Bookinfo 앱에 Topology Spread Constraints를 적용해보고자 한다.
Topology Spread Constraints 구성 설명
필드 설명
maxSkew | 가장 많은 zone과 가장 적은 zone 간 Pod 수 차이 허용값 |
topologyKey | 기준이 되는 topology 레이블 (예: zone) |
whenUnsatisfiable | 조건 미충족 시 행동 (DoNotSchedule or ScheduleAnyway) |
labelSelector | 이 Spread가 적용될 Pod 셀렉터 조건 |
apiVersion: apps/v1
kind: Deployment
metadata:
name: reviews-v1
labels:
app: reviews
version: v1
spec:
replicas: 1
selector:
matchLabels:
app: reviews
version: v1
template:
metadata:
labels:
app: reviews
version: v1
spec:
containers:
- name: reviews
image: docker.io/istio/examples-bookinfo-reviews-v1:1.20.2
imagePullPolicy: IfNotPresent
env:
- name: LOG_DIR
value: "/tmp/logs"
ports:
- containerPort: 9080
volumeMounts:
- name: tmp
mountPath: /tmp
- name: wlp-output
mountPath: /opt/ibm/wlp/output
volumes:
- name: wlp-output
emptyDir: {}
- name: tmp
emptyDir: {}
replicas: 3 이상이어야 의미있기에 replicas:3 으로 변경합니다.
# nodeSelector:
# - reviews-v1 Pod는 SRE Node Pool에만 배포되도록 제한합니다
#
# topologySpreadConstraints:
# - maxSkew: zone 간 Pod 개수 차이를 1개 이하로 유지합니다
# - topologyKey: "topology.kubernetes.io/zone" 레이블 기준으로 분산합니다
# - whenUnsatisfiable: "DoNotSchedule" → 조건이 안 맞으면 아예 배포하지 않음
# - labelSelector: app=reviews 에만 적용됩니다
apiVersion: apps/v1
kind: Deployment
metadata:
name: reviews-v1
labels:
app: reviews
version: v1
spec:
replicas: 3 # replicas: 3 이상이어야 Topology Spread Constraints 실험 의미 있음
selector:
matchLabels:
app: reviews
version: v1
template:
metadata:
labels:
app: reviews
version: v1
spec:
nodeSelector:
agentpool: sre # SRE Node Pool에만 배포되도록 지정
topologySpreadConstraints:
- maxSkew: 1 # zone 간 최대 1개 차이만 허용
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: reviews
containers:
- name: reviews
image: docker.io/istio/examples-bookinfo-reviews-v1:1.20.2
imagePullPolicy: IfNotPresent
env:
- name: LOG_DIR
value: "/tmp/logs"
ports:
- containerPort: 9080
volumeMounts:
- name: tmp
mountPath: /tmp
- name: wlp-output
mountPath: /opt/ibm/wlp/output
volumes:
- name: wlp-output
emptyDir: {}
- name: tmp
emptyDir: {}
- replicas: 3 으로 설정
- nodeSelector로 sre node pool에만 배포
- topologySpreadConstraints로 zone 간 균등 분산 시도
현재 분포 상태 확인
kubectl get pods -n bookinfo -l app=reviews -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
reviews-v1-84f648c8cb-ds5ct 1/1 Running 0 4m51s 172.20.3.142 aks-sre-57935366-vmss000001 <none> <none>
reviews-v1-84f648c8cb-xnc8w 1/1 Running 0 5m2s 172.20.2.22 aks-sre-57935366-vmss000000 <none> <none>
reviews-v1-84f648c8cb-zpllt 1/1 Running 0 4m40s 172.20.3.215 aks-sre-57935366-vmss000001 <none> <none>
kubectl get nodes -L topology.kubernetes.io/zone,agentpool
NAME STATUS ROLES AGE VERSION ZONE AGENTPOOL
aks-default-34042230-vmss000001 Ready <none> 29h v1.29.7 0 default
aks-devops-17720728-vmss000001 Ready <none> 29h v1.29.7 0 devops
aks-sre-57935366-vmss000000 Ready <none> 6m31s v1.29.7 koreacentral-2 sre
aks-sre-57935366-vmss000001 Ready <none> 6m25s v1.29.7 koreacentral-3 sre
현재 분포 요약
reviews-v1-ds5ct | aks-sre-vmss000001 | koreacentral-3 |
reviews-v1-zpllt | aks-sre-vmss000001 | koreacentral-3 |
reviews-v1-xnc8w | aks-sre-vmss000000 | koreacentral-2 |
특정 zone 노드 장애 시 Pod 재분산 확인
목표
- koreacentral-2 노드 하나 drain 시,
- Pod가 koreacentral-3 로 재스케줄되는지 확인
1. drain 실행
kubectl drain aks-sre-57935366-vmss000000 \
--ignore-daemonsets --delete-emptydir-data --force
주의
- --force 붙이면 system-critical Pod 없음 조건 무시
- --ignore-daemonsets: Cilium 등 데몬셋 영향 무시
- --delete-emptydir-data: emptyDir 볼륨 제거 허용
kubectl get pods -n bookinfo -l app=reviews -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
reviews-v1-84f648c8cb-cbw9r 0/1 Pending 0 55s <none> <none> <none> <none>
reviews-v1-84f648c8cb-ds5ct 1/1 Running 0 10m 172.20.3.142 aks-sre-57935366-vmss000001 <none> <none>
reviews-v1-84f648c8cb-zpllt 1/1 Running 0 10m 172.20.3.215 aks-sre-57935366-vmss000001 <none> <none>
reviews-v2-bdb6df55f-2lkj4 1/1 Running 0 163m 172.20.1.189 aks-devops-17720728-vmss000001 <none> <none>
reviews-v3-8fcb4697f-6j82g 1/1 Running 0 163m 172.20.1.10 aks-devops-17720728-vmss000001 <none> <none>
- zone koreacentral-3: Pod 2개 (남아 있음)
- zone koreacentral-2: Pod 0개
- 새 Pod는 koreacentral-2에만 갈 수 있어야 maxSkew ≤ 1 만족
- 그런데 koreacentral-2 노드는 drain 안 했기 때문에 Pod가 뜨지 못하고 있는 상태는 아님
- 오히려 koreacentral-3 노드가 drain 안 되어 여전히 Pod 2개 유지 중
배포 구성 요약
replicas: 3
nodeSelector:
agentpool: sre
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: ScheduleAnyway
- agentpool: sre → SRE 노드 풀로만 스케줄
- topologyKey: zone → zone 기준 분산
- ScheduleAnyway → 조건 위반 시에도 배포 진행
~ kubectl get pods -n bookinfo -l app=reviews -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
reviews-v1-5d4b6b75f-6cwk2 1/1 Running 0 2m14s 172.20.3.130 aks-sre-57935366-vmss000001 <none> <none>
reviews-v1-5d4b6b75f-cttfl 1/1 Running 0 2m13s 172.20.2.22 aks-sre-57935366-vmss000000 <none> <none>
reviews-v1-5d4b6b75f-n9qvk 1/1 Running 0 2m11s 172.20.2.136 aks-sre-57935366-vmss000000 <none> <none>
특정 zone 장애 시 스케줄링 확인
테스트: koreacentral-2 노드 Drain
kubectl drain aks-sre-57935366-vmss000000 \
--ignore-daemonsets --delete-emptydir-data --force
목적
zone-2 Pod 삭제 시, 나머지 Pod가 조건을 위반하면서도 배포되는지 확인
drain 이후 결과
➜ ~ kubectl get pods -n bookinfo -l app=reviews -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
reviews-v1-5d4b6b75f-6cwk2 1/1 Running 0 3m29s 172.20.3.130 aks-sre-57935366-vmss000001 <none> <none>
reviews-v1-5d4b6b75f-vtwhz 1/1 Running 0 32s 172.20.3.148 aks-sre-57935366-vmss000001 <none> <none>
reviews-v1-5d4b6b75f-w2p7w 1/1 Running 0 32s 172.20.3.108 aks-sre-57935366-vmss000001 <none> <none>
- topologySpreadConstraints는 단순 권장 설정이 아니라, 설정 값에 따라 스케줄링 자체를 결정하는 핵심 조건이 될 수 있음
- maxSkew: 1 은 분산 기준을 엄격히 적용하므로, Pod 간의 위치 차이를 1개 이하로 유지해야 함
- whenUnsatisfiable: ScheduleAnyway 옵션은 조건 위반 시에도 배포를 허용하므로, 장애 대응이나 고가용성 측면에서 유용
- 반면 DoNotSchedule은 시스템 안정성은 확보되지만, 조건이 맞지 않으면 서비스가 멈출 수 있음 → 운영 상황에 따라 전략 선택 필요
항목 | DoNotSchedule | ScheduleAnyway |
조건 위반 시 동작 | ❌ Pod 스케줄 금지 (Pending 발생) | ✅ 조건 위반해도 스케줄 강행 |
maxSkew 기준 적용 여부 | 강제 적용 | 권고 수준 (스케줄은 강행) |
장애 상황 대응력 | 낮음 (서비스 중단 발생 가능) | 높음 (서비스 지속성 확보 가능) |
실험 결과 요약 | Pod 배포 중단 → Pending | 모든 Pod 정상 Running 상태 유지 |
'Kubernetes' 카테고리의 다른 글
Helm 기반 Jenkins 설치 시 InitContainer 실패 원인 분석 및 해결 (0) | 2025.04.01 |
---|---|
k6 + Grafana + Prometheus로 성능 테스트 환경 구축 및 시각화 (0) | 2025.01.17 |
[CI/CD] Argo Rollout을 사용한 Blue/Green 배포 (4) | 2024.10.02 |
CNCF란? Cloud Native란? (0) | 2024.09.25 |
[Docker] Docker 이미지 빌드, 배포, 백업 (0) | 2024.07.25 |