按照此流程利用 Istio 容器网络接口(CNI)来安装、配置和使用 Istio 网格。
默认情况下,Istio 会在网格中部署的 Pods 上注入一个 initContainer
:istio-init
。istio-init
容器会将 Pod 的网络流量劫持到 Istio sidecar 代理上。这需要用户或部署 Pods 的 Service Account 具有足够的部署 NET_ADMIN
容器的 Kubernetes RBAC 权限。Istio 用户权限的提升,对于某些组织的安全政策来说,可能是难以接受的。Istio CNI 插件就是一个能够替代 istio-init
容器来实现相同的网络功能但却不需要 Istio 用户申请额外的 Kubernetes RBAC 授权的方案。
Istio CNI 插件会在 Kubernetes Pod 生命周期的网络设置阶段完成 Istio 网格的 Pod 流量转发设置工作,因此用户在部署 Pods 到 Istio 网格中时,不再需要配置 NET_ADMIN
功能需求了。Istio CNI 插件代替了 istio-init
容器所实现的功能。
- 前提条件:
- 安装支持 CNI 的 Kubernetes 集群,并且 kubelet 使用
--network-plugin=cni
参数启用 CNI 插件。
ps aux |grep kubelet
- Kubernetes 需要启用 ServiceAccount 准入控制器。
- 下载 istio:
curl -L https://istio.io/downloadIstio | sh -
cd istio-1.9.0
export PATH=$PWD/bin:$PATH #将 istioctl 加入环境变量
- 安装:
-
确认 Kubernetes 环境的 CNI 插件的
--cni-bin-dir
和--cni-conf-dir
设置。 -
使用 istioctl 安装 Istio CNI 和 Istio。参考 Istio 安装的说明,并设置
--set components.cni.enabled=true
和--set cni.components.cni.enabled=true
选项。 在上一步中,如果 istio-cni 不是按照默认设置安装的,还需要设置--set values.cni.cniBinDir=...
和--set values.cni.cniConfDir=...
选项。
- helm chart 参数:
选项 | 取值 | 默认值 | 描述 |
---|---|---|---|
hub |
用于拉取 install-cni 镜像的仓库地址。 |
||
tag |
用于拉取 install-cni 镜像的标签。 |
||
pullPolicy |
Always |
install-cni 镜像的拉取策略。 |
|
logLevel |
panic , fatal , error , warn , info , debug |
warn |
CNI 程序的日志级别。 |
excludeNamespaces |
[]string |
[ istio-system ] |
排除 Istio Pod 检查的命名空间列表。 |
cniBinDir |
/opt/cni/bin |
必须与集群中的 --cni-bin-dir (kubelet 参数)值一样。 |
|
cniConfDir |
/etc/cni/net.d |
必须与集群中的 --cni-conf-dir (kubelet 参数)值一样。 |
|
cniConfFileName |
不设置会自动查找 cni-conf-dir 目录的第一个文件(与 kubelet 一致)。主要用来测试 install-cni 的插件配置。如果设置了,install-cni 将会把插件配置注入到 cni-conf-dir 目录的该文件里面。 |
||
psp_cluster_role |
该值指的是一个 ClusterRole 并被用于在 istio-cni 的命名空间中创建一个 RoleBinding 。当使用 Pod 安全策略并且希望让 istio-cni 作为 priviliged Pods 运行时,这会非常有用。 |
||
podAnnotations |
{} |
Pod 级别自定义的附加注解。 |
这些选项可以在 istioctl manifest
命令中通过 values.cni.<option-name>
来访问,可以作为 --set
的参数,或者作为自定义覆盖文件中的相应路径。
- 排除 namespace:
使用以下命令来渲染并应用 Istio CNI 组件,并覆盖 istio-cni
的 logLevel
和 excludeNamespaces
参数的默认配置:
helm install istio-cni manifests/charts/istio-cni \
--set global.hub="docker.io/istio" \
--set global.tag="1.9.0" \
--set global.jwtPolicy=first-party-jwt \
--set cni.enabled=true \
--set cni.components.cni.enabled=true \
--set istio_cni.enabled=true \
--set values.cni.logLevel=info \
--set values.cni.excludeNamespaces={
"istio-system,kube-system"} \
-n kube-system
helm status -n kube-system istio-cni
NAME: istio-cni
LAST DEPLOYED: Sun Feb 21 18:44:32 2021
NAMESPACE: kube-system
STATUS: deployed
REVISION: 1
TEST SUITE: None
- Sidecar 注入的兼容性:
在 Helm 安装过程中需要用 istio_cni.enabled=true
生成 istio-sidecar-injector
Configmap,使用这一配置对 Kubernetes Pod 进行 Istio 注入才能够使用 Istio CNI 插件。
下列注入方式都是可以支持 Istio CNI 插件的:
-
自动 sidecar 注入
-
使用 istio-sidecar-injector configmap 进行手动注入
- 执行
istioctl kube-inject
直接使用 configmap:
istioctl kube-inject -f deployment.yaml -o deployment-injected.yaml --injectConfigMapName istio-sidecar-injector kubectl apply -f deployment-injected.yaml
- 用 configmap 创建文件,用于执行 istioctl kube-inject:
kubectl get cm -n istio-system istio-sidecar-injector -o=jsonpath='{.data.config}' > inject-config.yaml istioctl kube-inject -f deployment.yaml -o deployment-injected.yaml --injectConfigFile inject-config.yaml kubectl apply -f deployment-injected.yaml
- 执行
- 操作细节:
Istio CNI 插件会处理 Kubernetes Pod 的创建和删除事件,并作出如下动作:
-
通过 Istio sidecars 识别 Istio 用户应用 Pods 是否需要流量重定向
-
对 pod 网络命名空间进行配置,将流量转向 Istio sidecar
- 识别 Pod 是否需要流量重定向:
Istio CNI 插件会通过检查 Pod 是否符合下列要求来判断是否需要把业务 Pod 的流量交由 Sidecar 处理:
-
Pod 所在 Kubernetes 命名空间没在
exclude_namespaces
配置中列出。 -
Pod 中有一个名为 istio-proxy 的容器。
-
Pod 中的容器不止一个。
-
Pod 的注解不包含
sidecar.istio.io/inject
或其值为true
。
- 流量重定向参数:
为了将应用 Pod 的网络命名空间中的流量重定向至 Istio sidecar,Istio CNI 插件配置了命名空间的 iptables。下表描述了重定向功能的参数。通过设置应用 Pod 的注解来覆盖相应的参数的默认值。
注解名 | 取值 | 默认值 | 描述 |
---|---|---|---|
sidecar.istio.io/inject |
true , false |
true |
表示是否要注入 Istio sidecar。如果设置为 false ,Istio CNI 插件将不会为这个 Pod 配置命名空间的 iptables。 |
sidecar.istio.io/status |
由 Istio 的 sidecar 注入所创建的注解。如果没有,Istio CNI 插件将不会配置该 Pod 命名空间的 iptables。 | ||
sidecar.istio.io/interceptionMode |
REDIRECT, TPROXY |
REDIRECT |
所用的 iptables 重定向模式。 |
traffic.sidecar.istio.io/includeOutboundIPRanges |
<IPCidr1> ,<IPCidr2> ,… |
"*" |
逗号分隔的 CIDR 列表,列表范围内的 IP 地址才会发生重定向。默认值为 "*" ,会对所有流量进行重定向。 |
traffic.sidecar.istio.io/excludeOutboundIPRanges |
<IPCidr1> ,<IPCidr2> ,… |
逗号分隔的 CIDR 列表,范围内的 IP 不会进行重定向。该选项仅在 includeOutboundIPRanges 取值为 "*" 时生效。 |
|
traffic.sidecar.istio.io/includeInboundPorts |
<port1> ,<port2> ,… |
Pod 的 containerPorts 列表 |
逗号分隔的入站端口列表,这些流量会被重定向到 Sidecar,取值为 "*" 时会重定向所有端口。 |
traffic.sidecar.istio.io/excludeInboundPorts |
<port1> ,<port2> ,… |
逗号分隔的入站端口列表,列表中的端口不会被重定向到 Istio Sidecar 中。仅在 includeInboundPorts 取值为 "*" 时生效。 |
|
traffic.sidecar.istio.io/excludeOutboundPorts |
<port1> ,<port2> ,… |
逗号分隔的出站端口列表,列表中的端口流量不会重定向到 Envoy 中。 | |
traffic.sidecar.istio.io/kubevirtInterfaces |
<ethX> ,<ethY> ,… |
逗号分隔的虚拟接口列表,列表中的虚拟接口的入站流量(来自 VM)将被当作出站流量。 |
- 日志:
Istio CNI 插件在容器运行时的进程空间内运行。因此 kubelet 进程会将插件的日志记到它的日志中。
- 和应用的初始化容器的兼容性:
Istio CNI 插件可能会导致与应用 initContainers
的网络连通性。使用 Istio CNI 时,kubelet 会通过以下步骤启动一个注入的 pod:
-
Istio CNI 插件在 Pod 内设置流量重定向到 Istio sidecar。
-
等待所有的初始化容器成功执行完毕。
-
Istio sidecar 跟随 Pod 的其它容器一起启动。
初始化容器在 sidecar 启动之前执行,这会导致在它们执行期间会有流量丢失。 可以用以下的一种或所有设置来防止流量丢失:
-
设置
traffic.sidecar.istio.io/excludeOutboundIPRanges
注解来禁止重定向流量到任何与初始化容器有通信的 CIDRs。 -
设置
traffic.sidecar.istio.io/excludeOutboundPorts
注解来禁止重定向流量到初始化容器所用到的出站端口。
- 和其它 CNI 插件的兼容性:
Istio CNI 插件维护着和当前的 NET_ADMIN
istio-init
容器同样的兼容性。
Istio CNI 插件作为一个链式 CNI 插件存在,也就是说它的配置会作为一个新的配置列表元素被加入到现存 CNI 插件配置中。当 Pod 被创建或删除时,容器运行时会按照列表顺序调用每个插件。Istio CNI 插件只会把应用 Pod 的流量重定向到 Sidecar 中(通过在 Pod 的网络命名空间中使用 iptables 完成)。
Istio CNI 插件应该不会与设置 Pod 网络的基本 CNI 插件有冲突,但并不是所有的 CNI 插件都经过了验证。