개념
이 레슨은 읽는 레슨이 아니다
레슨 1~9 는 관점을 다뤘다. 제어 평면과 데이터 평면, 비동기 수렴, conditions, GitOps 동기화 판정, GPU 진단, 추론 지표, 장애 주입. 그 관점들의 공통 전제가 하나 있다 — 실제로 돌려 본 적이 있어야 감각이 생긴다.
문제는 환경이다. Private Cloud 도, GPU 클러스터도, 사내 플랫폼도 개인이 만들 수 없다. 그래서 이 분야는 "일을 해 봐야 배울 수 있는데, 배워야 일을 받는" 순환에 갇히기 쉽다.
이 레슨은 그 순환을 끊는다. 노트북 한 대에서 돌아가는 환경으로, 이 모듈의 핵심 기법 세 가지를 실제로 작동시킨다.
- 상태 모델을 판정 기준으로 쓰기 — 허용 경로와 금지 전이를 코드로 검사
- 수렴을 기다리는 폴링 — 고정 대기(sleep) 를 쓰지 않는 방법
- 스냅샷 전후 비교 — 시험이 남긴 리소스를 잡아내기
세 가지 모두 Kubernetes 에서 익히면 OpenStack 이나 사내 플랫폼으로 그대로 옮겨진다. 대상 API 는 바뀌지만 기법은 같다.
왜 kind 인가 — 그리고 한계
kind(Kubernetes IN Docker) 는 Docker 컨테이너를 노드로 써서 클러스터를 만드는
도구다. 공개 문서가 설명하는 설정 파일의 최소 형태는 kind: Cluster 와
apiVersion: kind.x-k8s.io/v1alpha4 를 지정하는 것이고, 노드 역할을 나열해
다중 노드 클러스터 를 만들 수 있다. 현재 지원 apiVersion, 설치 방법,
설정 항목은 kind 공식 문서에서 확인한다(원문 확인) — 버전에 따라 바뀌는 부분이다.
QA 실습에 kind 가 적합한 이유는 셋이다.
- 노드를 여러 개 만들 수 있다. 스케줄링, 노드 격리(cordon·drain), 노드 장애를 흉내 낼 수 있다. 단일 노드 환경으로는 못 하는 실습이다
- 클러스터를 버리고 다시 만드는 비용이 거의 없다. 기준선 상태로 되돌리는 것이 쉬워 반복 실습에 적합하다
- 제어 평면 구성 요소가 컨테이너로 보인다. 제어 평면을 일부러 멈춰 보는 실습이 가능하다(레슨 7 의 장애 주입 발상)
한계도 분명히 해 둔다. kind 에서 확인할 수 없는 것이 많다.
| 확인 가능 | 확인 불가 |
|---|---|
| 상태 전이·conditions·이벤트 | 실제 네트워크 지연·대역폭 특성 |
| 쿼터·권한·네임스페이스 격리 | 하드웨어 수준 격리와 장치 통과 |
| 컨트롤러 동작과 수렴 | GPU·고속 스토리지 성능 |
| 리소스 정리 누락 | 대규모 노드 수에서의 제어 평면 부하 |
| 매니페스트 적용 흐름·GitOps 동기화 | 실제 다중 테넌트 운영의 간섭 |
그래서 kind 랩의 목적은 성능 측정이 아니라 기법 숙달 이다. "이 환경에서 성능을 재서 보고한다" 는 결론으로 가면 틀린 결론이 된다. 이 구분은 모듈 62 레슨 3(시뮬레이터가 대체하지 못하는 것) 과 모듈 63 레슨 4(호스트와 대상의 차이) 에서 다룬 원칙과 같다.
랩 0단계 — 기준선을 먼저 만든다
실습에서 가장 많이 건너뛰는 단계이고, 건너뛰면 모든 비교가 무의미해진다.
[기준선(baseline) 이 없을 때]
시험 실행 → "리소스가 3개 남았네?" → 원래 몇 개였는지 모름 → 판정 불가
[기준선이 있을 때]
스냅샷 A 저장 → 시험 실행 → 스냅샷 B 저장 → A·B 차분 → 남은 것이 정확히 보인다기준선은 "시험 전 상태" 를 기계가 읽을 수 있는 형태로 저장한 것 이다. 사람이 눈으로 본 것은 기준선이 아니다.
클러스터에서 기준선으로 담을 것은 이렇다.
- 노드 목록과 각 노드의
Ready상태 - 네임스페이스 목록
- 네임스페이스별 리소스 수(파드·서비스·PVC·시크릿·컨피그맵 등)
PersistentVolume목록과 각 상태- 클러스터 범위 리소스(ClusterRole·CRD 등) 목록
기법 1 — 상태 모델을 판정 기준으로 쓰기
레슨 2 에서 선언형 상태와 conditions 를 다뤘다. 여기서는 그것을 검사 코드 로 옮긴다.
Kubernetes 리소스의 상태는 대개 status.conditions 배열로 노출된다. 각 조건에는
type, status, reason, message, 그리고 전이 시각이 담긴다. QA 가 판정에
쓸 수 있는 것이 이 구조다.
판정 기준을 세 축으로 쓴다.
축 1 — 최종 상태. 정해진 시간 안에 원하는 조건이 True 가 되는가.
축 2 — 허용된 경로. 중간에 거친 상태가 허용 목록 안에 있는가. 이것을 확인하려면 이벤트와 조건 전이를 수집 해야 한다. 한 번만 보면 최종 상태만 알 수 있다.
축 3 — 금지 전이. 일어나서는 안 되는 전이가 없었는가.
예 — 사용자 조작 없이 Ready=True 에서 Ready=False 로 돌아가기,
준비 완료 후 재시작 횟수가 올라가기.
축 2 와 3 이 QA 가 기여하는 지점이다. 개발자가 쓰는 검사는 대개 축 1 에서 멈춘다. "결국 됐다" 와 "제대로 됐다" 는 다르다 — 중간에 한 번 실패하고 재시도로 성공한 것은 축 1 에서는 통과이고 축 3 에서는 결함일 수 있다.
기법 2 — 폴링을 제대로 쓰기
인프라 검증에서 가장 흔한 나쁜 코드가 고정 대기 다.
[나쁜 코드]
apply 후 sleep 60 → 상태 확인
문제 1: 환경이 느리면 60초로 부족 → 간헐 실패(flaky)
문제 2: 환경이 빠르면 55초를 낭비 → 전체 시험이 느려짐
문제 3: 왜 60인지 설명할 수 없다 → 근거 없는 기준
[옳은 코드]
apply 후 "조건이 충족될 때까지" 폴링, 상한 시간과 함께
- 충족되면 즉시 진행 (빠르다)
- 상한까지 안 되면 실패 (근거 있는 기준)
- 실패 시 그 시점의 상태·이벤트를 함께 남긴다 (진단 가능)kubectl 에는 조건 대기 기능이 있다. 공개 문서가 설명하는 형태는
kubectl wait --for=condition=<조건> <리소스> 이고 --timeout 으로 상한을 준다.
지원하는 --for 표현과 옵션은 사용 중인 버전의 kubectl wait 문서에서
확인한다(원문 확인) — 버전에 따라 표현이 늘어난 부분이 있다.
도구가 제공하는 대기로 충분하지 않을 때(사내 플랫폼 API, 복합 조건, 전이 이력 수집) 는 직접 폴링을 쓴다. 직접 쓸 때 반드시 들어가야 하는 다섯 요소다.
| 요소 | 왜 필요한가 |
|---|---|
| 상한 시간(timeout) | 무한 대기를 막고, 기준을 명시한다 |
| 폴링 간격 | 너무 짧으면 API 서버에 부하, 너무 길면 전이를 놓친다 |
| 즉시 실패 조건 | 되돌릴 수 없는 실패 상태면 상한까지 기다릴 필요가 없다 |
| 실패 시 상태 덤프 | 타임아웃 메시지만으로는 원인을 알 수 없다 |
| 전이 기록 | 축 2·3 판정에 쓰인다 |
세 번째 요소가 실무에서 큰 차이를 만든다. 리소스가 Failed 로 떨어졌는데
상한 10분을 다 기다리면, 시험 100건에서 수 시간이 날아간다. 즉시 실패 조건을
넣으면 몇 초에 끝난다.
상한 시간의 근거 도 적어 둔다. "경험적으로 60초" 가 아니라 "이 환경에서 측정한 수렴 시간 분포의 상위값 + 여유" 로 정하고, 그 측정 결과를 남긴다. 근거가 있으면 환경이 바뀔 때 다시 계산할 수 있다.
기법 3 — 스냅샷 전후 비교로 누수 잡기
이 모듈의 첫 문장이 "인프라 플랫폼의 결함은 수렴하지 않는 상태와 남은 리소스로 드러난다" 였다. 남은 리소스를 잡는 방법이 스냅샷 비교다.
흐름은 단순하다.
스냅샷 A (시험 전)
↓
시험 실행 (리소스를 만들고, 쓰고, 지운다)
↓
정리 완료 대기 (여기서도 폴링 — 즉시 사라지지 않는다)
↓
스냅샷 B (시험 후)
↓
차분: B - A = 남은 것 / A - B = 사라진 것(있으면 더 심각)"A - B" 를 보는 것이 중요하다. 시험이 기존 리소스를 지워 버린 경우이고, 남은 리소스보다 훨씬 심각한 결함이다. 많은 팀이 "남은 것" 만 확인한다.
스냅샷 비교에서 다룰 세 가지 어려움이 있다.
1) 노이즈. 상태 필드, 타임스탬프, 리소스 버전, 자동 생성 토큰처럼 시험과 무관하게 바뀌는 항목 이 차분에 섞인다. 비교 전에 제외 규칙을 정한다. 제외 규칙을 문서로 두고, 무엇을 왜 제외했는지 적는다 — 제외 규칙이 과하면 결함을 못 보게 된다.
2) 비동기 정리. 리소스는 삭제 요청 즉시 사라지지 않는다. 종료 유예 기간이 있고, 종료자(finalizer) 가 붙어 있으면 더 오래 걸린다. "정리 완료" 를 폴링으로 확인한 뒤 스냅샷 B 를 찍는다. 이걸 안 하면 매번 "남은 리소스 있음" 이 나와 검사가 신뢰를 잃고, 결국 아무도 보지 않게 된다.
3) 소유 관계. 어떤 리소스는 다른 리소스가 만든 것이다. 상위 리소스를 지우면 하위가 따라 지워져야 한다. 차분에서 "하위만 남은 경우" 를 찾는 것이 소유 관계 결함을 잡는 방법이다.
OpenStack 올인원 — 선택지와 비용
레슨 3 에서 OpenStack 검증을 다뤘고, 그것도 손으로 해 보고 싶을 수 있다. 올인원 개발 환경을 구성하는 공개 수단이 있다(개발용 설치 스크립트 방식이 대표적). 설치 방법, 지원 운영체제와 버전, 필요 사양, 설정 파일 형식은 해당 프로젝트의 공식 문서에서 확인한다(원문 확인) — 이 영역은 변화가 빠르다.
다만 kind 와 비교해 비용 구조가 다르다 는 점을 알고 시작해야 한다.
| kind | OpenStack 올인원 | |
|---|---|---|
| 준비 시간 | 분 단위 | 시간 단위(설치·빌드) |
| 자원 요구 | 가벼움 | 메모리·디스크 요구가 큼 |
| 되돌리기 | 클러스터 삭제·재생성이 빠름 | 재설치가 비쌈 → 스냅샷 전략 필요 |
| 깨짐 빈도 | 낮음 | 환경 조건에 민감 |
실무적 권고는 이렇다. 기법 숙달은 kind 에서 하고, OpenStack 올인원은 "레슨 3 의 도구를 한 번 실행해 보는" 목적으로 제한한다. Tempest 같은 표준 도구를 실제로 돌려 보고, 포함·제외 목록이 어떻게 동작하는지 확인하는 정도로 목표를 좁히면 투자 대비 효과가 있다. 올인원 환경에서 성능이나 업그레이드를 검증하겠다는 목표는 비현실적이다.
그리고 가상 머신에 격리해서 올린다. 올인원 설치 스크립트는 호스트 설정을 광범위하게 바꾸므로, 개인 작업 환경에 직접 설치하지 않는다.
랩에서 얻은 것을 실무로 옮기기
이 랩의 최종 산출물은 클러스터가 아니라 재사용 가능한 검증 코드와 문서 다. 실무에 들어갔을 때 옮겨 갈 수 있는 형태로 만든다.
- 스냅샷 수집·비교 스크립트 — 대상 API 만 바꾸면 다른 플랫폼에 쓰인다
- 폴링 헬퍼 — 다섯 요소를 갖춘 대기 함수. 사내 플랫폼 API 에 그대로 적용
- 상태 모델 판정 기준서 — 허용 경로·금지 전이를 적는 양식
- 제외 규칙 문서 — 무엇을 왜 노이즈로 뒀는가
- 상한 시간 근거 기록 — 측정된 수렴 시간 분포
면접과 포트폴리오에서도 이쪽이 쓰인다. "Kubernetes 를 공부했습니다" 보다 "다중 노드 kind 클러스터에서 상태 전이 금지 조건을 검사하고, 스냅샷 차분으로 리소스 누수를 잡는 스크립트를 만들었습니다" 가 다르게 들린다.
실무에서 왜 필요한가
인프라 플랫폼 QA 채용에서 가장 큰 장벽이 환경 접근성 이다. 공고는 Kubernetes· OpenStack·GPU 플랫폼 경험을 요구하는데, 그 경험은 해당 조직에 들어가야 생긴다. 그래서 지원자 대부분이 문서로 읽은 지식 만 갖고 면접에 온다.
면접에서 그 차이가 바로 드러나는 질문이 있다. "비동기로 생성되는 리소스를 어떻게 검증하십니까." 읽기만 한 사람은 "상태가 ACTIVE 가 되는지 확인합니다" 라고 답한다. 해 본 사람은 고정 대기를 쓰지 않는 이유, 즉시 실패 조건, 실패 시 상태 덤프, 상한 시간의 근거 를 말한다. 이 차이는 kind 클러스터에서 한 주 실습하면 생긴다.
그리고 실무에 들어간 뒤에도 이 랩이 쓰인다. 사내 플랫폼의 시험 코드를 고칠 때, 먼저 kind 에서 기법을 검증해 보고 옮기는 것 이 안전하다. 운영 환경에서 실험하면 영향 범위를 통제하기 어렵다.
가장 실질적인 가치는 간헐 실패를 줄이는 역량 이다. 인프라 시험은 간헐 실패가 많고, 그 대부분이 고정 대기와 정리 미완료 에서 온다. 이 두 원인을 아는 사람이 시험 묶음을 고치면 실패율이 눈에 띄게 떨어지고, 그 성과는 조직에서 즉시 인정된다.