Kubernetes v1.36: 서비스 ExternalIPs 폐기 및 제거

발행: (2026년 5월 15일 AM 03:35 GMT+9)
9 분 소요

출처: Kubernetes Blog

.spec.externalIPs 필드는 클라우드가 아닌 클러스터에 대해 클라우드 로드밸런서와 유사한 기능을 제공하려는 초기 시도였습니다.
안타깝게도 이 API는 클러스터 내 모든 사용자를 완전히 신뢰한다는 전제하에 설계되었으며, 그 전제가 깨지는 경우 CVE-2020-8554 에서 설명한 다양한 보안 취약점이 발생합니다.

Kubernetes 1.21부터 프로젝트에서는 모든 사용자가 .spec.externalIPs 를 비활성화하도록 권고했습니다. 이를 쉽게 할 수 있도록 Kubernetes는 DenyServiceExternalIPs 라는 어드미션 컨트롤러를 추가했으며, 이를 활성화하면 자동으로 차단할 수 있습니다. 당시 SIG Network는 기본적으로 기능을 차단하는 것이 너무 큰 파괴적 변화라고 판단했습니다.

하지만 보안 문제는 여전히 존재하고, 프로젝트 차원에서 “기본적으로 안전하지 않은(insecure by default)” 상태에 점점 더 불만을 품게 되었습니다. 또한 클라우드가 아닌 클러스터에서도 로드밸런서와 같은 기능을 제공할 수 있는 더 나은 대안들이 등장했습니다.

그 결과, Service 의 .spec.externalIPs 필드는 Kubernetes 1.36 에서 공식적으로 폐기(deprecated) 되었습니다. 향후 마이너 릴리즈에서는 kube‑proxy 에서 해당 동작을 완전히 제거하고, Kubernetes 적합성 기준을 업데이트하여 호환 구현이 이 기능을 제공하지 않도록 할 예정입니다.

용어 정리 및 폐기되지 않은 항목

external IP 라는 용어는 Kubernetes 내에서 여러 의미로 사용됩니다.

  • Service API 에는 Service 가 응답할 추가 IP 주소를 지정하는 .spec.externalIPs 필드가 있습니다.
  • Node API 의 .status.addresses 필드에는 여러 종류의 주소가 포함되며, 그 중 하나가 ExternalIP 라고 불립니다.
  • kubectl 이 Service(타입 LoadBalancer) 정보를 기본 출력 형식으로 보여줄 때, 로드밸런서 IP 주소를 EXTERNAL-IP 열에 표시합니다.

이번 폐기는 위 중 첫 번째 항목, 즉 Service 의 .spec.externalIPs 필드에 관한 것입니다. 만약 여러분이 Service 에서 externalIPs 를 사용하고 있지 않다면 이번 변경은 적용되지 않습니다.

그럼에도 불구하고, 향후 externalIPs 필드 사용을 완전히 차단하고 싶다면 DenyServiceExternalIPs 어드미션 컨트롤러를 활성화하는 것이 좋습니다.

externalIPs 대안

.spec.externalIPs 를 사용하고 있다면 다음과 같은 대안들을 고려할 수 있습니다.

예시 Service

apiVersion: v1
kind: Service
metadata:
  name: my-example-service
spec:
  type: ClusterIP
  selector:
    app.kubernetes.io/name: my-example-app
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080
  externalIPs:
  - "192.0.2.4"

수동으로 관리하는 LoadBalancer Service 로 전환

가장 간단하지만 바람직하지 않은 방법은 externalIPs 대신 type: LoadBalancer Service 를 만들고, 로드밸런서 IP 를 직접 할당하는 것입니다. 이는 externalIPs 와 거의 동일하지만 중요한 차이점이 있습니다: 로드밸런서 IP 가 Service 의 .spec 이 아니라 .status 에 포함되며, RBAC 가 활성화된 클러스터에서는 일반 사용자가 기본적으로 수정할 수 없습니다.

따라서 이 방법은 관리자 권한을 부여받은 사용자만 사용할 수 있게 되며, 해당 사용자는 여전히 CVE-2020-8554 와 동일한 보안 위험을 재현할 수 있습니다(다른 사용자의 IP 를 탈취하는 등의 추가 검증은 없기 때문).

