Hyper-V와 윈도우 쿠버네티스

Jung-Hyun Nam
Oct 1 · 29 min read
Image for post
Image for post
맥북 부트캠프 위에서 구동하는 윈도우 노드를 포함하는 로컬 쿠버네티스 클러스터

You can read the English version here.

쿠버네티스 버전 1.14에서는 처음으로 윈도우 서버를 운영 체제로 사용하는 워커 노드 지원이 정식으로 추가되었습니다. 하지만 그 후로도 많은 개선이 이루어졌는데, 리눅스 버전의 쿠버네티스 워커 노드와 차이가 있던 부분이 좁혀지기 시작했습니다.

개인적으로는 윈도우 쿠버네티스가 프로덕션 환경에서 사용할 준비가 아직 되지 않았다고 보는 부분이 두 가지가 있었는데, 다음의 두 가지 부분입니다.

  • 윈도우 컨테이너와 윈도우 쿠버네티스가 의존하는 네트워크 기능은 호스트 네트워크 서비스 (이하 HNS)를 중심으로 구현됩니다. 쿠버네티스 클러스터 상에 서비스가 만들어지면, 서비스를 하나 만들때마다 트래픽을 라우팅하기 위하여 로컬 수신 포트 자원을 하나씩 소비합니다. 이 때문에 일정 개수 이상의 서비스가 만들어지면 윈도우 워커 노드에서 더 이상의 네트워크 통신이 불가능해집니다.
  • 시스템을 제어할 수 있는 권한 상승 컨테이너라는 컨셉이 구현되어있지 않아 kube-proxy를 수동으로 워커 노드의 서비스로 설치하고 구성해주어야해서 설치하고 사용하기 까다로웠습니다. 무엇보다도 컨테이너 형태가 아니므로 윈도우 워커 노드는 자동으로 새 버전의 쿠버네티스로 업그레이드할 수 없었습니다.

위의 두 가지 문제가 비로소 쿠버네티스 1.19 버전과 함께 어느 정도 해소되었고, 덕분에 로컬 환경에서 윈도우 쿠버네티스 클러스터를 확실하게 구성할 수 있게 되었습니다.

이번 아티클에서는 윈도우 쿠버네티스를 제가 사용하는 맥 북 프로에 부트캠프를 사용하여 직접 구축한 과정을 살펴보려고 합니다.

이번 아티클을 작성하면서 김기혁님의 아래 아티클의 도움을 많이 받았습니다. 다시 한 번 좋은 아티클을 작성해주셔서 감사드립니다.

맥 북에서 만드는 안정적인 Windows 10 환경

그다지 친절하게 설명된 부분이 아닌데, 맥 OS에는 장치가 도난당했을 때 장치 안의 데이터를 보호하기 위한 목적으로 전체 디스크 파티션을 암호화하는 기능인 FileVault 기능이 기본으로 켜져있습니다. Windows에는 BitLocker 기능이 제공되는 것과 같습니다.

안타깝게도 맥 OS에서 FileVault 기능을 활성화한 상태로 부트캠프 설치 도우미로 윈도우 10을 설치하려고 시도하면 모델이나 운영 체제 구성, 버전에 따라 차이가 있지만 설치가 올바르게 진행되지 않을 수 있습니다. 최근에 발매된 인텔 프로세서 기반 맥이 특히 그런 경향이 도드라집니다.

Hyper-V와 같이 복잡한 기능을 사용하려고할 경우 윈도우 10이 올바르게 설치되고 실행이 가능한 상태여야하므로 이 설정을 반드시 끈 상태에서 부트캠프로 윈도우 10 프로를 설치하는 것이 좋습니다.

FileVault를 끄지 않고는 할 수 없는가?

FileVault를 끄지 않고 맥 OS 환경을 벗어나지 않는 방법으로는 맥 OS에서 제공하는 가상화 소프트웨어 중 중첩 가상화 기능을 제공하는 소프트웨어를 사용하는 방법이 있습니다.

그러나 안타깝게도 지금까지의 경험으로는 패러렐즈와 VMware 퓨전이 여기에 해당됩니다. 그러나 중첩 가상화의 성능이 좋지 못하였고 실제로 사용하기에는 힘들었습니다.

FileVault를 끌 수 있는 상황이 아니라면, 다른 대안으로 중첩 가상화가 지원되는 클라우드 컴퓨팅 환경 (예: 마이크로소프트 애저의 Dv3나 Ev3, 또는 베어메탈 인스턴스가 지원되는 퍼블릭 클라우드 컴퓨팅 환경)을 이용할 수 있습니다.

