이번 장에서는 고가용성 클러스터를 구성하는 방법애 대해 알아보자. kubeadm으로 설치하며, 여러 개의 컨트롤 플레인 노드를 구성하기 위한 방법에 대한 자료이므로, minikube를 사용하고 있거나, 여러 개의 컨트롤 플레인 노드를 구성할 필요가 없으면 스킵해도 좋다.
안타깝게도 고가용성 클러스터 방식으로 설치하지 않은(단일 컨트롤플레인 노드로 구성된 클러스터) 클러스터는 허물고 다시 생성해야 할 것이다. (만약 이게 아니라면 방법 알려주시면 감사하겠습니다..)
고가용성 클러스터 종류
고가용성 쿠버네티스 클러스터를 구성하는 방법은 두 가지가 있다. 이번 글에서 설치 방법은 stack형 만을 다룰 것이다.
- Stack형 컨트롤 플레인 노드: etcd 멤버와 컨트롤 플레인 노드가 같이 위치해있는 구조로 External etcd 보다는 적은 인프라스트럭쳐 자원이 요구된다.
- External etcd 클러스터: 컨트롤 플레인 노드와 etcd member가 분리되어있다. Stack형에서 컨트롤 플레인 노드 만큼의 머신이 필요하기 때문에 Stack형 구조보다 많은 인프라스트럭쳐 자원이 요구된다.
Stack형 구조
스택형 HA 클러스터는 컨트롤 플레인 구성요소를 실행하는 kubeadm에서 관리하는 노드로 구성된 클러스터 위에 etcd에서 제공하는 분산 데이터 저장소 클러스터가 쌓이는 토폴로지이다.
각 컨트롤 플레인 노드는 kube-apiserver
, kube-scheduler
, kube-controller-manager
인스턴스를 구동한다. kube-apiserver
는 로드밸런서를 이용하여 워커 노드에 노출된다.
각 컨트롤 플레인 노드는 로컬 etcd member를 생성하고 해당 etcd member는 해당 노드의 kube-apiserver
, kube-scheduler
, kube-controller-manager
와 통신한다. (단일 컨트롤 플레인 노드와 다를 바 없다.)
이 토폴로지는 컨트롤 플레인과 etcd member를 같은 노드에 결합한다. 그러나 stack형 클러스터는 결합 실패의 위험이 있다. 하나의 노드가 다운된다면, etcd member와 컨트롤 플레인 인스턴스가 같이 다운되고 중복성이 손상된다. 이러한 경우에는 더 많은 컨트롤 플레인 노드를 추가하여 위험을 완화시킬 수 있다. 이러한 이유 때문에 HA 클러스터를 구성하기 위해서 stack형 클러스터를 구성한다면 최소 3개의 컨트롤 플레인이 필요하다. (필자는 2개의 컨트롤 플레인 노드를 구성해보았지만, 둘 중 하나의 노드를 셧다운시키면 쿠버네티스 클러스터가 동작하지 않게 된다. 그리고 3개의 컨트롤 플레인 노드를 구성하였을 때 하나의 노드가 셧다운 될 때는 잘 구동되었지만, 두개의 노드가 셧다운 되었을 때는 동작하지 않았다.)
External etcd 구조
External etcd형 클러스터는 etcd에서 제공하는 분산 데이터 저장소가 컨트롤 플레인 구성 요소를 실행하는 노드에 의해 형성된 클러스터 외부에 있는 토폴로지이다.
stack형 etcd와 같이 external etcd형 클러스터에서 각 컨트롤 플레인 노드는 kube-apiserver
, kube-scheduler
, kube-controller-manager
인스턴스를 구동한다. kube-apiserver
는 로드밸런서를 이용하여 워커 노드에 노출된다. 하지만, etcd member는 호스트와 분리되어 구동한다. 각 etcd 호스트는 각 컨트롤 플레인 노드의 kube-apiserver
와 통신한다.
이 토폴로지는 컨트롤 플레인과 etcd member를 분리한다. 그러므로 이 토폴로지는 컨트롤 플레인 인스턴스나 etcd member의 손실은 클러스터 이중화에 미치는 영향이 적으며 스택형 HA 토폴로지만큼 영향을 미치지 않는 HA 설정을 제공합니다. 그러나 이 토폴로지는 stacked HA 토폴로지의 컨트롤 플레인 노드 개수만큼의 추가 호스트가 필요하다.
Stack형 클러스터 구성
Stack형 클러스터를 구성하기 전에 필요한 자원은 아래와 같다.
- 3개 이상의 컨트롤플레인용 머신
- 3개 이상의 노드용 머신
- 하나의 로드밸런서용 머신
그리고 당연하지만, 모든 머신은 상호 네트워크 통신이 가능해야 한다.
kube-apiserver용 LB 생성
먼저 kube-apiserver용 로드밸런서를 생성한다.
$ sudo apt-get install haproxy
- 클라우드 환경에서는 컨트롤 플레인 노드를 TCP 포워딩 로드밸런서 뒤에 배치해야 한다. 로드밸런서는 타겟 리스트 내 모든 건강한 컨트롤 플레인으로 가는 트래픽을 분산시킨다. apiserver로의 헬스체크는 kube-apiserver가 듣는 포트로 향하는 TCP 체크이다.
- 클라우드 환경에서는 IP 주소를 직접 사용하지 않는 것이 좋다.
- 로드밸런서는 모든 컨트롤플레인 노드의 apiserver 포트와 통신이 되어야 하고 listening port로 들어오는 트래픽을 모두 허용해야 한다.
- 로드밸런서의 주소는 kubeadm의
ControlPlaneEndpoint
의 주소와 일치해야 한다.
그 후 /etc/haproxy/haproxy.cfg
에 haproxy 설정정보를 추가한다.
$ vi /etc/haproxy/haproxy.cfg
#---------------------------------------------------------------------
# Global settings
#---------------------------------------------------------------------
global
log /dev/log local0
log /dev/log local1 notice
daemon
#---------------------------------------------------------------------
# common defaults that all the 'listen' and 'backend' sections will
# use if not designated in their block
#---------------------------------------------------------------------
defaults
mode http
log global
option httplog
option dontlognull
option http-server-close
option forwardfor except 127.0.0.0/8
option redispatch
retries 1
timeout http-request 10s
timeout queue 20s
timeout connect 5s
timeout client 20s
timeout server 20s
timeout http-keep-alive 10s
timeout check 10s
#---------------------------------------------------------------------
# apiserver frontend which proxys to the control plane nodes
#---------------------------------------------------------------------
frontend apiserver
bind *:${APISERVER_DEST_PORT}
mode tcp
option tcplog
default_backend apiserver
#---------------------------------------------------------------------
# round robin balancing for apiserver
#---------------------------------------------------------------------
backend apiserver
option httpchk GET /healthz
http-check expect status 200
mode tcp
option ssl-hello-chk
balance roundrobin
server ${HOST1_ID} ${HOST1_ADDRESS}:${APISERVER_SRC_PORT} check
# [...]
${APISERVER_DEST_PORT}
: K8S가 API Server와 통신할 포트${APISERVER_SRC_PORT}
: API Server 인스턴스에서 사용하는 포트${HOST1_ID}
: 처음 로드밸런스되는 API Server 호스트의 심볼릭 이름${HOST1_ADDRESS}
: 처음 로드밸런스 되는 API Server 호스트에 대한 확인 가능한 주소 (DNS, IP주소 등..)server
라인 밑에서 추가적으로 로드밸런싱할 서버정보를 추가할 수 있다.
그리고 첫 번째 컨트롤 플레인 노드(가 될 머신) 에 로드밸런서를 추가하고 연결을 테스트한다.
$ sudo systemctl restart haproxy
$ sudo systemctl enable haproxy
$ nc -v ${LOAD_BALANCER_IP} ${PORT}
Connection to ${LOAD_BALANCER_IP} ${PORT} port [tcp/*] succeeded!
- connection refused 에러가 만약 발생한다면 apiserver가 아직 실행되지 않아서 발생하는 것이다.
- timeout이 발생한다면 컨트롤플레인 노드와 통신을 할 수 없다는 뜻이기 때문에 네트워크 설정을 확인해봐야 한다.
그 후 컨트롤플레인 노드가 추가된다면 추가된 컨트롤 플레인 노드마다 로드밸런싱 대상에 포함시키면 된다.
Stack형 컨트롤 플레인 노드 설치
먼저 컨트롤 플레인은 설치한다.
$ sudo kubeadm init --control-plane-endpoint ${LOAD_BALANCER_DNS}:${LOAD_BALANCER_PORT} --upload-certs
--control-plane-endpoint
: 로드밸런서의 DNS(IP주소):Port 로 설정해야 한다.--upload-certs
: 클러스터에서 모든 컨트롤 플레인 인스턴스끼리 공유해야하는 인증서를 업로드할 때 해당 플래그를 사용한다. 이를 사용하지 않고 직접 수동적으로 컨트롤플레인 노드에 인증서를 복사하거나 자동 툴을 사용하는 경우에는 해당 플래그를 사용하지 않아도 된다.--pod-network-cidr
이 필요하다면 당연히 추가한다.
설치가 완료되었다면 아래와 같이 화면에 출력될 것이다.
...
You can now join any number of the control-plane node running the following command on each as root:
kubeadm join ${LOAD_BALANCER_DNS}:${LOAD_BALANCER_PORT} --token ${TOKEN} \
--discovery-token-ca-cert-hash sha256:${DISCOVERY_TOKEN_CA_CERT_HASH} \
--control-plane --certificate-key ${CERTIFICATE_KEY}
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.
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join ${LOAD_BALANCER_DNS}:${LOAD_BALANCER_PORT} --token ${TOKEN} \
--discovery-token-ca-cert-hash sha256:${DISCOVERY_TOKEN_CA_CERT_HASH}
- 첫 번째 명령어로 컨트롤플레인 노드를 추가로 붙일 수 있다. (
--certificate-key
추가) - 두 번째 명령어로 일반 노드를 추가로 붙일 수 있다.
--upload-certs
가kubeadm init
와 함께 사용된다면 기본 컨트롤 플레인의 인증서가 암호화되어kubeadm-certs
시크릿에 업로드된다.- 인증서를 재 업로드하거나 새로운 decryption key를 생성하려고 한다면 컨트롤 플레인 노드에서 아래 명령어를 사용하면 된다.
$ sudo kubeadm init phase upload-certs --upload-certs
- 나중에 조인해서 사용할 수 있는 사용자 지정
--certificate-key
를 초기화 중에 지정할 수도 있다. $ kubeadm certs certificate-key
그 후 네트워크 애드온 플러그인을 적용하자. (flannel 등..)
$ kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
그리고 위에서 설명된 첫 번째 명령어, 두 번째 명령어로 컨트롤 플레인노드, 워커 노드를 설치하면 끝! (컨트롤 플레인 노드 추가했다면 HAproxy에서도 서버 추가하는 것 잊지말기!)
마무리
이번 장에서는 쿠버네티스 클러스터의 심장인 컨트롤 플레인노드에 대한 HA 구성에 대하여 살펴보았다. 다음 장에서는 쿠버네티스에서 컨테이너 기반 애플리케이션을 포함하여 애플리케이션을 배포하고 관리하기 위해 사용되는 쿠버네티스 오브젝트에 대하여 공부해보자.
2021.11.24 - [DevOps/Kubernetes] - [3] 쿠버네티스 오브젝트 (1)
'DevOps > Kubernetes' 카테고리의 다른 글
[7] 쿠버네티스 디플로이먼트 (0) | 2022.01.23 |
---|---|
[6] 쿠버네티스 파드 (0) | 2022.01.05 |
[5] 쿠버네티스 오브젝트 (2) (0) | 2022.01.02 |
[4] 쿠버네티스 오브젝트 (1) (0) | 2021.11.24 |
[1] 쿠버네티스 소개 (0) | 2021.11.20 |
댓글