Kubespray と Terraform でクラスターを構築する
アドオンは group_vars のスイッチ。有効にしたら動作を確かめる
한국어 원문으로 표시합니다.
목표
설치 전에 group_vars 로 metrics-server·local-path-provisioner·Helm 을 켜고, 설치 뒤 각각이 실제로 동작하는지 확인합니다.
-e 가 불리언을 문자열로 넘기는 함정과, 기본 네트워크 플러그인 calico 가 어떤 캡슐화로 떠 있는지도 봅니다.
왜 중요한가
kubespray 에서 애드온은 변수 하나입니다. 그래서 켜기는 쉽고, 켰다는 사실과 동작한다는 사실이 쉽게 섞입니다. metrics-server 는 떠 있어도 APIService 가 Available 이 아니면 HPA 가 멈추고, 스토리지 클래스는 있어도 PVC 가 노드 디스크에 붙지 않으면 상태 있는 앱이 뜨지 않습니다. 네트워크 플러그인은 설치 뒤에 바꾸기가 가장 어려운 선택이라, 무엇이 기본이고 그 기본이 어떤 망 조건을 요구하는지 알고 골라야 합니다.
단계
/root/ks/inventory/lab/group_vars/k8s_cluster/addons.yml에서metrics_server_enabled,local_path_provisioner_enabled,helm_enabled를 모두true로 바꾸세요.ansible-inventory --host node1으로 풀었을 때 세 값이 문자열이 아니라 불리언 true 여야 합니다./opt/ks/kubespray에서ansible-playbook -i /root/ks/inventory/lab/inventory.ini playbooks/boilerplate.yml -e helm_enabled=true와-e '{"helm_enabled": true}'를 각각 돌려 보세요./root/ks/addons/string-trap.json에kv_failed_task(첫 명령이 실패한 작업 이름, 역할 접두사 없이),kv_type(첫 명령에서 helm_enabled 가 된 타입:"str"또는"bool"),json_passed(두 번째 명령이 failed=0 으로 끝났는가, 불리언)를 적으세요./opt/ks/kubespray에서ansible-playbook -i /root/ks/inventory/lab/inventory.ini cluster.yml을 돌려 출력 전체를/root/ks/logs/cluster-1.log에 남기세요(약 8분). PLAY RECAP 의 node1 이failed=0이어야 합니다.kubectl top node가 node1 의 CPU·메모리를 보여 줄 때까지 기다린 뒤/root/ks/addons/metrics.json에apiservice_available(APIServicev1beta1.metrics.k8s.io의 Available 조건 status),image(metrics-server Deployment 의 컨테이너 이미지),insecure_tls(metrics-server 가--kubelet-insecure-tls인자로 떠 있는가, 불리언)를 적으세요.- default 네임스페이스에 PVC
data(storageClassNamelocal-path, 64Mi, ReadWriteOnce)와 그것을/data에 붙인 파드writer(이미지busybox:latest, 명령sh -c 'echo kubespray > /data/hello.txt && sleep 3600')를 만드세요. PVC 가 Bound 가 되고, 노드의 local-path 저장 경로 아래 그 볼륨 디렉터리에hello.txt가kubespray로 있어야 합니다. helm create /root/ks/addons/demo로 차트를 만들고helm install demo /root/ks/addons/demo -n demo --create-namespace --wait로 설치하세요. 릴리스demo가 deployed 이고 파드가 Ready 여야 합니다./root/ks/addons/helm.json에helm_version(helm version --template '{{.Version}}'),kubespray_helm_version(이 kubespray 판의 기본 helm_version, 앞에 v 를 붙여서)을 적으세요./root/ks/addons/cni.json에plugin(인벤토리가 푼 kube_network_plugin),calico_version(calico-node DaemonSet 의 calico-node 컨테이너 이미지 태그),vxlan_mode,ipip_mode(calicoctl.sh get ippool default-pool -o json의 spec 값),pool_cidr(그 IP 풀의 cidr)를 적으세요.
참고
- kubespray v2.32.0 이
/opt/ks/kubespray에, 인벤토리가/root/ks/inventory/lab/inventory.ini(kube_version 1.35.8)에 준비돼 있습니다. 설치는 3단계에서 직접 합니다. - 애드온 이미지는 registry.k8s.io·docker.io 에서 받습니다. 이 VM 은 공인 80/443 으로 나갈 수 있습니다.
- 흔한 실수: addons.yml 에
"true"처럼 따옴표를 붙이는 것. 어떤 변수는 validate_inventory 가 막고, 어떤 변수는 조건식에서 조용히 다르게 풀립니다. - 흔한 실수: kubectl top 이 처음 몇십 초 실패하는 것을 보고 metrics-server 를 다시 까는 것. 첫 수집 주기를 기다리세요.
- 문서: Kubespray — CNI 선택(k8s-cluster.yml) · Kubespray — Calico · Kubernetes — Resource metrics pipeline
애드온은 설치 전에 고른다
/root/ks/inventory/lab/group_vars/k8s_cluster/addons.yml 에서 metrics_server_enabled, local_path_provisioner_enabled, helm_enabled 를 모두 true 로 바꾸세요. ansible-inventory --host node1 으로 풀었을 때 세 값이 문자열이 아니라 불리언 true 여야 합니다.
샘플의 addons.yml 에는 세 줄이 false 로 적혀 있습니다. YAML 에서 따옴표 없는 true 는 불리언이고 "true" 는 문자열입니다. ansible-inventory 의 JSON 출력에서 둘은 true 와 "true" 로 구별됩니다.
-e 는 문자열을 넘긴다
/opt/ks/kubespray 에서 ansible-playbook -i /root/ks/inventory/lab/inventory.ini playbooks/boilerplate.yml -e helm_enabled=true 와 -e '{"helm_enabled": true}' 를 각각 돌려 보세요. /root/ks/addons/string-trap.json 에 kv_failed_task(첫 명령이 실패한 작업 이름, 역할 접두사 없이), kv_type(첫 명령에서 helm_enabled 가 된 타입: "str" 또는 "bool"), json_passed(두 번째 명령이 failed=0 으로 끝났는가, 불리언)를 적으세요.
ansible-core 2.19 부터 조건식은 반드시 불리언이어야 하고, -e key=value 는 언제나 문자열을 넘깁니다. kubespray 는 몇몇 알려진 불리언을 validate_inventory 에서 타입으로 검사합니다. 타입은 ansible -i ... node1 -m debug -a 'msg={{{{ helm_enabled | type_debug }}}}' -e helm_enabled=true 로 볼 수 있습니다.
애드온과 함께 세운다
/opt/ks/kubespray 에서 ansible-playbook -i /root/ks/inventory/lab/inventory.ini cluster.yml 을 돌려 출력 전체를 /root/ks/logs/cluster-1.log 에 남기세요(약 8분). PLAY RECAP 의 node1 이 failed=0 이어야 합니다.
애드온은 cluster.yml 의 마지막 play(Install Kubernetes apps)에서 설치됩니다. 이미 세운 클러스터라면 group_vars 를 바꾼 뒤 --tags apps 나 애드온 태그(metrics_server 등)로 그 부분만 다시 돌릴 수도 있지만, 여기서는 처음부터 켜고 세웁니다. 콘솔이 끊겨도 계속 돌게 systemd-run 이나 tmux 로 띄우세요.
metrics-server 가 정말 수치를 내는가
kubectl top node 가 node1 의 CPU·메모리를 보여 줄 때까지 기다린 뒤 /root/ks/addons/metrics.json 에 apiservice_available(APIService v1beta1.metrics.k8s.io 의 Available 조건 status), image(metrics-server Deployment 의 컨테이너 이미지), insecure_tls(metrics-server 가 --kubelet-insecure-tls 인자로 떠 있는가, 불리언)를 적으세요.
metrics-server 는 aggregation layer 로 API 서버에 붙습니다. APIService 가 Available 이 아니면 kubectl top 은 'Metrics API not available' 로 실패합니다. 첫 수치가 나오기까지 수십 초가 걸립니다. kubespray 기본값(metrics_server_kubelet_insecure_tls: true)은 kubelet 의 서빙 인증서를 검증하지 않는다는 뜻이라, 운영에서는 kubelet 서빙 인증서를 제대로 발급하는 쪽을 검토해야 합니다.
PVC 가 노드 디스크에 붙는다
default 네임스페이스에 PVC data(storageClassName local-path, 64Mi, ReadWriteOnce)와 그것을 /data 에 붙인 파드 writer(이미지 busybox:latest, 명령 sh -c 'echo kubespray > /data/hello.txt && sleep 3600')를 만드세요. PVC 가 Bound 가 되고, 노드의 local-path 저장 경로 아래 그 볼륨 디렉터리에 hello.txt 가 kubespray 로 있어야 합니다.
local-path-provisioner 는 PVC 를 쓰는 파드가 스케줄될 때(WaitForFirstConsumer) 노드 디스크에 디렉터리를 만들어 PV 로 줍니다. PV 의 spec.hostPath.path 나 spec.local.path 가 그 디렉터리입니다. busybox 는 local-path 가 쓰는 도우미 이미지라 kubespray 가 이미 받아 두었습니다.
kubespray 가 깐 Helm 으로 릴리스 하나
helm create /root/ks/addons/demo 로 차트를 만들고 helm install demo /root/ks/addons/demo -n demo --create-namespace --wait 로 설치하세요. 릴리스 demo 가 deployed 이고 파드가 Ready 여야 합니다. /root/ks/addons/helm.json 에 helm_version(helm version --template '{{.Version}}'), kubespray_helm_version(이 kubespray 판의 기본 helm_version, 앞에 v 를 붙여서)을 적으세요.
kubespray 의 Helm 은 get.helm.sh 에서 체크섬으로 고정한 판을 받아 /usr/local/bin/helm 에 둡니다. 기본 판은 roles/kubespray_defaults/vars/main/checksums.yml 의 helm_archive_checksums 첫 키입니다. helm create 가 만든 차트는 docker.io 의 nginx 이미지를 씁니다.
calico 는 어떻게 떠 있나
/root/ks/addons/cni.json 에 plugin(인벤토리가 푼 kube_network_plugin), calico_version(calico-node DaemonSet 의 calico-node 컨테이너 이미지 태그), vxlan_mode, ipip_mode(calicoctl.sh get ippool default-pool -o json 의 spec 값), pool_cidr(그 IP 풀의 cidr)를 적으세요.
kubespray 는 calicoctl 을 /usr/local/bin/calicoctl.sh 로 감싸 둡니다. 기본 IP 풀은 kube_pods_subnet 에서 만들어지고, 캡슐화는 calico_vxlan_mode·calico_ipip_mode 변수로 정해집니다. VXLAN 은 노드 사이 L3 만 통하면 되고, IPIP 는 IP 프로토콜 4 를 통과시켜야 합니다 — 클라우드 방화벽이 결정을 가르는 지점입니다.