安装 Istio CNI 插件
按照此流程利用 Istio 容器网络接口(CNI) 来安装、配置和使用 Istio 网格。
默认情况下,Istio 会在网格中部署的 Pod 上注入一个 initContainer
:istio-init
。 istio-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
容器所实现的功能。
注意:Istio CNI 插件作为一个链接的 CNI 插件运行,它被设计为与另一个 CNI 插件一起使用, 如 PTP 或 Calico。 详情请参见与其他CNI插件的兼容性。
安装 CNI
前提条件
安装支持 CNI 的 Kubernetes 集群,并且
kubelet
使用--network-plugin=cni
参数启用 CNI 插件。- AWS EKS、Azure AKS 和 IBM Cloud IKS 集群具备这一功能。
- Google Cloud GKE 集群只需启用以下特性之一,就可以启用 CNI: network policy、 intranode visibility、 workload identity、 pod security policy、 dataplane v2。
- OpenShift 默认启用了 CNI。
Kubernetes 需要启用 ServiceAccount 准入控制器。
- Kubernetes 文档中强烈建议所有使用
ServiceAccounts
的 Kubernetes 安装实例都启用该控制器。
- 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
$ helm install istio-cni istio/cni -n kube-system --wait
这将部署 istio-cni-node
DaemonSet 到集群中,将 Istio CNI 插件可执行文件安装到每个节点上并为此插件设置必要的配置。 CNI DaemonSet 使用 system-node-critical PriorityClass
来运行。
Istio CNI
有几个常用的安装选项:
components.cni.namespace=kube-system
配置命名空间以安装 CNI DaemonSet。values.cni.cniBinDir
和values.cni.cniConfDir
配置安装插件可执行文件的目录路径并创建插件配置。values.cni.cniConfFileName
配置插件配置文件的名称。values.cni.chained
控制是否将插件配置为链式的 CNI 插件。
在一个节点变得可调度和 Istio CNI 插件在该节点上准备就绪之间存在某个时间间隔。 如果应用 Pod 在此期间启动,则流量重定向可能会被不正确地设置,且流量可能绕过 Istio Sidecar。 这种竞争条件通过“检测和修复”方法得到缓解。 请查阅竞争条件和缓解措施一节以了解此缓解措施的影响。
通过 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
$ istioctl install --set profile=openshift
操作细节
升级
当使用原地升级来升级 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-1
、1.x
和 1.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:
- Istio CNI 插件在 Pod 内设置流量重定向到 Istio Sidecar。
- 等待所有的 Init 容器成功执行完毕。
- Istio Sidecar 跟随 Pod 的其它容器一起启动。
Init 容器在 Sidecar 启动之前执行,这会导致在它们执行期间会有流量丢失。 可以用以下的一种或所有设置来防止流量丢失:
- 使用
runAsUser
将 Init 容器的uid
设置为1337
。1337
是 Sidecar 代理使用的 uid。 这个uid
发送的流量并非通过 Istio 的iptables
规则进行捕获。 应用容器流量仍将像往常一样被捕获。 - 设置
traffic.sidecar.istio.io/excludeOutboundIPRanges
注解来禁止重定向流量到任何与 Init 容器有通信的 CIDR。 - 设置
traffic.sidecar.istio.io/excludeOutboundPorts
注解来禁止重定向流量到 Init 容器所用到的出站端口。
如果启用了 DNS 代理, 您必须使用 runAsUser 1337
解决方法,并且 Init 容器将流量发送到需要 DNS 解析的主机名。
请谨慎使用流量捕获排除法,因为 IP/端口排除注解不仅适用于 Init 容器流量,还适用于应用容器流量。 即发送到配置的 IP/端口的应用流量将绕过 Istio Sidecar。
和其它 CNI 插件的兼容性
Istio CNI 插件维护着与当前需要 NET_ADMIN
和 NET_RAW
权能的 istio-init
容器相同的 CNI 插件集。
Istio CNI 插件作为一个链式 CNI 插件存在。也就是说它的配置会作为一个新的配置列表元素被加入到现存 CNI 插件配置中。 参考 CNI 规范中的更多细节。 当 Pod 被创建或删除时,容器运行时会按照列表顺序调用每个插件。Istio CNI 插件只会把应用 Pod 的流量重定向到 Sidecar 中(通过在 Pod 的网络命名空间中使用 iptables
完成)。
Istio CNI 插件应该不会与设置 Pod 网络的基本 CNI 插件有冲突,但并不是所有的 CNI 插件都经过了验证。