폐쇄망에 쿠버네티스 클러스터를 설치하려면, 인터넷이 되는 환경에서 모든 파일을 모아 반입하는 과정이 선행되어야 한다. 이 글은 그 전체 흐름을 정리한 거다. 파일 준비 과정은 오프라인 파일 준비에서 다루니, 여기서는 반입 이후의 설치 과정을 중심으로 적는다.

1. 두 개의 환경

설치는 두 환경으로 나뉜다.

  • Packaging 서버 (온라인): 인터넷이 되는 곳에서 바이너리와 컨테이너 이미지, 리눅스 패키지를 모아 outputs 폴더에 패킹한다.
  • Agent 서버 (오프라인): 반입된 outputs를 받아 로컬 레지스트리, 패키지 저장소, 파일 서버를 구성하고 Ansible을 돌린다.

Agent 서버는 클러스터 대상 노드와 같은 사설망에 있어야 한다. Agent → 노드는 SSH, 노드 → Agent는 웹 서버 포트(80)와 레지스트리 포트(35000)로 통신한다.

2. Agent 서버 셋업

outputs 폴더를 Agent 서버로 옮긴 뒤, setup-all.sh를 실행하면 된다. 이 스크립트가 하는 일은 순서대로 이렇다.

setup-all.sh
├── setup-container.sh    # containerd 설치 + registry, nginx 이미지 로드
├── start-nginx.sh        # Nginx 컨테이너 실행 (패키지/바이너리 파일 서버)
├── start-registry.sh     # Docker registry 컨테이너 실행 (컨테이너 이미지)
├── load-push-all-images.sh  # 이미지 로드 + 로컬 registry에 push
└── start-ansible.sh      # Ansible 플레이북 컨테이너 실행

containerd 설치

Agent 서버에 containerd를 설치한다. install-containerd.sh가 containerd, runc, nerdctl, CNI 플러그인 바이너리를 내려받아 설치한다. 버전은 .env에 정의되어 있다.

# .env에서 주요 버전
RUNC_VERSION=1.2.6
CONTAINERD_VERSION=2.0.5
NERDCTL_VERSION=2.0.5
CNI_VERSION=1.4.1

NOTE

이 버전 값들은 Kubespray의 checksums.yml과 반드시 일치해야 한다. Kubespray가 설치할 containerd 버전과 Agent 서버의 containerd 버전이 어긋나면, 노드에서 이미지 pull이 안 되는 등 예상치 못한 문제가 터진다.

Nginx (파일 서버)

리눅스 패키지와 바이너리를 호스팅하는 Nginx 컨테이너다. --network host로 띄워서 80 포트로 접근 가능하게 한다.

$CONTAINER_CLI container run -d \
    --network host \
    --restart always \
    --name nginx \
    -v ${BASEDIR}:/usr/share/nginx/html \
    -v ${BASEDIR}/nginx-default.conf:/etc/nginx/conf.d/default.conf \
    nginx:${NGINX_VERSION}

노드에서 http://<agent-ip>/로 접속하면 패키지 저장소로 쓸 수 있다.

Docker Registry (컨테이너 이미지)

Kubespray가 pull할 컨테이너 이미지를 올려두는 레지스트리다.

$CONTAINER_CLI run -d \
    --network host \
    -e REGISTRY_HTTP_ADDR=0.0.0.0:${REGISTRY_PORT} \
    --restart always \
    --name registry \
    -v $REGISTRY_DIR:/var/lib/registry \
    registry:${REGISTRY_VERSION}

load-push-all-images.shimages.list에 있는 모든 이미지를 로드하고, registry.k8s.io 같은 접두사를 떼낸 뒤 localhost:35000에 push한다. 노드에서는 containerd 설정에 localhost:35000을 mirror로 등록해서 이미지를 당겨온다.

Ansible 컨테이너

플레이북을 실행할 컨테이너다. k8s-cluster-playbook 이미지를 로드하고 sleep infinity로 띄워둔다.

$CONTAINER_CLI run -d \
    --network host \
    --restart always \
    --name ansible \
    k8s-cluster-playbook:latest

이 컨테이너 안에 Kubespray 서브모듈, Ansible, kubectl이 다 들어있다. 여기서 ansible-playbook을 실행하면 된다.

3. 클러스터링

Agent 서버 셋업이 끝나면, Ansible 컨테이너 안에서 클러스터를 구축한다.

  1. bootstrap: 대상 노드에 SSH 키 배포, sudoer 설정, Python 설치
  2. NVIDIA 드라이버: GPU 노드에 드라이버·CUDA·toolkit 설치 (오프라인)
  3. 컨테이너 런타임: containerd 설치와 containerd 설정 (로컬 registry mirror)
  4. 클러스터 구축: Kubespray cluster.yml 실행
  5. 컨테이너 이미지 로드: 노드에 플러그인 컴포넌트 이미지 사전 로드
  6. 플러그인 설치: Cilium, Longhorn, SigNoz 등 Helmfile로 배포

4. Agent 서버 필요 환경

  • 리눅스 환경이 기본. 윈도우는 Docker Desktop 설치가 필요하고, Hyper-V 활성화와 UEFI 하드웨어 가상화 옵션이 켜져 있어야 한다.
  • Agent PC와 클러스터 대상 노드 간 다이렉트 통신 또는 프록시 필요
    • Agent → 노드: SSH 포트
    • 노드 → Agent: 웹 서버 포트 (80), 레지스트리 포트 (35000)

5. 서버 노드 필요 환경

  • authorized_keys에 Agent의 공개키 등록
  • 사용자 계정이 sudo 가능해야 함