쿠버네티스 클러스터 구성하는 것은 컨테이너화된 애플리케이션의 안정성과 견고성을 보장하는 데 중요합니다. 이 안내서는 kubeadm을 사용한 두 가지 다른 접근 방식에 대해 다루고 있습니다. 하나는 스택된 제어 평면 노드를 사용하고 다른 하나는 외부 etcd 클러스터를 사용합니다. 계속하기 전에 응용 프로그램 및 환경 요구 사항을 신중하게 검토하십시오.
사전 작업 리눅스 CentOS 네트워크 설정

리눅스 hostname 설정
먼저, 호스트네임을 localhost.localdomain
에서 ntech
로 변경합니다.
# hostnamectl set-hostname ntech
# hostnamectl
리눅스 네트워크 IP gateway 설정
그 후, 네트워크 설정을 변경합니다.
# nmcli con mod enp0s8 ipv4.addresses 192.168.25.31/24
# nmcli con mod enp0s8 ipv4.gateway 192.168.25.1
# nmcli con up enp0s8
hosts 파일 정의
다음은 각 노드의 NIC 설정입니다.
centos8
: 192.168.76.100master1
: 192.168.76.101master2
: 192.168.76.102master3
: 192.168.76.103worker1
: 192.168.76.104worker2
: 192.168.76.105lb
: 192.168.76.106
/etc/hosts 호스트 파일 설정
/etc/hosts
파일을 업데이트하여 각 노드에 대한 호스트 정보를 추가합니다.
192.168.76.100 centos8
192.168.76.101 master1.example.com master1
192.168.76.102 master2.example.com master2
192.168.76.103 master3.example.com master3
192.168.76.104 worker1.example.com worker1
192.168.76.105 worker2.example.com worker2
192.168.76.106 lb.example.com lb
쿠버네티스 클러스터 구성 설치

Docker 설치
# Docker 설치
yum install -y yum-utils
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# CentOS 8
dnf install docker-ce docker-ce-cli containerd.io --nobest
# CentOS 8 설치 문제 해결
yum remove -y docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-selinux docker-engine-selinux docker-engine
yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo http://download.docker.com/linux/centos/docker-ce.repo
yum install -y docker-ce
systemctl start docker
systemctl enable docker
systemctl status docker
## docker-ce 대신 docker를 설치하면 구 버전이 설치됩니다.
# CentOS 7
yum install docker-ce docker-ce-cli containerd.io -y
systemctl start docker && systemctl enable docker
docker version
방화벽 비활성화 및 iptables 설정
# 방화벽 중지 및 비활성화
systemctl stop firewalld
systemctl disable firewalld
# iptables 설정 업데이트
cat <<EOF > /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
sysctl --system
SWAP 및 SELinux 비활성화
# SWAP 비활성화
swapoff -a && sed -i '/swap/s/^/#/' /etc/fstab
# SELinux 비활성화
setenforce 0
sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
Kubernetes Repo 추가
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
EOF
kubelet, kubeadm, kubectl 설치 및 서비스 시작
yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes
systemctl enable kubelet && systemctl start kubelet
systemctl status kubelet
쿠버네티스 클러스터 LB (Load Balancer) 구성

mkdir /etc/nginx
cat << END > /etc/nginx/nginx.conf
event { }
stream {
upstream stream_backend {
last_conn;
server 192.168.76.101:6443;
server 192.168.76.102:6443;
server 192.168.76.103:6443;
}
server {
listen 6443;
proxy_pass stream_backend;
proxy_timeout 300s;
proxy_connect_timeout 1s;
}
}
END
Docker 컨테이너로 NGINX 실행 및 LB 운영
# NGINX 컨테이너 실행
docker run --name proxy -v /etc/nginx/nginx.conf:/etc/nginx/nginx:ro --restart=always -p 6443:6443 -d nginx
# 테스트 - 세션이 없으므로 실패 발생함
curl 192.168.76.105:6443
Kubeadm HA 클러스터 구성
# master1에서 kubeadm init 명령으로 LB 등록
kubeadm init --control-plane-endpoint "lb.example.com:6443" --upload-certs
또는
sudo kubeadm init --control-plane-endpoint "LOAD_BALANCER_DNS:LOAD_BALANCER_PORT" --upload-certs
kube-apiserver용 로드 밸런서 생성
kube-apiserver
로드 밸런서를 DNS로 확인되는 이름으로 생성하는 방법은 클라우드 환경에 따라 다양한 구성이 필요합니다. 다음은 하나의 예시이며 클러스터 요구 사항에 따라 다른 구성이 필요할 수 있습니다.
로드 밸런서는 클라우드 환경에서는 TCP 전달 로드 밸런서 뒤에 제어 플레인 노드를 배치해야 합니다. 이 로드 밸런서는 대상 목록의 모든 정상 제어 영역 노드에 트래픽을 분산하며, apiserver에 대한 상태 확인은 kube-apiserver가 수신 대기하는 포트(기본값: 6443)에 대한 TCP 확인입니다.
클라우드 환경에서는 IP 주소를 직접 사용하는 것이 권장되지 않습니다. 로드 밸런서는 apiserver 포트의 모든 제어 플레인 노드와 통신할 수 있어야 하며, 수신 포트에서 들어오는 트래픽을 허용해야 합니다. 로드 밸런서의 주소가 항상 kubeadm
의 주소와 일치하는지 확인해야 합니다.
로드 밸런서 구성은 클라우드 환경에 따라 다르므로 소프트웨어 부하 분산 옵션 가이드를 참조해야 합니다.
로드 밸런서에 첫 번째 제어 영역 노드를 추가하고 연결을 테스트합니다.
nc -v <LOAD_BALANCER_IP> <PORT>
API 서버가 실행 중이 아니기 때문에 연결이 거부될 것입니다. 그러나 타임아웃이 발생하면 로드 밸런서가 제어 플레인 노드와 통신할 수 없음을 의미합니다. 타임아웃이 발생하면 로드 밸런서를 재구성하여 제어 영역 노드와 통신하도록 해야 합니다.
나머지 제어 영역 노드를 로드 밸런서 대상 그룹에 추가합니다.
쿠버네티스 클러스터 control plane, etcd 노드설정
Kubernetes 클러스터에서 stacked control plane 및 etcd 노드를 설정하는 단계는 다음과 같습니다:

