LabHub
はじめる
배우기 러닝패스 코스

Kubespray と Terraform でクラスターを構築する

インベントリ 1 枚がクラスターの形を決める

LabHub 에서 이어서 보기

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

목표

kubespray v2.32.0 의 샘플 인벤토리로 노드 한 대짜리 클러스터의 인벤토리를 설계하고, 판을 group_vars 에 고정하고, 변수가 어느 층에서 이기는지와 그룹 이름을 틀렸을 때 무엇이 깨지는지를 직접 확인합니다. 클러스터는 아직 세우지 않습니다.

왜 중요한가

kubespray 로 클러스터를 세울 때 사람이 직접 쓰는 것은 사실상 인벤토리와 group_vars 뿐입니다. 플레이북은 그대로 두고 이 두 가지만 바꿔 클러스터의 모양(누가 컨트롤 플레인이고 누가 etcd 인가)과 내용(어느 판, 어느 CNI, 어느 런타임)을 정합니다. 그래서 설치가 틀어지는 원인도 대개 여기 있습니다 — 그룹 이름 하나를 틀리면 설치 1분 만에 엉뚱한 오류로 멈추고, 판을 적지 않으면 같은 인벤토리가 kubespray 를 올릴 때마다 다른 쿠버네티스를 설치합니다. 긴 설치를 돌리기 전에 인벤토리 도구로 풀린 값을 확인하는 습관이 이 모듈의 목표입니다.

단계

  1. /opt/ks/kubespray/inventory/sample/root/ks/inventory/lab 로 통째로 복사하세요. group_vars/all/all.ymlgroup_vars/k8s_cluster/k8s-cluster.yml 이 그 아래에 있어야 합니다.
  2. /root/ks/inventory/lab/inventory.ini 에 노드 node1kube_control_plane·kube_node 그룹에 넣고, etcdkube_control_plane 을 자식 그룹으로 받게([etcd:children]) 적으세요. k8s_clusterkube_control_plane·kube_node 를 자식으로 받게([k8s_cluster:children]) 적습니다. 연결 방식은 인벤토리 줄이 아니라 /root/ks/inventory/lab/host_vars/node1.ymlansible_connection: local 로 둡니다. inventory.ini 에는 ansible_connection 이 없어야 합니다.
  3. /opt/ks/kubespray 에서 ansible-inventory --list 를 두 번 돌려 파싱된 호스트 수를 세고 /root/ks/parse.jsondir_hosts(-i /root/ks/inventory/lab 로 디렉터리를 줬을 때), file_hosts(-i /root/ks/inventory/lab/inventory.ini), ignored_ext(kubespray 의 ansible.cfg 가 인벤토리 디렉터리에서 건너뛰는 확장자 중 inventory.ini 를 가리는 것, 점 포함 문자열)를 적으세요.
  4. /root/ks/inventory/lab/group_vars/k8s_cluster/k8s-cluster.ymlkube_version: 1.35.8 을 더하세요(샘플에는 없습니다). 그다음 ansible-inventory --host node1 으로 실제로 풀린 값을 읽어 /root/ks/vars.jsonkube_version, container_manager, kube_network_plugin, kube_proxy_mode, kube_service_addresses, kube_pods_subnet 여섯 개를 문자열로 적으세요.
  5. /root/ks/inventory/lab/group_vars/all/all.yml 끝에 kube_version: 1.34.11 을 잠시 더한 뒤, ansible -i /root/ks/inventory/lab/inventory.ini node1 -m debug -a var=kube_version 으로 실제 값을 보고, 같은 명령에 -e kube_version=1.36.4 를 붙여 한 번 더 보세요. /root/ks/precedence.jsonall_yml(all.yml 에 넣은 값), effective(-e 없이 이긴 값), extra_vars(-e 를 줬을 때 값), winner_file(-e 없이 이긴 값이 적힌 파일의 인벤토리 기준 상대 경로)을 적은 뒤 all.yml 에 넣은 줄은 지웁니다.
  6. /root/ks/broken/inventory.ini 는 누군가 [masters] 로 적은 인벤토리입니다. 고치지 말고 /opt/ks/kubespray 에서 ansible-playbook -i /root/ks/broken/inventory.ini playbooks/boilerplate.yml 을 돌려 보세요. /root/ks/broken.jsonfailed_task(실패한 작업의 이름, 역할 접두사 없이), node1_groups(이 인벤토리에서 node1 이 속한 그룹 이름 정렬 배열, all 과 ungrouped 제외), missing_group(비어 있어야 할 리 없는데 비어 있는 kubespray 그룹 이름)을 적으세요.
  7. /opt/ks/kubespray 에서 ansible-playbook -i /root/ks/inventory/lab/inventory.ini playbooks/boilerplate.yml 을 돌려 출력 전체를 /root/ks/logs/boilerplate.log 에 저장하세요. PLAY RECAP 에 failed=0 이어야 합니다.
  8. /root/ks/report.jsonkubespray_tag(git -C /opt/ks/kubespray describe --tags), ansible_core(ansible --version 첫 줄의 판 번호, 예 2.19.0), kube_version_default(이 판의 기본 kube_version), kube_version_min(이 판이 받아 주는 가장 낮은 판)을 적으세요.

