영어로 배우는 Cluster API: KubeVirt 위에 클러스터 찍어 내기
Your first management cluster: clusterctl init
목표
k3s 한 대를 Cluster API 의 관리 클러스터(management cluster)로 만듭니다. 프로바이더 넷의 판과 contract 를 읽고, 컨트롤러가 얼마나 동시에 reconcile 하는지 로그에서 찾고, 워크로드 클러스터 매니페스트를 만들어 둡니다. 마지막으로 오늘 한 일을 영어 진행 보고로 씁니다.
왜 중요한가
Cluster API 는 "클러스터를 만드는 일" 자체를 쿠버네티스 오브젝트로 바꿉니다. 그래서 클러스터를 만들고 고치는 쪽(관리 클러스터)이 따로 있어야 하고, 그 안에서 core·bootstrap·control-plane·infrastructure 네 종류의 컨트롤러가 각자 자기 오브젝트를 맡습니다. 어느 컨트롤러가 무엇을 맡는지 알아야 나중에 "Machine 이 왜 안 생기지" 를 볼 때 어느 로그를 열지 압니다. 이 코스는 그 과정에서 실제로 찍히는 영어 표현을 함께 익힙니다.
🏓 티티: 오늘의 영어 한 줄은 "The management cluster has been initialized successfully." 입니다. 2단계가 끝나면 화면에서 직접 찾아보세요!
단계
- Check that KubeVirt is ready to run VMs. 관리 클러스터의 KubeVirt 상태를 읽어
/root/capi/m1/kubevirt.json에version(KubeVirt CR 의 status.observedKubeVirtVersion),phase(status.phase),kvm_allocatable(노드 allocatable 의devices.kubevirt.io/kvm값, 화면에 보이는 문자열 그대로)을 적으세요. clusterctl init으로 이 k3s 를 관리 클러스터(management cluster)로 만드세요. 판은 core·bootstrap·control-plane 모두v1.14.3, infrastructure 는kubevirt:v0.11.2로 못 박고, 출력 전체를/root/capi/m1/init.log에 남깁니다. 끝나면 로그에Your management cluster has been initialized successfully!가 있고, 프로바이더 넷이 각자의 네임스페이스에 떠 있어야 합니다.- 설치된 프로바이더를 정리해
/root/capi/m1/providers.json에 적으세요. 키는CoreProvider,BootstrapProvider,ControlPlaneProvider,InfrastructureProvider이고 값은 각 Provider 오브젝트의 판입니다. 여기에infra_api_version(KubevirtCluster CRD 가 저장에 쓰는 API 판, 예:group/version꼴)과contract_labels(그 CRD 의 라벨 가운데cluster.x-k8s.io/v로 시작하는 키의 정렬된 목록)를 더합니다. - core 컨트롤러(capi-system 의 capi-controller-manager)가 뜰 때 남긴
Starting workers로그 줄을 읽고, 컨트롤러 이름(controller=값)마다worker count를/root/capi/m1/workers.json에{"machine": 10, ...}꼴로 적으세요. 로그에 나온 컨트롤러는 빠짐없이 적어야 합니다. controllerKind 가 아니라 controller 이름을 키로 쓰는 이유도 로그에서 찾아보세요(같은 Kind 를 보는 컨트롤러가 둘인 경우가 있습니다). - KubeVirt 기본 클러스터 템플릿이 요구하는 변수를 확인하세요.
clusterctl generate cluster capi-demo --infrastructure kubevirt:v0.11.2 --list-variables의 Required Variables 목록을 한 줄에 하나씩, 정렬해서/root/capi/m1/required-vars.txt에 적습니다. - 워크로드 클러스터 매니페스트를 만들어
/root/capi/m1/capi-demo.yaml에 저장하세요(적용은 하지 않습니다). 클러스터 이름capi-demo, 네임스페이스default, 쿠버네티스v1.34.1, 컨트롤 플레인 1대·워커 1대, 노드 디스크 이미지quay.io/capk/ubuntu-2404-container-disk:v1.34.1, CRI 소켓/var/run/containerd/containerd.sock입니다. - 오늘 한 일을 팀 채널에 올리는 영어 진행 보고로
/root/capi/m1/standup.md에 쓰세요. 문법은 채점하지 않고 정보만 봅니다. 반드시 들어갈 것: 무엇을 했는지(management cluster와clusterctl init), 판 두 개(v1.14.3,v0.11.2), 다음에 할 일을 밝히는Next:로 시작하는 줄 하나, 그리고 막힌 것이 있는지 밝히는Blockers:로 시작하는 줄 하나. 글은 영어로(라틴 문자 90% 이상), 전체 25단어 이상 쓰세요.
참고
- 준비된 것: k3s(관리 클러스터), cert-manager, KubeVirt v1.9.0, clusterctl v1.14.3. 작업 자리는
/root/capi/m1입니다. - clusterctl 은 보통 GitHub API 로 프로바이더 파일을 찾는데, API 는 IP 하나당 시간당 60번만 받아 줍니다. 이 VM 은 같은 파일을 미리 받아 두고
~/.config/cluster-api/clusterctl.yaml이 그 파일을 가리킵니다. 폐쇄망에서 쓰는 방법과 같습니다. - 흔한 실수: 판을 적지 않고
clusterctl init --infrastructure kubevirt만 치는 것. 오늘 최신이 내일 최신이 아니라 같은 명령이 다른 결과를 냅니다. - 흔한 실수: 6단계에서 만든 YAML 을 바로 적용하는 것. 이 VM 은 4 GiB 라 워크로드 클러스터 노드를 띄울 자리가 없습니다. 적용은 2모듈의 8 GiB VM 에서 합니다.
- 문서: The Cluster API Book: Quick Start · clusterctl init · Provider contracts
KubeVirt is deployed
Check that KubeVirt is ready to run VMs. 관리 클러스터의 KubeVirt 상태를 읽어 /root/capi/m1/kubevirt.json 에 version(KubeVirt CR 의 status.observedKubeVirtVersion), phase(status.phase), kvm_allocatable(노드 allocatable 의 devices.kubevirt.io/kvm 값, 화면에 보이는 문자열 그대로)을 적으세요.
KubeVirt 는 operator 가 KubeVirt 라는 사용자 정의 자원 하나를 보고 나머지(virt-api, virt-controller, virt-handler)를 세웁니다. kubectl -n kubevirt get kv kubevirt -o yaml 의 status 를 보세요. KVM 장치가 노드에 광고되어 있어야 VM 이 소프트웨어 에뮬레이션이 아니라 하드웨어 가속으로 뜹니다. 노드의 allocatable 은 kubectl get node -o json 으로 볼 수 있습니다.
Initialize the management cluster
clusterctl init 으로 이 k3s 를 관리 클러스터(management cluster)로 만드세요. 판은 core·bootstrap·control-plane 모두 v1.14.3, infrastructure 는 kubevirt:v0.11.2 로 못 박고, 출력 전체를 /root/capi/m1/init.log 에 남깁니다. 끝나면 로그에 Your management cluster has been initialized successfully! 가 있고, 프로바이더 넷이 각자의 네임스페이스에 떠 있어야 합니다.
clusterctl init 은 프로바이더마다 --core, --bootstrap, --control-plane, --infrastructure 에 이름:판 을 받습니다. 판을 적지 않으면 최신 판을 고르는데, 그러면 오늘과 내일의 결과가 달라질 수 있습니다. --wait-providers 를 주면 컨트롤러가 뜰 때까지 기다립니다. 이 VM 의 clusterctl 은 GitHub API 대신 로컬 저장소(~/.config/cluster-api/clusterctl.yaml)에서 프로바이더 파일을 읽습니다.
Read the provider contract
설치된 프로바이더를 정리해 /root/capi/m1/providers.json 에 적으세요. 키는 CoreProvider, BootstrapProvider, ControlPlaneProvider, InfrastructureProvider 이고 값은 각 Provider 오브젝트의 판입니다. 여기에 infra_api_version(KubevirtCluster CRD 가 저장에 쓰는 API 판, 예: group/version 꼴)과 contract_labels(그 CRD 의 라벨 가운데 cluster.x-k8s.io/v 로 시작하는 키의 정렬된 목록)를 더합니다.
clusterctl 은 설치한 것을 Provider 라는 오브젝트로 남깁니다(kubectl get providers -A). core 가 인프라 프로바이더의 API 판을 찾는 방법이 CRD 라벨입니다. kubectl get crd kubevirtclusters.infrastructure.cluster.x-k8s.io -o yaml 의 metadata.labels 와 spec.versions 가운데 storage: true 인 판을 보세요. 라벨 키가 contract 판이고 값이 그 contract 에 맞는 프로바이더 API 판입니다.
Starting workers
core 컨트롤러(capi-system 의 capi-controller-manager)가 뜰 때 남긴 Starting workers 로그 줄을 읽고, 컨트롤러 이름(controller= 값)마다 worker count 를 /root/capi/m1/workers.json 에 {"machine": 10, ...} 꼴로 적으세요. 로그에 나온 컨트롤러는 빠짐없이 적어야 합니다. controllerKind 가 아니라 controller 이름을 키로 쓰는 이유도 로그에서 찾아보세요(같은 Kind 를 보는 컨트롤러가 둘인 경우가 있습니다).
controller-runtime 으로 만든 컨트롤러는 시작할 때 Starting EventSource → Starting Controller → Starting workers 순서로 로그를 남깁니다. worker count 는 그 컨트롤러가 동시에 reconcile 하는 오브젝트 수(concurrency)입니다. kubectl -n capi-system logs deploy/capi-controller-manager | grep 'Starting workers' 로 시작해 보세요.
Required variables
KubeVirt 기본 클러스터 템플릿이 요구하는 변수를 확인하세요. clusterctl generate cluster capi-demo --infrastructure kubevirt:v0.11.2 --list-variables 의 Required Variables 목록을 한 줄에 하나씩, 정렬해서 /root/capi/m1/required-vars.txt 에 적습니다.
템플릿은 ${VAR} 자리표시자가 든 YAML 이고, clusterctl 이 환경 변수로 그 자리를 채웁니다. --list-variables 는 채우지 않고 목록만 보여 줍니다. Optional 은 기본값이 있는 변수입니다. 목록 앞의 - 와 들여쓰기는 빼고 이름만 적습니다.
Generate, but do not apply
워크로드 클러스터 매니페스트를 만들어 /root/capi/m1/capi-demo.yaml 에 저장하세요(적용은 하지 않습니다). 클러스터 이름 capi-demo, 네임스페이스 default, 쿠버네티스 v1.34.1, 컨트롤 플레인 1대·워커 1대, 노드 디스크 이미지 quay.io/capk/ubuntu-2404-container-disk:v1.34.1, CRI 소켓 /var/run/containerd/containerd.sock 입니다.
5단계에서 찾은 Required 변수는 환경 변수로 주고, 개수·판·네임스페이스는 --control-plane-machine-count, --worker-machine-count, --kubernetes-version, --target-namespace 플래그로 줍니다. 결과는 Cluster, KubevirtCluster, KubeadmControlPlane, MachineDeployment 등 여러 문서가 이어진 YAML 입니다. 채점기는 이 파일만 읽고 클러스터에는 아무것도 없어야 합니다.
Write a stand-up update in English
오늘 한 일을 팀 채널에 올리는 영어 진행 보고로 /root/capi/m1/standup.md 에 쓰세요. 문법은 채점하지 않고 정보만 봅니다. 반드시 들어갈 것: 무엇을 했는지(management cluster 와 clusterctl init), 판 두 개(v1.14.3, v0.11.2), 다음에 할 일을 밝히는 Next: 로 시작하는 줄 하나, 그리고 막힌 것이 있는지 밝히는 Blockers: 로 시작하는 줄 하나. 글은 영어로(라틴 문자 90% 이상), 전체 25단어 이상 쓰세요.
진행 보고(stand-up update)는 Done / Next / Blockers 세 칸이 기본입니다. 짧은 평서문으로, 판 번호와 명령처럼 확인할 수 있는 사실을 넣으면 읽는 사람이 다시 묻지 않습니다. 막힌 것이 없으면 Blockers: none. 이라고 적는 것이 관례입니다.