前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >(译)Istio Sidecar 注入:例外和除错

(译)Istio Sidecar 注入:例外和除错

作者头像
崔秀龙
发布2019-07-23 15:26:01
1.7K0
发布2019-07-23 15:26:01
举报
文章被收录于专栏:伪架构师

Kubernetes 环境下的 Istio 使用了 Sidecar 模型进行部署,把一个辅助容器(也就是 Sidecar)附加到业务 Pod 之中。这一过程让 Sidecar 容器和业务容器共享同样的网络栈,可以视为同一主机上的两个进程。这样一来,Istio 就能够接管业务应用的所有网络调用,就有了增强服务间通信能力的基础。

这个 Sidecar 容器命名为 istio-proxy,能够用手工或者自动方式进行注入。其实这个手工注入也不是 100% 徒手完成的。

手工注入

Istio 的发行版本中会带有一个 istioctl 工具。看名字就知道这工具很棒:)。它的一个能力就是把 istio-proxy Sidecar 注入到业务容器之中。我们可以用一个简单的 busybox Pod 来看看它的功能:

代码语言:javascript
复制
$ cat busybox.yamlapiVersion: v1
kind: Pod
metadata:
 name: busybox-test
spec:
 containers:
 - name: busybox-container
   image: busybox
   command: ['sh', '-c', 'echo Hello Kubernetes! && sleep infinity']$ istioctl kube-inject -f busybox.yaml > busybox-injected.yaml
$ cat busybox-injected.yaml
apiVersion: v1
kind: Pod
metadata:
 labels:
 name: busybox-test
spec:
 containers:
 - command:
   - sh
   - -c
   - echo Hello Kubernetes! && sleep infinity
   image: busybox
   name: busybox-container - image: docker.io/istio/proxyv2:1.0.2
   imagePullPolicy: IfNotPresent
   name: istio-proxy
   args:
     - proxy
     - sidecar
  ...

上文可见,这个命令生成了一个 YAML 文件,和原始文件有点像,但是 Pod 中加入了一个 Sidecar(istio-proxy)。这的确不是纯手工吧——至少让我们少打了不少字。然后就可以使用 kubectl apply 命令把这个修改后的文件提交给 Kubernetes 集群了:

代码语言:javascript
复制
$ kubectl apply -f busybox-injected.yaml# 如果不想生成中间文件,可以直接用管道完成全部操作。$ kubectl apply -f <(istioctl kube-inject -f busybox.yaml)

随之而来的一个问题就是:这些数据是哪来的?它怎么知道 Sidecar 镜像是 docker.io/istio/proxyv2:1.0.2 的?答案很简单:所有数据都来自于一个 ConfigMap,这个对象保存在 istio-system 命名空间:

代码语言:javascript
复制
$ kubectl -n istio-system describe configmap istio-sidecar-injector
Name:         istio-sidecar-injector
Namespace:    istio-systemData
====
config:
----
policy: enabled
template: |-
 initContainers:
 - name: istio-init
   image: "docker.io/istio/proxy_init:1.0.2"
...

可以对这个 ConfigMap 进行编辑,修改一些你需要的值,用来进行注入。不难发现,这主要是一个用于向 Pod 加入内容的模板。如果想要为 istio-proxy 容器使用其它对象,只要修改这个字段的内容就可以了,或者还可以调整任何其它要注入的东西。这个 ConfigMap 是用来完成网格中所有 Pod 的注入工作的,所以要小心从事。

因为 istioctl 要根据 ConfigMap 来获知注入内容,也就是说执行 istioctl 的用户必须能够访问到安装了 Istio 的 Kubernetes 集群的这一对象。如果因为某些原因无法访问到这一 ConfigMap,还可以在 istioctl 中使用一个本地的配置文件。

代码语言:javascript
复制
# 首先使用有权限的用户运行这一命令$ kubectl -n istio-system get configmap istio-sidecar-injector -o=jsonpath='{.data.config}' > inject-config.yaml# 这个文件可以随时进行任意修改。$ istioctl kube-inject --injectConfigFile inject-config.yaml ...

自动注入

注入 istio-proxy 还有另一个方式,就是要求 Istio 进行自动注入。为命名空间设置标签 istio-injection=enabled 就能满足这一需要了。如果命名空间加上了这个标签,所有其中的 Pod 都会被注入 istio-proxy Sidecar,也就无需手工执行 istioctl 处理 YAML 文件了。

工作方式很简单:它使用了 Kubernetes 的 MutatingWebhook,新 Pod 创建之前,这一功能会通知 Istio,让 Istio 有机会对新 Pod 进行就地修改,stio 会使用在 ConfigMap 中的模板把 istio-proxy 注入到 Pod 中。

看起来不错?

自动注入过程有很大的弹性:

  • istio-sidecar-injector ConfigMap 中有一个布尔值用来指定自动注入是否启用。
  • 只有使用标签进行标注的命名空间才会进行自动注入,也就是说用命名空间标签能够对自动注入进行控制。
  • 还可以使用 kubectl -n istio-system edit MutatingWebhookConfiguration istio-sidecar-injector 命令,修改其中的 namespaceSelector 字段来调整这个标签的用法,甚至移除这个限制(也就是为所有命名空间使用自动注入,慎用)。
  • 可以禁用特定 Pod 的自动注入。如果 Pod 包含注解 sidecar.istio.io/inject: "false",Istio 就不会为在这一 Pod 中注入 Sidecar。
  • 还有更保守的方式:只对选择的 Pod 进行注入——也就是白名单方式。设置策略为 false(kubectl -n istio-system edit configmap istio-sidecar-injector),只对包含注解 sidecar.istio.io/inject: "true" 进行注入。

