이 섹션의 다중 페이지 출력 화면임. 여기를 클릭하여 프린트.

이 페이지의 일반 화면으로 돌아가기.

배포 도구로 쿠버네티스 설치하기

자체 프로덕션 쿠버네티스 클러스터를 설정하는 데는 다양한 방법과 도구가 있다. 예를 들면 다음과 같다.

  • kubeadm

  • 클러스터 API: 여러 쿠버네티스 클러스터의 프로비저닝, 업그레이드 및 운영을 단순화하는 선언적 API와 도구를 제공하는 데 중점을 둔 쿠버네티스 하위 프로젝트이다.

  • kops: 자동화된 클러스터 프로비저닝 도구이다. 튜토리얼, 모범 사례, 구성 옵션 및 커뮤니티 참여에 대한 정보는 kOps 웹사이트에서 자세히 확인할 수 있다.

  • kubespray: 일반적인 OS/쿠버네티스 클러스터 구성 관리 작업을 위한 Ansible 플레이북, 인벤토리, 프로비저닝 도구 및 도메인 지식의 조합이다. #kubespray 슬랙 채널에서 커뮤니티에 참여할 수 있다.

1 - kubeadm으로 클러스터 구성하기

1.1 - kubeadm 설치하기

이 페이지에서는 kubeadm 툴박스 설치 방법을 보여준다. 이 설치 프로세스를 수행한 후 kubeadm으로 클러스터를 만드는 방법에 대한 자세한 내용은 kubeadm으로 클러스터 생성하기 페이지를 참고한다.

시작하기 전에

  • 호환되는 리눅스 머신. 쿠버네티스 프로젝트는 데비안 기반 배포판, 레드햇 기반 배포판, 그리고 패키지 매니저를 사용하지 않는 경우에 대한 일반적인 가이드를 제공한다.
  • 2 GB 이상의 램을 장착한 머신. (이 보다 작으면 사용자의 앱을 위한 공간이 거의 남지 않음)
  • 2 이상의 CPU.
  • 클러스터의 모든 머신에 걸친 전체 네트워크 연결. (공용 또는 사설 네트워크면 괜찮음)
  • 모든 노드에 대해 고유한 호스트 이름, MAC 주소 및 product_uuid. 자세한 내용은 여기를 참고한다.
  • 컴퓨터의 특정 포트들 개방. 자세한 내용은 여기를 참고한다.
  • 스왑의 비활성화. kubelet이 제대로 작동하게 하려면 반드시 스왑을 사용하지 않도록 설정한다.

MAC 주소 및 product_uuid가 모든 노드에 대해 고유한지 확인

  • 사용자는 ip link 또는 ifconfig -a 명령을 사용하여 네트워크 인터페이스의 MAC 주소를 확인할 수 있다.
  • product_uuid는 sudo cat /sys/class/dmi/id/product_uuid 명령을 사용하여 확인할 수 있다.

일부 가상 머신은 동일한 값을 가질 수 있지만 하드웨어 장치는 고유한 주소를 가질 가능성이 높다. 쿠버네티스는 이러한 값을 사용하여 클러스터의 노드를 고유하게 식별한다. 이러한 값이 각 노드에 고유하지 않으면 설치 프로세스가 실패할 수 있다.

네트워크 어댑터 확인

네트워크 어댑터가 두 개 이상이고, 쿠버네티스 컴포넌트가 디폴트 라우트(default route)에서 도달할 수 없는 경우, 쿠버네티스 클러스터 주소가 적절한 어댑터를 통해 이동하도록 IP 경로를 추가하는 것이 좋다.

필수 포트 확인

필수 포트들은 쿠버네티스 컴포넌트들이 서로 통신하기 위해서 열려 있어야 한다. 다음과 같이 netcat과 같은 도구를 이용하여 포트가 열려 있는지 확인해 볼 수 있다.

nc 127.0.0.1 6443 -zv -w 2

사용자가 사용하는 파드 네트워크 플러그인은 특정 포트를 열어야 할 수도 있다. 이것은 각 파드 네트워크 플러그인마다 다르므로, 필요한 포트에 대한 플러그인 문서를 참고한다.

컨테이너 런타임 설치

파드에서 컨테이너를 실행하기 위해, 쿠버네티스는 컨테이너 런타임을 사용한다.

기본적으로, 쿠버네티스는 컨테이너 런타임 인터페이스(CRI)를 사용하여 사용자가 선택한 컨테이너 런타임과 인터페이스한다.

런타임을 지정하지 않으면, kubeadm은 잘 알려진 엔드포인트를 스캐닝하여 설치된 컨테이너 런타임을 자동으로 감지하려고 한다.

컨테이너 런타임이 여러 개 감지되거나 하나도 감지되지 않은 경우, kubeadm은 에러를 반환하고 사용자가 어떤 것을 사용할지를 명시하도록 요청할 것이다.

더 많은 정보는 컨테이너 런타임을 참고한다.

아래 표는 지원 운영 체제에 대한 알려진 엔드포인트를 담고 있다.

리눅스 컨테이너 런타임
런타임 유닉스 도메인 소켓 경로
containerd unix:///var/run/containerd/containerd.sock
CRI-O unix:///var/run/crio/crio.sock
도커 엔진 (cri-dockerd 사용) unix:///var/run/cri-dockerd.sock

윈도우 컨테이너 런타임
런타임 윈도우 네임드 파이프(named pipe) 경로
containerd npipe:////./pipe/containerd-containerd
도커 엔진 (cri-dockerd 사용) npipe:////./pipe/cri-dockerd

