安装 Istio CNI 插件

按照此流程利用 Istio 容器网络接口(CNI) 来安装、配置和使用 Istio 网格。

默认情况下,Istio 会在网格中部署的 Pod 上注入一个 initContaineristio-initistio-init 容器会将 Pod 的网络流量劫持到 Istio Sidecar 代理上。 这需要用户或部署 Pod 的 Service Account 具有足够的部署 NET_ADMIN 容器的 Kubernetes RBAC 权限。Istio 用户权限的提升,对于某些组织的安全政策来说,可能是难以接受的。 Istio CNI 插件就是一个能够替代 istio-init 容器来实现相同的网络功能但却不需要 Istio 用户申请额外的 Kubernetes RBAC 授权的方案。

Istio CNI 插件会在 Kubernetes Pod 生命周期的网络设置阶段完成 Istio 网格 Pod 流量转发设置的工作, 因此用户在部署 Pod 到 Istio 网格中时,不再需要配置 NET_ADMIN 功能需求了。 Istio CNI 插件代替了 istio-init 容器所实现的功能。

安装 CNI

前提条件

  1. 安装支持 CNI 的 Kubernetes 集群,并且 kubelet 使用 --network-plugin=cni 参数启用 CNI 插件。

  2. Kubernetes 需要启用 ServiceAccount 准入控制器

    • Kubernetes 文档中强烈建议所有使用 ServiceAccounts 的 Kubernetes 安装实例都启用该控制器。

用 CNI 插件安装 Istio

在大多数环境中,可以使用以下配置安装基础的 Istio 集群并启用 CNI:

$ cat <<EOF > istio-cni.yaml
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
  components:
    cni:
      enabled: true
EOF
$ istioctl install -f istio-cni.yaml -y

这将部署 istio-cni-node DaemonSet 到集群中,将 Istio CNI 插件可执行文件安装到每个节点上并为此插件设置必要的配置。 CNI DaemonSet 使用 system-node-critical PriorityClass 来运行。

Istio CNI
Istio CNI

有几个常用的安装选项:

  • components.cni.namespace=kube-system 配置命名空间以安装 CNI DaemonSet。
  • values.cni.cniBinDirvalues.cni.cniConfDir 配置安装插件可执行文件的目录路径并创建插件配置。
  • values.cni.cniConfFileName 配置插件配置文件的名称。
  • values.cni.chained 控制是否将插件配置为链式的 CNI 插件。

通过 Helm 安装

$  helm install istiod istio/istiod -n istio-system --set values.istio_cni.enabled=true --wait

Istio CNI 和 Istio Discovery Chart 使用不同的值,需要您在安装 istiod Chart 时, 在重载值文件或命令提示符中设置以下内容来管理网络注解的同时关联 CNI 插件:

  • values.istio_cni.enabled 应设置为与 values.cni.enabled 相同的值。

  • values.istio_cni.chained 应设置为与 values.cni.chained 相同的值。

例如:

$  helm install istiod istio/istiod -n istio-system --set values.istio_cni.enabled=true --wait

托管 Kubernetes 设置

istio-cni 插件预期可用于任何使用 CNI 插件的托管 Kubernetes 版本。 默认的安装配置适用于大多数平台。某些平台需要特殊的安装设置。

apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
  components:
    cni:
      enabled: true
      namespace: kube-system
  values:
    cni:
      cniBinDir: /home/kubernetes/bin

操作细节

升级

当使用原地升级来升级 Istio 时, CNI 组件可以使用一个 IstioOperator 资源与控制平面一起升级。

使用金丝雀升级升级 Istio 时, 由于 CNI 组件以集群单例运行,建议将 CNI 组件与改版后的控制平面分开运行和升级。 下面的 IstioOperator 可用于独立操作 CNI 组件。

这对 Helm 而言不是问题,因为 istio-cni 是单独安装的。

apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
  profile: empty # 不包含其他组件
  components:
    cni:
      enabled: true
  values:
    cni:
      excludeNamespaces:
        - istio-system
        - kube-system

在启用 CNI 组件的情况下安装修订的控制平面时,需要设置 values.istio_cni.enabled, 这样 Sidecar 注入程序就不会注入 istio-init 这个 Init 容器。

apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
  revision: REVISION_NAME
  ...
  values:
    istio_cni:
      enabled: true
  ...