가격적인 측면에서 개인적으로는 마이크로소프트 애저의 Dv3 또는 Ev3 계열 인스턴스의 사용을 추천합니다.

마이크로소프트 애저의 Dv3 및 Ev3 인스턴스에 대한 자세한 정보는 여기를 참고하세요.

먼저 준비할 것

간결한 내용 전달을 위하여 다음의 전제 조건이 미리 구비되어있고, 조건에 일치한다고 가정하겠습니다. 왜 아래의 조건이 모두 일치해야하는지에 대해서는 따로 설명하겠습니다.

  1. 인터넷과의 고속 연결이 가능한 상태이며, 종량제 방식의 회선이 아니어야 합니다. (특히 모바일 네트워크 테더링 인터넷 연결은 권장하지 않습니다.)
  2. 이 아티클은 AMD64 아키텍처 기반의 Hyper-V와 윈도우 컨테이너를 기준으로 쓰여졌습니다.
  3. Hyper-V 호스트 컴퓨터의 메모리 크기는 적어도 16GiB 이상, 디스크는 적어도 512GiB 이상의 SSD로 구성되어있습니다.
  4. 윈도우 10 프로가 설치되어있고 부팅 가능한 상태입니다.
  5. Hyper-V를 윈도우 구성 요소 추가/제거에서 활성화한 상태입니다.
  6. 미국 영어 버전의 윈도우 서버 2019 데이터센터 버전 설치 미디어가 준비된 상태입니다.

Hyper-V 네트워크 구성하기

모든 준비가 끝나면 Hyper-V 관리자 콘솔에서 가상 스위치 관리자 창을 열어 다음 그림과 같이 쿠버네티스 클러스터 내부에서 사용할 목적의 내부용 스위치를 만듭니다.

Image for post
Image for post
가상 스위치 관리자에서 내부용 스위치를 만듭니다.

그리고 이 네트워크 스위치에 합류하는 가상 컴퓨터들이 인터넷과 통신할 수 있도록 인터넷 연결 공유 설정을 해주어야 합니다. 인터넷 연결이 가능한 어댑터를 찾아 아래 그림과 같이 새로 만든 내부용 가상 스위치 쪽으로 공유하도록 설정합니다.

Image for post
Image for post
네트워크 어댑터 속성 — 인터넷 연결이 들어오는 어댑터 — 공유 순으로 접근 가능합니다.

Hyper-V 가상 컴퓨터 만들기

이 아티클에서 설명하는 내용을 구현하기 위해 우분투 리눅스 18.04 LTS 버전을 사용하는 가상 컴퓨터 2대 (한 대는 컨트롤 플레인 노드, 다른 한 대는 워커 노드), 그리고 윈도우 워커 노드를 위한 가상 컴퓨터 1대를 생성해야 합니다.

가상 컴퓨터를 만드는 방법은 다양하지만, 우분투 리눅스의 경우 윈도우 와 마찬가지로 PC 제조사에 납품하는 시나리오를 상정하여 OOBE (Out-Of-Box Experience, 처음 PC를 인도받은 후 전원을 넣었을 때 경험하는 과정) 상태로 시스템을 구성하는 기능을 제공합니다. 이 기능을 응용하는 Hyper-V PC 빨리 만들기용으로 미리 제작된 템플릿을 이용할 수 있습니다.

총 3대의 가상 PC를 만들 때 아래의 조건을 충족하도록 만들면 됩니다.

  • 모든 가상 컴퓨터는 2세대 VM으로 만들도록 합니다.
  • 시스템의 사양이나 목적에 따라 다르겠으나, 가상 컴퓨터마다 최소 2개 이상의 CPU 코어와 최소 2GiB 이상의 메모리를 할당하도록 합니다.
  • 윈도우 VM의 경우 데스크톱 경험이 포함되지 않은 버전으로 설치하는 것이 전체적인 작업 시간 절약에 도움됩니다. 이렇게 설치하는 것을 윈도우 서버 코어 버전으로 설치했다고 말합니다.
  • 각 VM 안에서 실행되는 OS가 모든 보안 패치의 설치를 마친 상태가 되도록 업데이트를 진행합니다. (윈도우 서버 코어에서는 sconfig 명령어를 이용합니다.)
  • 각 VM 안에서 실행되는 OS가 DHCP가 아닌 고정 IP를 사용하도록 네트워크 설정을 변경합니다. (윈도우 서버 코어에서는 sconfig 명령어를 이용합니다.)
  • 각 VM 안의 hosts 파일 (리눅스의 경우 /etc/hosts 파일, 윈도우의 경우 C:\Windows\System32\Drivers\etc\hosts 파일)에 만들어놓은 각 VM의 컴퓨터 이름과 고정 IP 주소를 등록합니다. 제대로 등록했다면 모든 컴퓨터들이 ping 명령을 사용하여 서로의 IP 주소를 확인하고 커뮤니케이션할 수 있어야 합니다.

