设置 Sidecar

注入 Sidecar

为了充分利用 Istio 的所有特性,网格中的 pod 必须运行一个 Istio sidecar 代理。

向 Pod 中注入 Istio sidecar 的两种方法:使用 istioctl 手动注入或启用 Pod 所属命名空间的 Istio sidecar 注入器自动注入。

手动注入直接修改配置,如 Deployment,并将代理配置注入其中。

当 Pod 所属的命名空间启用自动注入后,自动注入器会使用准入控制器在创建 Pod 时自动注入代理配置。通过应用 istio-sidecar-injector ConfigMap 中定义的模版进行注入。

  • 下载 istio:
curl -L https://istio.io/downloadIstio | sh -

cd istio-1.9.0

export PATH=$PWD/bin:$PATH              #将 istioctl 加入环境变量

然后需要通过 helm 部署好 istio,此处省略。

  • 手动注入 sidecar:

要手动注入 deployment,请使用 istioctl kube-inject

istioctl kube-inject -f samples/sleep/sleep.yaml | kubectl apply -f -

默认情况下将使用集群内的配置,或者使用该配置的本地副本来完成注入。

kubectl -n istio-system get configmap istio-sidecar-injector -o=jsonpath='{.data.config}' > inject-config.yaml

kubectl -n istio-system get configmap istio-sidecar-injector -o=jsonpath='{.data.values}' > inject-values.yaml

kubectl -n istio-system get configmap istio -o=jsonpath='{.data.mesh}' > mesh-config.yaml

指定输入文件,运行 kube-inject 并部署。

istioctl kube-inject \
  --injectConfigFile inject-config.yaml \
  --meshConfigFile mesh-config.yaml \
  --valuesFile inject-values.yaml \
  --filename samples/sleep/sleep.yaml \
  | kubectl apply -f -

验证 sidecar 已经被注入到 READY 列下 2/2 的 sleep pod 中。

kubectl get pod -l app=sleep

NAME                     READY   STATUS    RESTARTS   AGE
sleep-64c6f57bc8-f5n4x   2/2     Running   0          24s
  • 自动注入 sidecar:

使用 Istio 提供的准入控制器变更 webhook,可以将 sidecar 自动添加到可用的 Kubernetes Pod 中。

当在一个命名空间中设置了 istio-injection=enabled 标签,且 injection webhook 被启用后,任何新的 Pod 都有将在创建时自动添加 sidecar。

请注意,区别于手动注入,自动注入发生在 Pod 层面,Deployment 本身将看不到有任何更改。取而代之,需要检查单独的 Pod(使用 kubectl describe)来查询被注入的代理。

  • 禁用或更新注入 webhook:

Sidecar 注入 webhook 是默认启用的。如果希望禁用 webhook,可以使用 Helm 将 sidecarInjectorWebhook.enabled 设置为 false


部署应用

  • 部署 sleep 应用:

验证 Deployment 和 Pod 只有一个容器。

kubectl apply -f samples/sleep/sleep.yaml

kubectl get deploy -o wide

NAME    READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS   IMAGES            SELECTOR
sleep   1/1     1            1           67s   sleep        curlimages/curl   app=sleep

kubectl get pod

NAME                     READY   STATUS    RESTARTS   AGE
sleep-64d7d56698-lwsjh   1/1     Running   0          2m29s
  • 给 namespace 打上标签:

将 default namespace 标记为 istio-injection=enabled

kubectl label namespace default istio-injection=enabled

kubectl get namespaces -L istio-injection

NAME              STATUS   AGE    ISTIO-INJECTION
default           Active   194d   enabled
ingress-nginx     Active   194d   
istio-system      Active   20h    
kube-node-lease   Active   194d   
kube-public       Active   194d   
kube-system       Active   194d

注入发生在 Pod 创建时。杀死正在运行的 Pod 并验证新创建的 Pod 是否注入 sidecar。原来的 Pod 具有 READY 为 1/1 的容器,注入 sidecar 后的 Pod 则具有 READY 为 2/2 的容器。

kubectl get pod -l app=sleep

NAME                     READY   STATUS    RESTARTS   AGE
sleep-64d7d56698-27mbt   2/2     Running   0          2m14s

查看已注入 Pod 的详细状态。可以看到被注入的 istio-proxy 容器和对应的卷。

kubectl describe pod -l app=sleep

禁用 default namespace 注入,并确认新的 pod 在创建时没有 sidecar。

kubectl label namespace default istio-injection-

kubectl delete pod -l app=sleep

kubectl get pod

NAME                     READY   STATUS    RESTARTS   AGE
sleep-64d7d56698-xcr8l   1/1     Running   0          7s

理解原理

当 Kubernetes 调用 webhook 时,admissionregistration 配置被应用。默认配置将 sidecar 注入到所有拥有 istio-injection=enabled 标签的 namespace 下的 Pod 中。istio-sidecar-injector 配置字典指定了注入 sidecar 的配置。如需更改指定哪些 namespace 被注入,可以使用以下命令编辑 MutatingWebhookConfiguration

kubectl edit mutatingwebhookconfiguration istio-sidecar-injector

修改 MutatingWebhookConfiguration 之后,应该重启 sidecar 注入器的 Pod。

  • 策略:

disabled - 默认情况下不会将 sidecar 注入到 Pod 中。在 Pod 模板规范中添加 sidecar.istio.io/inject 的值为 true 来覆盖默认值并启用注入。

enabled - sidecar 将默认注入到 Pod 中。在 Pod 模板规范中添加 sidecar.istio.io/inject 的值为 false 来覆盖默认值并禁用注入。

