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: ClusterIP Service를 위해 구성된 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에 대해 읽기

더 알아보기 (Learn more)