安装 Istio CNI 节点代理
Istio CNI 节点代理用于配置网格中 Pod 的流量重定向。它以 DaemonSet 的形式运行在每个节点上,并具有提升的权限。CNI 节点代理由 Istio 的两种 数据平面 模式使用。
对于 sidecar 数据平面模式,Istio CNI 节点代理是可选的。它消除了在网格中每个 Pod 中运行特权初始化容器的必要性,用每个 Kubernetes 节点上的单个特权节点代理 Pod 来替代该模型。
Istio CNI 节点代理在 ambient 模式文档。
按照本指南安装、配置和使用 Istio CNI 节点代理与 sidecar 数据平面模式。
边车流量重定向工作原理
使用 init 容器(无 Istio CNI 节点代理)
默认情况下,Istio 会在部署在网格中的 Pod 中注入一个初始化容器,istio-init
。istio-init
容器设置 Pod 网络流量重定向到/从 Istio sidecar 代理。这要求用户或部署 Pod 到网格的服务帐户具有足够的 Kubernetes RBAC 权限来部署 具有NET_ADMIN
和 NET_RAW
功能的容器。
使用 Istio CNI 节点代理
要求 Istio 用户拥有提升的 Kubernetes RBAC 权限对于某些组织的安全合规性来说是存在问题的,部署特权初始化容器与每个工作负载的要求也是如此。
istio-cni
节点代理实际上是 istio-init
容器的替代品,它实现了相同的网络功能,但不需要在每个工作负载中使用或部署特权初始化容器。相反,istio-cni
本身以单个特权 Pod 的形式运行在节点上。它利用此权限在节点上安装一个 链式 CNI 插件,该插件在“主”接口 CNI 插件之后被调用。每当创建新的 Pod 时,CNI 插件都会被 Kubernetes 作为主机节点上的特权进程动态调用,并且能够配置 Pod 网络。
Istio 链式 CNI 插件始终在主接口插件之后运行,识别需要流量重定向的带有 sidecar 的用户应用程序 Pod,并在 Kubernetes Pod 生命周期中的网络设置阶段设置重定向,从而消除了对特权初始化容器的需求,以及对 用户和 Pod 部署的 NET_ADMIN
和 NET_RAW
功能需求。
使用先决条件
使用正确配置的主接口 CNI 插件安装 Kubernetes。由于 支持 CNI 插件是实现 Kubernetes 网络模型所必需的,如果您有一个具有功能性 Pod 网络的相当新的 Kubernetes 集群,那么您可能已经拥有了它。
使用启用了 ServiceAccount 准入控制器 的 Kubernetes 安装 Kubernetes。
- Kubernetes 文档强烈建议在所有使用
ServiceAccounts
的 Kubernetes 安装中这样做。
- Kubernetes 文档强烈建议在所有使用
安装 CNI 节点代理
使用 istio-cni
组件安装 Istio
在大多数环境中,可以使用以下命令安装具有启用 istio-cni
组件的基本 Istio 集群。
$ cat <<EOF > istio-cni.yaml
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
components:
cni:
namespace: istio-system
enabled: true
EOF
$ istioctl install -f istio-cni.yaml -y
$ helm install istio-cni istio/cni -n istio-system --wait
这将在集群中部署一个 istio-cni
DaemonSet,它将在每个活动节点上创建一个 Pod,在每个节点上部署 Istio CNI 插件二进制文件,并为插件设置必要的节点级配置。CNI DaemonSet 运行的 PriorityClass
为 system-node-critical
。这是因为它是实际重新配置 Pod 网络以将它们添加到 Istio 网格的唯一方法。
请注意,如果您按照 使用 Helm 安装 指南使用 Helm 图表安装 istiod
,则必须使用以下额外覆盖值安装 istiod
,以便禁用特权 init 容器注入
$ helm install istiod istio/istiod -n istio-system --set pilot.cni.enabled=true --wait
其他配置
除了上述基本配置之外,还可以设置其他配置标志
values.cni.cniBinDir
和values.cni.cniConfDir
配置安装插件二进制文件和创建插件配置的目录路径。values.cni.cniConfFileName
配置插件配置文件的名称。values.cni.chained
控制是否将插件配置为链式 CNI 插件。
通常,不需要更改这些值,但某些平台可能使用非标准路径。如果有,请检查您特定平台的指南,此处。
处理版本 init 容器注入
当使用启用 CNI 组件的版本控制平面进行安装时,需要为每个安装的版本设置 values.pilot.cni.enabled=true
,以便边车注入器不尝试为该版本注入 istio-init
init 容器。
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
revision: REVISION_NAME
...
values:
pilot:
cni:
enabled: true
...
版本为 1.x
的 CNI 插件与版本为 1.x-1
、1.x
和 1.x+1
的控制平面兼容,这意味着只要 CNI 和控制平面的版本差异在一个次要版本内,就可以以任何顺序升级 CNI 和控制平面。
操作安装了 CNI 节点代理的集群
升级
当使用 就地升级 升级 Istio 时,可以使用一个 IstioOperator
资源将 CNI 组件与控制平面一起升级。
当使用 金丝雀升级 升级 Istio 时,由于 CNI 组件作为集群单例运行,因此建议与版本控制平面分开操作和升级 CNI 组件。
以下 IstioOperator
可用于独立升级 CNI 组件。
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
profile: empty # Do not include other components
components:
cni:
enabled: true
values:
cni:
excludeNamespaces:
- istio-system
对于 Helm 来说这不是问题,因为 istio-cni 是单独安装的,可以通过 Helm 升级
$ helm upgrade istio-cni istio/cni -n istio-system --wait
竞争条件和缓解措施
Istio CNI DaemonSet 在每个节点上安装 CNI 网络插件。但是,DaemonSet Pod 被调度到节点和 CNI 插件被安装并准备好使用之间存在时间差。应用程序 Pod 可能在该时间差内启动,并且 kubelet
对 Istio CNI 插件一无所知。结果是应用程序 Pod 启动时没有 Istio 流量重定向,并绕过了 Istio 边车。
为了缓解应用程序 Pod 和 Istio CNI DaemonSet 之间的竞争,istio-validation
init 容器作为边车注入的一部分被添加,它检测流量重定向是否正确设置,如果未设置,则阻止 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,重新调度时将具有正确的配置。 | 1.20 及更早版本中的默认值 |
values.cni.repair.labelPods | 更新 Pod | 只标记 Pod。用户需要采取手动操作来解决。 | |
values.cni.repair.repairPods | 无 | 动态地重新配置 Pod 以具有适当的配置。当容器重新启动时,Pod 将继续正常执行。 | 1.21 及更高版本中的默认值 |
流量重定向参数
为了将应用程序 Pod 网络命名空间中的流量重定向到/来自 Istio 代理边车,Istio CNI 插件配置了命名空间的 iptables。您可以使用与普通 pod 注释相同的注释来调整流量重定向参数,例如要包含或排除的端口和 IP 范围。有关可用参数,请参阅 资源注释。
与应用程序 init 容器的兼容性
Istio CNI 插件可能会导致边车数据平面模式下任何应用程序 init 容器的网络连接问题。当使用 Istio CNI 时,kubelet
使用以下步骤启动 Pod
- 默认接口 CNI 插件设置 Pod 网络接口并分配 Pod IP。
- Istio CNI 插件在 Pod 内设置到 Istio 边车代理的流量重定向。
- 所有 init 容器都成功执行并完成。
- Istio 边车代理与 Pod 的其他容器一起在 Pod 中启动。
init 容器在边车代理启动之前执行,这会导致它们执行期间流量丢失。使用以下设置之一避免这种流量丢失
- 使用
runAsUser
将 init 容器的uid
设置为1337
。1337
是 边车代理使用的uid
。由该uid
发送的流量不会被 Istio 的iptables
规则捕获。应用程序容器流量将照常被捕获。 - 将
traffic.sidecar.istio.io/excludeOutboundIPRanges
注释设置为禁用将流量重定向到 init 容器与之通信的任何 CIDR。 - 将
traffic.sidecar.istio.io/excludeOutboundPorts
注释设置为禁用将流量重定向到 init 容器使用的特定出站端口。
与其他 CNI 的兼容性
Istio CNI 插件遵循 CNI 规范,并且应该与任何同样遵循该规范的 CNI、容器运行时或其他插件兼容。
Istio CNI 插件作为链式 CNI 插件运行。这意味着它的配置被附加到现有 CNI 插件配置列表中。有关更多详细信息,请参阅 CNI 规范参考。
当创建或删除 Pod 时,容器运行时会按顺序调用列表中的每个插件。
Istio CNI 插件执行操作以设置应用程序 Pod 的流量重定向 - 在边车数据平面模式下,这意味着在 Pod 的网络命名空间中应用 iptables
规则以将 Pod 内的流量重定向到注入的 Istio 代理边车。