클라우드/쿠버네티스

[Kubernetes] 9. 쿠버네티스 kubeadm을 이용한 클러스터 구성

윤창이 2021. 7. 18. 17:24
728x90

[주의] 개인 공부를 위해 쓴 글이기 때문에 주관적인 내용은 물론, 쓰여진 정보가 틀린 것일 수도 있습니다!

피드백 부탁드립니다. (- -)(_ _) 꾸벅

 


https://kubernetes.io/ko/docs/setup/production-environment/tools/kubeadm/install-kubeadm/

 

kubeadm 설치하기

이 페이지에서는 kubeadm 툴박스를 설치하는 방법을 보여준다. 이 설치 프로세스를 수행한 후 kubeadm으로 클러스터를 만드는 방법에 대한 자세한 내용은 kubeadm을 사용하여 클러스터 생성하기 페이

kubernetes.io

 

 

Ubuntu 18.04 에서 진행하였고, Docker가 이미 설치되어있다는 가정하에 진행하였습니다.


[ 설치 전 Check List ]

  • 호환되는 리눅스 머신
  • RAM 2GB 이상
  • 2core 이상의 CPU
  • 클러스터 간의 네트워크 연결
  • 모든 노드들이 고유한 호스트 이름, MAC 주소, product_uuid
  • 특정 포트들이 사용 중이지 않아야 함
  • 스왑 메모리 비활성화

 

 

- Master Node

프로토콜 방향 포트 범위 목적 사용자
TCP 인바운드 6443 쿠버네티스 API 서버 모두
TCP 인바운드 2379-2380 etcd 서버 클라이언트 API kube-apiserver, etcd
TCP  인바운드 10250 kubelet API 자체, 컨트롤 플레인
TCP  인바운드 10251 kube-scheduler 자체
TCP 인바운드 10252 kube-controller-manager 자체

 

- Worker Node

프로토콜 방향 포트 범위 목적 사용자
TCP 인바운드 10250 kubelet API 자체, 컨트롤 플레인
TCP 인바운드 30000-32767 NodePort 서비스 모두

위에 해당하는 포트들은 사용 중이지 않아야 한다.

 

 

또한 파드에 컨테이너를 실행하기 위해 컨테이너 런타임을 사용하는데, 기본적으로 쿠버네티스는 CRI(Container Runtime Interface)를 사용하여 인터페이스 한다. 인터페이스를 지정하지 않으면 소켓 목록을 검색하여 자동으로 런타임을 자동으로 감지한다. 런타임 소켓 경로는 아래와 같다.

 

런타임 유닉스 도메인 소켓 경로
Docker /var/run/dockershim.sock
containerd /run/containerd/containerd.sock
CRI-O /var/run/crio/crio.sock

 


[ kubernetes 설치 전 해야하는 세팅 ]

 사용될 모든 머신에 아래 세팅을 해주어야 한다.

 

  • 스왑 메모리 비활성화
     swap 메모리란 - RAM의 가용 용량을 넘어서는 프로세스가 있으면 하드 디스크의 용량을 빌려 마치 RAM처럼 사용하는 메모리이다. 쿠버네티스의 kubelet은 이러한 상황을 처리하도록 만들어지지 않았기 때문에, 클러스터에 사용될 모든 서버 머신들은 스왑 메모리를 비활성화해야 한다.
    $ swapoff -a
    
    $ sudo vi /etc/fstab
    # swap과 관련된 부분을 주석 처리한다. (그 외 다른 부분 주석처리 시 영원히 안켜질 수 있으니 신중할 것)

 

  • 런타임으로 사용될 Docker 데몬을 cgroupfs대신 systemd를 사용 (필수X)
     kubernetes에서 권장하는 Docker 데몬의 드라이버는 systemd이다. systemd와 함께 cgroupfs를 사용하면 두 개의 서로 다른 cgroup 관리자가 존재하는 것이고, 시스템이 불안전해지는 사례가 있다고 한다.
    $ sudo cat > /etc/docker/daemon.json <<EOF
    {
      "exec-opts": ["native.cgroupdriver=systemd"],
      "log-driver": "json-file",
      "log-opts": {
        "max-size": "100m"
      },
      "storage-driver": "overlay2"
    }
    EOF
    
    $ sudo mkdir -p /etc/systemd/system/docker.service.d
    
    $ sudo systemctl daemon-reload
    
    $ sudo systemctl restart docker