kubeadm, kubelet 및 kubectl 설치

모든 머신에 다음 패키지들을 설치한다.

  • kubeadm: 클러스터를 부트스트랩하는 명령이다.

  • kubelet: 클러스터의 모든 머신에서 실행되는 파드와 컨테이너 시작과 같은 작업을 수행하는 컴포넌트이다.

  • kubectl: 클러스터와 통신하기 위한 커맨드 라인 유틸리티이다.

kubeadm은 kubelet 또는 kubectl 을 설치하거나 관리하지 않으므로, kubeadm이 설치하려는 쿠버네티스 컨트롤 플레인의 버전과 일치하는지 확인해야 한다. 그렇지 않으면, 예상치 못한 버그 동작으로 이어질 수 있는 버전 차이(skew)가 발생할 위험이 있다. 그러나, kubelet과 컨트롤 플레인 사이에 하나의 마이너 버전 차이가 지원되지만, kubelet 버전은 API 서버 버전 보다 높을 수 없다. 예를 들어, 1.7.0 버전의 kubelet은 1.8.0 API 서버와 완전히 호환되어야 하지만, 그 반대의 경우는 아니다.

kubectl 설치에 대한 정보는 kubectl 설치 및 설정을 참고한다.

버전 차이에 대한 자세한 내용은 다음을 참고한다.

  1. apt 패키지 색인을 업데이트하고, 쿠버네티스 apt 리포지터리를 사용하는 데 필요한 패키지를 설치한다.

    sudo apt-get update
    sudo apt-get install -y apt-transport-https ca-certificates curl
    
  2. 구글 클라우드의 공개 사이닝 키를 다운로드 한다.

    sudo curl -fsSLo /etc/apt/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg
    
  3. 쿠버네티스 apt 리포지터리를 추가한다.

    echo "deb [signed-by=/etc/apt/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
    
  4. apt 패키지 색인을 업데이트하고, kubelet, kubeadm, kubectl을 설치하고 해당 버전을 고정한다.

    sudo apt-get update
    sudo apt-get install -y kubelet kubeadm kubectl
    sudo apt-mark hold kubelet kubeadm kubectl
    

cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-\$basearch
enabled=1
gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
exclude=kubelet kubeadm kubectl
EOF

# permissive 모드로 SELinux 설정(효과적으로 비활성화)
sudo setenforce 0
sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config

sudo yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes

sudo systemctl enable --now kubelet

참고:

  • setenforce 0sed ... 를 실행하여 permissive 모드로 SELinux를 설정하면 효과적으로 비활성화된다. 컨테이너가 호스트 파일시스템(예를 들어, 파드 네트워크에 필요한)에 접근하도록 허용하는 데 필요하다. kubelet에서 SELinux 지원이 개선될 때까지 이 작업을 수행해야 한다.

  • 구성 방법을 알고 있는 경우 SELinux를 활성화된 상태로 둘 수 있지만 kubeadm에서 지원하지 않는 설정이 필요할 수 있다.

  • 사용 중인 레드햇 배포판이 basearch를 해석하지 못하여 baseurl이 실패하면, \$basearch를 당신의 컴퓨터의 아키텍처로 치환한다. uname -m 명령을 실행하여 해당 값을 확인한다. 예를 들어, x86_64에 대한 baseurl URL은 https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64 이다.

CNI 플러그인 설치(대부분의 파드 네트워크에 필요)

CNI_PLUGINS_VERSION="v1.1.1"
ARCH="amd64"
DEST="/opt/cni/bin"
sudo mkdir -p "$DEST"
curl -L "https://github.com/containernetworking/plugins/releases/download/${CNI_PLUGINS_VERSION}/cni-plugins-linux-${ARCH}-${CNI_PLUGINS_VERSION}.tgz" | sudo tar -C "$DEST" -xz

명령어 파일을 다운로드할 디렉터리 정의

DOWNLOAD_DIR="/usr/local/bin"
sudo mkdir -p "$DOWNLOAD_DIR"

crictl 설치(kubeadm / Kubelet 컨테이너 런타임 인터페이스(CRI)에 필요)

CRICTL_VERSION="v1.25.0"
ARCH="amd64"
curl -L "https://github.com/kubernetes-sigs/cri-tools/releases/download/${CRICTL_VERSION}/crictl-${CRICTL_VERSION}-linux-${ARCH}.tar.gz" | sudo tar -C $DOWNLOAD_DIR -xz

kubeadm, kubelet, kubectl 설치 및 kubelet systemd 서비스 추가

RELEASE="$(curl -sSL https://dl.k8s.io/release/stable.txt)"
ARCH="amd64"
cd $DOWNLOAD_DIR
sudo curl -L --remote-name-all https://dl.k8s.io/release/${RELEASE}/bin/linux/${ARCH}/{kubeadm,kubelet,kubectl}
sudo chmod +x {kubeadm,kubelet,kubectl}

RELEASE_VERSION="v0.4.0"
curl -sSL "https://raw.githubusercontent.com/kubernetes/release/${RELEASE_VERSION}/cmd/kubepkg/templates/latest/deb/kubelet/lib/systemd/system/kubelet.service" | sed "s:/usr/bin:${DOWNLOAD_DIR}:g" | sudo tee /etc/systemd/system/kubelet.service
sudo mkdir -p /etc/systemd/system/kubelet.service.d
curl -sSL "https://raw.githubusercontent.com/kubernetes/release/${RELEASE_VERSION}/cmd/kubepkg/templates/latest/deb/kubeadm/10-kubeadm.conf" | sed "s:/usr/bin:${DOWNLOAD_DIR}:g" | sudo tee /etc/systemd/system/kubelet.service.d/10-kubeadm.conf

