프로덕션 환경

프로덕션 수준의 쿠버네티스 클러스터 생성

프로덕션 수준의 쿠버네티스 클러스터에는 계획과 준비가 필요하다. 쿠버네티스 클러스터에 중요한 워크로드를 실행하려면 클러스터를 탄력적이도록 구성해야 한다. 이 페이지에서는 프로덕션용 클러스터를 설정하거나 기존 클러스터를 프로덕션용으로 업그레이드하기 위해 수행할 수 있는 단계를 설명한다. 이미 프로덕션 구성 내용에 익숙하여 단지 링크를 찾고 있다면, 다음 내용을 참고한다.

프로덕션 고려 사항

일반적으로 프로덕션 쿠버네티스 클러스터 환경에는 개인 학습용, 개발용 또는 테스트 환경용 클러스터보다 더 많은 요구 사항이 있다. 프로덕션 환경에는 많은 사용자의 보안 액세스, 일관된 가용성 및 변화하는 요구를 충족하기 위한 리소스가 필요할 수 있다.

프로덕션 쿠버네티스 환경이 상주할 위치(온 프레미스 또는 클라우드)와 직접 처리하거나 다른 사람에게 맡길 관리의 양을 결정할 때, 쿠버네티스 클러스터에 대한 요구 사항이 다음 이슈에 의해 어떻게 영향을 받는지 고려해야 한다.

  • 가용성: 단일 머신 쿠버네티스 학습 환경은 SPOF(Single Point of Failure, 단일 장애 지점) 이슈를 갖고 있다. 고가용성 클러스터를 만드는 것에는 다음과 같은 고려 사항이 있다.

    • 컨트롤 플레인과 워크 노드를 분리
    • 컨트롤 플레인 구성요소를 여러 노드에 복제
    • 클러스터의 API 서버로 가는 트래픽을 로드밸런싱
    • 워커 노드를 충분히 운영하거나, 워크로드 변경에 따라 빠르게 제공할 수 있도록 보장
  • 스케일링: 프로덕션 쿠버네티스 환경에 들어오는 요청의 양의 일정할 것으로 예상된다면, 필요한 만큼의 용량(capacity)을 증설하고 마무리할 수도 있다. 하지만, 요청의 양이 시간에 따라 점점 증가하거나 계절, 이벤트 등에 의해 극적으로 변동할 것으로 예상된다면, 컨트롤 플레인과 워커 노드로의 요청 증가로 인한 압박을 해소하기 위해 스케일 업 하거나 잉여 자원을 줄이기 위해 스케일 다운 하는 것에 대해 고려해야 한다.

  • 보안 및 접근 관리: 학습을 위한 쿠버네티스 클러스터에는 완전한 관리 권한을 가질 수 있다. 하지만 중요한 워크로드를 실행하며 두 명 이상의 사용자가 있는 공유 클러스터에는 누가, 그리고 무엇이 클러스터 자원에 접근할 수 있는지에 대해서 보다 정교한 접근 방식이 필요하다. 역할 기반 접근 제어(RBAC) 및 기타 보안 메커니즘을 사용하여, 사용자와 워크로드가 필요한 자원에 액세스할 수 있게 하면서도 워크로드와 클러스터를 안전하게 유지할 수 있다. 정책컨테이너 리소스를 관리하여, 사용자 및 워크로드가 접근할 수 있는 자원에 대한 제한을 설정할 수 있다.

쿠버네티스 프로덕션 환경을 직접 구축하기 전에, 이 작업의 일부 또는 전체를 턴키 클라우드 솔루션 제공 업체 또는 기타 쿠버네티스 파트너에게 넘기는 것을 고려할 수 있다. 다음과 같은 옵션이 있다.

  • 서버리스: 클러스터를 전혀 관리하지 않고 타사 장비에서 워크로드를 실행하기만 하면 된다. CPU 사용량, 메모리 및 디스크 요청과 같은 항목에 대한 요금이 부과된다.
  • 관리형 컨트롤 플레인: 쿠버네티스 서비스 공급자가 클러스터 컨트롤 플레인의 확장 및 가용성을 관리하고 패치 및 업그레이드를 처리하도록 한다.
  • 관리형 워커 노드: 필요에 맞는 노드 풀을 정의하면, 쿠버네티스 서비스 공급자는 해당 노드의 가용성 및 필요 시 업그레이드 제공을 보장한다.
  • 통합: 쿠버네티스를 스토리지, 컨테이너 레지스트리, 인증 방법 및 개발 도구와 같이 사용자가 필요로 하는 여러 서비스를 통합 제공하는 업체도 있다.

프로덕션 쿠버네티스 클러스터를 직접 구축하든 파트너와 협력하든, 요구 사항이 컨트롤 플레인, 워커 노드, 사용자 접근, 워크로드 자원과 관련되기 때문에, 다음 섹션들을 검토하는 것이 바람직하다.

프로덕션 클러스터 구성

프로덕션 수준 쿠버네티스 클러스터에서, 컨트롤 플레인은 다양한 방식으로 여러 컴퓨터에 분산될 수 있는 서비스들을 통해 클러스터를 관리한다. 반면, 각 워커 노드는 쿠버네티스 파드를 실행하도록 구성된 단일 엔티티를 나타낸다.

프로덕션 컨트롤 플레인

가장 간단한 쿠버네티스 클러스터는 모든 컨트롤 플레인 및 워커 노드 서비스가 하나의 머신에 실행되는 클러스터이다. 쿠버네티스 컴포넌트 그림에 명시된 대로, 워커 노드를 추가하여 해당 환경을 확장할 수 있다. 클러스터를 단기간만 사용하거나, 심각한 문제가 발생한 경우 폐기하는 것이 가능하다면, 이 방식을 선택할 수 있다.

