1. Blog
  2. Golang
  3. kubernetes
  4. Rust
  5. 关于作者

安装部署

安装部署

本文仅涉及将 istio 部署于 kubernetes .

按照目前的 kubernetes 服务部署方式,istio 可以通过一下几个方式部署:

  1. helm,这是 istio 的主要部署方式。
  2. istio operator,通过 kubernetes 的 operator 模式进行 istio 部署,这个方式使用起来最便捷。而实际上 operator 也是调用的 helm 进行部署和修改的。
  3. istioctl,istioctl 是 istio 的命令行工具,可以通过它控制 istio 上的各种配置。而实际上 istioctl 也是调用的 helm 进行部署的。

本文主要介绍使用 operator 方式部署。

建议直接看官方文档: istio/install

版本检查

istio 依赖 kubernetes 功能,需要按照当前的 k8s 版本选择适合的 istio 版本。参考 Support status of Istio releases

只要不是过于老旧的 k8s 集群,处于Supported versions内的都可以直接使用最新版本 istio

安装 istio operator

istio operator 可以通过两个方式安装

安装 istioctl

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

实际使用的脚本为istio/istio/downloadIstioCandidate.sh 可以选择安装 istioctl 并使用 istioctl 相关命令来配置 istio 部署,也可以使用在集群中安装 istio operator 的方式来配置 istio 部署。

istioctl operator init

对于 docker.io 拉取镜像失败的场景可以指定其他镜像仓库

istioctl operator init --hub example.com/istio

istioctl 还有许多可调参数

安装 istio

在安装完成 istio-operator 后可以通过 istio-operator CR 来安装 istio。 (推荐)在 istio-system 空间中安装 istio,因其为 istio 默认空间:

对于默认安装可以直接:

kubectl apply -f - <<EOF
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
metadata:
  namespace: istio-system
  name: default-istiocontrolplane
spec:
  profile: default
EOF

对于访问 docker.io 不方便的情况可以指定其他 OCI 仓库

apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
metadata:
  namespace: istio-system
  name: default-istiocontrolplane
spec:
  profile: default
  hub: example.com/istio # 第三方仓库(可选)
  tag: 1.11.0 #指定tag(可选),若不指定,与operator版本相同。

可配置字段参考IstioOperatorSpec

不同 profile 的区别在于默认安装的组件不同,使用默认配置即可。参考 Installation Configuration Profiles

istio operator 以及 istioctl 均使用的 helm 方式安装 istio,所有配置均会发送至 helm ,详细的配置以及默认配置参考对应 chart 的 helm value.yaml.

不同的 profile 对应不同的 helm charts 中的默认 values,参考manifests/profiles

这些所有的组件 helm chart 都在 istio repo manifests/charts 中。

集成 jaeger tracing

istio 可以与 jaeger 集成,将服务网格内的 tracing 数据发送至 jaeger 服务。与 jaeger 集成就是让每个服务网格内的 sidecar(envoy) 被配置为开启追踪并发送追踪数据至 jaeger。

官方配置参见 : Configurability

jaeger 安装参考Operator for Kubernetes

istio 使用的 zipkin 协议,对于 jaeger zipkin 参考Migrating from Zipkin

这里有一个小坑:

1.25 版本的 jaeger 默认不开启 zipkin 端口(9411),虽然其设置了环境变量 “COLLECTOR_ZIPKIN_HTTP_PORT” 但似乎没有生效。所以需要手动设置 options: {“collector.zipkin.host-port”:”9411”},以便于 istio 使用。

apiVersion: jaegertracing.io/v1
kind: Jaeger
spec:
  strategy: production
  collector:
    options:
      collector.zipkin.host-port: "9411" #指定这一个选项以开启 zipkin 9411

在 istio 中开启 tracing,主要有几个配置:

  1. 开启 tracing
  2. 配置 tracing 服务器地址
  3. 配置采样方式

需要在 istio-operator CR 中更新设置几个配置:

apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
  meshConfig:
    enableTracing: true # 开启tracing
    defaultConfig:
      tracing:
        sampling: 1.0 # 默认采样率 1%
        zipkin:
          address: jaeger-collector.observability:9411 # tracing 收集器地址

如果是使用 jaeger gaent 的方式,可能需要更改 tracing 服务地址。

配置 istio gateway sidecar inject

istio 网关实例配置参考: deploying-a-gateway