[ Kubernetes 설치 ]

 또한 사용될 모든 머신에 아래 패키지를 설치해주어야 한다. 

  • kubeadm :  클러스터를 구성하기 위한 다양한 기능을 제공한다.
  • kubelet :  클러스터의 모든 머신에서 실행되는 Pod와 Container 시작과 같은 작업을 수행하는 구성 요소이다.
  • kubectl :  클러스터와 통신하기 위한 Command-Line 유틸리티이다.
# Apt repository 구성
$ sudo apt-get install -y apt-transport-https curl
$ 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-get update


# kubernetes 설치 및 활성화 (최신버전은 뒤에 버전 안쓰면 됨)
$ sudo apt-get install -y kubelet=1.15.5-00 kubeadm=1.15.5-00 kubectl=1.15.5-00
$ systemctl enable kubelet && systemctl start kubelet


# 자동 업데이트 방지
$ sudo apt-mark hold kubelet kubeadm kubectl


# 설치 완료 버전 확인
$ kubeadm version
$ kubelet --version
$ kubectl version

 

게시글이 너무 오래되어 apt 구성이 안될 경우 아래 공식 설치 가이드를 따르자.

(https://kubernetes.io/ko/docs/setup/production-environment/tools/kubeadm/install-kubeadm/#k8s-install-0)

 


[ 마스터 노드 세팅 ]

# 각 주소는 아래를 확인하여 자신의 환경에 맞게 기입!
$ kubeadm init --pod-network-cidr=10.244.0.0/16 --apiserver-advertise-address=192.168.9.128

init 명령을 통해 master node를 구성할 수 있다. init 명령에 대한 인자는 아래와 같다.

  • --pod-network-cidr    :    Pod에서 사용할 네트워크의 대역. 각 서버의 네트워크 대역과 중복되지 않게 주의
  • --apiserver-advertise-address    :    다른 노드가 마스터에 조인할 수 있는 IP 주소를 설정
  • --control-plane-endpoint    :    고가용성을 위해 다중 마스터 노드를 구성할 때 공유 엔드포인트 설정
  • --kubernetes-version    :    특정 버전의 쿠버네티스를 설치하기 위한 인자

 

  1. pod-network-cidr 확인
    Flannel라는 CNI (Container Network Interface) 기반의 에드온을 사용하려면 10.244.0.0/16 대역을 사용하도록 권장하고 있다. 만일 호스트 네트워크에서 10.244.0.0/16의 대역을 사용하고 있다면, 다른 네트워크 대역을 사용하도록 한다.

  2. apiserver-advertise-address 확인
    $ ifconfig
    
    ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
            inet 192.168.9.128  netmask 255.255.255.0  broadcast 192.168.9.255
            inet6 fe80::20c:29ff:fe13:6431  prefixlen 64  scopeid 0x20<link>
            ether 00:0c:29:13:64:31  txqueuelen 1000  (Ethernet)
            RX packets 2716  bytes 3186866 (3.1 MB)
            RX errors 0  dropped 0  overruns 0  frame 0
            TX packets 940  bytes 99823 (99.8 KB)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    
    lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
            inet 127.0.0.1  netmask 255.0.0.0
            inet6 ::1  prefixlen 128  scopeid 0x10<host>
            loop  txqueuelen 1000  (Local Loopback)
            RX packets 124  bytes 9824 (9.8 KB)
            RX errors 0  dropped 0  overruns 0  frame 0
            TX packets 124  bytes 9824 (9.8 KB)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
     마스터 노드가 Control Plane으로서 동작할 것이고 그 노드의 주소를 kubeadm에 알려주어야 한다. ifconfig 명령을 통해 enp0s8 인터페이스명(다를 수 있다.)과 ipv4 주소인 192.168.9.128를 얻을 수 있다. 
    나는 로컬 환경에서의 클러스터를 구성하고 있는 것이라 사설 IP를 적어주었지만, 외부의 머신과 클러스터를 구성할 경우 외부 IP를 써주도록 해야한다.

 

init 명령을 실행했다면 출력 결과로 아래처럼 kubeadm join 명령과 토큰값이 뜬다. 이는 나중에 worker 노드가 마스터에 조인하기 위한 명령으로 쓰이니 메모해두도록 하자.

# kubeadm init의 결과물
kubeadm join 192.168.9.128:6443 --token 2ioegt.9075fhjpdfrd9tek \
        --discovery-token-ca-cert-hash sha256:d7c183342f2a493d16d790ba56e2c127abf1111925e7931788c37466ca33f10d

 

또한 마스터 노드의 init이 완료되면 아래 명령을 통해 Root 계정이 아닌 사용자 계정에서 kubectl 커맨드 명령어를 사용하여 클러스터를 제어할 수 있도록 한다.

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

 

 kubernetes는 admin.conf 파일을 자체적으로 가지고 있고, 이 파일을 가지고 관리자 역할의 인증 및 인가 처리를 할 수 있다. 이 파일을 $HOME/.kube/config에 복사하므로 사용자 계정이 kubectl 명령어를 사용하면서 관리가 인증을 받을 수 있도록 하는 것이다.


즉 admin.conf 파일은 인증 역할만 하는 것이고, 클러스터의 리소스에 접근하여 제어하기 위한 Role에 대한 권한 허용은 해당 계정(admin.conf)에 rolebinding을 통해서 가능하다. 이 방식을 RBAC (Role-based access control)라고 하는데 자세한 내용은 추후에 공부해 보아야겠다.

 

 

이제 마스터 노드의 CNI를 배포하여야한다. 나는 Calico를 네트워크 인터페이스로 쓰기로 하였다. Flannel도 혹시 몰라 배포 명령어를 적어 두었으니 둘 중 하나만 사용하면 되겠다. 

# Flannel
$ kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

# Calico
$ kubectl apply -f https://docs.projectcalico.org/archive/v3.8/manifests/calico.yaml

CNI 애드온은 정말 여러 개가 존재하지만 (참고 : https://kubernetes.io/ko/docs/concepts/cluster-administration/addons/) 무엇을 써야할지 모르겠고, 사실 둘 차이도 크게 모르겠다. 나중에 공부. 그놈의 나중에

(Calico 버전은 바뀔 수도 있으니 공식 문서 참고 바람 - https://projectcalico.docs.tigera.io/getting-started/kubernetes/quickstart)

 

잘 배포되었는지 확인.

$ kubectl get pod -n kube-system
$ kubectl get nodes

 


[ 워커 노드 세팅 ]

$ kubeadm join 192.168.9.128:6443 --token 2ioegt.9075fhjpdfrd9tek \
        --discovery-token-ca-cert-hash sha256:d7c183342f2a493d16d790ba56e2c127abf1111925e7931788c37466ca33f10d

단순히 마스터 노드 init 과정에서 얻은 join 명령을 그대로 실행하면 되겠다. join의 인자들은 아래와 같다.

  • <마스터 노드의 ip>:6443   :   6443 포트는 kubernetes api server 프로세스의 기본 포트
  • --token    :     토큰 값이다. 24시간 뒤에 바뀜
  • --discovery-token-ca-cert-hash    :    해쉬 값

만약 토큰 값이나 해쉬 값이 만료되었거나, 까먹었다면 아래 명령어를 마스터 노드에 입력하여 확인 가능하다.

# 토큰 값 확인
$ kubeadm token list

# 해쉬 값 확인
$ openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | \
   openssl dgst -sha256 -hex | sed 's/^.* //'
   
# 토큰 만료 시 재발급
$ kubeadm token create

 

조인 완료시 아래와 같이 클러스터 노드 구성이 된 것을 확인 가능하다.


[ 현재 우리가 배포한 쿠버네티스 구조 ]

다음번엔 master node를 통해 직접 deployment를 배포하여 worker node에 잘 올라가는지 확인.


 

 

728x90