참고

샘플 인벤토리를 내 자리로 복사한다

/opt/ks/kubespray/inventory/sample/root/ks/inventory/lab 로 통째로 복사하세요. group_vars/all/all.ymlgroup_vars/k8s_cluster/k8s-cluster.yml 이 그 아래에 있어야 합니다.

kubespray 는 인벤토리 디렉터리 옆의 group_vars 를 읽습니다. 샘플을 고치지 않고 복사하는 이유는 다음 판으로 올릴 때 샘플이 바뀌기 때문입니다. 대상 디렉터리가 이미 있으면 cp -r 은 그 안에 sample 이라는 하위 디렉터리를 하나 더 만듭니다.

노드 한 대를 세 그룹에 넣는다

/root/ks/inventory/lab/inventory.ini 에 노드 node1kube_control_plane·kube_node 그룹에 넣고, etcdkube_control_plane 을 자식 그룹으로 받게([etcd:children]) 적으세요. k8s_clusterkube_control_plane·kube_node 를 자식으로 받게([k8s_cluster:children]) 적습니다. 연결 방식은 인벤토리 줄이 아니라 /root/ks/inventory/lab/host_vars/node1.ymlansible_connection: local 로 둡니다. inventory.ini 에는 ansible_connection 이 없어야 합니다.

이 VM 이 제어 노드이자 대상 노드라 ssh 대신 local 연결을 씁니다. 그 사실을 host_vars 에 두면, 노드가 늘 때 인벤토리에는 이름만 더하고 연결 방식은 노드별 파일에서 바꾸면 됩니다. 그룹 이름은 kubespray 가 정한 철자 그대로여야 합니다. 샘플 inventory.ini 에는 k8s_cluster 가 없습니다 — kubespray 가 플레이북 안에서 만들기 때문인데, 그러면 플레이북 밖의 도구(ansible-inventory, ansible 애드혹)는 group_vars/k8s_cluster 를 읽지 못합니다.

디렉터리를 주면 호스트가 0개다

/opt/ks/kubespray 에서 ansible-inventory --list 를 두 번 돌려 파싱된 호스트 수를 세고 /root/ks/parse.jsondir_hosts(-i /root/ks/inventory/lab 로 디렉터리를 줬을 때), file_hosts(-i /root/ks/inventory/lab/inventory.ini), ignored_ext(kubespray 의 ansible.cfg 가 인벤토리 디렉터리에서 건너뛰는 확장자 중 inventory.ini 를 가리는 것, 점 포함 문자열)를 적으세요.

호스트 수는 --list 결과의 _meta.hostvars 키 개수로 셀 수 있습니다. ansible-inventory 가 어느 설정 파일을 읽는지는 ansible-config dump --only-changed 로 볼 수 있고, 그 파일은 현재 디렉터리에서 찾습니다.

판을 group_vars 에 고정한다

/root/ks/inventory/lab/group_vars/k8s_cluster/k8s-cluster.ymlkube_version: 1.35.8 을 더하세요(샘플에는 없습니다). 그다음 ansible-inventory --host node1 으로 실제로 풀린 값을 읽어 /root/ks/vars.jsonkube_version, container_manager, kube_network_plugin, kube_proxy_mode, kube_service_addresses, kube_pods_subnet 여섯 개를 문자열로 적으세요.

