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

閉域網のミラーとプライベート CA

社内レジストリミラーから元の名前のまま取得する

LabHub 에서 이어서 보기

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

이 실습은 진짜 k3s 에서 돕니다

VM 안에 k3s 한 대(v1.33.3+k3s1)가 떠 있고, skopeo·podman 과 우분투의 docker-registry 패키지(CNCF distribution 레지스트리)가 깔려 있습니다. 처음 뜨는 데 몇 분이 걸립니다. VM 은 처음에는 인터넷(80/443)에 닿습니다 — 3단계까지가 연결된 반입 준비 이고, 4단계에서 여러분이 바깥 송신을 막아 폐쇄망 으로 바꿉니다. 채점은 바깥에서 VM 의 8899 포트로 들어오는 에이전트가 하므로, 이미 맺은 연결과 루프백을 막으면 채점이 끊깁니다.

목표

사설 CA 로 사내 레지스트리를 HTTPS 로 세우고 이미지를 다이제스트 그대로 옮긴 뒤, 바깥이 막힌 상태에서 이미지 이름을 바꾸지 않고 podman·containerd·쿠버네티스가 사내 미러에서 받게 한다.

왜 중요한가

폐쇄망에서 매니페스트의 이미지 이름을 사내 레지스트리 주소로 전부 바꾸면, 차트와 매니페스트가 바깥과 갈라지고 다음 버전을 받을 때마다 다시 고쳐야 한다. 미러는 이름은 그대로 두고 "그 레지스트리는 여기서 받는다" 만 런타임에 알려 준다. 런타임마다 설정 파일이 다르다는 것이 함정이다 — podman 은 registries.conf, containerd 는 hosts.toml, k3s 는 registries.yaml. 그리고 모두 사설 CA 를 따로 알려 줘야 한다.

예상 60분이다. 세션이 끝나면 VM 이 사라지니 남기고 싶은 파일은 종료 전에 따로 보관한다.

단계

  1. /root/registry/pki 에 루트(ca.crt·ca.key, CN Airgap Internal Root CA)와 registry.airgap.internal 인증서(registry.crt·registry.key, SAN)를 만들고 /etc/hosts127.0.0.1 registry.airgap.internal 을 더한다.
  2. /etc/docker/registry/config.yml 로 사내 레지스트리가 127.0.0.1:5000 에서 그 인증서로 HTTPS 를 내주게 하고, 서비스를 살려 부팅 때도 뜨게 한다. 레지스트리 서비스 계정이 키를 읽을 수 있어야 한다.
  3. 연결된 동안 registry.k8s.io/e2e-test-images/busybox:1.36.1-1registry.k8s.io/pause:3.10 을 사내 레지스트리의 같은 경로(registry.airgap.internal:5000/e2e-test-images/busybox:1.36.1-1, .../pause:3.10)로 다이제스트를 보존해 옮기고, /root/registry/digests.txt원래이름 다이제스트 를 한 줄씩 적는다.
  4. 다시 돌려도 규칙이 한 벌만 남는 /root/registry/egress.sh 로 바깥 송신을 막는다(체인 AIRGAP-EGRESS, OUTPUT·FORWARD 에서 한 번씩, 루프백·이미 맺은 연결·10.42.0.0/16·10.43.0.0/16 은 살린다).
  5. podman: /etc/containers/registries.conf.d/50-airgap-mirror.confregistry.k8s.io 의 미러를 사내 레지스트리로 두고 사설 CA 를 알려 준 뒤, 원래 이름 registry.k8s.io/e2e-test-images/busybox:1.36.1-1 로 pull 한다.
  6. containerd: /root/registry/certs.d/registry.k8s.io/hosts.toml 을 손으로 쓰고, k3s ctr -n airgap-ctr images pull --hosts-dir /root/registry/certs.d registry.k8s.io/pause:3.10 으로 받는다.
  7. 쿠버네티스: /etc/rancher/k3s/registries.yaml 로 k3s 가 사내 미러를 쓰게 하고 k3s 를 다시 띄운 뒤, 네임스페이스 airgap 에 원래 이름·imagePullPolicy: Always 인 파드 mirror-busybox(매니페스트 /root/registry/mirror-busybox.yaml)를 Running 으로 만든다.
  8. /root/registry/mirror-record.json 에 반입 기록을 남긴다 — images 배열의 항목마다 ref·mirror_ref·digest·pulled_by(podman·ctr·kubelet 가운데 실제로 받은 것들), 최상위에 egress_blocked.

