본문 바로가기

가상화/Kubernetes

[kubernetes] kubeadm을 사용하여 고 가용성(HA) 클러스터 만들기

반응형

개요

kubernetes에서 HA를 구성하는 방법으로 stacked etcd, external etcd 두가지 방법이 있다. 그림 1의 stacked etcd는 control plane node에서 etcd가  작동하는 반면, 그림 2의 external etcd는 control plane node와 etcd가 다른 노드에서 작동한다. HA를 구성하기 위해서는 쿼럼이 과반수를 초과해야만 하기 때문에 최소 3대 이상(3,5,7,...)의 노드를 필요로 한다. 이번 시간에는 stacked etcd 를 구성하는 방법에 대해 알아보고자 한다.

[그림 1] HA 토폴로지 - stacked etcd
[그림 1] HA 토폴로지 - external etcd

구성환경

Ubuntu 18.04.1, Docker 19.03.8, Kubernet v1.17.4

사전 준비

Docker, Kubernet이 미리 설치 되어 있어야한다.

로드 발란서(Load Balancer)

 - dns 로드 발란서 사용, apisvr 라운드로빈(round-robin) 활용, 참고로 도메인은 hoya.com

apisvr    IN      A       192.168.0.160
              IN      A       192.168.0.161 
              IN      A       192.168.0.162

 

첫번째 Control plane node

1. Control plane 초기화

shell> sudo kubeadm init --control-plane-endpoint apisvr.hoya.com:6443 --upload-certs

** apisvr.hoya.com:6443 은 자기 환경에 맞게 설정한다.

--upload-certs : control plane 인스턴스에서 공유해야 하는 인증서를 업로드(자동배포), 수동으로 인증서를 복사할 경우는 이 옵션 생략

control plane 초기화(kubeadm init)를 진행하면 아래와 같은 내용이 출력될 것이다. 아래 내용을 복사해 놓도록 한다. 이 명령어를 이용하여 클러스터에 조인(join) 할수 있다. 파란색글씨(위쪽)는 control plane 노드에서 실행, 주황색 글씨(아래)는 worker node에서 실행

You can now join any number of control-plane node by running the following command on each as a root:
kubeadm join apisvr.hoya.com:6443 --token 9vr73a.a8uxyaju799qwdjv --discovery-token-ca-cert-hash sha256:7c2e69131a36ae2a042a339b33381c6d0d43887e2de83720eff5359e26aec866 --control-plane --certificate-key f8902e114ef118304e561c3ecd4d0b543adc226b7a07f675f56564185ffe0c07

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 to reload certs afterward.

Then you can join any number of worker nodes by running the following on each as root:
kubeadm join apisvr.hoya.com:6443 --token 9vr73a.a8uxyaju799qwdjv --discovery-token-ca-cert-hash sha256:7c2e69131a36ae2a042a339b33381c6d0d43887e2de83720eff5359e26aec866

참고: certificate-key를 지정하여 나중에 조인에서 사용할 수 있습니다. 

shell> sudo kubeadm certs certificate-key
f8902e114ef118304e561c3ecd4d0b543adc226b7a07f675f56564185ffe0c07 

참고: worker node에서 토큰을 사용하여 클러스터에 가입하는 데 필요한 전체 'kubeadm join' 플래그를 출력

shell> sudo kubeadm token create --print-join-command

참고: 인증서를 다시 업로드하고 새 암호 해독 키를 생성하려면 이미 클러스터에 연결된 control plane 노드에서 다음 명령을 사용하십시오.

shell> sudo kubeadm init phase upload-certs --upload-certs
W0322 16:20:40.631234  101997 validation.go:28] Cannot validate kube-proxy config - no validator is available
W0322 16:20:40.631413  101997 validation.go:28] Cannot validate kubelet config - no validator is available
[upload-certs] Storing the certificates in Secret "kubeadm-certs" in the "kube-system" Namespace
[upload-certs] Using certificate key:
7f97aaa65bfec1f039c4dbdf3a2073de853c708bd4d9ff9d72b776b0f9874c9d

