Skip to content

Kubernetes 설치

사전 준비단계

사전 준비에 해당되는 내용들은 master node, worker node 에 모두 적용된다.

쿠버네티스(K8s) 작업을 수행하는 모든 노드에 접속해서 빠짐없이 실행해야 한다!

Docker Engine 설치

먼저 Docker 공식문서를 참조하여 도커를 설치한다.

도커가 설치되면 컨테이너 런타임 Containerd 도 자동으로 설치된다. K8s 가 컨테이너를 관리할 때 이것이 사용된다.

통신모듈 설정

K8s 클러스터 내부에서 통신이 가능하려면 리눅스 네트워크 설정을 변경해야 한다.

먼저 커널 공간에서 패킷을 필터링하는 br_netfilter 모듈을 활성화한다.

sudo modprobe br_netfilter

시스템 재부팅 시 초기화되는 것을 막으려면 modules-load 설정이 필요하다.

cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
br_netfilter
EOF

그리고 커널 브릿지를 통과하는 패킷이 iptables 방화벽도 거치도록 sysctl 설정을 변경한다.

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 컴포넌트가 정상 작동하려면 API 요청이 방화벽에서 차단되지 않도록 포트를 개방해야 한다.

각 프토로콜에 대응하는 포트 번호를 참조하여 클러스터 내부 트래픽이 해당 포트를 사용할 수 있도록 방화벽을 설정하자.

스왑 메모리 해제

리눅스는 기본적으로 메모리의 초과 사용을 대비해서 디스크 공간 일부를 메모리로 사용한다.

하지만 K8s 자원관리 체계는 스왑 메모리를 고려하지 않고 설계되었기 때문에 이 기능을 해제해야 한다.

kubeadm CLI 설치

공식 문서를 참조하여 클러스터를 생성하고 K8s 컴포넌트를 제어하는 명령줄 도구를 설치해보자.

컨테이너 런타임과 kubelet 이 사용하는 cgroup driver가 일치하는지 반드시 확인해보자.

클러스터 생성하기

Control plane 은 마스터 노드에서 설치해야 한다.

방화벽 설정에서 Kubernetes API 서버용 포트 6443 이 loopback 에서 개방되었는지 확인해보자.

nc 127.0.0.1 6443 -zv -w 2

Control plane 생성

kubeadm init --pod-network-cidr=10.244.0.0/16 --apiserver-advertise-address=<내부IP>

위 명령을 실행해서 클러스터 및 control plane 이 성공적으로 생성되면 다음과 같은 문구가 뜬다.

Your Kubernetes control-plane has initialized successfully!

...

You can now join any number of machines by running the following on each node
as root:

  kubeadm join <control-plane-host>:<control-plane-port> --token <token> --discovery-token-ca-cert-hash sha256:<hash>

문구 맨 아래에 kubeadm join ... 명령을 복사해서 메모장에 기록해두자. 나중에 worker node 를 생성하고 붙일 때 필요하다.

이제 kubectl 명령어 접근권한을 취득하기 위해 아래 명령을 입력하자.

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

kubectl 작동을 확인해보는 차원에서 모든 namespace 공간에 존재하는 Pod 목록을 조회해보자.

kubectl get pods -A
NAMESPACE      NAME                             READY   STATUS    RESTARTS       AGE
kube-system    etcd-master                      1/1     Running   5              78m
kube-system    kube-apiserver-master            1/1     Running   5              78m
kube-system    kube-controller-manager-master   1/1     Running   5              78m
kube-system    kube-proxy-gd4da                 1/1     Running   2 (45m ago)    75m
kube-system    kube-scheduler-master            1/1     Running   5              78m

CNI 플러그인 설치

클러스터 DNS 를 포함해서 Pod 끼리 통신할 수 있는 네트워크를 구축하려면 CNI(Container Network Interface) 가 필요하다.

K8s 클러스터와 호환되는 CNI 플러그인 목록은 여기에서 참고. 필자는 설치 및 관리가 편리한 flannel 플러그인을 선택하겠다.

  1. flannel 공식 저장소에서 kube-flannel.yml 파일을 내려받기
  2. kubectl apply -f kube-flannel.yml 을 실행해서 flannel 플러그인 설치
  3. 만약 설치후 /run/flannel/subnet.env 파일이 없다면 직접 추가하기

  4. kubectl get pods -n kube-flannel 을 실행해서 생성된 Pod 확인

    NAME                    READY   STATUS    RESTARTS       AGE
    kube-flannel-ds-5sd3d   1/1     Running   0              80m
    

주의사항

Worker node 등록

이제 K8s 컨테이너를 실행하는 worker node 컴퓨터에 접속한다.

이전에 Control plane 만들고 나서 복사했던 명령어를 실행하면 된다. 아래는 예시.

kubeadm join 192.168.1.11:6443 --token ssakq.03psdfgs4eq31omogi \
        --discovery-token-ca-cert-hash sha256:13se53sxd8dnh3k08834ssdsw4e488fbbbf2eebaaf037b2

등록이 끝났다면 마스터 노드에 접속해서 worker node 가 잘 인식되는지 확인해보자.

kubectl get nodes

Troubleshoot

context deadline exceeded

$ kubectl apply -f manifest.yaml

Error from server (InternalError): error when creating "manifest.yaml": Internal error occurred:
failed calling webhook "ipaddresspoolvalidationwebhook.metallb.io": failed to call webhook:
Post "https://metallb-webhook-service.metallb-system.svc:443/validate-metallb-io-v1beta1-ipaddresspool?timeout=10s": context deadline exceeded 

마니페스트를 적용할 때 웹훅 연결이 안되서 리소스 생성에 실패하는 문제를 겪었다.

클러스터 네트워크를 구현하는 flannel 이 패킷을 전송하는 특정 포트가 있는데, 이게 방화벽에서 차단된 것이었다.

공식 문서에서 방화벽 관련 권고사항을 확인하고 방화벽을 수정하여 해결했다.