安装 Istio sidecar

备注:以下需要 Istio 0.5.0 或更高版本。 0.4.0 及 以前版本参见 https://archive.istio.io/v0.4/docs/setup/kubernetes/sidecar-injection。

Pod Spec 中需满足的条件

为了成为 Service Mesh 中的一部分,kubernetes 集群中的每个 Pod 都必须满足如下条件:

  1. Service 关联:每个 pod 都必须只属于某一个 Kubernetes Service (当前不支持一个 pod 同时属于多个 service)。
  2. 命名的端口:Service 的端口必须命名。端口的名字必须遵循如下格式 <protocol>[-<suffix>],可以是httphttp2grpcmongo、 或者 redis 作为 <protocol> ,这样才能使用 Istio 的路由功能。例如name: http2-fooname: http 都是有效的端口名称,而 name: http2foo 不是。如果端口的名称是不可识别的前缀或者未命名,那么该端口上的流量就会作为普通的 TCP 流量来处理(除非使用 Protocol: UDP 明确声明使用 UDP 端口)。
  3. 带有 app label 的 Deployment:我们建议 kubernetes 的Deploymenet 资源的配置文件中为 Pod 明确指定 app label。每个 Deployment 的配置中都需要有个与其他 Deployment 不同的含有意义的 app label。app label 用于在分布式追踪中添加上下文信息。
  4. Mesh 中的每个 pod 里都有一个 Sidecar:最后,Mesh 中的每个 pod 都必须运行与 Istio 兼容的 sidecar。以下部分介绍了将 sidecar 注入到 pod 中的两种方法:使用istioctl 命令行工具手动注入,或者使用 Istio Initializer 自动注入。注意 sidecar 不涉及到流量,因为它们与容器位于同一个 pod 中。

注入

手动注入需要修改控制器的配置文件,如 deployment。通过修改 deployment 文件中的 pod 模板规范可实现该deployment 下创建的所有 pod 都注入 sidecar。添加/更新/删除 sidecar 需要修改整个 deployment。

自动注入会在 pod 创建的时候注入,无需更改控制器资源。Sidecar 可通过以下方式更新:选择性地手动删除 pod 或者系统得进行 deployment 滚动更新。

手动或者自动注入都使用同样的模板配置。自动注入会从 istio-system 命名空间下获取 istio-inject 的 ConfigMap。手动注入可以通过本地文件或者 Configmap 。

默认安装中还提供了两个注入模板的变种:istio-sidecar-injector-configmap-release.yamlistio-sidecar-injector-configmap-debug.yaml。Debug 版本中包含用于调试的代理镜像、附加的日志和 core dump 功能以用于调试 sidecar 代理。

手动注入 sidecar

