Computing

Kubernetes 고가용성(HA) (2): kubeadm을 통한 고가용성 배포 본문

Cloud/Kubernetes

Kubernetes 고가용성(HA) (2): kubeadm을 통한 고가용성 배포

jhson989 2023. 1. 4. 23:57

이전글

- Kubernetes 고가용성(HA) (1): 고가용성과 Kube Master의 고가용성

이전 글에서 쿠버네티스 클러스터의 고가용성을 위해 Multiple Masters를 클러스터에 배포한다는 것을 배웠다. 이번 포스터에서는 간단하게 Multiple Masters를 포함하는 쿠버네티스 클러스터를 배포하는 방법에 대해서 정리하고자 한다.

 

 

 

실습 환경

쿠버네티스 클러스터 설치는 kubeadm을 통해 최소한의 시스템으로 설치할 예정이다. 아쉽게도 개인 컴퓨터 환경이기에 3대의 가상머신(VM)과 HAProxy[1]이라는 가상 load balancer를 이용할 예정이다. 실습 환경은 다음과 같다.

 

[각 가상머신 구성]

- OS: CentOS 8

- CPU: Physically 2 cores

- Memory: 4 GB

- Hypervisor: Qemu-KVM

 

[쿠버네티스 클러스터 구성 환경]

- Kubernetes v1.25

- CRI: CRI-O v1.25

- 3대 Control planes

    - 노드 A: 192.168.122.21 (hostname: s1)

    - 노드 B: 192.168.122.22 (hostname: s2)

    - 노드 C: 192.168.122.23 (hostname: s3)

- 0대 Worker nodes (taint를 통해 Control plane에서 pod 실행 예정)

 

[Load Balancer]

- HAProxy

- 노드 A가 LB 역할 수행

 

kubeadm을 통한 고가용성 쿠버네티스 클러스터 배포는 총 3단계로 구성된다.

- HAProxy를 통한 Load Balancer 설치

- kubeadm init을 통한 노드 A에서 쿠버네티스 클러스터 초기화

- kubeadm join을 통해 나머지 Masters(노드 B, 노드 C) 참여

 

 

 

Load Balancer 설치

물리 로드 밸런서(하드웨어 스위치)가 없기에 HAProxy라는 소프트웨어 로드 밸런서를 이용하여 Masters들간의 로드 밸런서(LB)를 구현하고자 한다.

 

간단히 HAProxy를 소개하자면 오픈소스 LB로, HAProxy가 설치된 컴퓨터가 L4/L7 로드 밸런싱 기능을 대신수행하게 된다. L4 로드 밸런싱은 IP:Port 기준으로 로드 밸런싱을 수행하는 것이고, L7 로드 밸런싱은 URI, Http Header, Cookie 등 애플리케이션 내용에 따라 로드 밸런싱을 수행하는 것이다. 이번 실습에서는 Master들의 IP:Port를 기준으로 로드 밸런싱을 수행할 것이기에 L4 로드 밸런싱을 이용할 것이다. 

 

HAProxy 설치는 매우 간단하다. 실습 환경에서는 노드 A가 LB역할을 수행할 것이기에 HAProxy를 노드 A에만 설치하면 된다. (다만 이러한 구성에서 노드 A가 고장나면 LB도 고장나는 것이기에 사실 노드 A가 고장나면 노드 B, C 모두 이용하지 못하게 된다. 실제 구현에서는 안정적인 물리 로드 밸런서를 설치하든 다른 서버에 LB를 설치하든 LB간 failover 설정을 하든 추가적인 설정을 해야 한다.)

 

$ yum install haproxy

 

설치가 끝나면 HAProxy 설정을 해주어야 한다. 위에서 언급했듯 노드 A가 LB 역할을 담당할 것이고, 노드 A는 자신에게 들어온 네트워크 트래픽을 노드 A, 노드 B, 노드 C에게 나눠줄 것이다. 나눠줄 때는 기준이 필요한데 round robin 방식[2]을 트래픽 분산 기준으로 설정할 것이다. 노드 A에서만 설정해주면 되고 노드 B와 노드 C는 건드릴 필요 없다.

 

HAProxy 설정을 위해서는 [etc/haproxy/haproxy.cfg] 파일에 설정을 추가해주어야 한다. 구체적으로 노드 A의 36443 포트로 들어오는 트래픽을 노드 A, B, C의 api-server의 port인 6443으로 로드 밸런싱할 것이다.

 

트래픽 -> 192.168.122.21:36443 -> 192.168.122.21:6443

or

트래픽 -> 192.168.122.21:36443 -> 192.168.122.22:6443

or

트래픽 -> 192.168.122.21:36443 -> 192.168.122.23:6443

 