클라이언트와 서버 모두를 위한 SSH 구성하기

그리고 편리하고 효율적인 진행을 위하여 각 VM에는 SSH로 접속할 수 있도록 설정하고, 이후의 작업은 윈도우 터미널을 사용하여 진행하겠습니다.

윈도우 터미널은 마이크로소프트 스토어에서 설치할 수 있습니다.

윈도우 10 컴퓨터에서 SSH 클라이언트를 구성하는 방법은 아래 글을 참고하여 설정할 수 있습니다.

리눅스에서 SSH 서버를 구성하는 방법은 아래 글을 참고하여 설정할 수 있습니다. 윈도우10 컴퓨터 상에서 만든 SSH 공개 키 ($env:USERPROFILE\.ssh\id_rsa.pub 또는 %USERPROFILE%\.ssh\id_rsa.pub 파일)를 아래 아티클을 참고하여 서버에 등록하면 ID와 비밀 번호 없이 키 인증으로 서버에 접근할 수 있습니다.

마지막으로 윈도우 서버에서 SSH 서버를 구성하는 방법은 아래 글을 참고하여 설정할 수 있습니다. 마찬가지로 윈도우 10 컴퓨터 상에서 만든 SSH 공개 키를 윈도우 서버에 등록해서 사용하면 편리합니다.

여기까지 진행을 마쳤다면 상세한 내용을 하나씩 살펴보도록 하겠습니다.

리눅스 가상 컴퓨터 (공통) 설치 진행하기

이 구간은 컨트롤 플레인 노드와 워커 노드 모두 필요한 구간입니다.

소프트웨어 설치하기

우선 SSH 서버와 함께 필요한 소프트웨어들을 설치합니다.

sudo apt -y install curl vim apt-transport-https
  • curl: 인터넷에서 셸 스크립트를 받아 바로 실행할 때 자주 사용하게 되므로 설치합니다.
  • vim: 파일 편집을 위하여 이 에디터를 사용하겠습니다. vim 대신 nano 등 다른 에디터를 사용해도 무방합니다.
  • apt-transport-https: apt 패키지 관리자에 다른 개발자가 운영하는 업데이트 카탈로그를 추가하기 위한 유틸리티로 쿠버네티스 CLI 도구를 쉽게 설치할 목적으로 사용합니다.

도커 설치 및 구성

이제 도커를 설치합니다. 랜처가 제공하는 자동 설치 스크립트로 간편하게 설치를 진행할 수 있습니다.

curl https://releases.rancher.com/install-docker/19.03.sh | sh

설치를 진행한 후에는 현재 사용자 계정을 도커 사용자 그룹에 포함시켜 sudo 명령 없이도 docker CLI로 도커 데몬에 연결할 수 있게 만듭니다. 그 다음 한 번 로그아웃하고 다시 로그인합니다.

sudo usermod -aG docker $USERlogout

이어서 쿠버네티스가 정상적으로 작동할 수 있도록 만들기 위하여 도커의 설정 파일 daemon.json 파일을 수정합니다.

sudo vim /etc/docker/daemon.json

설정 파일의 내용은 다음과 같이 구성합니다.

{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"f
},
"storage-driver": "overlay2"
}

변경된 내용을 저장한 후 도커 데몬을 다시 실행하기 위해 아래 명령어를 입력합니다.

sudo systemctl restart docker

시스템 설정 변경하기

쿠버네티스가 작동하려면 스왑을 꺼야 합니다. 그리고 플란넬 CNI를 윈도우 워커 노드와 원활하게 연동할 수 있도록 리눅스 노드들의 커널 파라미터를 수정해야 합니다.

우선 스왑을 비활성화하기 위하여 다음 명령어를 실행합니다.

sudo swapoff -a

그 다음 시스템을 다시 시작한 후에도 스왑을 비활성화한 상태를 유지할 수 있도록 다음 명령어를 실행하여 /etc/fstab 파일의 내용을 고쳐놓습니다.

sudo sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab

마지막으로 윈도우 워커 노드와 함께 플란넬 CNI를 위한 설정 변경이 필요한데, 아래 명령어를 실행하여 네트워크 설정을 변경합니다. (관련 공식 문서 참고)

sudo sysctl net.bridge.bridge-nf-call-iptables=1

쿠버네티스 CLI 설치하기

이제 쿠버네티스 클러스터를 설치, 구성, 관리할 수 있는 CLI 도구를 설치할 차례입니다.

구글이 호스팅하는 apt용 업데이트 카탈로그를 시스템에 등록해야 합니다. 아래 명령어를 실행합니다.

curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -cat <<EOF | sudo tee /etc/apt/sources.list.d/kubernetes.list
deb https://apt.kubernetes.io/ kubernetes-xenial main
EOF
sudo apt update

그 다음 관련 도구를 설치한 후, 선택한 버전이 고정되도록 합니다.

sudo apt-get install -y kubelet kubeadm kubectlsudo apt-mark hold kubelet kubeadm kubectl

각 노드 (컨트롤 플레인, 워커)에서 사용할 kubeadm 도구가 잘 설치되었는지 확인하기 위하여 다음 명령어를 실행해봅니다.

kubeadm version

버전 정보가 정확히 표시되면 설치가 완료된 것입니다.

리눅스 컨트롤 플레인 노드 설치 진행하기

컨트롤 플레인 노드를 설치하기 위하여 아래 명령어를 입력하여 클러스터를 초기화합니다.

sudo kubeadm init --pod-network-cidr=10.244.0.0/16

참고로 이 명령어에서 --pot-network-cidr 명령어에 대입하는 CIDR 범위는 오버레이 네트워크로 이어질 다른 노드와 공유할 파드에 할당될 IP 대역을 나타내는 것으로 적절한 값을 선택합니다. 로컬 테스트 환경을 위한 것이므로 위의 기본값을 그대로 사용해도 무방합니다.

⚠ 중요 — 잠시 기다리면 설치가 완료될 것입니다. 설치가 끝나면 다른 워커 노드를 위한 가입 명령어가 나타나는데, 명령어를 잘 복사해둡니다.

그 다음, 클러스터에 접근할 수 있는 기본 인증 정보가 들어있는 관리자용 설정 파일을 홈 디렉터리에 복사합니다.

mkdir -p $HOME/.kube 
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

위의 명령어를 실행한 다음 모든 파드가 정상적으로 구동되는 것을 모니터링하기 위하여 아래 명령어를 실행합니다.

watch kubectl get pods -A

모든 파드가 실행 중 상태로 나타나면 Ctrl+C 키를 눌러 실행을 종료합니다.

리눅스용 플란넬 CNI 설치하기

이제 플란넬 CNI를 설치할 차례입니다. 기본으로 제공되는 YAML 파일을 그대로 사용할 수는 없고, 편집해서 사용해야 합니다.

우선 kube-flannel.yml 파일을 다운로드합니다.

curl -L https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml -o kube-flannel.yaml

그 다음 텍스트 편집기로 YML 파일을 열어 net-conf.json: | 문자열을 찾습니다. 아마 다음과 비슷하게 되어있을 것입니다.

net-conf.json: |
{
"Network": "10.244.0.0/16",
"Backend": {
"Type": "vxlan"
}
}

여기서 Network 부분은 클러스터 초기화 단계에서 지정한 파드 CIDR 대역과 일치하도록 값을 고칩니다. 그리고 Backend 속성 아래에는 다음의 항목을 추가해야 합니다.

  • VNI: 4096
  • Port: 4789

완성된 내용은 다음과 같습니다.

net-conf.json: |
{
"Network": "10.244.0.0/16",
"Backend": {
"Type": "vxlan",
"VNI" : 4096,
"Port": 4789
}
}

변경된 YAML 파일을 배포하기 위하여 아래 명령어를 입력합니다.

kubectl apply -f kube-flannel.yml

위의 명령어를 실행한 다음 모든 파드가정상적으로 구동되는 것을 모니터링하기 위하여 아래 명령어를 실행합니다.

watch kubectl get pods -A

리눅스 워커 노드 설치 진행하기

kubeadm init 명령어로 초기 클러스터 구성을 할 때 발급받은 명령어를 워커 노드에 sudo 명령어를 붙여 초기화하면 설치가 손쉽게 끝납니다.