想要更大弹性?

还有些上面提到的方法无法满足的弹性要求:

如果不熟悉 Openshift 的用户,它有一个功能叫做 source-to-image(代码到镜像,s2i),这一功能会将代码构建为容器镜像。提供一个 git 仓库作为输入(支持多种语言),就会输出镜像并运行到 Openshift 集群上。

这是一个神奇的功能。这里不会介绍很多细节,我只会告诉你本文中需要了解的事情:在这一过程中 Openshift 会创建一或更多个的用于进行构建的中间、辅助 Pod。构建过程结束之后,二进制工件被构建为容器镜像,而辅助 Pod 会被销毁。

如果我们为指定命名空间启用了自动注入,并使用 Openshift 的 s2i 功能,会让这些辅助 Pod 也被注入 Sidecar,这些 Pod 是 Openshift 创建的,我们无法对其进行注解以阻止 Sidecar 的注入。辅助 Pod 无需进行注入,怎么办呢?

一个可能的解决方法就是用上面提到的保守方案,只对特定 Pod 启用注入,但是就要对 Pod 进行特别的注解。还有别的方式。

新方案

1.1.0 中,Istio 自动注入可以根据标签进行例外设置:不管命名空间标签如何,策略如何设置,对符合标签选择器要求的 Pod 都不进行注入。可以在 istio-sidecar-injector 中加入例外设置。

代码语言:javascript
复制
$ kubectl -n istio-system describe configmap istio-sidecar-injector
apiVersion: v1
kind: ConfigMap
metadata:
 name: istio-sidecar-injector
data:
 config: |-
   policy: enabled
   neverInjectSelector:
     - matchExpressions:
       - {key: openshift.io/build.name, operator: Exists}
     - matchExpressions:
       - {key: openshift.io/deployer-pod-for.name, operator: Exists}
   template: |-
     initContainers:
...

可以看到上面的 neverInjectSelector 字段,它是一个 Kubernetes 标签选择器的数组。不同元素之间是“或”关系,第一次发现有符合条件的标签之后就会跳过其它判断。上面的语句意味着:包含 openshift.io/build.name 或者 openshift.io/deployer-pod-for.name 标签的 Pod,不管标签值如何,都不会进行注入。

为了完整性起见,可以使用 alwaysInjectSelector 字段,这个字段会无视全局策略,向符合条件的 Pod 进行注入。

标签选择器方式产生了很大的弹性,能够处理更多的例外情况。阅读 Kubernetes 文档可以了解更多这方面的内容。

值得注意的是,Pod 注解还是有更高的优先级,如果 Pod 注解包含了 sidecar.istio.io/inject: "true/false",会被优先处理,所以自动注入的评估顺序是:

Pod 注解 → NeverInjectSelector → AlwaysInjectSelector → 命名空间策略。

注入选择器是新特性,这方面的文档还在更新,但是其它部分的文档和例子,都可以在官方文档中查看。

Pod 为什么没注入?

这是个常见问题。按照前面的介绍(例如给命名空间打标签)进行操作,结果 Pod 还没有被注入。

或者刚好相反,Pod 明明注解为 sidecar.istio.io/inject: "false,还是被注入了,为什么?

可以看看 sidecar-injector Pod 的日志:

代码语言:javascript
复制
$ pod=$(kubectl -n istio-system get pods -l istio=sidecar-injector -o jsonpath='{.items[0].metadata.name}')
$ kubectl -n istio-system logs -f $pod

然后可以创建业务 Pod,看看日志输出的具体内容。要看到更详细的日志(经常会很有用),可以编辑 sidecar-injector Deployment 对象,给它加上参数 --log_output_level=default:debug

代码语言:javascript
复制
$ kubectl -n istio-system edit deployment istio-sidecar-injector
...
     containers:
     - args:
       - --caCertFile=/etc/istio/certs/root-cert.pem
       - --tlsCertFile=/etc/istio/certs/cert-chain.pem
       - --tlsKeyFile=/etc/istio/certs/key.pem
       - --injectConfig=/etc/istio/inject/config
       - --meshConfig=/etc/istio/config/mesh
       - --healthCheckInterval=2s
       - --healthCheckFile=/health
       - --log_output_level=default:debug
       image: docker.io/istio/sidecar_injector:1.0.2
       imagePullPolicy: IfNotPresent
...

编辑成功之后 Pod 会重启,完成之后就可以重新查看日志了:

代码语言:javascript
复制
$ pod=$(kubectl -n istio-system get pods -l istio=sidecar-injector -o jsonpath='{.items[0].metadata.name}')
$ kubectl -n istio-system logs -f $pod

提示

如果在日志中还是找不到问题原因,就代表 sidecar-injector Pod 没有收到 Pod 创建的通知,也就不会触发自动注入的操作。这可能是因为命名空间没有正确标签导致的,因此需要检查一下命名空间的标签以及 MutatingWebhookConfiguration 中的配置。缺省情况下,命名空间应该设置 istio-injection=enabled 标签。可以使用 kubectl -n istio-system edit MutatingWebhookConfiguration istio-sidecar-injector 命令检查其中的 namespaceSelector 字段内容。

完成排查之后,可以再次编辑 sidecar-injector Deployment 对象,清除新加入的参数。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-12-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 伪架构师 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 手工注入
  • 自动注入
  • 看起来不错?
  • 想要更大弹性?
    • 新方案
    • Pod 为什么没注入?
      • 提示
      相关产品与服务
      容器服务
      腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档