LabHub
시작하기
배우기 러닝패스 코스

kubespray 와 Terraform 으로 클러스터 세우기

폐쇄망에 들고 갈 것의 목록 — 파일·이미지·파이썬

LabHub 에서 이어서 보기

목표

kubespray 가 설치 중에 받는 파일과 이미지의 목록을 만들고, 인벤토리의 오프라인 변수로 그 목록이 사내 미러(registry.lab.internal:5000, http://files.lab.internal)를 가리키게 바꿉니다. 미러를 채울 사람에게 넘길 대응표와, 제어 노드의 Ansible 까지 담은 반입 꾸러미를 만듭니다. 실제 폐쇄망과 미러는 만들지 않습니다.

왜 중요한가

폐쇄망 설치의 실패는 대부분 "빠뜨린 것" 입니다. 반입 심사를 거쳐 들고 들어간 뒤에야 파일 하나가 없다는 것을 알면 다시 나갔다 와야 하고, 그 왕복이 며칠입니다. 그래서 설치 도구가 무엇을 받는지 도구 스스로 말하게 하고(generate_list.sh), 그 목록이 정말 이번에 설치할 판의 것인지, 모든 주소가 사내를 가리키는지를 밖에 있을 때 확인해야 합니다. 이 모듈에서 만나는 목록 판 함정은 실제로 이 코스를 만들며 겪은 것입니다 — 인벤토리에 판을 적어 두었는데 목록은 다른 판으로 나왔습니다.

단계

  1. /opt/ks/kubespray/contrib/offline 에서 ./generate_list.sh 를 인자 없이 돌리고, 만들어진 temp/files.list·temp/images.list/root/ks/offline/default/ 에 복사하세요. /root/ks/offline/default/count.jsonfiles, images(두 목록의 줄 수)와 registries(images.list 의 첫 경로 조각별 개수, 예 {"quay.io": 3})를 적으세요.
  2. 인벤토리의 kube_version 은 1.35.8 입니다. ./generate_list.sh -i /root/ks/inventory/lab/inventory.ini 로 한 번, 여기에 -e kube_version=1.35.8 을 더해 한 번 돌리고 각각 images.list 의 kube-apiserver 태그를 확인하세요. /root/ks/offline/trap.jsonwith_inventory(첫 실행의 kube-apiserver 태그), with_extra_var(두 번째 실행의 태그), ignored_group(인벤토리의 kube_version 이 적힌 group_vars 그룹 가운데 목록 플레이북에 적용되지 않은 그룹 이름)을 적으세요.
  3. /root/ks/inventory/lab/group_vars/all/offline.yml 를 고쳐 registry_host: "registry.lab.internal:5000", files_repo: "http://files.lab.internal" 를 두고, kubespray 문서의 폐쇄망 절대로 kube_image_repo·gcr_image_repo·docker_image_repo·quay_image_repo·github_image_repo{{ registry_host }} 로, github_url·dl_k8s_io_url·storage_googleapis_url·get_helm_url{{ files_repo }}/<원래 도메인> 으로 두세요. 파일은 group_vars/all 에 있어야 합니다.
  4. ./generate_list.sh -i /root/ks/inventory/lab/inventory.ini -e kube_version=1.35.8 로 목록을 다시 만들고 두 파일을 /root/ks/offline/mirror/ 에 복사하세요. files.list 의 모든 줄이 http://files.lab.internal/ 로, images.list 의 모든 줄이 registry.lab.internal:5000/ 로 시작하고, 줄 수가 1단계와 같아야 합니다.
  5. 미러를 채우는 사람에게 넘길 대응표를 만드세요. 오프라인 변수를 적용하지 않은 1.35.8 원본 목록과 4단계의 미러 목록을 줄 단위로 짝지어, /root/ks/offline/image-map.tsv원본<TAB>미러 를 한 줄에 하나씩(images.list 의 모든 이미지) 적으세요.
  6. /root/ks/inventory/lab/group_vars/all/offline.ymlcontainerd_registries_mirrors 를 더해, prefix registry.lab.internal:5000 가 host http://registry.lab.internal:5000 를 pull·resolve 로 쓰고 TLS 검증을 건너뛰게(skip_verify: true) 하세요. ansible-inventory --host node1 이 이 목록을 그대로 풀어야 합니다.
  7. kubespray 의 requirements.txt 로 파이썬 패키지를 /root/ks/offline/pypi/ 에 내려받고(pip download), 인터넷을 쓰지 않는 설치가 그 디렉터리만으로 풀리는지 pip install --dry-run --no-index --find-links /root/ks/offline/pypi -r requirements.txt 로 확인하세요. /root/ks/offline/pypi.jsonwheels(내려받은 파일 수), resolved(dry-run 이 성공했는가, 불리언)를 적습니다.

참고

무엇을 받는지 목록부터

/opt/ks/kubespray/contrib/offline 에서 ./generate_list.sh 를 인자 없이 돌리고, 만들어진 temp/files.list·temp/images.list/root/ks/offline/default/ 에 복사하세요. /root/ks/offline/default/count.jsonfiles, images(두 목록의 줄 수)와 registries(images.list 의 첫 경로 조각별 개수, 예 {"quay.io": 3})를 적으세요.

generate_list.sh 는 roles/kubespray_defaults/defaults/main/download.yml 에서 download_url 과 이미지 repo·tag 를 뽑아 틀을 만들고, 작은 플레이북으로 변수를 채웁니다. 켜지 않은 CNI·애드온의 것까지 모두 들어 있어 실제 설치보다 넉넉합니다. 이미지 목록의 첫 조각이 곧 미러해야 할 원본 레지스트리입니다.

목록이 조용히 다른 판으로 나온다

인벤토리의 kube_version 은 1.35.8 입니다. ./generate_list.sh -i /root/ks/inventory/lab/inventory.ini 로 한 번, 여기에 -e kube_version=1.35.8 을 더해 한 번 돌리고 각각 images.list 의 kube-apiserver 태그를 확인하세요. /root/ks/offline/trap.jsonwith_inventory(첫 실행의 kube-apiserver 태그), with_extra_var(두 번째 실행의 태그), ignored_group(인벤토리의 kube_version 이 적힌 group_vars 그룹 가운데 목록 플레이북에 적용되지 않은 그룹 이름)을 적으세요.

generate_list.yml 은 hosts: localhost 로 돕니다. localhost 는 인벤토리의 어느 그룹에도 없어서 all 의 group_vars 만 받습니다. 목록이 틀린 판으로 나오면 반입한 파일로는 설치가 시작되자마자 '파일이 없다' 로 멈춥니다 — 그것도 폐쇄망 현장에서요.

인벤토리가 사내 미러를 가리키게

/root/ks/inventory/lab/group_vars/all/offline.yml 를 고쳐 registry_host: "registry.lab.internal:5000", files_repo: "http://files.lab.internal" 를 두고, kubespray 문서의 폐쇄망 절대로 kube_image_repo·gcr_image_repo·docker_image_repo·quay_image_repo·github_image_repo{{ registry_host }} 로, github_url·dl_k8s_io_url·storage_googleapis_url·get_helm_url{{ files_repo }}/<원래 도메인> 으로 두세요. 파일은 group_vars/all 에 있어야 합니다.

문서의 팁대로 files_repo 아래에 원래 도메인을 첫 디렉터리로 두면(files_repo/github.com/...) 미러를 채울 때 URL 을 기계적으로 옮길 수 있습니다. 변수를 all 에 두는 이유는 두 가지입니다 — etcd 만 있는 노드도 받아야 하고, 목록 플레이북(localhost)도 이 값을 읽어야 합니다.

목록이 전부 사내 주소가 되었나

./generate_list.sh -i /root/ks/inventory/lab/inventory.ini -e kube_version=1.35.8 로 목록을 다시 만들고 두 파일을 /root/ks/offline/mirror/ 에 복사하세요. files.list 의 모든 줄이 http://files.lab.internal/ 로, images.list 의 모든 줄이 registry.lab.internal:5000/ 로 시작하고, 줄 수가 1단계와 같아야 합니다.

한 줄이라도 원래 도메인이 남아 있으면 그 파일이나 이미지는 폐쇄망에서 받을 수 없습니다. 남은 줄이 있다면 어느 변수가 빠졌는지 그 줄의 도메인이 알려 줍니다.

원본과 미러의 짝

미러를 채우는 사람에게 넘길 대응표를 만드세요. 오프라인 변수를 적용하지 않은 1.35.8 원본 목록과 4단계의 미러 목록을 줄 단위로 짝지어, /root/ks/offline/image-map.tsv원본<TAB>미러 를 한 줄에 하나씩(images.list 의 모든 이미지) 적으세요.

오프라인 변수는 group_vars/all 에 있으니, 원본 목록은 인벤토리 없이 -e kube_version=... 만 주고 만듭니다. 두 목록은 같은 틀에서 나와 순서가 같습니다. 레지스트리 주소만 바뀌고 경로는 그대로라는 점이 미러 설계의 핵심입니다 — 미러 쪽 경로를 바꾸면 이 대응이 깨집니다.

노드가 사내 레지스트리를 믿게

/root/ks/inventory/lab/group_vars/all/offline.ymlcontainerd_registries_mirrors 를 더해, prefix registry.lab.internal:5000 가 host http://registry.lab.internal:5000 를 pull·resolve 로 쓰고 TLS 검증을 건너뛰게(skip_verify: true) 하세요. ansible-inventory --host node1 이 이 목록을 그대로 풀어야 합니다.

kubespray 문서는 containerd 2 와 1.7 의 설정 방법이 다르다고 적습니다. 2 에서는 containerd_registries_mirrors 가 /etc/containerd/certs.d//hosts.toml 로 바뀝니다. 실습용이라 TLS 를 끄지만, 운영에서는 사내 CA 로 서명한 인증서를 쓰고 skip_verify 를 켜지 않는 것이 원칙입니다.

Ansible 도 반입해야 한다

kubespray 의 requirements.txt 로 파이썬 패키지를 /root/ks/offline/pypi/ 에 내려받고(pip download), 인터넷을 쓰지 않는 설치가 그 디렉터리만으로 풀리는지 pip install --dry-run --no-index --find-links /root/ks/offline/pypi -r requirements.txt 로 확인하세요. /root/ks/offline/pypi.jsonwheels(내려받은 파일 수), resolved(dry-run 이 성공했는가, 불리언)를 적습니다.

폐쇄망에서는 제어 노드의 Ansible 도 가져가야 합니다. kubespray 문서가 파이썬 패키지를 '선택' 으로 적은 것은 OS 가 같은 판을 주는 경우를 뜻하는데, 이 판은 ansible==12.3.0 처럼 정확한 판을 요구해서 대개 직접 가져가야 합니다. 내려받을 때와 설치할 때의 파이썬 판과 CPU 아키텍처가 같아야 합니다 — 휠 파일 이름에 그것이 적혀 있습니다.