첫 번째 Control Plane 노드 설정 단계:
다음 명령을 사용하여 control plane을 초기화합니다:
sudo kubeadm init --control-plane-endpoint "LOAD_BALANCER_DNS:LOAD_BALANCER_PORT" --upload-certs
--kubernetes-version
플래그를 사용하여 Kubernetes 버전을 설정할 수 있습니다.--control-plane-endpoint
플래그는 로드 밸런서의 주소 또는 DNS 및 포트를 지정해야 합니다.--upload-certs
플래그는 control-plane 인스턴스 간에 공유되는 인증서를 업로드하는 데 사용됩니다.
출력에는 control-plane 노드를 추가하는 데 사용할 수 있는 kubeadm join
명령이 포함됩니다.
일부 CNI 네트워크 플러그인은 추가 구성이 필요할 수 있습니다. 자세한 내용은 CNI 네트워크 문서를 참조하세요.
나머지 Control Plane 노드 설정 단계:
각 추가 control-plane 노드에 대해:
첫 번째 노드 초기화 출력에서 제공된 kubeadm 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
플래그는 새로운 control plane을 생성합니다.--certificate-key
옵션은 클러스터에서kubeadm-certs
시크릿으로부터 control plane 인증서를 다운로드하고 지정된 키를 사용하여 해독합니다.
여러 control-plane 노드를 병렬로 추가할 수 있습니다.
인증서 재업로드:
- 필요한 경우 다음 명령을 사용하여 인증서를 다시 업로드하고 새로운 해독 키를 생성할 수 있습니다:
sudo kubeadm init phase upload-certs --upload-certs
- 사용자 지정 인증서 키를 생성하려면 다음 명령을 사용합니다:
kubeadm certs certificate-key
kubeadm-certs
시크릿 및 해독 키는 두 시간 후에 만료됩니다.
CNI 플러그인 적용:
- 사용 사례에 맞는 CNI 플러그인을 선택하고 적용하세요. CNI 제공자를 설치하는 지침을 따르고 구성이 kubeadm 구성 파일에 지정된 Pod CIDR과 일치하는지 확인하세요.
Control Plane Pods 확인:
다음 명령을 사용하여 control plane 구성 요소의 상태를 확인합니다:
kubectl get pod -n kube-system -w
control plane 구성 요소의 pod가 올바르게 시작되었는지 확인하세요.
외부 etcd 노드 클러스터 설정
외부 etcd 노드를 사용하는 Kubernetes 클러스터를 설정하는 단계는 스택된 etcd와 비슷하지만, 먼저 etcd를 설정하고 그 정보를 kubeadm 구성 파일에 전달해야 한다는 점이 차이가 있습니다.

