ServiceMesh-istio(一)

ServiceMesh-istio(一)

十一月 27, 2018

之前我们讲了 Linkerd2 ,也了解了什么是 ServiceMesh ,本篇开始我们来讲 ServiceMesh 的另一种实现方式 Istio。本篇作为 Istio 第一篇主要讲述Istio的概念、功能、安装以及演示sidecar的注入。

什么是 Istio

Istio是一个用来连接、管理和加密微服务的开放平台。可以让你在不修改微服务源代码的情况之下,很轻松地给微服务加上诸如负载均衡、服务间认证、监控等等的功能。从宏观上来说,Istio 有助于降低应用上云部署的复杂性,并减轻开发团队对微服务移植到云平台上的压力和运维团队的对微服务管理的压力。它是一个完全开源的服务网格,可以透明地分层到现有的分布式应用程序上。它也是一个平台,包括允许它集成到任何日志记录平台、遥测或策略系统的 API。Istio 的多样化功能集使您能够成功高效地运行分布式微服务架构,并提供保护、连接和监控微服务的统一方法。

1
istio, an open platform to connect, manage, and secure microservices

想要让服务支持 Istio,只需要在您的环境中部署一个特殊的 sidecar 代理,使用 Istio 控制平面功能配置和管理代理,拦截微服务之间的所有网络通信:

  • HTTP、gRPC、WebSocket 和 TCP 流量的自动负载均衡。—负载均衡
  • 通过丰富的路由规则、重试、故障转移和故障注入,可以对流量行为进行细粒度控制。—熔断、流量管理
  • 可插入的策略层和配置 API,支持访问控制、速率限制和配额。—策略控制
  • 对出入集群入口和出口中所有流量的自动度量指标、日志记录和跟踪。—监控、分布式追踪
  • 通过强大的基于身份的验证和授权,在集群中实现安全的服务间通信。—认证与授权

Istio 是独立于平台的,旨在运行在各种环境中,包括跨云、内部部署、Kubernetes、Mesos 等。Istio 目前支持:

  • 在 Kubernetes 上部署的服务
  • 使用 Consul 注册的服务
  • 在虚拟机上部署的服务

而本篇主要描述在 Kubernetes 部署 istio 和用 istio 管理已经部署在 Kubernetes 上的服务。

Istio 的架构

Istio 的架构和 Linkerd2 类似,逻辑上分为数据平面和控制平面:

  • 数据平面的职责是处理网格内部服务之间的通信,并负责服务发现、负载均衡、流量管理、健康检查等功能。由所有以 sidecar 模式部署的智能代理 Envoy 所组成的,作为每个pod所有流量的代理,可以调节和控制微服务及 Mixer 之间所有的网络通信。
  • 控制平面的职责是管理和配置 Sidecar 代理以实施策略并收集遥测。负责管理和配置代理来路由流量,以及配置 Mixer 以实施策略和收集遥测数据。有三个组件:Pilot、Mixer 和 Citadel。
  • Envoy 被部署为sidecar,和应用容器被部署在同一个pod中,代理应用所有的请求,能够完成动态服务发现、负载均衡、TLS终止、HTTP/2 & gRPC 代理、熔断、健康检查、基于百分比流量拆分的灰度发布、故障注入、丰富的度量指标。
    envoy 代理将大量关于流量行为的信号作为属性提取出来,而这些属性又可以在 Mixer 中用于执行策略决策,并发送给监控系统,以提供整个网格行为的信息。

  • Mixer 是一个平台无关的组件,负责在 istio 上执行访问控制和使用策略,同时从envoy和其他服务收集监控数据(遥测),将收集到的信息传给用户可以自定义的后端进行处理。

  • Pilot 为 Envoy 提供服务发现、智能路由(如:A/B测试、金丝雀部署)和弹性流量管理功能(如超时、重试、熔断)。它负责将控制流量行为的高级路由规则转化成特定的 envoy 的配置,并在运行时将他们传播到sidecar。

  • Citadel 通过内置身份和凭证管理可以提供强大的服务间和终端用户身份验证。同时可以将未加密的流量加密,并支持RBAC,以控制谁可以访问您的服务。

安装

下载 Istio

进入 Istio release 页面(说明下本文环境已经做了很久了,现在最新版本已经到1.0.4了)

1
2
3
4
$ wget https://github.com/istio/istio/releases/download/1.0.2/istio-1.0.2-linux.tar.gz
$ tar zxf istio-1.0.2-linux.tar.gz
$ cp istio-1.0.2/bin/istioctl /usr/local/bin/
$ cd istio-1.0.2