그러나 더 영구적이고 가용성이 높은 클러스터가 필요한 경우 컨트롤 플레인 확장을 고려해야 한다. 설계 상, 단일 시스템에서 실행되는 단일 시스템 컨트롤 플레인 서비스는 가용성이 높지 않다. 클러스터를 계속 유지하면서 문제가 발생한 경우 복구할 수 있는지 여부가 중요한 경우, 다음 사항들을 고려한다.

  • 배포 도구 선택: kubeadm, kops, kubespray와 같은 도구를 이용해 컨트롤 플레인을 배포할 수 있다. 배포 도구로 쿠버네티스 설치하기에서 여러 배포 도구를 이용한 프로덕션 수준 배포에 대한 팁을 확인한다. 배포 시, 다양한 컨테이너 런타임을 사용할 수 있다.
  • 인증서 관리: 컨트롤 플레인 서비스 간의 보안 통신은 인증서를 사용하여 구현된다. 인증서는 배포 중에 자동으로 생성되거나, 또는 자체 인증 기관을 사용하여 생성할 수 있다. PKI 인증서 및 요구 조건에서 상세 사항을 확인한다.
  • apiserver를 위한 로드밸런서 구성: 여러 노드에서 실행되는 apiserver 서비스 인스턴스에 외부 API 호출을 분산할 수 있도록 로드밸런서를 구성한다. 외부 로드밸런서 생성하기에서 상세 사항을 확인한다.
  • etcd 서비스 분리 및 백업: etcd 서비스는 다른 컨트롤 플레인 서비스와 동일한 시스템에서 실행되거나, 또는 추가 보안 및 가용성을 위해 별도의 시스템에서 실행될 수 있다. etcd는 클러스터 구성 데이터를 저장하므로 필요한 경우 해당 데이터베이스를 복구할 수 있도록 etcd 데이터베이스를 정기적으로 백업해야 한다. etcd FAQ에서 etcd 구성 및 사용 상세를 확인한다. 쿠버네티스를 위한 etcd 클러스터 운영하기kubeadm을 이용하여 고가용성 etcd 생성하기에서 상세 사항을 확인한다.
  • 다중 컨트롤 플레인 시스템 구성: 고가용성을 위해, 컨트롤 플레인은 단일 머신으로 제한되지 않아야 한다. 컨트롤 플레인 서비스가 init 서비스(예: systemd)에 의해 실행되는 경우, 각 서비스는 최소 3대의 머신에서 실행되어야 한다. 그러나, 컨트롤 플레인 서비스를 쿠버네티스 상의 파드 형태로 실행하면 각 서비스 복제본 요청이 보장된다. 스케줄러는 내결함성이 있어야 하고, 고가용성은 필요하지 않다. 일부 배포 도구는 쿠버네티스 서비스의 리더 선출을 수행하기 위해 Raft 합의 알고리즘을 설정한다. 리더를 맡은 서비스가 사라지면 다른 서비스가 스스로 리더가 되어 인계를 받는다.
  • 다중 영역(zone)으로 확장: 클러스터를 항상 사용 가능한 상태로 유지하는 것이 중요하다면 여러 데이터 센터(클라우드 환경에서는 '영역'이라고 함)에서 실행되는 클러스터를 만드는 것이 좋다. 영역의 그룹을 지역(region)이라고 한다. 동일한 지역의 여러 영역에 클러스터를 분산하면 하나의 영역을 사용할 수 없게 된 경우에도 클러스터가 계속 작동할 가능성을 높일 수 있다. 여러 영역에서 실행에서 상세 사항을 확인한다.
  • 구동 중인 기능 관리: 클러스터를 계속 유지하려면, 상태 및 보안을 유지하기 위해 수행해야 하는 작업이 있다. 예를 들어 kubeadm으로 클러스터를 생성한 경우, 인증서 관리kubeadm 클러스터 업그레이드하기에 대해 도움이 되는 가이드가 있다. 클러스터 운영하기에서 더 많은 쿠버네티스 관리 작업을 볼 수 있다.

컨트롤 플레인 서비스를 실행할 때 사용 가능한 옵션에 대해 보려면, kube-apiserver, kube-controller-manager, kube-scheduler를 참조한다. 고가용성 컨트롤 플레인 예제는 고가용성 토폴로지를 위한 옵션, kubeadm을 이용하여 고가용성 클러스터 생성하기, 쿠버네티스를 위한 etcd 클러스터 운영하기를 참조한다. etcd 백업 계획을 세우려면 etcd 클러스터 백업하기를 참고한다.

프로덕션 워커 노드