kubelet 활성화 및 시작

systemctl enable --now kubelet

kubelet은 이제 kubeadm이 수행할 작업을 알려 줄 때까지 크래시루프(crashloop) 상태로 기다려야 하므로 몇 초마다 다시 시작된다.

cgroup 드라이버 구성

컨테이너 런타임과 kubelet은 "cgroup 드라이버"라는 속성을 갖고 있으며, cgroup 드라이버는 리눅스 머신의 cgroup 관리 측면에 있어서 중요하다.

문제 해결

kubeadm에 문제가 있는 경우, 문제 해결 문서를 참고한다.

다음 내용

1.2 - kubeadm으로 클러스터 생성하기

kubeadm을 사용하면, 모범 사례를 준수하는 최소 작동 가능한 쿠버네티스 클러스터를 생성할 수 있다. 실제로 kubeadm을 사용하여 쿠버네티스 적합성 테스트를 통과하는 클러스터를 구성할 수 있다. kubeadm부트스트랩 토큰 및 클러스터 업그레이드와 같은 다른 클러스터 수명 주기 기능도 지원한다.

kubeadm 도구는 다음과 같은 경우에 적합하다.

  • 간단한 방법으로 쿠버네티스를 처음 시도해 보려는 경우
  • 기존 사용자가 클러스터 설정을 자동화하고 애플리케이션을 테스트하려는 경우
  • 더 큰 범위를 가진 다른 생태계 및/또는 설치 도구의 구성 요소로 사용하는 경우

노트북, 클라우드 서버 세트, 라즈베리 파이 등 다양한 머신에 kubeadm을 설치하여 사용할 수 있다. 클라우드 또는 온프레미스에 배포하든, kubeadm을 Ansible 또는 Terraform과 같은 프로비저닝 시스템에 통합할 수 있다.

시작하기 전에

이 가이드를 따르려면 다음이 필요하다.

  • deb/rpm 호환 리눅스 OS를 실행하는 하나 이상의 머신(예: 우분투 또는 CentOS)
  • 머신당 2GiB 이상의 RAM(이보다 적으면 앱을 위한 공간이 거의 남지 않음)
  • 컨트롤 플레인 노드로 사용하는 머신에 최소 2개의 CPU
  • 클러스터의 모든 머신 간 전체 네트워크 연결. 퍼블릭 또는 프라이빗 네트워크를 사용할 수 있다.

또한 새 클러스터에서 사용하려는 쿠버네티스 버전을 배포할 수 있는 kubeadm 버전을 사용해야 한다.

쿠버네티스 버전 및 버전 차이 지원 정책 이 쿠버네티스 전체와 마찬가지로 kubeadm에도 적용된다. 해당 정책을 확인하여 지원되는 쿠버네티스 및 kubeadm 버전을 알아보자. 이 페이지는 쿠버네티스 v1.34용으로 작성되었다.

kubeadm 도구의 전체 기능 상태는 일반 가용성(GA)이다. 일부 하위 기능은 아직 활발히 개발 중이다. 도구가 발전함에 따라 클러스터 생성 구현이 약간 변경될 수 있지만, 전체적인 구현은 꽤 안정적이어야 한다.

목표

  • 단일 컨트롤 플레인 쿠버네티스 클러스터 설치
  • 파드가 서로 통신할 수 있도록 클러스터에 파드 네트워크 설치

지침

호스트 준비

구성 요소 설치

모든 호스트에 컨테이너 런타임과 kubeadm을 설치한다. 자세한 지침과 기타 전제 조건은 kubeadm 설치하기를 참조한다.

네트워크 설정

kubeadm은 다른 쿠버네티스 구성 요소와 마찬가지로 호스트의 기본 게이트웨이와 연결된 네트워크 인터페이스에서 사용 가능한 IP를 찾으려고 시도한다. 그런 다음 이 IP는 구성 요소가 수행하는 광고 및/또는 수신에 사용된다.

리눅스 호스트에서 이 IP가 무엇인지 확인하려면 다음을 사용할 수 있다.

ip route show # "default via"로 시작하는 줄을 찾는다

쿠버네티스 구성 요소는 사용자 정의 네트워크 인터페이스를 옵션으로 허용하지 않으므로, 이러한 사용자 정의 구성이 필요한 모든 구성 요소 인스턴스에 사용자 정의 IP 주소를 플래그로 전달해야 한다.

initjoin 모두로 생성된 컨트롤 플레인 노드에 대한 API 서버 광고(advertise) 주소를 구성하려면 --apiserver-advertise-address 플래그를 사용할 수 있다. 선호하는 방법은 이 옵션을 kubeadm API에서 InitConfiguration.localAPIEndpointJoinConfiguration.controlPlane.localAPIEndpoint로 설정하는 것이다.

모든 노드의 kubelet의 경우, kubeadm 구성 파일(InitConfiguration 또는 JoinConfiguration)내의 .nodeRegistration.kubeletExtraArgs에서 --node-ip 옵션을 전달할 수 있다.

듀얼 스택의 경우 kubeadm을 사용한 듀얼 스택 지원을 참조한다.

