Kubernetes 설치
사전 준비단계
사전 준비에 해당되는 내용들은 master node, worker node 에 모두 적용된다.
쿠버네티스(K8s) 작업을 수행하는 모든 노드에 접속해서 빠짐없이 실행해야 한다!
Docker Engine 설치
먼저 Docker 공식문서를 참조하여 도커를 설치한다.
도커가 설치되면 컨테이너 런타임 Containerd 도 자동으로 설치된다. K8s 가 컨테이너를 관리할 때 이것이 사용된다.
통신모듈 설정
K8s 클러스터 내부에서 통신이 가능하려면 리눅스 네트워크 설정을 변경해야 한다.
먼저 커널 공간에서 패킷을 필터링하는 br_netfilter 모듈을 활성화한다.
시스템 재부팅 시 초기화되는 것을 막으려면 modules-load 설정이 필요하다.
그리고 커널 브릿지를 통과하는 패킷이 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 에서 개방되었는지 확인해보자.
Control plane 생성
위 명령을 실행해서 클러스터 및 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 목록을 조회해보자.
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 플러그인을 선택하겠다.
- flannel 공식 저장소에서 kube-flannel.yml 파일을 내려받기
kubectl apply -f kube-flannel.yml을 실행해서 flannel 플러그인 설치-
만약 설치후
/run/flannel/subnet.env파일이 없다면 직접 추가하기 -
kubectl get pods -n kube-flannel을 실행해서 생성된 Pod 확인
주의사항
- flannel 설치 후
/run/flannel/subnet.env파일이 생성되지 않는 경우가 있다. 그렇다면 직접 생성해야 한다. - 특정 커널 환경에서 VXLAN 패킷의 체크섬이 변질되는 문제가 있다.
tx-checksum-ip-generic옵션을 해제하여 해결할 수 있다.
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 가 잘 인식되는지 확인해보자.
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 이 패킷을 전송하는 특정 포트가 있는데, 이게 방화벽에서 차단된 것이었다.
공식 문서에서 방화벽 관련 권고사항을 확인하고 방화벽을 수정하여 해결했다.