默认的 istio operator 没有对 istio-gateway 设置开启注入,也就无法记录网关的追踪数据。默认将 gateway 安装在了 istio-system 空间,安全起见,推荐将其移动至独立的空间。

需要更改两个配置:

  1. Gateway 安装的目标空间。
  2. Gateway 设置注入方式为 gateway 方式(区别于 sidecar 模式)。
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
  components:
    ingressGateways:
      - name: istio-ingress
        namespace: istio-ingress # gateway namespace
  values:
    gateways:
      istio-ingressgateway:
        injectionTemplate: "gateway" # enable gateway injection

1.11 新增的针对 gateway 的注入方式,不再使用 sidecar。gateway-injection istio 对 gateway 的注入方式与常规不同,无法使用 sidecar 方式注入 gateway,需要指定 injectionTemplate 为 gateway。

此时从 jaeger 界面查询即可查询到从 gateway 开始的追踪数据了。

开启 istio cni

Install Istio with the Istio CNI plugin

istio cni 解决的问题是:

由于 istio 会向 pod 注入 sidecar 和一个 initContainer,initContainer 用于改变 iptables 规则将流量导至 sidecar,这就需要要求 pod 有 NET_ADMIN 能力。 如此的 Pod 权限,可能让网络存在安全风险或者有其他的不便。

istio cni 在 Pod 生命周期的创建网络阶段就进行了这个更改,在容器运行时就不再需要 NET_ADMIN 能力了

apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
  components:
    cni:
      enabled: true # enable cni

由于 cni 插件是链式执行的,istio cni 不会与其他 cni 冲突,安装 istio cni 也不会替换已存在的 cni 插件。calico cni 下启用 istio cni 后的 cni 配置类似如下:

example-configuration

{
  "cniVersion": "0.3.1",
  "name": "k8s-pod-network",
  "plugins": [
    {
      "type": "calico"
      ...
    },
    ...
    {
      "kubernetes": {
        "cni_bin_dir": "/opt/cni/bin",
        "exclude_namespaces": ["istio-system", "kube-system"],
        "kubeconfig": "/etc/cni/net.d/ZZZ-istio-cni-kubeconfig"
      },
      "log_level": "info",
      "log_uds_address": "/var/run/istio-cni/log.sock",
      "name": "istio-cni",
      "type": "istio-cni"
    }
  ]
}

安装 kiali 进行可视化

kiali 是 mesh 的可视化工具,文档上推荐通过 istio addon 方式安装

kiali-operator也有但是没有正式的易用的文档。

kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.11/samples/addons/kiali.yaml

可以使用 istioctl 进行展示access_to_the_ui

istioctl dashboard kiali

使用 istioctl 是临时方案,若要持久化,kiali 在端口 20001 监听 webui 地址,可以访问其 service.

kiali 默认部署与 istio-system 空间下,使用了名称为 kiali 的 configmap 作为配置。

其文档上没有太多关于配置的说明,默认配置参考config.go#L407

我们的部署使用了外部的 promethus 以及 jaeger 等,需要修改配置才能使 kiali 正常生效。主要涉及如下配置:

# configmap kiali
external_services:
  grafana:
    in_cluster_url: http://grafana.grafana:3000
  prometheus:
    url: http://prometheus.monitoring:9090
  tracing:
    in_cluster_url: http://jaeger-query.observability:16685/jaeger

与 prometheus 集成

kiali 使用了 prometheus 数据来生成 kiali graph,为了能够正确的生成这些图,需要从 prometheus 获取 envoy sidecar 的指标。即需要保证 envoy 相关指标被 primetheus 采集到。

prometheus/#configuration 提供两种方式实现。

sidecar 在注入的时候存在配置 meshConfig.enablePrometheusMerge , 其控制了 sidecar 的注入行为,如果为 true 则会将原 pod 的 prometheus 注解更换为聚合的 prometheus 注解(如下)。

kind: Pod
metadata:
  annotations:
    prometheus.io/path: /stats/prometheus
    prometheus.io/port: "15020"
    prometheus.io/scrape: "true"

