시작하기
본 섹션에는 쿠버네티스를 설정하고 실행하는 다양한 방법이 나열되어 있다.
쿠버네티스를 설치할 때는 유지보수의 용이성, 보안, 제어, 사용 가능한 리소스, 그리고
클러스터를 운영하고 관리하기 위해 필요한 전문성을 기반으로 설치 유형을 선택한다.
쿠버네티스를 다운로드하여
로컬 머신에, 클라우드에, 데이터센터에 쿠버네티스 클러스터를 구축할 수 있다.
kube-apiserver나 kube-proxy와 같은 몇몇 쿠버네티스 컴포넌트들은
클러스터 내에서 컨테이너 이미지를 통해 배포할 수 있다.
쿠버네티스 컴포넌트들은 가급적 컨테이너 이미지로 실행하는 것을 추천하며,
이를 통해 쿠버네티스가 해당 컴포넌트들을 관리하도록 한다.
컨테이너를 구동하는 컴포넌트(특히 kubelet)는 여기에 속하지 않는다.
쿠버네티스 클러스터를 직접 관리하고 싶지 않다면, 인증된 플랫폼과
같은 매니지드 서비스를 선택할 수도 있다.
광범위한 클라우드 또는 베어 메탈 환경에 걸쳐 사용할 수 있는
표준화된/맞춤형 솔루션도 있다.
학습 환경
쿠버네티스를 배우고 있다면, 쿠버네티스 커뮤니티에서 지원하는 도구나,
로컬 머신에서 쿠버네티스를 설치하기 위한 생태계 내의 도구를 사용한다.
도구 설치를 살펴본다.
프로덕션 환경
프로덕션 환경을 위한
솔루션을 평가할 때에는, 쿠버네티스 클러스터(또는 추상화된 객체)
운영에 대한 어떤 측면을 스스로 관리하기를 원하는지,
또는 제공자에게 넘기기를 원하는지 고려한다.
클러스터를 직접 관리하는 경우, 공식적으로 지원되는 쿠버네티스 구축 도구는
kubeadm이다.
다음 내용
쿠버네티스의 컨트롤 플레인은
리눅스에서 실행되도록 설계되었다. 클러스터 내에서는 리눅스 또는
다른 운영 체제(예: 윈도우)에서 애플리케이션을 실행할 수 있다.
1 - 학습 환경
2 - 프로덕션 환경
프로덕션 수준의 쿠버네티스 클러스터 생성
프로덕션 수준의 쿠버네티스 클러스터에는 계획과 준비가 필요하다.
쿠버네티스 클러스터에 중요한 워크로드를 실행하려면 클러스터를 탄력적이도록 구성해야 한다.
이 페이지에서는 프로덕션용 클러스터를 설정하거나 기존 클러스터를 프로덕션용으로 업그레이드하기 위해
수행할 수 있는 단계를 설명한다.
이미 프로덕션 구성 내용에 익숙하여 단지 링크를 찾고 있다면,
다음 내용을 참고한다.
프로덕션 고려 사항
일반적으로 프로덕션 쿠버네티스 클러스터 환경에는
개인 학습용, 개발용 또는 테스트 환경용 클러스터보다 더 많은 요구 사항이 있다.
프로덕션 환경에는 많은 사용자의 보안 액세스, 일관된 가용성 및
변화하는 요구를 충족하기 위한 리소스가 필요할 수 있다.
프로덕션 쿠버네티스 환경이 상주할 위치(온 프레미스 또는 클라우드)와
직접 처리하거나 다른 사람에게 맡길 관리의 양을 결정할 때,
쿠버네티스 클러스터에 대한 요구 사항이
다음 이슈에 의해 어떻게 영향을 받는지 고려해야 한다.
가용성: 단일 머신 쿠버네티스 학습 환경은 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 서비스 오토스케일링을 확인한다.
- 추가적인 서비스 어카운트 생성: 사용자 계정은 클러스터에서 사용자가 무엇을 할 수 있는지 결정하는 반면에,
서비스 어카운트는 특정 네임스페이스 내의 파드 접근 권한을 결정한다.
기본적으로, 파드는 자신의 네임스페이스의 기본 서비스 어카운트을 이용한다.
서비스 어카운트 관리하기에서
새로운 서비스 어카운트을 생성하는 방법을 확인한다. 예를 들어, 다음의 작업을 할 수 있다.
다음 내용
2.1 - 컨테이너 런타임
참고: Dockershim은 쿠버네티스 릴리스 1.24부터 쿠버네티스 프로젝트에서 제거되었다. 더 자세한 내용은
Dockershim 제거 FAQ를 참고한다.
파드가 노드에서 실행될 수 있도록 클러스터의 각 노드에
컨테이너 런타임을
설치해야 한다. 이 페이지에서는 관련된 항목을 설명하고
노드 설정 관련 작업을 설명한다.
쿠버네티스 1.34에서는
컨테이너 런타임 인터페이스(CRI) 요구사항을 만족하는
런타임을 사용해야 한다.
더 자세한 정보는 CRI 버전 지원을 참조한다.
이 페이지는 쿠버네티스에서
여러 공통 컨테이너 런타임을 사용하는 방법에 대한 개요를 제공한다.
참고:
쿠버네티스 v1.24 이전 릴리스는
도커심 이라는 구성 요소를 사용하여 도커 엔진과의 직접 통합을 지원했다.
이 특별한 직접 통합은
더 이상 쿠버네티스에 포함되지 않는다(이 제거는
v1.20 릴리스의 일부로 공지되었다).
이 제거가 어떻게 영향을 미치는지 알아보려면
도커심 제거가 영향을 미치는지 확인하기 문서를 확인한다.
도커심을 사용하던 환경에서 이전(migrating)하는 방법을 보려면,
도커심에서 이전하기를 확인한다.
v1.34 이외의 쿠버네티스 버전을 사용하고 있다면,
해당 버전의 문서를 참고한다.
필수 요소들 설치 및 구성하기
다음 단계에서는 리눅스의 쿠버네티스 노드를 위한 일반적인 설정들을 적용한다.
만약 필요하지 않다고 생각한다면 몇몇 설정들은 넘어가도 무방하다.
더 자세한 정보는, 네트워크 플러그인 요구사항이나 각자 사용 중인 컨테이너 런타임에 해당하는 문서를 확인한다.
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
로 설정해야 한다. 자세한 설명은
컨테이너 런타임 대한 문서를 참조한다. 예를 들면 다음과 같다.
주의:
클러스터에 결합되어 있는 노드의 cgroup 관리자를 변경하는 것은 신중하게 수행해야 한다.
하나의 cgroup 드라이버의 의미를 사용하여 kubelet이 파드를 생성해왔다면,
컨테이너 런타임을 다른 cgroup 드라이버로 변경하는 것은 존재하는 기존 파드에 대해 파드 샌드박스 재생성을 시도할 때, 에러가 발생할 수 있다.
kubelet을 재시작하는 것은 에러를 해결할 수 없을 것이다.
자동화가 가능하다면, 업데이트된 구성을 사용하여 노드를 다른 노드로
교체하거나, 자동화를 사용하여 다시 설치한다.
kubeadm으로 생성한 클러스터의 드라이버를 systemd
로 변경하기
기존에 kubeadm으로 생성한 클러스터의 cgroup 드라이버를 systemd
로 변경하려면,
cgroup 드라이버 설정하기를 참고한다.
CRI 버전 지원
사용할 컨테이너 런타임이 적어도 CRI의 v1alpha2 이상을 지원해야 한다.
쿠버네티스 1.34 버전에서는 기본적으로 CRI API 중 v1을 사용한다.
컨테이너 런타임이 v1 API를 지원하지 않으면,
kubelet은 대신 (사용 중단된) v1alpha2 API를 사용하도록 설정된다.
컨테이너 런타임
참고: 이 섹션은 쿠버네티스에 필요한 기능을 제공하는 써드파티 프로젝트와 관련이 있다. 쿠버네티스 프로젝트 작성자는 써드파티 프로젝트에 책임이 없다. 이 페이지는
CNCF 웹사이트 가이드라인에 따라 프로젝트를 알파벳 순으로 나열한다. 이 목록에 프로젝트를 추가하려면 변경사항을 제출하기 전에
콘텐츠 가이드를 읽어본다.
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.toml
의 systemd
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를 패키지(RPM, .deb
등)를 통해 설치하였다면,
CRI integration 플러그인은 기본적으로 비활성화되어 있다.
쿠버네티스에서 containerd를 사용하기 위해서는 CRI support가 활성화되어 있어야 한다.
cri
가 /etc/containerd/config.toml
파일 안에 있는 disabled_plugins
목록에 포함되지 않도록 주의하자.
만약 해당 파일을 변경하였다면, containerd
를 다시 시작한다.
이 변경 사항을 적용하려면, 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 기능을 지원한다.
도커 엔진
참고:
아래의 지침은
당신이 도커 엔진과 쿠버네티스를 통합하는 데
cri-dockerd
어댑터를 사용하고 있다고 가정한다.
각 노드에서, 도커 엔진 설치하기에 따라
리눅스 배포판에 맞게 도커를 설치한다.
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 - 배포 도구로 쿠버네티스 설치하기
자체 프로덕션 쿠버네티스 클러스터를 설정하는 데는 다양한 방법과 도구가 있다.
예를 들면 다음과 같다.
kubeadm
클러스터 API: 여러 쿠버네티스 클러스터의 프로비저닝,
업그레이드 및 운영을 단순화하는 선언적 API와 도구를 제공하는 데 중점을 둔
쿠버네티스 하위 프로젝트이다.
kops: 자동화된 클러스터 프로비저닝 도구이다.
튜토리얼, 모범 사례, 구성 옵션 및 커뮤니티
참여에 대한 정보는
kOps
웹사이트에서 자세히 확인할 수 있다.
kubespray:
일반적인 OS/쿠버네티스 클러스터 구성 관리 작업을 위한 Ansible
플레이북, 인벤토리,
프로비저닝 도구 및 도메인 지식의
조합이다. #kubespray
슬랙 채널에서 커뮤니티에 참여할 수 있다.
2.2.1 - kubeadm으로 클러스터 구성하기
2.2.1.1 - kubeadm 설치하기
이 페이지에서는 kubeadm
툴박스 설치 방법을 보여준다.
이 설치 프로세스를 수행한 후 kubeadm으로 클러스터를 만드는 방법에 대한 자세한 내용은
kubeadm으로 클러스터 생성하기 페이지를 참고한다.
This installation guide is for Kubernetes v1.34. If you want to use a different Kubernetes version, please refer to the following pages instead:
시작하기 전에
- 호환되는 리눅스 호스트. 쿠버네티스 프로젝트는 데비안 및 레드햇 기반 리눅스 배포판과
패키지 매니저가 없는 배포판에 대한 일반적인 지침을 제공한다.
- 머신당 2GB 이상의 RAM (이보다 적으면 앱을 위한 공간이 거의 남지 않는다).
- 컨트롤 플레인 머신에는 2개 이상의 CPU.
- 클러스터의 모든 머신 간 완전한 네트워크 연결 (공용 또는 사설 네트워크 무관).
- 모든 노드에 대해 고유한 호스트네임, MAC 주소, 그리고 product_uuid. 자세한 내용은 여기를 참고한다.
- 머신에 특정 포트들이 열려있어야 한다. 자세한 내용은 여기를 참고한다.
참고:
kubeadm
설치는 동적 링킹을 사용하는 바이너리를 통해 수행되며 대상 시스템이
glibc
를 제공한다고 가정한다.
이는 많은 리눅스 배포판(데비안, 우분투, 페도라, CentOS 등 포함)에서 합리적인 가정이지만
알파인 리눅스(Alpine Linux)와 같이 기본적으로
glibc
를
포함하지 않는 커스텀 및 경량 배포판에서는 항상 그런 것은 아니다.
배포판이
glibc
를 포함하거나 예상되는 심볼을 제공하는
호환성 레이어를 포함할 것으로 예상된다.
OS 버전 확인
참고: 이 섹션은 쿠버네티스에 필요한 기능을 제공하는 써드파티 프로젝트와 관련이 있다. 쿠버네티스 프로젝트 작성자는 써드파티 프로젝트에 책임이 없다. 이 페이지는
CNCF 웹사이트 가이드라인에 따라 프로젝트를 알파벳 순으로 나열한다. 이 목록에 프로젝트를 추가하려면 변경사항을 제출하기 전에
콘텐츠 가이드를 읽어본다.
- kubeadm 프로젝트는 LTS 커널을 지원한다. LTS 커널 목록을 참고한다.
uname -r
명령을 사용하여 커널 버전을 확인할 수 있다
자세한 정보는 리눅스 커널 요구사항을 참고한다.
- kubeadm 프로젝트는 최신 커널 버전을 지원한다. 최신 커널 목록은 윈도우 서버 릴리스 정보를 참고한다.
systeminfo
명령을 사용하여 커널 버전(OS 버전이라고도 함)을 확인할 수 있다
자세한 정보는 윈도우 OS 버전 호환성을 참고한다.
kubeadm으로 생성된 쿠버네티스 클러스터는 커널 기능을 사용하는 소프트웨어에 의존한다.
이 소프트웨어에는 컨테이너 런타임,
kubelet,
그리고 컨테이너 네트워크 인터페이스 플러그인이 포함되지만 이에 국한되지 않는다.
지원되지 않는 커널 버전으로 인한 예기치 않은 오류를 방지하기 위해, kubeadm은 SystemVerification
사전 검사를 실행한다.
이 검사는 커널 버전이 지원되지 않으면 실패한다.
kubeadm이 커널 버전을 지원하지 않더라도,
커널이 필요한 기능을 제공한다는 것을 알고 있다면 검사를 건너뛰도록 선택할 수 있다.
모든 노드에서 MAC 주소와 product_uuid가 고유한지 확인
ip link
또는 ifconfig -a
명령을 사용하여 네트워크 인터페이스의 MAC 주소를 확인할 수 있다sudo cat /sys/class/dmi/id/product_uuid
명령을 사용하여 product_uuid를 확인할 수 있다
하드웨어 장치는 고유한 주소를 가질 가능성이 매우 높지만, 일부 가상 머신은 동일한 값을 가질 수 있다.
쿠버네티스는 이러한 값을 사용하여 클러스터의 노드를 고유하게 식별한다.
이러한 값이 각 노드에서 고유하지 않으면 설치 과정이
실패할 수 있다.
네트워크 어댑터 확인
네트워크 어댑터가 두 개 이상이고, 쿠버네티스 컴포넌트가 디폴트 라우트(default route)에서 도달할 수 없는
경우, 쿠버네티스 클러스터 주소가 적절한 어댑터를 통해 이동하도록 IP 경로를 추가하는 것이 좋다.
필수 포트 확인
쿠버네티스 컴포넌트가 서로 통신하려면 이러한
필수 포트가 열려 있어야 한다.
netcat과 같은 도구를 사용하여 포트가 열려 있는지 확인할 수 있다. 예를 들어
nc 127.0.0.1 6443 -zv -w 2
사용하는 파드 네트워크 플러그인도 특정 포트가 열려 있어야 할 수 있다.
각 파드 네트워크 플러그인마다 다르므로,
해당 플러그인이 필요로 하는 포트에 대해서는 플러그인 문서를 참고한다.
스왑 구성
노드에서 스왑 메모리가 감지되면 kubelet의 기본 동작은 시작에 실패하는 것이다.
이는 스왑이 비활성화되거나 kubelet에 의해 용인되어야 함을 의미한다.
- 스왑을 용인하려면, kubelet 구성에
failSwapOn: false
를 추가하거나 커맨드라인 인수로 설정한다.
참고: failSwapOn: false
가 제공되더라도 워크로드는 기본적으로 스왑에 접근할 수 없다.
이는 kubelet 구성 파일에서 다시 swapBehavior
를 설정하여 변경할 수 있다. 스왑을 사용하려면,
기본 NoSwap
설정이 아닌 다른 swapBehavior
를 설정한다.
자세한 내용은 스왑 메모리 관리를 참고한다. - 스왑을 비활성화하려면,
sudo swapoff -a
를 사용하여 일시적으로 스와핑을 비활성화할 수 있다.
재부팅 후에도 이 변경사항을 유지하려면, 시스템 구성 방법에 따라
/etc/fstab
, systemd.swap
과 같은 구성 파일에서 스왑이 비활성화되어 있는지 확인한다.
컨테이너 런타임 설치
파드에서 컨테이너를 실행하기 위해, 쿠버네티스는
컨테이너 런타임을 사용한다.
기본적으로, 쿠버네티스는
컨테이너 런타임 인터페이스(CRI)를
사용하여 사용자가 선택한 컨테이너 런타임과 인터페이스한다.
런타임을 지정하지 않으면, kubeadm은 잘 알려진 엔드포인트를 스캐닝하여
설치된 컨테이너 런타임을 자동으로 감지하려고 한다.
컨테이너 런타임이 여러 개 감지되거나 하나도 감지되지 않은 경우,
kubeadm은 에러를 반환하고 사용자가 어떤 것을 사용할지를 명시하도록 요청할 것이다.
자세한 정보는 컨테이너 런타임
을 참고한다.
참고:
도커 엔진은 컨테이너 런타임이 쿠버네티스와 호환되기 위한 요구 사항인
CRI를 만족하지 않는다.
이러한 이유로, 추가 서비스인
cri-dockerd가 설치되어야 한다.
cri-dockerd는 쿠버네티스 버전 1.24부터 kubelet에서
제거된
기존 내장 도커 엔진 지원을 기반으로 한 프로젝트이다.
아래 표는 지원 운영 체제에 대한 알려진 엔드포인트를 담고 있다.
리눅스 컨테이너 런타임런타임 | 유닉스 도메인 소켓 경로 |
---|
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 설치 및 설정을 참고한다.
경고:
이 지침은 모든 시스템 업그레이드에서 모든 쿠버네티스 패키지를 제외한다.
이는 kubeadm 및 쿠버네티스를
업그레이드 하는 데 특별한 주의가 필요하기 때문이다.
버전 차이에 대한 자세한 내용은 다음을 참고한다.
참고: The legacy package repositories (
apt.kubernetes.io
and
yum.kubernetes.io
) have been
deprecated and frozen starting from September 13, 2023.
Using the new package repositories hosted at pkgs.k8s.io
is strongly recommended and required in order to install Kubernetes versions released after September 13, 2023.
The deprecated legacy repositories, and their contents, might be removed at any time in the future and without
a further notice period. The new package repositories provide downloads for Kubernetes versions starting with v1.24.0.
참고:
각 쿠버네티스 마이너 버전마다 전용 패키지 저장소가 있다.
v1.34가 아닌 다른 마이너 버전을 설치하려면,
원하는 마이너 버전에 대한 설치 가이드를 참고한다.다음 지침은 쿠버네티스 v1.34에 대한 것이다.
apt
패키지 인덱스를 업데이트하고 쿠버네티스 apt
리포지터리를 사용하는 데 필요한 패키지를 설치한다.
sudo apt-get update
# apt-transport-https는 더미 패키지일 수 있다. 그렇다면 해당 패키지를 건너뛸 수 있다
sudo apt-get install -y apt-transport-https ca-certificates curl gpg
쿠버네티스 패키지 리포지터리용 공개 샤이닝 키를 다운로드한다.
모든 리포지터리에 동일한 서명 키가 사용되므로 URL의 버전은 무시할 수 있다.
# `/etc/apt/keyrings` 디렉터리가 존재하지 않으면, curl 명령 전에 생성해야 한다. 아래 참고사항을 읽어본다.
# sudo mkdir -p -m 755 /etc/apt/keyrings
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.34/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
참고:
데비안 12와 우분투 22.04보다 오래된 릴리스에서는 /etc/apt/keyrings
디렉터리가 기본적으로 존재하지 않으며, curl 명령 전에 생성되어야 한다.적절한 쿠버네티스 apt
리포지터리를 추가한다. 이 리포지터리에는 쿠버네티스 1.34에 대한
패키지만 있다는 점에 유의한다. 다른 쿠버네티스 마이너 버전의 경우, 원하는 마이너 버전과 일치하도록
URL의 쿠버네티스 마이너 버전을 변경해야 한다
(설치할 계획인 쿠버네티스 버전에 대한 문서를 읽고 있는지도
확인해야 한다).
# 이 명령어는 /etc/apt/sources.list.d/kubernetes.list 에 있는 기존 구성을 덮어쓴다.
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.34/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
apt
패키지 색인을 업데이트하고, kubelet, kubeadm, kubectl을 설치하고 해당 버전을 고정한다.
sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl
(선택사항) kubeadm을 실행하기 전에 kubelet 서비스를 활성화한다.
sudo systemctl enable --now kubelet
SELinux를 permissive
모드로 설정한다.
다음 지침은 쿠버네티스 1.34에 대한 것이다.
# SELinux를 permissive 모드로 설정한다 (효과적으로 비활성화)
sudo setenforce 0
sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
주의:
setenforce 0
및 sed ...
실행으로 SELinux를 permissive 모드로 설정하면 효과적으로 비활성화된다.
이는 컨테이너가 호스트 파일시스템에 접근할 수 있도록 하기 위해 필요하다.
예를 들어, 일부 클러스터 네트워크 플러그인에서 이를 요구한다.
kubelet에서 SELinux 지원이 개선될 때까지 이렇게 해야 한다.- SELinux를 구성하는 방법을 알고 있다면 SELinux를 활성화된 상태로 둘 수 있지만
kubeadm에서 지원하지 않는 설정이 필요할 수 있다.
쿠버네티스 yum
리포지터리를 추가한다.
리포지터리 정의의 exclude
파라미터는 쿠버네티스를 업그레이드하기 위해
따라야 하는 특별한 절차가 있으므로 yum update
실행 시 쿠버네티스와 관련된
패키지가 업그레이드되지 않도록 한다.
이 리포지터리에는 쿠버네티스 1.34에
대한 패키지만 있다는 점에 유의한다.
다른 쿠버네티스 마이너 버전의 경우, 원하는 마이너 버전과 일치하도록
URL의 쿠버네티스 마이너 버전을 변경해야 한다
(설치할 계획인 쿠버네티스 버전에 대한 문서를 읽고 있는지도 확인해야 한다).
# 이것은 /etc/yum.repos.d/kubernetes.repo에 있는 기존 구성을 덮어쓴다
cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://pkgs.k8s.io/core:/stable:/v1.34/rpm/
enabled=1
gpgcheck=1
gpgkey=https://pkgs.k8s.io/core:/stable:/v1.34/rpm/repodata/repomd.xml.key
exclude=kubelet kubeadm kubectl cri-tools kubernetes-cni
EOF
kubelet, kubeadm 및 kubectl을 설치한다.
sudo yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes
(선택사항) kubeadm을 실행하기 전에 kubelet 서비스를 활성화한다.
sudo systemctl enable --now kubelet
CNI 플러그인 설치(대부분의 파드 네트워크에 필요)
CNI_PLUGINS_VERSION="v1.3.0"
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
변수는 쓰기 가능한 디렉터리로 설정되어야 한다.
Flatcar Container Linux를 실행 중인 경우, DOWNLOAD_DIR="/opt/bin"
을 설정한다.DOWNLOAD_DIR="/usr/local/bin"
sudo mkdir -p "$DOWNLOAD_DIR"
선택적으로 crictl을 설치한다 (컨테이너 런타임 인터페이스(CRI)와의 상호작용에 필요, kubeadm에는 선택사항).
CRICTL_VERSION="v1.31.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
을 설치하고 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}
sudo chmod +x {kubeadm,kubelet}
RELEASE_VERSION="v0.16.2"
curl -sSL "https://raw.githubusercontent.com/kubernetes/release/${RELEASE_VERSION}/cmd/krel/templates/latest/kubelet/kubelet.service" | sed "s:/usr/bin:${DOWNLOAD_DIR}:g" | sudo tee /usr/lib/systemd/system/kubelet.service
sudo mkdir -p /usr/lib/systemd/system/kubelet.service.d
curl -sSL "https://raw.githubusercontent.com/kubernetes/release/${RELEASE_VERSION}/cmd/krel/templates/latest/kubeadm/10-kubeadm.conf" | sed "s:/usr/bin:${DOWNLOAD_DIR}:g" | sudo tee /usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf
참고:
기본적으로
glibc
를 포함하지 않는 리눅스 배포판에 대해서는
시작하기 전에 섹션의 참고사항을 참고한다.
도구 설치 페이지의 지침에 따라 kubectl
을 설치한다.
선택적으로, kubeadm을 실행하기 전에 kubelet 서비스를 활성화한다.
sudo systemctl enable --now kubelet
참고:
Flatcar Container Linux 배포판은
/usr
디렉터리를 읽기 전용 파일시스템으로 마운트한다.
클러스터를 부트스트랩하기 전에, 쓰기 가능한 디렉터리를 구성하기 위한 추가 단계를 수행해야 한다.
쓰기 가능한 디렉터리를 설정하는 방법을 알아 보려면
Kubeadm 문제 해결 가이드를 참고한다.
kubelet은 이제 kubeadm이 수행할 작업을 알려 줄 때까지 크래시루프(crashloop) 상태로
기다려야 하므로 몇 초마다 다시 시작된다.
cgroup 드라이버 구성
컨테이너 런타임과 kubelet은
"cgroup 드라이버"라는 속성을 갖고 있으며,
cgroup 드라이버는 리눅스 머신의 cgroup 관리 측면에 있어서 중요하다.
경고:
컨테이너 런타임과 kubelet의 cgroup 드라이버를 일치시켜야 하며, 그렇지 않으면 kubelet 프로세스에 오류가 발생한다.
더 자세한 사항은 cgroup 드라이버 설정하기를 참고한다.
문제 해결
kubeadm에 문제가 있는 경우,
문제 해결 문서를 참고한다.
다음 내용
2.2.1.2 - kubeadm 문제 해결
다른 프로그램과 마찬가지로, kubeadm을 설치하거나 실행하는 중에 오류가 발생할 수 있다.
이 페이지에는 일반적인 실패 시나리오를 나열하고 문제를 이해하고 해결하는 데 도움을 줄 수 있는 단계를 제공한다.
아래에 문제가 언급되어 있지 않다면 다음 단계를 따르도록 한다.
문제가 kubeadm의 버그라고 생각되는 경우:
kubeadm 작동 방식이 확실하지 않은 경우, 슬랙의 #kubeadm
에서 질문하거나,
스택오버플로우에 질문을 올릴 수 있다. 사람들이 도움을 줄 수
있도록 #kubernetes
및 #kubeadm
과 같은 관련 태그를 포함한다.
RBAC 누락으로 인해 v1.18 노드를 v1.17 클러스터에 참여할 수 없음
v1.18 kubeadm은 같은 이름의 노드가 이미 존재하는 경우 클러스터에 노드가 참여하는 것을 방지하는 기능을 추가했다.
이를 위해 bootstrap-token 사용자가 노드 객체를 GET할 수 있도록 RBAC를 추가해야 했다.
그러나 이로 인해 v1.18의 kubeadm join
이 kubeadm 1.17로 생성된 클러스터에 참여할 수 없는 문제가 발생한다.
이 문제를 해결하기 위한 두 가지 옵션이 있다.
kubeadm v1.18을 사용하여 컨트롤 플레인 노드에서 kubeadm init phase bootstrap-token
을 실행한다.
이렇게 하면 나머지 bootstrap-token 권한도 활성화된다는 점에 유의한다.
또는
kubectl apply -f ...
를 사용하여 다음 RBAC를 수동으로 적용한다.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: kubeadm:get-nodes
rules:
- apiGroups:
- ""
resources:
- nodes
verbs:
- get
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: kubeadm:get-nodes
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: kubeadm:get-nodes
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: system:bootstrappers:kubeadm:default-node-token
설치 중 ebtables
또는 유사한 실행 파일을 찾을 수 없음
kubeadm init
을 실행하는 동안 다음과 같은 경고 메시지가 출력된다면
[preflight] WARNING: ebtables not found in system path
[preflight] WARNING: ethtool not found in system path
노드에 ebtables
, ethtool
또는 유사한 실행 파일이 누락되었을 수 있다.
다음 명령으로 설치할 수 있다.
- 우분투/데비안 사용자의 경우,
apt install ebtables ethtool
을 실행한다. - CentOS/페도라 사용자의 경우,
yum install ebtables ethtool
을 실행한다.
설치 중 kubeadm이 컨트롤 플레인을 기다리다가 진행되지 않음 (block)
kubeadm init
이 다음 줄을 출력한 후 중단되는 경우
[apiclient] Created API client, waiting for the control plane to become ready
이는 여러 문제로 인해 발생할 수 있다. 가장 일반적인 원인은
- 네트워크 연결 문제: 계속하기 전에 머신에 완전한 네트워크 연결이 있는지 확인한다.
- 컨테이너 런타임의 cgroup 드라이버가 kubelet과 다름. 올바르게
구성하는 방법은 cgroup 드라이버 구성을 참조한다.
- 컨트롤 플레인 컨테이너가 크래시 루프에 있거나 중단됨.
docker ps
를 실행하고
docker logs
를 실행하여 각 컨테이너를 조사할 수 있다. 다른 컨테이너 런타임의 경우
crictl로 쿠버네티스 노드 디버깅하기를 참조한다.
관리되는 컨테이너를 제거할 때 kubeadm이 멈춤
컨테이너 런타임이 중단되고 쿠버네티스가 관리하는 컨테이너를 제거하지 않으면
다음과 같은 일이 발생할 수 있다.
[preflight] Running pre-flight checks
[reset] Stopping the kubelet service
[reset] Unmounting mounted directories in "/var/lib/kubelet"
[reset] Removing kubernetes-managed containers
(block)
가능한 해결 방안은 컨테이너 런타임을 재시작한 뒤 kubeadm reset
을 다시 실행하는 것이다.
또한 crictl
을 사용하여 컨테이너 런타임의 상태를 디버그할 수도 있다.
crictl로 쿠버네티스 노드 디버깅하기를 참조한다.
RunContainerError
, CrashLoopBackOff
또는 Error
상태의 파드
kubeadm init
직후에는 이러한 상태의 파드가 없어야 한다.
kubeadm init
직후 에 이러한 상태의 파드가 있다면
kubeadm 저장소에 이슈를 열자. coredns
(또는 kube-dns
)는
네트워크 애드온을 배포하기 전까지는 Pending
상태여야 한다.- 네트워크 애드온을 배포한 이후에도
RunContainerError
, CrashLoopBackOff
또는 Error
상태의
파드가 보이고 coredns
(또는 kube-dns
)에 아무 일도 일어나지 않는다면,
설치한 파드 네트워크 애드온이 어떤 식으로든 손상되었을 가능성이 높다.
더 많은 RBAC 권한을 부여하거나 최신 버전을 사용해야 할 수 있다. 파드
네트워크 공급자의 이슈 트래커에 이슈를 제출하고 분류를 받자.
coredns
가 Pending
상태에 멈춤
이는 예상된 동작이며 설계의 일부다. kubeadm은 네트워크 공급자에 구애받지 않으므로 관리자가
선택한 파드 네트워크 애드온을 설치해야
한다. CoreDNS가 완전히 배포되기
전에 파드 네트워크를 설치해야 한다. 따라서 네트워크가 설정되기 전까지 Pending
상태가 된다.
HostPort
서비스가 동작하지 않음
HostPort
와 HostIP
기능의 지원 여부는 파드 네트워크 공급자에 따라
달라진다. HostPort
및 HostIP
기능을 사용할 수 있는지 알아보려면 파드 네트워크 애드온
작성자에게 문의한다.
Calico, Canal 및 Flannel CNI 공급자는 HostPort를 지원하는 것으로 확인되었다.
자세한 내용은
CNI portmap 문서를 참조한다.
네트워크 공급자가 portmap CNI 플러그인을 지원하지 않는 경우,
서비스의 NodePort 기능을
사용하거나 HostNetwork=true
를 사용해야 할 수 있다.
파드가 서비스 IP를 통해 액세스할 수 없음
많은 네트워크 애드온이 아직 파드가 서비스 IP를 통해 자신에 액세스할 수 있도록 하는 헤어핀 모드
를 활성화하지 않는다. 이는
CNI와 관련된 문제다. 헤어핀 모드 지원의
최신 상태를 확인하려면 네트워크 애드온 공급자에게 문의한다.
VirtualBox를 사용하는 경우(직접 또는 Vagrant를 통해)
hostname -i
가 라우팅 가능한 IP 주소를 반환하는지 확인해야 한다. 기본적으로 첫 번째
인터페이스는 라우팅할 수 없는 호스트 전용 네트워크에 연결된다. 해결 방법은
/etc/hosts
를 수정하는 것이다. 예시는 이
Vagrantfile을
참조한다.
TLS 인증서 오류
다음 오류는 인증서 불일치 가능성을 나타낸다.
# kubectl get pods
Unable to connect to the server: x509: certificate signed by unknown authority (possibly because of "crypto/rsa: verification error" while trying to verify candidate authority certificate "kubernetes")
$HOME/.kube/config
파일에 유효한 인증서가 포함되어 있는지 확인하고 필요한 경우
인증서를 재생성한다. kubeconfig 파일의 인증서는 base64로
인코딩되어 있다. base64 --decode
명령을 사용하여 인증서를 디코딩하고
openssl x509 -text -noout
을 사용하여 인증서 정보를 볼 수 있다.
다음을 사용하여 KUBECONFIG
환경 변수를 해제한다.
또는 기본 KUBECONFIG
위치로 설정한다.
export KUBECONFIG=/etc/kubernetes/admin.conf
또 다른 해결 방법은 "admin" 사용자의 기존 kubeconfig
를 덮어쓰는 것이다.
mv $HOME/.kube $HOME/.kube.bak
mkdir $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
Kubelet 클라이언트 인증서 갱신 실패
기본적으로 kubeadm은 /etc/kubernetes/kubelet.conf
에 지정된 /var/lib/kubelet/pki/kubelet-client-current.pem
심볼릭 링크를 사용하여 kubelet 클라이언트 인증서가 자동 갱신되도록 구성한다.
이 갱신 프로세스가 실패하면 kube-apiserver 로그에 x509: certificate has expired or is not yet valid
와
같은 오류가 표시될 수 있다. 이 문제를 해결하려면 다음 단계를 따라야 한다.
실패한 노드에서 /etc/kubernetes/kubelet.conf
및 /var/lib/kubelet/pki/kubelet-client*
를 백업하고 삭제한다.
/etc/kubernetes/pki/ca.key
가 있는 클러스터의 작동 중인 컨트롤 플레인 노드에서
kubeadm kubeconfig user --org system:nodes --client-name system:node:$NODE > kubelet.conf
를 실행한다.
$NODE
는 클러스터에서 기존에 실패한 노드 이름으로 설정해야 한다.
결과 kubelet.conf
를 수동으로 수정하여 클러스터 이름과 서버 엔드포인트를 조정하거나
kubeconfig user --config
를 전달한다(추가 사용자를 위한 kubeconfig 파일 생성 참조). 클러스터에
ca.key
가 없으면 kubelet.conf
에 포함된 인증서에 외부에서 서명해야 한다.
결과 kubelet.conf
를 실패한 노드의 /etc/kubernetes/kubelet.conf
에 복사한다.
실패한 노드에서 kubelet을 재시작(systemctl restart kubelet
)하고
/var/lib/kubelet/pki/kubelet-client-current.pem
이 재생성될 때까지 기다린다.
kubelet.conf
를 수동으로 편집하여 갱신된 kubelet 클라이언트 인증서를 가리키도록 한다.
client-certificate-data
및 client-key-data
를 다음으로 교체한다.
client-certificate: /var/lib/kubelet/pki/kubelet-client-current.pem
client-key: /var/lib/kubelet/pki/kubelet-client-current.pem
kubelet을 재시작한다.
노드가 Ready
가 되었는지 확인한다.
Vagrant에서 flannel을 파드 네트워크로 사용할 때 기본 NIC
다음 오류는 파드 네트워크에 문제가 있음을 나타낼 수 있다.
Error from server (NotFound): the server could not find the requested resource
Vagrant 내에서 파드 네트워크로 flannel을 사용하는 경우, flannel의
기본 인터페이스 이름을 지정해야 한다.
Vagrant는 일반적으로 모든 VM에 두 개의 인터페이스를 할당한다. 첫 번째는 모든 호스트에
10.0.2.15
IP 주소가 할당되며, NAT 처리되는 외부 트래픽을 위한 것이다.
이는 호스트의 첫 번째 인터페이스를 기본값으로 하는 flannel에 문제를 일으킬 수 있다.
이로 인해 모든 호스트가 동일한 공용 IP 주소를 가지고 있다고 생각하게 된다. 이를 방지하려면
flannel에 --iface eth1
플래그를 전달하여 두 번째 인터페이스가 선택하도록 한다.
컨테이너에 공용이 아닌 IP가 사용됨
정상적으로 작동하는 클러스터에서 kubectl logs
및 kubectl run
명령이
다음 오류와 함께 반환될 수 있다.
Error from server: Get https://10.19.0.41:10250/containerLogs/default/mysql-ddc65b868-glc5m/mysql: dial tcp 10.19.0.41:10250: getsockopt: no route to host
이는 쿠버네티스에서 머신 공급자의 정책에 따라, 겉보기에는 동일한 서브넷에 있는 다른 IP와
통신할 수 없는 IP를 사용하는 쿠버네티스 (환경) 때문일 수 있다.
DigitalOcean은 eth0
에 공용 IP와 플로팅 IP 기능의 앵커로 내부적으로
사용되는 프라이빗 IP를 할당하지만, kubelet
은 공용 IP 대신 후자를 노드의
InternalIP
로 선택한다.
ifconfig
는 문제가 되는 별칭 IP 주소를 표시하지 않으므로 이 시나리오를 확인하려면
ifconfig
대신 ip addr show
를 사용한다. 또는 DigitalOcean에 특정한 API 엔드포인트를
사용하여 드롭릿(droplet)에서 앵커 IP를 쿼리할 수 있다.
curl http://169.254.169.254/metadata/v1/interfaces/public/0/anchor_ipv4/address
해결 방법은 --node-ip
를 사용하여 kubelet
에 사용할 IP를 알려주는 것이다.
DigitalOcean을 사용하는 경우, 공용 IP(eth0
에 할당됨) 또는
선택적 프라이빗 네트워크를 사용하려는 경우 프라이빗 IP(eth1
에 할당됨)가
될 수 있다. kubeadm
NodeRegistrationOptions
구조의
kubeletExtraArgs
섹션을 이에 사용할 수 있다.
그런 다음 kubelet
을 재시작한다.
systemctl daemon-reload
systemctl restart kubelet
coredns
파드가 CrashLoopBackOff
또는 Error
상태
이전 버전의 Docker와 함께 SELinux를 실행하는 노드가 있는 경우, coredns
파드가 시작되지 않는 시나리오가
발생할 수 있다. 이를 해결하려면 다음 옵션 중 하나를 시도할 수 있다.
kubectl -n kube-system get deployment coredns -o yaml | \
sed 's/allowPrivilegeEscalation: false/allowPrivilegeEscalation: true/g' | \
kubectl apply -f -
CoreDNS가 CrashLoopBackOff
를 가지는 또 다른 원인은 쿠버네티스에 배포된 CoreDNS 파드가 루프를 감지하는 경우다.
CoreDNS가 루프를 감지하고 종료할 때마다 쿠버네티스가 CoreDNS 파드를 재시작하지 않도록
여러 해결 방법을 사용할 수 있다.
경고:
SELinux를 비활성화하거나 allowPrivilegeEscalation
을 true
로 설정하면
클러스터의 보안이 손상될 수 있다.etcd 파드가 지속적으로 재시작됨
다음 오류가 발생하는 경우
rpc error: code = 2 desc = oci runtime error: exec failed: container_linux.go:247: starting container process caused "process_linux.go:110: decoding init error from pipe caused \"read parent: connection reset by peer\""
이 문제는 Docker 1.13.1.84와 함께 CentOS 7을 실행하는 경우 나타난다.
이 버전의 Docker는 kubelet이 etcd 컨테이너로 실행되는 것을 방지할 수 있다.
이 문제를 해결하려면 다음 옵션 중 하나를 선택한다.
1.13.1-75와 같은 이전 버전의 Docker로 롤백
yum downgrade docker-1.13.1-75.git8633870.el7.centos.x86_64 docker-client-1.13.1-75.git8633870.el7.centos.x86_64 docker-common-1.13.1-75.git8633870.el7.centos.x86_64
18.06과 같은 최신 권장 버전 중 하나를 설치
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
yum install docker-ce-18.06.1.ce-3.el7.x86_64
--component-extra-args
와 같은 kubeadm init
플래그를 사용하면 kube-apiserver와 같은 컨트롤 플레인
구성 요소에 사용자 정의 인수를 전달할 수 있다. 그러나 이 메커니즘은 값을 구문 분석하는 데 사용되는
기본 유형(mapStringString
)으로 인해 제한된다.
--apiserver-extra-args "enable-admission-plugins=LimitRanger,NamespaceExists"
와 같이
여러 쉼표로 구분된 값을 지원하는 인수를 전달하기로 결정한 경우, 이 플래그는
flag: malformed pair, expect string=string
으로 실패한다. 이는 --apiserver-extra-args
의
인수 목록이 key=value
쌍을 예상하고 이 경우 NamespacesExists
가 값이 없는 키로
간주되기 때문이다.
대안으로 key=value
쌍을 다음과 같이 분리할 수 있다.
--apiserver-extra-args "enable-admission-plugins=LimitRanger,enable-admission-plugins=NamespaceExists"
그러나 이는 enable-admission-plugins
키가 NamespaceExists
값만 가지게 된다.
알려진 해결 방법은 kubeadm 구성 파일을 사용하는 것이다.
cloud-controller-manager가 노드를 초기화하기 전에 kube-proxy가 스케줄됨
클라우드 공급자 시나리오에서 kube-proxy는 cloud-controller-manager가 노드 주소를
초기화하기 전에 새 워커 노드에 스케줄될 수 있다. 이로 인해 kube-proxy가
노드의 IP 주소를 제대로 가져오지 못하고 로드 밸런서를 관리하는 프록시 기능에 연쇄적인
영향을 미친다.
kube-proxy 파드에서 다음 오류를 볼 수 있다.
server.go:610] Failed to retrieve node IP: host IP unknown; known addresses: []
proxier.go:340] invalid nodeIP, initializing kube-proxy with 127.0.0.1 as nodeIP
알려진 해결 방법은 kube-proxy DaemonSet을 패치하여 조건에 관계없이 컨트롤 플레인 노드에
스케줄할 수 있도록 하고, 초기 보호 조건이 완화될 때까지 다른 노드에서
제외하는 것이다.
kubectl -n kube-system patch ds kube-proxy -p='{
"spec": {
"template": {
"spec": {
"tolerations": [
{
"key": "CriticalAddonsOnly",
"operator": "Exists"
},
{
"effect": "NoSchedule",
"key": "node-role.kubernetes.io/control-plane"
}
]
}
}
}
}'
이 문제에 대한 추적 이슈는 여기에 있다.
노드에서 /usr
이 읽기 전용으로 마운트됨
Fedora CoreOS 또는 Flatcar Container Linux와 같은 리눅스 배포판에서는 /usr
디렉터리가 읽기 전용 파일시스템으로 마운트된다.
flex-volume 지원을 위해
kubelet 및 kube-controller-manager와 같은 쿠버네티스 구성 요소는
/usr/libexec/kubernetes/kubelet-plugins/volume/exec/
의 기본 경로를 사용하지만, flex-volume 디렉터리는 기능이
작동하려면 쓰기 가능해야 한다.
참고:
FlexVolume은 쿠버네티스 v1.23 릴리스에서 사용 중단되었다.이 문제를 해결하려면 kubeadm 구성 파일을
사용하여 flex-volume 디렉터리를 구성할 수 있다.
기본 컨트롤 플레인 노드(kubeadm init
을 사용하여 생성)에서
--config
를 사용하여 다음 파일을 전달한다.
apiVersion: kubeadm.k8s.io/v1beta4
kind: InitConfiguration
nodeRegistration:
kubeletExtraArgs:
- name: "volume-plugin-dir"
value: "/opt/libexec/kubernetes/kubelet-plugins/volume/exec/"
---
apiVersion: kubeadm.k8s.io/v1beta4
kind: ClusterConfiguration
controllerManager:
extraArgs:
- name: "flex-volume-plugin-dir"
value: "/opt/libexec/kubernetes/kubelet-plugins/volume/exec/"
참여하는 노드에서
apiVersion: kubeadm.k8s.io/v1beta4
kind: JoinConfiguration
nodeRegistration:
kubeletExtraArgs:
- name: "volume-plugin-dir"
value: "/opt/libexec/kubernetes/kubelet-plugins/volume/exec/"
또는 /etc/fstab
를 수정하여 /usr
마운트를 쓰기 가능하게 만들 수 있지만,
이는 리눅스 배포판의 설계 원칙을 수정하는 것임을 유의한다.
kubeadm upgrade plan
이 context deadline exceeded
오류 메시지 출력
이 오류 메시지는 외부 etcd를 실행하는 경우 kubeadm
으로 쿠버네티스 클러스터를
업그레이드할 때 표시된다. 이는 중요한 버그가 아니며 이전 버전의 kubeadm이
외부 etcd 클러스터에서 버전 검사를 수행하기 때문에 발생한다.
kubeadm upgrade apply ...
를 계속 진행할 수 있다.
이 문제는 버전 1.19부터 수정되었다.
kubeadm reset
이 /var/lib/kubelet
을 언마운트함
/var/lib/kubelet
이 마운트되어 있는 경우, kubeadm reset
을 수행하면 효과적으로 언마운트된다.
이 문제를 해결하려면 kubeadm reset
작업을 수행한 후 /var/lib/kubelet
디렉터리를 다시 마운트한다.
이는 kubeadm 1.15에서 도입된 회귀 버그다. 이 문제는 1.20에서 수정되었다.
kubeadm 클러스터에서 metrics-server를 안전하게 사용할 수 없음
kubeadm 클러스터에서 metrics-server는
--kubelet-insecure-tls
를 전달하여 안전하지 않게 사용할 수 있다. 이는 프로덕션 클러스터에는 권장되지 않는다.
metrics-server와 kubelet 간에 TLS를 사용하려는 경우 문제가 있다.
kubeadm이 kubelet에 대해 자체 서명된 서빙 인증서를 배포하기 때문이다. 이로 인해
metrics-server 측에서 다음 오류가 발생할 수 있다.
x509: certificate signed by unknown authority
x509: certificate is valid for IP-foo not IP-bar
kubeadm 클러스터에서 kubelet이 올바르게 서명된 서빙 인증서를 갖도록 구성하는 방법을 이해하려면
서명된 kubelet 서빙 인증서 활성화를 참조한다.
또는 metrics-server를 안전하게 실행하는 방법을 참조한다.
etcd 해시가 변경되지 않아 업그레이드 실패
노드가 현재 kubeadm 버전 v1.28.0, v1.28.1 또는 v1.28.2로 관리되는 경우
kubeadm 바이너리 v1.28.3 이상으로 컨트롤 플레인 노드를 업그레이드하는 경우에만 해당된다.
발생할 수 있는 오류 메시지는 다음과 같다.
[upgrade/etcd] Failed to upgrade etcd: couldn't upgrade control plane. kubeadm has tried to recover everything into the earlier state. Errors faced: static Pod hash for component etcd on Node kinder-upgrade-control-plane-1 did not change after 5m0s: timed out waiting for the condition
[upgrade/etcd] Waiting for previous etcd to become available
I0907 10:10:09.109104 3704 etcd.go:588] [etcd] attempting to see if all cluster endpoints ([https://172.17.0.6:2379/ https://172.17.0.4:2379/ https://172.17.0.3:2379/]) are available 1/10
[upgrade/etcd] Etcd was rolled back and is now available
static Pod hash for component etcd on Node kinder-upgrade-control-plane-1 did not change after 5m0s: timed out waiting for the condition
couldn't upgrade control plane. kubeadm has tried to recover everything into the earlier state. Errors faced
k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade.rollbackOldManifests
cmd/kubeadm/app/phases/upgrade/staticpods.go:525
k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade.upgradeComponent
cmd/kubeadm/app/phases/upgrade/staticpods.go:254
k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade.performEtcdStaticPodUpgrade
cmd/kubeadm/app/phases/upgrade/staticpods.go:338
...
이 실패의 이유는 영향을 받는 버전이 PodSpec에 원하지 않는 기본값을 사용하여
etcd 매니페스트 파일을 생성하기 때문이다. 이로 인해 매니페스트 비교에서 차이가 발생하고
kubeadm은 파드 해시의 변경을 기대하지만 kubelet은 해시를 업데이트하지 않는다.
클러스터에서 이 문제가 표시되는 경우 이를 해결하는 두 가지 방법이 있다.
영향을 받는 버전과 v1.28.3(또는 이후 버전) 사이에서 etcd 업그레이드를 건너뛸 수 있다.
kubeadm upgrade {apply|node} [version] --etcd-upgrade=false
이는 나중의 v1.28 패치 버전에서 새 etcd 버전이 도입된 경우 권장되지 않는다.
업그레이드하기 전에 etcd 정적 파드의 매니페스트를 패치하여 문제가 있는 기본 속성을 제거한다.
diff --git a/etc/kubernetes/manifests/etcd_defaults.yaml b/etc/kubernetes/manifests/etcd_origin.yaml
index d807ccbe0aa..46b35f00e15 100644
--- a/etc/kubernetes/manifests/etcd_defaults.yaml
+++ b/etc/kubernetes/manifests/etcd_origin.yaml
@@ -43,7 +43,6 @@ spec:
scheme: HTTP
initialDelaySeconds: 10
periodSeconds: 10
- successThreshold: 1
timeoutSeconds: 15
name: etcd
resources:
@@ -59,26 +58,18 @@ spec:
scheme: HTTP
initialDelaySeconds: 10
periodSeconds: 10
- successThreshold: 1
timeoutSeconds: 15
- terminationMessagePath: /dev/termination-log
- terminationMessagePolicy: File
volumeMounts:
- mountPath: /var/lib/etcd
name: etcd-data
- mountPath: /etc/kubernetes/pki/etcd
name: etcd-certs
- dnsPolicy: ClusterFirst
- enableServiceLinks: true
hostNetwork: true
priority: 2000001000
priorityClassName: system-node-critical
- restartPolicy: Always
- schedulerName: default-scheduler
securityContext:
seccompProfile:
type: RuntimeDefault
- terminationGracePeriodSeconds: 30
volumes:
- hostPath:
path: /etc/kubernetes/pki/etcd
이 버그에 대한 자세한 정보는
추적 이슈에서 찾을 수 있다.
2.2.1.3 - 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 alpha
아래의 모든 명령은 정의상 알파 수준에서 지원된다.목표
- 단일 컨트롤 플레인 쿠버네티스 클러스터 설치
- 파드가 서로 통신할 수 있도록 클러스터에 파드
네트워크 설치
지침
호스트 준비
구성 요소 설치
모든 호스트에 컨테이너 런타임과
kubeadm을 설치한다. 자세한 지침과 기타 전제 조건은
kubeadm 설치하기를 참조한다.
참고:
이미 kubeadm을 설치한 경우, kubeadm 업그레이드 방법은
리눅스 노드 업그레이드
문서의 처음 두 단계를 참조한다.
업그레이드할 때 kubelet은 kubeadm이 수행할 작업을 알려줄 때까지 크래시루프(crashloop)에서
대기하면서 몇 초마다 재시작된다. 이 크래시루프는 예상되고 정상적인 동작이다.
컨트롤 플레인을 초기화한 후 kubelet은 정상적으로 실행된다.
네트워크 설정
kubeadm은 다른 쿠버네티스 구성 요소와 마찬가지로 호스트의
기본 게이트웨이와 연결된 네트워크 인터페이스에서 사용 가능한 IP를 찾으려고 시도한다. 그런 다음
이 IP는 구성 요소가 수행하는 광고 및/또는 수신에 사용된다.
리눅스 호스트에서 이 IP가 무엇인지 확인하려면 다음을 사용할 수 있다.
ip route show # "default via"로 시작하는 줄을 찾는다
참고:
호스트에 둘 이상의 기본 게이트웨이가 있는 경우, 쿠버네티스 구성 요소는
적합한 글로벌 유니캐스트 IP 주소를 가진 첫 번째 게이트웨이를 사용하려고 시도한다.
이러한 선택을 할 때 게이트웨이의 정확한 순서는
운영 체제와 커널 버전에 따라 다를 수 있다.쿠버네티스 구성 요소는 사용자 정의 네트워크 인터페이스를 옵션으로 허용하지 않으므로,
이러한 사용자 정의 구성이 필요한 모든 구성 요소 인스턴스에 사용자 정의 IP 주소를
플래그로 전달해야 한다.
참고:
호스트에 기본 게이트웨이가 없고 사용자 정의 IP 주소가
쿠버네티스 구성 요소에 전달되지 않으면, 구성 요소가 오류와 함께 종료될 수 있다.init
과 join
모두로 생성된 컨트롤 플레인 노드에 대한 API 서버 광고(advertise) 주소를
구성하려면 --apiserver-advertise-address
플래그를 사용할 수 있다.
선호하는 방법은 이 옵션을 kubeadm API에서
InitConfiguration.localAPIEndpoint
및 JoinConfiguration.controlPlane.localAPIEndpoint
로 설정하는 것이다.
모든 노드의 kubelet의 경우, kubeadm
구성 파일(InitConfiguration
또는 JoinConfiguration
)내의
.nodeRegistration.kubeletExtraArgs
에서 --node-ip
옵션을 전달할 수 있다.
듀얼 스택의 경우
kubeadm을 사용한 듀얼 스택 지원을 참조한다.
컨트롤 플레인 구성 요소에 할당하는 IP 주소는 X.509 인증서의 주체
대체 이름 필드의 일부가 된다. 이러한 IP 주소를 변경하려면
새 인증서에 서명하고 영향을 받는 구성 요소를 재시작하여 인증서 파일의 변경
사항이 반영되도록 해야 한다. 이 주제에 대한 자세한 내용은
수동 인증서 갱신을
참조한다.
경고:
쿠버네티스 프로젝트는 이 접근 방식(사용자 정의 IP 주소로 모든 구성 요소 인스턴스를 구성)을
권장하지 않는다. 대신 쿠버네티스 관리자는 기본 게이트웨이 IP가 쿠버네티스 구성 요소가 자동 감지하고
사용하는 IP가 되도록 호스트 네트워크를 설정하는 것을 권장한다.
리눅스 노드에서는 ip route
와 같은 명령을 사용하여 네트워킹을 구성할 수 있으며, 운영
체제에서 더 높은 수준의 네트워크 관리 도구를 제공할 수도 있다. 노드의 기본 게이트웨이가
퍼블릭 IP 주소인 경우, 노드와 클러스터를 보호하는 패킷 필터링 또는 기타
보안 조치를 구성해야 한다.필요한 컨테이너 이미지 준비
이 단계는 선택 사항이며, 노드에서 인터넷 연결 없이 클러스터를 생성할 때 kubeadm init
및 kubeadm join
이
registry.k8s.io
에 호스팅된 기본 컨테이너 이미지를 다운로드하지 않도록 하려는 경우에만 적용된다.
kubeadm에는 인터넷 연결 없이 클러스터를 생성할 때 필요한 이미지를
미리 가져오는 데 도움이 되는 명령이 있다.
자세한 내용은 인터넷 연결 없이 kubeadm 실행을
참조한다.
kubeadm을 사용하면 필요한 이미지에 대해 사용자 정의 이미지 저장소를 사용할 수 있다. 자세한 내용은
사용자 정의 이미지 사용을
참조한다.
컨트롤 플레인 노드 초기화
컨트롤 플레인 노드는 etcd
(클러스터 데이터베이스) 및
API 서버
(kubectl 명령줄 도구가 통신하는)를
포함한 컨트롤 플레인 구성 요소가 실행되는 머신이다.
- (권장) 이 단일 컨트롤 플레인
kubeadm
클러스터를
고가용성으로
업그레이드할 계획이 있다면, 모든 컨트롤 플레인 노드에 대한 공유 엔드포인트를 설정하기 위해 --control-plane-endpoint
를 지정해야 한다.
이러한 엔드포인트는 로드 밸런서의 DNS 이름 또는 IP 주소일 수 있다. - 파드 네트워크 애드온(add-on)을 선택하고,
kubeadm init
에 전달해야 하는 인수가 있는지 확인한다. 선택한
서드파티 공급자에 따라 --pod-network-cidr
을
공급자별 값으로 설정해야 할 수 있다. 파드 네트워크 애드온 설치를 참조한다. - (선택 사항)
kubeadm
은 잘 알려진 엔드포인트 목록을 사용하여 컨테이너 런타임을
감지하려고 시도한다. 다른 컨테이너 런타임을 사용하거나 프로비저닝된
노드에 둘 이상이 설치된 경우 kubeadm
에 --cri-socket
인수를 지정한다.
런타임 설치를 참조한다.
컨트롤 플레인 노드를 초기화하려면 다음을 실행한다.
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
이 생성하는 kubeconfig 파일 admin.conf
에는
Subject: O = kubeadm:cluster-admins, CN = kubernetes-admin
인증서가 포함되어 있다. kubeadm:cluster-admins
그룹은
내장 cluster-admin
ClusterRole에 바인딩된다.
admin.conf
파일을 누구와도 공유하지 않는다.
kubeadm init
은 Subject: O = system:masters, CN = kubernetes-super-admin
인증서가
포함된 또 다른 kubeconfig 파일 super-admin.conf
를 생성한다.
system:masters
는 권한 부여 계층(예: RBAC)을 우회하는 긴급 수퍼 사용자 그룹이다.
super-admin.conf
파일을 누구와도 공유하지 않는다. 파일을 안전한 위치로 이동하는 것을 권장한다.
추가 사용자를 위한 kubeconfig 파일을 생성하기 위해
kubeadm kubeconfig user
를 사용하는 방법은
추가 사용자를 위한 kubeconfig 파일 생성을 참조한다.
kubeadm init
이 출력하는 kubeadm join
명령을 기록해 둔다.
클러스터에 노드를 추가하려면 이 명령이 필요하다.
토큰은 컨트롤 플레인 노드와 추가되는 노드 간의 상호 인증에 사용된다.
여기에 포함된 토큰은 비밀(secret)이다. 이 토큰을 안전하게 보관한다. 이 토큰을 가진 사람은 누구나
클러스터에 인증된 노드를 추가할 수 있기 때문이다. 이러한 토큰은
kubeadm token
명령으로 나열, 생성 및 삭제할 수 있다.
kubeadm 참조 가이드를 참조한다.
파드 네트워크 애드온 설치
주의:
이 섹션에는 네트워킹 설정 및 배포 순서에 대한 중요한
정보가 포함되어 있다.
진행하기 전에 이 모든 조언을 주의 깊게 읽어보자.
파드가 서로 통신할 수 있도록
컨테이너 네트워크 인터페이스
(CNI) 기반 파드 네트워크 애드온을 배포해야 한다.
네트워크가 설치되기 전에는 클러스터 DNS(CoreDNS)가 시작되지 않는다.
파드 네트워크가 호스트 네트워크와 겹치지 않도록
주의한다. 겹치는 부분이 있으면 문제가 발생할 가능성이 높다.
(네트워크 플러그인의 선호 파드 네트워크와 일부 호스트
네트워크 간에 충돌을 발견한 경우, 대신 사용할 적절한
CIDR 블록을 생각한 다음 kubeadm init
중에
--pod-network-cidr
과 함께 사용하고 네트워크 플러그인의 YAML에서 대체해야 한다.)
기본적으로 kubeadm
은
RBAC(역할 기반 액세스
제어) 사용을 설정하고 시행한다.
파드 네트워크 플러그인이 RBAC를 지원하는지, 그리고 배포에 사용하는 매니페스트도
지원하는지 확인한다.
클러스터에 IPv6(듀얼 스택 또는 단일 스택 IPv6 전용 네트워킹)를
사용하려면 파드 네트워크 플러그인이
IPv6를 지원하는지 확인한다.
IPv6 지원은 CNI v0.6.0에 추가되었다.
참고:
Kubeadm은 CNI에 구애받지 않아야 하며 CNI 공급자 검증은 현재 e2e 테스트 범위를 벗어난다.
CNI 플러그인과 관련된 문제를 발견하면 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
참고:
위의 예시는 루트에 대해 SSH 액세스가 활성화되어 있다고 가정한다. 그렇지 않은 경우
admin.conf
파일을 다른 사용자가 액세스할 수 있도록 복사하고 대신 해당 사용자를
사용하여 scp
할 수 있다.
admin.conf
파일은 사용자에게 클러스터에 대한 수퍼유저(superuser) 권한을 부여한다.
이 파일은 드물게 사용해야 한다. 일반 사용자의 경우 권한을 부여할
고유한 자격 증명을 생성하는 것이 좋다.
kubeadm kubeconfig user --client-name <CN>
명령으로 이 작업을 수행할 수 있다.
이 명령은 KubeConfig 파일을 STDOUT으로 출력하며,
이를 파일에 저장하고 사용자에게 배포해야 한다. 그런 다음
kubectl create (cluster)rolebinding
을 사용하여 권한을 부여한다.
(선택 사항) 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
이 설치한 상태를 재설정한다.
재설정 프로세스는 iptables 규칙이나 IPVS 테이블을 재설정하거나 정리하지 않는다.
iptables를 재설정하려면 수동으로 수행해야 한다.
iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X
IPVS 테이블을 재설정하려면 다음 명령을 실행해야 한다.
이제 노드를 제거한다.
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 데이터베이스가 실행되는 단일 컨트롤 플레인
노드가 있다. 즉, 컨트롤 플레인 노드가 실패하면 클러스터가 데이터를 잃을 수 있으며
처음부터 다시 생성해야 할 수 있다.
해결 방법:
kubeadm deb/rpm 패키지와 바이너리는
멀티 플랫폼 제안에 따라 amd64, arm(32비트), arm64, ppc64le 및 s390x용으로 빌드된다.
컨트롤 플레인 및 애드온용 멀티 플랫폼 컨테이너 이미지도 v1.12부터 지원된다.
일부 네트워크 공급자만 모든 플랫폼에 대한 솔루션을 제공한다. 공급자가
선택한 플랫폼을 지원하는지 확인하려면 위의 네트워크 공급자 목록이나
각 공급자의 문서를 참조한다.
문제 해결
kubeadm에 문제가 발생하면
문제 해결 문서를 참조한다.
다음 내용
피드백
2.2.1.4 - kubeadm API로 컴포넌트 사용자 정의하기
이 페이지는 kubeadm이 배포하는 컴포넌트(component)들을 사용자 정의하는 방법을 다룬다. 컨트롤 플레인 컴포넌트에
대해서는 Cluster Configuration
구조에서 플래그를 사용하거나 노드당 패치를 사용할 수 있다. kubelet과
kube-proxy의 경우, KubeletConfiguration
과 KubeProxyConfiguration
을 각각 사용할 수 있다.
이 모든 옵션이 kubeadm 구성 API를 통해 가용하다.
구성의 각 필드 상세 사항은
API 참조 페이지에서 찾아볼 수 있다.
참고:
kubeadm의 CoreDNS 디플로이먼트 사용자 정의는 현재 제공되지 않는다.
kube-system/coredns
컨피그맵을 수동으로
패치하고, 그 이후에 CoreDNS
파드를 다시 생성해야 한다. 또는,
기본 CoreDNS 디플로이먼트를 생략하고 자체 변형(variant)을 배포할 수 있다.
더 자세한 사항은
kubeadm에서 초기화 단계 사용하기을 참고한다.
ClusterConfiguration
의 플래그로 컨트롤 플레인 사용자 정의하기
kubeadm의 ClusterConfiguration
오브젝트는 API 서버, 컨트롤러매니저, 스케줄러, Etcd와 같은 컨트롤 플레인 컴포넌트에 전달되는
기본 플래그를 사용자가 덮어쓸 수 있도록 노출한다.
이 컴포넌트는 다음 구조체를 사용하여 정의된다.
apiServer
controllerManager
scheduler
etcd
이 구조체들은 공통 필드인 extraArgs
를 포함하며, 이 필드는 키: 값
쌍으로 구성된다.
컨트롤 플레인 컴포넌트를 위한 플래그를 덮어쓰려면 다음을 수행한다.
- 사용자 구성에 적절한
extraArgs
필드를 추가한다. extraArgs
필드에 플래그를 추가한다.kubeadm init
에 --config <CONFIG YAML 파일>
파라미터를 추가해서 실행한다.
참고:
kubeadm config print init-defaults
를 실행하고 원하는 파일에 출력을
저장하여 기본값들로 구성된 ClusterConfiguration
오브젝트를 생성할 수 있다.참고:
ClusterConfiguration
오브젝트는 현재 kubeadm 클러스터에서 전역(global)으로 사용된다. 즉, 사용자가 추가하는 모든 플래그는
다른 노드에 있는 동일한 컴포넌트에도 모두 적용될 것이다. 다른 노드에서
컴포넌트별로 개별 구성을 적용하려면
패치를 사용하면 된다.
참고:
플래그(키)를 복제하거나 동일한 플래그
--foo
를 여러 번 전달하는 것은 현재 지원하지 않는다.
이 문제를 해결하려면
패치를 사용해야 한다.
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을 사용하면 패치 파일이 있는 디렉토리를 개별 노드에 대한 InitConfiguration
과 JoinConfiguration
에
전달할 수 있다. 이 패치는 컴포넌트 구성이 디스크에 기록되기 전에 최종 사용자 정의 단계로
사용될 수 있다.
--config <YOUR CONFIG YAML>
을 사용하여 이 파일을 kubeadm init
에 전달할 수 있다.
apiVersion: kubeadm.k8s.io/v1beta3
kind: InitConfiguration
patches:
directory: /home/user/somedir
참고:
kubeadm init
의 경우, ---
로 구분된 ClusterConfiguration
과 InitConfiguration
을 모두
포함하는 파일을 전달할 수 있다.--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
의 형태이다.
target
은 kube-apiserver
, kube-controller-manager
, kube-scheduler
, etcd
그리고 kubeletconfiguration
중 하나가 될 수 있다.patchtype
은 strategic
, merge
그리고 json
중 하나가 될 수 있으며
kubectl에서 지원하는 패치 형식을 준수해야 한다.
patchtype
의 기본값은 strategic
이다.extension
은 json
또는 yaml
중 하나여야 한다.suffix
는 어떤 패치가 먼저 적용되는지를 결정하는 데 사용할 수 있는 영숫자 형태의
선택적 문자열이다.
참고:
kubeadm upgrade
를 사용하여 kubeadm 노드를 업그레이드하는 경우, 업그레이드 이후에도
사용자 정의를 유지하려면 동일한 패치를 다시 제공해야 한다. 이는 동일한 디렉토리로 지정된 --patches
플래그를 사용하여 처리할 수 있다. kubeadm upgrade
는 동일 목적으로 재사용할 수 있는 구성
API 구조를 현재는 지원하지 않는다.kubelet 사용자 정의하기
kubelet을 사용자 정의하려면, KubeletConfiguration
을
동일한 구성 파일 내에서 ---
로 구분된 ClusterConfiguration
이나 InitConfiguration
다음에 추가하면 된다.
그런 다음 kubeadm init
에 해당 파일을 전달하면, kubeadm은 동일한 기본 KubeletConfiguration
을
클러스터의 모든 노드에 적용한다.
기본 KubeletConfiguration
에 더하여 인스턴스별 구성을 적용하기 위해서는
kubeletconfiguration
패치 target을 이용할 수 있다.
다른 방법으로는, kubelet 플래그를 덮어쓰기(overrides)로 사용하여,
InitConfiguration
및 JoinConfiguration
모두에서 지원되는 nodeRegistration.kubeletExtraArgs
에 전달할 수 있다.
일부 kubelet 플래그는 더 이상 사용되지 않는다(deprecated). 따라서 사용하기 전에
kubelet 참조 문서를 통해 상태를 확인해야 한다.
이 외 더 자세한 사항은 kubeadm을 통해 클러스터의 각 kubelet 구성하기에서 살펴본다.
kube-proxy 사용자 정의하기
kube-proxy를 사용자 정의하려면, KubeProxyConfiguration
을 ---
로 구분된 ClusterConfiguration
이나 InitConfiguration
다음에 두고 kubeadm init
에 전달하면 된다.
자세한 사항은 API 참조 페이지에서 살펴볼 수 있다.
참고:
kubeadm은 kube-proxy를
데몬셋으로 배포한다. 이것은
KubeProxyConfiguration
이 클러스터의 모든 kube-proxy 인스턴스에 적용된다는 것을 의미한다.
2.2.1.5 - 고가용성 토폴로지 선택
이 페이지는 고가용성(HA) 쿠버네티스 클러스터의 토플로지를 구성하는 두 가지 선택 사항을 설명한다.
다음과 같이 HA 클러스터를 구성할 수 있다.
- etcd 노드와 컨트롤 플레인 노드를 함께 위치시키는 중첩된(stacked) 컨트롤 플레인 노드 방식
- etcd와 컨트롤 플레인이 분리된 노드에서 운영되는 외부 etcd 노드 방식
HA 클러스터를 구성하기 전에 각 토플로지의 장단점을 주의 깊게 고려해야 한다.
참고:
kubeadm은 etcd 클러스터를 정적으로 부트스트랩한다. 자세한 내용은 etcd
클러스터 구성 가이드
를 읽는다.
중첩된 etcd 토플로지
중첩된 HA 클러스터는 etcd에서 제공하는 분산 데이터 저장소 클러스터를,
컨트롤 플레인 구성 요소를 실행하는 kubeadm으로 관리되는 노드에 의해서 형성된 클러스터 상단에
중첩하는 토플로지이다.
각 컨트롤 플레인 노드는 kube-apiserver
, kube-scheduler
, kube-controller-manager
인스턴스를 운영한다.
kube-apiserver
는 로드 밸런서를 이용하여 워커 노드에 노출되어 있다.
각 컨트롤 플레인 노드는 지역 etcd 맴버를 생성하고
이 etcd 맴버는 오직 해당 노드의 kube-apiserver
와 통신한다.
비슷한 방식이 지역의 kube-controller-manager
와 kube-scheduler
에도 적용된다.
이 토플로지는 컨트롤 플레인과 etcd 맴버가 같은 노드에 묶여 있다.
이는 외부 etcd 노드의 클러스터를 구성하는 것보다는 단순하며 복제 관리도 간단하다.
그러나 중첩된 클러스터는 커플링에 실패할 위험이 있다. 한 노드가 다운되면 etcd 맴버와 컨트롤 플레인을 모두 잃어버리고,
중복성도 손상된다. 더 많은 컨트롤 플레인 노드를 추가하여 이 위험을 완화할 수 있다.
그러므로 HA 클러스터를 위해 최소 3개인 중첩된 컨트롤 플레인 노드를 운영해야 한다.
이는 kubeadm의 기본 토플로지이다. 지역 etcd 맴버는
kubeadm init
와 kubeadm join --control-plane
을 이용할 때에 컨트롤 플레인 노드에 자동으로 생성된다.

외부 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 노드가 필요하다.

다음 내용
2.3 - 턴키 클라우드 솔루션
이 페이지는 인증된 쿠버네티스 솔루션 제공자 목록을 제공한다. 각 제공자
페이지를 통해서, 프로덕션에 준비된 클러스터를 설치 및 설정하는 방법을
학습할 수 있다.
3 - 모범 사례
3.1 - 대형 클러스터에 대한 고려 사항
클러스터는 컨트롤 플레인에서 관리하는
쿠버네티스 에이전트를 실행하는 노드(물리
또는 가상 머신)의 집합이다.
쿠버네티스 v1.34는 노드 5,000개까지의 클러스터를 지원한다. 보다 정확하게는,
쿠버네티스는 다음 기준을 모두 만족하는 설정을 수용하도록 설계되었다.
- 노드 당 파드 110 개 이하
- 노드 5,000개 이하
- 전체 파드 150,000개 이하
- 전체 컨테이너 300,000개 이하
노드를 추가하거나 제거하여 클러스터를 확장할 수 있다. 이를 수행하는 방법은
클러스터 배포 방법에 따라 다르다.
클라우드 프로바이더 리소스 쿼터
여러 노드를 가지는 클러스터를 만들 때, 클라우드 프로바이더 쿼터 이슈를 피하기 위해
고려할 점은 다음과 같다.
- 다음과 같은 클라우드 리소스에 대한 쿼터 증가를 요청한다.
- 컴퓨터 인스턴스
- CPU
- 스토리지 볼륨
- 사용 중인 IP 주소
- 패킷 필터링 규칙 세트
- 로드밸런서 개수
- 로그 스트림
- 일부 클라우드 프로바이더는 새로운 인스턴스 생성 속도에 상한이 있어, 클러스터 확장 작업 간 새로운 노드를 일괄적으로 배치하고, 배치 간에 일시 중지한다.
컨트롤 플레인 컴포넌트
대규모 클러스터의 경우, 충분한 컴퓨트 및 기타 리소스가 있는 컨트롤 플레인이
필요하다.
일반적으로 장애 영역 당 하나 또는 두 개의 컨트롤 플레인 인스턴스를
실행하고, 해당 인스턴스를 수직으로(vertically) 먼저 확장한 다음 (수직) 규모로 하락하는
지점에 도달한 후 수평으로(horizontally) 확장한다.
내결함성을 제공하려면 장애 영역 당 하나 이상의 인스턴스를 실행해야 한다. 쿠버네티스
노드는 동일한 장애 영역에 있는 컨트롤 플레인 엔드포인트로 트래픽을
자동으로 조정하지 않는다. 그러나, 클라우드 프로바이더는 이를 수행하기 위한 자체 메커니즘을 가지고 있을 수 있다.
예를 들어, 관리형 로드 밸런서를 사용하여 장애 영역 A 의
kubelet 및 파드에서 시작되는 트래픽을 전송하도록 로드 밸런서를 구성하고, 해당 트래픽을
A 영역에 있는 컨트롤 플레인 호스트로만 전달한다. 단일 컨트롤 플레인 호스트 또는
엔드포인트 장애 영역 A 이 오프라인이 되면, 영역 A 의 노드에 대한
모든 컨트롤 플레인 트래픽이 이제 영역간에 전송되고 있음을 의미한다. 각 영역에서 여러 컨트롤 플레인 호스트를
실행하면 가용성이 낮아진다.
etcd 저장소
큰 클러스터의 성능 향상을 위해, 사용자는 이벤트 오브젝트를 각각의
전용 etcd 인스턴스에 저장한다.
클러스터 생성시의 부가 스트립트이다.
클러스터 생성 시에 (사용자 도구를 사용하여) 다음을 수행할 수 있다.
쿠버네티스를 위한 etcd 클러스터 운영하기와
kubeadm을 이용하여 고가용성 etcd 생성하기에서
큰 클러스터를 위한 etcd를 설정하고 관리하는 방법에 대한 상세 사항을 확인한다.
애드온 리소스
쿠버네티스 리소스 제한은
파드와 컨테이너가 다른 컴포넌트에 영향을 줄 수 있는 메모리 누수 및 기타 방식의 영향을
최소화하는 데 도움이 된다. 이러한 리소스 제한은 애플리케이션 워크로드에 적용될 수 있는 것처럼
애드온 리소스에도 적용될 수 있다.
예를 들어, 로깅 컴포넌트에 대한 CPU 및 메모리 제한을 설정할 수 있다.
...
containers:
- name: fluentd-cloud-logging
image: fluent/fluentd-kubernetes-daemonset:v1
resources:
limits:
cpu: 100m
memory: 200Mi
애드온의 기본 제한은 일반적으로 중소형 쿠버네티스 클러스터에서
각 애드온을 실행한 경험에서 수집된 데이터를 기반으로 한다. 대규모 클러스터에서
실행할 때, 애드온은 종종 기본 제한보다 많은 리소스를 소비한다.
이러한 값을 조정하지 않고 대규모 클러스터를 배포하면, 애드온이
메모리 제한에 계속 도달하기 때문에 지속적으로 종료될 수 있다.
또는, 애드온이 실행될 수 있지만 CPU 시간 슬라이스 제한으로 인해
성능이 저하된다.
클러스터 애드온 리소스 문제가 발생하지 않도록, 노드가 많은 클러스터를
만들 때, 다음 사항을 고려한다.
- 일부 애드온은 수직으로 확장된다. 클러스터 또는 전체 장애 영역을
제공하는 애드온 레플리카가 하나 있다. 이러한 애드온의 경우, 클러스터를 확장할 때
요청과 제한을 늘린다.
- 많은 애드온은 수평으로 확장된다. 더 많은 파드를 실행하여 용량을 추가하지만,
매우 큰 클러스터에서는 CPU 또는 메모리 제한을 약간 높여야 할 수도 있다.
VerticalPodAutoscaler는 recommender 모드에서 실행되어 요청 및 제한에 대한
제안 수치를 제공할 수 있다.
- 일부 애드온은 데몬셋(DaemonSet)에 의해 제어되는 노드 당 하나의 복사본으로 실행된다(예: 노드 수준 로그 수집기). 수평
확장 애드온의 경우와 유사하게, CPU 또는 메모리 제한을 약간 높여야
할 수도 있다.
다음 내용
VerticalPodAutoscaler
는 리소스 요청 및 파드 제한을 관리하는 데 도움이 되도록
클러스터에 배포할 수 있는 사용자 정의 리소스이다.
클러스터에 중요한 애드온을 포함하여 클러스터 컴포넌트를 확장하는 방법에 대한
자세한 내용은 Vertical Pod Autoscaler를
방문하여 배워본다.
클러스터 오토스케일러는
여러 클라우드 프로바이더와 통합되어 클러스터의 리소스 요구 수준에 맞는
노드 수를 실행할 수 있도록 도와준다.
addon resizer는
클러스터 스케일이 변경될 때 자동으로 애드온 크기를 조정할 수 있도록 도와준다.
3.2 - 여러 영역에서 실행
이 페이지에서는 여러 영역에서 쿠버네티스를 실행하는 방법을 설명한다.
배경
쿠버네티스는 단일 쿠버네티스 클러스터가 여러 장애 영역에서
실행될 수 있도록 설계되었다. 일반적으로 이러한 영역은 지역(region) 이라는
논리적 그룹 내에 적합하다. 주요 클라우드 제공자는 지역을 일관된 기능 집합을
제공하는 장애 영역 집합(가용성 영역 이라고도 함)으로
정의한다. 지역 내에서 각 영역은 동일한 API 및
서비스를 제공한다.
일반적인 클라우드 아키텍처는 한 영역의 장애가 다른 영역의 서비스도
손상시킬 가능성을 최소화하는 것을 목표로 한다.
컨트롤 플레인 동작
모든 컨트롤 플레인 컴포넌트는
컴포넌트별로 복제되는 교환 가능한 리소스 풀로 실행을
지원한다.
클러스터 컨트롤 플레인을 배포할 때, 여러 장애 영역에
컨트롤 플레인 컴포넌트의 복제본을 배치한다. 가용성이
중요한 문제인 경우, 3개 이상의 장애 영역을 선택하고
각 개별 컨트롤 플레인 컴포넌트(API 서버, 스케줄러, etcd,
클러스터 컨트롤러 관리자)를 3개 이상의 장애 영역에 복제한다.
클라우드 컨트롤러 관리자를 실행 중인 경우 선택한
모든 장애 영역에 걸쳐 이를 복제해야 한다.
참고:
쿠버네티스는 API 서버 엔드포인트에 대한 교차 영역 복원성을 제공하지
않는다. DNS 라운드-로빈, SRV 레코드 또는 상태 확인 기능이 있는
써드파티 로드 밸런싱 솔루션을 포함하여 다양한 기술을 사용하여
클러스터 API 서버의 가용성을 향상시킬 수 있다.노드 동작
쿠버네티스는 클러스터의 여러 노드에 걸쳐
워크로드 리소스(예: 디플로이먼트(Deployment)
또는 스테이트풀셋(StatefulSet))에
대한 파드를 자동으로 분배한다. 이러한 분배는
실패에 대한 영향을 줄이는 데 도움이 된다.
노드가 시작되면, 각 노드의 kubelet이 쿠버네티스 API에서
특정 kubelet을 나타내는 노드 오브젝트에
레이블을 자동으로 추가한다.
이러한 레이블에는
영역 정보가 포함될 수 있다.
클러스터가 여러 영역 또는 지역에 걸쳐있는 경우,
파드 토폴로지 분배 제약 조건과
함께 노드 레이블을 사용하여
파드가 장애 도메인(지역, 영역, 특정 노드) 간 클러스터에
분산되는 방식을 제어할 수 있다.
이러한 힌트를 통해
스케줄러는
더 나은 예상 가용성을 위해 파드를 배치할 수 있으므로, 상관 관계가 있는
오류가 전체 워크로드에 영향을 미칠 위험을 줄일 수 있다.
예를 들어, 가능할 때마다 스테이트풀셋의
3개 복제본이 모두 서로 다른 영역에서 실행되도록 제약 조건을
설정할 수 있다. 각 워크로드에 사용 중인
가용 영역을 명시적으로 정의하지 않고 이를 선언적으로
정의할 수 있다.
여러 영역에 노드 분배
쿠버네티스의 코어는 사용자를 위해 노드를 생성하지 않는다. 사용자가 직접 수행하거나,
클러스터 API와 같은 도구를 사용하여
사용자 대신 노드를 관리해야 한다.
클러스터 API와 같은 도구를 사용하면 여러 장애 도메인에서
클러스터의 워커 노드로 실행할 머신 집합과 전체 영역 서비스 중단 시
클러스터를 자동으로 복구하는 규칙을 정의할 수 있다.
파드에 대한 수동 영역 할당
생성한 파드와 디플로이먼트, 스테이트풀셋, 잡(Job)과
같은 워크로드 리소스의 파드 템플릿에 노드 셀렉터 제약 조건을
적용할 수 있다.
영역에 대한 스토리지 접근
퍼시스턴트 볼륨이 생성되면, PersistentVolumeLabel
어드미션 컨트롤러는
특정 영역에 연결된 모든 퍼시스턴트볼륨(PersistentVolume)에 영역 레이블을 자동으로
추가한다. 그런 다음 스케줄러는
NoVolumeZoneConflict
프레디케이트(predicate)를 통해 주어진 퍼시스턴트볼륨을 요구하는 파드가
해당 볼륨과 동일한 영역에만 배치되도록 한다.
해당 클래스의 스토리지가 사용할 수 있는 장애 도메인(영역)을 지정하는
퍼시스턴트볼륨클레임(PersistentVolumeClaims)에 대한
스토리지클래스(StorageClass)를 지정할 수 있다.
장애 도메인 또는 영역을 인식하는 스토리지클래스 구성에 대한 자세한 내용은
허용된 토폴로지를 참고한다.
네트워킹
쿠버네티스가 스스로 영역-인지(zone-aware) 네트워킹을 포함하지는 않는다.
네트워크 플러그인을
사용하여 클러스터 네트워킹을 구성할 수 있으며, 해당 네트워크 솔루션에는 영역별 요소가
있을 수 있다. 예를 들어, 클라우드 제공자가
type=LoadBalancer
를 사용하여 서비스를 지원하는 경우, 로드 밸런서는 지정된 연결을 처리하는
로드 밸런서 요소와 동일한 영역에서 실행 중인 파드로만 트래픽을 보낼 수 있다.
자세한 내용은 클라우드 제공자의 문서를 확인한다.
사용자 정의 또는 온-프레미스 배포의 경우, 비슷한 고려 사항이 적용된다.
다른 장애 영역 처리를 포함한 서비스와
인그레스(Ingress) 동작은
클러스터가 설정된 방식에 명확히 의존한다.
장애 복구
클러스터를 설정할 때, 한 지역의 모든 장애 영역이 동시에
오프라인 상태가 되는 경우 설정에서 서비스를 복원할 수 있는지
여부와 방법을 고려해야 할 수도 있다. 예를 들어, 영역에서 파드를 실행할 수 있는
노드가 적어도 하나 이상 있어야 하는가?
클러스터에 중요한 복구 작업이 클러스터에
적어도 하나 이상의 정상 노드에 의존하지 않는지 확인한다. 예를 들어, 모든 노드가
비정상인 경우, 하나 이상의 노드를 서비스할 수 있을 만큼 복구를 완료할 수 있도록 특별한
톨러레이션(toleration)으로
복구 작업을 실행해야 할 수 있다.
쿠버네티스는 이 문제에 대한 답을 제공하지 않는다. 그러나,
고려해야 할 사항이다.
다음 내용
스케줄러가 구성된 제약 조건을 준수하면서, 클러스터에 파드를 배치하는 방법을 알아보려면,
스케줄링과 축출(eviction)을 참고한다.
3.3 - 노드 구성 검증하기
노드 적합성 테스트
노드 적합성 테스트 는 노드의 시스템 검증과 기능 테스트를 제공하기 위해 컨테이너화된
테스트 프레임워크이다.
테스트는 노드가 쿠버네티스를 위한 최소 요구조건을 만족하는지를 검증한다.
그리고 테스트를 통과한 노드는 쿠버네티스 클러스터에 참여할 자격이 주어진다.
노드 필수 구성 요소
노드 적합성 테스트를 실행하기 위해서는,
해당 노드는 표준 쿠버네티스 노드로서 동일한 전제조건을 만족해야 한다.
노드는 최소한 아래 데몬들이 설치되어 있어야 한다.
노드 적합성 테스트 실행
노드 적합성 테스트는 다음 순서로 진행된다.
- kubelet에 대한
--kubeconfig
옵션의 값을 계산한다. 예를 들면, 다음과 같다.
--kubeconfig = / var / lib / kubelet / config.yaml
.
테스트 프레임워크는 kubelet을 테스트하기 위해 로컬 컨트롤 플레인을 시작하기 때문에,
http://localhost:8080
을 API 서버의 URL로 사용한다.
사용할 수 있는 kubelet 커맨드 라인 파라미터가 몇 개 있다.
--cloud-provider
: --cloud-provider=gce
를 사용 중이라면,
테스트 실행 시에는 제거해야 한다.
- 다음 커맨드로 노드 적합성 테스트를 실행한다.
# $CONFIG_DIR는 Kublet의 파드 매니페스트 경로이다.
# $LOG_DIR는 테스트 출력 경로이다.
sudo docker run -it --rm --privileged --net=host \
-v /:/rootfs -v $CONFIG_DIR:$CONFIG_DIR -v $LOG_DIR:/var/result \
registry.k8s.io/node-test:0.2
다른 아키텍처에서 노드 적합성 테스트 실행
쿠버네티스는 다른 아키텍쳐용 노드 적합성 테스트 Docker 이미지도 제공한다.
Arch | Image |
---|
amd64 | node-test-amd64 |
arm | node-test-arm |
arm64 | node-test-arm64 |
선택된 테스트 실행
특정 테스트만 실행하기 위해서는 환경 변수 FOCUS
에 테스트하고자 하는 테스트를 정규식으로 지정한다.
sudo docker run -it --rm --privileged --net=host \
-v /:/rootfs:ro -v $CONFIG_DIR:$CONFIG_DIR -v $LOG_DIR:/var/result \
-e FOCUS=MirrorPod \ # MirrorPod 테스트만 실행
registry.k8s.io/node-test:0.2
특정 테스트를 건너뛰기 위해서는, 환경 변수 SKIP
에 건너뛰고자 하는 테스트를 정규식으로 지정한다.
sudo docker run -it --rm --privileged --net=host \
-v /:/rootfs:ro -v $CONFIG_DIR:$CONFIG_DIR -v $LOG_DIR:/var/result \
-e SKIP=MirrorPod \ # MirrorPod 테스트만 건너뛰고 모든 적합성 테스트를 실행한다
registry.k8s.io/node-test:0.2
노드 적합성 테스트는 노드 e2e 테스트를 컨테이너화한 버전이다.
기본적으로, 모든 적합성 테스트를 실행한다.
이론적으로, 컨테이너와 필요한 볼륨을 적절히 설정했다면 어떤 노드 e2e 테스트도 수행할 수 있다.
하지만, 적합성 테스트가 아닌 테스트들은 훨씬 복잡한 설정이 필요하기 때문에 적합성 테스트만 실행하기를 강하게 추천한다.
주의 사항
- 테스트 후, 노드 적합성 테스트 이미지 및 기능 테스트에 사용된 이미지들을 포함하여 몇 개의 Docker 이미지들이 노드에 남는다.
- 테스트 후, 노드에 죽은 컨테이너가 남는다. 기능 테스트 도중에 생성된 컨테이너들이다.
3.4 - 파드 시큐리티 스탠다드 강제하기
이 페이지는 파드 시큐리티 스탠다드(Pod Security Standards)를
강제(enforce)하는 모범 사례에 대한 개요를 제공한다.
내장된 파드 시큐리티 어드미션 컨트롤러 사용
기능 상태:
Kubernetes v1.25 [stable]
파드 시큐리티 어드미션 컨트롤러(Pod Security Admission Controller)는
더 이상 사용되지 않는 파드시큐리티폴리시(PodSecurityPolicy)를 대체한다.
모든 클러스터 네임스페이스 구성
구성이 전혀 없는 네임스페이스는 클러스터 시큐리티 모델에서 심각한 틈으로 간주해야
한다. 시간을 들여 각 네임스페이스에서 발생하는 워크로드 유형을 분석하고,
파드 시큐리티 폴리시를 참조하여 각각에 적합한 수준을 결정하는 것을 권장한다.
레이블이 없는 네임스페이스는 아직 평가되지 않았음을 표시해야 한다.
모든 네임스페이스의 모든 워크로드에 동일한 보안 요구 사항이 있는 시나리오에서,
파드 시큐리티 레이블을 대량으로 적용할 수 있는 방법을 보여주는 예시를
제공한다.
최소 권한 원칙 수용
이상적인 경우 모든 네임스페이스의 모든 파드가 제한된
정책의 요구 사항을 충족할
것이다. 그러나 일부 워크로드는 정당한 이유로 승격된 권한(elevated privilege)이 필요하므로 이는
불가능하거나 실용적이지 않다.
권한 있는(privileged)
워크로드를 허용하는 네임스페이스는 적절한 액세스 제어를 설정하고 시행해야 한다.- 허용되는 네임스페이스에서 실행되는 워크로드의 경우, 고유한 보안 요구 사항에
대한 문서를 유지 관리한다. 가능하다면 이러한 요구 사항을 어떻게 더 제한할 수
있는지 고려해야 한다.
다중 모드(multi-mode) 전략 채택
파드 시큐리티 스탠다드 어드미션 컨트롤러의 감사(audit)
및 경고(warn)
모드를 사용하면 기존 워크로드를
중단하지 않고 파드에 대한 중요한 보안 현황을 쉽게 이해할 수 있다.
이러한 모드들을 모든 네임스페이스에 강제(enforce)
하려는 원하는 수준 및 버전으로
설정하는 것이 좋다. 이 단계에서 생성된 경고 및 감사 어노테이션은 해당 상태로
안내할 수 있다. 워크로드 작성자가 원하는 수준에 맞게 변경을 수행할 것으로 예상되는 경우
경고
모드를 활성화한다. 감사 로그를 사용하여 원하는 수준에 맞게 변경 사항을
모니터링/구동하려는 경우 감사
모드를 활성화한다.
강제
모드를 원하는 값으로 설정한 경우 이러한 모드는 몇 가지 다른 방식으로도
유용할 수 있다.
경고
를 강제
와 같은 수준으로 설정하면 클라이언트가 유효성 검사를
통과하지 못한 파드(또는 파드 템플릿이 있는 리소스)를 만들려고 할 때 경고를 받게 된다.
이렇게 하면 규정을 준수하도록 해당 리소스를 업데이트하는 데 도움이 된다.강제
를 최신이 아닌 특정 버전에 고정하는 네임스페이스에서는 감사
및 경고
모드가
강제
와 동일한 수준으로 설정되지만, 최신
버전으로 고정하면 설정(setting) 정보를 볼 수 있다.
이는 이전 버전에서는 허용되지만 현재 모범 사례에서는 허용되지 않는다.
타사(third-party) 대안
참고: 이 섹션은 쿠버네티스에 필요한 기능을 제공하는 써드파티 프로젝트와 관련이 있다. 쿠버네티스 프로젝트 작성자는 써드파티 프로젝트에 책임이 없다. 이 페이지는
CNCF 웹사이트 가이드라인에 따라 프로젝트를 알파벳 순으로 나열한다. 이 목록에 프로젝트를 추가하려면 변경사항을 제출하기 전에
콘텐츠 가이드를 읽어본다.
쿠버네티스 에코시스템에서 보안 프로필을 적용하기 위한 다른 대안이
개발되고 있다.
내장 솔루션(예: 파드 시큐리티 어드미션 컨트롤러)과 타사 도구를
사용할지 여부는 전적으로 사용자의 상황에 달려 있다. 솔루션을 평가할 때
공급망의 신뢰가 중요하다. 궁극적으로 앞서 언급한 접근 방식 중
하나를 사용하는 것이 아무것도 하지 않는 것보다 낫다.
3.5 - PKI 인증서 및 요구 사항
쿠버네티스는 TLS를 통한 인증을 위해서 PKI 인증서가 필요하다.
만약 kubeadm으로 쿠버네티스를 설치한다면, 클러스터에 필요한 인증서는 자동으로 생성된다.
또한 더 안전하게 자신이 소유한 인증서를 생성할 수 있다. 이를 테면, 개인키를 API 서버에 저장하지 않으므로 더 안전하게 보관할 수 있다.
이 페이지는 클러스터가 필요로 하는 인증서에 대해서 설명한다.
클러스터에서 인증서가 이용되는 방식
쿠버네티스는 다음 작업에서 PKI를 필요로 한다.
- kubelet에서 API 서버 인증서를 인증시 사용하는 클라이언트 인증서
- API 서버가 kubelet과 통신하기 위한
kubelet 서버 인증서
- API 서버 엔드포인트를 위한 서버 인증서
- API 서버에 클러스터 관리자 인증을 위한 클라이언트 인증서
- API 서버에서 kubelet과 통신을 위한 클라이언트 인증서
- API 서버에서 etcd 간의 통신을 위한 클라이언트 인증서
- 컨트롤러 매니저와 API 서버 간의 통신을 위한 클라이언트 인증서/kubeconfig
- 스케줄러와 API 서버간 통신을 위한 클라이언트 인증서/kubeconfig
- front-proxy를 위한 클라이언트와 서버 인증서
참고:
front-proxy
인증서는 kube-proxy에서
API 서버 확장을 지원할 때만 kube-proxy에서 필요하다.
etcd 역시 클라이언트와 피어 간에 상호 TLS 인증을 구현한다.
인증서를 저장하는 위치
만약 쿠버네티스를 kubeadm으로 설치했다면, 대부분의 인증서는 /etc/kubernetes/pki
에 저장된다. 이 문서에 언급된 모든 파일 경로는 그 디렉터리에 상대적이나, kubeadm이 /etc/kubernetes
에 저장하는 사용자 어카운트 인증서는 예외이다.
인증서 수동 설정
필요한 인증서를 kubeadm으로 생성하기 싫다면, 단일 루트 CA를 이용하거나 모든 인증서를 제공하여 생성할 수 있다. 소유한 인증기관을 이용해서 생성하는 방법에 대해서는 인증서를 살펴본다.
인증서를 관리하는 방법에 대해서는 kubeadm을 사용한 인증서 관리를 살펴본다.
단일 루트 CA
관리자에 의해 제어되는 단일 루트 CA를 만들 수 있다. 이 루트 CA는 여러 중간 CA를 생성할 수 있고, 모든 추가 생성에 관해서도 쿠버네티스 자체에 위임할 수 있다.
필요 CA:
경로 | 기본 CN | 설명 |
---|
ca.crt,key | kubernetes-ca | 쿠버네티스 일반 CA |
etcd/ca.crt,key | etcd-ca | 모든 etcd 관련 기능을 위해서 |
front-proxy-ca.crt,key | kubernetes-front-proxy-ca | front-end proxy 위해서 |
위의 CA외에도, 서비스 계정 관리를 위한 공개/개인 키 쌍인 sa.key
와 sa.pub
을 얻는 것이 필요하다.
다음은 이전 표에 나온 CA 키와 인증서 파일을 보여준다.
/etc/kubernetes/pki/ca.crt
/etc/kubernetes/pki/ca.key
/etc/kubernetes/pki/etcd/ca.crt
/etc/kubernetes/pki/etcd/ca.key
/etc/kubernetes/pki/front-proxy-ca.crt
/etc/kubernetes/pki/front-proxy-ca.key
모든 인증서
이런 개인키를 API 서버에 복사하기 원치 않는다면, 모든 인증서를 스스로 생성할 수 있다.
필요한 인증서:
기본 CN | 부모 CA | O (주체에서) | 종류 | 호스트 (SAN) |
---|
kube-etcd | etcd-ca | | server, client | <hostname> , <Host_IP> , localhost , 127.0.0.1 |
kube-etcd-peer | etcd-ca | | server, client | <hostname> , <Host_IP> , localhost , 127.0.0.1 |
kube-etcd-healthcheck-client | etcd-ca | | client | |
kube-apiserver-etcd-client | etcd-ca | system:masters | client | |
kube-apiserver | kubernetes-ca | | server | <hostname> , <Host_IP> , <advertise_IP> , [1] |
kube-apiserver-kubelet-client | kubernetes-ca | system:masters | client | |
front-proxy-client | kubernetes-front-proxy-ca | | client | |
[1]: 클러스터에 접속한 다른 IP 또는 DNS 이름(kubeadm이 사용하는
로드 밸런서 안정 IP 또는 DNS 이름, kubernetes
, kubernetes.default
, kubernetes.default.svc
,
kubernetes.default.svc.cluster
, kubernetes.default.svc.cluster.local
)
kind
는 하나 이상의 x509 키 사용 종류를 가진다.
종류 | 키 사용 |
---|
server | digital signature, key encipherment, server auth |
client | digital signature, key encipherment, client auth |
참고:
위에 나열된 호스트/SAN은 작업 중인 클러스터를 획득하는데 권장된다. 특정 설정이 필요한 경우, 모든 서버 인증서에 SAN을 추가할 수 있다.참고:
kubeadm 사용자만 해당:
- 개인 키 없이 클러스터 CA 인증서에 복사하는 시나리오는 kubeadm 문서에서 외부 CA라고 한다.
- 위 목록을 kubeadm이 생성한 PKI와 비교하는 경우,
kube-etcd
, kube-etcd-peer
와 kube-etcd-healthcheck-client
인증서는
외부 etcd 케이스에서는 생성하지 않는 것을 알고 있어야 한다.
인증서 파일 경로
인증서는 권고하는 파일 경로에 존재해야 한다(kubeadm에서 사용되는 것처럼).
경로는 위치에 관계없이 주어진 파라미터를 사용하여 지정해야 한다.
기본 CN | 권고되는 키 파일 경로 | 권고하는 인증서 파일 경로 | 명령어 | 키 파라미터 | 인증서 파라미터 |
---|
etcd-ca | etcd/ca.key | etcd/ca.crt | kube-apiserver | | --etcd-cafile |
kube-apiserver-etcd-client | apiserver-etcd-client.key | apiserver-etcd-client.crt | kube-apiserver | --etcd-keyfile | --etcd-certfile |
kubernetes-ca | ca.key | ca.crt | kube-apiserver | | --client-ca-file |
kubernetes-ca | ca.key | ca.crt | kube-controller-manager | --cluster-signing-key-file | --client-ca-file, --root-ca-file, --cluster-signing-cert-file |
kube-apiserver | apiserver.key | apiserver.crt | kube-apiserver | --tls-private-key-file | --tls-cert-file |
kube-apiserver-kubelet-client | apiserver-kubelet-client.key | apiserver-kubelet-client.crt | kube-apiserver | --kubelet-client-key | --kubelet-client-certificate |
front-proxy-ca | front-proxy-ca.key | front-proxy-ca.crt | kube-apiserver | | --requestheader-client-ca-file |
front-proxy-ca | front-proxy-ca.key | front-proxy-ca.crt | kube-controller-manager | | --requestheader-client-ca-file |
front-proxy-client | front-proxy-client.key | front-proxy-client.crt | kube-apiserver | --proxy-client-key-file | --proxy-client-cert-file |
etcd-ca | etcd/ca.key | etcd/ca.crt | etcd | | --trusted-ca-file, --peer-trusted-ca-file |
kube-etcd | etcd/server.key | etcd/server.crt | etcd | --key-file | --cert-file |
kube-etcd-peer | etcd/peer.key | etcd/peer.crt | etcd | --peer-key-file | --peer-cert-file |
etcd-ca | | etcd/ca.crt | etcdctl | | --cacert |
kube-etcd-healthcheck-client | etcd/healthcheck-client.key | etcd/healthcheck-client.crt | etcdctl | --key | --cert |
서비스 계정 키 쌍에도 동일한 고려 사항이 적용된다.
개인키 경로 | 공개 키 경로 | 명령어 | 파라미터 |
---|
sa.key | | kube-controller-manager | --service-account-private-key-file |
| sa.pub | kube-apiserver | --service-account-key-file |
다음은 키와 인증서를 모두 생성할 때에 제공해야 하는 이전 표에 있는 파일의 경로를 보여준다.
/etc/kubernetes/pki/etcd/ca.key
/etc/kubernetes/pki/etcd/ca.crt
/etc/kubernetes/pki/apiserver-etcd-client.key
/etc/kubernetes/pki/apiserver-etcd-client.crt
/etc/kubernetes/pki/ca.key
/etc/kubernetes/pki/ca.crt
/etc/kubernetes/pki/apiserver.key
/etc/kubernetes/pki/apiserver.crt
/etc/kubernetes/pki/apiserver-kubelet-client.key
/etc/kubernetes/pki/apiserver-kubelet-client.crt
/etc/kubernetes/pki/front-proxy-ca.key
/etc/kubernetes/pki/front-proxy-ca.crt
/etc/kubernetes/pki/front-proxy-client.key
/etc/kubernetes/pki/front-proxy-client.crt
/etc/kubernetes/pki/etcd/server.key
/etc/kubernetes/pki/etcd/server.crt
/etc/kubernetes/pki/etcd/peer.key
/etc/kubernetes/pki/etcd/peer.crt
/etc/kubernetes/pki/etcd/healthcheck-client.key
/etc/kubernetes/pki/etcd/healthcheck-client.crt
/etc/kubernetes/pki/sa.key
/etc/kubernetes/pki/sa.pub
각 사용자 계정을 위한 인증서 설정하기
반드시 이런 관리자 계정과 서비스 계정을 설정해야 한다.
파일명 | 자격증명 이름 | 기본 CN | O (주체에서) |
---|
admin.conf | default-admin | kubernetes-admin | system:masters |
kubelet.conf | default-auth | system:node:<nodeName> (note를 보자) | system:nodes |
controller-manager.conf | default-controller-manager | system:kube-controller-manager | |
scheduler.conf | default-scheduler | system:kube-scheduler | |
참고:
kubelet.conf
을 위한
<nodeName>
값은 API 서버에 등록된 것처럼 kubelet에 제공되는 노드 이름 값과
반드시 정확히 일치해야 한다. 더 자세한 내용은
노드 인증을 살펴보자.
각 환경 설정에 대해 주어진 CN과 O를 이용하여 x509 인증서와 키쌍을 생성한다.
각 환경 설정에 대해 다음과 같이 kubectl
를 실행한다.
KUBECONFIG=<filename> kubectl config set-cluster default-cluster --server=https://<host ip>:6443 --certificate-authority <path-to-kubernetes-ca> --embed-certs
KUBECONFIG=<filename> kubectl config set-credentials <credential-name> --client-key <path-to-key>.pem --client-certificate <path-to-cert>.pem --embed-certs
KUBECONFIG=<filename> kubectl config set-context default-system --cluster default-cluster --user <credential-name>
KUBECONFIG=<filename> kubectl config use-context default-system
이 파일들은 다음과 같이 사용된다.
파일명 | 명령어 | 설명 |
---|
admin.conf | kubectl | 클러스터 관리자를 설정한다. |
kubelet.conf | kubelet | 클러스터 각 노드를 위해 필요하다. |
controller-manager.conf | kube-controller-manager | 반드시 매니페스트를 manifests/kube-controller-manager.yaml 에 추가해야 한다. |
scheduler.conf | kube-scheduler | 반드시 매니페스트를 manifests/kube-scheduler.yaml 에 추가해야 한다. |
다음의 파일은 이전 표에 나열된 파일의 전체 경로를 보여준다.
/etc/kubernetes/admin.conf
/etc/kubernetes/kubelet.conf
/etc/kubernetes/controller-manager.conf
/etc/kubernetes/scheduler.conf