프로덕션 수준 워크로드는 복원력이 있어야 하고, 이들이 의존하는 모든 것들(예: CoreDNS)도 복원력이 있어야 한다. 컨트롤 플레인을 자체적으로 관리하든 클라우드 공급자가 대신 수행하도록 하든 상관없이, 워커 노드(간단히 노드라고도 함)를 어떤 방법으로 관리할지 고려해야 한다.

  • 노드 구성하기: 노드는 물리적 또는 가상 머신일 수 있다. 직접 노드를 만들고 관리하려면 지원되는 운영 체제를 설치한 다음 적절한 노드 서비스를 추가하고 실행한다. 다음을 고려해야 한다.
    • 워크로드의 요구 사항 (노드가 적절한 메모리, CPU, 디스크 속도, 저장 용량을 갖도록 구성)
    • 일반적인 컴퓨터 시스템이면 되는지, 아니면 GPU, 윈도우 노드, 또는 VM 격리를 필요로 하는 워크로드가 있는지
  • 노드 검증하기: 노드 구성 검증하기에서 노드가 쿠버네티스 클러스터에 조인(join)에 필요한 요구 사항을 만족하는지 확인하는 방법을 알아본다.
  • 클러스터에 노드 추가하기: 클러스터를 자체적으로 관리하는 경우, 머신을 준비하고, 클러스터의 apiserver에 이를 수동으로 추가하거나 또는 머신이 스스로 등록하도록 하여 노드를 추가할 수 있다. 이러한 방식으로 노드를 추가하는 방법을 보려면 노드 섹션을 확인한다.
  • 노드 스케일링: 클러스터가 최종적으로 필요로 하게 될 용량만큼 확장하는 것에 대한 계획이 있어야 한다. 실행해야 하는 파드 및 컨테이너 수에 따라 필요한 노드 수를 판별하려면 대형 클러스터에 대한 고려 사항을 확인한다. 만약 노드를 직접 관리한다면, 직접 물리적 장비를 구입하고 설치해야 할 수도 있음을 의미한다.
  • 노드 자동 스케일링: 대부분의 클라우드 공급자는 비정상 노드를 교체하거나 수요에 따라 노드 수를 늘리거나 줄일 수 있도록 클러스터 오토스케일러를 지원한다. 자주 묻는 질문에서 오토스케일러가 어떻게 동작하는지, 배치 섹션에서 각 클라우드 공급자별로 어떻게 구현했는지를 확인한다. 온프레미스의 경우, 필요에 따라 새 노드를 가동하도록 스크립트를 구성할 수 있는 가상화 플랫폼이 있다.
  • 노드 헬스 체크 구성: 중요한 워크로드의 경우, 해당 노드에서 실행 중인 노드와 파드의 상태가 정상인지 확인하고 싶을 것이다. Node Problem Detector 데몬을 사용하면 노드가 정상인지 확인할 수 있다.

프로덕션 사용자 관리

프로덕션에서는, 클러스터를 한 명 또는 여러 명이 사용하던 모델에서 수십에서 수백 명이 사용하는 모델로 바꿔야 하는 경우가 발생할 수 있다. 학습 환경 또는 플랫폼 프로토타입에서는 모든 작업에 대한 단일 관리 계정으로도 충분할 수 있다. 프로덕션에서는 여러 네임스페이스에 대한, 액세스 수준이 각각 다른 더 많은 계정이 필요하다.

프로덕션 수준의 클러스터를 사용한다는 것은 다른 사용자의 액세스를 선택적으로 허용할 방법을 결정하는 것을 의미한다. 특히 클러스터에 액세스를 시도하는 사용자의 신원을 확인(인증, authentication)하고 요청한 작업을 수행할 권한이 있는지 결정(인가, authorization)하기 위한 다음과 같은 전략을 선택해야 한다.

  • 인증: apiserver는 클라이언트 인증서, 전달자 토큰, 인증 프록시 또는 HTTP 기본 인증을 사용하여 사용자를 인증할 수 있다. 사용자는 인증 방법을 선택하여 사용할 수 있다. apiserver는 또한 플러그인을 사용하여 LDAP 또는 Kerberos와 같은 조직의 기존 인증 방법을 활용할 수 있다. 쿠버네티스 사용자를 인증하는 다양한 방법에 대한 설명은 인증을 참조한다.
  • 인가: 일반 사용자 인가를 위해, RBAC 와 ABAC 중 하나를 선택하여 사용할 수 있다. 인가 개요에서 사용자 계정과 서비스 어카운트 인가를 위한 여러 가지 모드를 확인할 수 있다.
    • 역할 기반 접근 제어 (RBAC): 인증된 사용자에게 특정 권한 집합을 허용하여 클러스터에 대한 액세스를 할당할 수 있다. 특정 네임스페이스(Role) 또는 전체 클러스터(ClusterRole)에 권한을 할당할 수 있다. 그 뒤에 RoleBindings 및 ClusterRoleBindings를 사용하여 해당 권한을 특정 사용자에게 연결할 수 있다.
    • 속성 기반 접근 제어 (ABAC): 클러스터의 리소스 속성을 기반으로 정책을 생성하고 이러한 속성을 기반으로 액세스를 허용하거나 거부할 수 있다. 정책 파일의 각 줄은 버전 관리 속성(apiVersion 및 종류), 그리고 '대상(사용자 또는 그룹)', '리소스 속성', '비 리소스 속성(/version 또는 /apis)' 및 '읽기 전용'과 일치하는 사양 속성 맵을 식별한다. 자세한 내용은 예시를 참조한다.

프로덕션 쿠버네티스 클러스터에 인증과 인가를 설정할 때, 다음의 사항을 고려해야 한다.

  • 인가 모드 설정: 쿠버네티스 API 서버 (kube-apiserver)를 실행할 때, --authorization-mode 플래그를 사용하여 인증 모드를 설정해야 한다. 예를 들어, kube-adminserver.yaml 파일(*/etc/kubernetes/manifests*에 있는) 안의 플래그를 Node,RBAC으로 설정할 수 있다. 이렇게 하여 인증된 요청이 Node 인가와 RBAC 인가를 사용할 수 있게 된다.
  • 사용자 인증서와 롤 바인딩 생성(RBAC을 사용하는 경우): RBAC 인증을 사용하는 경우, 사용자는 클러스터 CA가 서명한 CSR(CertificateSigningRequest)을 만들 수 있다. 그 뒤에 각 사용자에게 역할 및 ClusterRoles를 바인딩할 수 있다. 자세한 내용은 인증서 서명 요청을 참조한다.
  • 속성을 포함하는 정책 생성(ABAC을 사용하는 경우): ABAC 인증을 사용하는 경우, 속성의 집합으로 정책을 생성하여, 인증된 사용자 또는 그룹이 특정 리소스(예: 파드), 네임스페이스, 또는 apiGroup에 접근할 수 있도록 한다. 예시에서 더 많은 정보를 확인한다.
  • 어드미션 컨트롤러 도입 고려: 웹훅 토큰 인증은 API 서버를 통해 들어오는 요청의 인가에 사용할 수 있는 추가적인 방법이다. 웹훅 및 다른 인가 형식을 사용하려면 API 서버에 어드미션 컨트롤러를 추가해야 한다.