다만, 명령어를 아주 나중에 실행하려는 경우 — 또는 — 가입 명령어를 미처 기록하지 못한 경우 컨트롤 플레인 노드에서 다음 명령어를 실행하여 새로운 토큰과 함께 가입용 명령어를 재발급할 수 있습니다.

kubeadm token create --print-join-command

혹은 기존의 토큰 값과 CA 인증서 해시 값을 복원할 수 있습니다.

$MASTER_IP=(컨트롤 플레인 노드의 IP 주소)$TOKEN=kubeadm token list -o jsonpath='{.token}'$CA_CERT_HASH=openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'

복원한 값을 사용하여 아래 명령어와 같은 형태로 새로운 워커 노드 가입 시 사용할 수 있습니다.

sudo kubeadm join $MASTER_IP:6443 --token $TOKEN --discovery-token-ca-cert-hash sha256:$CA_CERT_HASH

노드 가입이 완료되면 컨트롤 플레인 노드의 셸로 이동하여 kubectl 명령어로 노드의 상태를 확인합니다. Ready 상태로 바뀌기까지 다소 시간이 걸릴 수 있습니다.

watch kubectl get nodes -o wide

윈도우 워커 노드 구성하기

이제 윈도우 워커 노드를 구성할 차례입니다.

윈도우 워커 노드의 네트워킹 설정에 대하여

윈도우용 CNI 플러그인은 HNS가 제공하는 정보와 API를 기반으로 네트워크를 구성합니다.

이 때 윈도우 운영 체제가 드러내는 네트워크 어댑터에 대한 정보들은 리눅스 및 유닉스와는 달리 사람이 인지할 수 있는 표시 이름이나 완전히 규칙성이 없는 고유 아이디만으로 찾을 수 있도록 되어있어, 네트워크 어댑터를 표시 이름 기준으로 찾게 됩니다.

이 때문에 미국 영어 버전의 윈도우 서버를 설치해서 쓰는 것이 편리합니다. 비 영어권 버전의 윈도우 서버를 사용할 경우 기본 이더넷 어댑터의 이름의 Ethernet이 아닌 다른 문자열일 수 있습니다.

또한 워커 노드로 추가할 윈도우 컴퓨터들은 동일한 하드웨어 구성을 가져야 합니다. 쿠버네티스 1.19 버전부터는 랜처가 윈도우용 쿠버네티스 프로젝트에 기여한 WINS 서버를 사용하여 관리자 권한이 필요한 동작은 컨테이너에서 WINS 서버로 올려보내도록 하는 방식으로 kube-proxy를 컨테이너로 배포할 수 있게 만들었습니다.

이 때 기본 이더넷 어댑터 이름이 지정된 것과 다르게 시스템에 등록되어있으면 데몬 셋이 제대로 실행되지 않을 수 있고, 상황에 따라 매번 수정해야 할 수 있습니다.

따라서 이 조건에 일치하지 않을 경우 아래 단계를 수행할 때 제대로 동작하지 않을 경우 조건에 맞게 수정하면서 진행해야 합니다.

쿠버네티스 클러스터 버전 확인하기

윈도우용 쿠버네티스 워커 노드를 추가하는 과정은 리눅스와 다릅니다. 따라서 몇 가지 정보가 분명히 일치하는지 확인하고 계속 진행해야 합니다. 우선 컨트롤 플레인 노드에서 아래 명령어를 실행하여 클러스터에 참가하는 모든 노드들의 쿠버네티스 버전이 일치하고, 어떤 버전을 사용하는지 확인합니다.

kubectl get nodes -o wide

윈도우 서버 버전 확인하기

글의 서두에서 이야기하였듯 완전한 쿠버네티스 기능을 윈도우에서 사용할 수 있도록 반드시 최신 버전의 윈도우 버전으로 업그레이드해야 합니다. 지금 설치된 윈도우 서버의 버전을 우선 아래 명령어로 확인합니다.

cmd.exe /s /c ver

실행한 후 나타나는 버전 정보가 다음보다 높게 표시되어야 합니다.

Microsoft Windows [Version 10.0.17763.1432]

메이저 버전, 마이너 버전, 빌드 버전이 10.0.17763 미만인 경우 윈도우 서버 2019가 아니기 때문에 윈도우 쿠버네티스를 사용하는데 제약이 있거나 사용이 불가능할 수 있습니다. 여기에 해당하는 경우 제자리 업그레이드를 시도하거나, 윈도우 서버 2019에서 작업을 다시 진행해야 합니다.

