기본적으로 kubeadm은 각 컨트롤 플레인 노드에서 로컬 etcd 인스턴스를 실행한다. etcd 클러스터를 외부 클러스터로 간주하고 호스트를 분리하여 etcd 인스턴스를 프로비저닝할 수도 있다. 두 접근 방식의 차이점은 고가용성 토폴로지 선택 페이지에서 다룬다.
이 작업에서는 클러스터 생성 중 kubeadm이 사용할 수 있는 멤버 3개로 구성된 고가용성 외부 etcd 클러스터를 만드는 과정을 안내한다.
registry.k8s.io)에 접근할 수 있거나
kubeadm config images list/pull을 사용하여 필요한 etcd 이미지를 나열하거나 가져올 수 있어야 한다.
이 가이드에서는 kubelet이 관리하는 스태틱(static) 파드로
etcd 인스턴스를 설정한다.ssh와 scp로 이 요구 사항을 충족할 수 있다.일반적인 방법은 한 노드에서 모든 인증서를 생성한 다음 필요한 파일만 다른 노드에 배포하는 것이다.
etcd의 서비스 관리자로 kubelet을 구성한다.
cat << EOF > /etc/systemd/system/kubelet.service.d/kubelet.conf
# "systemd"를 컨테이너 런타임의 cgroup 드라이버로 바꾼다. kubelet의 기본값은 "cgroupfs"이다.
# 다른 컨테이너 런타임을 사용하는 경우, 필요에 따라 "containerRuntimeEndpoint" 값을 바꾼다.
#
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
authentication:
anonymous:
enabled: false
webhook:
enabled: false
authorization:
mode: AlwaysAllow
cgroupDriver: systemd
address: 127.0.0.1
containerRuntimeEndpoint: unix:///var/run/containerd/containerd.sock
staticPodPath: /etc/kubernetes/manifests
EOF
cat << EOF > /etc/systemd/system/kubelet.service.d/20-etcd-service-manager.conf
[Service]
ExecStart=
ExecStart=/usr/bin/kubelet --config=/etc/systemd/system/kubelet.service.d/kubelet.conf
Restart=always
EOF
systemctl daemon-reload
systemctl restart kubelet
kubelet이 실행 중인지 확인하려면 상태를 점검한다.
systemctl status kubelet
kubeadm의 구성 파일을 만든다.
다음 스크립트를 사용하여 etcd 멤버를 실행할 각 호스트에 대한 kubeadm 구성 파일을 하나씩 생성한다.
# HOST0, HOST1 및 HOST2를 호스트의 IP 주소로 변경한다
export HOST0=10.0.0.6
export HOST1=10.0.0.7
export HOST2=10.0.0.8
# NAME0, NAME1 및 NAME2를 각 호스트의 호스트네임으로 변경한다
export NAME0="infra0"
export NAME1="infra1"
export NAME2="infra2"
# 다른 호스트로 옮길 파일을 저장할 임시 디렉터리를 만든다
mkdir -p /tmp/${HOST0}/ /tmp/${HOST1}/ /tmp/${HOST2}/
HOSTS=(${HOST0} ${HOST1} ${HOST2})
NAMES=(${NAME0} ${NAME1} ${NAME2})
for i in "${!HOSTS[@]}"; do
HOST=${HOSTS[$i]}
NAME=${NAMES[$i]}
cat << EOF > /tmp/${HOST}/kubeadmcfg.yaml
---
apiVersion: "kubeadm.k8s.io/v1beta4"
kind: InitConfiguration
nodeRegistration:
name: ${NAME}
localAPIEndpoint:
advertiseAddress: ${HOST}
---
apiVersion: "kubeadm.k8s.io/v1beta4"
kind: ClusterConfiguration
etcd:
local:
serverCertSANs:
- "${HOST}"
peerCertSANs:
- "${HOST}"
extraArgs:
- name: initial-cluster
value: ${NAMES[0]}=https://${HOSTS[0]}:2380,${NAMES[1]}=https://${HOSTS[1]}:2380,${NAMES[2]}=https://${HOSTS[2]}:2380
- name: initial-cluster-state
value: new
- name: name
value: ${NAME}
- name: listen-peer-urls
value: https://${HOST}:2380
- name: listen-client-urls
value: https://${HOST}:2379
- name: advertise-client-urls
value: https://${HOST}:2379
- name: initial-advertise-peer-urls
value: https://${HOST}:2380
EOF
done
인증 기관을 생성한다.
이미 인증 기관(CA)이 있다면 CA의 crt 및 key 파일을 /etc/kubernetes/pki/etcd/ca.crt와
/etc/kubernetes/pki/etcd/ca.key에 복사하기만 하면 된다.
이 파일을 복사한 후에는
다음 단계인 "각 멤버의 인증서 생성하기"로 진행한다.
아직 CA가 없다면 (kubeadm 구성 파일을 생성한)
$HOST0에서 다음 명령을 실행한다.
kubeadm init phase certs etcd-ca
이 명령으로 다음 두 파일을 만든다.
/etc/kubernetes/pki/etcd/ca.crt/etc/kubernetes/pki/etcd/ca.key각 멤버의 인증서를 생성한다.
kubeadm init phase certs etcd-server --config=/tmp/${HOST2}/kubeadmcfg.yaml
kubeadm init phase certs etcd-peer --config=/tmp/${HOST2}/kubeadmcfg.yaml
kubeadm init phase certs etcd-healthcheck-client --config=/tmp/${HOST2}/kubeadmcfg.yaml
kubeadm init phase certs apiserver-etcd-client --config=/tmp/${HOST2}/kubeadmcfg.yaml
cp -R /etc/kubernetes/pki /tmp/${HOST2}/
# 재사용할 수 없는 인증서를 정리한다
find /etc/kubernetes/pki -not -name ca.crt -not -name ca.key -type f -delete
kubeadm init phase certs etcd-server --config=/tmp/${HOST1}/kubeadmcfg.yaml
kubeadm init phase certs etcd-peer --config=/tmp/${HOST1}/kubeadmcfg.yaml
kubeadm init phase certs etcd-healthcheck-client --config=/tmp/${HOST1}/kubeadmcfg.yaml
kubeadm init phase certs apiserver-etcd-client --config=/tmp/${HOST1}/kubeadmcfg.yaml
cp -R /etc/kubernetes/pki /tmp/${HOST1}/
find /etc/kubernetes/pki -not -name ca.crt -not -name ca.key -type f -delete
kubeadm init phase certs etcd-server --config=/tmp/${HOST0}/kubeadmcfg.yaml
kubeadm init phase certs etcd-peer --config=/tmp/${HOST0}/kubeadmcfg.yaml
kubeadm init phase certs etcd-healthcheck-client --config=/tmp/${HOST0}/kubeadmcfg.yaml
kubeadm init phase certs apiserver-etcd-client --config=/tmp/${HOST0}/kubeadmcfg.yaml
# HOST0용 인증서이므로 옮길 필요가 없다
# 이 호스트에서 복사하면 안 되는 인증서를 정리한다
find /tmp/${HOST2} -name ca.key -type f -delete
find /tmp/${HOST1} -name ca.key -type f -delete
인증서와 kubeadm 구성을 복사한다.
인증서를 생성했으므로 이제 인증서를 해당 호스트로 옮겨야 한다.
USER=ubuntu
HOST=${HOST1}
scp -r /tmp/${HOST}/* ${USER}@${HOST}:
ssh ${USER}@${HOST}
USER@HOST $ sudo -Es
root@HOST $ chown -R root:root pki
root@HOST $ mv pki /etc/kubernetes/
필요한 파일이 모두 있는지 확인한다.
$HOST0에 필요한 파일의 전체 목록은 다음과 같다.
/tmp/${HOST0}
└── kubeadmcfg.yaml
---
/etc/kubernetes/pki
├── apiserver-etcd-client.crt
├── apiserver-etcd-client.key
└── etcd
├── ca.crt
├── ca.key
├── healthcheck-client.crt
├── healthcheck-client.key
├── peer.crt
├── peer.key
├── server.crt
└── server.key
$HOST1:
$HOME
└── kubeadmcfg.yaml
---
/etc/kubernetes/pki
├── apiserver-etcd-client.crt
├── apiserver-etcd-client.key
└── etcd
├── ca.crt
├── healthcheck-client.crt
├── healthcheck-client.key
├── peer.crt
├── peer.key
├── server.crt
└── server.key
$HOST2:
$HOME
└── kubeadmcfg.yaml
---
/etc/kubernetes/pki
├── apiserver-etcd-client.crt
├── apiserver-etcd-client.key
└── etcd
├── ca.crt
├── healthcheck-client.crt
├── healthcheck-client.key
├── peer.crt
├── peer.key
├── server.crt
└── server.key
스태틱 파드 매니페스트를 생성한다.
이제 인증서와 구성이 준비되었으므로 매니페스트를 만들 차례다.
각 호스트에서 kubeadm 명령을 실행하여
etcd의 스태틱 매니페스트를 생성한다.
root@HOST0 $ kubeadm init phase etcd local --config=/tmp/${HOST0}/kubeadmcfg.yaml
root@HOST1 $ kubeadm init phase etcd local --config=$HOME/kubeadmcfg.yaml
root@HOST2 $ kubeadm init phase etcd local --config=$HOME/kubeadmcfg.yaml
선택 사항: 클러스터 헬스를 확인한다.
만약 etcdctl을 사용할 수 없다면 컨테이너 이미지 안에서 이 도구를 실행할 수 있다.
이 작업은 crictl run 같은 도구를 사용해 Kubernetes를 거치지 않고
컨테이너 런타임에서 직접 수행한다.
ETCDCTL_API=3 etcdctl \
--cert /etc/kubernetes/pki/etcd/peer.crt \
--key /etc/kubernetes/pki/etcd/peer.key \
--cacert /etc/kubernetes/pki/etcd/ca.crt \
--endpoints https://${HOST0}:2379 endpoint health
...
https://[HOST0 IP]:2379 is healthy: successfully committed proposal: took = 16.283339ms
https://[HOST1 IP]:2379 is healthy: successfully committed proposal: took = 19.44402ms
https://[HOST2 IP]:2379 is healthy: successfully committed proposal: took = 35.926451ms
${HOST0}을 테스트할 호스트의 IP 주소로 설정한다.멤버 3개가 정상적으로 작동하는 etcd 클러스터를 만들었다면, kubeadm의 외부 etcd 방식을 사용하여 고가용성 컨트롤 플레인을 계속 설정할 수 있다.