#########################################################
# /etc/haproxy/haproxy.cfg 파일에 설정 추가
#########################################################
$ sudo cat << EOF >> /etc/haproxy/haproxy.cfg
frontend kube-masters-lb
	bind 0.0.0.0:36443
	mode tcp
	default_backend kube-masters

backend kube-masters
	mode tcp
	balance roundrobin
	server s1 192.168.122.21:6443 check
	server s2 192.168.122.22:6443 check
	server s3 192.168.122.23:6443 check
EOF
#########################################################
# HAProxy 재실행
#########################################################
$ sudo systemctl restart haproxy

#########################################################
# HAProxy 상태 확인: active(running)인지 확인 필요
#########################################################
$ sudo systemctl status haproxy

 

이상으로 LB 설정은 끝났다. 이제 192.168.122.21:36443로 들어온 네트워크 트래픽은 노드 A,B,C의 6443 포트로 포워딩될 것이다. 

 

 

 

kubeadm init

우리 실습은 다음과 같이 진행될 것이다. 노드 A에서 [kubeadm init] 명령어를 통해 쿠버네티스를 초기화한다. 노드 B와 노드 C는 [kubeadm join] 명령어를 통해 노드 A가 만든 쿠버네티스 클러스터에 참여한다.

 

kubeadm을 통한 쿠버네티스 클러스터 설치의 시작은 kubeadm init을 통해 쿠버네티스 클러스터를 생성하는 것이다. 노드 A에서 kubeadm init을 실행하도록 하자. 명령어는 다음과 같다.

 

##########################################################################################
# kubeadm init 명령어
# - --control-plane-endpoint: control-plane에 접근하기 위한 주소. LB의 주소를 입력하면 됨
# - --upload-certs: Master들을 join 시키기 위해서는 certificate-key가 필요함. certificate-key 생성 옵션
# - --pod-network-cidr: Pod들의 네트워크 대역 설정
# - --cri-socket: cri 소켓 설정. 실습환경에서는 cri-o 사용
##########################################################################################
$ kubeadm init --control-plane-endpoint 192.168.122.21:36443 --upload-certs --pod-network-cidr=172.31.0.0/16 --cri-socket unix:///var/run/crio/crio.sock

 

어느 정도 시간이 흐르면 긴 글이 출력될 것이다. 글을 읽다보면 control-plane을 어떻게 추가하는 지, worker들을 어떻게 추가하는 지 적혀 있을 것이다.

 

############################################################
# 출력 예시
############################################################
... # 위 생략
You can now join any number of the control-plane node running the following command on each as root:

  kubeadm join 192.168.122.21:36443 --token a4h9aa.aaaa45ctwaaaa5wo \
	--discovery-token-ca-cert-hash sha256:aaaaaaaaaea314b2e57584aaa4837db27b9508bcd51aaa8d39e613aaa151aaaa \
	--control-plane --certificate-key c5aaaaa036b061ed2ae0aaaa2d17a1faaaaa2eaeeaa06a070aaa3ff2aaaaaaa2

Please note that the certificate-key gives access to cluster sensitive data, keep it secret!
As a safeguard, uploaded-certs will be deleted in two hours; If necessary, you can use
"kubeadm init phase upload-certs --upload-certs" to reload certs afterward.
... # 아래 생략

 

위 출력에서 중간을 보면 "kubeadm join [IP:Port] --token [token] --discovery-token-ca-cert-hash [hash] --control-plane --certificate-key [key]"를 찾을 수 있을 것이다. 저 문구를 그대로 복사해서 노드 B, 노드 C에 실행시키면 노드 B와 노드 C를 클러스터에 "join"시킬 수 있다. 

 

 

 

kubeadm join

노드 B와 노드 C에서 각각 다음을 실행하자.

 

kubeadm join 192.168.122.21:36443 --token a4h9aa.aaaa45ctwaaaa5wo \
	--discovery-token-ca-cert-hash sha256:aaaaaaaaaea314b2e57584aaa4837db27b9508bcd51aaa8d39e613aaa151aaaa \
	--control-plane --certificate-key c5aaaaa036b061ed2ae0aaaa2d17a1faaaaa2eaeeaa06a070aaa3ff2aaaaaaa2

 

어느 정도의 시간이 지나면 성공적으로 join되었다고 출력된다. 다중 Master를 통한 고가용성 쿠버네티스 클러스터 구축이 완료되었다.

 

 

 

Kubernetes 설치 확인

노드 A에서 CNI 등을 설치하고 난 후 kubectl을 통해 확인하면 다음과 같이 여러 control-plane이 존재함을 확인할 수 있다.

 

Fig 1. kubectl get nodes의 결과

 

 

 

Reference

[1] http://www.haproxy.org/

[2] https://en.wikipedia.org/wiki/Load_balancing_(computing)#Round-robin_scheduling