这篇文章发表已超过一年。较旧的文章可能包含过时的内容。请检查页面中的信息自发布以来是否已不再准确。
使用 Istio service mesh 管理微服务
今日的帖子由 Istio 团队撰写,展示了如何在 Kubernetes 中为微服务提供可见性、弹性、安全性和控制。
服务是现代软件架构的核心。部署一系列模块化、小型(微)服务,而不是大型单体应用,使开发人员能够灵活地在系统的不同语言、技术和发布节奏下工作;这会提高生产力和速度,特别是对于大型团队而言。
然而,随着微服务的普及,由于大型系统中服务数量庞大,新的问题也随之出现。对于单体应用只需解决一次的问题,例如安全性、负载均衡、监控和速率限制等,现在需要针对每个服务进行处理。
Kubernetes 和服务
Kubernetes 通过其 Service 构造支持微服务架构。它允许开发人员抽象出一组 Pod 的功能,并通过一个定义良好的 API 将其暴露给其他开发人员。它允许为这种抽象添加名称,并执行基础的 L4 负载均衡。但它无法解决更高级别的问题,例如 L7 指标、流量拆分、速率限制、熔断等。
上周在 GlueCon 2017 上发布的 Istio,通过服务网格框架从根本上解决了这些问题。使用 Istio,开发人员可以专注于实现微服务的核心逻辑,而将其他事情——流量管理、服务发现、服务身份和安全以及策略强制执行——交给框架处理。更棒的是,即使对于现有微服务,也可以在不重写或重新编译任何部分的情况下实现这一点。Istio 使用 Envoy 作为其运行时代理组件,并提供一个可扩展的中间层,用于全局性的横切策略强制执行和遥测数据收集。
当前版本的 Istio 主要面向 Kubernetes 用户,其打包方式使得用户可以通过几行命令安装,并立即获得 Kubernetes 中微服务的可见性、弹性、安全性和控制能力。
在接下来的系列博客文章中,我们将介绍一个由 4 个独立微服务组成的简单应用。首先,我们将演示如何使用纯 Kubernetes 部署该应用。然后,我们将在启用 Istio 的集群中部署完全相同的服务,而无需更改任何应用代码——并观察如何获取指标。
在后续文章中,我们将重点介绍更高级的功能,例如 HTTP 请求路由、策略、身份和安全管理。
示例应用:BookInfo
我们将使用一个名为 BookInfo 的简单应用,它展示了商店中图书的信息、评论和评分。该应用由用不同语言编写的四个微服务组成
由于这些微服务的容器镜像都可以在 Docker Hub 中找到,我们在 Kubernetes 中部署此应用所需的只是 yaml 配置。
值得注意的是,这些服务不依赖于 Kubernetes 和 Istio,但这使其成为一个有趣的案例研究。特别是,评论服务涉及多种服务、语言和版本,使其成为一个有趣的服务网格示例。有关此示例的更多信息,请参阅此处。
在 Kubernetes 中运行 Bookinfo 应用
在本文中,我们将重点介绍应用的 v1 版本
使用 Kubernetes 进行部署非常简单,与部署任何其他服务没有区别。productpage 微服务的 Service 和 Deployment 资源如下所示:
apiVersion: v1
kind: Service
metadata:
name: productpage
labels:
app: productpage
spec:
type: NodePort
ports:
- port: 9080
name: http
selector:
app: productpage
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: productpage-v1
spec:
replicas: 1
template:
metadata:
labels:
app: productpage
track: stable
spec:
containers:
- name: productpage
image: istio/examples-bookinfo-productpage-v1
imagePullPolicy: IfNotPresent
ports:
- containerPort: 9080
如果要运行此应用,我们需要部署的另外两个服务是 details 和 reviews-v1。此时我们不需要部署 ratings 服务,因为 reviews 服务的 v1 版本不使用它。其余服务的基本模式与 productpage 相同。所有服务的 yaml 文件可以在此处找到。
要将服务作为普通 Kubernetes 应用运行
kubectl apply -f bookinfo-v1.yaml
要从集群外部访问应用程序,我们需要 productpage 服务的 NodePort 地址
export BOOKINFO\_URL=$(kubectl get po -l app=productpage -o jsonpath={.items[0].status.hostIP}):$(kubectl get svc productpage -o jsonpath={.spec.ports[0].nodePort})
现在我们可以将浏览器指向 http://$BOOKINFO_URL/productpage,并看到
使用 Istio 运行 Bookinfo 应用
现在我们已经看到了应用,我们将稍微调整部署以使其与 Istio 一起工作。首先,我们需要在集群中安装 Istio。为了看到所有指标和追踪功能的实际效果,我们还安装了可选的 Prometheus、Grafana 和 Zipkin 附加组件。现在我们可以删除之前的应用,然后使用完全相同的 yaml 文件再次启动 Bookinfo 应用,这次是使用 Istio
kubectl delete -f bookinfo-v1.yaml
kubectl apply -f \<(istioctl kube-inject -f bookinfo-v1.yaml)
注意,这次我们在创建部署之前使用 istioctl kube-inject 命令修改 bookinfo-v1.yaml。它将 Envoy Sidecar 注入到 Kubernetes Pod 中,具体说明请参阅此处。因此,所有微服务都打包了一个 Envoy Sidecar,用于管理服务的进出流量。
在 Istio 服务网格中,我们不希望像在纯 Kubernetes 中那样直接访问应用 productpage。相反,我们希望请求路径中包含一个 Envoy Sidecar,以便我们可以使用 Istio 的管理功能(版本路由、熔断器、策略等)来控制对 productpage 的外部调用,就像控制内部请求一样。 Istio 的 Ingress 控制器就是为此目的而使用的。
要使用 Istio Ingress 控制器,我们需要为应用创建一个 Kubernetes Ingress 资源,并使用 kubernetes.io/ingress.class: "istio" 进行标注,如下所示:
cat \<\<EOF ``` kubectl create -f -
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: bookinfo
annotations:
kubernetes.io/ingress.class: "istio"
spec:
rules:
- http:
paths:
- path: /productpage
backend:
serviceName: productpage
servicePort: 9080
- path: /login
backend:
serviceName: productpage
servicePort: 9080
- path: /logout
backend:
serviceName: productpage
servicePort: 9080
EOF
使用 Istio 部署 v1 版本的 bookinfo 应用后,结果如下所示:
这次我们将使用 Istio Ingress 控制器的 NodePort 地址来访问应用
export BOOKINFO\_URL=$(kubectl get po -l istio=ingress -o jsonpath={.items[0].status.hostIP}):$(kubectl get svc istio-ingress -o jsonpath={.spec.ports[0].nodePort})
现在我们可以加载 http://$BOOKINFO_URL/productpage 页面,并再次看到正在运行的应用——对于用户来说,与之前未集成 Istio 的部署应该没有区别。
然而,现在应用正在 Istio 服务网格中运行,我们可以立即看到一些优势。
指标收集
Istio 开箱即用的第一个功能是在 Prometheus 中收集指标。这些指标由 Envoy 中的 Istio 过滤器生成,根据默认规则(可定制)进行收集,然后发送到 Prometheus。这些指标可以在 Grafana 的 Istio 仪表盘中进行可视化。请注意,虽然 Prometheus 是开箱即用的默认指标后端,但 Istio 允许您接入其他后端,我们将在未来的博客文章中进行演示。
为了演示,我们将首先运行以下命令来为应用生成一些负载
wrk -t1 -c1 -d20s http://$BOOKINFO\_URL/productpage
我们获取 Grafana 的 NodePort URL
export GRAFANA\_URL=$(kubectl get po -l app=grafana -o jsonpath={.items[0].status.hostIP}):$(kubectl get svc grafana -o jsonpath={.spec.ports[0].nodePort})
现在我们可以在浏览器中打开 http://$GRAFANA_URL/dashboard/db/istio-dashboard,查看每个 Bookinfo 服务的各种性能指标
分布式追踪 我们从 Istio 获得的下一个功能是使用 Zipkin 进行调用追踪。我们获取其 NodePort URL
export ZIPKIN\_URL=$(kubectl get po -l app=zipkin -o jsonpath={.items[0].status.hostIP}):$(kubectl get svc zipkin -o jsonpath={.spec.ports[0].nodePort})
现在我们可以将浏览器指向 http://$ZIPKIN_URL/,查看通过 Bookinfo 服务的请求追踪跨度。
尽管 Envoy 代理开箱即用地将追踪跨度发送到 Zipkin,但要充分利用其潜力,应用程序需要感知 Zipkin 并转发一些头部信息,以将各个跨度关联起来。详细信息请参阅 zipkin-tracing。
整体视角 Istio 提供的指标不仅仅是一种便利。通过在整个服务网格中生成统一指标,它们提供了一致的视图。我们无需担心协调各种运行时代理发出的不同类型指标,或添加任意代理来收集遗留的未插桩应用的指标。我们也不再需要依赖开发流程来正确地对应用进行插桩以生成指标。服务网格可以看到所有流量,甚至包括进出遗留的“黑盒”服务的流量,并为所有流量生成指标。总结 上面的演示展示了只需几个步骤,我们就可以启动由 Istio 支持的服务并在其上观察 L7 指标。在接下来的几周,我们将继续演示 Istio 的更多功能,例如策略管理和 HTTP 请求路由。Google、IBM 和 Lyft 基于我们为内部和企业客户构建和运营大型复杂微服务部署的共同经验,联合创建了 Istio。Istio 是一项行业范围内的社区努力。我们很高兴看到行业合作伙伴的热情以及他们带来的见解。当我们迈出下一步并将 Istio 发布到更广泛的社区时,我们迫不及待地想看看更广泛的贡献者社区会带来什么。如果您正在使用或考虑在 Kubernetes 上使用微服务架构,我们鼓励您尝试 Istio,在 istio.io 上了解更多信息,告诉我们您的想法,或者更好的是,加入开发者社区,帮助塑造它的未来!
--代表 Istio 团队。Frank Budinsky,IBM 软件工程师;Andra Cismaru,Google 软件工程师;Israel Shalom,Google 产品经理。
- 在 GitHub 上参与 Kubernetes 项目
- 在 Stack Overflow 上提问(或回答问题)
- 在 Slack 上与社区联系
- 在 Twitter 上关注我们 @Kubernetesio 获取最新动态