참고

사내 레지스트리 인증서

/root/registry/pki 에 루트(ca.crt·ca.key)와 registry.airgap.internal 인증서(registry.crt·registry.key, SAN)를 만들고 /etc/hosts 에 이름을 더한다.

루트는 자기 서명에 CA:TRUE, 서버 인증서는 루트로 서명하면서 확장 파일로 SAN 을 줍니다. 사설 CA 모듈과 같은 절차입니다.

사내 레지스트리를 HTTPS 로

/etc/docker/registry/config.yml 로 레지스트리가 127.0.0.1:5000 에서 그 인증서로 HTTPS 를 내주게 하고, 서비스를 살려 부팅 때도 뜨게 한다.

설정의 http 절에 주소와 tls(인증서·키 경로)를 줍니다. 서비스는 전용 계정으로 돌기 때문에 키를 그 계정이 읽을 수 있는 곳·권한으로 두어야 합니다. 안 뜨면 journalctl -u docker-registry 부터 보세요.

다이제스트를 보존해 옮기기

두 이미지를 사내 레지스트리의 같은 경로로 다이제스트를 보존해 옮기고, /root/registry/digests.txt원래이름 다이제스트 를 한 줄씩 적는다.

skopeo copy 는 레지스트리에서 레지스트리로 바로 옮깁니다. 여러 아키텍처 목록을 통째로 옮겨야 다이제스트가 바깥과 같습니다. 사내 레지스트리의 CA 는 /etc/containers/certs.d/<호스트:포트>/ca.crt 에 두면 skopeo 와 podman 이 함께 씁니다.

바깥 송신을 막아 폐쇄망 만들기

다시 돌려도 규칙이 한 벌만 남는 /root/registry/egress.sh 로 바깥 송신을 막는다.

새 체인을 만들어 OUTPUT 과 FORWARD 맨 앞에서 그리로 보내면, 비우고 다시 채우는 방식으로 몇 번을 돌려도 같은 모양이 됩니다. 채점 에이전트와 쿠버네티스 대역을 먼저 살리세요.

podman: registries.conf 의 mirror

/etc/containers/registries.conf.d/50-airgap-mirror.confregistry.k8s.io 의 미러를 사내 레지스트리로 두고, 원래 이름으로 busybox 를 pull 한다.

registries.conf 의 [[registry]] 는 prefix 로 어떤 이름에 적용할지, [[registry.mirror]] 는 먼저 시도할 위치를 적습니다. 이름은 바꾸지 않습니다. 사설 CA 는 3단계에서 둔 certs.d 가 그대로 쓰입니다.

containerd: hosts.toml 을 손으로

/root/registry/certs.d/registry.k8s.io/hosts.toml 을 쓰고, k3s ctr -n airgap-ctr images pull --hosts-dir /root/registry/certs.d registry.k8s.io/pause:3.10 으로 받는다.

디렉터리 이름이 원래 레지스트리이고, 파일 안의 server 가 원래 주소, [host."..."] 가 먼저 시도할 미러입니다. 미러에는 pull·resolve 권한과 CA 경로를 적습니다.

쿠버네티스: registries.yaml 과 Always 파드

/etc/rancher/k3s/registries.yaml 로 k3s 가 사내 미러를 쓰게 하고 다시 띄운 뒤, imagePullPolicy: Always 인 파드 mirror-busybox(매니페스트 /root/registry/mirror-busybox.yaml)를 네임스페이스 airgap 에서 Running 으로 만든다.

mirrors 에 원래 레지스트리와 endpoint 를, configs 에 미러 주소의 tls ca_file 을 적습니다. k3s 문서대로 바꾼 뒤에는 k3s 를 다시 띄워야 합니다. 이미지 이름은 원래 그대로 둡니다 — Always 여도 미러에서 태그를 풀 수 있으면 뜹니다.

반입 기록을 레지스트리·런타임과 대조

/root/registry/mirror-record.json 에 이미지마다 ref·mirror_ref·digest·pulled_by 와 최상위 egress_blocked 를 남긴다.

다이제스트는 사내 레지스트리에 물어 뽑고, pulled_by 는 podman·ctr·kubelet 가운데 실제로 그 이미지를 받은 쪽을 적습니다. 값은 손으로 옮기지 말고 명령 출력에서 모으세요.