워크로드에 자원 제한 걸기

프로덕션 워크로드의 요구 사항이 쿠버네티스 컨트롤 플레인 안팎의 압박을 초래할 수 있다. 워크로드의 요구 사항을 충족하도록 클러스터를 구성할 때 다음 항목을 고려한다.

  • 네임스페이스 제한 설정: 메모리, CPU와 같은 자원의 네임스페이스 별 쿼터를 설정한다. 메모리, CPU 와 API 리소스 관리에서 상세 사항을 확인한다. 계층적 네임스페이스를 설정하여 제한을 상속할 수도 있다.
  • DNS 요청에 대한 대비: 워크로드가 대규모로 확장될 것으로 예상된다면, DNS 서비스도 확장할 준비가 되어 있어야 한다. 클러스터의 DNS 서비스 오토스케일링을 확인한다.
  • 추가적인 서비스 어카운트 생성: 사용자 계정은 클러스터에서 사용자가 무엇을 할 수 있는지 결정하는 반면에, 서비스 어카운트는 특정 네임스페이스 내의 파드 접근 권한을 결정한다. 기본적으로, 파드는 자신의 네임스페이스의 기본 서비스 어카운트을 이용한다. 서비스 어카운트 관리하기에서 새로운 서비스 어카운트을 생성하는 방법을 확인한다. 예를 들어, 다음의 작업을 할 수 있다.

다음 내용

1 - 컨테이너 런타임

파드가 노드에서 실행될 수 있도록 클러스터의 각 노드에 컨테이너 런타임을 설치해야 한다. 이 페이지에서는 관련된 항목을 설명하고 노드 설정 관련 작업을 설명한다.

쿠버네티스 1.32에서는 컨테이너 런타임 인터페이스(CRI) 요구사항을 만족하는 런타임을 사용해야 한다.

더 자세한 정보는 CRI 버전 지원을 참조한다.

이 페이지는 쿠버네티스에서 여러 공통 컨테이너 런타임을 사용하는 방법에 대한 개요를 제공한다.

필수 요소들 설치 및 구성하기

다음 단계에서는 리눅스의 쿠버네티스 노드를 위한 일반적인 설정들을 적용한다.

만약 필요하지 않다고 생각한다면 몇몇 설정들은 넘어가도 무방하다.

더 자세한 정보는, 네트워크 플러그인 요구사항이나 각자 사용 중인 컨테이너 런타임에 해당하는 문서를 확인한다.

IPv4를 포워딩하여 iptables가 브리지된 트래픽을 보게 하기

lsmod | grep br_netfilter를 실행하여 br_netfilter 모듈이 로드되었는지 확인한다.

명시적으로 로드하려면, sudo modprobe br_netfilter를 실행한다.

리눅스 노드의 iptables가 브리지된 트래픽을 올바르게 보기 위한 요구 사항으로, sysctl 구성에서 net.bridge.bridge-nf-call-iptables가 1로 설정되어 있는지 확인한다. 예를 들어,

cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF

sudo modprobe overlay
sudo modprobe br_netfilter

# 필요한 sysctl 파라미터를 설정하면, 재부팅 후에도 값이 유지된다.
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables  = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward                 = 1
EOF

# 재부팅하지 않고 sysctl 파라미터 적용하기
sudo sysctl --system

cgroup 드라이버

리눅스에서, control group은 프로세스에 할당된 리소스를 제한하는데 사용된다.

kubelet과 그에 연계된 컨테이너 런타임 모두 컨트롤 그룹(control group)들과 상호작용 해야 하는데, 이는 파드 및 컨테이너 자원 관리가 수정될 수 있도록 하고 cpu 혹은 메모리와 같은 자원의 요청(request)과 상한(limit)을 설정하기 위함이다. 컨트롤 그룹과 상호작용하기 위해서는, kubelet과 컨테이너 런타임이 cgroup 드라이버를 사용해야 한다. 매우 중요한 점은, kubelet과 컨테이너 런타임이 같은 cgroup group 드라이버를 사용해야 하며 구성도 동일해야 한다는 것이다.

두 가지의 cgroup 드라이버가 이용 가능하다.

cgroupfs 드라이버

cgroupfs 드라이버는 kubelet의 기본 cgroup 드라이버이다. cgroupfs 드라이버가 사용될 때, kubelet과 컨테이너 런타임은 직접적으로 cgroup 파일시스템과 상호작용하여 cgroup들을 설정한다.

cgroupfs 드라이버가 권장되지 않는 때가 있는데, systemd가 init 시스템인 경우이다. 이것은 systemd가 시스템에 단 하나의 cgroup 관리자만 있을 것으로 기대하기 때문이다. 또한, cgroup v2를 사용할 경우에도 cgroupfs 대신 systemd cgroup 드라이버를 사용한다.

systemd cgroup 드라이버

리눅스 배포판의 init 시스템이 systemd인 경우, init 프로세스는 root control group(cgroup)을 생성 및 사용하는 cgroup 관리자로 작동한다.

systemd는 cgroup과 긴밀하게 통합되어 있으며 매 systemd 단위로 cgroup을 할당한다. 결과적으로, systemd를 init 시스템으로 사용하고 cgroupfs 드라이버를 사용하면, 그 시스템은 두 개의 다른 cgroup 관리자를 갖게 된다.

두 개의 cgroup 관리자는 시스템 상 사용 가능한 자원과 사용 중인 자원들에 대하여 두 가지 관점을 가져 혼동을 초래한다. 예를 들어, kubelet과 컨테이너 런타임은 cgroupfs를 사용하고 나머지 프로세스는 systemd를 사용하도록 노드를 구성한 경우, 노드가 자원 압박으로 인해 불안정해질 수 있다.

