277 lines
15 KiB
Markdown
277 lines
15 KiB
Markdown
---
|
|
# reviewers:
|
|
# - freehan
|
|
title: 엔드포인트슬라이스
|
|
content_type: concept
|
|
weight: 60
|
|
description: >-
|
|
엔드포인트슬라이스 API는 서비스가 대규모 백엔드를 처리할 수 있도록 확장할 수 있게 해주고,
|
|
클러스터가 정상적인 백엔드의 리스트를 효율적으로 업데이트 할 수 있도록
|
|
쿠버네티스가 사용하는 메커니즘이다.
|
|
---
|
|
|
|
|
|
<!-- overview -->
|
|
|
|
{{< feature-state for_k8s_version="v1.21" state="stable" >}}
|
|
|
|
쿠버네티스의 _엔드포인트슬라이스_ API 는 쿠버네티스 클러스터 내의 네트워크 엔드포인트를
|
|
추적하는 방법을 제공한다. 엔드포인트슬라이스는 [엔드포인트](/ko/docs/concepts/services-networking/service/#endpoints)보다 더 유동적이고, 확장 가능한
|
|
대안을 제안한다.
|
|
|
|
<!-- body -->
|
|
|
|
## 엔드포인트슬라이스 API {#endpointslice-resource}
|
|
|
|
쿠버네티스에서 엔드포인트슬라이스는 일련의 네트워크 엔드포인트에 대한
|
|
참조를 포함한다. 쿠버네티스 서비스에 {{< glossary_tooltip text="셀렉터"
|
|
term_id="selector" >}}가 지정되면 컨트롤 플레인은 자동으로
|
|
엔드포인트슬라이스를 생성한다. 이 엔드포인트슬라이스는
|
|
서비스 셀렉터와 매치되는 모든 파드들을 포함하고 참조한다. 엔드포인트슬라이스는
|
|
프로토콜, 포트 번호 및 서비스 이름의 고유한 조합을 통해 네트워크 엔드포인트를
|
|
그룹화한다.
|
|
엔드포인트슬라이스 오브젝트의 이름은 유효한
|
|
[DNS 서브도메인 이름](/ko/docs/concepts/overview/working-with-objects/names/#dns-서브도메인-이름)이어야 한다.
|
|
|
|
예를 들어, 여기에 `example` 쿠버네티스 서비스가 소유하는 엔드포인트슬라이스
|
|
객체 샘플이 있다.
|
|
|
|
```yaml
|
|
apiVersion: discovery.k8s.io/v1
|
|
kind: EndpointSlice
|
|
metadata:
|
|
name: example-abc
|
|
labels:
|
|
kubernetes.io/service-name: example
|
|
addressType: IPv4
|
|
ports:
|
|
- name: http
|
|
protocol: TCP
|
|
port: 80
|
|
endpoints:
|
|
- addresses:
|
|
- "10.1.2.3"
|
|
conditions:
|
|
ready: true
|
|
hostname: pod-1
|
|
nodeName: node-1
|
|
zone: us-west2-a
|
|
```
|
|
|
|
기본적으로, 컨트롤 플레인은 각각 100개 이하의 엔드포인트를
|
|
갖도록 엔드포인트슬라이스를
|
|
생성하고 관리한다. `--max-endpoints-per-slice`
|
|
{{< glossary_tooltip text="kube-controller-manager" term_id="kube-controller-manager" >}}
|
|
플래그를 사용하여, 최대 1000개까지 구성할 수 있다.
|
|
|
|
엔드포인트슬라이스는 내부 트래픽을 라우트하는 방법에 대해
|
|
{{< glossary_tooltip term_id="kube-proxy" text="kube-proxy" >}}에
|
|
신뢰할 수 있는 소스로 역할을 할 수 있다.
|
|
|
|
### 주소 유형
|
|
|
|
엔드포인트슬라이스는 다음 주소 유형을 지원한다.
|
|
|
|
* IPv4
|
|
* IPv6
|
|
* FQDN (전체 주소 도메인 이름)
|
|
|
|
각 엔드포인트슬라이스 객체는 특정한 IP 주소 유형을 나타낸다.
|
|
IPv4와 IPv6를 사용할 수 있는 서비스가 있을 경우,
|
|
최소 두개의 엔드포인트슬라이스 객체가 존재한다(IPv4를 위해 하나, IPv6를 위해 하나).
|
|
|
|
### 컨디션
|
|
|
|
엔드포인트슬라이스 API는 컨슈머에게 유용한 엔드포인트에 대한 조건을 저장한다.
|
|
조건은 `ready`, `serving` 및 `Terminating` 세 가지가 있다.
|
|
|
|
#### Ready
|
|
|
|
`ready`는 파드의 `Ready` 조건에 매핑되는 조건이다. `Ready` 조건이 `True`로 설정된 실행 중인 파드는
|
|
이 엔드포인트슬라이스 조건도 `true`로 설정되어야 한다. 호환성의
|
|
이유로, 파드가 종료될 때 `ready`는 절대 `true`가 되면 안 된다. 컨슈머는 `serving` 조건을 참조하여
|
|
파드 종료 준비 상태(readiness)를 검사해야 한다.
|
|
이 규칙의 유일한 예외는 `spec.publishNotReadyAddresses`가 `true`로 설정된 서비스이다.
|
|
이러한 서비스의 엔드 포인트는 항상 `ready`조건이 `true`로 설정된다.
|
|
|
|
#### Serving
|
|
|
|
{{< feature-state for_k8s_version="v1.22" state="beta" >}}
|
|
|
|
`serving`은 종료 상태를 고려하지 않는다는 점을 제외하면 `ready` 조건과 동일하다.
|
|
엔드포인트슬라이스 API 컨슈머는 파드가 종료되는 동안 파드 준비 상태에 관심이 있다면
|
|
이 조건을 확인해야 한다.
|
|
|
|
{{< note >}}
|
|
|
|
`serving`은 `ready`와 거의 동일하지만 `ready`의 기존 의미가 깨지는 것을 방지하기 위해 추가되었다.
|
|
엔드포인트를 종료하기 위해 `ready`가 `true` 일 수 있다면 기존 클라이언트에게는 예상치 못한 일이 될 수 있다.
|
|
역사적으로 종료된 엔드포인트는 처음부터 엔드포인트 또는 엔드포인트슬라이스 API에 포함되지 않았기 때문이다.
|
|
이러한 이유로 `ready`는 엔드포인트 종료를 위해 _always_ `false`이며,
|
|
클라이언트가 `ready`에 대한 기존 의미와 관계없이 파드 종료 준비 상태를
|
|
추적 할 수 있도록 v1.20에 새로운 조건 `serving`이 추가되었다.
|
|
|
|
{{< /note >}}
|
|
|
|
#### Terminating
|
|
|
|
{{< feature-state for_k8s_version="v1.22" state="beta" >}}
|
|
|
|
`종료(Terminating)`는 엔드포인트가 종료되는지 여부를 나타내는 조건이다.
|
|
파드의 경우 삭제 타임 스탬프가 설정된 모든 파드이다.
|
|
|
|
### 토폴로지 정보 {#topology}
|
|
|
|
엔드포인트슬라이스 내의 각 엔드 포인트는 관련 토폴로지 정보를 포함할 수 있다.
|
|
토폴로지 정보에는 엔드 포인트의 위치와 해당 노드 및
|
|
영역에 대한 정보가 포함된다. 엔드포인트슬라이스의 다음의 엔드 포인트별
|
|
필드에서 사용할 수 있다.
|
|
|
|
*`nodeName` - 이 엔드 포인트가 있는 노드의 이름이다.
|
|
*`zone` - 이 엔드 포인트가 있는 영역이다.
|
|
|
|
{{< note >}}
|
|
v1 API에서는, 전용 필드 `nodeName` 및 `zone` 을 위해 엔드 포인트별
|
|
`topology` 가 효과적으로 제거되었다.
|
|
|
|
`EndpointSlice` 리소스의 `endpoint` 필드에 임의의 토폴로지 필드를 설정하는 것은
|
|
더 이상 사용되지 않으며 v1 API에서 지원되지 않는다.
|
|
대신, v1 API는 개별 `nodeName` 및 `zone` 필드 설정을 지원한다.
|
|
이러한 필드는 API 버전 간에 자동으로 번역된다.
|
|
예를 들어, v1beta1 API의 `topology` 필드에 있는 `"topology.kubernetes.io/zone"` 키 값은
|
|
v1 API의 `zone` 필드로 접근할 수 있다.
|
|
{{< /note >}}
|
|
|
|
### 관리
|
|
|
|
대부분의 경우, 컨트롤 플레인(특히, 엔드포인트슬라이스
|
|
{{< glossary_tooltip text="컨트롤러" term_id="controller" >}})는
|
|
엔드포인트슬라이스 오브젝트를 생성하고 관리한다. 다른 엔티티나 컨트롤러가 추가
|
|
엔드포인트슬라이스 집합을 관리하게 할 수 있는 서비스 메시 구현과 같이
|
|
엔드포인트슬라이스에 대한 다양한 다른 유스케이스가 있다.
|
|
|
|
여러 엔티티가 서로 간섭하지 않고 엔드포인트슬라이스를
|
|
관리할 수 있도록 쿠버네티스는 엔드포인트슬라이스를 관리하는
|
|
엔티티를 나타내는 `endpointslice.kubernetes.io/managed-by`
|
|
{{< glossary_tooltip term_id="label" text="레이블" >}}을
|
|
정의한다.
|
|
엔드포인트슬라이스 컨트롤러는 관리하는 모든 엔드포인트슬라이스에 레이블의 값으로
|
|
`endpointslice-controller.k8s.io` 를 설정한다. 엔드포인트슬라이스를
|
|
관리하는 다른 엔티티도 이 레이블에 고유한 값을 설정해야 한다.
|
|
|
|
### 소유권
|
|
|
|
대부분의 유스케이스에서, 엔드포인트슬라이스 오브젝트가 엔드포인트를
|
|
추적하는 서비스가 엔드포인트슬라이스를 소유한다. 이 소유권은 각 엔드포인트슬라이스의 소유자
|
|
참조와 서비스에 속한 모든 엔드포인트슬라이스의 간단한 조회를 가능하게 하는
|
|
`kubernetes.io/service-name` 레이블로 표시된다.
|
|
|
|
### 엔드포인트슬라이스 미러링
|
|
|
|
경우에 따라, 애플리케이션이 사용자 지정 엔드포인트 리소스를 생성한다. 이러한
|
|
애플리케이션이 엔드포인트와 엔드포인트슬라이스 리소스에 동시에 쓸 필요가 없도록
|
|
클러스터의 컨트롤 플레인은 대부분의 엔드포인트 리소스를
|
|
해당 엔드포인트슬라이스에 미러링한다.
|
|
|
|
컨트롤 플레인은 다음을 제외하고 엔드포인트 리소스를 미러링한다.
|
|
|
|
* 엔드포인트 리소스에는 `endpointslice.kubernetes.io/skip-mirror` 레이블이
|
|
`true` 로 설정되어 있다.
|
|
* 엔드포인트 리소스에는 `control-plane.alpha.kubernetes.io/leader`
|
|
어노테이션이 있다.
|
|
* 해당 서비스 리소스가 존재하지 않는다.
|
|
* 해당 서비스 리소스에 nil이 아닌 셀렉터가 있다.
|
|
|
|
개별 엔드포인트 리소스는 여러 엔드포인트슬라이스로 변환될 수 있다.
|
|
엔드포인트 리소스에 여러 하위 집합이 있거나 여러 IP 제품군(IPv4 및 IPv6)이 있는
|
|
엔드포인트가 포함된 경우 변환이 일어난다. 하위 집합 당 최대 1000개의 주소가
|
|
엔드포인트슬라이스에 미러링된다.
|
|
|
|
### 엔드포인트슬라이스의 배포
|
|
|
|
각 엔드포인트슬라이스에는 리소스 내에 모든 엔드포인트가 적용되는
|
|
포트 집합이 있다. 서비스에 알려진 포트를 사용하는 경우 파드는
|
|
동일하게 알려진 포트에 대해 다른 대상 포트 번호로 끝날 수 있으며 다른
|
|
엔드포인트슬라이스가 필요하다. 이는 하위 집합이 엔드포인트와 그룹화하는
|
|
방식의 논리와 유사하다.
|
|
|
|
컨트롤 플레인은 엔드포인트슬라이스를 최대한 채우려고 노력하지만,
|
|
적극적으로 재조정하지는 않는다. 로직은 매우 직관적이다.
|
|
|
|
1. 기존 엔드포인트슬라이스에 대해 반복적으로, 더 이상 필요하지 않는 엔드포인트를
|
|
제거하고 변경에 의해 일치하는 엔드포인트를 업데이트 한다.
|
|
2. 첫 번째 단계에서 수정된 엔드포인트슬라이스를 반복해서
|
|
필요한 새 엔드포인트로 채운다.
|
|
3. 추가할 새 엔드포인트가 여전히 남아있으면, 이전에 변경되지 않은
|
|
슬라이스에 엔드포인트를 맞추거나 새로운 것을 생성한다.
|
|
|
|
중요한 것은, 세 번째 단계는 엔드포인트슬라이스를 완벽하게 전부 배포하는 것보다
|
|
엔드포인트슬라이스 업데이트 제한을 우선시한다. 예를 들어, 추가할 새 엔드포인트가
|
|
10개이고 각각 5개의 공간을 사용할 수 있는 엔드포인트 공간이 있는 2개의
|
|
엔드포인트슬라이스가 있는 경우, 이 방법은 기존 엔드포인트슬라이스
|
|
2개를 채우는 대신에 새 엔드포인트슬라이스를 생성한다. 다른 말로, 단일
|
|
엔드포인트슬라이스를 생성하는 것이 여러 엔드포인트슬라이스를 업데이트하는 것 보다 더 선호된다.
|
|
|
|
각 노드에서 kube-proxy를 실행하고 엔드포인트슬라이스를 관찰하면,
|
|
엔드포인트슬라이스에 대한 모든 변경 사항이 클러스터의 모든 노드로 전송되기
|
|
때문에 상대적으로 비용이 많이 소요된다. 이 방법은 여러 엔드포인트슬라이스가
|
|
가득 차지 않은 결과가 발생할지라도, 모든 노드에 전송해야 하는
|
|
변경 횟수를 의도적으로 제한하기 위한 것이다.
|
|
|
|
실제로는, 이러한 이상적이지 않은 분배는 드물 것이다. 엔드포인트슬라이스
|
|
컨트롤러에서 처리하는 대부분의 변경 내용은 기존 엔드포인트슬라이스에
|
|
적합할 정도로 적고, 그렇지 않은 경우 새 엔드포인트슬라이스가
|
|
필요할 수 있다. 디플로이먼트의 롤링 업데이트도 모든 파드와 해당
|
|
교체되는 엔드포인트에 대해서 엔드포인트슬라이스를
|
|
자연스럽게 재포장한다.
|
|
|
|
### 중복 엔드포인트
|
|
|
|
엔드포인트슬라이스 변경의 특성으로 인해, 엔드포인트는 동시에 둘 이상의
|
|
엔드포인트슬라이스에 표시될 수 있다. 이는 다른 엔드포인트슬라이스 오브젝트에
|
|
대한 변경 사항이 다른 시간에서의 쿠버네티스 클라이언트 워치(watch)/캐시에
|
|
도착할 수 있기 때문에 자연스럽게 발생한다.
|
|
|
|
{{< note >}}
|
|
엔드포인트슬라이스 API의 클라이언트는 반드시 서비스에 연관된 모든 존재하는 엔드포인트슬라이스에 대해
|
|
반복하고, 고유한 각 네트워크 엔드포인트들의 완전한 리스트를 구성해야 한다. 엔드포인트는 다른
|
|
엔드포인트슬라이스에서 중복될 수 있음에 유의한다.
|
|
|
|
엔드포인트 집계와 중복 제거 방법에 대한 레퍼런스 구현은 `kube-proxy` 의
|
|
`EndpointSliceCache` 구현에서 찾을 수 있다.
|
|
{{< /note >}}
|
|
|
|
## 엔드포인트와 비교 {#motivation}
|
|
|
|
기존 엔드포인트 API는 쿠버네티스에서 네트워크 엔드포인트를 추적하는
|
|
간단하고 직접적인 방법을 제공했다. 쿠버네티스 클러스터와
|
|
{{< glossary_tooltip text="서비스" term_id="service" >}}가 더 많은 수의 백엔드 파드로
|
|
더 많은 트래픽을 처리하고 전송하는 방향으로 성장함에 따라, 이 API의 한계가 더욱 눈에 띄게
|
|
되었다.
|
|
특히나, 많은 수의 네트워크 엔드포인트로 확장하는 것에
|
|
어려움이 있었다.
|
|
|
|
서비스에 대한 모든 네트워크 엔드포인트가 단일 엔드포인트
|
|
객체에 저장되기 때문에 이러한 엔드포인트 객체들이 상당히 커지는 경우도 있었다. 안정적인
|
|
서비스(오랜 기간 동안 같은 엔드포인트 세트)의 경우 영향은
|
|
비교적 덜 눈에 띄지만, 여전히 쿠버네티스의 일부 사용 사례들은 잘 처리되지 않았다.
|
|
|
|
서비스가 많은 백엔드 엔드포인트를 가지고
|
|
워크로드가 자주 증가하거나, 새로운 변경사항이 자주 롤 아웃 될 경우,
|
|
해당 서비스의 단일 엔드포인트 객체에 대한 각 업데이트는
|
|
쿠버네티스 클러스터 컴포넌트 사이(컨트롤 플레인 내, 그리고 노드와 API 서버 사이)에
|
|
상당한 네트워크 트래픽이 발생할 것임을 의미했다.
|
|
이러한 추가 트래픽은 또한 CPU 사용 관점에서도 굉장한 비용을 발생시켰다.
|
|
|
|
엔드포인트슬라이스 사용 시, 단일 파드를 추가하거나 삭제하는 작업은 (다수의 파드를 추가/삭제하는 작업과 비교했을 때)
|
|
해당 변경을 감시하고 있는 클라이언트에 동일한 _수_의 업데이트를 트리거한다.
|
|
하지만, 파드 대규모 추가/삭제의 경우 업데이트 메시지의 크기는 훨씬 작다.
|
|
|
|
엔드포인트슬라이스는 듀얼 스택 네트워킹과 토폴로지 인식 라우팅과 같은
|
|
새로운 기능에 대한 혁신을 가능하게 했다.
|
|
|
|
## {{% heading "whatsnext" %}}
|
|
|
|
* [서비스와 애플리케이션 연결하기](/ko/docs/tutorials/services/connect-applications-service/) 튜토리얼을 따라하기
|
|
* [엔드포인트슬라이스 API 레퍼런스](/docs/reference/kubernetes-api/service-resources/endpoint-slice-v1/) 를 읽어보기
|
|
* [엔드포인트 API 레퍼런스](/docs/reference/kubernetes-api/service-resources/endpoints-v1/) 를 읽어보기 |