LabHub
Get started
배우기 러닝패스 코스

Building clusters with Kubespray and Terraform

Why you choose a network plugin, and what to check after enabling add-ons

LabHub 에서 이어서 보기

한국어 원문으로 표시합니다.

한 줄 요약

kubespray 의 애드온과 네트워크 플러그인은 group_vars 의 스위치이고, 스위치를 켠 것과 그것이 동작하는 것은 따로 확인해야 하며, 네트워크 플러그인만은 나중에 바꾸기 어려우니 설치 전에 이유를 갖고 고릅니다.

왜 이게 필요했나

kubeadm 은 CNI 도, metrics-server 도, 스토리지도 고르지 않습니다. 사람이 매니페스트를 찾아 판을 맞춰 적용해야 하고, 그 판이 클러스터 판과 맞는지도 사람이 봅니다. kubespray 는 이것을 변수로 묶었습니다. kube_network_plugin: calico 한 줄이 calico 의 CRD·데몬셋·IP 풀을 만들고, metrics_server_enabled: true 한 줄이 metrics-server 와 APIService 를 만듭니다. 판과 이미지 주소는 kubespray 릴리스가 고정해 두었으므로, 같은 인벤토리는 언제 돌려도 같은 애드온을 설치합니다. 대신 켰다는 사실만 남고 동작을 확인하는 일은 여전히 사람의 몫입니다.

어떻게 동작하나

네트워크 플러그인. group_vars/k8s_cluster/k8s-cluster.ymlkube_network_plugin 이 고릅니다. 샘플의 주석이 말하는 선택지는 cilium, calico, kube-ovn, flannel, 그리고 직접 설치할 때 쓰는 cni(플러그인 바이너리만 풀고 설정은 비워 둔다)와 none 입니다. 기본은 calico 이고, v2.32.0 의 calico 기본값은 calico_vxlan_mode: Always, calico_ipip_mode: Never 입니다. 즉 노드 사이 파드 트래픽을 VXLAN(UDP 4789)으로 감쌉니다.

고르는 이유는 대개 세 가지입니다. 첫째 NetworkPolicy — flannel 은 파드 네트워크만 주고 정책은 집행하지 않으므로, 정책이 필요하면 calico 나 cilium 입니다. 둘째 망 조건 — IPIP 는 IP 프로토콜 4 를, VXLAN 은 UDP 4789 를, BGP 모드는 TCP 179 를 노드 사이에 통과시켜야 합니다. kubespray 의 포트 문서가 CNI 별로 이 표를 따로 둔 이유입니다. 셋째 운영 부담 — cilium 은 eBPF 로 kube-proxy 를 대신하고 관측(Hubble)까지 주지만 커널 판과 설정 항목이 늘어납니다. 어느 쪽이든 설치 뒤에 바꾸는 것은 사실상 재설치입니다. 파드 IP 대역과 노드의 라우팅이 플러그인에 묶여 있기 때문입니다.

애드온. group_vars/k8s_cluster/addons.yml 에 모여 있고 샘플에서는 전부 false 입니다. 이 모듈에서 켜는 셋은 이렇습니다.

metrics_server_enabled           kubectl top · HPA 의 자원 지표. aggregation layer 로 API 서버에 붙는다
local_path_provisioner_enabled   노드 디스크(/opt/local-path-provisioner/)를 PV 로 주는 동적 프로비저너
helm_enabled                     helm 바이너리를 체크섬으로 고정한 판으로 /usr/local/bin 에 둔다

애드온은 cluster.yml 의 마지막 play 인 "Install Kubernetes apps" 에서 설치되고, 각 역할에 태그(metrics_server 등)가 있어 이미 세운 클러스터에서 그 부분만 다시 돌릴 수도 있습니다.

불리언 함정. ansible-core 2.19(Ansible 12)부터 조건식은 반드시 불리언이어야 합니다. 그런데 -e helm_enabled=true 는 문자열 "true" 를 넘깁니다. kubespray 는 몇몇 잘 알려진 스위치를 validate_inventory 의 "Stop if known booleans are set as strings" 로 막는데, 실측해 보면 이 검사가 보는 것은 download_run_once·download_always_pull·helm_enabled·openstack_lbaas_enabled 넷뿐입니다. 나머지 스위치를 문자열로 주면 그 검사에는 걸리지 않고 조건식이 쓰이는 자리에서 따로 문제가 됩니다. 릴리스 노트가 권하는 대로 -e '{"helm_enabled": true}' 처럼 JSON 으로 넘기거나, 따옴표 없는 YAML 불리언으로 인벤토리에 적는 것이 답입니다.

현장에서 만나는 모습

metrics-server 를 켜 두고 "HPA 가 안 늘어난다" 는 문의를 받는 일이 흔합니다. 확인 순서는 APIService 의 Available 조건 → metrics-server 로그 → kubelet 연결입니다. kubespray 기본값 metrics_server_kubelet_insecure_tls: true 는 metrics-server 가 kubelet 의 서빙 인증서를 검증하지 않는다는 뜻입니다. 단일 노드 실습에서는 편하지만, 운영에서는 kubelet 서빙 인증서를 제대로 발급하고(kubelet_rotate_server_certificates) 이 값을 끄는 쪽을 검토해야 합니다. 켜기 쉬운 기본값에는 대개 이런 거래가 숨어 있습니다.

local-path-provisioner 는 PVC 를 쓰는 파드가 스케줄될 때 그 노드 디스크에 디렉터리를 만들어 줍니다. 편하지만 데이터가 노드에 묶이므로, 노드가 사라지면 데이터도 사라집니다. 실습용·캐시용으로는 좋고, 복제가 필요한 데이터에는 맞지 않습니다.

다음 실습에서 할 것

addons.yml 로 세 애드온을 켜고, -e key=value 와 JSON 형식이 boilerplate 검사에서 어떻게 다르게 풀리는지 확인합니다. 설치한 뒤 kubectl top 과 APIService, PVC 가 노드 디스크에 붙는 모습, kubespray 가 깐 Helm 으로 만든 릴리스를 차례로 확인하고, calico 의 IP 풀에서 캡슐화 방식을 읽습니다.