配置范围

为了对服务网格进行编程,Istio 控制平面(Istiod)会读取各种配置, 包括如 ServiceNode 之类的核心 Kubernetes 类型, 以及如 Gateway 这样的 Istio 自身的类型。 然后将它们发送到数据平面(有关更多信息,请参阅架构)。

默认情况下,控制平面将读取所有命名空间中的所有配置。 每个代理实例也将接收所有命名空间的配置。这包括未在网格中注册的工作负载的信息。

此默认值可确保开箱即用的正确行为,但会带来可扩展性成本。 每个配置都需要一定的成本(主要是 CPU 和内存)来维护和保持其更新。 在大规模情况下,限制配置范围以避免过多的资源消耗至关重要。

范围机制

Istio 提供了一些工具来帮助控制配置范围以满足不同的用例。 根据您的要求,这些范围可以单独使用或一起使用。

  • Sidecar 为特定工作负载提供了一种机制来导入一组配置
  • exportTo 提供了一种将配置导出到一组工作负载的机制
  • discoverySelectors 提供了一种机制让 Istio 完全忽略一组配置

Sidecar 导入

Sidecar 中的 egress.hosts 字段允许指定要导入的配置列表。受 Sidecar 资源影响的 Sidecar 只能看到符合指定条件的配置。

例如:

  1. apiVersion: networking.istio.io/v1beta1
  2. kind: Sidecar
  3. metadata:
  4. name: default
  5. spec:
  6. egress:
  7. - hosts:
  8. - "./*" # 从我们自有命名空间导入所有配置
  9. - "bookinfo/*" # 从 bookinfo 命名空间导入所有配置
  10. - "external-services/example.com" # 仅从 external-services 命名空间导入 'example.com'

exportTo

Istio 的 VirtualServiceDestinationRuleServiceEntry 提供了 spec.exportTo 字段。同样,Service 可以使用 networking.istio.io/exportTo 注解进行配置。

与允许工作负载所有者控制其依赖项的 Sidecar 不同, exportTo 以相反的方式工作,并允许服务所有者控制自己服务的可见性。

例如,此配置使 details Service 仅对其自己的命名空间和 client 命名空间可见:

  1. apiVersion: v1
  2. kind: Service
  3. metadata:
  4. name: details
  5. annotations:
  6. networking.istio.io/exportTo: ".,client"
  7. spec: ...

DiscoverySelectors

虽然以前的控制操作在工作负载或服务所有者级别上运行, 但 DiscoverySelectors 提供了对配置可见性的网格范围控制。发现选择器允许指定命名空间对控制平面可见的标准。 任何不匹配的命名空间都会被控制平面完全忽略。

这可以在安装过程中被配置为 meshConfig 的一部分。例如:

  1. meshConfig:
  2. discoverySelectors:
  3. - matchLabels:
  4. # 允许在任何命名空间使用 `istio-discovery=enabled`
  5. istio-discovery: enabled
  6. - matchLabels:
  7. # 允许“kube-system”;Kubernetes 会自动将此标签添加到每个命名空间
  8. kubernetes.io/metadata.name: kube-system

Istiod 将始终向 Kubernetes 开放所有命名空间的监视。 然而,发现选择器将忽略在处理早期未选择的对象,从而最大限度地降低成本。

常见问题

我该如何了解某种配置的成本?

为了获得缩小配置范围的最佳投入回报,了解每个对象的成本会很有帮助。 不幸的是,没有一个简单的答案。可扩展性取决于很多因素。但是,有一些一般准则:

在 Istio 中,配置更改的成本很高,因为它们需要重新计算。 虽然 Endpoints 更改(通常来自 Pod 向上或向下扩展)经过了大量优化, 但大多数其他配置的代驾都相当高昂。当控制器不断地对对象进行更改时, 这可能特别有害(有时这种情况是意外发生的!)。有一些用于检测哪些配置正在更改的工具:

  • Istiod 将记录每个更改,例如:Push debounce stable 1 for config Gateway/default/gateway: ..., full=true。 这会展示 default 命名空间中的 Gateway 对象已被更改。 full=false 将表示并优化例如 Endpoint 的更新。 注意:对 ServiceEndpoints 的更改都将已 ServiceEntry 进行展示。
  • Istiod 会通过 pilot_k8s_cfg_eventspilot_k8s_reg_events 暴露每次变更的指标。
  • kubectl get <resource> --watch -oyaml --show-managed-fields 可以展示对一个或多个对象的更改, 以帮助了解正在更改的内容以及更改者。

无头服务(Headless Services) (除了被声明为 HTTP)随着实例数量的变化而增减。 这使得大型无头服务变得代价高昂,并且是使用 exportTo 或等效项排除的良好候选者。

如果我连接到我设置的范围之外的服务会发生什么?

当连接到已通过范围机制之一排除的服务时,数据平面将不知道有关目标的任何信息, 因此它将被视为未匹配的流量

针对网关怎么样?

虽然网关将遵循 exportToDiscoverySelectors,但 Sidecar 对象不会影响网关。 然而,与 Sidecar 不同的是,网关默认没有整个集群的配置。 相反,每个配置都显式附加到网关,这在很大程度上避免了这个问题。

然而,目前 数据平面配置的一部分 (用 Envoy 术语来说是“集群”)总是为整个集群发送,即使它没有被明确引用。