컨트롤 플레인 구성 요소에 할당하는 IP 주소는 X.509 인증서의 주체 대체 이름 필드의 일부가 된다. 이러한 IP 주소를 변경하려면 새 인증서에 서명하고 영향을 받는 구성 요소를 재시작하여 인증서 파일의 변경 사항이 반영되도록 해야 한다. 이 주제에 대한 자세한 내용은 수동 인증서 갱신을 참조한다.

필요한 컨테이너 이미지 준비

이 단계는 선택 사항이며, 노드에서 인터넷 연결 없이 클러스터를 생성할 때 kubeadm initkubeadm joinregistry.k8s.io에 호스팅된 기본 컨테이너 이미지를 다운로드하지 않도록 하려는 경우에만 적용된다.

kubeadm에는 인터넷 연결 없이 클러스터를 생성할 때 필요한 이미지를 미리 가져오는 데 도움이 되는 명령이 있다. 자세한 내용은 인터넷 연결 없이 kubeadm 실행을 참조한다.

kubeadm을 사용하면 필요한 이미지에 대해 사용자 정의 이미지 저장소를 사용할 수 있다. 자세한 내용은 사용자 정의 이미지 사용을 참조한다.

컨트롤 플레인 노드 초기화

컨트롤 플레인 노드는 etcd (클러스터 데이터베이스) 및 API 서버 (kubectl 명령줄 도구가 통신하는)를 포함한 컨트롤 플레인 구성 요소가 실행되는 머신이다.

  1. (권장) 이 단일 컨트롤 플레인 kubeadm 클러스터를 고가용성으로 업그레이드할 계획이 있다면, 모든 컨트롤 플레인 노드에 대한 공유 엔드포인트를 설정하기 위해 --control-plane-endpoint를 지정해야 한다. 이러한 엔드포인트는 로드 밸런서의 DNS 이름 또는 IP 주소일 수 있다.
  2. 파드 네트워크 애드온(add-on)을 선택하고, kubeadm init에 전달해야 하는 인수가 있는지 확인한다. 선택한 서드파티 공급자에 따라 --pod-network-cidr을 공급자별 값으로 설정해야 할 수 있다. 파드 네트워크 애드온 설치를 참조한다.
  3. (선택 사항) kubeadm은 잘 알려진 엔드포인트 목록을 사용하여 컨테이너 런타임을 감지하려고 시도한다. 다른 컨테이너 런타임을 사용하거나 프로비저닝된 노드에 둘 이상이 설치된 경우 kubeadm--cri-socket 인수를 지정한다. 런타임 설치를 참조한다.

컨트롤 플레인 노드를 초기화하려면 다음을 실행한다.

kubeadm init <args>

apiserver-advertise-address 및 ControlPlaneEndpoint에 대한 고려 사항

--apiserver-advertise-address를 사용하여 이 특정 컨트롤 플레인 노드의 API 서버에 대한 광고 주소를 설정할 수 있지만, --control-plane-endpoint를 사용하여 모든 컨트롤 플레인 노드에 대한 공유 엔드포인트를 설정할 수 있다.

--control-plane-endpoint는 IP 주소와 IP 주소에 매핑할 수 있는 DNS 이름을 모두 허용한다. 이러한 매핑과 관련하여 가능한 솔루션을 평가하려면 네트워크 관리자에게 문의하는 것이 좋다.

다음은 매핑 예시이다.

192.168.0.102 cluster-endpoint

여기서 192.168.0.102는 이 노드의 IP 주소이고 cluster-endpoint는 이 IP에 매핑되는 사용자 정의 DNS 이름이다. 이를 통해 kubeadm init--control-plane-endpoint=cluster-endpoint를 전달하고 kubeadm join에 동일한 DNS 이름을 전달할 수 있다. 나중에 고가용성 시나리오에서 cluster-endpoint가 로드 밸런서 주소를 가리키도록 수정할 수 있다.

--control-plane-endpoint 없이 생성된 단일 컨트롤 플레인 클러스터를 고가용성 클러스터로 전환하는 것은 kubeadm에서 지원하지 않는다.

추가 정보

kubeadm init 인수에 대한 자세한 내용은 kubeadm 참조 가이드를 참조한다.

구성 파일로 kubeadm init을 구성하려면 구성 파일과 함께 kubeadm init 사용을 참조한다.

컨트롤 플레인 구성 요소 및 etcd 서버에 대한 활성(liveness) 프로브에 선택적 IPv6 할당을 포함하여 컨트롤 플레인 구성 요소를 사용자 정의하려면 사용자 정의 인수에 문서화된 대로 각 구성 요소에 추가 인수를 제공한다.

이미 생성된 클러스터를 재구성하려면 kubeadm 클러스터 재구성을 참조한다.

kubeadm init을 다시 실행하려면 먼저 클러스터를 해체해야 한다.

클러스터에 다른 아키텍처의 노드를 추가(join)하는 경우, 배포된 데몬셋이 이 아키텍처에 대한 컨테이너 이미지를 지원하는지 확인한다.

kubeadm init은 먼저 머신이 쿠버네티스를 실행할 준비가 되었는지 확인하기 위해 일련의 사전 검사를 실행한다. 이러한 사전 검사는 경고를 표시하고 오류가 발생하면 종료된다. 그런 다음 kubeadm init은 클러스터 컨트롤 플레인 구성 요소를 다운로드하고 설치한다. 이 작업은 몇 분 정도 걸릴 수 있다. 완료되면 다음이 표시된다.

Your Kubernetes control-plane has initialized successfully!

