元鉴
返回中文阅读流

Kubernetes Blog

Kubernetes v1.36:弃用并移除 Service ExternalIPs

Service 的 .spec.externalIPs 存在安全风险,Kubernetes 1.36 正式弃用,未来版本将移除相关支持。

中文内容

已翻译official company source英文原文2026-05-14

Kubernetes v1.36:弃用并移除 Service ExternalIPs

By Adrian Moisey (independent), Dan Winship (Red Hat), | Thursday, May 14, 2026

Service 的 .spec.externalIPs 字段是早期为非云集群提供类似云负载均衡器功能的一种尝试。遗憾的是,该 API 假定集群中的每个用户都是完全可信的;在任何并非如此的情况下,它都会带来多种安全漏洞利用方式,如 CVE-2020-8554 所述。

自 Kubernetes 1.21 起,Kubernetes 项目一直建议所有用户禁用 .spec.externalIPs。为使这一操作更容易,Kubernetes 还添加了一个可启用的准入控制器(DenyServiceExternalIPs)来实现这一点。当时,SIG Network 认为默认阻止该功能会造成过大的破坏性变更,难以考虑。

然而,安全问题仍然存在,并且作为一个项目,我们对该功能“默认不安全”的状态越来越不满意。此外,对于希望获得类似负载均衡器功能的非云集群,现在已经有了几种更好的替代方案。

因此,Service 的 .spec.externalIPs 字段现已在 Kubernetes 1.36 中正式弃用。我们预计 Kubernetes 未来的某个小版本将从 kube-proxy 中移除该行为的实现,并会更新 Kubernetes 一致性标准,要求符合标准的实现不得提供支持。

关于术语以及未被弃用的内容说明

在 Kubernetes 中,“external IP”这一说法有些多义:

  • Service API 有一个 .spec.externalIPs 字段,可用于添加 Service 会响应的额外 IP 地址。
  • Node API 的 .status.addresses 字段可以列出多种不同类型的地址,其中一种称为 ExternalIP。
  • kubectl 工具在以默认输出格式显示类型为 LoadBalancer 的 Service 信息时,会在列标题 EXTERNAL-IP 下显示负载均衡器 IP 地址。

此次弃用针对的是上述第一种情况。如果你没有在任何 Service 中设置 externalIPs 字段,那么这不适用于你。

尽管如此,作为预防措施,你可能仍希望启用 DenyServiceExternalIPs 准入控制器,以阻止未来对 externalIPs 字段的任何使用。

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 Services 替代 externalIPs

最简单(但也是最差)的选择,是直接从使用 externalIPs 改为使用 type: LoadBalancer 服务,并手动分配一个负载均衡器 IP。本质上,这几乎与 externalIPs 完全相同,但有一个重要区别:负载均衡器 IP 是 Service 的 .status 的一部分,而不是其 .spec 的一部分;在启用了 RBAC 的集群中,普通用户默认无法编辑它。因此,这种 externalIPs 的替代方式只会提供给获得管理员授权的用户(不过这些用户随后将完全有能力复制 CVE-2020-8554;仍然不会有进一步检查来确保一个用户没有窃取另一个用户的 IP 等)。

由于 Kubernetes 中 .status 的工作方式,你必须先创建不带负载均衡器 IP 的 Service,然后在第二步添加该 IP:

$ cat loadbalancer-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: my-example-service
spec:
  # prevent any real load balancer controllers from managing this service
  # by using a non-existent 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 服务最初设计为由云负载均衡器作为后端支持,但 Kubernetes 也可以通过使用第三方负载均衡器控制器(如 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 甚至支持 Service 中已弃用的 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 内部 Kubernetes Ingress、负载均衡和 Service Mesh API 的下一代方案。Gateway API 旨在修复 Service 和 Ingress 资源的不足,使其成为一个非常可靠、稳健且正在积极开发的解决方案。

externalIPs 弃用时间线

此次弃用的大致时间线如下:

  1. 随着 Kubernetes 1.36 发布,该字段已被弃用;当用户使用此字段时,Kubernetes 现在会发出警告
  2. 大约一年后(最早 v1.40),kube-proxy 将禁用对 .spec.externalIPs 的支持,但如果用户需要更多时间完成迁移,将有一种方式可以选择重新启用
  3. 再大约一年后(最早 v1.43),支持将被完全禁用;用户将无法再选择重新启用
  • 下一页 →
Last modified May 05, 2026 at 3:26 PM PST: move all to same dir (284d039bc7)

原文标题

Kubernetes v1.36: Deprecation and removal of Service ExternalIPs