服务网格平稳落地:Istio 中精准控制 Sidecar 的注入
为什么
说起服务网格,这幅图大家肯定不会陌生。这就是服务网格的网络,也是网格架构的终极形态。
那在迁移到网格架构之前,我们的系统是什么样的?
我们的系统在演进的过程中,不可避免的会遇到各种 0 到 1 过程中的中间态。比如下面这种,可以比较直观的看出 Istio 或者网格是部分覆盖的。这个过程中,我们需要平滑、可控的推进,才能在保障系统可用性的前提下进行架构的演进。
怎么做
Sidecar 的注入分两种:手动和自动。
手动
手动就是利用 Istio 的 cli 工具 istioctl kube-inject
对资源 yaml 进行修改:
$ istioctl kube-inject -f samples/sleep/sleep.yaml | kubectl apply -f -
serviceaccount/sleep created
service/sleep created
deployment.apps/sleep created
手动的方式比较适合开发阶段使用。
自动
sidecar 的自动注入则是通过 mutating webhook admission controller 实现的。其原理简单说就是拦截 pod的创建请求来对 pod 的资源定义进行修改。
我们对截取了 istio-sidecar-injector
MutatingWebhookConfiguration
的部分内容。
webhooks:
...
matchPolicy: Exact #1
name: sidecar-injector.istio.io
namespaceSelector: #2
matchLabels:
istio-injection: enabled
objectSelector: #3
matchExpressions:
- key: sidecar.istio.io/inject
operator: NotIn
values:
- "false"
rules: #4
- apiGroups:
- ""
apiVersions:
- v1
operations:
- CREATE
resources:
- pods
scope: '*'
...
- 这里的
matchPolicy: Exact
针对的是 #4 中的apiGroups
与apiVersions
的组合,即精确匹配v1/pods
的CREATE
请求 - 顾名思义,匹配符合条件的
namespace
- 同2,匹配符合条件的
object
注: #2、#3 支持 Kubernetes 的标签选择语法
按照前面的说明,这个 hook 会拦截打了 istio-injection: enabled
label 的 namespace 下,没有打 sidecar.istio.io/inject: false
标签的 v1/pod
的创建。通过 https://istiod.istio-system:443/inject
端点对 pod 的定义进行定制(添加 init-container
、sidecar 容器等)。
有人可能会说这样还不够精准,因为可能某个 namespace 下只有部分对象才会注入 sidecar。
这就需要借助 istiod
的逻辑了。
只针对特定 pod 注入sidecar 或忽略注入
在 configmap
istio-sidecar-injector
中有两个字段 alwaysInjectSelector
和 neverInjectSelector
。从名字来看这两个分别提供了白名单、黑名单的功能。
alwaysInjectSelector: []
neverInjectSelector:[]
我们只需如下调整(需要重启 istiod),然后为需要注入 sidecar 的资源打上相应的标签即可。
alwaysInjectSelector:
- matchExpressions:
- key: sidecar.istio.io/inject
operator: In
values:
- "true"
- "enabled"
- "yes"