To start using your cluster, you need to run the following as a regular user:

  mkdir -p $HOME/.kube
  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  sudo chown $(id -u):$(id -g) $HOME/.kube/config

You should now deploy a Pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  /docs/concepts/cluster-administration/addons/

You can now join any number of machines by running the following on each node
as root:

  kubeadm join <control-plane-host>:<control-plane-port> --token <token> --discovery-token-ca-cert-hash sha256:<hash>

루트(root)가 아닌 사용자가 kubectl을 사용할 수 있도록 하려면 kubeadm init 출력의 일부이기도 한 다음 명령을 실행한다.

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

또는 root 사용자인 경우 다음을 실행할 수 있다.

export KUBECONFIG=/etc/kubernetes/admin.conf

kubeadm init이 출력하는 kubeadm join 명령을 기록해 둔다. 클러스터에 노드를 추가하려면 이 명령이 필요하다.

토큰은 컨트롤 플레인 노드와 추가되는 노드 간의 상호 인증에 사용된다. 여기에 포함된 토큰은 비밀(secret)이다. 이 토큰을 안전하게 보관한다. 이 토큰을 가진 사람은 누구나 클러스터에 인증된 노드를 추가할 수 있기 때문이다. 이러한 토큰은 kubeadm token 명령으로 나열, 생성 및 삭제할 수 있다. kubeadm 참조 가이드를 참조한다.

파드 네트워크 애드온 설치

여러 외부 프로젝트가 CNI를 사용하여 쿠버네티스 파드 네트워크를 제공하며, 그 중 일부는 네트워크 정책도 지원한다.

쿠버네티스 네트워킹 모델을 구현하는 애드온 목록을 참조한다.

쿠버네티스에서 지원하는 네트워킹 애드온의 전체 목록은 아니지만 애드온 설치 페이지를 참조한다. 컨트롤 플레인 노드 또는 kubeconfig 자격 증명이 있는 노드에서 다음 명령으로 파드 네트워크 애드온을 설치할 수 있다.

kubectl apply -f <add-on.yaml>

클러스터당 하나의 파드 네트워크만 설치할 수 있다.

파드 네트워크가 설치되면 kubectl get pods --all-namespaces 출력에서 CoreDNS 파드가 Running 상태인지 확인하여 작동하는지 확인할 수 있다. CoreDNS 파드가 실행 중이면 노드 추가를 계속할 수 있다.

네트워크가 작동하지 않거나 CoreDNS가 Running 상태가 아닌 경우 kubeadm에 대한 문제 해결 가이드를 확인한다.

관리되는 노드 레이블

기본적으로 kubeadm은 노드 등록 시 kubelet이 자체 적용할 수 있는 레이블을 제한하는 NodeRestriction 어드미션 컨트롤러를 활성화한다. 어드미션 컨트롤러 문서에서는 kubelet --node-labels 옵션과 함께 사용할 수 있는 레이블을 다룬다. node-role.kubernetes.io/control-plane 레이블은 이러한 제한된 레이블이며 kubeadm은 노드가 생성된 후 권한 있는 클라이언트를 사용하여 수동으로 적용한다. 수동으로 수행하려면 kubectl label을 사용하고 kubeadm이 관리하는 /etc/kubernetes/admin.conf와 같은 권한 있는 kubeconfig를 사용하는지 확인한다.

컨트롤 플레인 노드 격리

기본적으로 클러스터는 보안상의 이유로 컨트롤 플레인 노드에 파드를 스케줄하지 않는다. 예를 들어 단일 머신 쿠버네티스 클러스터의 경우 컨트롤 플레인 노드에 파드를 스케줄할 수 있도록 하려면 다음을 실행한다.

kubectl taint nodes --all node-role.kubernetes.io/control-plane-

출력은 다음과 같다.

node "test-01" untainted
...

이렇게 하면 컨트롤 플레인 노드를 포함하여 node-role.kubernetes.io/control-plane:NoSchedule 테인트(taint)가 있는 모든 노드에서 해당 테인트가 제거되어 스케줄러가 모든 곳에 파드를 스케줄할 수 있게 된다.

또한 다음 명령을 실행하여 컨트롤 플레인 노드에서 node.kubernetes.io/exclude-from-external-load-balancers 레이블을 제거할 수 있다. 이 레이블은 해당 노드를 백엔드 서버 목록에서 제외한다.

kubectl label nodes --all node.kubernetes.io/exclude-from-external-load-balancers-

더 많은 컨트롤 플레인 노드 추가

더 많은 컨트롤 플레인 노드를 추가하여 고가용성 kubeadm 클러스터를 생성하는 단계는 kubeadm으로 고가용성 클러스터 생성을 참조한다.

워커 노드 추가

워커 노드는 워크로드가 실행되는 곳이다.

다음 페이지에서는 kubeadm join 명령을 사용하여 클러스터에 리눅스 및 Windows 워커 노드를 추가하는 방법을 보여준다.

(선택 사항) 컨트롤 플레인 노드가 아닌 머신에서 클러스터 제어

다른 컴퓨터(예: 노트북)의 kubectl이 클러스터와 통신하도록 하려면 다음과 같이 컨트롤 플레인 노드에서 관리자 kubeconfig 파일을 워크스테이션으로 복사해야 한다.

scp root@<control-plane-host>:/etc/kubernetes/admin.conf .
kubectl --kubeconfig ./admin.conf get nodes

(선택 사항) API 서버를 localhost로 프록시