安装目录中包含:

  • install/ 目录中包含了 Kubernetes 安装所需的 .yaml 文件
  • samples/ 目录中是示例应用
  • istioctl 客户端文件保存在 bin/ 目录之中。istioctl 的功能是手工进行 Envoy Sidecar 的注入,以及对路由规则、策略的管理
  • istio.VERSION 配置文件

Istio 安装

在安装 Istio 之前要确保你已经部署了 Kubernetes 集群( 版本要求 v1.9 及以上 )并配置好本地的 kubectl 客户端,如果想用 Helm 部署 istio 还需要配置好 helm 客户端。

  1. 使用 kubectl 安装 istio

    1
    $ kubectl create -f install/kubernetes/istio-demo.yaml
  2. 安装包内的 install/kubernetes/helm 目录中包含了 Istio 的 Chart,官方提供了两种方法:可以使用 helm template 生成 istio.yaml 然后再安装。也可以通过 Tiller 使用 helm install 直接安装,但这里由于网络受限一直也没这么做过,就不讲解了。

  • 使用 helm template 安装 istio
    1
    2
    3
    4
    5
    6
    # 将 Istio 的核心组件呈现为名为 istio.yaml 的 Kubernetes 清单文件:
    $ helm template install/kubernetes/helm/istio --name istio --namespace istio-system > istio.yaml

    # 通过清单文件安装组件
    $ kubectl create namespace istio-system
    $ kubectl create -f istio.yaml

Istio 配备了一组丰富而强大的功能,但你可能只需要这些功能的一部分。例如,你可能只对安装 Istio 的流量管理所需的最小集合感兴趣。

  • 使用 helm template 最小化安装 istio
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    # 生成只使用 Istio 的流量管理功能的 Kubernetes 清单文件:
    $ helm template install/kubernetes/helm/istio --name istio --namespace istio-system \
    --set ingress.enabled=false \
    --set gateways.istio-ingressgateway.enabled=false \
    --set gateways.istio-egressgateway.enabled=false \
    --set galley.enabled=false \
    --set sidecarInjectorWebhook.enabled=false \
    --set mixer.enabled=false \
    --set prometheus.enabled=false \
    --set global.proxy.envoyStatsd.enabled=false > istio-mini.yaml

    # 通过清单文件安装组件
    $ kubectl create namespace istio-system
    $ kubectl create -f istio-mini.yaml