앞의 세 버전 번호가 일치하지만 마지막 버전 번호가 다른 경우가 있습니다.마지막 번호는 1432 이상이어야 합니다. HNS 네트워크의 DSR 로드 밸런서 지원이 정식으로 추가된 버전이 해당 버전입니다.

만약 위 버전보다 낮은 경우 윈도우 업데이트를 실행하여 최신 버전의 월간 업데이트를 설치하거나, 마이크로소프트 업데이트 카탈로그 사이트에 방문하여 KB4571748 업데이트 패키지를 직접 다운로드하여 설치할 수 있습니다.

윈도우용 플란넬 CNI 배포하기

네트워크 어댑터 이름이 Ethernet과 일치하는지 확인하기 위하여, 윈도우 파워셸 명령어로 다음과 같이 확인해봅니다.

Get-NetAdapter

이름을 확인한 다음에는 윈도우용 kube-proxy 데몬 셋을 배포합니다. 이 때 v1.19.2 부분은 정확한 버전으로 대체해야 합니다. 다음과 같이 컨트롤 플레인 노드에서 명령어를 실행합니다.

curl -L https://github.com/kubernetes-sigs/sig-windows-tools/releases/latest/download/kube-proxy.yml | sed 's/VERSION/v1.19.2/g' | kubectl apply -f -

이제 WINS 서버를 사용하는 윈도우용 플란넬 CNI 플러그인의 데몬 셋을 배포해야 합니다. 다음과 같이 컨트롤 플레인 노드에서 실행합니다.

kubectl apply -f https://github.com/kubernetes-sigs/sig-windows-tools/releases/latest/download/flannel-overlay.yml

이더넷 어댑터의 이름이 Ethernet 이 아니면 아래 명령어처럼 수정하여 진행하도록 합니다. (sed 명령어에서 첫 번째 부분이 바꿀 문자열, 두 번째 부분은 바꾸려는 문자열입니다.)

curl -L https://github.com/kubernetes-sigs/sig-windows-tools/releases/latest/download/flannel-overlay.yml | sed 's/Ethernet/Ethernet0 2/g' | kubectl apply -f -

아직 윈도우 노드를 추가하기 전이므로 일단 이 상태에서 계속 진행합니다.

엔터프라이즈용 도커 설치하기

윈도우 서버용 도커는 기본적으로 윈도우 서버 라이선싱 비용 안에 가격이 포함되어있습니다. 그래서 마이크로소프트는 본인들이 제공하는 패키지 리포지터리를 통하여 설치할 수 있도록 무료로 제공합니다. 다음의 설치 방법에 따라 설치를 진행하겠습니다.

주의: 아래 명령어로 설치하지 않고 도커 공식 웹 사이트 및 관련 웹 사이트에서 설치하는 윈도우용 도커는 윈도우 서버에서 프로덕션용으로 사용할 수 없는 커뮤니티/오픈소스용 도커 데스크톱 버전이거나 윈도우 컨테이너를 지원하지 않는 도커 툴 박스이므로 착오없도록 주의합니다.

우선 도커 설치를 위한 종속성을 먼저 설치합니다.

Install-Module -Name DockerMsftProvider -Repository PSGallery -Force

그 다음 최신 버전의 엔터프라이즈용 도커를 설치합니다.

Install-Package -Name docker -ProviderName DockerMsftProvider

도커 서비스가 시스템 시작과 함께 같이 시작되도록 도커 서비스 시작 모드를 자동 시작으로 변경합니다.

Set-Service -Name 'docker' -StartupType Automatic

도커 엔진 설치 직후에는 시스템을 다시 시작해야 하므로 아래 명령어를 실행합니다.

Restart-Computer -Force

윈도우용 쿠버네티스 워커 노드 설치하기

이제 윈도우용 쿠버네티스 워커 노드를 설치할 차례입니다. 쿠버네티스 프로젝트에서 활동하는 윈도우 SIG 팀이 만든 파워셸 스크립트를 사용하여 간단하게 설치를 완료할 수 있습니다.

curl.exe -LO https://github.com/kubernetes-sigs/sig-windows-tools/releases/latest/download/PrepareNode.ps1

다운로드할 때에는 윈도우 서버 2019에 내장되어있는 curl.exe 유틸리티를 사용하여 다운로드합니다.

curl.exe 는 파워셸의 Invoke-WebRequest 명령어와는 달리 인터넷 익스플로러에 대한 종속성이 없고, 리눅스의 curl 명령어를 직접 윈도우용으로 포팅한 것이므로 익숙하게 사용할 수 있습니다.