使用内置的默认模板和从 istio ConfigMap 中动态获取服务网格配置文件实现 sidecar 的手动注入。可以通过 flag 设置来覆盖附加参数(参见:istioctl kube-inject --help

  1. kubectl apply -f <(~istioctl kube-inject -f samples/sleep/sleep.yaml)

在没有 kubernetes 集群的情况下也可以执行 kube-inject 。这可以用来创建服务网格的 configmap 和注入配置。

  1. kubectl create -f install/kubernetes/istio-sidecar-injector-configmap-release.yaml \
  2. --dry-run \
  3. -o=jsonpath='{.data.config}' > inject-config.yaml
  4. kubectl -n istio-system get configmap istio -o=jsonpath='{.data.mesh}' > mesh-config.yaml

在输入的文件上运行 kube-inject

  1. istioctl kube-inject \
  2. --injectConfigFile inject-config.yaml \
  3. --meshConfigFile mesh-config.yaml \
  4. --filename samples/sleep/sleep.yaml \
  5. --output sleep-injected.yaml

部署注入后的 YAML 文件:

  1. kubectl apply -f sleep-injected.yaml

验证 sidecar 已经注入到 Deployment 中:

  1. kubectl get deployment sleep -o wide
  1. NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
  2. sleep 1 1 1 1 2h sleep,istio-proxy tutum/curl,unknown/proxy:unknown app=sleep

自动注入 sidecar

关于 Webhook 管理控制的整体介绍可以参见: validatingadmissionwebhook-alpha-in-18-beta-in-19

前置条件

kubernetes 1.9 的集群需要启动 admissionregistration.k8s.io/v1beta1

  1. kubectl api-versions | grep admissionregistration.k8s.io/v1beta1
  1. Copyadmissionregistration.k8s.io/v1beta1

GKE

1.9.1 版本中已经具备非白名单早期用户访问的 alpha 集群 (参考:https://cloud.google.com/kubernetes-engine/release-notes#january-16-2018)。

  1. gcloud container clusters create <cluster-name> \
  2. --enable-kubernetes-alpha
  3. --cluster-version=1.9.1-gke.0
  4. --zone=<zone>
  5. --project <project-name>
  1. Copygcloud container clusters get-credentials <cluster-name> \
  2. --zone <zone> \
  3. --project <project-name>
  1. Copykubectl create clusterrolebinding cluster-admin-binding \
  2. --clusterrole=cluster-admin \
  3. --user=$(gcloud config get-value core/account)

minikube

TODO(https://github.com/istio/istio.github.io/issues/885)

IBM Cloud Container Service

TODO(https://github.com/istio/istio.github.io/issues/887)

AWS with Kops

TODO(https://github.com/istio/istio.github.io/issues/886)

安装 Webhook

安装基本的 Istio

  1. kubectl apply -f install/kubernetes/istio.yaml

Webhook 需要签名的 cert/key 对。使用 install/kubernetes/webhook-create-signed-cert.sh 生成 kuberntes CA 签发的 cert/key 对,结果文件 cert/key 被 sidecar 注入的 webhook 当做 kuberntes 密钥去使用。

备注: Kubernetes CA 批准(approval)需要权限能够创建和验证 CSR。 更多信息参见:https://kubernetes.io/docs/tasks/tls/managing-tls-in-a-clusterinstall/kubernetes/webhook-create-signed-cert.sh

  1. ./install/kubernetes/webhook-create-signed-cert.sh \
  2. --service istio-sidecar-injector \
  3. --namespace istio-system \
  4. --secret sidecar-injector-certs

安装 sidecar 注入的 configmap:

  1. kubectl apply -f install/kubernetes/istio-sidecar-injector-configmap-release.yaml

设置安装 yaml 中 webhook 的 caBundle,以便 api-server能够用来调用 webhook。

  1. cat install/kubernetes/istio-sidecar-injector.yaml | \
  2. ./install/kubernetes/webhook-patch-ca-bundle.sh > \
  3. install/kubernetes/istio-sidecar-injector-with-ca-bundle.yaml

安装 sidecar 注册器 webhook。

  1. kubectl apply -f install/kubernetes/istio-sidecar-injector-with-ca-bundle.yaml

sidecar 注入的 webhook 应该已经运行。

  1. kubectl -n istio-system get deployment -listio=sidecar-injector
  1. NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
  2. istio-sidecar-injector 1 1 1 1 1d

NamespaceSelector 决定是否在一个对象上运行 webhook,取决于该对象的所在的 namespace 是否匹配选择器

(参见: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors)。默认webhook 的配置使用 istio-injection=enabled.

采用标签 istio-injection 查看 namespae,用以确认 default 命名空间下没有被打标签。

  1. Copykubectl get namespace -L istio-injection
  2. CopyNAME STATUS AGE ISTIO-INJECTION
  3. default Active 1h
  4. istio-system Active 1h
  5. kube-public Active 1h
  6. kube-system Active 1h

部署程序

部署 sleep 程序。验证 deployment 和 pod 都有一个单独的container。

  1. kubectl apply -f samples/sleep/sleep.yaml
  1. kubectl get deployment -o wide
  1. NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
  2. sleep 1 1 1 1 12m sleep tutum/curl app=sleep
  1. kubectl get pod
  1. NAME READY STATUS RESTARTS AGE
  2. sleep-776b7bcdcd-7hpnk 1/1 Running 0 4

default 命名空间下的设置标签 istio-injection=enabled

  1. kubectl label namespace default istio-injection=enabled
  1. kubectl get namespace -L istio-injection
  1. NAME STATUS AGE ISTIO-INJECTION
  2. default Active 1h enabled
  3. istio-system Active 1h
  4. kube-public Active 1h
  5. kube-system Active 1h

注入动作会在 pod 创建的时候发生。杀掉运行的 pod 并验新创建的 pod 已经被注入 sidecar。原来老的 pod 具有 1/1 就绪的的 containers 而被注入的新的 pod 具有 2/2 就绪的 containers。

  1. kubectl delete pod sleep-776b7bcdcd-7hpnk
  1. kubectl get pod
  1. NAME READY STATUS RESTARTS AGE
  2. sleep-776b7bcdcd-7hpnk 1/1 Terminating 0 1m
  3. sleep-776b7bcdcd-bhn9m 2/2 Running 0 7s

default命名空间下禁用注入,验证新的 pod 中 sidecar 不再存在。

  1. kubectl label namespace default istio-injection-
  1. kubectl delete pod sleep-776b7bcdcd-bhn9m
  1. kubectl get pod
  1. NAME READY STATUS RESTARTS AGE
  2. sleep-776b7bcdcd-bhn9m 2/2 Terminating 0 2m
  3. sleep-776b7bcdcd-gmvnr 1/1 Running 0 2s

了解发生什么

admissionregistration.k8s.io/v1alpha1#MutatingWebhookConfiguration
配置 webhook 何时被 kubernetes 调用。Istio 默认选择 namespace 下被打了标签 istio-injection=enabled的Pod。这个行为可以通过修改
install/kubernetes/istio-sidecar-injector-with-ca-bundle.yaml中的 MutatingWebhookConfiguration 配置。

istio-system 命名空间下的 istio-inject ConfigMap 保存了默认注入策略(policy)和 sidecar 注入模板(template)。

策略(policy)

disabled - sidecar 注入器默认不会注入到 pod 中。添加pod模板定义中的注解 sidecar.istio.io/inject 值为 true会启用注入功能。

enabled - sidecar 注入器默认会注入到 pod 中。添加pod模板定义中的注解 sidecar.istio.io/inject 值为 false会禁止注入功能。

模板(template)

sidecar 注入模板使用 https://golang.org/pkg/text/template,当解析和执行后会被解码成以下的 struct 结构,包含了一系列要注入 pod 的 containers 和 volumes。

  1. type SidecarInjectionSpec struct {
  2. InitContainers []v1.Container `yaml:"initContainers"`
  3. Containers []v1.Container `yaml:"containers"`
  4. Volumes []v1.Volume `yaml:"volumes"`
  5. }

模板会在运行的过程中被应用成以下的数据 struct:

  1. type SidecarTemplateData struct {
  2. ObjectMeta *metav1.ObjectMeta
  3. Spec *v1.PodSpec
  4. ProxyConfig *meshconfig.ProxyConfig // Defined by https://istio.io/docs/reference/config/service-mesh.html#proxyconfig
  5. MeshConfig *meshconfig.MeshConfig // Defined by https://istio.io/docs/reference/config/service-mesh.html#meshconfig
  6. }

ObjectMetaSpec 来自于 pod。 ProxyConfigMeshConfig 来自于namespace istio-system下的istio ConfigMap。模板可以用于条件定义注入的 containers 和 volumes。

例如,以下的模板片段,来自于 install/kubernetes/istio-sidecar-injector-configmap-release.yaml

  1. containers:
  2. - name: istio-proxy
  3. image: istio.io/proxy:0.5.0
  4. args:
  5. - proxy
  6. - sidecar
  7. - --configPath
  8. - {{ .ProxyConfig.ConfigPath }}
  9. - --binaryPath
  10. - {{ .ProxyConfig.BinaryPath }}
  11. - --serviceCluster
  12. {{ if ne "" (index .ObjectMeta.Labels "app") -}}
  13. - {{ index .ObjectMeta.Labels "app" }}
  14. {{ else -}}
  15. - "istio-proxy"
  16. {{ end -}}

sample/sleep/sleep.yaml 中的pod定义被应用后会被扩展成:

  1. containers:
  2. - name: istio-proxy
  3. image: istio.io/proxy:0.5.0
  4. args:
  5. - proxy
  6. - sidecar
  7. - --configPath
  8. - /etc/istio/proxy
  9. - --binaryPath
  10. - /usr/local/bin/envoy
  11. - --serviceCluster
  12. - sleep

卸载 webhook

  1. kubectl delete -f install/kubernetes/istio-sidecar-injector-with-ca-bundle.yaml

上述命令并不移除已经已经注入到 Pod 中的 Sidecar。如有需要可以通过滚动升级(rolling update)或者简单删除 pods 使 部署(deployment)重新创建 Pod。