클러스터 외부에서 API 서버에 연결하려면 kubectl proxy를 사용할 수 있다.

scp root@<control-plane-host>:/etc/kubernetes/admin.conf .
kubectl --kubeconfig ./admin.conf proxy

이제 http://localhost:8001/api/v1에서 로컬로 API 서버에 액세스할 수 있다.

정리

테스트용으로 클러스터에 일회용 서버를 사용한 경우, 전원을 끄고 추가 정리를 수행하지 않을 수 있다. kubectl config delete-cluster를 사용하여 클러스터에 대한 로컬 참조를 삭제할 수 있다.

그러나 클러스터를 더 깔끔하게 프로비저닝 해제하려면 먼저 노드를 드레인(drain)하고 노드가 비어 있는지 확인한 다음 노드 구성을 해제해야 한다.

노드 제거

적절한 자격 증명으로 컨트롤 플레인 노드와 통신하여 다음을 실행한다.

kubectl drain <node name> --delete-emptydir-data --force --ignore-daemonsets

노드를 제거하기 전에 kubeadm이 설치한 상태를 재설정한다.

kubeadm reset

재설정 프로세스는 iptables 규칙이나 IPVS 테이블을 재설정하거나 정리하지 않는다. iptables를 재설정하려면 수동으로 수행해야 한다.

iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X

IPVS 테이블을 재설정하려면 다음 명령을 실행해야 한다.

ipvsadm -C

이제 노드를 제거한다.

kubectl delete node <node name>

다시 시작하려면 적절한 인수와 함께 kubeadm init 또는 kubeadm join을 실행한다.

컨트롤 플레인 정리

컨트롤 플레인 호스트에서 kubeadm reset을 사용하여 최선의 노력으로 정리를 트리거할 수 있다.

이 하위 명령 및 해당 옵션에 대한 자세한 내용은 kubeadm reset 참조 문서를 확인한다.

버전 차이 정책

kubeadm이 관리하는 일부 구성 요소에 대해 버전 차이를 허용하지만, kubeadm 버전을 컨트롤 플레인 구성 요소, kube-proxy 및 kubelet의 버전과 일치시키는 것이 좋다.

kubeadm과 쿠버네티스 버전 간의 차이

kubeadm은 kubeadm과 동일한 버전 또는 한 버전 이전의 쿠버네티스 구성 요소와 함께 사용할 수 있다. 쿠버네티스 버전은 kubeadm init--kubernetes-version 플래그 또는 --config 사용 시 ClusterConfiguration.kubernetesVersion 필드를 사용하여 kubeadm에 지정할 수 있다. 이 옵션은 kube-apiserver, kube-controller-manager, kube-scheduler 및 kube-proxy의 버전을 제어한다.

예시:

  • kubeadm이 1.34인 경우
  • kubernetesVersion은 1.34 또는 1.33이어야 한다

kubeadm과 kubelet 간의 차이

쿠버네티스 버전과 마찬가지로, kubeadm은 kubeadm과 동일한 버전 또는 세 버전 이전의 kubelet 버전과 함께 사용할 수 있다.

예시:

  • kubeadm이 1.34인 경우
  • 호스트의 kubelet은 1.34, 1.33, 1.32 또는 1.31이어야 한다

kubeadm 간의 차이

kubeadm 명령이 kubeadm이 관리하는 기존 노드 또는 전체 클러스터에서 작동할 수 있는 방법에는 특정 제한이 있다.

새 노드가 클러스터에 추가되는 경우, kubeadm join에 사용되는 kubeadm 바이너리는 kubeadm init으로 클러스터를 생성하거나 kubeadm upgrade로 동일한 노드를 업그레이드하는 데 사용된 kubeadm의 마지막 버전과 일치해야 한다. kubeadm upgrade를 제외한 나머지 kubeadm 명령에도 유사한 규칙이 적용된다.

kubeadm join 예시:

  • kubeadm 버전 1.34을 사용하여 kubeadm init으로 클러스터를 생성한 경우
  • 추가되는 노드는 1.34 버전의 kubeadm 바이너리를 사용해야 한다

업그레이드 중인 노드는 노드 관리에 사용된 kubeadm 버전과 동일한 MINOR 버전 또는 하나 높은 MINOR 버전의 kubeadm을 사용해야 한다.

kubeadm upgrade 예시:

  • kubeadm 버전 1.33을 사용하여 노드를 생성하거나 업그레이드한 경우
  • 노드 업그레이드에 사용되는 kubeadm 버전은 1.33 또는 1.34이어야 한다

다른 쿠버네티스 구성 요소 간의 버전 차이에 대해 자세히 알아보려면 버전 차이 정책을 참조한다.

제한사항

클러스터 복원력(resilience)

여기서 생성된 클러스터에는 단일 etcd 데이터베이스가 실행되는 단일 컨트롤 플레인 노드가 있다. 즉, 컨트롤 플레인 노드가 실패하면 클러스터가 데이터를 잃을 수 있으며 처음부터 다시 생성해야 할 수 있다.

해결 방법:

  • 정기적으로 etcd를 백업한다. kubeadm이 구성한 etcd 데이터 디렉터리는 컨트롤 플레인 노드의 /var/lib/etcd에 있다.

  • 여러 컨트롤 플레인 노드를 사용한다. 고가용성을 제공하는 클러스터 토폴로지를 선택하려면 고가용성 토폴로지 옵션을 읽을 수 있다.

플랫폼 호환성

