Service ClusterIP 할당
Service ClusterIP 할당 (Service ClusterIP allocation)
쿠버네티스에서 Service는 Pod 집합에서 실행되는 애플리케이션을 노출하는 추상적인 방법이에요. Service는 클러스터 범위의 가상 IP 주소를 가질 수 있어요(type: ClusterIP Service 사용). 클라이언트는 그 가상 IP 주소로 연결할 수 있고, 쿠버네티스는 그 Service로의 트래픽을 여러 백킹 Pod에 걸쳐 로드밸런싱해요.
출처: 문서
본문
Service ClusterIP는 어떻게 할당되나요? (How Service ClusterIPs are allocated?)
쿠버네티스가 Service에 가상 IP 주소를 할당해야 할 때, 그 할당은 두 가지 방식 중 하나로 이루어져요.
- 동적으로(dynamically) — 클러스터의 컨트롤 플레인이
type: ClusterIPService를 위해 구성된 IP 범위 내에서 사용 가능한 IP 주소를 자동으로 선택해요. - 정적으로(statically) — Service를 위해 구성된 IP 범위 내에서 선택한 IP 주소를 직접 지정해요.
클러스터 전체에서 모든 Service ClusterIP는 유일해야 해요. 이미 할당된 ClusterIP로 특정 Service를 만들려고 하면 오류가 반환돼요.
왜 Service Cluster IP를 예약해야 하나요? (Why do you need to reserve Service Cluster IPs?)
때로는 잘 알려진 IP 주소에서 Service를 실행하고 싶을 수 있어요. 그래야 클러스터의 다른 컴포넌트와 사용자가 그 Service를 사용할 수 있기 때문이에요.
가장 좋은 예는 클러스터의 DNS Service예요. 관례적으로 일부 쿠버네티스 설치 프로그램은 Service IP 범위의 10번째 IP 주소를 DNS 서비스에 할당해요. Service IP 범위가 10.96.0.0/16으로 구성된 클러스터에서 DNS Service IP를 10.96.0.10으로 하고 싶다면 다음과 같은 Service를 만들어야 해요.
apiVersion: v1
kind: Service
metadata:
labels:
k8s-app: kube-dns
kubernetes.io/cluster-service: "true"
kubernetes.io/name: CoreDNS
name: kube-dns
namespace: kube-system
spec:
clusterIP: 10.96.0.10
ports:
- name: dns
port: 53
protocol: UDP
targetPort: 53
- name: dns-tcp
port: 53
protocol: TCP
targetPort: 53
selector:
k8s-app: kube-dns
type: ClusterIP
하지만 앞서 설명한 대로, IP 주소 10.96.0.10은 예약되지 않았어요. 다른 Service가 동적 할당보다 먼저 또는 동시에 생성되면 이 IP를 할당받을 수 있어요. 그래서 DNS Service가 충돌 오류로 실패하기 때문에 생성하지 못할 수 있어요.
Service ClusterIP 충돌을 어떻게 피할 수 있나요? (How can you avoid Service ClusterIP conflicts?)
Service에 ClusterIP를 할당하기 위해 쿠버네티스에서 구현한 할당 전략은 충돌 위험을 줄여요.
ClusterIP 범위는 공식 min(max(16, cidrSize / 16), 256)에 따라 나뉘는데, 설명하면 16보다 작거나 256보다 크지 않으며 그 사이에 단계적으로 증가하는 값이에요.
동적 IP 할당은 기본적으로 상위 대역(upper band)을 사용하고, 이것이 소진되면 하위 범위를 사용해요. 이렇게 하면 사용자가 낮은 충돌 위험으로 하위 대역에서 정적 할당을 사용할 수 있어요.
예시 (Examples)
예시 1 (Example 1)
이 예시는 Service의 IP 주소에 10.96.0.0/24 (CIDR 표기) IP 주소 범위를 사용해요.
- 범위 크기: 2^8 - 2 = 254
- 대역 오프셋(Band Offset):
min(max(16, 256/16), 256)=min(16, 256)= 16 - 정적 대역 시작: 10.96.0.1
- 정적 대역 끝: 10.96.0.16
- 범위 끝: 10.96.0.254
10.96.0.0/24 범위에서 "Static" 16, "Dynamic" 238으로 나뉘어요.
예시 2 (Example 2)
이 예시는 Service의 IP 주소에 10.96.0.0/20 (CIDR 표기) IP 주소 범위를 사용해요.
- 범위 크기: 2^12 - 2 = 4094
- 대역 오프셋:
min(max(16, 4096/16), 256)=min(256, 256)= 256 - 정적 대역 시작: 10.96.0.1
- 정적 대역 끝: 10.96.1.0
- 범위 끝: 10.96.15.254
10.96.0.0/20 범위에서 "Static" 256, "Dynamic" 3838로 나뉘어요.
예시 3 (Example 3)
이 예시는 Service의 IP 주소에 10.96.0.0/16 (CIDR 표기) IP 주소 범위를 사용해요.
- 범위 크기: 2^16 - 2 = 65534
- 대역 오프셋:
min(max(16, 65536/16), 256)=min(4096, 256)= 256 - 정적 대역 시작: 10.96.0.1
- 정적 대역 끝: 10.96.1.0
- 범위 끝: 10.96.255.254
10.96.0.0/16 범위에서 "Static" 256, "Dynamic" 65278로 나뉘어요.
다음 단계 (What's next)
- Service 외부 트래픽 정책에 대해 읽기
- Service로 애플리케이션 연결하기에 대해 읽기
- Service에 대해 읽기