본문 바로가기

Kubenetes/Kubernetes Internal

쿠버네티스 인터널 - 5 (고가용성 클러스터)

1. 앱의 가용성 높이기

 

쿠버네티스에서 앱을 실행할 때 노드가 실패할 경우에도 다양한 컨트롤러가 앱이 지정된 스케일에서 원할하게 실행되도록 한다. 애플리케이션의 가용성을 높이려면 배포 리소스를 통해 애플리케이션을 실행하고 적절한 수의 복제본을 구성하기만 하면 된다.

 

ㅁ 가동 중단 시간을 줄일는 여러가지 실행 방법

 

다운타임을 회피하려면 활성 복제본과 함께 추가 비활성 복제본을 실행하고 빠른 실행 리스 또는 리더 선출 매커니즘을 사용해 하나만 활성 상태인지 확인해야 한다.

리더 선출 매커니즘이 익숙하지 않은 경우 분산 환경에서 실행되는 여러 애플리케이션 인스턴스가 리더가 되는 합의에 도달하는 방법이다.

 

리더는 유일하게 하나의 작업을 수행하는 반면 다른 모든 리더는 리더가 실패하고 리더가 되기를 기다리는 중이다. 또는 리더가 쓰기를 수행하는 유일한 인스턴스이고 다른 모든 리더가 읽기를 제공하는 등 모두 활성화 될 수 있다. 

 

이 메커니즘은 애플리케이션 자체에 통합될 필요가 없다. 모든 리더 선출 작업ㅇ르 수행하고 활성화될 때 메인 컨테이너에 신호를 보내는 사이드카 컨테이너를 사용할 수 있다.

 

쿠버네티스 리더 선출의 예를

 

https://github.com/kubernetes/contrib/tree/master/election 

 

kubernetes-retired/contrib

[EOL] This is a place for various components in the Kubernetes ecosystem that aren't part of the Kubernetes core. - kubernetes-retired/contrib

github.com

에서 찾을 수 있다.

 

 

2. 쿠버네티스 컨트롤 플레인  컴포넌트의 가용성 높이기

 

 ㅇ 모든 API 객체가 보관되는 분산 데이터 스토리지인 etcd

 ㅇ API 서버

 ㅇ 모든 컨트롤러가 실행되는 프로세스인 컨트롤러 매니저

 ㅇ 스케줄러

 

아래는 고가용성 클러스터의 개요다.

 

세 개의 노드를 갖는 고가용성 클러스터

ㅁ etcd 클러스터 실행

 

etcd는 분산 시스템으로 설계됐으므로 주요 기능 중 하나는 여러 개의 etcd 인스턴스를 실행할 수 있기 때문에 가용성을 높이는 것은 그리 어려운 일은 아니다.

 

가용성을 높이는데 필요한 모든 것은 절절한 수의 머신에서 실행하고 서로 인식하도록 하는 것이다. 모든 인스턴스 구성에 있는 다른 모든 인스턴스 목록을 포함시켜 작업을 수행한다. 예를 들어 인스턴스를 시작할 때 다른 etcd 인스턴스에 연결할 수 있는 IP 및 포트를 지정한다.

 

etcd는 모든 인스턴스에서 데이터를 복제하므로 3개 머신 클러스터를 실행할 때 노드 중 하나가 실패해도 클러스터는 읽기 및 쓰기 작업을 모두 허용한다.

 

단일 노드 이상으로 내결함성을 높이려면 클러스터에 2~3개의 노드 장애를 각각 처리할 수 있도록 5~7개의 etcd 노드를 실행해야 한다. 7개 이상의 etcd 인스턴스를 갖는 것은 거의 필요하지 않으며 성능에 영향을 미치기 시작한다.

 

ㅁ API 서버의 여러 인스턴스 실행

 

API 서버의 가용성을 높이는 것은 훨씬 간단하다. API 서버는 상태가 유지 되지 않기 때문에(모든 데이터는 etcd에 저장하지만 API 서버는 이를 캐시만 한다.) 필요한 만큼 API 서버를 실행할 수 있으며 서로를 인지할 필요도 없다.

 

일반적으로 하나의 API 서버가 모든 etcd 인스턴스와 함께 배치된다. 이렇게 하면 모든 API 서버 인스턴스가 로컬 etcd 인스턴스와만 통신하기 때문에 etcd 인스턴스에 로드 밸런서가 필요하지 않다.

 

반면에 API 서버는 로드 밸런서 앞단에 위치해야 하므로 클라이언트(kubectl 뿐만 아니라 컨트롤러 매니저, 스케줄러 및 모든 kubelet)는 항상 정상 API 서버 인스턴스에만 연결 한다.

 

ㅁ 컨트롤러와 스케줄러의 고가용성 확보

 

컨트롤러와 스케줄러는 클러스터의 상태와 행위가 변경될 때 각 컴포넌트의 여러 인스턴스를 실행하면 모두 같은 작업을 수행하게 된다. 서로 경쟁하고 있어 원치 않는 결과를 초래할 수 있다.

 

따라서 이런 컴포넌트의 여러 인스턴스를 실행할 때 한번에 하나의 인스턴스만 활성화 될 수 있다. 이것은 컴포넌트 자체 처리로 가능하다. 각 개별 컴포넌트는 선출된 리더일 때만 활성화된다. 

 

리더만  실제 작업을 수행하지만 모든 인스턴스는 대기 중이며 현재 리더가 실패할 때까지 대기한다. 현재 리더가 실패하면 나머지 인스턴스는 새로운 리더를 선출하고, 그 다음 리더가 작업을 수행한다.  이 매커니즘으로 두 개의 컴포넌트가 동시에 작동하지 않고 동일한 작업을 수행하는 것을 방지한다.

 

단일 컨트롤러 매니저와 단일 스케줄러만 호라성화 되어 있고 다른 것은 대기 상태이다.

 

컨트롤러 매니저 및 스케줄러는 API 서버 및 etcd와 함께 배치하거나 별도의 시스템에서 실행할 수 있다. 함께 배치하면 로컬 API 서버와 직접 통신할 수 있고 그렇지 않으면 로드 밸런서를 통해 API 서버에 연결된다.

 

ㅁ 컨트롤 플레인 컴포넌트에 사용된 리더 선출 매커니즘 이해

 

리더 선출 매커니즘은 API서버에서 리소스를 생성함으로써 순수하게 동작한다. 

 

$ kubectl get endpoints kube-scheduler -n kube-system -o yaml

의 내용에서 

 

metadata:

  annotations:

    control-plane.alpha.kubernetes.io/leader: {"holderIdentity":   ~  

 

위의 control-plane.laph.kubernetes.io/leader 애노테이션에서 holderIdentity라는 필드에 이름을 올리는 데 성공한 첫 번째 인스턴스가 리더가 된다.

 

이 로직은 낙관성 동시성 로직으로 누구난 시도하는 사람 중 첫번째 성공하는 인스턴스가 리더가 되는 로직이다.

일단 리더가 되면 리소스를 주기적(기본적으로 2초 마다)으로 업데이트하여 다른 모든 인스턴스는 리소스가 아직 사랑 있음을 알게 된다.