etcd 클러스터 설정
클러스터를 설정하는 일반적인 접근 방식은 한 노드에서 모든 인증서를 생성하고 다른 노드로 필요한 파일만 배포하는 것입니다.
주의: 이 예제에서는 kubeadm에 이미 모든 필요한 암호화 도구가 포함되어 있습니다. 다른 암호화 도구는 필요하지 않습니다.
주의: 아래의 예제는 IPv4 주소를 사용하지만, kubeadm, kubelet 및 etcd를 IPv6 주소를 사용하도록 구성할 수도 있습니다. 일부 Kubernetes 옵션에서는 듀얼 스택을 지원하지만 etcd에서는 지원되지 않습니다. Kubernetes 듀얼 스택 지원에 대한 자세한 내용은 Kubeadm과 듀얼 스택 지원을 참조하세요.
kubelet을 etcd의 서비스 매니저로 구성
주의: 이 작업은 etcd가 실행될 각 호스트에서 수행해야 합니다.
kubelet
을 etcd의 서비스 매니저로 구성합니다. etcd가 먼저 생성되었기 때문에 새로운 유닛 파일을 만들어 우선 순위를 높이는 방식으로 서비스 우선 순위를 재정의해야 합니다.
cat << EOF > /etc/systemd/system/kubelet.service.d/kubelet.conf
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
kubelet daemon 재시작 및 확인
systemctl daemon-reload
systemctl restart kubelet
# kubelet 상태를 확인하여 실행 중인지 확인합니다.systemctl status kubelet
kubeadm을 위한 구성 파일 생성
각 etcd 멤버를 위해 하나의 kubeadm 구성 파일을 생성합니다. 다음 스크립트를 사용하여 각 호스트에 대해 kubeadm 구성 파일을 생성합니다.
export HOST0=10.0.0.6
export HOST1=10.0.0.7
export HOST2=10.0.0.8
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/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가 이미 있다면, CA의 crt 및 key 파일을 /etc/kubernetes/pki/etcd/ca.crt
및 /etc/kubernetes/pki/etcd/ca.key
로 복사합니다. 이 파일들을 복사한 후 다음 단계인 “각 멤버를 위한 인증서 생성”으로 진행합니다.
CA가 없다면 다음 명령을 실행하여 $HOST0 (kubeadm 구성 파일을 생성한 곳)에서 CA를 생성합니다.
kubeadm init phase certs etcd-ca
이 명령은 두 개의 파일을 생성합니다:
/etc/kubernetes/pki/etcd/ca.crt
/etc/kubernetes/pki/etcd/ca.key
각 멤버를 위한 인증서 생성
각 etcd 멤버의 인증서를 생성합니다.
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.yam
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}/kubead
수동 인증서 배포
만약 kubeadm init
명령에 --upload-certs
플래그를 사용하지 않았다면, 즉, 기본 제어 플레인 노드의 인증서를 다른 제어 플레인 노드에 자동으로 업로드하지 않았다면, 수동으로 복사해야 합니다. 이를 위해 scp
와 같은 도구를 사용합니다.
SSH 에이전트 활성화
eval $(ssh-agent)
ssh-add ~/.ssh/path_to_private_key
ssh -A 10.0.0.7
sudo -E -s
인증서 복사 스크립트 실행
USER=ubuntu # 사용자에 따라 변경 가능
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
# 외부 etcd를 사용하는 경우 다음 라인을 건너뛰세요
scp /etc/kubernetes/pki/etcd/ca.key “${USER}”@$host:etcd-ca.key
done
주의: 위 목록에서 필요한 인증서만 복사하세요. kubeadm은 제어 플레인 인스턴스 조인에 필요한 SAN을 사용하여 나머지 인증서 생성을 처리합니다. 모든 인증서를 실수로 복사하면 필수 SAN이 부족하여 추가 노드 생성이 실패할 수 있습니다.
조인 제어 플레인 노드에서 실행할 스크립트
각 조인 제어 플레인 노드에서 아래 스크립트를 실행하여 인증서를 이동시켜야 합니다.
USER=ubuntu # 사용자에 따라 변경 가능
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
외부 etcd를 사용하는 경우 다음 라인을 건너뛰세요
mv /home/${USER}/etcd-ca.key /etc/kubernetes/pki/etcd/ca.key
이제 각 제어 플레인 노드에서 위 스크립트를 실행하여 인증서를 수동으로 배포하고 클러스터를 설정할 수 있습니다.
결론
고가용성 Kubernetes 클러스터를 설정하려면 신중한 계획 및 구성이 필요합니다. 인프라 리소스와 환경에 따라 두 가지 다른 접근 방식 중 하나를 선택해야 합니다. 스택된 제어 평면 노드를 사용하면 인프라가 적게 필요하지만 etcd 멤버와 제어 평면 노드가 동일한 위치에 있습니다. 반면에 외부 etcd 클러스터를 사용하면 더 많은 인프라가 필요하지만 제어 평면 노드와 etcd 멤버가 분리됩니다.
클러스터를 설정하고 실행하는 데 성공하면 애플리케이션을 배포하고 관리하는 데 도움이 되는 kubectl을 설치하는 것이 좋습니다. 이를 통해 클러스터를 모니터링하고 트러블슈팅하는 데 도움이 됩니다.
마지막으로, 클러스터를 사용하기 전에 네트워크 플러그인(CNI)을 선택하고 적용해야 합니다. CNI는 클러스터 내에서 컨테이너 간 통신을 관리하며 적절한 플러그인을 선택하지 않으면 클러스터가 제대로 실행되지 않을 수 있습니다.
이러한 단계를 따르면 안정적이고 고가용성 있는 Kubernetes 클러스터를 설정할 수 있습니다. 클러스터를 유지 관리하려면 필요한 조치를 취하고 주기적으로 업그레이드하는 것이 중요합니다. 이를 통해 신뢰성 높은 컨테이너 오케스트레이션 환경을 구축할 수 있습니다.