사용 리소스
HAPROXY 설정을 해주나, 기존 스택형 ETCD 구조와 같은 설정을 따랐다.
k8s 마스터 노드 HA 구성 - 참고
etcd가 실행되어야 하는 모든 호스트에서 수행한다.
cat << EOF > /etc/systemd/system/kubelet.service.d/20-etcd-service-manager.conf
[Service]
ExecStart=
# Replace "systemd" with the cgroup driver of your container runtime. The default value in the kubelet is "cgroupfs".
# Replace the value of "--container-runtime-endpoint" for a different container runtime if needed.
ExecStart=/usr/bin/kubelet --address=127.0.0.1 --pod-manifest-path=/etc/kubernetes/manifests --cgroup-driver=systemd --container-runtime=remote --container-runtime-endpoint=unix:///var/run/containerd/containerd.sock
Restart=always
EOF
---
systemctl daemon-reload
systemctl restart kubelet
메인이 되는 ETCD 호스트에서 진행한다.
# 자신의 환경에 맞는 HOST IP 입력
export HOST0=10.0.0.6
export HOST1=10.0.0.7
export HOST2=10.0.0.8
# 자신의 환경에 맞는 HOST NAME 입력
export NAME0="etcd-1"
export NAME1="etcd-2"
export NAME2="etcd-3"
# 각 호스트별 임시 파일 생성
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/v1beta3"
kind: InitConfiguration
nodeRegistration:
name: ${NAME}
localAPIEndpoint:
advertiseAddress: ${HOST}
---
apiVersion: "kubeadm.k8s.io/v1beta3"
kind: ClusterConfiguration
etcd:
local:
serverCertSANs:
- "${HOST}"
peerCertSANs:
- "${HOST}"
extraArgs:
initial-cluster: ${NAMES[0]}=https://${HOSTS[0]}:2380,${NAMES[1]}=https://${HOSTS[1]}:2380,${NAMES[2]}=https://${HOSTS[2]}:2380
initial-cluster-state: new
name: ${NAME}
listen-peer-urls: https://${HOST}:2380
listen-client-urls: https://${HOST}:2379
advertise-client-urls: https://${HOST}:2379
initial-advertise-peer-urls: https://${HOST}:2380
EOF
done
kubeadm에 대한 구성 파일을 생성한 위치에서 생성한다.
이미 CA가 있는 경우 CA crt와 key파일을 /etc/kubernetes/pki/etcd/ca.crt
및 /etc/kubernetes/pki/etcd/ca.key
에 복사한다.
kubeadm init phase certs etcd-ca
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}/
# cleanup non-reusable certificates
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
# No need to move the certs because they are for HOST0
# clean up certs that should not be copied off this host
find /tmp/${HOST2} -name ca.key -type f -delete
find /tmp/${HOST1} -name ca.key -type f -delete
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/
ssh 키 같은 경우는 각자 환경에 맞게 알아서 하자.
이제까지 정상적으로 진행했다면, 각 호스트에 대해 아래와 같은 파일 구조를 볼 수있다.
# 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, 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
docker run --rm -it \
--net host \
-v /etc/kubernetes:/etc/kubernetes k8s.gcr.io/etcd:${ETCD_TAG} 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 --cluster
{ETCD_TAG}
는 자신의 etcd 버전 태그를 입력해준다.
아래 명령어를 통해 확인 가능.
kubeadm config images list
정상적으로 설정 되었다면 아래와 같은 화면을 만날 수 있다.
사실상 etcd 파트를 제외하면 나머지 부분은 큰 차이 없다.
기존의 etcd 노드에서 필요한 파일들을 컨트롤 플레인 노드로 복사하고 적절한 위치로 옮겨준다.
export CONTROL_PLANE="ubuntu@10.0.0.7"
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}":
mkdir -p /etc/kubernetes/pki/etcd/
cp /root/ca.crt /etc/kubernetes/pki/etcd/
cp /root/apiserver-etcd-client.crt /etc/kubernetes/pki/
cp /root/apiserver-etcd-client.key /etc/kubernetes/pki/
kubeadm-config.yaml
파일을 생성해준다.
apiVersion: kubeadm.k8s.io/v1beta3
kind: ClusterConfiguration
kubernetesVersion: stable
controlPlaneEndpoint: "haproxy:6443" # change this (see below)
etcd:
external:
endpoints:
- https://etcd-1:2379 # change ETCD_0_IP appropriately
- https://etcd-2:2379 # change ETCD_1_IP appropriately
- https://etcd-3: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
각 호스트의 이름을 주의 해주고, etcd의 호스트 네임은 etcd의 NAME
변수와 일치 시켜줘야 한다.
etcd의 kubeadmcfg.yaml
을 생성할 때 사용한 NAME
변수를 생각하자.
kubeadm init --config kubeadm-config.yaml --upload-certs
클러스터를 초기화 시켜준다.
스택형 etcd 구조때 사용한 명령어들이 kubeadm-config.yaml
에 작성되어 있다고 생각하면 편할듯.
성공 시 익숙한 화면이 나오고 각 컨트롤 플레인 노드와 워커 노드에서 join 시켜주고, CNI를 설치하자.
root@master-1:~# kubectl get nodes
NAME STATUS ROLES AGE VERSION
master-1 Ready control-plane 19m v1.24.4
master-2 Ready control-plane 16m v1.24.4
master-3 Ready control-plane 16m v1.24.4
node-1 Ready <none> 14m v1.24.4
익숙한 결과를 얻을 수 있다 !
기존의 GCP 계정의 크레딧이 만료되어 새로 크레딧을 발급 받고,
클러스터를 구축하는 과정(외부 etcd 구조)에서 기존의 내용대로 token을 새로 발급 받는 과정에서 에러가 발생했다.
기존에는 어떻게 성공했는지 기억나지 않아 여러 삽질을 하다가..
https://github.com/kubernetes/kubeadm/issues/1886 링크를 통해 해결했다.
kubeadm init phase upload-certs --upload-certs --config kubeadm-config.yaml
명령어를 통해 certificate-key
를 발급 받는다.
기존에 구성할 때 사용했던 명령어를 그대로 사용했더니 이러한 에러가 ;;
https://stackoverflow.com/questions/73995195/k8s-weave-installation-error-converting-yaml-to-json-yaml
위 명령어는 사용 중인 URL은 HTTP 301을 생성하며, 이를 따를 경우 일부 HTML을 제공합니다. YAML로 구문 분석할 때 분명히 오류가 발생합니다.
라는 내용을 찾을 수 있었다.
실제로 링크가 잘못되었나 해서 wget으로 파일을 받아보니 html 파일이긴 하더라..
작성일이 1일 차 인거보니 버전업에서 발생한 문제인가 싶다..
kubectl apply -f https://github.com/weaveworks/weave/releases/download/v2.8.1/weave-daemonset-k8s.yaml
를 사용하자