Istio 服务网格
(一) Istio 介绍
一、Istio 服务简介
Istio 是一个开源的服务网格(Service Mesh)平台,专为微服务架构设计,能够帮助开发者和运维人员更轻松地管理、监控和保护复杂的微服务应用。它通过无侵入方式注入一个代理(sidecar proxy)到每个服务实例中,控制并优化服务间的通信,提供统一的流量管理、可观测性和安全特性。
Istio 主要由 Google、IBM 和 Lyft 联合开发,支持 Kubernetes 等容器化平台。它通过分离服务逻辑与网络控制,简化了分布式系统的管理,让微服务团队能够专注于业务逻辑,而无需考虑底层的网络和通信复杂性。
二、使用 Istio 的原因与优势
流量控制:Istio 提供丰富的流量控制机制,包括负载均衡、服务发现、故障注入、重试和超时设置,帮助开发者更好地管理微服务之间的流量。
增强安全性:Istio 提供了端到端的加密(mTLS)、认证与授权机制,以及基于策略的流量控制,确保微服务间的通信安全,同时减少了手动配置的复杂性。
可观测性:Istio 通过 Envoy 代理实现丰富的监控、追踪和日志功能。它能够为每个微服务提供实时的性能指标,方便开发者快速发现和定位问题,提高故障诊断的效率。
服务弹性:Istio 支持故障注入、熔断器、超时和重试策略,增强了微服务架构的弹性。当某个服务发生故障时,能够自动实现降级或快速恢复,避免单点故障带来的影响。
可扩展性与平台无关性:Istio 能够与 Kubernetes、Virtual Machines(VMs)等不同环境集成,使其具有极高的可扩展性和跨平台支持能力。此外,Istio 提供了丰富的扩展能力,允许开发者根据需求定制流量规则、策略和扩展功能。
三、Istio 的核心功能及架构设计
流量管理:
- Istio 通过控制微服务间的通信流量,实现蓝绿部署、金丝雀发布、A/B 测试等功能。它支持通过路由规则对流量进行细粒度的控制,包括请求重试、超时设置、负载均衡策略和流量镜像。
安全性:
- Istio 支持自动化的身份认证(Authentication)、授权(Authorization)和数据加密。使用 Istio,可以实现零信任网络架构,确保所有服务之间的通信都是安全的。同时,通过 mTLS(Mutual TLS)加密,确保数据在服务之间传输时得到保护。
可观测性:
- Istio 集成了分布式追踪(Tracing)、指标(Metrics)和日志记录(Logging)功能,帮助开发者和运维人员在复杂的微服务系统中实时监控和分析应用的性能表现。
- Envoy 代理会收集所有服务间的流量数据,向 Prometheus、Grafana 等监控系统提供详细的性能指标,并与 Jaeger、Zipkin 等追踪工具集成。
策略执行与配置管理:
- Istio 通过 Mixer 组件对所有流量应用统一的策略,确保不同微服务间遵守相应的访问控制、配额管理等策略。
- 配置管理方面,Istio 使用 Pilot 组件来管理和分发所有代理的流量规则,简化了微服务架构中复杂的配置管理过程。
架构设计:
- Envoy:Istio 的核心组件之一,是一个轻量级、灵活的边车代理,负责处理微服务之间的所有网络流量。Envoy 通过透明拦截应用程序的出入流量,执行 Istio 配置的流量管理策略。
- Pilot:负责为 Envoy 代理提供流量管理规则,并动态调整微服务的流量行为,确保系统在流量模式变化时保持稳定。
- Mixer:负责策略执行和遥测数据收集。它通过与外部系统集成,收集指标、日志,并执行访问控制、配额管理等操作。
- Citadel:提供身份验证、密钥管理和数据加密功能,确保微服务间通信的安全性。
Istio 的架构设计通过模块化、插件化的方式,确保每个组件可以独立运行与扩展,满足不同规模的微服务系统的需求。
(二) Istio 实战
一、Istio 安装与启用
服务器 | IP | K8s 版本 | Istio 版本 |
---|---|---|---|
master | 192.168.92.130 | 1.23.0 | 1.17.0 |
node01 | 192.168.92.131 | 1.23.0 | 1.17.0 |
node02 | 192.168.92.132 | 1.23.0 | 1.17.0 |
在部署好 Kubernetes 和 网络插件 ( Calico 或者是 Flannel ) 之后,进行如下操作
1. 准备工作
检查 K8s 网络插件是否部署成功,节点是否都 Ready 了
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
master Ready control-plane,master 58m v1.23.0
node01 Ready <none> 57m v1.23.0
node02 Ready <none> 57m v1.23.0
$ kubectl get pods -A
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system calico-kube-controllers-64cc74d646-7b97t 1/1 Running 0 2m21s
kube-system calico-node-r864s 1/1 Running 0 2m21s
kube-system calico-node-vkc7p 1/1 Running 0 2m21s
kube-system calico-node-w2sb7 1/1 Running 0 2m21s
kube-system coredns-64897985d-g4l9q 1/1 Running 0 15m
kube-system coredns-64897985d-zvpbc 1/1 Running 0 15m
kube-system etcd-master 1/1 Running 0 15m
kube-system kube-apiserver-master 1/1 Running 0 15m
kube-system kube-controller-manager-master 1/1 Running 0 15m
kube-system kube-proxy-6j9wn 1/1 Running 0 15m
kube-system kube-proxy-f8p85 1/1 Running 0 15m
kube-system kube-proxy-rdxft 1/1 Running 0 15m
kube-system kube-scheduler-master 1/1 Running 0 15m
然后到官方网站↗查找对应你所使用的 K8s 都可以使用哪些版本的 Istio 我的是 v1.23.0
的 Kubernetes 可以使用 1.13~1.17 的 Istio,我这里选择的是 1.17 的 Istio
2. 下载 Istio
根据官方的快速安装指南↗,我们可以按照如下方式快速部署 Istio 熟悉了简单的 Istio 部署之后,您如果对安装其他配置类型或高级部署模型↗感兴趣,请参阅我们应该采用哪种 Istio 安装方法?↗ 的 FAQ 页面来进行更高级的安装
转到 Istio 发布 ↗页面,下载适用于您操作系统的安装文件, 或 自动下载并获取最新版本↗(Linux 或 macOS)
$ curl -L https://istio.io/downloadIstio | sh -
上述命令下载 Istio 的最新版本(以数字表示)。可以在命令行中传递变量来下载特定版本或覆盖处理器架构。 例如,要下载适用于 x86_64 体系结构的 Istio 1.23.2,可以运行以下命令
$ curl -L https://istio.io/downloadIstio | ISTIO_VERSION=1.23.2 TARGET_ARCH=x86_64 sh -
而今天这里我们只需要 1.17.0 版本的 Istio,所以我们可以执行以下命令
$ curl -L https://istio.io/downloadIstio | ISTIO_VERSION=1.17.0 sh -
转到 Istio 软件包目录
$ cd istio-1.17.0
安装目录中包含:
samples/
中的示例应用程序bin/
目录中的istioctl
客户端二进制文件
将
istioctl
客户端添加到您的 Path 中(Linux 或 MacOS)$ export PATH=$PWD/bin:$PATH
安装 Istio
我们使用
demo
配置文件↗。 选择它是为了拥有一组适合测试的默认设置,但还有其他配置文件可用于生产、 性能测试或 OpenShift↗。与 Istio Gateway↗ 不同, 创建 Kubernetes Gateway↗ 时, 默认情况下还会 部署网关代理服务器↗。 由于不会使用它们,因此我们禁用通常作为
demo
配置文件的一部分安装的默认 Istio Gateway 服务的部署。使用
demo
配置文件安装 Istio,无需任何 Gateway$ istioctl install -f samples/bookinfo/demo-profile-no-gateways.yaml -y ✔ Istio core installed ✔ Istiod installed ✔ Installation complete Made this installation the default for injection and validation.
给命名空间添加标签,指示 Istio 在部署应用的时候,自动注入 Envoy Sidecar 代理
$ kubectl label namespace default istio-injection=enabled namespace/default labeled
安装 Kubernetes Gateway API CRD
Kubernetes Gateway API CRD 在大多数 Kubernetes 集群上不会默认安装, 因此请确保在使用 Gateway API 之前已安装它们。
如果 Gateway API CRD 尚不存在,请安装它们
$ kubectl get crd gateways.gateway.networking.k8s.io &> /dev/null || \ { kubectl kustomize "github.com/kubernetes-sigs/gateway-api/config/crd?ref=v1.2.0" | kubectl apply -f -; }
部署 Istio Gateway
$ istioctl install --set profile=demo
- 如果这里有提示,按 Y 即可
二、启用 Istio
在上面的步骤中,我们其实已经启用了 Istio,接下来只需要检验即可
检查 Istio 控制平面和 Gateway
$ kubectl get pods -n istio-system NAME READY STATUS RESTARTS AGE istiod-6bf6c4cb67-mthzh 1/1 Running 0 60m $ kubectl get svc -n istio-system NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE istiod ClusterIP 10.111.202.76 <none> 15010/TCP,15012/TCP,443/TCP,15014/TCP 60m
使用
istioctl
工具验证$ istioctl verify-install 1 Istio control planes detected, checking --revision "default" only ✔ ClusterRole: istiod-istio-system.istio-system checked successfully ✔ ClusterRole: istio-reader-istio-system.istio-system checked successfully ✔ ClusterRoleBinding: istio-reader-istio-system.istio-system checked successfully ✔ ClusterRoleBinding: istiod-istio-system.istio-system checked successfully ✔ ServiceAccount: istio-reader-service-account.istio-system checked successfully ✔ Role: istiod-istio-system.istio-system checked successfully ✔ RoleBinding: istiod-istio-system.istio-system checked successfully ✔ ServiceAccount: istiod-service-account.istio-system checked successfully ✔ CustomResourceDefinition: wasmplugins.extensions.istio.io.istio-system checked successfully ✔ CustomResourceDefinition: destinationrules.networking.istio.io.istio-system checked successfully ✔ CustomResourceDefinition: envoyfilters.networking.istio.io.istio-system checked successfully ✔ CustomResourceDefinition: gateways.networking.istio.io.istio-system checked successfully ✔ CustomResourceDefinition: proxyconfigs.networking.istio.io.istio-system checked successfully ✔ CustomResourceDefinition: serviceentries.networking.istio.io.istio-system checked successfully ✔ CustomResourceDefinition: sidecars.networking.istio.io.istio-system checked successfully ✔ CustomResourceDefinition: virtualservices.networking.istio.io.istio-system checked successfully ✔ CustomResourceDefinition: workloadentries.networking.istio.io.istio-system checked successfully ✔ CustomResourceDefinition: workloadgroups.networking.istio.io.istio-system checked successfully ✔ CustomResourceDefinition: authorizationpolicies.security.istio.io.istio-system checked successfully ✔ CustomResourceDefinition: peerauthentications.security.istio.io.istio-system checked successfully ✔ CustomResourceDefinition: requestauthentications.security.istio.io.istio-system checked successfully ✔ CustomResourceDefinition: telemetries.telemetry.istio.io.istio-system checked successfully ✔ CustomResourceDefinition: istiooperators.install.istio.io.istio-system checked successfully ✔ ClusterRole: istiod-clusterrole-istio-system.istio-system checked successfully ✔ ClusterRole: istiod-gateway-controller-istio-system.istio-system checked successfully ✔ ClusterRoleBinding: istiod-clusterrole-istio-system.istio-system checked successfully ✔ ClusterRoleBinding: istiod-gateway-controller-istio-system.istio-system checked successfully ✔ ConfigMap: istio.istio-system checked successfully ✔ Deployment: istiod.istio-system checked successfully ✔ ConfigMap: istio-sidecar-injector.istio-system checked successfully ✔ MutatingWebhookConfiguration: istio-sidecar-injector.istio-system checked successfully ✔ PodDisruptionBudget: istiod.istio-system checked successfully ✔ ClusterRole: istio-reader-clusterrole-istio-system.istio-system checked successfully ✔ ClusterRoleBinding: istio-reader-clusterrole-istio-system.istio-system checked successfully ✔ Role: istiod.istio-system checked successfully ✔ RoleBinding: istiod.istio-system checked successfully ✔ Service: istiod.istio-system checked successfully ✔ ServiceAccount: istiod.istio-system checked successfully ✔ EnvoyFilter: stats-filter-1.13.istio-system checked successfully ✔ EnvoyFilter: tcp-stats-filter-1.13.istio-system checked successfully ✔ EnvoyFilter: stats-filter-1.14.istio-system checked successfully ✔ EnvoyFilter: tcp-stats-filter-1.14.istio-system checked successfully ✔ EnvoyFilter: stats-filter-1.15.istio-system checked successfully ✔ EnvoyFilter: tcp-stats-filter-1.15.istio-system checked successfully ✔ EnvoyFilter: stats-filter-1.16.istio-system checked successfully ✔ EnvoyFilter: tcp-stats-filter-1.16.istio-system checked successfully ✔ EnvoyFilter: stats-filter-1.17.istio-system checked successfully ✔ EnvoyFilter: tcp-stats-filter-1.17.istio-system checked successfully ✔ ValidatingWebhookConfiguration: istio-validator-istio-system.istio-system checked successfully Checked 15 custom resource definitions Checked 1 Istio Deployments ✔ Istio is installed and verified successfully
三、灰度发布(蓝绿部署)
a. 灰度发布 (Canary Deployment)
灰度发布(Canary Deployment),官方文档叫 “金丝雀部署”
假设我们有一个已部署的 helloworld 服务 v1 版本,我们想要测试(或简单上线)新版本 v2。 使用 Kubernetes,您可以通过简单地更新服务的 Deployment↗ 中的镜像并自动进行部署来 上线↗ 新版本的 helloworld 服务。 如果我们特能够小心保证在启动并且在仅启动一个或两个 v2 副本 暂停↗ 上线时有足够的 v1 副本运行,则能够保持金丝雀发布对系统的影响非常小。 后续我们可以观察效果,或在必要时进行 回滚↗。 最好,我们也能够对 Deployment 设置 HPA↗, 在上线过程中减少或增加副本以处理流量负载时,也能够保持副本比例一致。
b. 蓝绿部署 (Blue-Green Deployment)
蓝绿部署 (Blue-Green Deployment),又称 红/黑发布、蓝/绿发布等等
在蓝绿部署中,两个版本(例如 “蓝色” 的现有版本和 “绿色” 的新版本)同时运行。Istio 通过 VirtualService 的流量规则,可以将所有流量逐步从旧版本切换到新版本,确保在更新过程中不影响用户体验。测试完成并验证新版本稳定后,再完全切换到新版本。
1. 部署 Kiali
Kiali 是一个为 Istio 提供图形化界面和丰富观测功能的 Dashboard 的开源项目,其名称源于希腊语,意思是望远镜。用户利用 Kiali 可以监测网格内服务的实时工作状态,管理Istio的网络配置,快速识别网络问题。但是从Istio 1.7开始,默认不安装控制面板Kiali等组件,所以需要用户自行单独安装控制面板Kiali及相关的组件。
首先,进入到 Istio 的安装解压目录下,然后通过以下命令安装
$ cd istio-1.17.0
$ kubectl apply -f samples/addons
serviceaccount/grafana created
configmap/grafana created
service/grafana created
deployment.apps/grafana created
configmap/istio-grafana-dashboards created
configmap/istio-services-grafana-dashboards created
deployment.apps/jaeger created
service/tracing created
service/zipkin created
service/jaeger-collector created
serviceaccount/kiali created
configmap/kiali created
clusterrole.rbac.authorization.k8s.io/kiali-viewer created
clusterrole.rbac.authorization.k8s.io/kiali created
clusterrolebinding.rbac.authorization.k8s.io/kiali created
role.rbac.authorization.k8s.io/kiali-controlplane created
rolebinding.rbac.authorization.k8s.io/kiali-controlplane created
service/kiali created
deployment.apps/kiali created
serviceaccount/prometheus created
configmap/prometheus created
clusterrole.rbac.authorization.k8s.io/prometheus created
clusterrolebinding.rbac.authorization.k8s.io/prometheus created
service/prometheus created
deployment.apps/prometheus created
安装时,可能由于网络原因会报错,重新试几次就好了。安装完成后,通过 kubecl get
相关命令来查询 pod
的运行状态以观察是否部署完成
$ kubectl get pods -n istio-system
2. 配置 Kiali Dashboard
查看 kiali
服务,发现其类型为 ClusterIP
(集群IP),没有对外暴露端口,无法从外部访问
$ kubectl get service kiali -n istio-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kiali ClusterIP 10.96.48.0 <none> 20001/TCP,9090/TCP 10m
所以此时需要通过 NodePort
的方式对外暴露控制面板
# 我们将原来的 `ClusterIP` 类型的 service 导出 yaml 文件
$ kubectl get svc -n istio-system kiali -o yaml > kiali-nodeport.yaml
# 修改原来的配置
$ vi kiali-nodeport.yaml
# 删除以下内容
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"labels":{"app":"kiali","app.kubernetes.io/instance":"kiali","app.kubernetes.io/managed-by":"Helm","app.kubernetes.io/name":"kiali","app.kubernetes.io/part-of":"kiali","app.kubernetes.io/version":"v1.63.1","helm.sh/chart":"kiali-server-1.63.1","version":"v1.63.1"},"name":"kiali","namespace":"istio-system"},"spec":{"ports":[{"appProtocol":"http","name":"http","port":20001,"protocol":"TCP"},{"appProtocol":"http","name":"http-metrics","port":9090,"protocol":"TCP"}],"selector":{"app.kubernetes.io/instance":"kiali","app.kubernetes.io/name":"kiali"}}}
resourceVersion: "8373"
uid: ef6e2156-3943-4213-985f-9581c573f30d
status:
loadBalancer: {}
# 修改以下内容
spec:
# 原本此处为 ClusterIP
type: NodePort
# 运行文件
$ kubectl apply -f kiali-nodeport.yaml
service/kiali configured
此时再查看 kiali
的 service,可以看到端口已经暴露了出来
$ kubectl get service kiali -n istio-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kiali NodePort 10.96.48.0 <none> 20001:31646/TCP,9090:31599/TCP 13m
然后在浏览器输入 http://<ip_address>:31646/kiali
打开 Kiali 的登陆页面,登陆成功后,Kiali 的总览视图如下所示
3. Weather Forecast 项目
3.1 项目简介
“Weather Forecast” 是一个经常用来展示 Istio 蓝绿部署的示例项目。它通常模拟天气预报应用的场景,演示如何使用 Istio 实现零停机的应用发布。它一共包含四个微服务
在 Istio 示例项目中,“Weather Forecast” 是一个经典的微服务应用示例,通常用于演示 Istio 的流量管理、负载均衡和蓝绿部署等功能。该项目包含多个服务组件(如 frontend
、forecast
、recommendation
等),并利用 Istio 的 Service Mesh 技术实现服务的可观察性、故障注入和流量分离等功能。这类微服务示例项目可以帮助开发者通过实验性部署来熟悉 Istio 的功能。
frontend
:前台服务,会调用 advertisement 和 forecast 这两个服务,展示整个应用的页面advertisement
:广告服务,返回的静态的广告图片forecast
:添加预报服务,返回相应城市的天气数据recommendation
:推荐服务,根据天气情况向用户推荐穿衣和运行等信息 其中,frontend 服务的有两个版本- forecast 服务有两个版本:
- v1 版本
- 界面按钮为绿色
- 直接返回天气信息
- v2 版本
- 界面按钮为蓝色
- 请求
recommendation
服务,获取推荐信息,并结合天气信息一起返回数据
- v1 版本
关于具体的源代码和部署方法,Weather Forecast项目的代码主要集中在镜像内,而部署配置文件则位于项目的 manifests
目录中。开发者可以根据该目录中的配置文件,结合 Istio 的官方文档来学习如何通过网关、虚拟服务等配置来管理流量
3.2 Weather Forecast 部署
下载项目源码(由于官方版的 Kubernetes API 版本未及时更新,可能会导致报错,所以我们这里使用下面的 Github 项目进行部署)
$ git clone https://github.com/AnitsuriW/cloud-native-istio.git
添加 v1 版本的服务
$ kubectl create ns weather
ns
是 namespace 的缩写
$ kubectl label namespace weather istio-injection=enabled
istio-injection=enabled
是
$ kubectl apply -f install/weather-v1.yaml -n weather
等待服务安装成功
$ kubectl get svc,pod -n weather NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/advertisement ClusterIP 10.103.198.173 <none> 3003/TCP 9m39s service/forecast ClusterIP 10.109.184.76 <none> 3002/TCP 9m39s service/frontend ClusterIP 10.104.185.8 <none> 3000/TCP 9m39s NAME READY STATUS RESTARTS AGE pod/advertisement-v1-676465d7ff-wjdlj 2/2 Running 0 9m39s pod/forecast-v1-7c7f755996-wvmzr 2/2 Running 0 9m39s pod/frontend-v1-6ffb44559f-4tdpl 2/2 Running 0 9m39s
添加网关资源 Gateway
$ kubectl apply -f install/weather-gateway.yaml
验证访问页面,添加完网关资源 Gateway 后访问
istio-ingressgateway
地址即可$ kubectl get svc -n istio-system istio-ingressgateway NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE istio-ingressgateway LoadBalancer 10.110.169.234 <pending> 15021:31159/TCP,80:30421/TCP,443:31706/TCP,31400:30101/TCP,15443:31964/TCP 25m
- 这里对应 80 端口的是 30421,所以我们访问
http://<ip_address>:30421
即可,然后点击【查询天气】进行查询
- 这里对应 80 端口的是 30421,所以我们访问
4. 配置 蓝绿部署 过程 (以 Weather Forecast 为基础)
在这个实验中,有两个核心配置文件贯穿全文
VirtualService
: 路由规则配置(虚拟服务),定义路由规则,可以将满足条件的流量都转发到对应的服务后端DestinationRule
: 目标规则配置,定义发生路由后应用于服务流量的策略,描述到达目标的请求怎么处理 目标规则是配合虚拟服务来使用的,主要用来定义子集,子集实际上就是具体的目标地址,除此以外,它主要描述的是到达目标请求后如何去处理,所谓的目标就是子集,而如何处理就是指具体的策略
4.1 初始状态部署
在开始试验之前,首先对每个服务都创建各自的 VirtualService
和 DestinationRule
资源,将访问请求路由到所有服务的 v1 版本
$ kubectl apply -f install/destination-rule-v1.yaml -n weather
$ kubectl apply -f install/virtual-service-v1.yaml -n weather
查看配置的路由规则,以 forecast
服务为例
$ kubectl get vs -n weather forecast-route -o yaml
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"networking.istio.io/v1alpha3","kind":"VirtualService","metadata":{"annotations":{},"name":"forecast-route","namespace":"weather"},"spec":{"hosts":["forecast"],"http":[{"route":[{"destination":{"host":"forecast","subset":"v1"}}]}]}}
creationTimestamp: "2024-11-04T06:09:12Z"
generation: 1
name: forecast-route
namespace: weather
resourceVersion: "16932"
uid: ad1e9e43-655f-4203-b7ff-e314c6255779
spec:
hosts:
- forecast
http:
- route:
- destination:
host: forecast
subset: v1
在浏览器中多次加载前台页面,并查询城市的天气信息,确认显示正常。然后打开 Kiali 控制台,查看各个服务之间的调用关系
4.2 基础流量比例的路由
场景: 用户需要软件能够根据不同的天气情况推荐合适的穿衣和运动信息,于是开发的同学增加了
recommendation
新服务,并升级forecast
服务到 v2 版本来调用recommendation
服务 在新特征上线时,运维的同学首先部署forecast
服务的 v2 版本和recommendation
服务,并对forecast
服务的 v2 版本进行灰度发布
部署
recommendation
服务 和forecast
服务的 v2 版本$ kubectl apply -f install/recommendation-service/recommendation-all.yaml -f install/forecast-service/forecast-v2-deployment.yaml -n weather
更新
forecast
服务 v2 版本的DestinationRule
$ kubectl apply -f install/forecast-service/forecast-v2-destination.yaml -n weather
查看下发成功的配置,可以看到增加了 v2 版本
subnet
的定义$ kubectl get dr forecast-dr -o yaml -n weather apiVersion: networking.istio.io/v1beta1 kind: DestinationRule metadata: annotations: kubectl.kubernetes.io/last-applied-configuration: | {"apiVersion":"networking.istio.io/v1alpha3","kind":"DestinationRule","metadata":{"annotations":{},"name":"forecast-dr","namespace":"weather"},"spec":{"host":"forecast","subsets":[{"labels":{"version":"v1"},"name":"v1"},{"labels":{"version":"v2"},"name":"v2"}]}} creationTimestamp: "2024-11-04T06:07:45Z" generation: 2 name: forecast-dr namespace: weather resourceVersion: "23255" uid: 5b391c83-92a8-46d3-9f38-40ba63ca3b5b spec: host: forecast subsets: - labels: version: v1 name: v1 - labels: version: v2 name: v2
这时去浏览器查询天气,显然还不会出现推荐信息,因为所有流量依然都被路由到
forecast
服务的 v1 版本,不会调用recommendation
服务配置
forecast
服务的VirtualService
配置,其中的weight
字段显示了相应服务的流量占比,可以看到此时为 v1:v2 = 1:1$ kubectl apply -f chapter-files/canary-release/vs-forecast-weight-based-50.yaml -n weather
在浏览器中查看配置后的效果
多次刷新查询天气页面,可以发现大概约 50% 的情况下不显示推荐服务,表示调用了
forecast
服务的 v1 版本;在另外 50% 的情况下表示推荐服务,调用了forecast
服务的 v2 版本(刷新页面基本上是两个版本交替着来)继续增加
forecast
服务的 v2 版本的流量比例,直到流量全部被路由到 v2 版本$ kubectl apply -f chapter-files/canary-release/vs-forecast-weight-based-v2.yaml -n weather
在浏览器查看配置后的效果,多次刷新页面查询天气,每次都会出现推荐信息,说明访问请求都被路由到了
forecast
服务 v2 版本保留
forecast
服务的老版本 v1 一段时间,再确认 v2 版本的各性能指标稳定后,删除老版本 v1 的所有资源,完成灰度发布
4.3 基础请求内容的发布
在生产环境中同时上线了
forecast
服务的 v1 和 v2 版本,运维同学希望让不同终端用户访问不同的版本 eg. Chrome 的用户能看到推荐信息,但让使用其他浏览器的用户看不到推荐信息
只需要修改 forecast
服务 v2 版本的 DestinationRule 中的 match 条件,使来自 Chrome 浏览器的请求路由刀 v2 版本上,其余的不变即可
$ cat chapter-files/canary-release/vs-forecast-header-based.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: forecast-route
namespace: weather
spec:
hosts:
- forecast
http:
- match:
- headers:
User-Agent:
regex: .*(Chrome/([\d.]+)).*
route:
- destination:
host: forecast
subset: v2
- route:
- destination:
host: forecast
在浏览器查看配置后的结果:
使用 Chrome 浏览器多次查看。发现始终显示推荐信息,说明访问到
forecast
服务的 v2 版本其他浏览器查看。发现不显示推荐信息,说明访问到
forecast
服务的 v1 版本
四、流量镜像 (Traffic Mirroing)
1. 流量镜像 (Traffic Mirroing) 介绍
流量镜像 (Traffic Mirroring) 是一种网络技术,通常用于监控、分析和调试网络流量。其核心概念是在不中断正常流量的情况下,将真实的网络流量(来自用户、设备、服务器等)复制或镜像到另一个目标位置,供分析、调试或其他用途。
1.1 流量镜像的主要特点:
复制流量: 流量镜像会将原始流量(可能是进出某个应用程序、服务器、网络设备等的流量)复制到一个镜像端口或服务,不会影响正常的流量传输。
透明性: 流量镜像通常对网络中的其他设备和用户是透明的,即流量镜像的过程不会影响原始流量的传输速度或质量。
流量分析: 复制的流量可以用于各种分析任务,比如性能监控、安全检测、故障排查、行为分析等。通过这种方式,可以不干扰现有服务的运行,而对流量进行深入研究。
1.2 流量镜像的常见应用场景:
性能监控与优化: 通过镜像流量,管理员可以查看网络的实际流量,帮助分析瓶颈或性能问题。
安全检测: 流量镜像可以帮助安全团队检测潜在的网络攻击、恶意流量或异常行为。通过分析流量,及时发现并阻止攻击。
故障排查: 当网络或应用出现问题时,可以使用流量镜像功能进行详细的流量分析,帮助确定问题所在,例如:丢包、延迟或应用错误。
流量分析与报告: 利用镜像流量,管理员可以生成网络流量报告,进行流量模式分析,帮助企业优化网络架构或调整带宽分配。
合规性与审计: 某些行业或组织需要进行流量审计,以确保遵守合规性标准。流量镜像允许企业以非干扰方式记录和分析流量。
3. 流量镜像的实现方式:
硬件镜像: 在交换机或路由器等网络设备中进行流量镜像。通过配置设备的镜像端口,所有通过该设备的流量都可以被复制到其他端口。
虚拟化环境中的流量镜像: 在虚拟化环境中(如Kubernetes、VMware等),流量镜像通常通过软件配置完成。可以使用虚拟交换机或软件工具来实现镜像。
云环境中的流量镜像: 云服务提供商(如AWS、Azure等)通常也提供流量镜像的功能。例如,AWS 提供了 Traffic Mirroring 服务,让用户能够复制EC2实例的流量,用于分析。
1.4 流量镜像与流量复制的区别:
- 流量镜像:通常只对流量进行复制和分析,复制的流量不会对原始流量造成干扰。
- 流量复制:指的是复制流量并将其传输到其他目的地进行处理或分析,通常不会保留源设备上的流量。
1.5 流量镜像的优缺点:
优点:
- 非侵入性:流量镜像不会影响原始流量,适合在生产环境中使用。
- 多样的用途:可以用于性能监控、安全分析、故障诊断等多个场景。
- 便于实施:在大多数网络设备和云平台中都可以方便地配置流量镜像。
缺点:
- 增加负载:复制流量会带来额外的网络负载,特别是在高流量环境下,需要确保镜像目的地能够承载这些额外流量。
- 可能的数据泄露风险:镜像的流量如果没有安全措施,可能导致敏感信息泄露。
2. 部署 httpbin 应用
- v1 版本 deployment
v1 和 v2 一样拥有标签 app: httpbin
,同时拥有不同的 version: v1
标签
mirrors-httpbin-v1.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: httpbin-v1
spec:
replicas: 1
selector:
matchLabels:
app: httpbin
version: v1
template:
metadata:
labels:
app: httpbin
version: v1
spec:
containers:
- image: docker.io/kennethreitz/httpbin
imagePullPolicy: IfNotPresent
name: httpbin
command: ["gunicorn", "--access-logfile", "-", "-b", "0.0.0.0:80", "httpbin:app"]
ports:
- containerPort: 80
- v2 版本 deployment
v2 和 v1 一样拥有标签 app: httpbin
,同时拥有不同的 version: v2
标签
mirrors-httpbin-v2.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: httpbin-v2
spec:
replicas: 1
selector:
matchLabels:
app: httpbin
version: v2
template:
metadata:
labels:
app: httpbin
version: v2
spec:
containers:
- image: docker.io/kennethreitz/httpbin
imagePullPolicy: IfNotPresent
name: httpbin
command: ["gunicorn", "--access-logfile", "-", "-b", "0.0.0.0:80", "httpbin:app"]
ports:
- containerPort: 80
- Service
service 通过标签 app: httpbin
关联 httpbin-v1
和 httpbin-v2
mirrors-httpbin-service.yaml
apiVersion: v1
kind: Service
metadata:
name: httpbin
labels:
app: httpbin
spec:
ports:
- name: http
port: 8000
targetPort: 80
selector:
app: httpbin
- 测试容器 sleep
sleep 用于测试
mirrors-sleep.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: sleep
spec:
replicas: 1
selector:
matchLabels:
app: sleep
template:
metadata:
labels:
app: sleep
spec:
containers:
- name: sleep
image: curlimages/curl
command: ["/bin/sleep","3650d"]
imagePullPolicy: IfNotPresent
部署以上的 deployment 和 svc
$ kubectl apply -f Traffic-Mirroring/mirrors-httpbin-v1.yaml
$ kubectl apply -f Traffic-Mirroring/mirrors-httpbin-v2.yaml
$ kubectl apply -f Traffic-Mirroring/mirrors-httpbin-service.yaml
$ kubectl apply -f Traffic-Mirroring/mirrors-sleep.yaml
3. 配置路由
3.1 所有流量到 v1
3.1.1 部署 dr 和 vs
Traffic-Mirroring/mirrors-httpbin-vs-dr.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: httpbin
spec:
hosts:
- httpbin
http:
- route:
- destination:
host: httpbin
subset: v1
weight: 100
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: httpbin
spec:
host: httpbin
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
部署 dr 和 vs
$ kubectl apply -f Traffic-Mirroring/mirrors-httpbin-vs-dr.yaml
3.1.2 测试访问
通过 sleep 容器向 httpbin 发起访问
$ kubectl exec deployments/sleep -- curl -sS http://httpbin:8000/headers
由于所有流量都发给 v1,所以 v1 有一条访问记录,而 v2 没有
$ kubectl logs deployments/httpbin-v1
$ kubectl logs deployments/httpbin-v2
3.2 将 v1 的流量全部镜像给 v2
3.2.1 将 v1 所有的流量镜像给 v2 版本
Traffic-Mirroring/mirrors-httpbin-v1-2-v2.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: httpbin
spec:
hosts:
- httpbin
http:
- route:
- destination:
host: httpbin
subset: v1
weight: 100
mirror:
host: httpbin
subset: v2
mirrorPercentage:
value: 100.0
部署 vs
$ kubectl apply -f Traffic-Mirroring/mirrors-httpbin-v1-2-v2.yaml
3.2.2 测试访问
通过 sleep 容器向 httpbin 发起访问
$ kubectl exec deployments/sleep -- curl -sS http://httpbin:8000/headers
由于所有流量都被发给v1并且镜像给了v2,所以v1有一条访问记录,v2在同一时间也有一条相同的访问记录
$ kubectl logs deployments/httpbin-v1
$ kubectl logs deployments/httpbin-v2
至此,Istio 的流量镜像 Traffic Mirroring 实验完成
五、分布式追踪
1. 概要
1.1 分布式追踪概述
分布式链路追踪可以让用户对跨多个分布式服务网格的 1 个请求进行追踪分析。 进而可以通过可视化的方式更加深入地了解请求的延迟、序列化和并行度。
Istio 利用 Envoy 的分布式追踪↗ 功能提供了开箱即用的链路追踪集成。 确切地说,Istio 提供了安装各种链路追踪后端服务的选项,并且通过配置代理来自动发送链路追踪 span 到分布式追踪系统服务。
1.2 追踪上下文传递
尽管 Istio 代理能够自动发送 span,但需要一些附加信息才能将这些 span 加到同一个调用链。 所以当代理发送 span 信息的时候,应用程序需要附加适当的 HTTP 请求头信息,这样才能够把多个 span 加到同一个调用链。
要做到这一点,每个应用程序必须从每个传入的请求中收集请求头,并将这些请求头转发到传入请求所触发的所有传出请求中。 具体选择转发哪些请求头取决于所配置的链路追踪后端,要转发的请求头在每个链路追踪系统特定的任务页面进行说明, 以下是一个汇总:
所有应用程序必须转发以下请求头:
x-request-id
:这是 Envoy 专用的请求头,用于对日志和追踪进行一致的采样。
对于 Zipkin、Jaeger 和 Stackdriver,应转发 B3 多请求头格式:
x-b3-traceid
x-b3-spanid
x-b3-parentspanid
x-b3-sampled
x-b3-flags
这些是 Zipkin、Jaeger 和其它更多工具支持的请求头。
对于 Datadog,应转发以下请求头,这些转发由对应语言和框架的 Datadog 客户端库自动处理。
x-datadog-trace-id
x-datadog-parent-id
x-datadog-sampling-priority
对于 Lightstep,应转发 OpenTracing span 上下文请求头:
x-ot-span-context
对于 Stackdriver,您可以使用以下任一请求头来替代 B3 多请求头格式:
grpc-trace-bin
:标准的 grpc 追踪头。traceparent
:追踪所用的 W3C 追踪上下文标准,受 OpenTelemetry 和日益增加的 Jaeger 客户端库所支持。x-cloud-trace-context
:被 Google Cloud 产品 API 所使用。
例如,如果您看基于 Python 语言的 productpage
服务这个例子,可以看到这个应用程序使用了 OpenTracing↗ 库从 HTTP 请求中提取所需的请求头信息:
def getForwardHeaders(request):
headers = {}
# 可以使用 opentracing span 填充 x-b3-*** 请求头
span = get_current_span()
carrier = {}
tracer.inject(
span_context=span.context,
format=Format.HTTP_HEADERS,
carrier=carrier)
headers.update(carrier)
# ...
incoming_headers = ['x-request-id',
'x-ot-span-context',
'x-datadog-trace-id',
'x-datadog-parent-id',
'x-datadog-sampling-priority',
'traceparent',
'tracestate',
'x-cloud-trace-context',
'grpc-trace-bin',
'user-agent',
'cookie',
'authorization',
'jwt',
]
# ...
for ihdr in incoming_headers:
val = request.headers.get(ihdr)
if val is not None:
headers[ihdr] = val
return headers
在 review 这个应用中(Java)使用 requestHeaders
做了类似的事情:
@GET
@Path("/reviews/{productId}")
public Response bookReviewsById(@PathParam("productId") int productId, @Context HttpHeaders requestHeaders) {
// ...
if (ratings_enabled) {
JsonObject ratingsResponse = getRatings(Integer.toString(productId), requestHeaders);
当您在应用程序中进行下游调用时,请确保包含这些请求头。
2. 使用 Telemetry API 配置链路追踪
Istio 提供了配置高级链路追踪选项的功能,例如采样率和向已采集的 span 中添加自定义标签。
Telemetry API 不适用于 Istio 1.17.0 及以上版本
他被移至 Zipkin API 组
2.1 安装
在此示例中,我们将发送跟踪信息到 链路追踪系统 zipkin
↗, 请确保已安装它:
$ cat <<EOF > ./tracing.yaml
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
meshConfig:
enableTracing: true
defaultConfig:
tracing: {} # 禁用 MeshConfig 链路追踪选项
extensionProviders:
# 添加 zipkin 提供商
- name: zipkin
zipkin:
service: zipkin.istio-system.svc.cluster.local
port: 9411
EOF
$ istioctl install -f ./tracing.yaml --skip-confirmation
2.2 启用服务网格的链路追踪
通过以下配置启用链路追踪:
$ kubectl apply -f - <<EOF
apiVersion: telemetry.istio.io/v1
kind: Telemetry
metadata:
name: mesh-default
namespace: istio-system
spec:
tracing:
- providers:
- name: "zipkin"
EOF
2.3 自定义链路追踪采样率
采样率选项可用于控制向链路追踪系统报告的请求百分比, 应根据服务网格中的流量和您想要收集的链路追踪数据量来配置此选项, 默认采样率为 1%。
$ kubectl apply -f - <<EOF
apiVersion: telemetry.istio.io/v1
kind: Telemetry
metadata:
name: mesh-default
namespace: istio-system
spec:
tracing:
- providers:
- name: "zipkin"
randomSamplingPercentage: 100.00
EOF
2.4 自定义链路追踪标签
可以基于文本、环境变量和客户端请求标头向 span 中添加自定义标签,以在与环境相关的 span 中提供额外的信息。
:warning:添加自定义标签的数量没有限制,但标签名称必须唯一。
可以使用以下三种方式来添加自定义标签
literal 选项可以将一个静态的值添加到每个 span 中
apiVersion: telemetry.istio.io/v1 kind: Telemetry metadata: name: mesh-default namespace: istio-system spec: tracing: - providers: - name: "zipkin" randomSamplingPercentage: 100.00 customTags: "provider": literal: value: "zipkin"
环境变量可以用于从工作负载代理环境中自定义标签
apiVersion: telemetry.istio.io/v1 kind: Telemetry metadata: name: mesh-default namespace: istio-system spec: tracing: - providers: - name: "zipkin" randomSamplingPercentage: 100.00 customTags: "cluster_id": environment: name: ISTIO_META_CLUSTER_ID defaultValue: Kubernetes # 可选
为了基于环境变量添加自定义标签,您必须修改根 Istio 系统命名空间中的
istio-sidecar-injector
的 ConfigMap客户端请求头选项可用于从传入的客户端请求头中添加标签
apiVersion: telemetry.istio.io/v1 kind: Telemetry metadata: name: mesh-default namespace: istio-system spec: tracing: - providers: - name: "zipkin" randomSamplingPercentage: 100.00 customTags: my_tag_header: header: name: <CLIENT-HEADER> defaultValue: <VALUE> # 可选
2.5 自定义链路追踪标签长度
默认情况下,HttpUrl
的 span 标签的请求最大长度为 256。要修改此最大长度, 请将以下内容添加到您的 tracing.yaml
配置文件中
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
meshConfig:
enableTracing: true
defaultConfig:
tracing: {} # 通过 MeshConfig 禁用链路追踪选项
extensionProviders:
# 添加 zipkin 提供商
- name: zipkin
zipkin:
service: zipkin.istio-system.svc.cluster.local
port: 9411
maxTagLength: <VALUE>
3. Zipkin
服务器 | IP | K8s 版本 | Istio 版本 |
---|---|---|---|
master | 192.168.72.130 | v1.28.15 | 1.24.0 |
node01 | 192.168.72.131 | v1.28.15 | 1.24.0 |
node02 | 192.168.72.132 | v1.28.15 | 1.24.0 |
3.1 安装
方法一:快速开始
$ kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.24/samples/addons/extras/zipkin.yaml
通过 kubectl apply -f
将 Zipkin 部署到集群中。此示例仅用于演示, 没有针对其性能或安全性进行调优。
方法二: 定制化安装
参阅 Zipkin 文档 ↗开始安装。Zipkin 集成 Istio 使用时无需进行特殊修改。
Zipkin 安装完成后,您需要指定 Istio 代理用来向 Deployment 发送追踪数据。 可以在安装时通过指定参数 --set values.global.tracer.zipkin.address=<zipkin-collector-address>:9411
进行配置。更高级配置例如:TLS 配置可以参考 ProxyConfig.Tracing↗ 链接。
3.2 部署 Bookinfo 示例应用程序
进入 Istio 安装目录
Istio 默认自动注入 Sidecar↗。 为
default
命名空间打上标签istio-injection=enabled
:$ kubectl label namespace default istio-injection=enabled
如果上面的不行,就输入下面的这个
$ kubectl label namespace istio-system istio-injection=enabled
使用
kubectl
命令来部署应用:$ kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml service/details created serviceaccount/bookinfo-details created deployment.apps/details-v1 created service/ratings created serviceaccount/bookinfo-ratings created deployment.apps/ratings-v1 created service/reviews created serviceaccount/bookinfo-reviews created deployment.apps/reviews-v1 created deployment.apps/reviews-v2 created deployment.apps/reviews-v3 created service/productpage created serviceaccount/bookinfo-productpage created deployment.apps/productpage-v1 created
上面这条命令会启动 bookinfo
应用架构图中显示的全部四个服务。 也会启动三个版本的 reviews 服务:v1、v2 以及 v3。
在实际部署中,会先部署新版本的微服务,而不是同时部署所有版本
确认所有的服务和 Pod 都已被正确地定义和启动
$ kubectl get services,pods NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/details ClusterIP 10.100.237.29 <none> 9080/TCP 99m service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 19h service/productpage ClusterIP 10.98.164.48 <none> 9080/TCP 99m service/ratings ClusterIP 10.104.239.23 <none> 9080/TCP 99m service/reviews ClusterIP 10.98.175.53 <none> 9080/TCP 99m NAME READY STATUS RESTARTS AGE pod/details-v1-649d7678b5-q9z95 2/2 Running 0 99m pod/productpage-v1-5c5fb9b4b4-qwfq5 2/2 Running 0 99m pod/ratings-v1-794db9df8f-fmdmv 2/2 Running 0 99m pod/reviews-v1-7f9f5df695-2bfbp 2/2 Running 0 99m pod/reviews-v2-65c9797659-fvgpc 2/2 Running 0 99m pod/reviews-v3-84b8cc6647-jggpm 2/2 Running 0 99m
要确认 Bookinfo 应用正在运行,请从某个 Pod 中(例如从
ratings
中)用curl
命令对此应用发送一条请求:$ kubectl exec "$(kubectl get pod -l app=ratings -o jsonpath='{.items[0].metadata.name}')" -c ratings -- curl -sS productpage:9080/productpage | grep -o "<title>.*</title>" <title>Simple Bookstore App</title>
3.3 确定 Ingress IP 和端口
既然 Bookinfo 服务已启动并运行,您就需要使此应用可以从 Kubernetes 集群外部进行访问, 例如从浏览器进行访问
为 Bookinfo 应用定义一个网关:
# 使用以下命令创建 Istio 网关 $ kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yaml gateway.networking.istio.io/bookinfo-gateway created virtualservice.networking.istio.io/bookinfo created # 确认网关创建完成 $ kubectl get gateway NAME AGE bookinfo-gateway 23s
遵循 这些指示说明↗ 设置
INGRESS_HOST
和INGRESS_PORT
变量来访问网关:将以下环境变量设置到您集群中 Istio Ingress Gateway 所用的名称及其所在的命名空间:
$ export INGRESS_NAME=istio-ingressgateway $ export INGRESS_NS=istio-system
如果使用 Helm 安装 Istio,则 Ingress Gateway 名称和命名空间都是
istio-ingress
:$ export INGRESS_NAME=istio-ingress $ export INGRESS_NS=istio-ingress
执行如下指令,确定您的 Kubernetes 集群是否运行在支持外部负载均衡器的环境中:
$ kubectl get svc "$INGRESS_NAME" -n "$INGRESS_NS" NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE istio-ingressgateway LoadBalancer 10.96.106.180 <pending> 15021:31413/TCP,80:32570/TCP,443:32444/TCP,31400:31256/TCP,15443:31988/TCP 19h
如果
EXTERNAL-IP
值已设置,说明环境正在使用外部负载均衡器,可以用其为 Ingress Gateway 提供服务。 如果EXTERNAL-IP
值为<none>
(或持续显示<pending>
),说明环境没有为 Ingress Gateway 提供外部负载均衡器,无法使用 Ingress Gateway。如果您的环境不支持外部负载均衡器,您可以尝试使用 Node Port 访问 Ingress Gateway↗。 否则,使用以下命令设置 Ingress IP 和端口
$ export INGRESS_HOST=$(kubectl -n "$INGRESS_NS" get service "$INGRESS_NAME" -o jsonpath='{.status.loadBalancer.ingress[0].ip}') $ export INGRESS_PORT=$(kubectl -n "$INGRESS_NS" get service "$INGRESS_NAME" -o jsonpath='{.spec.ports[?(@.name=="http2")].port}') $ export SECURE_INGRESS_PORT=$(kubectl -n "$INGRESS_NS" get service "$INGRESS_NAME" -o jsonpath='{.spec.ports[?(@.name=="https")].port}') $ export TCP_INGRESS_PORT=$(kubectl -n "$INGRESS_NS" get service "$INGRESS_NAME" -o jsonpath='{.spec.ports[?(@.name=="tcp")].port}')
在特定的环境下,可能会使用主机名来暴露负载均衡器,而不是 IP 地址。 此时,Ingress Gateway 的
EXTERNAL-IP
值将不再是 IP 地址,而是主机名。 前文设置INGRESS_HOST
环境变量的命令将执行失败。使用下面的命令更正INGRESS_HOST
值:$ export INGRESS_HOST=$(kubectl -n "$INGRESS_NS" get service "$INGRESS_NAME" -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')
设置
GATEWAY_URL
$ export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT
3.4 确认可以从集群外部访问应用
要确认是否能够从集群外部访问 Bookinfo 应用,可以运行以下 curl
命令
$ curl -s "http://${GATEWAY_URL}/productpage" | grep -o "<title>.*</title>"
<title>Simple Bookstore App</title>
还可以用浏览器打开网址 http://$GATEWAY_URL/productpage
,来浏览应用的 Web 页面。 如果刷新几次应用的页面,就会看到 productpage
页面会以轮询的方式展示不同版本的 reviews
服务 (红色星形、黑色星形或者没有星形)。reviews
服务出现这种情况是因为还没有使用 Istio 来控制版本的路由
3.5 定义服务版本
在可以使用 Istio 控制 Bookinfo 版本路由之前,您需要定义可用的版本
# Istio 在目标规则中使用 subsets(子集) 定义服务的版本。运行以下命令为 Bookinfo 服务创建默认的目标规则
$ kubectl apply -f samples/bookinfo/networking/destination-rule-all.yaml
destinationrule.networking.istio.io/productpage created
destinationrule.networking.istio.io/reviews created
destinationrule.networking.istio.io/ratings created
destinationrule.networking.istio.io/details created
default
和demo
的 配置文件 ↗默认启用了 自动双向 TLS↗ 。 要强制执行双向 TLS,请使用samples/bookinfo/networking/destination-rule-all-mtls.yaml
中的目标规则。
等待几秒钟,以使目标规则生效。
$ kubectl get destinationrules -o yaml
3.6 访问仪表盘
远程访问遥测插件↗ 详细介绍了如何通过网关配置对 Istio 插件的访问
对于测试(或临时访问),您也可以使用端口转发。假设已将 Zipkin 部署到 istio-system
命名空间,请使用以下内容
$ istioctl dashboard zipkin
3.7 使用 Bookinfo 示例产生追踪
当 Bookinfo 应用程序启动并运行时,访问
http://$GATEWAY_URL/productpage
一次或多次以生成追踪信息$ kubectl get svc istio-ingressgateway -n istio-system NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE istio-ingressgateway NodePort 10.96.106.180 <none> 15021:31413/TCP,80:32570/TCP,443:32444/TCP,31400:31256/TCP,15443:31988/TCP 19h
像这里,我就应该访问
http://192.168.72.130:32570/productpage
要查看追踪数据,必须向服务发送请求。请求的数量取决于 Istio 的采样率。 采样率在安装 Istio 时设置,默认采样速率为 1%。在第一个跟踪可见之前,您需要发送至少 100 个请求。 使用以下命令向
productpage
服务发送 100 个请求$ for i in $(seq 1 100); do curl -s -o /dev/null "http://$GATEWAY_URL/productpage"; done
在搜索面板中,点击
+
号,从第一个下拉列表中选择serviceName
, 从第二个下拉列表中选择productpage.default
,再点击搜索图标点击
ISTIO-INGRESSGATEWAY
的搜索结果,查看与之对应的最新的/productpage
请求的详细信息追踪由一组 Span 组成,其中每个 Span 对应一个 Bookinfo Service,这些服务在执行
/productpage
请求或 Istio 内部组件时被调用,例如:istio-ingressgateway
3.8 清理
使用 Control-C 或删除任何可能仍在运行的
istioctl
进程$ killall istioctl
如果不打算继续深入探索任何后续任务的话,请参考 Bookinfo 清理↗ 说明,关闭应用程序