Istio 会被安装到 istio-system 命名空间下,并且能够对所有其他命名空间的服务进行管理。如下图所示,其中 istio-cleanup-secrets 和 istio-grafana-post-install 都是 job,istio-cleanup-secrets 用于清理过去的 Istio 遗留下来的 CA 部署(包括 sa、deploy 以及 svc 三个对象; istio-grafana-post-install 用于配置 Grafana。

等所有 Pod 启动后,可以通过 NodePort、Ingress 或者 kubectl proxy 来访问Prometheus、Grafana、Servicegraph 和 Jaeger服务。本文中我使用 Ingress 的方式暴露这四个服务。

Prometheus、Grafana、Servicegraph 和 Jaeger服务的 Ingress 文件如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
[root@lab01 ~]# cat istio-ingress.yaml
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: prometheus
namespace: istio-system
spec:
rules:
- host: prometheus.istio.io
http:
paths:
- path: /
backend:
serviceName: prometheus
servicePort: 9090

---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: grafana
namespace: istio-system
spec:
rules:
- host: grafana.istio.io
http:
paths:
- path: /
backend:
serviceName: grafana
servicePort: 3000

---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: servicegraph
namespace: istio-system
spec:
rules:
- host: servicegraph.istio.io
http:
paths:
- path: /
backend:
serviceName: servicegraph
servicePort: 8088

---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: tracing
namespace: istio-system
spec:
rules:
- host: tracing.istio.io
http:
paths:
- path: /
backend:
serviceName: tracing
servicePort: 80

创建 Ingress

1
$ kubectl create -f istio-ingress.yaml

浏览器所在主机修改hosts文件,添加host和ingress controller对应主机

1
172.xx.xx.229  tracing.istio.io prometheus.istio.io grafana.istio.io servicegraph.istio.io

演示示例

  1. 手动注入

    1
    2
    3
    4
    5
    # 使用集群内置配置将 Sidecar 注入到 Deployment 中,然后再创建带有代理的应用:
    $ istioctl kube-inject -f samples/bookinfo/platform/kube/bookinfo.yaml | kubectl apply -f -

    # 给应用定义 Ingress gateway:
    $ kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yaml
  2. 自动注入,原理和Linkerd2类似的,下次我们详细再说

部署完成后可以看到有三个版本的reviews,关于这个 demo 我们后面的测试会详细讲解。

  1. 访问测试前,我们先找到 ingressgateway 所在节点和 NodePort
    1
    2
    $ export GATEWAY_URL=$(kubectl -n istio-system get po -l istio=ingressgateway -o go-template='{{range .items}}{{.status.hostIP}}{{end}}')
    $ export HTTP2_PORT=$(kubectl -n istio-system get svc istio-ingressgateway -o go-template='{{range .spec.ports}}{{if eq .name "http2"}}{{.nodePort}}{{end}}{{end}}')

通过 ingressgateway 访问测试

连续访问100次,返回200为正常

1
$ for i in {1..100}; do curl -o /dev/null -s -w "%{http_code}\n" http://${GATEWAY_URL}:${HTTP2_PORT}/productpage; done

通过 http://prometheus.istio.io 尝试在 Prometheus 中查询数据:

通过 http://grafana.istio.io 访问 Grafana 服务:

通过 http://servicegraph.istio.io 访问 ServiceGraph 服务,展示服务之间调用关系图,其中使用 DOT 作为图形描述语言而 graphviz 将 DOT 语言的文本渲染成为图片。

通过 http://tracing.istio.io/ 访问 Jaeger 跟踪页面,尝试查询 productpage 的历史访问数据:

为 Istio 安装可观测性工具 Kiali

没有一个统一的可视化工具是不是很麻烦呢? Kiali 是专为 Istio 提供可视化服务网格的拓扑的一个开源项目,你可以通过 Kali 监控到服务网格中微服务各个组件的运行状况,Kiali 也可以调用 Jaeger 提供服务链路的分布式追踪能力。

Kiali 版本查询 kiali release

1
2
# 由于 “envsubst” 在Ubuntu中默认有安装,所以我们这里 centos 系统还要从 gettext 中安装 “envsubst”
$ yum install gettext
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# Jaeger 和 Grafana 的 ingress 地址,一定要可从浏览器打开的地址,如 ingress 或 NodePort
$ JAEGER_URL="http://tracing.istio.io"
$ GRAFANA_URL="http://grafana.istio.io"

# 要安装的 Kiali 的版本,当时我选用的是0.10.0
$ VERSION_LABEL="v0.10.0"

# 安装
$ curl https://raw.githubusercontent.com/kiali/kiali/${VERSION_LABEL}/deploy/kubernetes/kiali-configmap.yaml | \
VERSION_LABEL=${VERSION_LABEL} \
JAEGER_URL=${JAEGER_URL} \
ISTIO_NAMESPACE=istio-system \
GRAFANA_URL=${GRAFANA_URL} envsubst | kubectl create -n istio-system -f -

$ curl https://raw.githubusercontent.com/kiali/kiali/${VERSION_LABEL}/deploy/kubernetes/kiali-secrets.yaml | \
VERSION_LABEL=${VERSION_LABEL} envsubst | kubectl create -n istio-system -f -

$ curl https://raw.githubusercontent.com/kiali/kiali/${VERSION_LABEL}/deploy/kubernetes/kiali.yaml | \
VERSION_LABEL=${VERSION_LABEL} \
IMAGE_NAME=kiali/kiali \
IMAGE_VERSION=${VERSION_LABEL} \
NAMESPACE=istio-system \
VERBOSE_MODE=4 \
IMAGE_PULL_POLICY_TOKEN="imagePullPolicy: Always" envsubst | kubectl create -n istio-system -f -

查看 kiali 的 service 可知,我们可以通过 NodePort 的方式访问 kiali 的 ui

使用 admin/admin 登录 Kiali

统一成用 ingress 访问

1
2
3
4
5
6
7
8
9
10
11
[root@lab01 ~]# kubectl edit ingress kiali -n istio-system -oyaml
……
spec:
rules:
- host: kiali.istio.io
http:
paths:
- backend:
serviceName: kiali
servicePort: 20001
path: /

添加 hosts

1
172.xx.xx.229  kiali.istio.io …………

安装完成,后面我们着重来看他的功能实现,也计划将中文社区中的一些文档搬过来,当然有我的还有其他朋友的,都会一一注明的。