kubeadm deb/rpm 패키지와 바이너리는 멀티 플랫폼 제안에 따라 amd64, arm(32비트), arm64, ppc64le 및 s390x용으로 빌드된다.

컨트롤 플레인 및 애드온용 멀티 플랫폼 컨테이너 이미지도 v1.12부터 지원된다.

일부 네트워크 공급자만 모든 플랫폼에 대한 솔루션을 제공한다. 공급자가 선택한 플랫폼을 지원하는지 확인하려면 위의 네트워크 공급자 목록이나 각 공급자의 문서를 참조한다.

문제 해결

kubeadm에 문제가 발생하면 문제 해결 문서를 참조한다.

다음 내용

피드백

1.3 - kubeadm API로 컴포넌트 사용자 정의하기

이 페이지는 kubeadm이 배포하는 컴포넌트(component)들을 사용자 정의하는 방법을 다룬다. 컨트롤 플레인 컴포넌트에 대해서는 Cluster Configuration 구조에서 플래그를 사용하거나 노드당 패치를 사용할 수 있다. kubelet과 kube-proxy의 경우, KubeletConfigurationKubeProxyConfiguration을 각각 사용할 수 있다.

이 모든 옵션이 kubeadm 구성 API를 통해 가용하다. 구성의 각 필드 상세 사항은 API 참조 페이지에서 찾아볼 수 있다.

ClusterConfiguration의 플래그로 컨트롤 플레인 사용자 정의하기

kubeadm의 ClusterConfiguration 오브젝트는 API 서버, 컨트롤러매니저, 스케줄러, Etcd와 같은 컨트롤 플레인 컴포넌트에 전달되는 기본 플래그를 사용자가 덮어쓸 수 있도록 노출한다. 이 컴포넌트는 다음 구조체를 사용하여 정의된다.

  • apiServer
  • controllerManager
  • scheduler
  • etcd

이 구조체들은 공통 필드인 extraArgs를 포함하며, 이 필드는 키: 값 쌍으로 구성된다. 컨트롤 플레인 컴포넌트를 위한 플래그를 덮어쓰려면 다음을 수행한다.

  1. 사용자 구성에 적절한 extraArgs 필드를 추가한다.
  2. extraArgs 필드에 플래그를 추가한다.
  3. kubeadm init--config <CONFIG YAML 파일> 파라미터를 추가해서 실행한다.

APIServer 플래그

자세한 내용은 kube-apiserver 레퍼런스 문서를 확인한다.

사용 예시:

apiVersion: kubeadm.k8s.io/v1beta3
kind: ClusterConfiguration
kubernetesVersion: v1.16.0
apiServer:
  extraArgs:
    anonymous-auth: "false"
    enable-admission-plugins: AlwaysPullImages,DefaultStorageClass
    audit-log-path: /home/johndoe/audit.log

컨트롤러매니저 플래그

자세한 내용은 kube-controller-manager 레퍼런스 문서를 확인한다.

사용 예시:

apiVersion: kubeadm.k8s.io/v1beta3
kind: ClusterConfiguration
kubernetesVersion: v1.16.0
controllerManager:
  extraArgs:
    cluster-signing-key-file: /home/johndoe/keys/ca.key
    deployment-controller-sync-period: "50"

스케줄러 플래그

자세한 내용은 kube-scheduler 레퍼런스 문서를 확인한다.

사용 예시:

apiVersion: kubeadm.k8s.io/v1beta3
kind: ClusterConfiguration
kubernetesVersion: v1.16.0
scheduler:
  extraArgs:
    config: /etc/kubernetes/scheduler-config.yaml
  extraVolumes:
    - name: schedulerconfig
      hostPath: /home/johndoe/schedconfig.yaml
      mountPath: /etc/kubernetes/scheduler-config.yaml
      readOnly: true
      pathType: "File"

Etcd 플래그

자세한 사항은 etcd 서버 문서를 확인한다.

사용 예시:

apiVersion: kubeadm.k8s.io/v1beta3
kind: ClusterConfiguration
etcd:
  local:
    extraArgs:
      election-timeout: 1000

패치를 통해 사용자 정의하기

기능 상태: Kubernetes v1.22 [beta]

Kubeadm을 사용하면 패치 파일이 있는 디렉토리를 개별 노드에 대한 InitConfigurationJoinConfiguration에 전달할 수 있다. 이 패치는 컴포넌트 구성이 디스크에 기록되기 전에 최종 사용자 정의 단계로 사용될 수 있다.

--config <YOUR CONFIG YAML>을 사용하여 이 파일을 kubeadm init에 전달할 수 있다.

apiVersion: kubeadm.k8s.io/v1beta3
kind: InitConfiguration
  patches:
    directory: /home/user/somedir

--config <YOUR CONFIG YAML>을 사용하여 이 파일을 kubeadm join에 전달할 수 있다.

apiVersion: kubeadm.k8s.io/v1beta3
kind: JoinConfiguration
  patches:
    directory: /home/user/somedir

디렉토리는 target[suffix][+patchtype].extension 형태의 파일을 포함해야 한다. 예를 들면, kube-apiserver0+merge.yaml 또는 단순히 etcd.json의 형태이다.

  • targetkube-apiserver, kube-controller-manager, kube-scheduler, etcd 그리고 kubeletconfiguration 중 하나가 될 수 있다.
  • patchtypestrategic, merge 그리고 json 중 하나가 될 수 있으며 kubectl에서 지원하는 패치 형식을 준수해야 한다. patchtype의 기본값은 strategic이다.
  • extensionjson 또는 yaml 중 하나여야 한다.
  • suffix는 어떤 패치가 먼저 적용되는지를 결정하는 데 사용할 수 있는 영숫자 형태의 선택적 문자열이다.

