우분투 쿠버네티스 클러스터 설치하기

    0. 쿠버네티스 클러스터 개요

    • Virtual Box를 이용해서 3개의 VM을 만든다. 3개의 VM은 ubuntu 이미지를 이용해서 만들고, 각 VM은 프로세스를 2개 이상 배당 받도록 지정한다. 
    • 사용자 PC에서 Port 포워딩을 통해서 각 Node에 접속할 수 있도록 한다.  
    • VM(k8s Node) 들은 30.0.2/24를 CIDR로 사용한다. 
    • Service Network는 40.0.0.0/16을 CIDR로 한다.
    • Pod Network는 50.0.0.0/16을 CIDR로 한다.

    쿠버네티스 클러스터에 대한 개요는 다음과 같다. 위의 내용대로 구현해서 클러스터가 정상 형성되는 것을 확인하는 것까지가 목표다. 

     

    1. 우분투 기본설정 업데이트하기 (마스터 / 워커 모두 진행)

    # shell
    sudo apt update
    sudo apt upgrade
    
    # shell
    # ssh : super putty
    
    sudo apt install vim net-tools ssh -y

    최초로 우분투를 설치했다면 위 명령어를 이용해서 우분투의 라이브러리 등을 최신화 해준다. 

     

    2. 사용할 IP 대역을 고정한다. (마스터 / 워커 모두 진행)

    우분투 설정 창에서 다음과 같이 IP 주소를 고정한다. 고정한 후 터미널에서 IP를 확인하면 고정한 것처럼 30.0.2.31이 나오는 것을 확인할 수 있다. 

    2-2 SuperPutty에 등록하기

    Virtual Box를 이용하는 경우 Host OS에서 복사한 것을 Guest OS에 복사 붙여넣기가 잘 안되는 경우가 많다. 일일이 커맨드 치기가 어렵기 때문에 SuperPutty를 등록한다. 호스트 네임은 우분투 계정@Localhost으로 하면 된다. Port는 Port 포워딩에 설정된 값으로 한다.

     

    3번 들어가기 전

    https://docs.docker.com/engine/install/ubuntu/#set-up-the-repository

    최근 k8s 버전이 업데이트 되면서 Docker를 설치하는 방법이 바뀌었다. 만약 이전 Docker를 설치하게 된다면, kubelet을 띄울 때 에러가 발생한다. 아래 Docker 설치하는 과정을 그대로 따라하는 대신 위의 공식 문서를 보고 Docker를 설치하는 것을 추천한다. 

     

    3. 필요한 패키지 설치 (마스터 / 워커 모두 진행)

    $ sudo apt-get install \
    ca-certificates \
    curl \
    gnupg \
    lsb-release -y

    이 명령어를 통해 필요한 패키지를 설치한다. Docker / K8s를 받기 위해서는 curl 명령을 통해서 특정 repository에서 값을 받아와야하는데, 이 때 인증서 같은 것들이 필요하다. 따라서 위의 패키지를 먼저 설치한다. 

     

    4. Docker GPG Key 추가 + Docker Repository 등록 (마스터 / 워커 모두 진행)

    $ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
    
    $ echo \
      "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
      $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

    위 명령어를 이용해서 Docker GPG Key를 추가한다. 이제 Docker를 설치할 준비가 완료된다. GPG key가 등록되어야 추가한 Docker Repository에서 apt-get update를 정상적으로 수행할 수 있게 된다. 

    5. Docker 설치

    $ sudo apt-get update
    $ sudo apt-get install docker-ce docker-ce-cli containerd.io

    위 명령어를 이용하면 Docker를 설치할 수 있다. 윈도우에서는 Docker Desktop으로 손쉽게 설치할 수 있지만 리눅스니까... 

     

    6. Docker 정상 확인 (마스터 / 워커에서 모두 실행)

    $ sudo systemctl status docker

    위 명령을 이용해서 Docker가 정상적으로 동작하고 있는지 확인한다. 

    다음과 같이 active (running)을 확인할 수 있다. 

     

    7. Docker 항상 실행되도록 설정 (마스터 / 워커에서 모두 실행)

    $ sudo systemctl enable docker

    쿠버네티스는 컨테이너 런타임으로 Docker를 사용한다. 따라서 Docker는 항상 VM이 재부팅 되어도 켜져있어야 한다. 위 명령어를 이용해서 Docker가 항상 실행되어 있도록 설정해준다. 

     

    8. Swap Disable 설정 (마스터 / 워커)

    $ sudo su - root
    $ swapoff -a && sed -i '/swap/s/^/#/' /etc/fstab

    k8s 설치  메뉴얼에서는 Swap을 disable로 사용할 것을 권장한다. 따라서 나도 그렇게 사용했다. 이 때 일반 계정으로 하면 권한이 부족하기 때문에 root 계정으로 전환한 후 한다. 

     

    9. 노드 간 통신을 위한 브릿지 설정(마스터 / 워커)

    $ cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
    br_netfilter
    EOF
    
    $ cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
    net.bridge.bridge-nf-call-ip6tables = 1
    net.bridge.bridge-nf-call-iptables = 1
    EOF
    
    $ sysctl --system

    k8s에서는 노드 간 통신에서 netfilter를 사용해서 IP를 Resolve를 해준다. 따라서 사용할 수 있도록 설정을 해주고, 설정을 적용시켜준다. 

     

    10. 쿠버네티스 설치 (마스터 / 워커 노드)

    sudo apt-get update -y
    sudo apt-get install -y apt-transport-https ca-certificates curl
    sudo curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg
    
    echo "deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
    sudo apt-get update
    
    # 설치
    sudo apt-get install -y kubelet kubeadm kubectl
    
    # 버전 고정
    sudo apt-mark hold kubelet kubeadm kubectl
    
    # 시작
    systemctl start kubelet && systemctl enable kubelet

    Docker를 설치하던것과 동일하게 GPG Key를 추가하고, 이후에 Repository를 추가한다. 그리고 그 Repository에서 쿠버네티스 관련 컴포넌트인 kubelet kubeadm kubectl을 다운 받아준다.  쿠버네티스에서는 kubelet을 통해서 Pod이 생기기 때문에 마스터 / 워커 노드에 모두 설치해주고 항상 켜져있도록 해준다. 

     

    11. Docker 명령어 수정 (마스터/워커 노드 실행)

    sudo mkdir /etc/docker
    
    cat <<EOF | sudo tee /etc/docker/daemon.json
    {
      "exec-opts": ["native.cgroupdriver=systemd"],
      "log-driver": "json-file",
      "log-opts": {
        "max-size": "100m"
      },
      "storage-driver": "overlay2"
    }
    EOF
    
    
    
    sudo systemctl enable docker 
    sudo systemctl daemon-reload 
    sudo systemctl restart docker

    쿠버네티스 1.22 버전 이상부터는 Docker의 systemd와 cgroup을 맞춰줘야한다. 따라서 위 명령어를 이용해서 Docker Daemon의 설정값을 수정하고 다시 재시작한다.

     

    12. 마스터 노드 활성화 (마스터 노드만)

    $ kubeadm init --apiserver-advertise-address 30.0.2.30 --pod-network-cidr=50.0.0.0/16 --service-cidr=40.0.0.0/16
    
    ## kubeadm 실행 시 에러가 발생하면 다음 명령어를 사용한다. containerd가 잘못 설치되었기 때문임.
    $ rm /etc/containerd/config.toml
    $ sudo systemctl restart containerd

    위 명령어로 마스터 노드를 활성화 시킨다. 마스터 노드의 kube-apiserver의 주소를 알려준다.

    그럼 다음과 같이 결과로 이런 값이 나온다. 이것은 워커 노드가 마스터 노드에 조인해서 쿠버네티스 클러스터를 생성할 때 필요하기 때문에 반드시 어디다가 작성해둔다. 

    kubeadm join 30.0.2.30:6443 --token 0ee9on.xgyeka52w29ax0vr \
            --discovery-token-ca-cert-hash sha256:d7c037b00b739a0e0ecabbdaa36e200e482b86eebd77b040963affe494c71549

    위의 값을 잊어버려도 상관없다. 아래 명령어를 이용해서 다시 Join 토큰을 발급 받으면 된다. 

     $ kubeadm token create --print-join-command

     

     

    13. 마스터 노드에 인증서 복사해두기 (마스터 노드만)

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

    kubectl을 이용해서 보통 쿠버네티스 클러스터를 관리한다. kubectl을 이용하기 위해서는 쿠버네티스 클러스터의 인증서를 가지고 있어야 한다. 따라서 이걸 복사해서 kubectl이 사용할 수 있도록 해주는 작업이 필요한데 그것이 위의 작업이다.

    $ kubectl get node

    정상 동작하는 것은 위의 명령어를 이용해서 확인할 수 있다.

    다음과 같이 마스터 노드가 떠 있는 것을 볼 수 있다. 

     

    14. 파드 네트워크 add on 설치(마스터 노드에만)

    $ kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml

    위의 명령어로 Pod 네트워크인 calico 인터페이스를 add on으로 설치할 수 있다.

    정상적으로 설치되면 다음과 같이 calico 어쩌고 하는 Pod들이 kube-system namespace에 설치된 것을 볼 수 있다.

     

    15. 워커 노드의 쿠버네티스 클러스터 조인 (워커 노드만)

    $ kubeadm join 30.0.2.30:6443 --token 0ee9on.xgyeka52w29ax0vr \
            --discovery-token-ca-cert-hash sha256:d7c037b00b739a0e0ecabbdaa36e200e482b86eebd77b040963affe494c71549

    아까 마스터 노드를 처음 활성화 했을 때 생긴 kubeadm join 명령어를 복사해서 붙여넣기를 하면 된다. 만약에 또 Container Runtime 에러가 발생한다면 ContainerD와 관련된 설정을 위에서 했던 것처럼 삭제하고 다시 하면 된다. 

     

    16. 클러스터 조인은 되어있는데 not ready 인 경우 (마스터 노드만)

    // CNI Add On 설치
    // 최근 설치하는 주소가 바뀜.
    $ kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.25.1/manifests/calico.yaml
    
    $ kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

    이 명령어를 마스터 노드에서 수행해서 add on을 설치한다. 이것은 CNI라는 것인데 k8s 내에서 Pod끼리 통신할 수 있도록 도와주는 녀석이다. 

     

    17. 최종 확인

    $ kubectl get nodes

    마스터 노드에서 위 명령어를 사용해서 node가 정상적으로 붙었는지를 확인한다.

    다음과 같이 2개의 노드가 정상적으로 붙은 것을 확인할 수 있다. 

     

     

    22.10.03 수정

    Nat Network로 Port 포워딩을 할 때, Host OS에 특정 Port가 Guest Os의 특정 Port로 매칭되는 형식으로 되어있음. 따라서 k8s에서 동적으로 생성되는 Pod / Service로 Host 하는게 꽤 어렵지 않을까? 라는 생각이 들었음

    이런 이유 때문에는 Nat Network Port 포워딩 방식을 Nat + 호스트 네트워크의 고정 IP로 Node로 접근할 수 있도록 해두었음. 

     

     

    참고 자료

     

    댓글

    Designed by JB FACTORY