이러한 불안정성을 줄이는 방법은, systemd가 init 시스템으로 선택되었을 때에는 systemd를 kubelet과 컨테이너 런타임의 cgroup 드라이버로 사용하는 것이다.

systemd를 cgroup 드라이버로 사용하기 위해서는, KubeletConfiguration를 수정하여 cgroupDriver 옵션을 systemd로 지정하는 것이다. 예를 들면 다음과 같다.

apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
...
cgroupDriver: systemd

systemd를 kubelet의 cgroup 드라이버로 구성했다면, 반드시 컨테이너 런타임의 cgroup 드라이버 또한 systemd로 설정해야 한다. 자세한 설명은 컨테이너 런타임 대한 문서를 참조한다. 예를 들면 다음과 같다.

kubeadm으로 생성한 클러스터의 드라이버를 systemd로 변경하기

기존에 kubeadm으로 생성한 클러스터의 cgroup 드라이버를 systemd로 변경하려면, cgroup 드라이버 설정하기를 참고한다.

CRI 버전 지원

사용할 컨테이너 런타임이 적어도 CRI의 v1alpha2 이상을 지원해야 한다.

쿠버네티스 1.32 버전에서는 기본적으로 CRI API 중 v1을 사용한다. 컨테이너 런타임이 v1 API를 지원하지 않으면, kubelet은 대신 (사용 중단된) v1alpha2 API를 사용하도록 설정된다.

컨테이너 런타임

containerd

이 섹션에는 containerd를 CRI 런타임으로 사용하는 데 필요한 단계를 간략하게 설명한다.

다음 명령을 사용하여 시스템에 containerd를 설치한다.

containerd 시작하기의 지침에 따라, 유효한 환경 설정 파일(config.toml)을 생성한다.

/etc/containerd/config.toml 경로에서 파일을 찾을 수 있음.

`C:\Program Files\containerd\config.toml` 경로에서 파일을 찾을 수 있음.

리눅스에서, containerd를 위한 기본 CRI 소켓은 /run/containerd/containerd.sock이다. 윈도우에서, 기본 CRI 엔드포인트는 npipe://./pipe/containerd-containerd이다.

systemd cgroup 드라이버 환경 설정하기

/etc/containerd/config.tomlsystemd cgroup 드라이버를 runc 에서 사용하려면, 다음과 같이 설정한다.