kubelet 사용자 정의하기

kubelet을 사용자 정의하려면, KubeletConfiguration을 동일한 구성 파일 내에서 ---로 구분된 ClusterConfiguration이나 InitConfiguration 다음에 추가하면 된다. 그런 다음 kubeadm init에 해당 파일을 전달하면, kubeadm은 동일한 기본 KubeletConfiguration을 클러스터의 모든 노드에 적용한다.

기본 KubeletConfiguration에 더하여 인스턴스별 구성을 적용하기 위해서는 kubeletconfiguration 패치 target을 이용할 수 있다.

다른 방법으로는, kubelet 플래그를 덮어쓰기(overrides)로 사용하여, InitConfigurationJoinConfiguration 모두에서 지원되는 nodeRegistration.kubeletExtraArgs에 전달할 수 있다. 일부 kubelet 플래그는 더 이상 사용되지 않는다(deprecated). 따라서 사용하기 전에 kubelet 참조 문서를 통해 상태를 확인해야 한다.

이 외 더 자세한 사항은 kubeadm을 통해 클러스터의 각 kubelet 구성하기에서 살펴본다.

kube-proxy 사용자 정의하기

kube-proxy를 사용자 정의하려면, KubeProxyConfiguration---로 구분된 ClusterConfiguration이나 InitConfiguration 다음에 두고 kubeadm init에 전달하면 된다.

자세한 사항은 API 참조 페이지에서 살펴볼 수 있다.

1.4 - 고가용성 토폴로지 선택

이 페이지는 고가용성(HA) 쿠버네티스 클러스터의 토플로지를 구성하는 두 가지 선택 사항을 설명한다.

다음과 같이 HA 클러스터를 구성할 수 있다.

  • etcd 노드와 컨트롤 플레인 노드를 함께 위치시키는 중첩된(stacked) 컨트롤 플레인 노드 방식
  • etcd와 컨트롤 플레인이 분리된 노드에서 운영되는 외부 etcd 노드 방식

HA 클러스터를 구성하기 전에 각 토플로지의 장단점을 주의 깊게 고려해야 한다.

중첩된 etcd 토플로지

중첩된 HA 클러스터는 etcd에서 제공하는 분산 데이터 저장소 클러스터를, 컨트롤 플레인 구성 요소를 실행하는 kubeadm으로 관리되는 노드에 의해서 형성된 클러스터 상단에 중첩하는 토플로지이다.

각 컨트롤 플레인 노드는 kube-apiserver, kube-scheduler, kube-controller-manager 인스턴스를 운영한다. kube-apiserver는 로드 밸런서를 이용하여 워커 노드에 노출되어 있다.

각 컨트롤 플레인 노드는 지역 etcd 맴버를 생성하고 이 etcd 맴버는 오직 해당 노드의 kube-apiserver와 통신한다. 비슷한 방식이 지역의 kube-controller-managerkube-scheduler에도 적용된다.

이 토플로지는 컨트롤 플레인과 etcd 맴버가 같은 노드에 묶여 있다. 이는 외부 etcd 노드의 클러스터를 구성하는 것보다는 단순하며 복제 관리도 간단하다.

그러나 중첩된 클러스터는 커플링에 실패할 위험이 있다. 한 노드가 다운되면 etcd 맴버와 컨트롤 플레인을 모두 잃어버리고, 중복성도 손상된다. 더 많은 컨트롤 플레인 노드를 추가하여 이 위험을 완화할 수 있다.

그러므로 HA 클러스터를 위해 최소 3개인 중첩된 컨트롤 플레인 노드를 운영해야 한다.

이는 kubeadm의 기본 토플로지이다. 지역 etcd 맴버는 kubeadm initkubeadm join --control-plane 을 이용할 때에 컨트롤 플레인 노드에 자동으로 생성된다.

중첩된 etcd 토플로지

외부 etcd 토플로지

외부 etcd를 이용하는 HA 클러스터는 etcd로 제공한 분산된 데이터 스토리지 클러스터가 컨트롤 플레인 구성 요소를 운영하는 노드로 형성하는 클러스터의 외부에 있는 토플로지이다.

중첩된 etcd 토플로지와 유사하게, 외부 etcd 토플로지에 각 컨트롤 플레인 노드는 kube-apiserver, kube-scheduler, kube-controller-manager의 인스턴스를 운영한다. 그리고 kube-apiserver는 로드 밸런서를 이용하여 워커노드에 노출한다. 그러나 etcd 맴버는 분리된 호스트에서 운영되고, 각 etcd 호스트는 각 컨트롤 플레인 노드의 kube-apiserver와 통신한다.

이 토플로지는 컨트롤 플레인과 etcd 맴버를 분리한다. 이는 그러므로 컨트롤 플레인 인스턴스나 etcd 맴버를 잃는 충격이 덜하고, 클러스터 중복성에 있어 중첩된 HA 토플로지만큼 영향을 미치지 않는다.

그러나, 이 토플로지는 중첩된 토플로지에 비해 호스트 개수가 두배나 필요하다. 이 토플로지로 HA 클러스터를 구성하기 위해서는 최소한 3개의 컨트롤 플레인과 3개의 etcd 노드가 필요하다.

외부 etcd 토플로지

다음 내용