참고 :  클러스터를 control plane 조인(join)하는 데 필요한 전체 'kubeadm join' 플래그를 출력

shell> sudo kubeadm token create --print-join-command --certificate-key \  7f97aaa65bfec1f039c4dbdf3a2073de853c708bd4d9ff9d72b776b0f9874c9d

2. CNI(Container Network Interface) 플러그인 설치

- 여기서는 weave CNI 플러그인 설치(그외 flannel, Calico, ....)

shell> kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"

컨트롤러에서 클러스터를 관리하기 위해서 아래의 명령을 실행

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

나머지 Control plane 노드

1. 첫번째 Control plane 노드에서 kubeadm init 결과(파란색 글씨)를 실행한다.

shell> kubeadm join apisvr.hoya.com:6443 --token 9vr73a.a8uxyaju799qwdjv --discovery-token-ca-cert-hash sha256:7c2e69131a36ae2a042a339b33381c6d0d43887e2de83720eff5359e26aec866 --control-plane --certificate-key f8902e114ef118304e561c3ecd4d0b543adc226b7a07f675f56564185ffe0c07 

-  나머지 컨트롤러에서도 클러스터를 관리하기 위해서 아래의 명령을 실행

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

2. 확인

- 노드 상태가 Ready인지 확인

shell> kubectl get nodes
NAME        STATUS   ROLES    AGE     VERSION
master1    Ready    master   41s     v1.17.4
master2    Ready    master   3m59s   v1.17.4
master3    Ready    master   92s     v1.17.4
shell>

- pods의 상태(Status)가 모두 Running 상태인지 확인

shell> kubectl get pods --all-namespaces
NAMESPACE     NAME                                READY   STATUS    RESTARTS   AGE
kube-system   coredns-6955765f44-7jk6m            1/1     Running   0          3m42s
kube-system   coredns-6955765f44-vgw2j            1/1     Running   0          3m42s
kube-system   etcd-master3                       1/1     Running   0          31s
kube-system   etcd-master1                       1/1     Running   0          3m44s
kube-system   etcd-master2                      1/1     Running   0          83s
kube-system   kube-apiserver-master3             1/1     Running   0          33s
kube-system   kube-apiserver-master1             1/1     Running   0          3m44s
kube-system   kube-apiserver-master2            1/1     Running   0          84s
kube-system   kube-controller-manager-master3    1/1     Running   0          33s
kube-system   kube-controller-manager-master1    1/1     Running   1          3m44s
kube-system   kube-controller-manager-master2   1/1     Running   0          84s
kube-system   kube-proxy-hd8vq                    1/1     Running   0          84s
kube-system   kube-proxy-v9s8h                    1/1     Running   0          3m42s
kube-system   kube-proxy-z76td                    1/1     Running   0          33s
kube-system   kube-scheduler-master3             1/1     Running   0          33s
kube-system   kube-scheduler-master1             1/1     Running   1          3m44s
kube-system   kube-scheduler-master2            1/1     Running   0          84s
kube-system   weave-net-6dkt6                     2/2     Running   3          84s
kube-system   weave-net-9zswx                     2/2     Running   0          3m3s
kube-system   weave-net-fvf9q                     2/2     Running   0          33s

woker node

1. 첫번째 Control plane 노드에서 kubeadm init 결과(주황색 글씨)를 실행한다.

kubeadm join apisvr.hoya.com:6443 --token 9vr73a.a8uxyaju799qwdjv --discovery-token-ca-cert-hash sha256:7c2e69131a36ae2a042a339b33381c6d0d43887e2de83720eff5359e26aec866

 

HA에서 control plane 노드 제거

 방법 1) 제거 할 노드에서 아래 명령어(kubeadm reset) 실행

shell> sudo kubeadm reset

