TOPIC/Infra

Virtual Machine으로 Kubernetes Cluster 구성하기 (1)

H-Y-E-N 2024. 3. 7. 13:50

안녕하세요. HYEN입니다.

드디어 미뤄두고 미뤄뒀던 Kubernetes Cluster on Virtual Machine 구성 테스트를 완료하였습니다. 🎉🎉

VMWare로 한번, Azure Virtual Machine으로 한 번, 총 두 번 테스트를 했던 적이 있어 우선 순위에서 밀렸던 것도 사실이긴합니다. 🥹

하지만 반복하지 않으면 까먹기 때문에 여유가 생긴 지금! 테스트 내용을 정리해 보고자 합니다. 


Contents

     

    1. Virtual Machine 배포

    Azure 환경에 [가상 머신]을 세 대 배포하여, 1대는 control plane, 2대는 node로 사용합니다. 

     

    1.1 Virtual Machine 배포

    1.1.1 [리소스 그룹] 생성

    • 구독 : # 사용할 구독 선택
    • 리소스 그룹 : rg-k8s-test # 리소스 명 입력
    • 영역 : Korea Central # 가상 머신이 배포될 Azure Region 선택

     

    1.1.2 [가상 머신] 생성

    세 대 모두 배포 방법은 모두 동일합니다.

    본 테스트에서는 이름만 변경하였으나 필요에 따라 control plane의 역할을 하는 [가상 머신]의 SKU를 더 크게 지정할 수 있습니다.

     

    • [기본 사항]
      • 노란색으로 하이라이트한 부분에 대해 설정을 완료한 후 [다음 : 디스크 >] 버튼을 클릭하여 다음 탭으로 이동합니다.

     

    • [디스크] 탭
      • OS 디스크 크기 및 OS 디스크 유형을 지정한 후 [다음 : 네트워킹 >] 버튼을 클릭하여 넘어갑니다. 
        (본 테스트에서는 default 값을 유지하였습니다.)
    • [네트워킹] 탭
      • [가상 네트워크] 생성
        • 이름, 가상 네트워크의 주소 범위, 서브넷 이름, 서브넷 주소 범위 등에 대해 지정한 후 [확인]을 클릭하여 [가상 네트워크] 생성을 완료합니다. 

      • [공용 IP] 제거
        • [공용 IP]는 [없음]을 선택합니다.

        • private한 cluster를 구성해야 하기 때문에 [공용 IP]를 붙이지 않습니다.

        • 추후 2번 과정에서 Bastion용 가상 머신과의 VNet Peering을 진행합니다.


      • 하기 스크린샷과 같이 설정이 필요한 부분을 확인한 후 [다음 : 관리 >] 버튼을 클릭하여 넘어갑니다.
    • [검토 + 만들기] 탭 
      • [검토 + 만들기] 탭을 클릭하여 유효성 검사 후 [가상 머신] 생성을 진행합니다.

     

     

    위와 같은 방식으로 Node용 [가상 머신]을 두 대 더 생성합니다. (이름은 변경해야 합니다.)

    본 테스트에서는 Node용 [가상 머신]의 이름을 node-hyein-01node-hyein-02로 지정하였습니다.

     

    1.2 VNet Peering 구성

    Kubernetes Cluster를 이루는 가상 머신의 경우 [공용 IP]를 붙이지 않고 private하게 구성하였기 때문에 Local에서 직접 접근할 수 없습니다.

     

    따라서 Bastion용 가상 머신을 생성해야 합니다.

    Bastion용 가상 머신은 Kubernetes Cluster를 이루는 가상 머신이 배포된 [가상 네트워크]와 다른 대역에 배포한 후 [VNet Peering]을 진행합니다.

     

    Bastion용 [가상 머신]의 OS 종류는 중요하지 않으며 배포 과정은 이번 글에서는 생략하겠습니다.

    (Ubuntu의 경우 상기 2번 과정과 동일합니다.)

     

    • 연결할 [가상 네트워크] 중 하나를 Azure Portal 상에서 선택한 후 [설정] > [피어링] 탭 > [+ 추가]


    • [피어링] 정보를 입력합니다.
      • 노란색으로 하이라이트한 부분에 대해 설정을 완료한 후 [추가] 버튼을 클릭하여 [피어링]을 진행합니다.

     

    1.3 Virtual Machine 접근

    Bastion VM에 접속한 후 각 [가상 머신]에 접근합니다.

    VNet Peering을 맺은 상태이기 때문에, Bastion VM에서 각 [가상 머신]으로 정상적으로 접근이 되어야 합니다.

     

    • Local Machine > Bastion VM 접근 : ssh hyein@{public ip}

    • Bastion VM > 각 [가상 머신] 접근
      • Control Plane : ssh hyein@10.0.0.4

      • Node 01 : ssh hyein@10.0.0.5

      • Node 02 : ssh hyein@10.0.0.6

     

    2. Kubernetes Cluster 구성

    지금부터는 가상 머신 상에 Kubernetes Cluster를 구축해 볼텐데요.

    모든 가상 머신에 동일하게 적용해야 하는 부분에 대해 먼저 다뤄보겠습니다.

     

    2.1 Containerd 설치

    Docker를 따로 사용하지 않을 것이기 때문에 Docker를 설치하지 않고 Containerd만 설치를 하도록 하겠습니다.

    설치에 앞서 먼저 Containerd가 무엇인지부터 짚고 넘어가 보겠습니다.

     

    Containerd란?

    Containerd가 무엇인지에 앞서 먼저 Container Runtime이라는 개념을 알고 넘어가야 하는데요.

    Container Runtime이란 container 실행을 담당하는 software이며, 이러한 Container Runtime을 호출할 수 있는 표준화된 인터페이스는 CRI, 즉 Container Runtime Interface라고 합니다.

    Kubernetes는 container를 관리하기 위한 Orchestration tool로, 다양한 Container Runtime과 통신하여 container를 관리합니다. 그리고 이 때 이러한 통신을 담당하는 것이 바로 CRI입니다.

    CRI가 Kubernetes와 Containerd 간의 표준화된 API를 정의하기 때문에 사용자는 CRI 포맷을 지원하는 Container Runtime을 Kubernetes에서 모두 사용할 수 있습니다.

    Docker가 바로 가장 널리 사용되는 Container Runtime 중 하나입니다.
    Docker는 CRI 개발 이전부터 널리 쓰이던 Container Runtime이기 때문에 CRI를 준수하지 않습니다.
    그렇기 때문에 Docker는 kubelet과 Dockerd 사이에 docker-shim을 사용하여 이를 대신해 왔는데요.

    하드코딩된 docker-shim을 유지 보수하는 것이 점점 어려워지고 Docker라는 Container Runtime을 위해서만 이러한 어댑터를 유지하는 것이 표준화와는 거리가 멀기에 Kubernetes는 docker-shim에 대한 지원을 v1.24에서 중단하게 되었습니다.

    이러한 CRI를 준수하는 Container Runtime으로는 Containerd와 CRI-O가 있습니다.
    그 중 Containerd를 사용하여 이번 테스트를 진행하고자 합니다.

    Containerd는 Docker에서도 사용된 Container Runtime 기술로 컨테이너화된 application을 실행, 관리하고 관련된 작업들을 수행하는데 사용되는 Container Runtime이라고 볼 수 있습니다.

    Kubernetes v1.24부터는 Kubernetes Cluster를 위해 Docker를 설치하지 않아도 되며, Containerd만 설치해 주면 됩니다.

     

    설명이 굉장히 길어졌습니다..🫠

    지금부터 Containerd를 각 [가상 머신]에 설치해 보도록 하겠습니다.

     

     

     

    • 원하는 버전을 선택한 후 마우스를 우클릭하여 [링크 주소 복사] 버튼을 통해 링크를 복사합니다.


    • wget {복사한 링크 주소} 명령어를 통해 tar 파일을 각 [가상 머신]에 다운로드 합니다.

     

    • tar 파일을 /usr/local 디렉토리에 압축해제 합니다.
      • tar Cxzvf /usr/local containerd-1.7.13-linux-amd64.tar.gz

      • /usr/local 디렉토리는 보통 사용자가 직접 설치한 소프트웨어를 저장하는 디렉토리이며 여기에 저장된 프로그램은 시스템 전체에서 사용 가능하기 때문에 해당 디렉토리에 tar 파일을 압축 해제 하겠습니다.

      • C는 디렉토리 변경 옵션으로 특정 디렉토리에 파일을 압축 해제하기 위해 사용합니다.

     

     

    • 하기 명령어를 사용하여 Containerd service를 시작합니다.
      • sudo systemctl daemon-reload

      • sudo systemctl enable --now containerd

     

    • sudo systemctl status containerd  명령어를 사용하여 Containerd의 상태를 확인합니다.

     

     

    • runc.amd64를 선택한 후 마우스를 우클릭하여 [링크 주소 복사] 버튼을 통해 링크를 복사합니다.

    • wget {복사한 링크 주소} 명령어를 입력하여 runc.amd64를 각 [가상 머신]에 다운로드 합니다.

     

    • install -m 755 runc.amd64 /usr/local/sbin/runc  명령어를 입력하여 runc.amd64를 /usr/local/sbin/runc 디렉토리에 설치합니다.

     

    • Step 3의 지침을 따르기에 앞서 mkdir -p /opt/cni/bin 명령어를 통해 /opt/cni/bin이라는 디렉토리를 생성합니다.

     

     

    • 원하는 버전을 선택한 후 마우스를 우클릭하여 [링크 주소 복사] 버튼을 통해 링크를 복사합니다.

     

    • wget {복사한 링크 주소} 명령어를 입력하여 cni plugin을 각 [가상 머신]에 다운로드한 후 tar Cxzvf /opt/cni/bin/ cni-plugins-linux-amd64-v1.4.0.tgz 명령어를 입력하여 tar 파일을 /opt/cni/bin/ 디렉토리에 압축 해제 합니다.

     

    • Containerd에 대한 설정 파일을 생성하고 변경하기 위해 우선 설정 파일을 저장할 디렉토리를 생성합니다. (mkdir -p /etc/containerd)

     

    • Containerd에서 제공하는 config 명령어를 사용하여 default config 정보를 얻고 그것을 config.toml라는 파일에 저장합니다. (containerd config default > /etc/containerd/config.toml)

     

    2. 2 Swap Off

    공식 문서를 보면 Kubernetes v1.28에서는 swap memory를 사용할 수 있도록 beta support를 지원한다고 되어 있으나 beta support이므로 일단 swap off를 진행하도록 하겠습니다.

    (참고 링크 : https://kubernetes.io/blog/2023/08/24/swap-linux-beta/)

     

    swap off를 진행하기에 앞서, 잠시 swap이 무엇인지 간단하게 확인하고 넘어가겠습니다.

     

    swap은 컴퓨터의 물리적인 RAM이 부족할 때 사용되는 보조 저장소입니다.
    OS가 메모리를 효율적으로 관리하기 위해 보통 사용되는데요.

    시스템에 메모리가 부족한 경우 OS는 현재 사용되지 않는 메모리를 swap 영역으로 이동시켜 물리적인 메모리 공간을 확보하게 됩니다.

     

    사실 Azure의 [가상 머신]은 기본적으로 swap이 비활성화되어 있기 때문에 해당 부분은 확인만 하고 넘어가시면 될 것 같습니다.

    • sudo swapon --show 명령어를 입력하였을 때 아무것도 출력되지 않거나, free -h 명령어를 입력하였을 때 하기와 같이 Swap 부분의 total이 0B로 출력되는지 확인합니다.

     

    2. 3 kubeadm, kubelet, kubectl 설치

    마지막으로 모든 [가상 머신]에 kubeadm, kubelet, kubectl을 설치해 보겠습니다. 

     

    kubeadm은 Kubernetes Cluster를 구성하는데 사용되며 Control Plane과 Node들을 설정하고 필수 구성 요소를 설치하여 Kubernetes Cluster를 준비하는 작업들을 지원합니다.

     

    하기 링크를 참고하여 모든 [가상 머신]에 kubeadm, kubelet, kubectl을 설치합니다.

    (참고 링크 : https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/)

     

    • 패키지 매니저를 사용하지 않는 경우를 선택해야 합니다.

     

    • CNI plugin의 경우 위에서 이미 설치했기 때문에 해당 내용은 생략합니다.

     

    • DOWNLOAD_DIR="/usr/local/bin”의 경우 하기 명령어에서 사용하기 때문에 변수를 선언해 줍니다.

     

    • crictl을 설치합니다.

     

    • kubeadm, kubelet, kubectl 설치 및 kubelet systemd 서비스를 추가합니다.

     

    • kubelet을 활성화하고 시작합니다.

     

    • kubectl을 입력하였을 때 하기와 같이 출력되면 세 도구가 정상적으로 설치된 것입니다. 
      kubelet이나 kubeadm을 입력해서 확인해도 됩니다.

    이렇게 Kubernetes Cluster를 이루는 가상 머신을 배포하고 Containerd를 설치하는 등 공통적으로 적용해야 할 부분에 대해 다뤄보았습니다. 

    다음 글에서는 이를 바탕으로 Control Plane을 초기화하고 Kubernetes Cluster로서 각 가상 머신들이 join하는 방법, 그리고 Node에 대한 Roles을 Labeling하는 방법에 대해 알아보겠습니다. 😜

    728x90
    320x100
    SMALL