今天我们来分析istio中注入组件istio-sidecar-injector:
用户空间Pod要想加入服务网格, 首先需要注入sidecar container, istio 提供了2种方式实现注入:
「注入」的本质是修改Pod的资源定义, 添加相应的sidecar container定义, 内容包括2个新容器:
istio-init
的initContainer: 通过配置iptables来劫持Pod中的流量istio-proxy
的sidecar容器: 两个进程pilot-agent和envoy, pilot-agent 进行初始化并启动envoykubernetes Admission Control (准入控制)有2种:
其中, Dynamic Admission Control 包含2种:
其中, Admission Webhooks 又包含2种准入控制:
ValidatingAdmissionWebhook 和 MutatingAdmissionWebhook
istio 使用了MutatingAdmissionWebhook来实现 sidecar 注入, 首先需要保证以下条件满足:
kubectl label namespace default istio-injection=enabled
--enable-aggregator-routing=true
且证书和api server连通性正确设置.kube-apiserver 还需要一个配置对象来获取istio关心的资源对象类型, 以及webhook的服务地址. 如果你是使用helm安装的istio, 配置对象已经添加好了, 查阅MutatingWebhookConfiguration:
- apiVersion: admissionregistration.k8s.io/v1beta1
kind: MutatingWebhookConfiguration
metadata:
name: istio-sidecar-injector
webhooks:
- clientConfig:
service:
name: istio-sidecar-injector
namespace: istio-system
path: /inject
name: sidecar-injector.istio.io
namespaceSelector:
matchLabels:
istio-injection: enabled
rules:
- apiGroups:
- ""
apiVersions:
- v1
operations:
- CREATE
resources:
- pods
该配置告诉kube-apiserver: 命名空间istio-system 中的服务 istio-sidecar-injector
(默认端口443), 通过路由/inject
, 处理v1/pods
的CREATE, 同时pod需要满足命名空间istio-injection: enabled
, 当有符合条件的pod被创建时, kube-apiserver就会对该服务发起调用, 服务返回的内容正是添加了sidecar注入的pod定义.
查看Pod istio-sidecar-injector
定义:
% kubectl -n istio-system get pod istio-sidecar-injector-sdfssddf-fsdfsd -oyaml
...(略)...
volumeMounts:
- mountPath: /etc/istio/inject
name: inject-config
readOnly: true
volumes:
- configMap:
items:
- key: config
path: config
name: istio-sidecar-injector
name: inject-config
可以看到该Pod利用projected volume 把istio-sidecar-injector
这个config map 的config挂到了自己容器路径/etc/istio/inject/config
, config map 内容正是注入用户空间pod所需的模板.
如果是使用helm安装istio, 该 configMap 模板github源码位于:
https://github.com/istio/istio/blob/master/install/kubernetes/helm/istio/templates/sidecar-injector-configmap.yaml.
该config map 是在安装istio时添加的, kubernetes 会自动维护 projected volume的更新,所以容器 sidecar-injector
只需要从本地文件直接读取所需配置.
用户可以按需修改该模板内容:
% kubectl -n istio-system get configmap istio-sidecar-injector -o=jsonpath='{.data.config}'
查看该configMap, 其中 data.config
包含以下内容(简化版):
policy: enabled // 是否开启自动注入
template: |-
initContainers:
[[ if ne (annotation .ObjectMeta `sidecar.istio.io/interceptionMode` .ProxyConfig.InterceptionMode) "NONE" ]]
- name: istio-init
image: "docker.io/istio/proxy_init:1.1.0"
.....
securityContext:
capabilities:
add:
- NET_ADMIN
.....
containers:
- name: istio-proxy
args:
- proxy
- sidecar
.....
image: [[ annotation .ObjectMeta `sidecar.istio.io/proxyImage` "docker.io/istio/proxyv2:1.1.0" ]]
.....
readinessProbe:
httpGet:
path: /healthz/ready
port: [[ annotation .ObjectMeta `status.sidecar.istio.io/port` 0 ]]
.....
securityContext:
capabilities:
add:
- NET_ADMIN
runAsGroup: 1337
.....
volumeMounts:
.....
- mountPath: /etc/istio/proxy
name: istio-envoy
- mountPath: /etc/certs/
name: istio-certs
readOnly: true
.....
volumes:
.....
- emptyDir:
medium: Memory
name: istio-envoy
- name: istio-certs
secret:
optional: true
[[ if eq .Spec.ServiceAccountName "" -]]
secretName: istio.default
[[ else -]]
secretName: [[ printf "istio.%s" .Spec.ServiceAccountName ]]
.....
另外istio-sidecar-injector
还给容器istio-proxy
挂了2个volumes:
istio-envoy
的emptydir volume, 挂载到容器目录/etc/istio/proxy
, 作为envoy的配置文件目录istio-certs
的secret volume, 默认secret名为istio.default
, 挂载到容器目录/etc/certs/
, 存放相关的证书, 包括服务端证书, 和可能的mtls客户端证书% kubectl exec productpage-v1-sdffsds-fdsfs -c istio-proxy -- ls /etc/certs/
cert-chain.pem
key.pem
root-cert.pem
后续文章将会对sidecar istio-proxy
进一步分析.