下面的示例使用 sidecar.istio.io/inject 注解来禁用 sidecar 注入。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: ignored
spec:
  template:
    metadata:
      annotations:
        sidecar.istio.io/inject: "false"
    spec:
      containers:
      - name: ignored
        image: tutum/curl
        command: ["/bin/sleep","infinity"]
  • 模板:

Sidecar 注入模板使用 https://golang.org/pkg/text/template,当解析和执行时,将解码成下面的结构体,包含需要注入到 Pod 中的容器和卷。

type SidecarInjectionSpec struct {
    
    
      RewriteAppHTTPProbe bool                          `yaml:"rewriteAppHTTPProbe"`
      InitContainers      []corev1.Container            `yaml:"initContainers"`
      Containers          []corev1.Container            `yaml:"containers"`
      Volumes             []corev1.Volume               `yaml:"volumes"`
      DNSConfig           *corev1.PodDNSConfig          `yaml:"dnsConfig"`
      ImagePullSecrets    []corev1.LocalObjectReference `yaml:"imagePullSecrets"`
}

该模板在运行时应用于以下数据结构。

type SidecarTemplateData struct {
    
    
    DeploymentMeta *metav1.ObjectMeta
    ObjectMeta     *metav1.ObjectMeta
    Spec           *corev1.PodSpec
    ProxyConfig    *meshconfig.ProxyConfig  // Defined by https://istio.io/docs/reference/config/service-mesh.html#proxyconfig
    MeshConfig     *meshconfig.MeshConfig   // Defined by https://istio.io/docs/reference/config/service-mesh.html#meshconfig
}

ObjectMetaSpec 来源于 Pod。ProxyConfigMeshConfig 来源于 istio-system namespace 下 istio 的 ConfigMap。模版可以使用这些数据有条件地定义被注入的卷和容器。

例如下面的模版。

containers:
- name: istio-proxy
  image: istio.io/proxy:0.5.0
  args:
  - proxy
  - sidecar
  - --configPath
  - {
    
    {
    
     .ProxyConfig.ConfigPath }}
  - --binaryPath
  - {
    
    {
    
     .ProxyConfig.BinaryPath }}
  - --serviceCluster
  {
    
    {
    
     if ne "" (index .ObjectMeta.Labels "app") -}}
  - {
    
    {
    
     index .ObjectMeta.Labels "app" }}
  {
    
    {
    
     else -}}
  - "istio-proxy"
  {
    
    {
    
     end -}}

将在使用模版 samples/sleep/sleep.yaml 定义的 Pod 被应用时变为

containers:
- name: istio-proxy
  image: istio.io/proxy:0.5.0
  args:
  - proxy
  - sidecar
  - --configPath
  - /etc/istio/proxy
  - --binaryPath
  - /usr/local/bin/envoy
  - --serviceCluster
  - sleep

对于例外

有些情况下用户无法控制 Pod 的创建,例如,这些用户是被其他人创建的。因此他们无法在 Pod 中添加 sidecar.istio.io/inject 注解,来明确是否安装 sidecar。

考虑在部署应用程序时创建辅助 Pod 作为中间步骤。例如 OpenShift Source to Image Builds,创建这样的 Pod 用于构建应用程序的源代码。构建二进制工件后,应用程序 Pod 就可以运行了,而用于辅助的 Pod 则被丢弃。这些中间 Pod 不应该有 Istio sidecar,即使策略被设置为 enabled,并且名称空间被正确标记为自动注入。

对于这种情况,可以根据 Pod 上的标签,指示 Istio 不要在那些 Pod 中注入 sidecar。可以通过编辑 istio-sidecar-injector 的 ConfigMap 并添加 neverInjectSelector 条目来实现。它是一个 Kubernetes 标签选择器数组,使用 OR'd,在第一次匹配成功后则停止。看一个例子:

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:
...

上面声明的意思是:永远不要注入带有 openshift.io/build.name 或者 openshift.io/deployer-pod-for.name 标签的 Pod —— 标签的值无关紧要,只检查键是否存在。添加了这个规则之后,就涵盖了上面所说的 OpenShift 的构建用例,也就是说辅助 Pod 不会被注入 sidecar(因为 source-to-image 工具产生的辅助 Pod 明确包含这些标签)。

完整起见,还可以使用一个名为 alwaysInjectSelector 的字段,它具有类似的语法,总是将 sidecar 注入匹配标签选择器的 Pod 中,而忽略全局策略。

值得注意的是,Pod 中的注解具有比标签选择器更高的优先级。如果一个 Pod 有 sidecar.istio.io/inject: "true/false" 的标记那么它将先被履行。因此,优先级的顺序为:

Pod Annotations → NeverInjectSelector → AlwaysInjectSelector → Default Policy


卸载 sidecar 自动注入器

kubectl delete mutatingwebhookconfiguration istio-sidecar-injector

kubectl delete svc -n istio-system istio-sidecar-injector

kubectl delete deploy -n istio-system istio-sidecar-injector

kubectl delete sa -n istio-system istio-sidecar-injector-service-account

kubectl delete clusterrole istio-sidecar-injector-istio-system

kubectl delete clusterrolebinding istio-sidecar-injector-admin-role-binding-istio-system

上面的命令不会从 Pod 中移除注入的 sidecar。需要进行滚动更新或者直接删除 Pod,并强制 Deployment 创建它们。

同时给 namespace 去掉自动注入的标签:

kubectl label namespace default istio-injection-

猜你喜欢

转载自blog.csdn.net/miss1181248983/article/details/116166667