1.x 版本的 CNI 插件兼容 1.x-11.x1.x+1 版本的控制平面, 这意味着 CNI 和控制平面可以按任何顺序进行升级,只要它们的版本差异在一个次要版本之内。

竞争条件和缓解措施

Istio CNI DaemonSet 在每个节点上安装 CNI 网络插件。 但是,在将 DaemonSet Pod 调度到一个节点上与 CNI 插件被安装好并准备就绪之间存在一个时间间隔。 应用 Pod 有可能在这个时间间隔内启动,而 kubelet 不了解 Istio CNI 插件。 结果应用 Pod 在没有 Istio 流量重定向的情况下启动并绕过了 Istio Sidecar。

为了缓解应用 Pod 和 Istio CNI DaemonSet 之间的竞争,添加了 istio-validation Init 容器作为 Sidecar 注入的一部分。 该容器会检测流量重定向是否设置正确,如果不正确则阻止 Pod 启动。CNI DaemonSet 将检测并驱逐任何卡在这种状态下的 Pod。 当新的 Pod 启动时,它应该正确设置流量重定向。此缓解措施默认被启用,可以通过将 values.cni.repair.enabled 设置为 false 来关闭。

这种修复能力可以进一步配置不同的 RBAC 权限,以帮助缓解 ISTIO-SECURITY-2023-005 中详述的理论攻击向量。根据实际需要将以下字段设置为 true/false,您可以选择向 Istio CNI 授予 Kubernetes RBAC 权限。

配置作用出错时的行为备注
values.cni.repair.deletePods删除 Pod删除 Pod,当 Pod 被重新调度时具有正确的配置。1.20 及更早版本中的默认设置
values.cni.repair.labelPods更新 Pod仅对 Pod 进行打标签。用户将需要采取手动操作来修复。
values.cni.repair.repairPods动态重新配置 Pod 以具有适当的配置。当容器重新启动时,Pod 将继续正常执行。1.21 及更高版本中的默认设置

流量重定向参数

为了将应用 Pod 的网络命名空间中的流量重定向至 Istio Sidecar,Istio CNI 插件配置了命名空间的 iptables。 您可以使用与正常情况相同的 Pod 注解来调整流量重定向参数,例如要包含或排除在重定向之外的端口和 IP 范围。 有关可用参数,请参阅资源注解

与应用的 Init 容器的兼容性

Istio CNI 插件可能会导致与任何应用 initContainers 的网络连通性问题。 使用 Istio CNI 时,kubelet 会通过以下步骤启动一个注入的 Pod:

  1. Istio CNI 插件在 Pod 内设置流量重定向到 Istio Sidecar。
  2. 等待所有的 Init 容器成功执行完毕。
  3. Istio Sidecar 跟随 Pod 的其它容器一起启动。

Init 容器在 Sidecar 启动之前执行,这会导致在它们执行期间会有流量丢失。 可以用以下的一种或所有设置来防止流量丢失:

  1. 使用 runAsUser 将 Init 容器的 uid 设置为 13371337Sidecar 代理使用的 uid。 这个 uid 发送的流量并非通过 Istio 的 iptables 规则进行捕获。 应用容器流量仍将像往常一样被捕获。
  2. 设置 traffic.sidecar.istio.io/excludeOutboundIPRanges 注解来禁止重定向流量到任何与 Init 容器有通信的 CIDR。
  3. 设置 traffic.sidecar.istio.io/excludeOutboundPorts 注解来禁止重定向流量到 Init 容器所用到的出站端口。

和其它 CNI 插件的兼容性

Istio CNI 插件维护着与当前需要 NET_ADMINNET_RAW 权能的 istio-init 容器相同的 CNI 插件集。

Istio CNI 插件作为一个链式 CNI 插件存在。也就是说它的配置会作为一个新的配置列表元素被加入到现存 CNI 插件配置中。 参考 CNI 规范中的更多细节。 当 Pod 被创建或删除时,容器运行时会按照列表顺序调用每个插件。Istio CNI 插件只会把应用 Pod 的流量重定向到 Sidecar 中(通过在 Pod 的网络命名空间中使用 iptables 完成)。

这些信息有用吗?
您是否有更多建议和改进意见?

感谢您的反馈!