揭开 Istio Sidecar 注入模型的神秘面纱
揭秘 Istio 是如何将其数据平面组件添加到现有 deployment。
Istio 服务网格体系结构的简单概述总是从控制平面和数据平面开始。
从 Istio 的文档 :
重要的是要理解向应用程序 pod 中注入边车是自动进行的,尽管也可以手动注入。流量从应用服务流向 sidecar,而开发人员无需关心它。一旦将应用程序连接到 Istio 服务网格,开发者便可以开始使用并获得服务网格中的所有效益。但是,数据平面管道是如何发生的,以及无缝迁移工作的真正要求是什么?在本文中,我们将深入研究 Sidecar 注入模型的细节,以非常清楚地理解 Sidecar 注入的工作原理。
Sidecar 注入
简单来说,Sidecar 注入会将额外容器的配置添加到 Pod 模板中。Istio 服务网格目前所需的容器有:
istio-init
init 容器用于设置 iptables 规则,以便将入站/出站流量通过 sidecar 代理。初始化容器与应用程序容器在以下方面有所不同:
- 它在启动应用容器之前运行,并一直运行直至完成。
- 如果有多个初始化容器,则每个容器都应在启动下一个容器之前成功完成。
因此,您可以看到,对于不需要成为实际应用容器一部分的设置或初始化作业来说,这种容器是多么的完美。在这种情况下,istio-init
就是这样做并设置了 iptables
规则。
istio-proxy
这个容器是真正的 sidecar 代理(基于 Envoy)。
手动注入
在手动注入方法中,可以使用 istioctl
修改容器模板并添加前面提到的两个容器的配置。不论是手动注入还是自动注入,Istio 都从 istio-sidecar-injector
和的 istio
两个 Configmap 对象中获取配置。
我们先来看看 istio-sidecar-injector
Configmap 的配置,了解一下其中的内容。
如您所见,configmap 包含了 istio-init
初始化容器和 istio-proxy
代理容器的配置。该配置包括容器镜像的名称以及拦截模式,权限要求等参数。
从安全的角度来看,重要的是要注意 istio-init
需要 NET_ADMIN
权限来修改 pod 命名空间中的 iptables
,如果 istio-proxy
是 TPROXY
模式,也需要这一权限。由于该仅限于 pod 的命名空间,因此应该没有问题。但是,我们注意到最近的 open-shift 版本可能会出现一些问题,因此需要一种解决方法。本文结尾处提到了一个这样的选择。
要修改当前的 Pod 模板以进行 sidecar 注入,您可以:
或者
要使用修改后的 Configmap 或本地 Configmap:
从 configmap 创建
inject-config.yaml
和mesh-config.yaml
修改现有的 pod 模板,在这个例子中是,
demo-red.yaml
:提交
demo-red-injected.yaml
如上所示,我们使用 sidecar-injector
和网格配置创建了一个新模板,然后使用 kubectl
应用该新模板。如果我们查看注入后的 YAML 文件,它具有 Istio 特定容器的配置,如上所述。一旦我们应用注入后的 YAML 文件,我们将看到两个容器正在运行。其中一个是实际的应用程序容器,另一个是 istio-proxy
sidecar。
这里没有 3 个 Pod,因为 istio-init
容器是一个 init 类型的容器,它在完成应做的操作后退出,其用于在 pod 中设置 iptable
规则。为了确认 init 容器已退出,让我们看一下 kubectl describe
的输出:
从输出中可以看出,istio-init
容器的 State
为 Terminated
,而 Reason
是 Completed
。只有两个容器是运行的,主应用程序 demo-red
容器和 istio-proxy
容器。
自动注入
在大多数情况下,您不想在每次部署应用程序时都使用 istioctl
命令手动注入边车,而是希望 Istio 自动将 sidecar 注入到您的 pod 中。这是推荐的方法,要使自动注入生效,您只需要用 istio-injection=enabled
标记想部署应用程序的命名空间。
贴上标签后,Istio 会自动为您在该命名空间中部署的所有 pod 注入 sidecar。下面的例子里,istio-dev
命名空间中部署的 pod 被自动注入了 sidecar:
但它是如何工作的呢?要深入了解这一点,我们需要理解 Kubernetes 准入控制器。
对于 sidecar 自动注入,Istio 依赖于 Mutating Admission Webhook
。让我们来看看 istio-sidecar-injector
中的配置详情。
在这里,您可以看到与标签 istio-injection:enabled
相匹配的 webhook namespaceSelector
标签。在这种情况下,您还会看到在创建容器时要完成的操作和资源。当 apiserver
接收到与其中一个规则匹配的请求时,apiserver
会根据 clientconfig
配置中指定的 name: istio-sidecar-injector
键值对,向 webhook 服务发送准入审查请求。我们应该能够看到该服务正在 istio-system
命名空间中运行。
最终,该配置与手动注入中的配置几乎相同。只是它是在 pod 创建过程中自动完成的,因此您不会看到部署中的更改。您需要使用 kubectl describe
来查看 sidecar 代理和 init 代理。
sidecar 自动注入不仅取决于 webhook 的 namespaceSelector
机制,还取决于默认注入策略和每个 pod 自身注解。
如果你再次查看 istio-sidecar-injector
ConfigMap,它将定义默认的注入策略。在这个示例中,它是默认启用的。
您还可以在 pod 模板中使用注解 sidecar.istio.io/inject
覆盖默认策略。以下示例展示如何为 Deployment
中的 pod 禁用 sidecar 自动注入。
此示例显示了许多变量,这取决于是否在命名空间、ConfigMap 和 pod 中控制 sidecar 自动注入,它们是:
- webhook
namespaceSelector
(istio-injection: enabled
) - 默认策略(在 ConfigMap
istio-sidecar-injector
中配置) - 每个 pod 的重载注解(
sidecar.istio.io/inject
)
注入状态表根据上述变量的值清晰显示了最终注入状态。
从应用容器到 Sidecar 代理的流量
既然我们已经清楚了如何将 sidecar 容器和 init 容器注入到应用清单中,那么 sidecar 代理如何捕获容器之间的入站和出站流量?我们曾简要提到过,这是通过在 pod 命名空间中设置 iptable
规则来完成的,而规则又是由 istio-init
容器完成的。现在,是时候验证命名空间中实际更新的内容了。
让我们进入上一节中部署的应用程序 pod 命名空间,并查看已配置的 iptables。我们将展示一个使用 nsenter
的例子。或者,您也可以通过特权模式进入容器并查看相同的信息。对于无法访问节点的人来说,使用 exec
进入 sidecar 并运行 iptables
更实用。
上面的输出清楚地表明,端口 80 的所有入站流量(即我们的 red-demo
应用正在监听的端口)现在已被 REDIRECTED
到端口 15001,即 istio-proxy
的端口,一个 Envoy 代理正在监听的端口。对于出站流量也是如此。
本文已经快结束了。我们希望本文有助于您弄清 Istio 是如何将 Sidecar 代理注入到现有部署中以及 Istio 是如何将流量路由到代理。