一般来说有几种配置方式:

  1. sidecar 会为 pod 增加 prometheus.io/scrape: "true" 注解,这个注解约定为存在该注解的 pod 会被 prometheus 发现并采集。也就能够被 kiali 所使用。(目前使用了 prometheus operator 关闭了该功能)
  2. 如果配置上没有对上述注解响应,即即使指定了注解也无法被发现。则需要主动设置采集规则customized-scraping-configurations

    - job_name: "istiod"
      kubernetes_sd_configs:
        - role: endpoints
          namespaces:
            names:
              - istio-system
      relabel_configs:
        - source_labels:
            [
              __meta_kubernetes_service_name,
              __meta_kubernetes_endpoint_port_name,
            ]
          action: keep
          regex: istiod;http-monitoring
    
    - job_name: "envoy-stats"
      metrics_path: /stats/prometheus
      kubernetes_sd_configs:
        - role: pod
      relabel_configs:
        - source_labels: [__meta_kubernetes_pod_container_port_name]
          action: keep
          regex: ".*-envoy-prom"
    

对于使用 prometheus operator 的可以将上述配置添加至 additional-scrape-configs secret 中。 参考additional-scrape-config.md

此外,还有一些 RecordRule 可以增加至 prometheus,参考using-prometheus-for-production-scale-monitoring

与 grafana 集成

integrations/grafana/

istio 可以在 grafana 生成许多 dashboard 以观察整个 istio 上的状态。

istio 在 grafana 仓库中有 7639 11829 7636 7630 7645 等几个 dashboard 可以使用,可以通过 grafana ui 进行安装。

对于使用 grafana operator 的方式,需要自行生成对应 CR。

开启 istio dns proxy

在 kubernetes istio 中的 service 使用 coredns 解析 dns。这有个弱点,无法解析 serviceentry 的域名。

作为改进,可以为 mesh 启用 DNS 代理,若 dns 能够在其缓存中找到则直接响应而无需转发至上游 dns(coredns)。

一方面,istio dns 可以在这个阶段对 serviceentry 中的 dns 做响应,另一方面,可以减少对上游 dns 的请求。

参考:dns-proxy

apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
  meshConfig:
    defaultConfig:
      proxyMetadata:
        # Enable basic DNS proxying
        ISTIO_META_DNS_CAPTURE: "true"
        # Enable automatic address allocation, optional
        ISTIO_META_DNS_AUTO_ALLOCATE: "true"

增加 sidecar egress 限制

istio 默认安装下监听所有空间下的 service 以便于网格服务之间都能够互相通信。 在集群 workload 较多的情况下,istio sidecar 中会存在集群所有的服务配置,占用的内存甚至可高达 GB 级别。

如果能够将 sidecar 中存储的配置项目缩减则可显著降低内存使用。

istio 提供了 SideCar 资源可以针对命名空间级别对 sidecar 中的服务条目进行限制。让该空间下的 sidecar 仅能访问所配置的服务。

sidecar 支持通过 ingress/egress 项目和 workloadSelector 选择需要配置的服务。

更多参考官方文档: istio/sidecar

以 book-info 为例:

apiVersion: networking.istio.io/v1beta1
kind: Sidecar
metadata:
  name: default
  namespace: istio-demo
spec:
  egress:
    - hosts:
        - "./*"

这个 sidecar 限制了服务发现的范围从整个集群到了当前 namespace。减少了内存占用,但是无法跨空间 mesh 通信。 如果需要跨空间通信则需要在 sidecar egress 上增加需要访问的空间。

hosts 中的条目以 namespace/dnsName 格式

调整前后内存占用对比:

$ kubectl -n istio-demo top pod
NAME                             CPU(cores)   MEMORY(bytes)
details-v1-6f6bc76446-4bksd      10m          327Mi
productpage-v1-69d595976-c8qkj   56m          281Mi
ratings-v1-75475c49cd-cbbnn      7m           325Mi
reviews-v1-c5f75b9d4-ngst4       67m          381Mi
reviews-v2-65dffdf654-s7kt4      50m          375Mi
reviews-v3-755bf5cf76-52bxj      9m           457Mi
$ kubectl -n istio-demo top pod --use-protocol-buffers
NAME                             CPU(cores)   MEMORY(bytes)
details-v1-6f6bc76446-vjkrw      8m           60Mi
productpage-v1-69d595976-sk8lc   56m          98Mi
ratings-v1-75475c49cd-bv6q6      10m          50Mi
reviews-v1-c5f75b9d4-2nk52       132m         150Mi
reviews-v2-65dffdf654-mdrbv      39m          189Mi
reviews-v3-755bf5cf76-lk829      140m         192Mi

常见问题