kubeadm으로 고가용성 클러스터 만들기
kubeadm으로 고가용성 클러스터 만들기 (Creating Highly Available Clusters with kubeadm)
이 페이지는 kubeadm을 사용해 고가용성(HA) 쿠버네티스 클러스터를 설정하는 두 가지 다른 접근 방식을 설명해요:
- 스택형(stacked) 제어 플레인 노드 사용. 이 접근 방식은 더 적은 인프라가 필요해요. etcd 멤버와 제어 플레인 노드가 공동 배치돼요.
- 외부 etcd 클러스터 사용. 이 접근 방식은 더 많은 인프라가 필요해요. 제어 플레인 노드와 etcd 멤버가 분리돼요.
진행하기 전에 어떤 접근 방식이 애플리케이션과 환경의 요구를 가장 잘 충족하는지 신중히 고려해야 해요. 고가용성 토폴로지 옵션은 각각의 장단점을 설명해요.
HA 클러스터 설정 중 문제가 발생하면 kubeadm 이슈 트래커에 보고해 주세요.
업그레이드 문서도 참조하세요.
주의:
출처: 문서
본문
시작하기 전에
전제 조건은 클러스터의 제어 플레인에 선택한 토폴로지에 따라 달라져요:
스택형 etcd (Stacked etcd)
필요한 것:
- kubeadm의 제어 플레인 노드 최소 요구 사항을 충족하는 3대 이상의 머신. 제어 플레인 노드가 홀수 개 있으면 머신이나 영역 장애 시 리더 선택에 도움이 될 수 있어요. 이미 설정되고 작동 중인 컨테이너 런타임을 포함.
- 이미 설정되고 작동 중인 컨테이너 런타임을 포함해, kubeadm의 워커 최소 요구 사항을 충족하는 3대 이상의 머신.
- 클러스터의 모든 머신 간의 완전한 네트워크 연결(공용 또는 사설 네트워크).
sudo를 사용하는 모든 머신에서의 슈퍼유저 권한. 다른 도구를 사용할 수 있어요; 이 안내서는 예시에서 sudo를 사용해요.- 시스템의 모든 노드에 대한 한 디바이스에서의 SSH 접근.
- 모든 머신에 이미 설치된 kubeadm과 kubelet.
문맥은 스택형 etcd 토폴로지를 참조하세요.
외부 etcd (External etcd)
필요한 것:
- kubeadm의 제어 플레인 노드 최소 요구 사항을 충족하는 3대 이상의 머신. 제어 플레인 노드가 홀수 개 있으면 머신이나 영역 장애 시 리더 선택에 도움이 될 수 있어요. 이미 설정되고 작동 중인 컨테이너 런타임을 포함.
- 이미 설정되고 작동 중인 컨테이너 런타임을 포함해, kubeadm의 워커 최소 요구 사항을 충족하는 3대 이상의 머신.
- 클러스터의 모든 머신 간의 완전한 네트워크 연결(공용 또는 사설 네트워크).
sudo를 사용하는 모든 머신에서의 슈퍼유저 권한. 다른 도구를 사용할 수 있어요; 이 안내서는 예시에서 sudo를 사용해요.- 시스템의 모든 노드에 대한 한 디바이스에서의 SSH 접근.
- 모든 머신에 이미 설치된 kubeadm과 kubelet.
그리고 추가로 필요해요:
- etcd 클러스터 멤버가 될 3대 이상의 추가 머신. etcd 클러스터에 홀수 개의 멤버를 두는 것은 최적의 투표 쿼럼을 달성하기 위한 요구 사항이에요. 이 머신들에도 kubeadm과 kubelet이 설치되어 있어야 해요. 이 머신들도 이미 설정되고 작동 중인 컨테이너 런타임이 필요해요.
문맥은 외부 etcd 토폴로지를 참조하세요.
컨테이너 이미지
각 호스트는 쿠버네티스 컨테이너 이미지 레지스트리인 registry.k8s.io에서 이미지를 읽고 가져올 수 있어야 해요. 호스트가 이미지를 가져올 수 없는 고가용성 클러스터를 배포하려면, 다른 수단으로 관련 호스트에 올바른 컨테이너 이미지가 이미 사용 가능한지 보장해야 해요.
명령줄 인터페이스
클러스터가 설정되면 쿠버네티스를 관리하기 위해 PC에 kubectl을 설치해야 해요. 각 제어 플레인 노드에 kubectl 도구를 설치하는 것도 유용한데, 문제 해결에 도움이 될 수 있기 때문이에요.
두 방법 모두의 첫 단계
kube-apiserver용 로드 밸런서 만들기
참고:
- DNS로 해석되는 이름을 가진 kube-apiserver 로드 밸런서를 만들어요. 클라우드 환경에서는 제어 플레인 노드를 TCP 포워딩 로드 밸런서 뒤에 배치해야 해요. 이 로드 밸런서는 대상 목록의 모든 정상 제어 플레인 노드에 트래픽을 분산해요. apiserver의 상태 확인은 kube-apiserver가 수신하는 포트(기본값
:6443)에 대한 TCP 검사예요. 클라우드 환경에서 IP 주소를 직접 사용하는 것은 권장되지 않아요. - 로드 밸런서는 apiserver 포트의 모든 제어 플레인 노드와 통신할 수 있어야 해요. 또한 수신 포트에서 들어오는 트래픽을 허용해야 해요.
- 로드 밸런서의 주소가 항상 kubeadm의
ControlPlaneEndpoint주소와 일치하는지 확인하세요. 자세한 내용은 소프트웨어 로드 밸런싱 옵션 가이드를 읽어보세요. - 첫 번째 제어 플레인 노드를 로드 밸런서에 추가하고 연결을 테스트해요:
nc -zv -w 2 <LOAD_BALANCER_IP> <PORT>
API 서버가 아직 실행되지 않으므로 연결 거부(connection refused) 오류가 예상돼요. 그러나 타임아웃은 로드 밸런서가 제어 플레인 노드와 통신할 수 없음을 의미해요. 타임아웃이 발생하면 로드 밸런서가 제어 플레인 노드와 통신하도록 재구성해요.
- 나머지 제어 플레인 노드를 로드 밸런서 대상 그룹에 추가해요.
스택형 제어 플레인과 etcd 노드
첫 번째 제어 플레인 노드의 단계
- 제어 플레인을 초기화해요:
sudo kubeadm init --control-plane-endpoint "LOAD_BALANCER_DNS:LOAD_BALANCER_PORT" --upload-certs
--kubernetes-version플래그를 사용해 사용할 쿠버네티스 버전을 설정할 수 있어요. kubeadm, kubelet, kubectl 그리고 쿠버네티스의 버전이 일치하는 것을 권장해요.--control-plane-endpoint플래그는 로드 밸런서의 주소나 DNS와 포트로 설정해야 해요.--upload-certs플래그는 모든 제어 플레인 인스턴스에 공유되어야 하는 인증서를 클러스터에 업로드하는 데 사용돼요. 대신 인증서를 제어 플레인 노드 간에 수동으로 또는 자동화 도구로 복사하는 것을 선호한다면, 이 플래그를 제거하고 아래의 수동 인증서 배포 섹션을 참조하세요.
참고:
kubeadm init 플래그 --config와 --certificate-key는 혼합할 수 없어요. kubeadm 구성(InitConfiguration과 JoinConfiguration: controlPlane 아래)을 사용하려면 적절한 구성 위치에 certificateKey 필드를 추가해야 해요.
일부 CNI 네트워크 플러그인은 예를 들어 파드 IP CIDR을 지정하는 등 추가 구성이 필요하고, 다른 것은 필요하지 않아요. CNI 네트워크 문서를 참조하세요. 파드 CIDR을 추가하려면 --pod-network-cidr 플래그를 전달하거나, kubeadm 구성 파일을 사용한다면 ClusterConfiguration의 networking 객체 아래에 podSubnet 필드를 설정하세요.
출력은 다음과 비슷해요:
...
You can now join any number of control-plane node by running the following command on each as root:
kubeadm join 192.168.0.200: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 192.168.0.200:6443 --token 9vr73a.a8uxyaju799qwdjv --discovery-token-ca-cert-hash sha256:7c2e69131a36ae2a042a339b33381c6d0d43887e2de83720eff5359e26aec866
- 이 출력을 텍스트 파일에 복사해요. 나중에 제어 플레인과 워커 노드를 클러스터에 조인하는 데 필요할 거예요.
--upload-certs가kubeadm init과 함께 사용되면, 기본 제어 플레인의 인증서가 암호화되어kubeadm-certsSecret에 업로드돼요.- 인증서를 다시 업로드하고 새 복호화 키를 생성하려면, 이미 클러스터에 조인된 제어 플레인 노드에서 다음 명령을 사용해요:
sudo kubeadm init phase upload-certs --upload-certs
- init 중에 사용자 지정
--certificate-key를 지정할 수도 있는데, 나중에 join이 사용할 수 있어요. 그러한 키를 생성하려면 다음 명령을 사용할 수 있어요:
kubeadm certs certificate-key
인증서 키는 32바이트 크기의 AES 키인 hex 인코딩 문자열이에요.
참고:
주의:
- 선택한 CNI 플러그인을 적용해요: 이 지침을 따라 CNI 제공자를 설치해요. 구성이 kubeadm 구성 파일에 지정된 파드 CIDR과 일치하는지 확인하세요(해당하는 경우).
참고:
- 다음을 입력하고 제어 플레인 컴포넌트의 파드가 시작되는 것을 지켜봐요:
kubectl get pod -n kube-system -w
나머지 제어 플레인 노드의 단계
각 추가 제어 플레인 노드에 대해:
- 첫 번째 노드에서
kubeadm init출력이 미리 준 `join 명령을 실행해요. 다음과 비슷해야 해요:
sudo kubeadm join 192.168.0.200:6443 --token 9vr73a.a8uxyaju799qwdjv --discovery-token-ca-cert-hash sha256:7c2e69131a36ae2a042a339b33381c6d0d43887e2de83720eff5359e26aec866 --control-plane --certificate-key f8902e114ef118304e561c3ecd4d0b543adc226b7a07f675f56564185ffe0c07
--control-plane플래그는 kubeadm join에게 새 제어 플레인을 만들라고 알려줘요.--certificate-key ...는 클러스터의kubeadm-certsSecret에서 제어 플레인 인증서를 다운로드하고 주어진 키로 복호화하게 해요.
참고:
외부 etcd 노드
외부 etcd 노드로 클러스터를 설정하는 것은 etcd를 먼저 설정하고 kubeadm 구성 파일에 etcd 정보를 전달해야 한다는 점을 제외하면 스택형 etcd에 사용된 절차와 유사해요.
etcd 클러스터 설정
- 이 지침을 따라 etcd 클러스터를 설정해요.
- 여기에 설명된 대로 SSH를 설정해요.
- 클러스터의 어떤 etcd 노드든 첫 번째 제어 플레인 노드에 다음 파일을 복사해요:
export CONTROL_PLANE="[email protected]"
scp /etc/kubernetes/pki/etcd/ca.crt "${CONTROL_PLANE}":
scp /etc/kubernetes/pki/apiserver-etcd-client.crt "${CONTROL_PLANE}":
scp /etc/kubernetes/pki/apiserver-etcd-client.key "${CONTROL_PLANE}":
CONTROL_PLANE값을 첫 번째 제어 플레인 노드의user@host로 교체해요.
첫 번째 제어 플레인 노드 설정
- 다음 내용으로
kubeadm-config.yaml이라는 파일을 만들어요:
---
apiVersion: kubeadm.k8s.io/v1beta4
kind: ClusterConfiguration
kubernetesVersion: stable
controlPlaneEndpoint: "LOAD_BALANCER_DNS:LOAD_BALANCER_PORT" # change this (see below)
etcd:
external:
endpoints:
- https://ETCD_0_IP:2379 # change ETCD_0_IP appropriately
- https://ETCD_1_IP:2379 # change ETCD_1_IP appropriately
- https://ETCD_2_IP:2379 # change ETCD_2_IP appropriately
caFile: /etc/kubernetes/pki/etcd/ca.crt
certFile: /etc/kubernetes/pki/apiserver-etcd-client.crt
keyFile: /etc/kubernetes/pki/apiserver-etcd-client.key
참고:
- 구성 템플릿의 다음 변수를 클러스터에 적절한 값으로 교체해요:
LOAD_BALANCER_DNS,LOAD_BALANCER_PORT,ETCD_0_IP,ETCD_1_IP,ETCD_2_IP.
다음 단계는 스택형 etcd 설정과 유사해요:
- 이 노드에서
sudo kubeadm init --config kubeadm-config.yaml --upload-certs를 실행해요. - 반환된 출력 join 명령을 나중에 사용하기 위해 텍스트 파일에 써요.
- 선택한 CNI 플러그인을 적용해요.
참고:
나머지 제어 플레인 노드의 단계
단계는 스택형 etcd 설정과 같아요:
- 첫 번째 제어 플레인 노드가 완전히 초기화되었는지 확인해요.
- 텍스트 파일에 저장한 join 명령으로 각 제어 플레인 노드를 조인해요. 제어 플레인 노드를 한 번에 하나씩 조인하는 것을 권장해요.
--certificate-key의 복호화 키가 기본적으로 두 시간 후에 만료된다는 것을 잊지 마세요.
제어 플레인 부트스트랩 후의 공통 작업
워커 설치
워커 노드는 이전에 kubeadm init 명령의 출력으로 저장한 명령으로 클러스터에 조인할 수 있어요:
sudo kubeadm join 192.168.0.200:6443 --token 9vr73a.a8uxyaju799qwdjv --discovery-token-ca-cert-hash sha256:7c2e69131a36ae2a042a339b33381c6d0d43887e2de83720eff5359e26aec866
수동 인증서 배포
--upload-certs 플래그와 함께 kubeadm init을 사용하지 않기로 선택했다면 기본 제어 플레인 노드에서 조인하는 제어 플레인 노드로 인증서를 수동으로 복사해야 한다는 뜻이에요.
이를 수행하는 방법은 여러 가지가 있어요. 다음 예시는 ssh와 scp를 사용해요.
단일 머신에서 모든 노드를 제어하려면 SSH가 필요해요.
- 시스템의 다른 모든 노드에 접근할 수 있는 주 디바이스에서 ssh-agent를 활성화해요:
eval $(ssh-agent)
- 세션에 SSH ID를 추가해요:
ssh-add ~/.ssh/path_to_private_key
-
노드 간에 SSH를 사용해 연결이 올바르게 작동하는지 확인해요.
-
어떤 노드에든 SSH할 때
-A플래그를 추가해요. 이 플래그는 SSH로 로그인한 노드가 PC의 SSH 에이전트에 접근할 수 있게 해줘요. 노드에서의 사용자 세션의 보안을 완전히 신뢰하지 않는다면 대체 방법을 고려하세요.
ssh -A 10.0.0.7
- 어떤 노드에서든 sudo를 사용할 때 SSH 포워딩이 작동하도록 환경을 보존해야 해요:
sudo -E -s
- 모든 노드에서 SSH를 구성한 후,
kubeadm init을 실행한 후 첫 번째 제어 플레인 노드에서 다음 스크립트를 실행해야 해요. 이 스크립트는 첫 번째 제어 플레인 노드에서 다른 제어 플레인 노드로 인증서를 복사해요:
다음 예시에서 CONTROL_PLANE_IPS를 다른 제어 플레인 노드의 IP 주소로 교체해요.
USER=ubuntu # customizable
CONTROL_PLANE_IPS="10.0.0.7 10.0.0.8"
for host in ${CONTROL_PLANE_IPS}; do
scp /etc/kubernetes/pki/ca.crt "${USER}"@$host:
scp /etc/kubernetes/pki/ca.key "${USER}"@$host:
scp /etc/kubernetes/pki/sa.key "${USER}"@$host:
scp /etc/kubernetes/pki/sa.pub "${USER}"@$host:
scp /etc/kubernetes/pki/front-proxy-ca.crt "${USER}"@$host:
scp /etc/kubernetes/pki/front-proxy-ca.key "${USER}"@$host:
scp /etc/kubernetes/pki/etcd/ca.crt "${USER}"@$host:etcd-ca.crt
# Skip the next line if you are using external etcd
scp /etc/kubernetes/pki/etcd/ca.key "${USER}"@$host:etcd-ca.key
done
주의:
위 목록의 인증서만 복사하세요. kubeadm은 조인하는 제어 플레인 인스턴스에 필요한 SAN이 있는 나머지 인증서 생성을 처리할 거예요. 실수로 모든 인증서를 복사하면, 필요한 SAN이 없어서 추가 노드 생성이 실패할 수 있어요.
- 그런 다음 각 조인하는 제어 플레인 노드에서
kubeadm join을 실행하기 전에 다음 스크립트를 실행해야 해요. 이 스크립트는 이전에 복사한 인증서를 홈 디렉터리에서/etc/kubernetes/pki로 이동해요:
USER=ubuntu # customizable
mkdir -p /etc/kubernetes/pki/etcd
mv /home/${USER}/ca.crt /etc/kubernetes/pki/
mv /home/${USER}/ca.key /etc/kubernetes/pki/
mv /home/${USER}/sa.pub /etc/kubernetes/pki/
mv /home/${USER}/sa.key /etc/kubernetes/pki/
mv /home/${USER}/front-proxy-ca.crt /etc/kubernetes/pki/
mv /home/${USER}/front-proxy-ca.key /etc/kubernetes/pki/
mv /home/${USER}/etcd-ca.crt /etc/kubernetes/pki/etcd/ca.crt
# Skip the next line if you are using external etcd
mv /home/${USER}/etcd-ca.key /etc/kubernetes/pki/etcd/ca.key