그 다음, 설치한 쿠버네티스 클러스터의 버전을 확인하여 파라미터를 적절하게 아래 명령어에 치환하여 파워셸 스크립트를 실행합니다. 여기서는 v1.19.2 버전을 설치했습니다.

.\PrepareNode.ps1 -KubernetesVersion v1.19.2

명령어를 실행하고나면 C:\k 위치에 kubeadm.exe 를 비롯한 필요한 프로그램 파일들이 복사됩니다. 이 디렉터리로 이동한 다음, 컨트롤 플레인 노드를 초기화한 후 발급받았던 명령어를 여기서도 실행합니다.

cd c:\kkubeadm.exe join <컨트롤 플레인 노드 IP>:6443 --token <토큰> --discovery-token-ca-cert-hash sha256:<CA 인증서 해시 값>

윈도우 워커 노드의 가입이 완료되면 앞 단계에서 등록한 데몬 셋이 자동으로 윈도우 워커 노드로 CNI 플러그인을 배포하기 시작합니다.

이 때 sigwindowstools/flannel 이미지는 윈도우 서버 코어를 베이스 이미지로 사용하기 때문에 초기에 이미지를 가져올 때 시간이 많이 걸리며, 컨테이너가 실행되어 기능이 동작할 때까지 노드는 Not Ready 상태로 남아있게 됩니다.

배포 중인 데몬 셋과 연결된 파드가 사용하려는 이미지의 이름과 태그를 찾은 후, 해당 이미지 정보를 윈도우 워커 노드의 셸에서 docker pull 명령어로 이미지를 가져오려고 시도하면 현재 어디까지 이미지를 다운로드했는지 확인할 수 있습니다.

테스트 애플리케이션 배포하기

윈도우 노드의 준비가 완료되면 이제 리눅스 컨테이너, 윈도우 컨테이너가 한 번에 어우러져 실행되는 복합 애플리케이션이 잘 작동하는지 시험해볼 차례입니다.

배포하려는 애플리케이션은 애저 쿠버네티스 서비스용 샘플로 개발된 AzureVote라는 파이썬 장고와 레디스로 구성된 간단한 웹 애플리케이션입니다.

여기서 레디스 컨테이너는 마이크로소프트 오픈 테크놀로지스 (구 법인)에서 만든 윈도우용 레디스 포팅 버전을 제가 윈도우 서버 2019 베이스 이미지를 기반으로 컨테이너로 만든 것입니다.

애플리케이션이 정상적으로 작동한다면 파이썬 장고 컨테이너로 접속했을 때 투표 화면이 표시되어야 합니다.

다음과 같은 YAML 파일을 준비하겠습니다.

apiVersion: apps/v1
kind: Deployment
metadata:
name: azure-vote-back
spec:
selector:
matchLabels:
app: azure-vote-back
replicas: 1
template:
metadata:
labels:
app: azure-vote-back
spec:
containers:
- name: azure-vote-back
image: rkttu/redis-windows:3.0-1809
ports:
- containerPort: 6379
name: redis
nodeSelector:
"beta.kubernetes.io/os": windows
---
apiVersion: v1
kind: Service
metadata:
name: azure-vote-back
spec:
ports:
- port: 6379
selector:
app: azure-vote-back
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: azure-vote-front
spec:
selector:
matchLabels:
app: azure-vote-front
replicas: 1
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
minReadySeconds: 5
template:
metadata:
labels:
app: azure-vote-front
spec:
containers:
- name: azure-vote-front
image: microsoft/azure-vote-front:v1
ports:
- containerPort: 80
resources:
requests:
cpu: 250m
limits:
cpu: 500m
env:
- name: REDIS
value: "azure-vote-back"
nodeSelector:
"beta.kubernetes.io/os": linux
---
apiVersion: v1
kind: Service
metadata:
name: azure-vote-front
spec:
type: LoadBalancer
ports:
- port: 80
selector:
app: azure-vote-front

위와 같이 만든 YAML 파일을 kubectl apply 명령으로 배포해보겠습니다.

kubectl apply -f azurevote.yaml

그 다음, 모든 Pod이 Ready 상태로 나타날 때까지 모니터링합니다. 역시 최초 배포이므로 베이스 이미지 다운로드에 시간이 걸립니다.

watch kubectl get pods -A

Pod이 제대로 구동되었는지 확인해보기 위하여 Python Django 프론트엔드 Pod의 IP 주소를 확인하여 curl 명령어로 응답을 확인해봅니다. HTML 페이지가 렌더링되고 있으면 Windows Server 위에서 실행되고 있는 Redis 컨테이너와 정상적으로 연결이 완료된 것입니다.