kube_version 을 적지 않으면 kubespray 판마다 기본값이 바뀌어, 같은 인벤토리로 다른 날 다른 쿠버네티스가 설치됩니다. 파일에 적은 것과 Ansible 이 실제로 푼 값이 같은지는 인벤토리 도구로 확인합니다. YAML 에서 1.35 처럼 점 하나짜리 숫자는 실수로 읽히지만 세 마디 판 번호는 문자열입니다.

같은 변수가 세 곳에 있으면

/root/ks/inventory/lab/group_vars/all/all.yml 끝에 kube_version: 1.34.11 을 잠시 더한 뒤, ansible -i /root/ks/inventory/lab/inventory.ini node1 -m debug -a var=kube_version 으로 실제 값을 보고, 같은 명령에 -e kube_version=1.36.4 를 붙여 한 번 더 보세요. /root/ks/precedence.jsonall_yml(all.yml 에 넣은 값), effective(-e 없이 이긴 값), extra_vars(-e 를 줬을 때 값), winner_file(-e 없이 이긴 값이 적힌 파일의 인벤토리 기준 상대 경로)을 적은 뒤 all.yml 에 넣은 줄은 지웁니다.

Ansible 은 더 구체적인 그룹의 group_vars 가 all 을 이깁니다. k8s_cluster 는 all 의 자식입니다. -e 로 준 extra vars 는 무엇보다 이깁니다 — 그래서 kubespray 문서가 -e 를 '내부 변수를 덮을 때' 로 좁혀 쓰라고 합니다. 명령은 kubespray 디렉터리에서 돌리세요.

그룹 이름을 틀리면 무엇이 깨지나

/root/ks/broken/inventory.ini 는 누군가 [masters] 로 적은 인벤토리입니다. 고치지 말고 /opt/ks/kubespray 에서 ansible-playbook -i /root/ks/broken/inventory.ini playbooks/boilerplate.yml 을 돌려 보세요. /root/ks/broken.jsonfailed_task(실패한 작업의 이름, 역할 접두사 없이), node1_groups(이 인벤토리에서 node1 이 속한 그룹 이름 정렬 배열, all 과 ungrouped 제외), missing_group(비어 있어야 할 리 없는데 비어 있는 kubespray 그룹 이름)을 적으세요.

오류 문구가 그룹 이름이 틀렸다고 말해 주지 않습니다. 실패한 조건식이 어느 그룹을 찾다 실패했는지 읽으세요. 옛 이름 kube-master 는 kubespray 가 알아서 옮겨 주지만 masters 는 아닙니다. 노드가 속한 그룹(자식 그룹을 거친 것 포함)은 ansible ... -m debug -a var=group_names 로 볼 수 있습니다.

내 인벤토리는 검사를 통과한다

/opt/ks/kubespray 에서 ansible-playbook -i /root/ks/inventory/lab/inventory.ini playbooks/boilerplate.yml 을 돌려 출력 전체를 /root/ks/logs/boilerplate.log 에 저장하세요. PLAY RECAP 에 failed=0 이어야 합니다.

boilerplate.yml 은 cluster.yml·upgrade-cluster.yml·reset.yml 이 모두 맨 앞에서 부르는 검사 묶음입니다. 여기서 막히는 것은 설치를 시작하기도 전에 막히는 것이라, 설치 전에 따로 돌려 두면 긴 플레이북을 돌리다 1분 만에 멈추는 일을 피할 수 있습니다.

이 판의 kubespray 가 받아 주는 범위

/root/ks/report.jsonkubespray_tag(git -C /opt/ks/kubespray describe --tags), ansible_core(ansible --version 첫 줄의 판 번호, 예 2.19.0), kube_version_default(이 판의 기본 kube_version), kube_version_min(이 판이 받아 주는 가장 낮은 판)을 적으세요.

kubespray 는 기본 판과 최소 판을 따로 적어 두지 않고 roles/kubespray_defaults/vars/main/checksums.yml 의 kubelet 체크섬 목록에서 첫 키와 마지막 키로 계산합니다(roles/kubespray_defaults/defaults/main/main.yml). 체크섬이 없는 판은 설치할 수 없다는 뜻입니다.