1 - 커스텀 리소스
커스텀 리소스 는 쿠버네티스 API의 익스텐션이다. 이 페이지에서는 쿠버네티스 클러스터에 커스텀 리소스를 추가할 시기와 독립형 서비스를 사용하는 시기에 대해 설명한다. 커스텀 리소스를 추가하는 두 가지 방법과 이들 중에서 선택하는 방법에 대해 설명한다.
커스텀 리소스
리소스 는 쿠버네티스 API에서 특정 종류의 API 오브젝트 모음을 저장하는 엔드포인트이다. 예를 들어 빌트인 파드 리소스에는 파드 오브젝트 모음이 포함되어 있다.
커스텀 리소스 는 쿠버네티스 API의 익스텐션으로, 기본 쿠버네티스 설치에서 반드시 사용할 수 있는 것은 아니다. 이는 특정 쿠버네티스 설치에 수정이 가해졌음을 나타낸다. 그러나 많은 핵심 쿠버네티스 기능은 이제 커스텀 리소스를 사용하여 구축되어, 쿠버네티스를 더욱 모듈화한다.
동적 등록을 통해 실행 중인 클러스터에서 커스텀 리소스가 나타나거나 사라질 수 있으며 클러스터 관리자는 클러스터 자체와 독립적으로 커스텀 리소스를 업데이트 할 수 있다. 커스텀 리소스가 설치되면 사용자는 파드 와 같은 빌트인 리소스와 마찬가지로 kubectl을 사용하여 해당 오브젝트를 생성하고 접근할 수 있다.
커스텀 컨트롤러
자체적으로 커스텀 리소스를 사용하면 구조화된 데이터를 저장하고 검색할 수 있다. 커스텀 리소스를 커스텀 컨트롤러 와 결합하면, 커스텀 리소스가 진정한 선언적(declarative) API 를 제공하게 된다.
쿠버네티스 선언적 API는 책임의 분리를 강제한다. 사용자는 리소스의 의도한 상태를 선언한다. 쿠버네티스 컨트롤러는 쿠버네티스 오브젝트의 현재 상태가 선언한 의도한 상태에 동기화 되도록 한다. 이는 서버에 무엇을 해야할지 지시하는 명령적인 API와는 대조된다.
클러스터 라이프사이클과 관계없이 실행 중인 클러스터에 커스텀 컨트롤러를 배포하고 업데이트할 수 있다. 커스텀 컨트롤러는 모든 종류의 리소스와 함께 작동할 수 있지만 커스텀 리소스와 결합할 때 특히 효과적이다. 오퍼레이터 패턴은 사용자 정의 리소스와 커스텀 컨트롤러를 결합한다. 커스텀 컨트롤러를 사용하여 특정 애플리케이션에 대한 도메인 지식을 쿠버네티스 API의 익스텐션으로 인코딩할 수 있다.
쿠버네티스 클러스터에 커스텀 리소스를 추가해야 하나?
새로운 API를 생성할 때 쿠버네티스 클러스터 API와 생성한 API를 애그리게이트할 것인지 아니면 생성한 API를 독립적으로 유지할 것인지 고려하자.
API 애그리게이트를 고려할 경우 | 독립 API를 고려할 경우 |
---|---|
API가 선언적이다. | API가 선언적 모델에 맞지 않다. |
kubectl 을 사용하여 새로운 타입을 읽고 쓸 수 있기를 원한다. |
kubectl 지원이 필요하지 않다. |
쿠버네티스 UI(예: 대시보드)에서 빌트인 타입과 함께 새로운 타입을 보길 원한다. | 쿠버네티스 UI 지원이 필요하지 않다. |
새로운 API를 개발 중이다. | 생성한 API를 제공하는 프로그램이 이미 있고 잘 작동하고 있다. |
API 그룹 및 네임스페이스와 같은 REST 리소스 경로에 적용하는 쿠버네티스의 형식 제한을 기꺼이 수용한다. (API 개요를 참고한다.) | 이미 정의된 REST API와 호환되도록 특정 REST 경로가 있어야 한다. |
자체 리소스는 자연스럽게 클러스터 또는 클러스터의 네임스페이스로 범위가 지정된다. | 클러스터 또는 네임스페이스 범위의 리소스는 적합하지 않다. 특정 리소스 경로를 제어해야 한다. |
쿠버네티스 API 지원 기능을 재사용하려고 한다. | 이러한 기능이 필요하지 않다. |
선언적 API
선언적 API에서는 다음의 특성이 있다.
- API는 상대적으로 적은 수의 상대적으로 작은 오브젝트(리소스)로 구성된다.
- 오브젝트는 애플리케이션 또는 인프라의 구성을 정의한다.
- 오브젝트는 비교적 드물게 업데이트 된다.
- 사람이 종종 오브젝트를 읽고 쓸 필요가 있다.
- 오브젝트의 주요 작업은 CRUD-y(생성, 읽기, 업데이트 및 삭제)이다.
- 오브젝트 간 트랜잭션은 필요하지 않다. API는 정확한(exact) 상태가 아니라 의도한 상태를 나타낸다.
명령형 API는 선언적이지 않다. 자신의 API가 선언적이지 않을 수 있다는 징후는 다음과 같다.
- 클라이언트는 "이 작업을 수행한다"라고 말하고 완료되면 동기(synchronous) 응답을 받는다.
- 클라이언트는 "이 작업을 수행한다"라고 말한 다음 작업 ID를 다시 가져오고 별도의 오퍼레이션(operation) 오브젝트를 확인하여 요청의 완료 여부를 결정해야 한다.
- RPC(원격 프로시저 호출)에 대해 얘기한다.
- 대량의 데이터를 직접 저장한다. 예: > 오브젝트별 몇 kB 또는 > 1000개의 오브젝트.
- 높은 대역폭 접근(초당 10개의 지속적인 요청)이 필요하다.
- 최종 사용자 데이터(예: 이미지, PII 등) 또는 애플리케이션에서 처리한 기타 대규모 데이터를 저장한다.
- 오브젝트에 대한 자연스러운 조작은 CRUD-y가 아니다.
- API는 오브젝트로 쉽게 모델링되지 않는다.
- 작업 ID 또는 작업 오브젝트로 보류 중인 작업을 나타내도록 선택했다.
컨피그맵을 사용해야 하나, 커스텀 리소스를 사용해야 하나?
다음 중 하나에 해당하면 컨피그맵을 사용하자.
mysql.cnf
또는pom.xml
과 같이 잘 문서화된 기존 구성 파일 형식이 있다.- 전체 구성 파일을 컨피그맵의 하나의 키에 넣고 싶다.
- 구성 파일의 주요 용도는 클러스터의 파드에서 실행 중인 프로그램이 파일을 사용하여 자체 구성하는 것이다.
- 파일 사용자는 쿠버네티스 API가 아닌 파드의 환경 변수 또는 파드의 파일을 통해 사용하는 것을 선호한다.
- 파일이 업데이트될 때 디플로이먼트 등을 통해 롤링 업데이트를 수행하려고 한다.
다음 중 대부분이 적용되는 경우 커스텀 리소스(CRD 또는 애그리게이트 API(aggregated API))를 사용하자.
- 쿠버네티스 클라이언트 라이브러리 및 CLI를 사용하여 새 리소스를 만들고 업데이트하려고 한다.
kubectl
의 최상위 지원을 원한다. 예:kubectl get my-object object-name
.- 새 오브젝트에 대한 업데이트를 감시한 다음 다른 오브젝트를 CRUD하거나 그 반대로 하는 새로운 자동화를 구축하려고 한다.
- 오브젝트의 업데이트를 처리하는 자동화를 작성하려고 한다.
.spec
,.status
및.metadata
와 같은 쿠버네티스 API 규칙을 사용하려고 한다.- 제어된 리소스의 콜렉션 또는 다른 리소스의 요약에 대한 오브젝트가 되기를 원한다.
커스텀 리소스 추가
쿠버네티스는 클러스터에 커스텀 리소스를 추가하는 두 가지 방법을 제공한다.
- CRD는 간단하며 프로그래밍 없이 만들 수 있다.
- API 애그리게이션에는 프로그래밍이 필요하지만, 데이터 저장 방법 및 API 버전 간 변환과 같은 API 동작을 보다 강력하게 제어할 수 있다.
쿠버네티스는 다양한 사용자의 요구를 충족시키기 위해 이 두 가지 옵션을 제공하므로 사용의 용이성이나 유연성이 저하되지 않는다.
애그리게이트 API는 기본 API 서버 뒤에 있는 하위 API 서버이며 프록시 역할을 한다. 이 배치를 API 애그리게이션(AA)이라고 한다. 사용자에게는 쿠버네티스 API가 확장된 것으로 나타난다.
CRD를 사용하면 다른 API 서버를 추가하지 않고도 새로운 타입의 리소스를 생성할 수 있다. CRD를 사용하기 위해 API 애그리게이션을 이해할 필요는 없다.
설치 방법에 관계없이 새 리소스는 커스텀 리소스라고 하며 빌트인 쿠버네티스 리소스(파드 등)와 구별된다.
커스텀리소스데피니션
커스텀리소스데피니션 API 리소스를 사용하면 커스텀 리소스를 정의할 수 있다. CRD 오브젝트를 정의하면 지정한 이름과 스키마를 사용하여 새 커스텀 리소스가 만들어진다. 쿠버네티스 API는 커스텀 리소스의 스토리지를 제공하고 처리한다. CRD 오브젝트의 이름은 유효한 DNS 서브도메인 이름이어야 한다.
따라서 커스텀 리소스를 처리하기 위해 자신의 API 서버를 작성할 수 없지만 구현의 일반적인 특성으로 인해 API 서버 애그리게이션보다 유연성이 떨어진다.
새 커스텀 리소스를 등록하고 새 리소스 타입의 인스턴스에 대해 작업하고 컨트롤러를 사용하여 이벤트를 처리하는 방법에 대한 예제는 커스텀 컨트롤러 예제를 참고한다.
API 서버 애그리게이션
일반적으로 쿠버네티스 API의 각 리소스에는 REST 요청을 처리하고 오브젝트의 퍼시스턴트 스토리지를 관리하는 코드가 필요하다. 주요 쿠버네티스 API 서버는 파드 및 서비스 와 같은 빌트인 리소스를 처리하고, 일반적으로 CRD를 통해 커스텀 리소스를 처리할 수 있다.
애그리게이션 레이어를 사용하면 자체 API 서버를 작성하고 배포하여 커스텀 리소스에 대한 특수한 구현을 제공할 수 있다. 주(main) API 서버는 사용자의 커스텀 리소스에 대한 요청을 사용자의 자체 API 서버에 위임하여 모든 클라이언트가 사용할 수 있게 한다.
커스텀 리소스를 추가할 방법 선택
CRD는 사용하기가 더 쉽다. 애그리게이트 API가 더 유연하다. 자신의 요구에 가장 잘 맞는 방법을 선택하자.
일반적으로 CRD는 다음과 같은 경우에 적합하다.
- 필드가 몇 개 되지 않는다
- 회사 내에서 또는 소규모 오픈소스 프로젝트의 일부인(상용 제품이 아닌) 리소스를 사용하고 있다.
사용 편의성 비교
CRD는 애그리게이트 API보다 생성하기가 쉽다.
CRD | 애그리게이트 API |
---|---|
프로그래밍이 필요하지 않다. 사용자는 CRD 컨트롤러에 대한 모든 언어를 선택할 수 있다. | 프로그래밍하고 바이너리와 이미지를 빌드해야 한다. |
실행할 추가 서비스가 없다. CR은 API 서버에서 처리한다. | 추가 서비스를 생성하면 실패할 수 있다. |
CRD가 생성된 후에는 지속적인 지원이 없다. 모든 버그 픽스는 일반적인 쿠버네티스 마스터 업그레이드의 일부로 선택된다. | 업스트림에서 버그 픽스를 주기적으로 선택하고 애그리게이트 API 서버를 다시 빌드하고 업데이트해야 할 수 있다. |
여러 버전의 API를 처리할 필요가 없다. 예를 들어, 이 리소스에 대한 클라이언트를 제어할 때 API와 동기화하여 업그레이드할 수 있다. | 인터넷에 공유할 익스텐션을 개발할 때와 같이 여러 버전의 API를 처리해야 한다. |
고급 기능 및 유연성
애그리게이트 API는 보다 고급 API 기능과 스토리지 레이어와 같은 다른 기능의 사용자 정의를 제공한다.
기능 | 설명 | CRD | 애그리게이트 API |
---|---|---|---|
유효성 검사 | 사용자가 오류를 방지하고 클라이언트와 독립적으로 API를 발전시킬 수 있도록 도와준다. 이러한 기능은 동시에 많은 클라이언트를 모두 업데이트할 수 없는 경우에 아주 유용하다. | 예. OpenAPI v3.0 유효성 검사를 사용하여 CRD에서 대부분의 유효성 검사를 지정할 수 있다. 웹훅 유효성 검사를 추가해서 다른 모든 유효성 검사를 지원한다. | 예, 임의의 유효성 검사를 지원한다. |
기본 설정 | 위를 참고하자. | 예, OpenAPI v3.0 유효성 검사의 default 키워드(1.17에서 GA) 또는 웹훅 변형(mutating)(이전 오브젝트의 etcd에서 읽을 때는 실행되지 않음)을 통해 지원한다. |
예 |
다중 버전 관리 | 두 가지 API 버전을 통해 동일한 오브젝트를 제공할 수 있다. 필드 이름 바꾸기와 같은 API 변경을 쉽게 할 수 있다. 클라이언트 버전을 제어하는 경우는 덜 중요하다. | 예 | 예 |
사용자 정의 스토리지 | 다른 성능 모드(예를 들어, 키-값 저장소 대신 시계열 데이터베이스)나 보안에 대한 격리(예를 들어, 암호화된 시크릿이나 다른 암호화) 기능을 가진 스토리지가 필요한 경우 | 아니오 | 예 |
사용자 정의 비즈니스 로직 | 오브젝트를 생성, 읽기, 업데이트 또는 삭제를 할 때 임의의 점검 또는 조치를 수행한다. | 예, 웹훅을 사용한다. | 예 |
서브리소스 크기 조정 | HorizontalPodAutoscaler 및 PodDisruptionBudget과 같은 시스템이 새로운 리소스와 상호 작용할 수 있다. | 예 | 예 |
서브리소스 상태 | 사용자가 스펙 섹션을 작성하고 컨트롤러가 상태 섹션을 작성하는 세분화된 접근 제어를 허용한다. 커스텀 리소스 데이터 변형 시 오브젝트 생성을 증가시킨다(리소스에서 별도의 스펙과 상태 섹션 필요). | 예 | 예 |
기타 서브리소스 | "logs" 또는 "exec"과 같은 CRUD 이외의 작업을 추가한다. | 아니오 | 예 |
strategic-merge-patch | 새로운 엔드포인트는 Content-Type: application/strategic-merge-patch+json 형식의 PATCH를 지원한다. 로컬 및 서버 양쪽에서 수정할 수도 있는 오브젝트를 업데이트하는 데 유용하다. 자세한 내용은 "kubectl 패치를 사용한 API 오브젝트 업데이트"를 참고한다. |
아니오 | 예 |
프로토콜 버퍼 | 새로운 리소스는 프로토콜 버퍼를 사용하려는 클라이언트를 지원한다. | 아니오 | 예 |
OpenAPI 스키마 | 서버에서 동적으로 가져올 수 있는 타입에 대한 OpenAPI(스웨거(swagger)) 스키마가 있는가? 허용된 필드만 설정하여 맞춤법이 틀린 필드 이름으로부터 사용자를 보호하는가? 타입이 적용되는가(즉, string 필드에 int 를 넣지 않는가?) |
예, OpenAPI v3.0 유효성 검사를 기반으로 하는 스키마(1.16에서 GA) | 예 |
일반적인 기능
CRD 또는 AA를 통해 커스텀 리소스를 생성하면 쿠버네티스 플랫폼 외부에서 구현하는 것과 비교하여 API에 대한 많은 기능이 제공된다.
기능 | 설명 |
---|---|
CRUD | 새로운 엔드포인트는 HTTP 및 kubectl 을 통해 CRUD 기본 작업을 지원한다. |
감시 | 새로운 엔드포인트는 HTTP를 통해 쿠버네티스 감시 작업을 지원한다. |
디스커버리 | kubectl 및 대시보드와 같은 클라이언트는 리소스에 대해 목록, 표시 및 필드 수정 작업을 자동으로 제공한다. |
json-patch | 새로운 엔드포인트는 Content-Type: application/json-patch+json 형식의 PATCH를 지원한다. |
merge-patch | 새로운 엔드포인트는 Content-Type: application/merge-patch+json 형식의 PATCH를 지원한다. |
HTTPS | 새로운 엔드포인트는 HTTPS를 사용한다. |
빌트인 인증 | 익스텐션에 대한 접근은 인증을 위해 기본 API 서버(애그리게이션 레이어)를 사용한다. |
빌트인 권한 부여 | 익스텐션에 접근하면 기본 API 서버(예: RBAC)에서 사용하는 권한을 재사용할 수 있다. |
Finalizer | 외부 정리가 발생할 때까지 익스텐션 리소스의 삭제를 차단한다. |
어드미션 웹훅 | 생성/업데이트/삭제 작업 중에 기본값을 설정하고 익스텐션 리소스의 유효성 검사를 한다. |
UI/CLI 디스플레이 | Kubectl, 대시보드는 익스텐션 리소스를 표시할 수 있다. |
설정하지 않음(unset)과 비어있음(empty) | 클라이언트는 값이 없는 필드 중에서 설정되지 않은 필드를 구별할 수 있다. |
클라이언트 라이브러리 생성 | 쿠버네티스는 일반 클라이언트 라이브러리와 타입별 클라이언트 라이브러리를 생성하는 도구를 제공한다. |
레이블 및 어노테이션 | 공통 메타데이터는 핵심 및 커스텀 리소스를 수정하는 방법을 알고 있는 도구이다. |
커스텀 리소스 설치 준비
클러스터에 커스텀 리소스를 추가하기 전에 알아야 할 몇 가지 사항이 있다.
써드파티 코드 및 새로운 장애 포인트
CRD를 생성해도 새로운 장애 포인트(예를 들어, API 서버에서 장애를 유발하는 써드파티 코드가 실행됨)가 자동으로 추가되지는 않지만, 패키지(예: 차트(Charts)) 또는 기타 설치 번들에는 CRD 및 새로운 커스텀 리소스에 대한 비즈니스 로직을 구현하는 써드파티 코드의 디플로이먼트가 포함되는 경우가 종종 있다.
애그리게이트 API 서버를 설치하려면 항상 새 디플로이먼트를 실행해야 한다.
스토리지
커스텀 리소스는 컨피그맵과 동일한 방식으로 스토리지 공간을 사용한다. 너무 많은 커스텀 리소스를 생성하면 API 서버의 스토리지 공간이 과부하될 수 있다.
애그리게이트 API 서버는 기본 API 서버와 동일한 스토리지를 사용할 수 있으며 이 경우 동일한 경고가 적용된다.
인증, 권한 부여 및 감사
CRD는 항상 API 서버의 빌트인 리소스와 동일한 인증, 권한 부여 및 감사 로깅을 사용한다.
권한 부여에 RBAC를 사용하는 경우 대부분의 RBAC 역할은 새로운 리소스에 대한 접근 권한을 부여하지 않는다(클러스터 관리자 역할 또는 와일드 카드 규칙으로 생성된 역할 제외). 새로운 리소스에 대한 접근 권한을 명시적으로 부여해야 한다. CRD 및 애그리게이트 API는 종종 추가하는 타입에 대한 새로운 역할 정의와 함께 제공된다.
애그리게이트 API 서버는 기본 API 서버와 동일한 인증, 권한 부여 및 감사를 사용하거나 사용하지 않을 수 있다.
커스텀 리소스에 접근
쿠버네티스 클라이언트 라이브러리를 사용하여 커스텀 리소스에 접근할 수 있다. 모든 클라이언트 라이브러리가 커스텀 리소스를 지원하는 것은 아니다. Go 와 python 클라이언트 라이브러리가 지원한다.
커스텀 리소스를 추가하면 다음을 사용하여 접근할 수 있다.
kubectl
- 쿠버네티스 동적 클라이언트
- 작성한 REST 클라이언트
- 쿠버네티스 클라이언트 생성 도구를 사용하여 생성된 클라이언트(하나를 생성하는 것은 고급 기능이지만, 일부 프로젝트는 CRD 또는 AA와 함께 클라이언트를 제공할 수 있다).
다음 내용
-
애그리게이션 레이어(aggregation layer)로 쿠버네티스 API 확장하는 방법에 대해 배우기.
-
커스텀리소스데피니션으로 쿠버네티스 API 확장하는 방법에 대해 배우기.
2 - 쿠버네티스 API 애그리게이션 레이어(aggregation layer)
애그리게이션 레이어는 코어 쿠버네티스 API가 제공하는 기능 이외에 더 많은 기능을 제공할 수 있도록 추가 API를 더해 쿠버네티스를 확장할 수 있게 해준다. 추가 API는 메트릭 서버와 같이 미리 만들어진 솔루션이거나 사용자가 직접 개발한 API일 수 있다.
애그리게이션 레이어는 사용자 정의 리소스와는 다르며, 애그리게이션 레이어는 kube-apiserver 가 새로운 종류의 오브젝트를 인식하도록 하는 방법이다.
애그리게이션 레이어
애그리게이션 레이어는 kube-apiserver 프로세스 안에서 구동된다. 확장 리소스가 등록되기 전까지, 애그리게이션 레이어는 아무 일도 하지 않는다. API를 등록하기 위해서, 사용자는 쿠버네티스 API 내에서 URL 경로를 "요구하는(claim)" APIService 오브젝트를 추가해야 한다. 이때, 애그리게이션 레이어는 해당 API 경로(예: /apis/myextensions.mycompany.io/v1/...)로 전송되는 모든 것을 등록된 APIService로 프록시하게 된다.
APIService를 구현하는 가장 일반적인 방법은 클러스터 내에 실행되고 있는 파드에서 extension API server 를 실행하는 것이다. extension API server를 사용해서 클러스터의 리소스를 관리하는 경우 extension API server("extension-apiserver" 라고도 한다)는 일반적으로 하나 이상의 컨트롤러와 쌍을 이룬다. apiserver-builder 라이브러리는 extension API server와 연관된 컨틀로러에 대한 스켈레톤을 제공한다.
응답 레이턴시
Extension-apiserver는 kube-apiserver로 오가는 연결의 레이턴시가 낮아야 한다. kube-apiserver로 부터의 디스커버리 요청은 왕복 레이턴시가 5초 이내여야 한다.
extention API server가 레이턴시 요구 사항을 달성할 수 없는 경우 이를 충족할 수 있도록 변경하는 것을 고려한다.
다음 내용
- 사용자의 환경에서 Aggregator를 동작시키려면, 애그리게이션 레이어를 설정한다.
- 다음에, 확장 API 서버를 구성해서 애그리게이션 레이어와 연계한다.
- API 레퍼런스에서 API 서비스에 대해 읽어본다.
대안으로, 어떻게 쿠버네티스 API를 커스텀 리소스 데피니션으로 확장하는지를 배워본다.