[ko] Updated outdated files in dev-1.27-ko.1 (M22-30)

pull/43138/head
Jihoon Seo 2023-09-21 10:56:14 +09:00
parent 8d888caad8
commit b39017b657
9 changed files with 419 additions and 175 deletions

View File

@ -14,9 +14,8 @@ hide_summary: true # 섹션의 목차에 별도로 기재
나타낸다. 컨테이너 이미지는 독립적으로 실행할 수 있고 런타임 환경에 대해
잘 정의된 가정을 만드는 실행 가능한 소프트웨어 번들이다.
일반적으로 {{< glossary_tooltip text="파드" term_id="pod" >}}에서
참조하기 전에 애플리케이션의 컨테이너 이미지를
생성해서 레지스트리로 푸시한다.
일반적으로 컨테이너 이미지는 {{< glossary_tooltip text="파드" term_id="pod" >}}에서 사용되기 전에
사용자가 애플리케이션의 컨테이너 이미지를 생성하고 레지스트리로 푸시하는 과정을 거친다.
이 페이지는 컨테이너 이미지 개념의 개요를 제공한다.
@ -97,7 +96,11 @@ hide_summary: true # 섹션의 목차에 별도로 기재
`<image-name>:<tag>``<image-name>@<digest>`로 교체한다.
(예를 들어, `image@sha256:45b23dee08af5e43a7fea6c4cf9c25ccf269ee113168c19722f87876677c5cb2`).
이미지 태그를 사용하는 경우, 이미지 레지스트리에서 한 이미지를 나타내는 태그에 코드를 변경하게 되면, 기존 코드와 신규 코드를 구동하는 파드가 섞이게 되고 만다. 이미지 다이제스트를 통해 이미지의 특정 버전을 유일하게 식별할 수 있기 때문에, 쿠버네티스는 매번 해당 이미지 이름과 다이제스트가 명시된 컨테이너를 기동해서 같은 코드를 구동한다. 이미지를 다이제스트로 명시하면 구동할 코드를 고정시켜서 레지스트리에서의 변경으로 인해 버전이 섞이는 일이 발생하지 않도록 해 준다.
이미지 태그를 사용하는 경우, 이미지 레지스트리에서 한 이미지를 나타내는 태그에 코드를 변경하게 되면,
기존 코드와 신규 코드를 구동하는 파드가 섞이게 되고 만다.
이미지 다이제스트를 통해 이미지의 특정 버전을 유일하게 식별할 수 있기 때문에,
쿠버네티스는 매번 해당 이미지 이름과 다이제스트가 명시된 컨테이너를 기동해서 같은 코드를 구동한다.
이미지를 다이제스트로 명시하면 구동할 코드를 고정시켜서 레지스트리에서의 변경으로 인해 버전이 섞이는 일이 발생하지 않도록 해 준다.
파드(및 파드 템플릿)가 생성될 때 구동 중인 워크로드가
태그가 아닌 이미지 다이제스트를 통해 정의되도록 조작해주는
@ -137,8 +140,8 @@ hide_summary: true # 섹션의 목차에 별도로 기재
그러면 사용자가 파드를 요청할 때 쿠버네티스가 정책을 `Always`로 설정한다.
- `imagePullPolicy`와 사용할 이미지의 태그를 생략한다.
그러면 사용자가 파드를 요청할 때 쿠버네티스가 정책을 `Always`로 설정한다.
- [AlwaysPullImages](/docs/reference/access-authn-authz/admission-controllers/#alwayspullimages) 어드미션 컨트롤러를 활성화 한다.
- [AlwaysPullImages](/docs/reference/access-authn-authz/admission-controllers/#alwayspullimages)
어드미션 컨트롤러를 활성화 한다.
### 이미지풀백오프(ImagePullBackOff)
@ -154,6 +157,48 @@ kubelet이 컨테이너 런타임을 사용하여 파드의 컨테이너 생성
쿠버네티스는 시간 간격을 늘려가면서 시도를 계속하며, 시간 간격의 상한은 쿠버네티스 코드에
300초(5분)로 정해져 있다.
## 순차 및 병렬 이미지 풀
기본적으로, kubelet은 이미지를 순차적으로 풀링한다.
다르게 말하면, kubelet은 이미지 서비스에 이미지 풀 요청을 한 번에 하나씩만 보낸다.
현재 처리 중인 요청이 완료될 때까지 다른 이미지 풀 요청은 기다려야 한다.
각 노드는 이미지 풀 결정을 독립적으로 수행한다.
순차 이미지 풀링을 사용하더라도, 서로 다른 두 노드가 동일한 이미지를 병렬적으로 풀링할 수 있다.
병렬 이미지 풀을 활성화하고 싶다면, [kubelet 구성](/docs/reference/config-api/kubelet-config.v1beta1/)의
`serializeImagePulls` 필드를 false로 설정할 수 있다.
`serializeImagePulls` 필드가 false로 설정되어 있으면,
이미지 풀 요청이 이미지 서비스로 즉시 전송되며, 여러 이미지가 동시에 풀링될 것이다.
병렬 이미지 풀을 활성화할 때,
사용 중인 컨테이너 런타임의 이미지 서비스가 병렬 이미지 풀을 처리할 수 있는지 확인한다.
kubelet은 단일 파드에 대해 여러 이미지를 병렬로 풀링하지는 않을 것이다.
예를 들어, 초기화 컨테이너와 애플리케이션 컨테이너로 이루어지는 파드가 있다면,
두 컨테이너에 대한 이미지 풀은 병렬로 진행되지 않을 것이다.
그러나, 서로 다른 이미지를 사용하는 두 파드가 있고, 병렬 이미지 풀이 활성화되어 있다면,
kubelet은 서로 다른 두 파드에 대해 이미지 풀을 병렬로 수행한다.
### 최대 병렬 이미지 풀
{{< feature-state for_k8s_version="v1.27" state="alpha" >}}
`serializeImagePulls`가 false로 설정되어 있으면,
kubelet은 기본적으로는 동시에 풀링할 수 있는 이미지의 수에 제한을 두지 않는다.
병렬 이미지 풀 수에 제한을 설정하고 싶으면,
kubelet 구성 내의 `maxParallelImagePulls` 필드를 설정할 수 있다.
`maxParallelImagePulls`_n_ 으로 설정하면, 동시에 _n_ 개의 이미지만 풀링할 수 있으며,
이를 초과하는 이미지 풀은 현재 진행 중인 이미지 풀이 완료되기를 기다려야 한다.
병렬 이미지 풀이 활성화되어 있는 경우에, 병렬 이미지 풀의 수를 제한하여
이미지 풀 작업이 네트워크 대역폭이나 디스크 입출력을 지나치게 많이 차지하는 것을 방지할 수 있다.
`maxParallelImagePulls`의 값은 1 이상의 양수로 설정할 수 있다.
`maxParallelImagePulls`를 2 이상의 값으로 지정했다면,
`serializeImagePulls`는 false로 설정해야 한다.
`maxParallelImagePulls`가 올바르게 설정되어 있지 않으면 kubelet은 시작에 실패할 것이다.
## 이미지 인덱스가 있는 다중 아키텍처 이미지
바이너리 이미지를 제공할 뿐만 아니라, 컨테이너 레지스트리는
@ -163,35 +208,39 @@ kubelet이 컨테이너 런타임을 사용하여 파드의 컨테이너 생성
아이디어는 이미지의 이름(예를 들어, `pause`, `example/mycontainer`, `kube-apiserver`)을 가질 수 있다는 것이다.
그래서 다른 시스템들이 사용하고 있는 컴퓨터 아키텍처에 적합한 바이너리 이미지를 가져올 수 있다.
쿠버네티스 자체는 일반적으로 `-$(ARCH)` 접미사로 컨테이너 이미지의 이름을 지정한다. 이전 버전과의 호환성을 위해,
접미사가 있는 오래된 이미지를 생성한다. 아이디어는 모든 아키텍처에 대한 매니페스트가 있는 `pause` 이미지와 이전 구성
또는 이전에 접미사로 이미지를 하드 코딩한 YAML 파일과 호환되는 `pause-amd64` 라고 하는 이미지를 생성한다.
쿠버네티스 자체는 일반적으로 `-$(ARCH)` 접미사로 컨테이너 이미지의 이름을 지정한다.
이전 버전과의 호환성을 위해, 접미사가 있는 오래된 이미지를 생성한다.
이에 대한 아이디어는, 모든 아키텍처에 대한 매니페스트가 있는 `pause` 이미지와
이전 구성 또는 이전에 접미사로 이미지를 하드 코딩한 YAML 파일과 호환되는
`pause-amd64` 라고 하는 이미지를 생성하는 것이다.
## 프라이빗 레지스트리 사용
프라이빗 레지스트리는 해당 레지스트리에서 이미지를 읽을 수 있는 키를 요구할 것이다.
자격 증명(credential)은 여러 가지 방법으로 제공될 수 있다.
- 프라이빗 레지스트리에 대한 인증을 위한 노드 구성
- 모든 파드는 구성된 프라이빗 레지스트리를 읽을 수 있음
- 클러스터 관리자에 의한 노드 구성 필요
- Kubelet 자격증명 제공자(Credential Provider)를 통해 프라이빗 레지스트리로부터 동적으로 자격증명을 가져오기
- kubelet은 특정 프라이빗 레지스트리에 대해 자격증명 제공자 실행
플러그인(credential provider exec plugin)을 사용하도록 설정될 수 있다.
- 미리 내려받은(pre-pulled) 이미지
- 모든 파드는 노드에 캐시된 모든 이미지를 사용 가능
- 셋업을 위해서는 모든 노드에 대해서 root 접근이 필요
- 파드에 ImagePullSecrets을 명시
- 자신의 키를 제공하는 파드만 프라이빗 레지스트리에 접근 가능
- 공급 업체별 또는 로컬 확장
- 사용자 정의 노드 구성을 사용하는 경우, 사용자(또는 클라우드
제공자)가 컨테이너 레지스트리에 대한 노드 인증 메커니즘을
구현할 수 있다.
- 프라이빗 레지스트리에 대한 인증을 위한 노드 구성
- 모든 파드는 구성된 프라이빗 레지스트리를 읽을 수 있음
- 클러스터 관리자에 의한 노드 구성 필요
- Kubelet 자격증명 제공자(Credential Provider)를 통해 프라이빗 레지스트리로부터 동적으로 자격증명을 가져오기
- kubelet은 특정 프라이빗 레지스트리에 대해 자격증명 제공자 실행
플러그인(credential provider exec plugin)을 사용하도록 설정될 수 있다.
- 미리 내려받은(pre-pulled) 이미지
- 모든 파드는 노드에 캐시된 모든 이미지를 사용 가능
- 셋업을 위해서는 모든 노드에 대해서 root 접근이 필요
- 파드에 ImagePullSecrets을 명시
- 자신의 키를 제공하는 파드만 프라이빗 레지스트리에 접근 가능
- 공급 업체별 또는 로컬 확장
- 사용자 정의 노드 구성을 사용하는 경우, 사용자(또는 클라우드
제공자)가 컨테이너 레지스트리에 대한 노드 인증 메커니즘을
구현할 수 있다.
이들 옵션은 아래에서 더 자세히 설명한다.
### 프라이빗 레지스트리에 인증하도록 노드 구성
크리덴셜 설정에 대한 상세 지침은 사용하는 컨테이너 런타임 및 레지스트리에 따라 다르다. 가장 정확한 정보는 솔루션 설명서를 참조해야 한다.
크리덴셜 설정에 대한 상세 지침은 사용하는 컨테이너 런타임 및 레지스트리에 따라 다르다.
가장 정확한 정보는 솔루션 설명서를 참조해야 한다.
프라이빗 컨테이너 이미지 레지스트리 구성 예시를 보려면,
[프라이빗 레지스트리에서 이미지 가져오기](/ko/docs/tasks/configure-pod-container/pull-image-private-registry/)를 참조한다.
@ -276,7 +325,6 @@ kubelet은 인식된 모든 크리덴셜을 순차적으로 이용하여 이미
이미지를 풀 해야 한다고 명시하면,
kubelet은 크리덴셜을 순차적으로 사용하여 풀을 시도한다.
### 미리 내려받은 이미지 {#pre-pulled-images}
{{< note >}}
@ -292,7 +340,8 @@ kubelet은 크리덴셜을 순차적으로 사용하여 풀을 시도한다.
레지스트리 인증의 대안으로 미리 풀 된 이미지에 의존하고 싶다면,
클러스터의 모든 노드가 동일한 미리 내려받은 이미지를 가지고 있는지 확인해야 한다.
이것은 특정 이미지를 속도를 위해 미리 로드하거나 프라이빗 레지스트리에 대한 인증의 대안으로 사용될 수 있다.
이것은 특정 이미지를 속도를 위해 미리 로드하거나
프라이빗 레지스트리에 대한 인증의 대안으로 사용될 수 있다.
모든 파드는 미리 내려받은 이미지에 대해 읽기 접근 권한을 가질 것이다.
@ -314,13 +363,18 @@ kubelet은 크리덴셜을 순차적으로 사용하여 풀을 시도한다.
대문자 값을 적절히 대체하여, 다음 커맨드를 실행한다.
```shell
kubectl create secret docker-registry <name> --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL
kubectl create secret docker-registry <name> \
--docker-server=DOCKER_REGISTRY_SERVER \
--docker-username=DOCKER_USER \
--docker-password=DOCKER_PASSWORD \
--docker-email=DOCKER_EMAIL
```
만약 도커 자격 증명 파일이 이미 존재한다면, 위의 명령을 사용하지 않고,
자격 증명 파일을 쿠버네티스 {{< glossary_tooltip text="시크릿" term_id="secret" >}}으로
가져올 수 있다.
[기존 도커 자격 증명으로 시크릿 생성](/ko/docs/tasks/configure-pod-container/pull-image-private-registry/#registry-secret-existing-credentials)에서 관련 방법을 설명하고 있다.
[기존 도커 자격 증명으로 시크릿 생성](/ko/docs/tasks/configure-pod-container/pull-image-private-registry/#registry-secret-existing-credentials)에서
관련 방법을 설명하고 있다.
`kubectl create secret docker-registry`
하나의 프라이빗 레지스트리에서만 작동하는 시크릿을 생성하기 때문에,
@ -333,8 +387,9 @@ kubectl create secret docker-registry <name> --docker-server=DOCKER_REGISTRY_SER
#### 파드의 imagePullSecrets 참조
이제, `imagePullSecrets` 섹션을 파드의 정의에 추가함으로써 해당 시크릿을
참조하는 파드를 생성할 수 있다.
이제, `imagePullSecrets` 섹션을 파드의 정의에 추가함으로써
해당 시크릿을 참조하는 파드를 생성할 수 있다. `imagePullSecrets` 배열의 각 항목으로는
해당 파드와 동일한 네임스페이스에 있는 시크릿만 참조할 수 있다.
예를 들면 다음과 같다.
@ -364,7 +419,8 @@ EOF
그러나, 이 필드의 셋팅은 [서비스 어카운트](/docs/tasks/configure-pod-container/configure-service-account/) 리소스에
imagePullSecrets을 셋팅하여 자동화할 수 있다.
자세한 지침을 위해서는 [서비스 어카운트에 ImagePullSecrets 추가](/docs/tasks/configure-pod-container/configure-service-account/#add-imagepullsecrets-to-a-service-account)를 확인한다.
자세한 지침을 위해서는
[서비스 어카운트에 ImagePullSecrets 추가](/docs/tasks/configure-pod-container/configure-service-account/#add-imagepullsecrets-to-a-service-account)를 확인한다.
이것은 노드 당 `.docker/config.json`와 함께 사용할 수 있다. 자격 증명은
병합될 것이다.
@ -377,7 +433,8 @@ imagePullSecrets을 셋팅하여 자동화할 수 있다.
1. 비소유 이미지(예를 들어, 오픈소스)만 실행하는 클러스터의 경우. 이미지를 숨길 필요가 없다.
- 퍼블릭 레지스트리의 퍼블릭 이미지를 사용한다.
- 설정이 필요 없다.
- 일부 클라우드 제공자는 퍼블릭 이미지를 자동으로 캐시하거나 미러링하므로, 가용성이 향상되고 이미지를 가져오는 시간이 줄어든다.
- 일부 클라우드 제공자는 퍼블릭 이미지를 자동으로 캐시하거나 미러링하므로,
가용성이 향상되고 이미지를 가져오는 시간이 줄어든다.
1. 모든 클러스터 사용자에게는 보이지만, 회사 외부에는 숨겨야하는 일부 독점 이미지를
실행하는 클러스터의 경우.
- 호스트된 프라이빗 레지스트리를 사용한다.
@ -388,17 +445,33 @@ imagePullSecrets을 셋팅하여 자동화할 수 있다.
- 그것은 수동 노드 구성에 비해서 클러스터 오토스케일링과 더 잘 동작할 것이다.
- 또는, 노드의 구성 변경이 불편한 클러스터에서는, `imagePullSecrets`를 사용한다.
1. 독점 이미지를 가진 클러스터로, 그 중 일부가 더 엄격한 접근 제어를 필요로 하는 경우.
- [AlwaysPullImages 어드미션 컨트롤러](/docs/reference/access-authn-authz/admission-controllers/#alwayspullimages)가 활성화되어 있는지 확인한다. 그렇지 않으면, 모든 파드가 잠재적으로 모든 이미지에 접근 권한을 가진다.
- [AlwaysPullImages 어드미션 컨트롤러](/docs/reference/access-authn-authz/admission-controllers/#alwayspullimages)가 활성화되어 있는지 확인한다.
그렇지 않으면, 모든 파드가 잠재적으로 모든 이미지에 접근 권한을 가진다.
- 민감한 데이터는 이미지 안에 포장하는 대신, "시크릿" 리소스로 이동한다.
1. 멀티-테넌트 클러스터에서 각 테넌트가 자신의 프라이빗 레지스트리를 필요로 하는 경우.
- [AlwaysPullImages 어드미션 컨트롤러](/docs/reference/access-authn-authz/admission-controllers/#alwayspullimages)가 활성화되어 있는지 확인한다. 그렇지 않으면, 모든 파드가 잠재적으로 모든 이미지에 접근 권한을 가진다.
- [AlwaysPullImages 어드미션 컨트롤러](/docs/reference/access-authn-authz/admission-controllers/#alwayspullimages)가 활성화되어 있는지 확인한다.
그렇지 않으면, 모든 파드가 잠재적으로 모든 이미지에 접근 권한을 가진다.
- 인가가 요구되도록 프라이빗 레지스트리를 실행한다.
- 각 테넌트에 대한 레지스트리 자격 증명을 생성하고, 시크릿에 넣고, 각 테넌트 네임스페이스에 시크릿을 채운다.
- 각 테넌트에 대한 레지스트리 자격 증명을 생성하고, 시크릿에 넣고,
각 테넌트 네임스페이스에 시크릿을 채운다.
- 테넌트는 해당 시크릿을 각 네임스페이스의 imagePullSecrets에 추가한다.
다중 레지스트리에 접근해야 하는 경우, 각 레지스트리에 대해 하나의 시크릿을 생성할 수 있다.
## 레거시 내장 kubelet 자격 증명 공급자
이전 버전의 Kubernetes에서, kubelet은 클라우드 공급자 자격 증명과 직접 통합되어 있었다.
이로 인해 이미지 레지스트리용 자격 증명을 동적으로 가져올 수 있었다.
이러한 kubelet 자격 증명 공급자 통합의 내장 구현은
ACR (Azure Container Registry), ECR (Elastic Container Registry), GCR (Google Container Registry) 의 3종이 있었다.
레거시 메카니즘에 대한 더 많은 정보는 현재 사용 중인 쿠버네티스 버전의 문서를 참고한다.
쿠버네티스 v1.26부터 v{{< skew latestVersion >}}까지는 레거시 메카니즘를 포함하고 있지 않으므로,
다음 중 한 가지 방법을 사용해야 한다.
- kubelet 이미지 자격 증명 공급자를 각 노드에 대해 구성한다
- `imagePullSecrets` 및 하나 이상의 시크릿을 사용하여 이미지 풀 자격 증명을 지정한다
## {{% heading "whatsnext" %}}
* [OCI 이미지 매니페스트 명세](https://github.com/opencontainers/image-spec/blob/master/manifest.md) 읽어보기.

View File

@ -1,6 +1,6 @@
---
title: 쿠버네티스 확장
weight: 110
weight: 999 # 이 섹션이 맨 마지막에 와야 한다
description: 쿠버네티스 클러스터의 동작을 변경하는 다양한 방법
# reviewers:
# - erictune
@ -283,6 +283,20 @@ FlexVolume 스토리지에 의존하는 파드를 실행하는 경우 kubelet은
[네트워크 플러그인](/ko/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/)을 통해
쿠버네티스는 다양한 네트워크 토폴로지 및 기술을 활용할 수 있게 된다.
### kubelet 이미지 자격 증명 공급자 플러그인
{{< feature-state for_k8s_version="v1.26" state="stable" >}}
kubelet 이미지 자격 증명 공급자는 kubelet이 이미지 레지스트리 자격 증명을 동적으로 가져올 수 있게 하는 플러그인이다.
이후, 자격 증명은 구성과 일치하는 컨테이너 이미지 레지스트리에서
이미지를 풀링할 때 사용된다.
이러한 플러그인은 외부 서비스와 통신하거나 로컬 파일을 사용하여 자격 증명을 가져올 수 있다.
이러한 방법으로, kubelet은 각 레지스트리에 대한 자격 증명을 정적으로 갖고 있지 않아도 되며,
다양한 인증 방법 및 프로토콜을 지원할 수 있다.
플러그인의 구성에 대한 상세 사항은
[kubelet 이미지 자격 증명 공급자 구성하기](/ko/docs/tasks/administer-cluster/kubelet-credential-provider/)를 참고한다.
### 스케줄링 익스텐션
스케줄러는 파드를 감시하고 파드를 노드에 할당하는 특수한 유형의

View File

@ -17,7 +17,7 @@ weight: 10
## 커스텀 리소스
*리소스* 는 [쿠버네티스 API](/ko/docs/concepts/overview/kubernetes-api/)에서 특정 종류의
[API 오브젝트](/ko/docs/concepts/overview/working-with-objects/kubernetes-objects/) 모음을 저장하는 엔드포인트이다.
{{< glossary_tooltip text="API 오브젝트" term_id="object" >}} 모음을 저장하는 엔드포인트이다.
예를 들어 빌트인 *파드* 리소스에는 파드 오브젝트 모음이 포함되어 있다.
*커스텀 리소스* 는 쿠버네티스 API의 익스텐션으로, 기본 쿠버네티스 설치에서 반드시

View File

@ -28,7 +28,7 @@ kubelet은 `Registration` gRPC 서비스를 노출시킨다.
```gRPC
service Registration {
rpc Register(RegisterRequest) returns (Empty) {}
rpc Register(RegisterRequest) returns (Empty) {}
}
```
@ -87,60 +87,65 @@ spec:
장치 플러그인의 일반적인 워크플로우에는 다음 단계가 포함된다.
* 초기화. 이 단계에서, 장치 플러그인은 공급 업체별 초기화 및 설정을 수행하여
장치가 준비 상태에 있는지 확인한다.
1. 초기화. 이 단계에서, 장치 플러그인은 공급 업체별 초기화 및 설정을 수행하여
장치가 준비 상태에 있는지 확인한다.
* 플러그인은 다음의 인터페이스를 구현하는 호스트 경로 `/var/lib/kubelet/device-plugins/`
아래에 유닉스 소켓과 함께 gRPC 서비스를 시작한다.
1. 플러그인은 다음의 인터페이스를 구현하는 호스트 경로 `/var/lib/kubelet/device-plugins/`
아래에 유닉스 소켓과 함께 gRPC 서비스를 시작한다.
```gRPC
service DevicePlugin {
// GetDevicePluginOptions는 장치 관리자와 통신할 옵션을 반환한다.
rpc GetDevicePluginOptions(Empty) returns (DevicePluginOptions) {}
```gRPC
service DevicePlugin {
// GetDevicePluginOptions는 장치 관리자와 통신할 옵션을 반환한다.
rpc GetDevicePluginOptions(Empty) returns (DevicePluginOptions) {}
// ListAndWatch는 장치 목록 스트림을 반환한다.
// 장치 상태가 변경되거나 장치가 사라질 때마다, ListAndWatch는
// 새 목록을 반환한다.
rpc ListAndWatch(Empty) returns (stream ListAndWatchResponse) {}
// ListAndWatch는 장치 목록 스트림을 반환한다.
// 장치 상태가 변경되거나 장치가 사라질 때마다, ListAndWatch는
// 새 목록을 반환한다.
rpc ListAndWatch(Empty) returns (stream ListAndWatchResponse) {}
// 컨테이너를 생성하는 동안 Allocate가 호출되어 장치
// 플러그인이 장치별 작업을 실행하고 kubelet에 장치를
// 컨테이너에서 사용할 수 있도록 하는 단계를 지시할 수 있다.
rpc Allocate(AllocateRequest) returns (AllocateResponse) {}
// 컨테이너를 생성하는 동안 Allocate가 호출되어 장치
// 플러그인이 장치별 작업을 실행하고 kubelet에 장치를
// 컨테이너에서 사용할 수 있도록 하는 단계를 지시할 수 있다.
rpc Allocate(AllocateRequest) returns (AllocateResponse) {}
// GetPreferredAllocation은 사용 가능한 장치 목록에서 할당할
// 기본 장치 집합을 반환한다. 그 결과로 반환된 선호하는 할당은
// devicemanager가 궁극적으로 수행하는 할당이 되는 것을 보장하지
// 않는다. 가능한 경우 devicemanager가 정보에 입각한 할당 결정을
// 내릴 수 있도록 설계되었다.
rpc GetPreferredAllocation(PreferredAllocationRequest) returns (PreferredAllocationResponse) {}
// GetPreferredAllocation은 사용 가능한 장치 목록에서 할당할
// 기본 장치 집합을 반환한다. 그 결과로 반환된 선호하는 할당은
// devicemanager가 궁극적으로 수행하는 할당이 되는 것을 보장하지
// 않는다. 가능한 경우 devicemanager가 정보에 입각한 할당 결정을
// 내릴 수 있도록 설계되었다.
rpc GetPreferredAllocation(PreferredAllocationRequest) returns (PreferredAllocationResponse) {}
// PreStartContainer는 등록 단계에서 장치 플러그인에 의해 표시되면 각 컨테이너가
// 시작되기 전에 호출된다. 장치 플러그인은 장치를 컨테이너에서 사용할 수 있도록 하기 전에
// 장치 재설정과 같은 장치별 작업을 실행할 수 있다.
rpc PreStartContainer(PreStartContainerRequest) returns (PreStartContainerResponse) {}
}
```
// PreStartContainer는 등록 단계에서 장치 플러그인에 의해 표시되면 각 컨테이너가
// 시작되기 전에 호출된다. 장치 플러그인은 장치를 컨테이너에서 사용할 수 있도록 하기 전에
// 장치 재설정과 같은 장치별 작업을 실행할 수 있다.
rpc PreStartContainer(PreStartContainerRequest) returns (PreStartContainerResponse) {}
}
```
{{< note >}}
`GetPreferredAllocation()` 또는 `PreStartContainer()` 에 대한 유용한 구현을
제공하기 위해 플러그인이 필요하지 않다. 이러한 호출(있는 경우) 중
사용할 수 있는 경우를 나타내는 플래그는 `GetDevicePluginOptions()`
호출에 의해 다시 전송된 `DevicePluginOptions` 메시지에 설정되어야 한다. `kubelet`
항상 `GetDevicePluginOptions()` 를 호출하여 사용할 수 있는
선택적 함수를 확인한 후 직접 호출한다.
{{< /note >}}
{{< note >}}
`GetPreferredAllocation()` 또는 `PreStartContainer()` 에 대한 유용한 구현을
제공하기 위해 플러그인이 필요하지 않다. 이러한 호출(있는 경우) 중
사용할 수 있는 경우를 나타내는 플래그는 `GetDevicePluginOptions()`
호출에 의해 다시 전송된 `DevicePluginOptions` 메시지에 설정되어야 한다. `kubelet`
항상 `GetDevicePluginOptions()` 를 호출하여 사용할 수 있는
선택적 함수를 확인한 후 직접 호출한다.
{{< /note >}}
* 플러그인은 호스트 경로 `/var/lib/kubelet/device-plugins/kubelet.sock` 에서
유닉스 소켓을 통해 kubelet에 직접 등록한다.
1. 플러그인은 호스트 경로 `/var/lib/kubelet/device-plugins/kubelet.sock` 에서
유닉스 소켓을 통해 kubelet에 직접 등록한다.
* 성공적으로 등록하고 나면, 장치 플러그인은 서빙(serving) 모드에서 실행되며, 그 동안 플러그인은 장치 상태를
모니터링하고 장치 상태 변경 시 kubelet에 다시 보고한다.
또한 gRPC 요청 `Allocate` 를 담당한다. `Allocate` 하는 동안, 장치 플러그인은
GPU 정리 또는 QRNG 초기화와 같은 장치별 준비를 수행할 수 있다.
작업이 성공하면, 장치 플러그인은 할당된 장치에 접근하기 위한 컨테이너 런타임 구성이 포함된
`AllocateResponse` 를 반환한다. kubelet은 이 정보를
컨테이너 런타임에 전달한다.
{{< note >}}
워크플로우의 순서가 중요하다. 플러그인이 자신을 kubelet에 등록하기 전에
gRPC 서비스를 서빙하고 있어야 등록이 문제 없이 성공한다.
{{< /note >}}
1. 성공적으로 등록하고 나면, 장치 플러그인은 서빙(serving) 모드에서 실행되며, 그 동안 플러그인은 장치 상태를
모니터링하고 장치 상태 변경 시 kubelet에 다시 보고한다.
또한 gRPC 요청 `Allocate` 를 담당한다. `Allocate` 하는 동안, 장치 플러그인은
GPU 정리 또는 QRNG 초기화와 같은 장치별 준비를 수행할 수 있다.
작업이 성공하면, 장치 플러그인은 할당된 장치에 접근하기 위한 컨테이너 런타임 구성이 포함된
`AllocateResponse` 를 반환한다. kubelet은 이 정보를
컨테이너 런타임에 전달한다.
### kubelet 재시작 처리
@ -158,8 +163,7 @@ kubelet 인스턴스에 자신을 다시 등록할 것으로 기대된다. 새 k
장치 플러그인은 특권을 가진 보안 컨텍스트에서 실행해야 한다.
장치 플러그인을 데몬셋으로 배포하는 경우, 플러그인의
[PodSpec](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#podspec-v1-core)에서
`/var/lib/kubelet/device-plugins`
{{< glossary_tooltip text="볼륨" term_id="volume" >}}으로 마운트해야 한다.
`/var/lib/kubelet/device-plugins` 를 {{< glossary_tooltip text="볼륨" term_id="volume" >}}으로 마운트해야 한다.
데몬셋 접근 방식을 선택하면 쿠버네티스를 사용하여 장치 플러그인의 파드를 노드에 배치하고,
장애 후 데몬 파드를 다시 시작하고, 업그레이드를 자동화할 수 있다.
@ -170,12 +174,14 @@ kubelet 인스턴스에 자신을 다시 등록할 것으로 기대된다. 새 k
해당 기능이 v1.12의 베타 버전으로 올라오면서 이는 필수 요구사항이 아니게 되었다.
해당 기능이 베타 버전이 된 이후로 API는 버전화되었고 그동안 변하지 않았다.
그러므로 kubelet 업그레이드를 원활하게 진행할 수 있을 것이지만,
안정화되기 전까지는 향후 API가 변할 수도 있으므로 업그레이드를 했을 때 절대로 문제가 없을 것이라고는 보장할 수는 없다.
안정화되기 전까지는 향후 API가 변할 수도 있으므로
업그레이드를 했을 때 절대로 문제가 없을 것이라고는 보장할 수는 없다.
{{< caution >}}
{{< note >}}
쿠버네티스의 장치 관리자 컴포넌트는 안정화된(GA) 기능이지만 _장치 플러그인 API_는 안정화되지 않았다.
장치 플러그인 API와 버전 호환성에 대한 정보는 [장치 플러그인 API 버전](/docs/reference/node/device-plugin-api-versions/)를 참고하라.
{{< /caution >}}
장치 플러그인 API와 버전 호환성에 대한 정보는
[장치 플러그인 API 버전](/docs/reference/node/device-plugin-api-versions/)를 참고하라.
{{< /note >}}
프로젝트로서, 쿠버네티스는 장치 플러그인 개발자에게 다음 사항을 권장한다.
@ -207,6 +213,7 @@ kubelet은 gRPC 서비스를 제공하여 사용 중인 장치를 검색하고,
service PodResourcesLister {
rpc List(ListPodResourcesRequest) returns (ListPodResourcesResponse) {}
rpc GetAllocatableResources(AllocatableResourcesRequest) returns (AllocatableResourcesResponse) {}
rpc Get(GetPodResourcesRequest) returns (GetPodResourcesResponse) {}
}
```
@ -214,7 +221,16 @@ service PodResourcesLister {
`List` 엔드포인트는 실행 중인 파드의 리소스에 대한 정보를 제공하며,
독점적으로 할당된 CPU의 ID, 장치 플러그인에 의해 보고된 장치 ID,
이러한 장치가 할당된 NUMA 노드의 ID와 같은 세부 정보를 함께 제공한다. 또한, NUMA 기반 머신의 경우, 컨테이너를 위해 예약된 메모리와 hugepage에 대한 정보를 포함한다.
이러한 장치가 할당된 NUMA 노드의 ID와 같은 세부 정보를 함께 제공한다.
또한, NUMA 기반 머신의 경우, 컨테이너를 위해 예약된 메모리와 hugepage에 대한 정보를 포함한다.
쿠버네티스 v1.27부터, `List` 엔드포인트는 `DynamicResourceAllocation` API에 의해
`ResourceClaims`에 할당된 실행 중인 파드에 대한 리소스 정보를 제공할 수 있다.
이 기능을 활성화하려면 `kubelet`을 실행할 때 다음 플래그를 사용해야 한다.
```
--feature-gates=DynamicResourceAllocation=true,KubeletPodResourcesDynamiceResources=true
```
```gRPC
// ListPodResourcesResponse는 List 함수가 반환하는 응답이다.
@ -235,6 +251,7 @@ message ContainerResources {
repeated ContainerDevices devices = 2;
repeated int64 cpu_ids = 3;
repeated ContainerMemory memory = 4;
repeated DynamicResource dynamic_resources = 5;
}
// ContainerMemory는 컨테이너에 할당된 메모리와 hugepage에 대한 정보를 포함한다.
@ -260,6 +277,28 @@ message ContainerDevices {
repeated string device_ids = 2;
TopologyInfo topology = 3;
}
// DynamicResource는 동적 리소스 할당에 의해 컨테이너에 할당된 장치에 대한 정보를 포함한다.
message DynamicResource {
string class_name = 1;
string claim_name = 2;
string claim_namespace = 3;
repeated ClaimResource claim_resources = 4;
}
// ClaimResource는 각 플러그인별 리소스 정보를 포함한다.
message ClaimResource {
repeated CDIDevice cdi_devices = 1 [(gogoproto.customname) = "CDIDevices"];
}
// CDIDevice는 CDI 장치 정보를 나타낸다.
message CDIDevice {
// Fully qualified CDI device name
// for example: vendor.com/gpu=gpudevice1
// see more details in the CDI specification:
// https://github.com/container-orchestrated-devices/container-device-interface/blob/main/SPEC.md
string name = 1;
}
```
{{< note >}}
`List` 엔드포인트의 `ContainerResources` 내부에 있는 cpu_ids은 특정 컨테이너에 할당된
@ -290,7 +329,6 @@ List() 엔드포인트와 함께 사용되어야 한다. `GetAllocableResources`
충분하지 않으며, kubelet을 다시 시작하여 올바른 리소스 용량과 할당 가능(allocatable) 리소스를 반영해야 한다.
{{< /note >}}
```gRPC
// AllocatableResourcesResponses에는 kubelet이 알고 있는 모든 장치에 대한 정보가 포함된다.
message AllocatableResourcesResponse {
@ -312,8 +350,8 @@ message AllocatableResourcesResponse {
`ContainerDevices` 는 장치가 어떤 NUMA 셀과 연관되는지를 선언하는 토폴로지 정보를 노출한다.
NUMA 셀은 불분명한(opaque) 정수 ID를 사용하여 식별되며, 이 값은
[kubelet에 등록할 때](/ko/docs/concepts/extend-kubernetes/compute-storage-net/device-plugins/#토폴로지-관리자로-장치-플러그인-통합) 장치 플러그인이 보고하는 것과 일치한다.
[kubelet에 등록할 때](/ko/docs/concepts/extend-kubernetes/compute-storage-net/device-plugins/#토폴로지-관리자로-장치-플러그인-통합)
장치 플러그인이 보고하는 것과 일치한다.
gRPC 서비스는 `/var/lib/kubelet/pod-resources/kubelet.sock` 의 유닉스 소켓을 통해 제공된다.
장치 플러그인 리소스에 대한 모니터링 에이전트는 데몬 또는 데몬셋으로 배포할 수 있다.
@ -323,20 +361,51 @@ gRPC 서비스는 `/var/lib/kubelet/pod-resources/kubelet.sock` 의 유닉스
`/var/lib/kubelet/pod-resources`
{{< glossary_tooltip text="볼륨" term_id="volume" >}}으로 마운트해야 한다.
`PodResourcesLister service` 를 지원하려면 `KubeletPodResources` [기능 게이트](/ko/docs/reference/command-line-tools-reference/feature-gates/)를 활성화해야 한다.
`PodResourcesLister service` 를 지원하려면 `KubeletPodResources`
[기능 게이트](/ko/docs/reference/command-line-tools-reference/feature-gates/)를 활성화해야 한다.
이것은 쿠버네티스 1.15부터 기본으로 활성화되어 있으며, 쿠버네티스 1.20부터는 v1 상태이다.
### `Get` gRPC 엔드포인트 {#grpc-endpoint-get}
{{< feature-state state="alpha" for_k8s_version="v1.27" >}}
`Get` 엔드포인트는 실행 중인 파드의 리소스 정보를 제공한다.
이 엔드포인트는 `List` 엔드포인트가 제공하는 것과 비슷한 정보를 노출한다.
`Get` 엔드포인트는 실행 중인 파드의 `PodName``PodNamespace`를 필요로 한다.
```gRPC
// GetPodResourcesRequest는 파드에 대한 정보를 포함한다.
message GetPodResourcesRequest {
string pod_name = 1;
string pod_namespace = 2;
}
```
이 기능을 활성화하려면 kubelet 서비스를 실행할 때 다음 플래그를 사용해야 한다.
```
--feature-gates=KubeletPodResourcesGet=true
```
`Get` 엔드포인트는 동적 리소스 할당 API에 의해 할당된
동적 리소스와 관련된 파드 정보를 제공할 수 있다.
이 기능을 활성화하려면 kubelet 서비스를 실행할 때 다음 플래그를 사용해야 한다.
```
--feature-gates=KubeletPodResourcesGet=true,DynamicResourceAllocation=true,KubeletPodResourcesDynamiceResources=true
```
## 토폴로지 관리자로 장치 플러그인 통합
{{< feature-state for_k8s_version="v1.18" state="beta" >}}
토폴로지 관리자는 kubelet 컴포넌트로, 리소스를 토폴로지 정렬 방식으로 조정할 수 있다.
이를 위해, 장치 플러그인 API가 `TopologyInfo` 구조체를 포함하도록 확장되었다.
이를 위해, 장치 플러그인 API가 `TopologyInfo` 구조체를 포함하도록
확장되었다.
```gRPC
message TopologyInfo {
repeated NUMANode nodes = 1;
repeated NUMANode nodes = 1;
}
message NUMANode {
@ -344,8 +413,10 @@ message NUMANode {
}
```
토폴로지 관리자를 활용하려는 장치 플러그인은 장치 ID 및 장치의 정상 상태와 함께 장치 등록의 일부로 채워진 TopologyInfo 구조체를 다시 보낼 수 있다.
그런 다음 장치 관리자는 이 정보를 사용하여 토폴로지 관리자와 상의하고 리소스 할당 결정을 내린다.
토폴로지 관리자를 활용하려는 장치 플러그인은 장치 ID 및 장치의 정상 상태와 함께
장치 등록의 일부로 채워진 TopologyInfo 구조체를 다시 보낼 수 있다.
그런 다음 장치 관리자는 이 정보를 사용하여
토폴로지 관리자와 상의하고 리소스 할당 결정을 내린다.
`TopologyInfo``nodes` 필드에 `nil`(기본값) 또는 NUMA 노드 목록을 설정하는 것을 지원한다.
이를 통해 복수의 NUMA 노드에 연관된 장치에 대해 장치 플러그인을 설정할 수 있다.
@ -366,8 +437,10 @@ pluginapi.Device{ID: "25102017", Health: pluginapi.Healthy, Topology:&pluginapi.
다음은 장치 플러그인 구현의 예이다.
* [AMD GPU 장치 플러그인](https://github.com/RadeonOpenCompute/k8s-device-plugin)
* 인텔 GPU, FPGA, QAT, VPU, SGX, DSA, DLB 및 IAA 장치용 [인텔 장치 플러그인](https://github.com/intel/intel-device-plugins-for-kubernetes)
* 하드웨어 지원 가상화를 위한 [KubeVirt 장치 플러그인](https://github.com/kubevirt/kubernetes-device-plugins)
* 인텔 GPU, FPGA, QAT, VPU, SGX, DSA, DLB 및 IAA 장치용
[인텔 장치 플러그인](https://github.com/intel/intel-device-plugins-for-kubernetes)
* 하드웨어 지원 가상화를 위한
[KubeVirt 장치 플러그인](https://github.com/kubevirt/kubernetes-device-plugins)
* [컨테이너에 최적화된 OS를 위한 NVIDIA GPU 장치 플러그인](https://github.com/GoogleCloudPlatform/container-engine-accelerators/tree/master/cmd/nvidia_gpu)
* [RDMA 장치 플러그인](https://github.com/hustcat/k8s-rdma-device-plugin)
* [SocketCAN 장치 플러그인](https://github.com/collabora/k8s-socketcan)
@ -377,8 +450,10 @@ pluginapi.Device{ID: "25102017", Health: pluginapi.Healthy, Topology:&pluginapi.
## {{% heading "whatsnext" %}}
* 장치 플러그인을 사용한 [GPU 리소스 스케줄링](/ko/docs/tasks/manage-gpus/scheduling-gpus/)에 대해 알아보기
* 노드에서의 [확장 리소스 알리기](/ko/docs/tasks/administer-cluster/extended-resource-node/)에 대해 배우기
* 장치 플러그인을 사용한 [GPU 리소스 스케줄링](/ko/docs/tasks/manage-gpus/scheduling-gpus/)에 대해
알아보기
* 노드에서의 [확장 리소스 알리기](/ko/docs/tasks/administer-cluster/extended-resource-node/)에 대해
배우기
* [토폴로지 관리자](/docs/tasks/administer-cluster/topology-manager/)에 대해 알아보기
* 쿠버네티스에서 [TLS 인그레스에 하드웨어 가속](/blog/2019/04/24/hardware-accelerated-ssl/tls-termination-in-ingress-controllers-using-kubernetes-device-plugins-and-runtimeclass/) 사용에 대해 읽기
* 쿠버네티스에서 [TLS 인그레스에 하드웨어 가속](/blog/2019/04/24/hardware-accelerated-ssl/tls-termination-in-ingress-controllers-using-kubernetes-device-plugins-and-runtimeclass/) 사용에 대해
읽기

View File

@ -16,7 +16,8 @@ weight: 10
사용 중인 클러스터와 호환되며 사용자의 요구 사항을 충족하는 CNI 플러그인을 사용해야 한다.
더 넓은 쿠버네티스 생태계에 다양한 플러그인이 (오픈소스와 클로즈드 소스로) 존재한다.
CNI 플러그인은 [쿠버네티스 네트워크 모델](/ko/docs/concepts/services-networking/#쿠버네티스-네트워크-모델)을 구현해야 한다.
CNI 플러그인은
[쿠버네티스 네트워크 모델](/ko/docs/concepts/services-networking/#쿠버네티스-네트워크-모델)을 구현해야 한다.
[v0.4.0](https://github.com/containernetworking/cni/blob/spec-v0.4.0/SPEC.md) 이상의
CNI 스펙과 호환되는 CNI 플러그인을 사용해야 한다.
@ -29,17 +30,21 @@ CNI 스펙 [v1.0.0](https://github.com/containernetworking/cni/blob/spec-v1.0.0/
## 설치
네트워킹 컨텍스트에서 컨테이너 런타임은 kubelet을 위한 CRI 서비스를 제공하도록 구성된 노드의 데몬이다.
특히, 컨테이너 런타임은 쿠버네티스 네트워크 모델을 구현하는 데 필요한 CNI 플러그인을 로드하도록 구성되어야 한다.
특히, 컨테이너 런타임은 쿠버네티스 네트워크 모델을 구현하는 데 필요한
CNI 플러그인을 로드하도록 구성되어야 한다.
{{< note >}}
쿠버네티스 1.24 이전까지는 `cni-bin-dir``network-plugin` 커맨드 라인 파라미터를 사용해 kubelet이 CNI 플러그인을 관리하게 할 수도 있었다.
이 커맨드 라인 파라미터들은 쿠버네티스 1.24에서 제거되었으며, CNI 관리는 더 이상 kubelet 범위에 포함되지 않는다.
쿠버네티스 1.24 이전까지는 `cni-bin-dir``network-plugin` 커맨드 라인 파라미터를 사용해
kubelet이 CNI 플러그인을 관리하게 할 수도 있었다.
이 커맨드 라인 파라미터들은 쿠버네티스 1.24에서 제거되었으며,
CNI 관리는 더 이상 kubelet 범위에 포함되지 않는다.
도커심 제거 후 문제가 발생하는 경우
[CNI 플러그인 관련 오류 문제 해결](/docs/tasks/administer-cluster/migrating-from-dockershim/troubleshooting-cni-plugin-related-errors/)을 참조하자.
{{< /note >}}
컨테이너 런타임에서 CNI 플러그인을 관리하는 방법에 관한 자세한 내용은 아래 예시와 같은 컨테이너 런타임에 대한 문서를 참조하자.
컨테이너 런타임에서 CNI 플러그인을 관리하는 방법에 관한 자세한 내용은
아래 예시와 같은 컨테이너 런타임에 대한 문서를 참조하자.
- [containerd](https://github.com/containerd/containerd/blob/main/script/setup/install-cni)
- [CRI-O](https://github.com/cri-o/cri-o/blob/main/contrib/cni/README.md)
@ -49,21 +54,28 @@ CNI 플러그인을 설치하고 관리하는 방법에 관한 자세한 내용
## 네트워크 플러그인 요구 사항
쿠버네티스를 빌드하거나 배포하는 플러그인 개발자와 사용자들을 위해, 플러그인은 kube-proxy를 지원하기 위한 특정 설정이 필요할 수도 있다.
쿠버네티스를 빌드하거나 배포하는 플러그인 개발자와 사용자들을 위해,
플러그인은 kube-proxy를 지원하기 위한 특정 설정이 필요할 수도 있다.
iptables 프록시는 iptables에 의존하며, 플러그인은 컨테이너 트래픽이 iptables에 사용 가능하도록 해야 한다.
예를 들어, 플러그인이 컨테이너를 리눅스 브릿지에 연결하는 경우, 플러그인은 `net/bridge/bridge-nf-call-iptables` sysctl을
예를 들어, 플러그인이 컨테이너를 리눅스 브릿지에 연결하는 경우,
플러그인은 `net/bridge/bridge-nf-call-iptables` sysctl을
`1`로 설정하여 iptables 프록시가 올바르게 작동하는지 확인해야 한다.
플러그인이 Linux 브리지를 사용하지 않고 대신 Open vSwitch나 다른 메커니즘을 사용하는 경우, 컨테이너 트래픽이 프록시에 대해 적절하게 라우팅되도록 해야 한다.
플러그인이 Linux 브리지를 사용하지 않고 대신 Open vSwitch나 다른 메커니즘을 사용하는 경우,
컨테이너 트래픽이 프록시에 대해 적절하게 라우팅되도록 해야 한다.
kubelet 네트워크 플러그인이 지정되지 않은 경우, 기본적으로 `noop` 플러그인이 사용되며,
`net/bridge/bridge-nf-call-iptables=1`을 설정하여 간단한 구성(브릿지가 있는 도커 등)이 iptables 프록시에서 올바르게 작동하도록 한다.
`net/bridge/bridge-nf-call-iptables=1`을 설정하여 간단한 구성(브릿지가 있는 도커 등)이
iptables 프록시에서 올바르게 작동하도록 한다.
### 루프백 CNI
쿠버네티스 네트워크 모델을 구현하기 위해 노드에 설치된 CNI 플러그인 외에도, 쿠버네티스는 각 샌드박스(파드 샌드박스, VM 샌드박스 등)에
쿠버네티스 네트워크 모델을 구현하기 위해 노드에 설치된 CNI 플러그인 외에도,
쿠버네티스는 각 샌드박스(파드 샌드박스, VM 샌드박스 등)에
사용되는 루프백 인터페이스 `lo`를 제공하기 위한 컨테이너 런타임도 요구한다.
루프백 인터페이스 구현은 [CNI 루프백 플러그인](https://github.com/containernetworking/plugins/blob/master/plugins/main/loopback/loopback.go)을
재사용하거나 자체 코드를 개발하여 수행할 수 있다. ([CRI-O 예시 참조](https://github.com/cri-o/ocicni/blob/release-1.24/pkg/ocicni/util_linux.go#L91))
루프백 인터페이스 구현은
[CNI 루프백 플러그인](https://github.com/containernetworking/plugins/blob/master/plugins/main/loopback/loopback.go)을
재사용하거나 자체 코드를 개발하여 수행할 수 있다
([CRI-O 예시 참조](https://github.com/cri-o/ocicni/blob/release-1.24/pkg/ocicni/util_linux.go#L91)).
### hostPort 지원
@ -97,7 +109,8 @@ CNI 네트워킹 플러그인은 `hostPort` 를 지원한다. CNI 플러그인
},
{
"type": "portmap",
"capabilities": {"portMappings": true}
"capabilities": {"portMappings": true},
"externalSetMarkChain": "KUBE-MARK-MASQ"
}
]
}
@ -112,7 +125,8 @@ CNI 네트워킹 플러그인은 파드 수신 및 송신 트래픽 셰이핑도
플러그인을 사용하거나 대역폭 제어 기능이 있는 자체 플러그인을 사용할 수 있다.
트래픽 셰이핑 지원을 활성화하려면, CNI 구성 파일 (기본값 `/etc/cni/net.d`)에 `bandwidth` 플러그인을
추가하고, 바이너리가 CNI 실행 파일 디렉터리(기본값: `/opt/cni/bin`)에 포함되어 있는지 확인한다.
추가하고, 바이너리가 CNI 실행 파일 디렉터리(기본값: `/opt/cni/bin`)에 포함되어 있는지
확인한다.
```json
{

View File

@ -119,6 +119,7 @@ kubectl edit SampleDB/example-database # 일부 설정을 수동으로 변경하
* [kubebuilder](https://book.kubebuilder.io/) 사용하기
* [KubeOps](https://buehler.github.io/dotnet-operator-sdk/) (.NET 오퍼레이터 SDK)
* [KUDO](https://kudo.dev/) (Kubernetes Universal Declarative Operator)
* [Mast](https://docs.ansi.services/mast/user_guide/operator/)
* 웹훅(WebHook)과 함께 [Metacontroller](https://metacontroller.github.io/metacontroller/intro.html)를
사용하여 직접 구현하기
* [오퍼레이터 프레임워크](https://operatorframework.io)

View File

@ -36,76 +36,105 @@ no_list: true
![배포 혁명](/images/docs/Container_Evolution.svg)
**전통적인 배포 시대:**
초기 조직은 애플리케이션을 물리 서버에서 실행했었다. 한 물리 서버에서 여러 애플리케이션의 리소스 한계를 정의할 방법이 없었기에,
리소스 할당의 문제가 발생했다. 예를 들어 물리 서버 하나에서 여러 애플리케이션을 실행하면, 리소스 전부를 차지하는 애플리케이션 인스턴스가 있을 수 있고,
결과적으로는 다른 애플리케이션의 성능이 저하될 수 있었다. 이에 대한 해결책으로 서로 다른 여러 물리 서버에서 각 애플리케이션을 실행할 수도 있다.
초기 조직은 애플리케이션을 물리 서버에서 실행했었다.
한 물리 서버에서 여러 애플리케이션의 리소스 한계를 정의할 방법이 없었기에,
리소스 할당의 문제가 발생했다. 예를 들어 물리 서버 하나에서 여러 애플리케이션을 실행하면,
리소스 전부를 차지하는 애플리케이션 인스턴스가 있을 수 있고,
결과적으로는 다른 애플리케이션의 성능이 저하될 수 있었다.
이에 대한 해결책으로 서로 다른 여러 물리 서버에서 각 애플리케이션을 실행할 수도 있다.
그러나 이는 리소스가 충분히 활용되지 않는다는 점에서 확장 가능하지 않았으며, 조직이 많은 물리 서버를 유지하는 데에 높은 비용이 들었다.
**가상화된 배포 시대:** 그 해결책으로 가상화가 도입되었다. 이는 단일 물리 서버의 CPU에서 여러 가상 시스템 (VM)을 실행할 수 있게 한다.
가상화를 사용하면 VM간에 애플리케이션을 격리하고 애플리케이션의 정보를 다른 애플리케이션에서 자유롭게 액세스할 수 없으므로, 일정 수준의 보안성을 제공할 수 있다.
**가상화된 배포 시대:** 그 해결책으로 가상화가 도입되었다.
이는 단일 물리 서버의 CPU에서 여러 가상 시스템 (VM)을 실행할 수 있게 한다.
가상화를 사용하면 VM간에 애플리케이션을 격리하고 애플리케이션의 정보를
다른 애플리케이션에서 자유롭게 액세스할 수 없으므로, 일정 수준의 보안성을 제공할 수 있다.
가상화를 사용하면 물리 서버에서 리소스를 보다 효율적으로 활용할 수 있으며, 쉽게 애플리케이션을 추가하거나 업데이트할 수 있고
하드웨어 비용을 절감할 수 있어 더 나은 확장성을 제공한다. 가상화를 통해 일련의 물리 리소스를 폐기 가능한(disposable)
가상 머신으로 구성된 클러스터로 만들 수 있다.
가상화를 사용하면 물리 서버에서 리소스를 보다 효율적으로 활용할 수 있으며,
쉽게 애플리케이션을 추가하거나 업데이트할 수 있고
하드웨어 비용을 절감할 수 있어 더 나은 확장성을 제공한다.
가상화를 통해 일련의 물리 리소스를 폐기 가능한(disposable) 가상 머신으로 구성된 클러스터로 만들 수 있다.
각 VM은 가상화된 하드웨어 상에서 자체 운영체제를 포함한 모든 구성 요소를 실행하는 하나의 완전한 머신이다.
각 VM은 가상화된 하드웨어 상에서 자체 운영체제를 포함한
모든 구성 요소를 실행하는 하나의 완전한 머신이다.
**컨테이너 개발 시대:** 컨테이너는 VM과 유사하지만 격리 속성을 완화하여 애플리케이션 간에 운영체제(OS)를 공유한다.
그러므로 컨테이너는 가볍다고 여겨진다. VM과 마찬가지로 컨테이너에는 자체 파일 시스템, CPU 점유율, 메모리, 프로세스 공간 등이 있다.
기본 인프라와의 종속성을 끊었기 때문에, 클라우드나 OS 배포본에 모두 이식할 수 있다.
**컨테이너 개발 시대:** 컨테이너는 VM과 유사하지만
격리 속성을 완화하여 애플리케이션 간에 운영체제(OS)를 공유한다.
그러므로 컨테이너는 가볍다고 여겨진다.
VM과 마찬가지로 컨테이너에는 자체 파일 시스템, CPU 점유율, 메모리, 프로세스 공간 등이 있다.
기본 인프라와의 종속성을 끊었기 때문에,
클라우드나 OS 배포본에 모두 이식할 수 있다.
컨테이너는 다음과 같은 추가적인 혜택을 제공하기 때문에 유명해졌다.
* 기민한 애플리케이션 생성과 배포: VM 이미지를 사용하는 것에 비해 컨테이너 이미지 생성이 보다 쉽고 효율적이다.
* 지속적인 개발, 통합 및 배포: 안정적이고 주기적으로 컨테이너 이미지를 빌드해서 배포할 수 있고 (이미지의 불변성 덕에) 빠르고
* 기민한 애플리케이션 생성과 배포: VM 이미지를 사용하는 것에 비해
컨테이너 이미지 생성이 보다 쉽고 효율적이다.
* 지속적인 개발, 통합 및 배포: 안정적이고 주기적으로 컨테이너 이미지를 빌드하여 배포할 수 있고,
(이미지의 불변성 덕에) 빠르고
효율적으로 롤백할 수 있다.
* 개발과 운영의 관심사 분리: 배포 시점이 아닌 빌드/릴리스 시점에 애플리케이션 컨테이너 이미지를 만들기 때문에, 애플리케이션이
인프라스트럭처에서 분리된다.
* 가시성(observability): OS 수준의 정보와 메트릭에 머무르지 않고, 애플리케이션의 헬스와 그 밖의 시그널을 볼 수 있다.
* 개발, 테스팅 및 운영 환경에 걸친 일관성: 랩탑에서도 클라우드에서와 동일하게 구동된다.
* 클라우드 및 OS 배포판 간 이식성: Ubuntu, RHEL, CoreOS, 온-프레미스, 주요 퍼블릭 클라우드와 어디에서든 구동된다.
* 개발과 운영의 관심사 분리: 배포 시점이 아닌 빌드/릴리스 시점에
애플리케이션 컨테이너 이미지를 만들기 때문에,
애플리케이션을 인프라스트럭처와 분리하여 개발할 수 있게 된다.
* 가시성(observability): OS 수준의 정보와 메트릭에 머무르지 않고,
애플리케이션의 헬스와 그 밖의 시그널을 볼 수 있다.
* 개발, 테스팅 및 운영 환경에 걸친 일관성:
클라우드에서 구동되는 것과 동일하게 랩탑에서도 구동된다.
* 클라우드 및 OS 배포판 간 이식성: Ubuntu, RHEL, CoreOS,
온-프레미스, 주요 퍼블릭 클라우드와 어디에서든 구동된다.
* 애플리케이션 중심 관리: 가상 하드웨어 상에서 OS를 실행하는 수준에서 논리적인 리소스를 사용하는 OS 상에서 애플리케이션을
실행하는 수준으로 추상화 수준이 높아진다.
* 느슨하게 커플되고, 분산되고, 유연하며, 자유로운 마이크로서비스: 애플리케이션은 단일 목적의 머신에서 모놀리식 스택으로 구동되지 않고
보다 작고 독립적인 단위로 쪼개져서 동적으로 배포되고 관리될 수 있다.
* 느슨하게 커플되고, 분산되고, 유연하며, 자유로운 마이크로서비스:
애플리케이션은 단일 목적의 머신에서 모놀리식 스택으로 구동되지 않고
더 작고 독립적인 단위로 쪼개져서 동적으로 배포되고 관리될 수 있다.
* 리소스 격리: 애플리케이션 성능을 예측할 수 있다.
* 리소스 사용량: 고효율 고집적.
## 쿠버네티스가 왜 필요하고 무엇을 할 수 있나 {#why-you-need-kubernetes-and-what-can-it-do}
컨테이너는 애플리케이션을 포장하고 실행하는 좋은 방법이다. 프로덕션 환경에서는 애플리케이션을 실행하는 컨테이너를 관리하고
가동 중지 시간이 없는지 확인해야 한다. 예를 들어 컨테이너가 다운되면 다른 컨테이너를 다시 시작해야 한다.
컨테이너는 애플리케이션을 포장하고 실행하는 좋은 방법이다.
프로덕션 환경에서는 애플리케이션을 실행하는 컨테이너를 관리하고 가동 중지 시간이 없는지 확인해야 한다.
예를 들어 컨테이너가 다운되면 다른 컨테이너를 다시 시작해야 한다.
이 문제를 시스템에 의해 처리한다면 더 쉽지 않을까?
그것이 쿠버네티스가 필요한 이유이다! 쿠버네티스는 분산 시스템을 탄력적으로 실행하기 위한 프레임 워크를 제공한다.
애플리케이션의 확장과 장애 조치를 처리하고, 배포 패턴 등을 제공한다. 예를 들어, 쿠버네티스는 시스템의 카나리아 배포를 쉽게 관리할 수 있다.
그것이 쿠버네티스가 필요한 이유이다!
쿠버네티스는 분산 시스템을 탄력적으로 실행하기 위한 프레임 워크를 제공한다.
애플리케이션의 확장과 장애 조치를 처리하고, 배포 패턴 등을 제공한다.
예를 들어, 쿠버네티스는 시스템의 카나리아 배포를 쉽게 관리할 수 있다.
쿠버네티스는 다음을 제공한다.
* **서비스 디스커버리와 로드 밸런싱**
쿠버네티스는 DNS 이름을 사용하거나 자체 IP 주소를 사용하여 컨테이너를 노출할 수 있다. 컨테이너에 대한 트래픽이 많으면,
쿠버네티스는 DNS 이름을 사용하거나 자체 IP 주소를 사용하여 컨테이너를 노출할 수 있다.
컨테이너에 대한 트래픽이 많으면,
쿠버네티스는 네트워크 트래픽을 로드밸런싱하고 배포하여 배포가 안정적으로 이루어질 수 있다.
* **스토리지 오케스트레이션**
쿠버네티스를 사용하면 로컬 저장소, 공용 클라우드 공급자 등과 같이 원하는 저장소 시스템을 자동으로 탑재할 수 있다
쿠버네티스를 사용하면 로컬 저장소, 공용 클라우드 공급자 등과 같이
원하는 저장소 시스템을 자동으로 탑재할 수 있다
* **자동화된 롤아웃과 롤백**
쿠버네티스를 사용하여 배포된 컨테이너의 원하는 상태를 서술할 수 있으며 현재 상태를 원하는 상태로 설정한 속도에 따라 변경할 수 있다.
예를 들어 쿠버네티스를 자동화해서 배포용 새 컨테이너를 만들고, 기존 컨테이너를 제거하고, 모든 리소스를 새 컨테이너에 적용할 수 있다.
쿠버네티스를 사용하여 배포된 컨테이너의 원하는 상태를 서술할 수 있으며
현재 상태를 원하는 상태로 설정한 속도에 따라 변경할 수 있다.
예를 들어 쿠버네티스를 자동화해서 배포용 새 컨테이너를 만들고,
기존 컨테이너를 제거하고, 모든 리소스를 새 컨테이너에 적용할 수 있다.
* **자동화된 빈 패킹(bin packing)**
컨테이너화된 작업을 실행하는데 사용할 수 있는 쿠버네티스 클러스터 노드를 제공한다. 각 컨테이너가 필요로 하는 CPU와 메모리(RAM)를
쿠버네티스에게 지시한다. 쿠버네티스는 컨테이너를 노드에 맞추어서 리소스를 가장 잘 사용할 수 있도록 해준다.
컨테이너화된 작업을 실행하는데 사용할 수 있는 쿠버네티스 클러스터 노드를 제공한다.
각 컨테이너가 필요로 하는 CPU와 메모리(RAM)를 쿠버네티스에게 지시한다.
쿠버네티스는 컨테이너를 노드에 맞추어서 리소스를 가장 잘 사용할 수 있도록 해준다.
* **자동화된 복구(self-healing)**
쿠버네티스는 실패한 컨테이너를 다시 시작하고, 컨테이너를 교체하며, '사용자 정의 상태 검사'에 응답하지 않는 컨테이너를 죽이고,
쿠버네티스는 실패한 컨테이너를 다시 시작하고, 컨테이너를 교체하며,
'사용자 정의 상태 검사'에 응답하지 않는 컨테이너를 죽이고,
서비스 준비가 끝날 때까지 그러한 과정을 클라이언트에 보여주지 않는다.
* **시크릿과 구성 관리**
쿠버네티스를 사용하면 암호, OAuth 토큰 및 SSH 키와 같은 중요한 정보를 저장하고 관리할 수 있다.
컨테이너 이미지를 재구성하지 않고 스택 구성에 시크릿을 노출하지 않고도 시크릿 및 애플리케이션 구성을 배포 및 업데이트할 수 있다.
컨테이너 이미지를 재구성하지 않고 스택 구성에 시크릿을 노출하지 않고도
시크릿 및 애플리케이션 구성을 배포 및 업데이트할 수 있다.
## 쿠버네티스가 아닌 것
쿠버네티스는 전통적인, 모든 것이 포함된 Platform as a Service(PaaS)가 아니다.
쿠버네티스는 하드웨어 수준보다는 컨테이너 수준에서 운영되기 때문에, PaaS가 일반적으로 제공하는 배포, 스케일링,
로드 밸런싱과 같은 기능을 제공하며, 사용자가 로깅, 모니터링 및 알림 솔루션을 통합할 수 있다. 하지만,
쿠버네티스는 모놀리식(monolithic)이 아니어서, 이런 기본 솔루션이 선택적이며 추가나 제거가 용이하다.
쿠버네티스는 하드웨어 수준보다는 컨테이너 수준에서 운영되기 때문에,
PaaS가 일반적으로 제공하는 배포, 스케일링, 로드 밸런싱과 같은 기능을 제공하며,
사용자가 로깅, 모니터링 및 알림 솔루션을 통합할 수 있다.
하지만, 쿠버네티스는 모놀리식(monolithic)이 아니어서,
이런 기본 솔루션이 선택적이며 추가나 제거가 용이하다.
쿠버네티스는 개발자 플랫폼을 만드는 구성 요소를 제공하지만, 필요한 경우 사용자의 선택권과 유연성을 지켜준다.
쿠버네티스는:
@ -113,20 +142,26 @@ no_list: true
* 지원하는 애플리케이션의 유형을 제약하지 않는다. 쿠버네티스는 상태 유지가 필요 없는(stateless) 워크로드,
상태 유지가 필요한(stateful) 워크로드, 데이터 처리를 위한 워크로드를 포함해서 극단적으로 다양한 워크로드를 지원하는 것을 목표로 한다.
애플리케이션이 컨테이너에서 구동될 수 있다면, 쿠버네티스에서도 잘 동작할 것이다.
* 소스 코드를 배포하지 않으며 애플리케이션을 빌드하지 않는다. 지속적인 통합과 전달과 배포, 곧 CI/CD 워크플로우는 조직 문화와
* 소스 코드를 배포하지 않으며 애플리케이션을 빌드하지 않는다.
지속적인 통합과 전달과 배포, 곧 CI/CD 워크플로우는 조직 문화와
취향에 따를 뿐만 아니라 기술적인 요구사항으로 결정된다.
* 애플리케이션 레벨의 서비스를 제공하지 않는다. 애플리케이션 레벨의 서비스에는 미들웨어(예, 메시지 버스),
* 애플리케이션 레벨의 서비스를 제공하지 않는다.
애플리케이션 레벨의 서비스에는 미들웨어(예, 메시지 버스),
데이터 처리 프레임워크(예, Spark), 데이터베이스(예, MySQL), 캐시 또는 클러스터 스토리지 시스템(예, Ceph) 등이 있다.
이런 컴포넌트는 쿠버네티스 상에서 구동될 수 있고, 쿠버네티스 상에서 구동 중인 애플리케이션이
[Open Service Broker](https://openservicebrokerapi.org/)와 같은 이식 가능한 메커니즘을 통해 접근할 수도 있다.
* 로깅, 모니터링 또는 경보 솔루션을 포함하지 않는다. 개념 증명을 위한 일부 통합이나, 메트릭을 수집하고 노출하는 메커니즘을 제공한다.
* 기본 설정 언어/시스템(예, Jsonnet)을 제공하거나 요구하지 않는다. 선언적 명세의 임의적인 형식을 목적으로 하는 선언적 API를 제공한다.
* 포괄적인 머신 설정, 유지보수, 관리, 자동 복구 시스템을 제공하거나 채택하지 않는다.
* 로깅, 모니터링 또는 경보 솔루션을 포함하지 않는다.
개념 증명을 위한 일부 통합이나, 메트릭을 수집하고 노출하는 메커니즘을 제공한다.
* 기본 설정 언어/시스템(예, Jsonnet)을 제공하거나 요구하지 않는다.
선언적 명세의 임의적인 형식을 목적으로 하는 선언적 API를 제공한다.
* 포괄적인 머신 설정, 유지보수, 관리, 자동 복구 시스템을
제공하거나 채택하지 않는다.
* 추가로, 쿠버네티스는 단순한 오케스트레이션 시스템이 아니다. 사실, 쿠버네티스는 오케스트레이션의 필요성을 없애준다.
오케스트레이션의 기술적인 정의는 A를 먼저 한 다음, B를 하고, C를 하는 것과 같이 정의된 워크플로우를 수행하는 것이다.
반면에, 쿠버네티스는 독립적이고 조합 가능한 제어 프로세스들로 구성되어 있다. 이 프로세스는 지속적으로 현재 상태를 입력받은
의도한 상태로 나아가도록 한다. A에서 C로 어떻게 갔는지는 상관이 없다. 중앙화된 제어도 필요치 않다. 이로써 시스템이 보다 더
사용하기 쉬워지고, 강력해지며, 견고하고, 회복력을 갖추게 되며, 확장 가능해진다.
반면에, 쿠버네티스는 독립적이고 조합 가능한 제어 프로세스들로 구성되어 있다.
이 프로세스는 지속적으로 현재 상태를 입력받은 의도한 상태로 나아가도록 한다.
A에서 C로 어떻게 갔는지는 상관이 없다. 중앙화된 제어도 필요치 않다.
이로써 시스템이 보다 더 사용하기 쉬워지고, 강력해지며, 견고하고, 회복력을 갖추게 되며, 확장 가능해진다.
## {{% heading "whatsnext" %}}

View File

@ -122,10 +122,20 @@ kube-controller-manager와 마찬가지로 cloud-controller-manager는 논리적
[클러스터-레벨 로깅](/ko/docs/concepts/cluster-administration/logging/) 메커니즘은
검색/열람 인터페이스와 함께 중앙 로그 저장소에 컨테이너 로그를 저장하는 책임을 진다.
### 네트워크 플러그인
[네트워크 플러그인](/ko/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/)은
컨테이너 네트워크 인터페이스(Container Network Interface, CNI) 스펙을 구현한 소프트웨어 구성 요소이다.
네트워크 플러그인은 파드에 IP주소를 할당하고 클러스터 내의 다른 파드와 통신할 수 있도록 해 준다.
## {{% heading "whatsnext" %}}
* [노드](/ko/docs/concepts/architecture/nodes/)에 대해 더 배우기
* [컨트롤러](/ko/docs/concepts/architecture/controller/)에 대해 더 배우기
* [kube-scheduler](/ko/docs/concepts/scheduling-eviction/kube-scheduler/)에 대해 더 배우기
* etcd의 공식 [문서](https://etcd.io/docs/) 읽기
다음에 대해 더 살펴본다.
* [노드](/ko/docs/concepts/architecture/nodes/) 및 [노드와 컨트롤 플레인 간의 통신](/ko/docs/concepts/architecture/control-plane-node-communication/).
* 쿠버네티스 [컨트롤러](/ko/docs/concepts/architecture/controller/).
* 쿠버네티스 기본 스케줄러인 [kube-scheduler](/ko/docs/concepts/scheduling-eviction/kube-scheduler/).
* etcd의 공식 [문서](https://etcd.io/docs/).
* 쿠버네티스의 몇 가지 [컨테이너 런타임](/ko/docs/setup/production-environment/container-runtimes/).
* [cloud-controller-manager](/docs/concepts/architecture/cloud-controller/)를 사용하여 클라우드 공급자와 연동하기.
* [kubectl](/docs/reference/generated/kubectl/kubectl-commands) 명령.

View File

@ -82,13 +82,9 @@ IDL(인터페이스 정의 언어) 파일을 참고한다.
### OpenAPI V3
{{< feature-state state="beta" for_k8s_version="v1.24" >}}
{{< feature-state state="stable" for_k8s_version="v1.27" >}}
쿠버네티스 {{< param "version" >}} 버전은 OpenAPI v3 API 발행(publishing)에 대한 베타 지원을 제공한다.
이는 베타 기능이며 기본적으로 활성화되어 있다.
kube-apiserver 구성 요소에
`OpenAPIV3` [기능 게이트](/ko/docs/reference/command-line-tools-reference/feature-gates/)를 비활성화하여
이 베타 기능을 비활성화할 수 있다.
쿠버네티스는 쿠버네티스 API에 대한 설명을 OpenAPI v3로 발행(publishing)한다.
`/openapi/v3` 디스커버리 엔드포인트는 사용 가능한 모든
그룹/버전의 목록을 제공한다. 이 엔드포인트는 JSON 만을 반환한다.
@ -153,11 +149,37 @@ kube-apiserver 구성 요소에
</tbody>
</table>
OpenAPI V3 가져오기의 Golang 구현은 `k8s.io/client-go/openapi3` 패키지를 확인한다.
## 지속성
쿠버네티스는 오브젝트의 직렬화된 상태를
{{< glossary_tooltip term_id="etcd" >}}에 기록하여 저장한다.
## API 디스커버리
클러스터에서 지원하는 모든 그룹 버전의 목록이
`/api``/apis` 엔드포인트에 발행된다.
또한 각 그룹 버전은 지원하는 리소스 목록을 `/apis/<group>/<version>`(예:
`/apis/rbac.authorization.k8s.io/v1alpha1`)에 노출한다.
kubectl은 클러스터가 지원하는 리소스 목록을 가져오는 데에
이러한 엔드포인트를 사용한다.
### 합산(aggregated) 디스커버리
{{< feature-state state="beta" for_k8s_version="v1.27" >}}
쿠버네티스는 클러스터가 지원하는 리소스 정보를 각 그룹 버전별 API로 발행하는 것 대신
2개의 엔드포인트(`/api` 및 `/apis`)로 발행하는
합산 디스커버리를 베타 수준으로 지원한다.
이러한 엔드포인트를 사용하면 일반적인 쿠버네티스 클러스터에 대한 디스커버리 시
전송되는 요청의 수를 대폭 줄일 수 있다.
이러한 요청은 각 엔드포인트에 요청을 보낼 때
Accept 헤더에 다음과 같이 합산 디스커버리임을 나타내면 된다.
`Accept: application/json;v=v2beta1;g=apidiscovery.k8s.io;as=APIGroupDiscoveryList`.
이 엔드포인트는 ETag 및 protobuf 인코딩도 지원한다.
## API 그룹과 버전 규칙
필드를 쉽게 제거하거나 리소스 표현을 재구성하기 위해,