13년차의 서버실

서버, 인프라, 홈랩 기술 블로그

[태그:] ClusterAPI

  • [k8s] Kubeadm vs ClusterAPI: Kubernetes 클러스터 프로비저닝 도구 비교

    [k8s] Kubeadm vs ClusterAPI: Kubernetes 클러스터 프로비저닝 도구 비교

    Kubeadm vs ClusterAPI: Kubernetes 클러스터 프로비저닝 도구 비교

    Kubeadm과 ClusterAPI를 비교할 때, 많은 분들이 같은 지점에서 막혀 있더라고요. “클러스터 하나 빨리 올리면 되는 건가?”, 아니면 “여러 환경에서 반복 가능하게 클러스터 구축 체계를 만들어야 하나?” 같은 고민 말이에요. 저도 홈랩에서 처음엔 kubeadm(쿠버네티스 클러스터 초기화 도구)만으로 시작했었는데, 노드 수가 늘고 재현 가능한 배포가 필요해지니까 Cluster API(CAPI, 쿠버네티스 방식으로 클러스터 자체를 관리하는 프로젝트) 쪽이 갑자기 눈에 들어오더라고요. 처음엔 이게 뭔가 싶었습니다. 컨트롤러도 많고, 프로바이더도 많고, YAML도 길고요. 근데 구조를 한 번 이해하고 나니 왜 운영팀들이 이 조합을 진지하게 보는지 감이 왔습니다.

    이 글에서는 단순히 기능 나열만 하지 않고, Kubeadm vs ClusterAPI를 실제 운영 관점에서 풀어보겠습니다. 쉽게 말해, kubeadm은 클러스터를 시작하게 해주는 공구에 가깝고, ClusterAPI는 클러스터 생애주기 자체를 선언형으로 다루는 운영 프레임워크에 가깝습니다. 여기서 중요한 포인트! 둘은 경쟁 관계이면서도, 실전에서는 같이 엮이는 경우가 꽤 많습니다.

    Kubeadm ClusterAPI 비교를 보여주는 쿠버네티스 클러스터 프로비저닝 아키텍처 이미지

    kubeadm은 개별 클러스터 부트스트랩 흐름에, Cluster API는 관리 클러스터에서 워크로드 클러스터를 선언형으로 제어하는 흐름에 초점이 있습니다.

    Kubernetes 클러스터 프로비저닝, 뭐가 다른가요?

    쉽게 말해 kubeadm은 노드에 들어가서 클러스터를 만드는 도구입니다. 컨트롤 플레인(클러스터 제어 영역) 초기화, 조인 토큰 생성, 인증서 배포 같은 부트스트랩 작업을 잘 해주죠. 반면 Cluster API는 클러스터를 쿠버네티스 리소스처럼 다루는 방식입니다. 즉, “이런 모양의 클러스터를 만들어줘”라고 선언하면 컨트롤러가 그 상태를 맞추려고 움직입니다.

    제가 직접 해보니 kubeadm은 구조가 비교적 단순해서 학습 진입 장벽이 낮았습니다. 특히 베어메탈(가상화 없이 물리 서버 직접 운영)이나 홈랩처럼 손으로 만질 수 있는 환경에서는 진짜 빠릅니다. 반대로 Cluster API는 관리 클러스터(다른 클러스터를 제어하는 클러스터)라는 개념부터 잡아야 해서 초반 허들이 있습니다. 대신 익숙해지면 반복 배포, 업그레이드, 스케일링, 클러스터 폐기까지 흐름이 꽤 깔끔해집니다.

    • kubeadm: 단일 클러스터 프로비저닝에 강함
    • Cluster API: 여러 클러스터의 선언형 운영과 생애주기 관리에 강함
    • CAPI + kubeadm: Cluster API가 kubeadm 기반 부트스트랩을 활용하는 조합이 현실

    Kubeadm vs ClusterAPI 핵심 구조 비교

    비교 항목 kubeadm Cluster API
    주요 목적 쿠버네티스 클러스터 초기 구성 클러스터 생성, 변경, 업그레이드, 삭제까지 생애주기 관리
    운영 방식 명령형(명령 실행 중심) 선언형(원하는 상태 기술)
    주요 실행 위치 대상 노드 관리 클러스터의 컨트롤러
    멀티 클러스터 운영 수동 설계 필요 기본 개념 자체가 멀티 클러스터 친화적
    인프라 연동 직접 구성 필요 Infrastructure Provider(인프라 프로바이더)로 연동
    업그레이드 자동화 운영 스크립트나 절차 설계 필요 버전 선언 후 컨트롤러 기반 롤링 변경 가능
    초기 난이도 상대적으로 낮음 상대적으로 높음

    여기서 중요한 포인트! Cluster API가 kubeadm을 대체하는 느낌으로 보일 수 있는데, 실제로는 Cluster API 안에서 kubeadm bootstrap provider를 사용하는 사례가 많습니다. 즉, kubeadm은 여전히 중요한 구성요소고, Cluster API는 그걸 더 큰 자동화 체계 안에 넣는 느낌이라고 보시면 이해가 편합니다.

    언제 kubeadm이 더 잘 맞을까요?

    • 처음 쿠버네티스 구조를 익히는 단계일 때
    • 노드 수가 적고 클러스터 수가 많지 않을 때
    • 베어메탈이나 제한된 홈랩 환경에서 빠르게 검증할 때
    • 구성 과정을 손으로 제어해야 안심되는 팀 문화일 때

    언제 Cluster API가 빛날까요?

    • 동일한 형태의 클러스터를 반복 생성해야 할 때
    • 개발, 스테이징, 운영 환경을 비슷한 클러스터 구축 템플릿으로 관리할 때
    • 클러스터 업그레이드와 노드 교체를 체계화하고 싶을 때
    • GitOps(Git 기반 선언형 운영)와 잘 엮고 싶을 때

    실전 구현 1: kubeadm으로 클러스터 올리기

    먼저 kubeadm 흐름부터 보겠습니다. 실제로 써보니까 kubeadm은 클러스터 내부 동작을 이해하는 데 정말 좋았습니다. 인증서, kubelet(노드 에이전트), CNI(컨테이너 네트워크 플러그인) 같은 개념이 어디서 필요한지 몸으로 익히게 되거든요. 다만 그만큼 수동 단계도 많습니다. 삽질 좀 했습니다 ㅎㅎ

    1. 런타임(container runtime)과 kubelet, kubeadm, kubectl 설치
    2. 컨트롤 플레인 노드에서 초기화
    3. CNI 설치
    4. 워커 노드 조인
    5. 상태 검증
    sudo kubeadm init \
      --pod-network-cidr=192.168.0.0/16
    
    mkdir -p $HOME/.kube
    sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
    sudo chown $(id -u):$(id -g) $HOME/.kube/config
    
    kubectl get nodes

    초기화가 끝나면 바로 Ready가 안 뜰 수 있습니다. 여기서 당황 많이 하시더라고요. 대부분은 아직 CNI가 없어서 그렇습니다.

    kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/master/manifests/calico.yaml
    kubectl get pods -A

    워커 노드 조인은 `kubeadm token create –print-join-command`로 받은 명령을 그대로 실행하면 됩니다.

    kubeadm token create --print-join-command

    이 방식의 장점은 명확합니다. 어디서 뭐가 실패하는지 눈에 보입니다. 반대로 단점도 명확해요. 같은 클러스터를 세 번, 네 번 반복해서 만들다 보면 사람이 실수할 지점이 계속 생깁니다. 바로 이 지점에서 “클러스터 구축 도구를 더 선언형으로 가져가야 하나?”라는 생각이 들기 시작하더라고요.

    실전 구현 2: Cluster API로 선언형 클러스터 만들기

    이제 Cluster API 쪽입니다. 처음엔 관리 클러스터가 또 필요하다고 해서 부담스러웠는데, 실제 구조를 이해하고 나니 왜 필요한지 납득됐습니다. Cluster API는 몇 가지 핵심 컴포넌트로 나뉩니다.

    • Core Provider: Cluster API 핵심 리소스와 컨트롤러
    • Bootstrap Provider: 노드 초기화 데이터 생성(kubeadm 활용)
    • Control Plane Provider: 컨트롤 플레인 구성 관리
    • Infrastructure Provider: 실제 VM, 인스턴스, 머신, 네트워크 리소스 생성

    기본 흐름은 이렇습니다. 관리 클러스터에 Cluster API 컴포넌트를 설치하고, 그 위에 워크로드 클러스터(실제 애플리케이션이 올라갈 대상 클러스터)의 정의를 YAML로 적용합니다.

    clusterctl init --infrastructure <provider-name>

    프로바이더 이름은 사용하는 환경에 따라 달라집니다. 예를 들어 퍼블릭 클라우드, 프라이빗 클라우드, 베어메탈 쪽에서 선택지가 갈리죠. 여기서는 원리를 이해하는 데 집중하겠습니다.

    Cluster API 관리 클러스터와 워크로드 클러스터 구조를 설명하는 Kubeadm ClusterAPI 비교 이미지

    관리 클러스터에서 컨트롤러가 동작하고, 선언된 리소스를 바탕으로 워크로드 클러스터의 머신과 컨트롤 플레인을 조립하는 구조입니다.

    apiVersion: cluster.x-k8s.io/v1beta1
    kind: Cluster
    metadata:
      name: demo-cluster
    spec:
      controlPlaneRef:
        apiVersion: controlplane.cluster.x-k8s.io/v1beta1
        kind: KubeadmControlPlane
        name: demo-control-plane
      infrastructureRef:
        apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
        kind: GenericInfrastructureCluster
        name: demo-infra
    ---
    apiVersion: controlplane.cluster.x-k8s.io/v1beta1
    kind: KubeadmControlPlane
    metadata:
      name: demo-control-plane
    spec:
      replicas: 1
      version: v1.29.0
      kubeadmConfigSpec:
        clusterConfiguration: {}
        initConfiguration: {}
        joinConfiguration: {}
    ---
    apiVersion: cluster.x-k8s.io/v1beta1
    kind: MachineDeployment
    metadata:
      name: demo-md-0
    spec:
      clusterName: demo-cluster
      replicas: 2
      selector:
        matchLabels: {}
      template:
        spec:
          version: v1.29.0
          clusterName: demo-cluster

    위 YAML은 Cluster API 구조 예시입니다. 실제 배포에서는 인프라 프로바이더 리소스가 더 들어가고, 환경 변수나 자격 증명도 필요합니다. 중요한 건 클러스터를 명령으로 만드는 게 아니라 상태로 선언한다는 점입니다. 이게 Cluster API의 본질이에요.

    kubectl apply -f cluster.yaml
    kubectl get cluster
    kubectl get machinedeployments
    kubectl get machines

    제가 직접 해보니 여기서 재미있는 포인트가 있었습니다. kubeadm은 한 번 만들고 나면 이후 운영 자동화는 별도로 설계해야 하는데, Cluster API는 처음부터 “운영까지 생각한 구조”라는 느낌이 강합니다. 대신 디버깅은 더 추상적입니다. 노드 한 대에서 끝나는 문제가 아니라 컨트롤러, 프로바이더, 템플릿이 다 얽혀 있거든요.

    주의사항과 트러블슈팅: 실제로 많이 막히는 지점

    ⚠️ 여기 진짜 중요합니다. Kubeadm ClusterAPI 비교에서 많은 글이 장점만 말하는데, 실전에서는 막히는 지점이 선택 기준이 되더라고요.

    1. kubeadm은 CNI 전까지 정상처럼 보여도 정상 아닐 수 있습니다

    `kubeadm init`이 끝났다고 클러스터가 다 살아난 건 아닙니다. `kubectl get nodes`에서 `NotReady`가 보이면 CNI부터 의심하세요. 저도 처음엔 인증서 문제인 줄 알고 엉뚱한 로그만 한참 봤었습니다.

    kubectl describe node
    kubectl get pods -A
    journalctl -u kubelet

    2. Cluster API는 실패 지점이 더 분산됩니다

    예를 들어 머신이 안 생기면 인프라 프로바이더 문제인지, bootstrap 데이터 생성 문제인지, control plane reconciliation 문제인지 나눠서 봐야 합니다.

    kubectl get pods -A
    kubectl get clusters,machines,machinedeployments,kubeadmcontrolplanes
    kubectl describe machine <machine-name>
    kubectl logs -n capi-system deployment/capi-controller-manager

    혹시 이런 경험 있으신가요? 리소스는 분명히 생성됐는데 상태가 계속 `Provisioning`에서 안 넘어가는 경우요. 이럴 땐 대부분 인프라 쪽 자격 증명, 이미지 템플릿, 네트워크 전제조건이 빠져 있는 경우가 많았습니다.

    3. kubeadm은 단순한 대신 표준화가 흔들리기 쉽습니다

    운영자가 둘 이상만 돼도 설치 옵션, OS 준비 상태, 네트워크 플러그인 선택이 조금씩 달라집니다. 결국 문서화와 스크립트화가 필수입니다. 즉, kubeadm이 간단하다고 해서 운영 체계까지 단순한 건 아니더라고요.

    4. Cluster API는 관리 클러스터 자체의 안정성이 중요합니다

    관리 클러스터가 흔들리면 워크로드 클러스터 변경 작업도 영향받습니다. 그래서 초기에 “관리 클러스터를 어디에 둘 것인가”를 꽤 신중하게 봐야 합니다. 홈랩에서는 한 대에 몰아넣으면 편하긴 한데, 장애 분리 측면에서는 아쉬움이 남습니다.

    검증과 결과 확인: 뭐가 더 운영 친화적인가

    검증은 단순히 `kubectl get nodes`만 보면 부족합니다. 생성, 변경, 교체, 삭제 흐름까지 봐야 합니다. 이 부분이 Kubernetes 클러스터 프로비저닝 도구를 비교할 때 핵심이거든요.

    1. 클러스터 최초 생성 시간과 절차 복잡도 확인
    2. 워커 노드 확장 방식 확인
    3. 버전 변경 시 운영 개입량 확인
    4. 장애 시 복구 절차 문서화 가능성 확인
    kubectl get nodes -o wide
    kubectl get cluster
    kubectl get machines
    kubectl get events --sort-by=.lastTimestamp
    Kubeadm ClusterAPI 비교 결과를 검증하는 쿠버네티스 상태 확인 이미지

    노드 Ready 상태, Machine 리소스 변화, 이벤트 흐름을 통해 선언한 상태와 실제 상태가 맞아가는지 확인하는 장면을 상상하시면 됩니다.

    실제로 써보니까 결과는 꽤 분명했습니다. 하나의 클러스터를 깊게 이해하고 빠르게 구축하려면 kubeadm이 좋았고, 반복 가능한 다수의 클러스터를 체계적으로 관리하려면 Cluster API가 훨씬 운영 친화적이었습니다. 특히 업그레이드나 머신 교체 시나리오를 생각하면 차이가 더 벌어집니다.

    상황별 선택 가이드: 클러스터 구축 도구 어떤 게 맞을까

    상황 추천 이유
    홈랩에서 쿠버네티스 구조 학습 kubeadm 구성 요소를 직접 체감하기 좋음
    단일 운영 클러스터를 신중하게 수동 관리 kubeadm 절차가 명확하고 제어감이 높음
    여러 환경에 동일한 클러스터 배포 Cluster API 선언형 템플릿 재사용이 쉬움
    업그레이드/교체 자동화를 운영 정책으로 추진 Cluster API 생애주기 관리 철학에 잘 맞음
    베어메탈 자동화까지 포함한 확장 설계 환경에 따라 다름 인프라 프로바이더 성숙도와 운영 역량이 중요
    • 빠른 시작과 학습이 목표면 kubeadm
    • 반복성과 선언형 운영이 목표면 Cluster API
    • 둘 중 하나만 고집할 필요는 없음: kubeadm으로 원리 이해 후 CAPI로 확장하는 경로가 현실적
    Kubeadm ClusterAPI 비교 선택 기준을 정리한 요약 인포그래픽

    팀 규모, 클러스터 수, 자동화 요구사항, 관리 방식에 따라 어떤 도구가 더 어울리는지 한눈에 정리한 비교 이미지입니다.

    자주 묻는 질문

    Q1. Cluster API가 있으면 kubeadm은 이제 안 써도 되나요?

    그렇진 않습니다. 오히려 Cluster API 내부에서 kubeadm 기반 부트스트랩을 활용하는 경우가 흔합니다. kubeadm은 여전히 중요한 기반 기술입니다.

    Q2. 소규모 팀도 Cluster API를 바로 도입해야 할까요?

    반드시 그렇진 않습니다. 클러스터 수가 적고 운영자가 구조를 아직 익히는 단계라면 kubeadm이 더 현실적일 수 있습니다. 자동화 비용보다 복잡도 비용이 더 클 수 있거든요.

    Q3. GitOps와 더 잘 맞는 쪽은 무엇인가요?

    Cluster API가 더 자연스럽습니다. 클러스터 정의 자체를 리소스로 관리하니까 Git 저장소 기반 운영 모델과 궁합이 좋습니다.

    마무리: 현실적인 접근

    정리해보면 이렇습니다. Kubeadm vs ClusterAPI 비교는 단순한 우열 비교가 아니라, 운영 성숙도와 목표가 다른 두 접근입니다. 제가 직접 해보니 kubeadm은 쿠버네티스를 제대로 이해하게 해주는 좋은 선생님이었고, Cluster API는 그 다음 단계에서 운영 자동화를 체계로 바꿔주는 도구였습니다. 둘 중 하나가 무조건 정답은 아니었습니다.

    개인적으로는 이런 순서를 추천드립니다. 처음엔 kubeadm으로 컨트롤 플레인 초기화, CNI 연결, 노드 조인, 인증서 구조를 손으로 한 번 겪어보세요. 그다음 반복 배포가 필요해지는 시점에 Cluster API를 붙이면 훨씬 덜 헷갈립니다. 저도 처음엔 YAML만 보고 멍했었는데, 기반 개념을 알고 나니까 드디어 됐다! 싶은 순간이 오더라고요.

    다음 글에서는 kubeadm으로 만든 클러스터를 운영 표준화하는 방법이나, Cluster API와 GitOps를 연결하는 흐름을 따로 다뤄보겠습니다. 이전 글에서 다룬 네트워크 플러그인 비교나 Ingress(외부 트래픽 진입점) 구성 글과 함께 보시면 더 이해가 잘 되실 겁니다.

    처음엔 수동 구축으로 원리를 익히고, 이후 선언형 운영으로 넘어가는 학습 및 운영 로드맵을 보여주는 마무리 이미지입니다.

  • [k8s] ClusterAPI 도입 성공 사례: 온프레미스 Kubernetes 클러스터 자동화 구축기

    [k8s] ClusterAPI 도입 성공 사례: 온프레미스 Kubernetes 클러스터 자동화 구축기

    [인프라] ClusterAPI 도입으로 온프레미스 자동화 성공하기

    온프레미스 Kubernetes 환경을 오래 운영하다 보면 결국 같은 고민을 하게 됩니다. 클러스터 하나 만들 때마다 문서 열고, kubeadm 옵션 다시 확인하고, 네트워크랑 인증서 맞추고, 노드 추가할 때마다 사람 손이 들어가죠. 저도 그랬습니다. 그래서 이번 글에서는 제가 실제로 정리해 본 ClusterAPI 도입 사례를 중심으로, 온프레미스 Kubernetes 환경에서 클러스터 생성과 확장을 어떻게 자동화했는지 풀어보려고 합니다. 특히 여러 팀이 같은 기준으로 클러스터를 만들고 싶을 때, 이 접근이 왜 먹히는지 말씀드릴게요.

    처음엔 솔직히 이게 뭔가 싶었어요. Kubernetes 자체도 복잡한데 관리 클러스터까지 따로 둔다니 더 어려워 보였거든요. 근데 한 번 구조가 잡히고 나니까, “아 이건 사람 손을 줄이기 위한 운영 도구구나” 싶더라고요. 혹시 지금도 새 클러스터 만들 때마다 체크리스트부터 찾고 계신다면, 여기서 중요한 포인트를 같이 보시면 됩니다.

    ClusterAPI 도입 사례를 설명하는 온프레미스 Kubernetes 전체 아키텍처 이미지

    Management Cluster(관리 클러스터), Workload Cluster(운영 클러스터), 인프라 제공자와 GitOps 흐름을 한눈에 보여주는 아키텍처 이미지입니다.

    1. ClusterAPI란 무엇인가요?

    Cluster API(CAPI, 클러스터 수명주기 관리 프로젝트)를 쉽게 말하면, Kubernetes 방식으로 Kubernetes 클러스터를 만드는 도구예요. Deployment(디플로이먼트)를 선언적으로 관리하듯이, 클러스터 자체를 YAML로 선언하고 생성, 확장, 업그레이드까지 다루는 거죠.

    핵심은 세 가지입니다.

    • Management Cluster: 다른 클러스터를 생성하고 관리하는 기준 클러스터입니다.
    • Workload Cluster: 실제 애플리케이션이 올라가는 대상 클러스터입니다.
    • Provider: vSphere(브이스피어, 가상화 플랫폼), OpenStack(오픈스택, 프라이빗 클라우드 플랫폼), Bare Metal(베어메탈, 물리 서버) 같은 인프라와 연결해 주는 구성입니다.

    제가 직접 해보니 중요한 건 “클러스터 생성 절차를 코드로 옮긴다”는 점이었어요. 이게 되면 담당자가 바뀌어도 운영 방식이 흔들리지 않거든요. ClusterAPI 도입 사례가 주목받는 이유도 결국 여기 있습니다.

    2. 왜 온프레미스 Kubernetes 자동화에 잘 맞았나

    클라우드는 원래 API가 잘 되어 있어서 자동화가 비교적 쉬워요. 반면 온프레미스는 가상화 플랫폼, 네트워크, IP 할당 정책, 이미지 관리, 인증서 처리까지 다 제각각인 경우가 많습니다. 그래서 클러스터 자동화가 더 절실한데, 아이러니하게도 더 어렵죠.

    제가 보기에 Cluster API가 온프레미스에서 특히 좋았던 이유는 아래와 같았습니다.

    구분 기존 수동 방식 ClusterAPI 방식
    클러스터 생성 문서 따라 수동 실행 YAML 기반 선언형 생성
    확장 노드별 개별 작업 replica 수 조정 중심
    표준화 작업자 숙련도 영향 큼 템플릿 재사용 가능
    변경 이력 위키나 메모 의존 Git 기반 추적 가능
    복구 재현 어려움 동일 매니페스트 재적용 가능

    특히 여러 환경을 동시에 굴릴 때 차이가 컸어요. 개발, 스테이징, 운영이 따로 있으면 사람이 일일이 맞추다가 꼭 어긋나거든요. 반면 CAPI 구축을 해두면 템플릿 하나에서 변수만 바꿔 환경을 복제할 수 있어서 훨씬 안정적이었습니다.

    3. 제가 잡았던 목표와 설계 기준

    이번 ClusterAPI 도입 사례에서 제가 세운 기준은 과하지 않게 명확했어요.

    1. 클러스터 생성 절차를 문서가 아니라 Git 저장소 기준으로 관리할 것
    2. Control Plane(컨트롤 플레인, 클러스터 제어 영역)과 Worker Node(워커 노드, 실제 워크로드 실행 서버) 확장을 분리할 것
    3. 온프레미스 Kubernetes 환경에서도 동일한 템플릿을 재사용할 것
    4. 장애가 나더라도 다시 만들 수 있는 구조를 우선할 것

    여기서 중요한 포인트는 “처음부터 모든 걸 자동화하려고 하지 않는다”는 점이에요. 저도 처음엔 네트워크, 스토리지, 로드밸런서까지 한 번에 묶으려다가 삽질 좀 했습니다 ㅎㅎ 결국 성공한 방식은 클러스터 수명주기부터 먼저 자동화하고, 그 다음에 GitOps와 운영 도구를 붙이는 순서였어요.

    4. CAPI 구축 전 준비: Management Cluster부터 정리

    실전 구현은 예시로 vSphere 기반 온프레미스 환경을 기준으로 설명드릴게요. 다만 구조 자체는 다른 인프라 제공자에도 비슷하게 적용됩니다. 준비 단계에서 필요한 건 대략 이 정도입니다.

    • kubectl(쿠버네티스 CLI), clusterctl(Cluster API CLI)
    • 부트스트랩용 Kubernetes 클러스터 1개
    • vSphere API 접근 정보 또는 사용하는 온프레미스 인프라 자격 정보
    • 템플릿에서 참조할 VM 이미지와 네트워크 정책
    • 로드밸런서 또는 API 서버 엔드포인트 전략

    저는 먼저 management cluster를 아주 작게 올리고, 여기에 Cluster API Controller(컨트롤러, 상태를 맞추는 구성요소)를 설치했어요. 이 관리 클러스터가 있어야 이후 workload cluster를 선언형으로 찍어낼 수 있거든요.

    export CLUSTER_TOPOLOGY=true
    export EXP_CLUSTER_RESOURCE_SET=true
    
    clusterctl init --infrastructure vsphere
    clusterctl version
    kubectl get pods -A

    이 단계에서 pod가 전부 Running 상태로 올라오는지 꼭 확인하셔야 합니다. 컨트롤러가 불안정하면 뒤 단계에서 증상이 꼬여서 원인 파악이 더 어려워져요.

    5. 실전 구현: 온프레미스 Kubernetes 클러스터 자동화 흐름

    이제 본격적으로 CAPI 구축을 진행합니다. 제 경험상 아래 순서가 가장 덜 꼬였습니다.

    1. 클러스터 템플릿 생성
    2. 환경 변수 주입
    3. 매니페스트 검토
    4. 적용 후 상태 확인
    5. 노드 확장 및 업그레이드 테스트
    export VSPHERE_SERVER=vc.example.local
    export VSPHERE_USERNAME=svc_clusterapi
    export VSPHERE_PASSWORD='change-me'
    export VSPHERE_DATACENTER=DC1
    export VSPHERE_DATASTORE=datastore01
    export VSPHERE_NETWORK=VM_Network
    export VSPHERE_RESOURCE_POOL=/DC1/host/Cluster/Resources
    export VSPHERE_FOLDER=/DC1/vm/k8s
    export VSPHERE_TEMPLATE=ubuntu-k8s-template
    export KUBERNETES_VERSION=v1.29.0
    export CONTROL_PLANE_MACHINE_COUNT=3
    export WORKER_MACHINE_COUNT=3
    export CLUSTER_NAME=onprem-prod-01
    
    clusterctl generate cluster ${CLUSTER_NAME} \
      --kubernetes-version ${KUBERNETES_VERSION} \
      --control-plane-machine-count=${CONTROL_PLANE_MACHINE_COUNT} \
      --worker-machine-count=${WORKER_MACHINE_COUNT} \
      > ${CLUSTER_NAME}.yaml

    생성된 YAML은 바로 적용하지 말고 한 번 읽어보시는 걸 권장합니다. 처음엔 귀찮아 보여도, 여기서 네트워크 이름이나 템플릿 참조가 틀린 걸 많이 잡더라고요.

    ClusterAPI 도입 사례의 템플릿 생성과 컨트롤러 배포 흐름 이미지

    clusterctl로 템플릿을 생성하고, management cluster에서 이를 해석해 workload cluster를 만드는 흐름을 설명하는 이미지입니다.

    apiVersion: cluster.x-k8s.io/v1beta1
    kind: Cluster
    metadata:
      name: onprem-prod-01
    spec:
      clusterNetwork:
        pods:
          cidrBlocks:
            - 192.168.0.0/16
        services:
          cidrBlocks:
            - 10.96.0.0/12
      controlPlaneRef:
        apiVersion: controlplane.cluster.x-k8s.io/v1beta1
        kind: KubeadmControlPlane
        name: onprem-prod-01-control-plane
      infrastructureRef:
        apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
        kind: VSphereCluster
        name: onprem-prod-01
    kubectl apply -f onprem-prod-01.yaml
    kubectl get cluster
    kubectl get machines
    kubectl get kubeadmcontrolplane
    kubectl describe cluster onprem-prod-01

    여기서 진짜 편한 점이 나와요. 워커 노드 늘릴 때도 별도 설치 문서가 아니라 replica 값을 조정하는 식으로 접근하게 되거든요. 사람이 SSH 들어가서 하나씩 붙이는 방식에서 벗어나는 거죠.

    apiVersion: cluster.x-k8s.io/v1beta1
    kind: MachineDeployment
    metadata:
      name: onprem-prod-01-md-0
    spec:
      replicas: 5

    이런 식으로 선언 상태를 바꾸면 컨트롤러가 맞춰 줘요. 실제로 써보니까 운영자가 해야 할 일이 “절차 수행”에서 “원하는 상태 정의”로 바뀌더라고요.

    6. ⚠️ 트러블슈팅: 제가 실제로 막혔던 지점들

    자동화라고 해서 처음부터 매끈하진 않았어요. 오히려 수동 설치보다 어디서 실패했는지 감이 안 잡혀서 더 답답할 때도 있었죠. 특히 아래 세 가지는 자주 만났습니다.

    6-1. VM은 생성됐는데 Kubernetes 노드로 안 붙는 문제

    이건 대부분 템플릿 이미지 문제였어요. cloud-init(클라우드 이닛, 초기 설정 자동화) 또는 kubeadm bootstrap 과정이 템플릿과 안 맞는 경우가 있더라고요. 저는 골든 이미지 재생성 후 해결했습니다.

    kubectl get kubeadmconfigs
    kubectl describe machine <machine-name>
    kubectl logs -n capv-system deployment/capv-controller-manager

    6-2. API 엔드포인트는 열렸는데 Control Plane이 Ready로 안 가는 문제

    로드밸런서 health check 조건과 kube-apiserver 준비 상태가 안 맞으면 이런 현상이 생겨요. 겉으로는 포트가 열려 보여도 Cluster API 쪽에서는 준비가 덜 된 걸로 판단할 수 있습니다.

    6-3. 머신 삭제가 느리거나 걸리는 문제

    finalizer(파이널라이저, 정리 작업 보장 메커니즘)와 인프라 자원 정리가 꼬일 때가 있어요. 이때는 무작정 리소스부터 지우지 말고, 어떤 컨트롤러가 막고 있는지 이벤트를 먼저 봐야 합니다.

    • ⚠️ 경고: 수동으로 VM만 먼저 삭제하면 CAPI 상태와 실제 인프라 상태가 어긋날 수 있습니다.
    • 💡 팁: 문제 상황은 이벤트, controller log, Machine 상태를 함께 봐야 빨리 풀려요.
    • 💡 팁: 운영 전 테스트 환경에서 scale-out, scale-in, control plane 교체를 꼭 해보세요.

    저도 처음엔 “왜 선언형인데 선언대로 안 되지?” 싶었는데, 결국 선언형도 기반 인프라와 부트스트랩 준비가 맞아야 돌아가더라고요. 이건 정말 직접 해봐야 감이 와요.

    7. 검증과 결과: 운영 방식이 어떻게 달라졌나

    검증은 단순히 클러스터가 떠 있느냐만 보면 부족합니다. 저는 아래 순서로 확인했어요.

    1. Control Plane 3대가 정상 Ready 상태인지 확인
    2. Worker Node 증설/축소가 선언대로 반영되는지 확인
    3. kubeconfig 추출 후 실제 워크로드 배포 테스트
    4. 클러스터 재생성 시 동일한 결과가 나오는지 확인
    clusterctl get kubeconfig onprem-prod-01 > onprem-prod-01.kubeconfig
    export KUBECONFIG=$(pwd)/onprem-prod-01.kubeconfig
    kubectl get nodes
    kubectl create deployment nginx --image=nginx
    kubectl get pods -o wide

    이 검증이 끝나고 나면 체감이 확 와요. 새 환경이 필요할 때 “며칠 잡아야 하나”가 아니라 “템플릿 변수 뭘 바꿔야 하나”로 대화가 바뀌거든요. 이게 제가 느낀 가장 큰 성과였어요. 숫자를 과장할 필요도 없이, 운영 피로도가 확실히 줄었습니다.

    ClusterAPI 도입 사례에서 생성된 온프레미스 Kubernetes 클러스터 검증 결과 이미지

    노드가 Ready 상태로 정렬되고 테스트 워크로드가 배포된 모습을 보여주는 결과 검증 이미지입니다.

    🎉 성과 정리

    • 클러스터 생성 절차가 사람 의존에서 Git 기반 표준 절차로 바뀜
    • 온프레미스 Kubernetes 환경에서도 재현 가능한 배포 흐름 확보
    • 운영팀 간 작업 편차 감소
    • 추후 GitOps, 모니터링, 정책 관리 연계가 쉬워짐

    8. 정리: ClusterAPI 도입 사례에서 배운 점

    이번 ClusterAPI 도입 사례를 통해 제가 가장 크게 배운 건, 자동화의 핵심은 도구보다 기준이라는 점이었어요. Cluster API는 만능 마법봉은 아니지만, 클러스터 생성과 확장을 운영 표준으로 묶는 데는 정말 강력했습니다. 특히 클러스터 자동화를 사람 손이 아니라 선언 상태 중심으로 옮긴다는 점에서, 장기 운영에 큰 차이를 만들더라고요.

    다만 처음부터 모든 걸 얹지는 마세요. Management cluster 안정화, 템플릿 검증, 네트워크 정책 정리, 골든 이미지 검증 순으로 가는 게 좋아요. 저도 처음엔 욕심냤다가 다시 돌아왔거든요. 근데 그렇게 한 바퀴 돌고 나니 구조가 훨씬 단단해졌습니다.

    ClusterAPI 도입 사례의 도입 전후 운영 방식 비교 이미지

    수동 구축과 선언형 자동화의 차이를 한눈에 보여주는 비교 이미지입니다.

    다음 글에서는 ClusterClass(클래스 기반 클러스터 템플릿)와 GitOps를 묶어서 운영 표준화를 더 밀어붙이는 방법도 다뤄볼 예정입니다. 이전 글에서 정리한 kubeadm 기반 수동 설치 방식과 비교해서 보시면 왜 CAPI 구축이 가치 있는지 더 선명하게 보이실 겁니다.

    FAQ. ClusterAPI 도입 시 자주 묻는 질문

    Q1. 작은 팀도 Cluster API가 필요할까요?

    클러스터 수가 1개뿐이면 당장 절실하지 않을 수 있어요. 다만 환경이 늘어날 계획이 있거나 표준화가 필요하다면 일찍 검토할 가치가 있습니다.

    Q2. 베어메탈에서도 가능한가요?

    가능합니다. 다만 사용하는 인프라 제공자와 네트워크 자동화 수준에 따라 난이도가 확 달라져요. 그래서 처음엔 가상화 환경에서 개념을 먼저 익히는 걸 추천드립니다.

    Q3. 업그레이드도 선언형으로 할 수 있나요?

    네, Kubernetes 버전과 관련 리소스 정의를 통해 관리하는 방식이 일반적이에요. 다만 운영 적용 전에는 테스트 클러스터에서 롤링 동작을 꼭 검증해 보셔야 합니다.

    ✅ 한 줄 정리: 온프레미스 Kubernetes를 반복해서 만들고 운영해야 한다면, Cluster API는 복잡함을 늘리는 도구가 아니라 반복 작업을 구조화하는 도구예요.