Image for post
Image for post
Pod의 정상 동작 여부 확인

이제 클러스터 밖에서 접속해볼 수 있도록 만들어진 프론트엔드 서비스에 외부 IP를 부여해야 합니다. 관리형 쿠버네티스 서비스와 다르게 Hyper-V에서는 로드밸런서로 부를 만한 구성 요소가 없어서 수동으로 외부 IP 주소를 할당해야 하며, 보통은 워커 노드의 IP 주소로 정합니다.

앞 단계에서 설정한 컨트롤 플레인 노드 또는 리눅스 워커 노드의 네트워크 상의 IP 주소를 확인하여 다음의 명령어를 실행합니다.

kubectl patch svc azure-vote-front -p '{"spec":{"externalIPs":["192.168.137.101"]}}'

그 다음, 윈도우 10 PC에서 해당 IP 주소로 웹 브라우저를 열어 접속하면 브라우저에 투표 페이지가 표시되는 것을 볼 수 있습니다.

Image for post
Image for post
AzureVote 앱 실행 결과

아쉽게도 윈도우 워커 노드의 IP 주소로는 이렇게 연결을 라우팅할 수 없었습니다.

대신 윈도우 워커 노드에 떠있는 웹 서버를 리눅스 워커 노드를 통해 라우팅하는 옵션을 사용하여 IIS 컨테이너에서 실행 중인 웹 사이트를 클러스터 외부로 서비스하도록 만들 수 있습니다. 예를 들면 다음과 같습니다.

apiVersion: v1
kind: Pod
metadata:
labels:
name: iis
name: iis
namespace: default
spec:
containers:
- image: microsoft/iis
imagePullPolicy: Always
name: iis
ports:
- containerPort: 80
nodeSelector:
beta.kubernetes.io/os: windows
---
apiVersion: v1
kind: Service
metadata:
labels:
name: iis
name: iis
spec:
ports:
- port: 8080
targetPort: 80
nodePort: 30080
selector:
name: iis
type: NodePort
Image for post
Image for post
로컬 Windows 쿠버네티스 클러스터에서 실행 중인 IIS 컨테이너

로컬 클러스터의 저장과 복구

클라우드나 데이터 센터 상에서 실행되는 클러스터와 달리 저는 맥북 프로에 이 클러스터를 만들었습니다. 사용하지 않을 때도 이 VM 클러스터를 계속 띄우는 것은 낭비이기도하고, 배터리 소비도 무시할 수 없을 것입니다.

이 때 로컬 클러스터에 참가하는 VM들을 순서에 맞추어 저장하고 복구하는 것을 테스트해보니 잘 작동해서 팁으로 공유드립니다. 컨트롤 플레인 노드부터 워커 노드 순으로 사용하지 않을 때 순서대로 저장시키고, 다시 사용할 때에도 컨트롤 플레인 노드부터 워커 노드 순으로 복구시키면 정상적으로 작동할 것입니다.

Image for post
Image for post
컨트롤 플레인 노드부터 워커 노드 순으로 저장하고 필요할 때 시작하면 배터리를 절약할 수 있습니다.

마무리

원래 이 아티클을 작성할 때에는 2020년 여름에 공개된 오픈 소스 버전의 윈도우용 칼리코 CNI 플러그인을 사용하는 것이 목표였습니다. 하지만 WINS 서버에 맞추어 칼리코 CNI 플러그인을 클러스터에 데몬 셋으로 배포하는 것은 개발이 필요한 부분이고 아티클의 범위를 벗어나는 부분이라 다루지 못했습니다.

그리고 아직 시간이 더 필요한 부분이지만, 추후에는 윈도우 쿠버네티스 역시 리눅스처럼 도커 엔터프라이즈 에디션을 직접 제어하는 방식이 아닌 윈도우용 containerd로 디커플링되는 것도 기대해볼 수 있을 것 같습니다. 이 기능이 정식으로 도입되면, 중첩 가상화가 필요하다는 한계가 있기는 하지만 OS 버전을 엄격하게 맞추어야 하는 불편한 부분을 해소할 수 있을 것입니다.

글에 대해 더 궁금하신 점이 있거나 자세히 알고 싶으신 부분이 있다면 댓글로 이야기하실 수 있습니다.

Beyond the Windows, Korean Edition

Beyond the Windows의 한국어 버전입니다.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store