** kubectl delete node로 control plane노드 를 제거하지 않도록 한다. 만약 kubectl delete node로 삭제하는 경우 이후 추가 되는 control plane 노드들은 HA에 추가 될수 없다. 그 이유는 kubeadm reset은 HA내 다른  control plane 노드의 etcd에서 etcd endpoint 정보를 지우지만 kubectl delete node는 HA 내의 다른 controle plane 노드에서 etcd endpoint 정보를 지우지 못하기 때문이다. 이로 인해 이후 HA에 추가되는 control plane 노드는 삭제된 노드의 etcd endpoint 접속이 되지 않기 때문에 etcd 유효성 검사 과정에서 오류가 발생하게 된다. 

- control plane 노드를 kubectl delete node 로 삭제후 control plane 노드 추가시 오류 메시지

shell> kubeadm join ..... --control-plane --certyficate-key
... 생략 ...
[check-etcd] Checking that the etcd cluster is healthy 
error execution phase check-etcd: etcd cluster is not healthy: failed to dial endpoint https://192.168.0.159:2379 with maintenance client: context deadline exceeded 
To see the stack trace of this error execute with --v=5 or higher

 방법 2) etcd member 삭제 진행 절차

  step 1. 유효한 control plane 노드에서 etcd member id 확인

shell> etcdctl --cacert=/etc/kubernetes/pki/etcd/ca.crt \ 
 --cert=/etc/kubernetes/pki/etcd/peer.crt \ 
 --key=/etc/kubernetes/pki/etcd/peer.key  member list 

81ce68f24db8ced, started, master1, https://192.168.0.159:2380, https://192.168.0.159:2379, false  
5364415ff53d0975, started, master3, https://192.168.0.158:2380, https://192.168.0.158:2379, false  
b27f6573a770c244, started, master2, https://192.168.0.149:2380, https://192.168.0.149:2379, false  
shell>

  step 2. 멤버 제거

shell> etcdctl -cacert=/etc/kubernetes/pki/etcd/ca.crt  \ 
--cert=/etc/kubernetes/pki/etcd/peer.crt \  
--key=/etc/kubernetes/pki/etcd/peer.key member remove 81ce68f24db8ced

Member  81ce68f24db8ced removed from cluster  88707d65fd36eb2 
shell>

 

TroubleShooting

참고 : 아래 환경에서 etcdctl 을 이용하여 접속하면 오류가 발생하여 etcd 버전을 업그레이드(v3.4.5)하여 진행, 아마 etcd, etcdctl 은 마이너 버전까지 일치해야만 정상 작동하는듯 하다.

 - kubernetes etcd 버전 : 3.4.3-0

 - etcdctl 버전

shell> etcdctl --version
etcdctl version: 3.2.10
API version: 2

 

증상 1) etcdctl version 3.2.10 으로 실행 오류 #1 - 404 오류 발생

shell> etcdctl -C https://192.168.0.149:2379 --ca-file=/tmp/pki/ca.crt  \
--cert-file=/tmp/pki/peer.crt  \
--key-file=/tmp/pki/peer.key member list 
unexpected status code 404 
shell>

증상 2) etcdctl version 3.2.10 으로 실행시 오류 #2( /etc/kubernetes/pki/etcd 디폴트 위치한 인증서 사용시)

shell> etcdctl -C https://192.168.0.149:2379 --ca-file=/etc/kubernetes/pki/etcd/ca.crt  \
--cert-file=/etc/kubernetes/pki/etcd/peer.crt  \
--key-file=/etc/kubernetes/pki/etcd/peer.key member list 
open /etc/kubernetes/pki/etcd/peer.crt: permission denied 
shell>

 

반응형

'가상화 > Kubernetes' 카테고리의 다른 글

[Docker] Image Build  (0) 2020.03.25
[kubernetes] 웹 UI(대시보드)  (0) 2020.03.23
[kubernetes] 설치  (0) 2020.03.15
[Docker] swarm 모드에서 컨테이너 rebalance  (0) 2020.01.15
[Docker] docker service create --mode 옵션  (0) 2020.01.15