[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
  ...
  [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
    SystemdCgroup = true

cgroup v2을 사용할 경우 systemd cgroup 드라이버가 권장된다.

이 변경 사항을 적용하려면, containerd를 재시작한다.

sudo systemctl restart containerd

kubeadm을 사용하는 경우, kubelet용 cgroup driver를 수동으로 구성한다.

샌드박스(pause) 이미지 덮어쓰기

containerd 설정에서 아래와 같이 샌드박스 이미지를 덮어쓸 수 있다.

[plugins."io.containerd.grpc.v1.cri"]
  sandbox_image = "registry.k8s.io/pause:3.2"

설정 파일을 변경하는 경우 역시 systemctl restart containerd를 통해 containerd를 재시작해야 한다.

CRI-O

이 섹션은 CRI-O를 컨테이너 런타임으로 설치하는 필수적인 단계를 담고 있다.

CRI-O를 설치하려면, CRI-O 설치 방법을 따른다.

cgroup 드라이버

CRI-O는 기본적으로 systemd cgroup 드라이버를 사용하며, 이는 대부분의 경우에 잘 동작할 것이다. cgroupfs cgroup 드라이버로 전환하려면, /etc/crio/crio.conf 를 수정하거나 /etc/crio/crio.conf.d/02-cgroup-manager.conf 에 드롭-인(drop-in) 구성을 배치한다. 예를 들면 다음과 같다.

[crio.runtime]
conmon_cgroup = "pod"
cgroup_manager = "cgroupfs"

또한 cgroupfs 와 함께 CRI-O를 사용할 때 pod 값으로 설정해야 하는 변경된 conmon_cgroup 에 유의해야 한다. 일반적으로 kubelet(일반적으로 kubeadm을 통해 수행됨)과 CRI-O의 cgroup 드라이버 구성을 동기화 상태로 유지해야 한다.

CRI-O의 경우, CRI 소켓은 기본적으로 /var/run/crio/crio.sock이다.

샌드박스(pause) 이미지 덮어쓰기

CRI-O 설정에서 아래와 같이 샌드박스 이미지를 덮어쓸 수 있다.

[crio.image]
pause_image="registry.k8s.io/pause:3.6"

이 옵션은 systemctl reload crio 혹은 crio 프로세스에 SIGHUP을 보내 변경사항을 적용하기 위한 live configuration reload 기능을 지원한다.

도커 엔진

  1. 각 노드에서, 도커 엔진 설치하기에 따라 리눅스 배포판에 맞게 도커를 설치한다.

  2. cri-dockerd 소스 코드 저장소의 지침대로 cri-dockerd를 설치한다.

cri-dockerd의 경우, CRI 소켓은 기본적으로 /run/cri-dockerd.sock이다.

미란티스 컨테이너 런타임

미란티스 컨테이너 런타임(MCR)은 상용 컨테이너 런타임이며 이전에는 도커 엔터프라이즈 에디션으로 알려져 있었다.

오픈소스인 cri-dockerd 컴포넌트를 이용하여 쿠버네티스에서 미란티스 컨테이너 런타임을 사용할 수 있으며, 이 컴포넌트는 MCR에 포함되어 있다.

미란티스 컨테이너 런타임을 설치하는 방법에 대해 더 알아보려면, MCR 배포 가이드를 참고한다.

CRI 소켓의 경로를 찾으려면 cri-docker.socket라는 이름의 systemd 유닛을 확인한다.

샌드박스(pause) 이미지 덮어쓰기

cri-dockerd 어댑터는, 파드 인프라 컨테이너("pause image")를 위해 어떤 컨테이너 이미지를 사용할지 명시하는 커맨드라인 인자를 받는다. 해당 커맨드라인 인자는 --pod-infra-container-image이다.

다음 내용

컨테이너 런타임과 더불어, 클러스터에는 동작하는 네트워크 플러그인도 필요하다.

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

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

2.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 -v

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

컨테이너 런타임 설치

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

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

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

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

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

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

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

윈도우 컨테이너 런타임
런타임윈도우 네임드 파이프(named pipe) 경로
containerdnpipe:////./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에 문제가 있는 경우, 문제 해결 문서를 참고한다.

다음 내용

2.1.2 - 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 참조 페이지에서 살펴볼 수 있다.

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

이 페이지는 고가용성(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 토플로지

다음 내용

2.2 - kOps로 쿠버네티스 설치하기

이곳 빠른 시작에서는 사용자가 얼마나 쉽게 AWS에 쿠버네티스 클러스터를 설치할 수 있는지 보여준다. kOps라는 이름의 툴을 이용할 것이다.

kOps는 자동화된 프로비저닝 시스템인데,

  • 완전 자동화된 설치
  • DNS를 통해 클러스터들의 신원 확인
  • 자체 복구: 모든 자원이 Auto-Scaling Groups에서 실행
  • 다양한 OS 지원(Amazon Linux, Debian, Flatcar, RHEL, Rocky and Ubuntu) - images.md 보기
  • 고가용성 지원 - high_availability.md 보기
  • 직접 프로비저닝 하거나 또는 할 수 있도록 terraform 매니페스트를 생성 - terraform.md 보기

시작하기 전에

클러스터 구축

(1/5) kops 설치

설치

releases page에서 kops를 다운로드한다(소스 코드로부터 빌드하는 것도 역시 편리하다).

최신 버전의 릴리스를 다운받는 명령어:

curl -LO https://github.com/kubernetes/kops/releases/download/$(curl -s https://api.github.com/repos/kubernetes/kops/releases/latest
| grep tag_name | cut -d '"' -f 4)/kops-darwin-amd64

특정 버전을 다운로드 받는다면 명령의 다음 부분을 특정 kops 버전으로 변경한다.

$(curl -s https://api.github.com/repos/kubernetes/kops/releases/latest | grep tag_name | cut -d '"' -f 4)

예를 들어 kops 버전을 v1.20.0을 다운로드 하려면 다음을 입력한다.

curl -LO https://github.com/kubernetes/kops/releases/download/v1.20.0/kops-darwin-amd64

kops 바이너리를 실행 가능하게 만든다.

chmod +x kops-darwin-amd64

kops 바이너리를 사용자의 PATH로 이동한다.

sudo mv kops-darwin-amd64 /usr/local/bin/kops

사용자는 Homebrew를 이용해서 kops를 설치할 수 있다.

brew update && brew install kops

최신 릴리스를 다운로드 받는 명령어:

curl -LO https://github.com/kubernetes/kops/releases/download/$(curl -s https://api.github.com/repos/kubernetes/kops/releases/latest | grep tag_name | cut -d '"' -f 4)/kops-linux-amd64

특정 버전의 kops를 다운로드하려면 명령의 다음 부분을 특정 kops 버전으로 변경한다.

$(curl -s https://api.github.com/repos/kubernetes/kops/releases/latest | grep tag_name | cut -d '"' -f 4)

예를 들어 kops 버전을 v1.20.0을 다운로드 하려면 다음을 입력한다.

curl -LO https://github.com/kubernetes/kops/releases/download/v1.20.0/kops-linux-amd64

kops 바이너리를 실행 가능하게 만든다.

chmod +x kops-linux-amd64

kops 바이너리를 사용자의 PATH로 이동한다.

sudo mv kops-linux-amd64 /usr/local/bin/kops

사용자는 Homebrew를 이용해서 kops를 설치할 수 있다.

brew update && brew install kops

(2/5) 클러스터에 사용할 route53 domain 생성

kops는 클러스터 내부와 외부 모두에서 검색을 위해 DNS을 사용하기에 클라이언트에서 쿠버네티스 API 서버에 연결할 수 있다.

이런 클러스터 이름에 kops는 명확한 견해을 가지는데: 반드시 유효한 DNS 이름이어야 한다. 이렇게 함으로써 사용자는 클러스터를 헷갈리지 않을것이고, 동료들과 혼선없이 공유할 수 있으며, IP를 기억할 필요없이 접근할 수 있다.

그렇게 하고 있겠지만, 클러스터를 구분하기 위해 서브도메인을 활용할 수 있다. 예를 들어 useast1.dev.example.com을 이용한다면, API 서버 엔드포인트는 api.useast1.dev.example.com가 될 것이다.

Route53 hosted zone은 서브도메인도 지원한다. 여러분의 hosted zone은 useast1.dev.example.com, dev.example.com 그리고 example.com 같은 것도 될 수 있다. kops는 이것들 모두와 잘 동작하며, 사용자는 보통 조직적인 부분을 고려해 결정한다(예를 들어, 사용자가 dev.example.com하위에 레코드를 생성하는것은 허용되지만, example.com하위에는 그렇지 않을 수 있다).

dev.example.com을 hosted zone으로 사용하고 있다고 가정해보자. 보통 사용자는 일반적인 방법 에 따라 생성하거나 aws route53 create-hosted-zone --name dev.example.com --caller-reference 1 와 같은 커맨드를 이용한다.

그 후 도메인 내 레코드들을 확인할 수 있도록 상위 도메인내에 NS 레코드를 생성해야 한다. 여기서는, dev NS 레코드를 example.com에 생성한다. 만약 이것이 루트 도메인 네임이라면 이 NS 레코드들은 도메인 등록기관을 통해서 생성해야 한다(예를 들어, example.comexample.com를 구매한 곳에서 설정 할 수 있다).

route53 도메인 설정을 확인한다(문제를 만드는 가장 큰 이유이다!). dig 툴을 실행해서 클러스터 설정이 정확한지 한번 더 확인한다.

dig NS dev.example.com

당신의 hosted zone용으로 할당된 3~4개의 NS 레코드를 Route53에서 확인할 수 있어야 한다.

(3/5) 클러스터 상태 저장용 S3 버킷 생성

kops는 설치 이후에도 클러스터를 관리할 수 있다. 이를 위해 사용자가 생성한 클러스터의 상태나 사용하는 키 정보들을 지속적으로 추적해야 한다. 이 정보가 S3에 저장된다. 이 버킷의 접근은 S3 권한으로 제어한다.

다수의 클러스터는 동일한 S3 버킷을 이용할 수 있고, 사용자는 이 S3 버킷을 같은 클러스트를 운영하는 동료에게 공유할 수 있다. 하지만 이 S3 버킷에 접근 가능한 사람은 사용자의 모든 클러스터에 관리자 접근이 가능하게 되니, 운영팀 이외로 공유되지 않도록 해야 한다.

그래서 보통 한 운영팀 당 하나의 S3 버킷을 가지도록 하기도 한다.(그리고 종종 운영팀 이름은 위에서 언급한 hosted zone과 동일하게 짓기도 한다!)

우리 예제에서는, dev.example.com를 hosted zone으로 했으니 clusters.dev.example.com를 S3 버킷 이름으로 정하자.

  • AWS_PROFILE를 선언한다. (AWS CLI 동작을 위해 다른 profile을 선택해야 할 경우)

  • aws s3 mb s3://clusters.dev.example.com를 이용해 S3 버킷을 생성한다.

  • export KOPS_STATE_STORE=s3://clusters.dev.example.com 하면, kops는 이 위치를 기본값으로 인식할 것이다. 이 부분을 bash profile등에 넣어두는것을 권장한다.

(4/5) 클러스터 설정 구성

클러스터 설정하려면, kops create cluster 를 실행한다:

kops create cluster --zones=us-east-1c useast1.dev.example.com

kops는 클러스터에 사용될 설정을 생성할것이다. 여기서 주의할 점은 실제 클러스트 리소스가 아닌 설정 만을 생성한다는 것에 주의하자 - 이 부분은 다음 단계에서 kops update cluster 으로 구성해볼 것이다. 그 때 만들어진 설정을 점검하거나 변경할 수 있다.

더 자세한 내용을 알아보기 위한 커맨드가 출력된다.

  • 클러스터 조회: kops get cluster
  • 클러스트 수정: kops edit cluster useast1.dev.example.com
  • 인스턴스 그룹 수정: kops edit ig --name=useast1.dev.example.com nodes
  • 마스터 인스턴스 그룹 수정: kops edit ig --name=useast1.dev.example.com master-us-east-1c

만약 kops사용이 처음이라면, 얼마 걸리지 않으니 이들을 시험해 본다. 인스턴스 그룹은 쿠버네티스 노드로 등록된 인스턴스의 집합을 말한다. AWS상에서는 auto-scaling-groups를 통해 만들어진다. 사용자는 여러 개의 인스턴스 그룹을 관리할 수 있는데, 예를 들어, spot과 on-demand 인스턴스 조합 또는 GPU 와 non-GPU 인스턴스의 조합으로 구성할 수 있다.

(5/5) AWS에 클러스터 생성

kops update cluster를 실행해 AWS에 클러스터를 생성한다.

kops update cluster useast1.dev.example.com --yes

실행은 수 초 만에 되지만, 실제로 클러스터가 준비되기 전까지 수 분이 걸릴 수 있다. 언제든 kops update cluster로 클러스터 설정을 변경할 수 있다. 사용자가 변경한 클러스터 설정을 그대로 반영해 줄 것이며, 필요다하면 AWS 나 쿠버네티스를 재설정 해 줄것이다.

예를 들면, kops edit ig nodes 뒤에 kops update cluster --yes를 실행해 설정을 반영한다. 그리고 kops rolling-update cluster로 설정을 즉시 원복시킬 수 있다.

--yes를 명시하지 않으면 kops update cluster 커맨드 후 어떤 설정이 변경될지가 표시된다. 운영계 클러스터 관리할 때 사용하기 좋다!

다른 애드온 탐험

애드온 리스트 에서 쿠버네티스 클러스터용 로깅, 모니터링, 네트워크 정책, 시각화 & 제어 등을 포함한 다른 애드온을 확인해본다.

정리하기

  • kops delete cluster useast1.dev.example.com --yes 로 클러스터를 삭제한다.

다음 내용

  • 쿠버네티스 개념kubectl에 대해 더 알아보기.
  • 튜토리얼, 모범사례 및 고급 구성 옵션에 대한 kOps 고급 사용법에 대해 더 자세히 알아본다.
  • 슬랙(Slack)에서 kOps 커뮤니티 토론을 할 수 있다: 커뮤니티 토론
  • 문제를 해결하거나 이슈를 제기하여 kOps 에 기여한다. 깃헙 이슈

2.3 - Kubespray로 쿠버네티스 설치하기

이 가이드는 Kubespray를 이용하여 GCE, Azure, OpenStack, AWS, vSphere, Equinix Metal(전 Packet), Oracle Cloud infrastructure(실험적) 또는 베어메탈 등에서 운영되는 쿠버네티스 클러스터를 설치하는 과정을 보여준다.

Kubespray는 Ansible 플레이북, 인벤토리, 프로비저닝 도구와 일반적인 운영체제, 쿠버네티스 클러스터의 설정 관리 작업에 대한 도메인 지식의 결합으로 만들어졌다. Kubespray는 아래와 같은 기능을 제공한다.

Kubespray 지원 사항

  • 고가용성을 지닌 클러스터
  • 구성 가능 (인스턴스를 위한 네트워크 플러그인 선택)
  • 대부분의 인기있는 리눅스 배포판들에 대한 지원
    • Flatcar Container Linux by Kinvolk
    • Debian Bullseye, Buster, Jessie, Stretch
    • Ubuntu 16.04, 18.04, 20.04, 22.04
    • CentOS/RHEL 7, 8, 9
    • Fedora 35, 36
    • Fedora CoreOS
    • openSUSE Leap 15.x/Tumbleweed
    • Oracle Linux 7, 8, 9
    • Alma Linux 8, 9
    • Rocky Linux 8, 9
    • Kylin Linux Advanced Server V10
    • Amazon Linux 2
  • 지속적인 통합 (CI) 테스트

클러스터를 설치해 줄 도구로 유스케이스와 가장 잘 맞는 것을 고르고 싶다면, kubespray를 kubeadm, kops비교한 글을 읽어보자.

클러스터 생성하기

(1/5) 아래의 요건 충족하기

언더레이(underlay) 요건을 만족하는 프로비전 한다.

  • 쿠버네티스는 최소한 v1.22 이상의 버전이 필요하다.
  • Ansible의 명령어를 실행하기 위해 Ansible v2.11+, Jinja 2.11+와 Python netaddr 라이브러리가 머신에 설치되어 있어야 한다.
  • 타겟 서버들은 docker 이미지를 풀(pull) 하기 위해 반드시 인터넷에 접속할 수 있어야 한다. 아니라면, 추가적인 설정을 해야 한다 (오프라인 환경 확인하기)
  • 타겟 서버들의 IPv4 포워딩이 활성화되어야 한다.
  • 파드와 서비스에서 IPv6를 이용한다면, 대상 서버도 IPv6 포워딩이 활성화되어야 한다.
  • 방화벽은 kubespray가 관리하지 않는다. 사용자는 기존 방식으로 자신의 규칙을 구현해야 한다. 배포 중에 만날 문제를 예방하려면 방화벽을 비활성화해야 한다.
  • 만약 kubespray가 루트가 아닌 사용자 계정에서 실행되었다면, 타겟 서버에서 알맞은 권한 상승 방법이 설정되어야 한다. 그 후에 ansible_become 플래그나 커맨드 파라미터들, --become 또는 -b 가 명시되어야 한다

Kubespray는 환경에 맞는 프로비저닝을 돕기 위해 아래와 같은 서비스를 제공한다:

(2/5) 인벤토리 파일 구성하기

서버들을 프로비저닝 한 후, Ansible의 인벤토리 파일을 만들어야 한다. 수동으로 만들 수도 있고, 동적인 인벤토리 스크립트를 통해 만들 수도 있다. 더 많이 알고싶다면 " 나만의 인벤토리 만들기" 글을 확인하자.

(3/5) 클러스터 디플로이먼트 계획하기

Kubespray에서는 디플로이먼트의 많은 속성들을 사용자가 정의(customize)할 수 있다:

  • 디플로이먼트 모드의 선택: kubeadm 또는 그 외
  • CNI(네트워킹) 플러그인
  • DNS 설정
  • 컨트롤 플레인 선택: 네이티브/바이너리 또는 컨테이너화 된 것
  • 컴포넌트 버전
  • Calico 라우터 리플렉터
  • 컴포넌트 런타임 옵션
  • 인증서 생성 방법

Kubespray의 변수 파일들을 사용자가 정의할 수 있다. 만약 Kubespray를 처음 접하는 경우, kubespray의 기본 설정값을 이용해 클러스터를 배포하고 Kubernetes를 탐색하는 것이 좋다.

(4/5) 클러스터 배포하기

다음으로, 클러스터를 배포한다.

Ansible-플레이북을 이용한 클러스터 디플로이먼트

ansible-playbook -i your/inventory/inventory.ini cluster.yml -b -v \
  --private-key=~/.ssh/private_key

규모가 큰 디플로이먼트는 (100개 이상의 노드) 최적의 결과를 얻기 위해 특정한 조정을 필요로 할 수도 있다.

(5/5) 디플로이먼트 검증하기

Kubespray는 Netchecker를 사용하여 파드 사이의 연결성과 DNS 해석을 검증할 방법을 제공한다. Netchecker는 netchecker-agents 파드들이 DNS 요청을 해석하고 기본(default) 네임스페이스 내부에서 서로에게 ping을 보낼 수 있도록 보장한다. 그 파드들은 나머지 워크로드의 유사한 동작을 모방하고 클러스터의 상태 표시기 역할을 한다.

클러스터 동작

Kubespray는 클러스터를 관리하기 위한 추가적인 플레이북, scaleupgrade 를 제공한다.

클러스터 스케일링하기

scale 플레이북을 실행해 클러스터에 워커 노드를 추가할 수 있다. 더 자세히 알고 싶다면, "노드 추가하기" 문서를 확인하자. remove-node 플레이북을 실행하면 클러스터로부터 워커 노드를 제거할 수 있다. 더 알고 싶다면 "노드 제거하기" 문서를 확인하자.

클러스터 업그레이드 하기

upgrade-cluster 플레이북을 실행해 클러스터를 업그레이드 할 수 있다. 더 자세히 알고 싶다면 "업그레이드" 문서를 확인하자.

클린업

reset 플레이북을 이용하여 노드들을 리셋하고 Kubespray로 설치된 모든 구성요소를 삭제할 수 있다.

피드백

다음 내용

  • Kubespray의 로드맵에서 계획중인 작업을 확인해보자.
  • Kubespray를 더 알아보자.

3 - 턴키 클라우드 솔루션

이 페이지는 인증된 쿠버네티스 솔루션 제공자 목록을 제공한다. 각 제공자 페이지를 통해서, 프로덕션에 준비된 클러스터를 설치 및 설정하는 방법을 학습할 수 있다.