.status 를 이용하려면 먼저 로드밸런서 IP 없이 Service 를 생성한 뒤, 두 번째 단계에서 IP 를 추가해야 합니다.

$ cat loadbalancer-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: my-example-service
spec:
  # 실제 로드밸런서 컨트롤러가 이 Service 를 관리하지 못하도록
  # 존재하지 않는 loadBalancerClass 를 지정
  loadBalancerClass: non-existent-class
  type: LoadBalancer
  selector:
    app.kubernetes.io/name: my-example-app
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080
$ kubectl apply -f loadbalancer-service.yaml
service/my-example-service created
$ kubectl patch service my-example-service --subresource=status --type=merge -p '{"status":{"loadBalancer":{"ingress":[{"ip":"192.0.2.4"}]}}}'

클라우드가 아닌 환경용 LoadBalancer 컨트롤러 사용

원래 LoadBalancer Service 는 클라우드 로드밸런서를 뒤에 두고 설계되었지만, MetalLB 와 같은 서드파티 컨트롤러를 이용하면 비클라우드 환경에서도 동작시킬 수 있습니다.

이 방법은 externalIPs 로 인한 보안 문제를 해결합니다. 관리자가 컨트롤러가 할당할 IP 범위를 지정하고, 컨트롤러가 동일 IP 가 두 서비스에 동시에 할당되지 않도록 보장하기 때문입니다.

예를 들어 MetalLB 를 설치·설정한 뒤, 클러스터 관리자는 다음과 같이 IP 풀을 정의할 수 있습니다.

apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: production
  namespace: metallb-system
spec:
  addresses:
  - 192.0.2.0/24
  autoAssign: true
  avoidBuggyIPs: false

그 후 사용자는 type: LoadBalancer Service 를 만들면 MetalLB 가 자동으로 IP 를 할당합니다. MetalLB 는 폐기된 loadBalancerIP 필드도 지원하므로, 기존 externalIPs 방식과 호환되게 특정 IP 를 요청할 수도 있습니다(해당 IP 가 사용 가능할 경우).

apiVersion: v1
kind: Service
metadata:
  name: my-example-service
spec:
  type: LoadBalancer
  selector:
    app.kubernetes.io/name: my-example-app
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080
  loadBalancerIP: "192.0.2.4"

다른 로드밸런서 컨트롤러에서도 유사한 방식으로 IP 할당을 제어할 수 있습니다.

Gateway API 활용

또 다른 대안은 Gateway API 를 구현하는 것입니다.

Gateway API 를 사용하면 클러스터 관리자가 Gateway 리소스를 정의하고, .spec.addresses 필드에 IP 주소를 지정할 수 있습니다. Gateway 리소스는 관리자가 관리하도록 설계되었으므로, RBAC 규칙을 통해 권한이 있는 사용자만 수정하도록 제한할 수 있습니다.

예시:

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: example-gateway
spec:
  gatewayClassName: example-gateway-class
  addresses:
  - type: IPAddress
    value: "192.0.2.4"
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: example-route
spec:
  parentRefs:
  - name: example-gateway
  rules:
  - backendRefs:
    - name: example-svc
      port: 80
---
apiVersion: v1
kind: Service
metadata:
  name: example-svc
spec:
  type: ClusterIP
  selector:
    app.kubernetes.io/name: example-app
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080

Gateway API 프로젝트는 Kubernetes Ingress, Load Balancing, Service Mesh API 의 차세대 버전으로, Service·Ingress 리소스의 한계를 보완하도록 설계되었습니다. 현재 활발히 개발 중이며, 매우 신뢰할 수 있는 솔루션으로 평가받고 있습니다.

externalIPs 폐기의 타임라인

대략적인 일정은 다음과 같습니다.

시점내용
Kubernetes 1.36 출시.spec.externalIPs 필드가 폐기됨. 사용 시 경고가 출력됩니다.
약 1년 후 (최소 v1.40)kube‑proxy 가 .spec.externalIPs 지원을 중단합니다. 다만, 마이그레이션이 필요할 경우 옵션으로 다시 활성화할 수 있는 방법을 제공합니다.
또 1년 후 (최소 v1.43)지원이 완전히 차단됩니다. 다시 활성화할 방법은 제공되지 않습니다.
0 조회
Back to Blog

관련 글

더 보기 »