외부 etcd HA 구성

Jaca·2022년 8월 22일
0

사전 준비

  • 홀수 개의 ETCD 인스턴스
  • TCP 포트 2379 및 2380을 통해 서로 통신할 수 있는 네트워크 설정
  • 호스트 간에 파일을 복사하기 위한 방법. 공식 홈페이지에서는 ssh및 scp 사용.

사용 리소스

  • haproxy (vCPU 2, RAM 2G) 1대
  • ectd (vCPU 2, RAM 2G) 3대
  • master-node (vCPU 2, RAM 4G) 3대
  • worker-node (vCPU 2, RAM 2G) 1대

HAPROXY 설정

HAPROXY 설정을 해주나, 기존 스택형 ETCD 구조와 같은 설정을 따랐다.
k8s 마스터 노드 HA 구성 - 참고

ETCD 클러스터 생성

kubelet을 etcd에 대한 서비스 관리자로 구성

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

kubeadm 구성 파일 생성

메인이 되는 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

CA 생성

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

인증서 및 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/

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

manifest 생성

각 호스트에서 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 파트를 제외하면 나머지 부분은 큰 차이 없다.

CA 복사

기존의 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/

control plane config

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

익숙한 결과를 얻을 수 있다 !

Link

Trouble Shooting

Cluster join

기존의 GCP 계정의 크레딧이 만료되어 새로 크레딧을 발급 받고,
클러스터를 구축하는 과정(외부 etcd 구조)에서 기존의 내용대로 token을 새로 발급 받는 과정에서 에러가 발생했다.

기존에는 어떻게 성공했는지 기억나지 않아 여러 삽질을 하다가..

https://github.com/kubernetes/kubeadm/issues/1886 링크를 통해 해결했다.

kubeadm init phase upload-certs --upload-certs --config kubeadm-config.yaml 명령어를 통해 certificate-key를 발급 받는다.

Weave CNI

기존에 구성할 때 사용했던 명령어를 그대로 사용했더니 이러한 에러가 ;;

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 를 사용하자

profile
I am me

0개의 댓글