原文html
在学习像 Istio 这样的新技术时,看一下示例应用程序老是一个好主意。 Istio repo 有一些示例应用程序,但它们彷佛有各类不足。 文档中的 BookInfo 是一个很好的示例。 可是,对于我而言,它太冗长,服务太多,并且文档彷佛专一于管理 BookInfo 应用程序,而不是从头开始构建。 有一个较小的 hellohttp 例子,但它更多的是关于自动伸缩而不是其余。shell
在这篇文章中,我想介绍一下基础知识,并向您展现如何从头开始构建支持 Istio 的“hellohttp”应用程序。 要记住的一点是,Istio 只管理您应用的流量。 在这种状况下,应用程序生命周期由底层平台 Kubernetes 管理。 所以,您须要了解容器和 Kubernetes 基础知识,而且须要了解 Istio Routing 原语,例如 Gateway,VirtualService,DestinationRule。 我假设大多数人都知道容器和 Kubernetes 基础知识。 我将在本文中专一于 Istio Routing。api
如下这些大体就是您须要遵循的,以得到 Istio 的“hellohttp”应用程序的步骤:浏览器
我不会在本文中介绍步骤 1 和 2,由于它们不是特定于 Istio 的。 若是您须要有关这些步骤的帮助,能够查看我在本文末尾提到的文章。 第 3 步也不是 Istio 特定的,但它是其余一切的先决条件,因此让咱们从那开始。app
正如我所提到的,应用程序生命周期由 Kubernetes 管理。 所以,您须要从建立 Kubernetes deployment 和 service 开始。 个人状况以下,我有一个容器化的 ASP.NET 核心应用程序,其镜像我已经推送到谷歌镜像仓库。 让咱们从建立一个hellohttp-deploy.yaml.yaml
文件开始:负载均衡
apiVersion: v1 kind: Service metadata: name: hellohttp-service labels: app: hellohttp spec: ports: - port: 80 name: http selector: app: hellohttp --- apiVersion: apps/v1 kind: Deployment metadata: name: hellohttp-v1 spec: replicas: 1 selector: matchLabels: app: hellohttp version: v1 template: metadata: labels: app: hellohttp version: v1 spec: containers: - name: hellohttp image: busybox imagePullPolicy: IfNotPresent command: ["/bin/sh", "-c", "echo 'hello httpd v1' > /var/www/index.html; httpd -f -p 80 -h /var/www/"] ports: - containerPort: 80
建立 Deployment 和 Service:ide
$ kubectl apply -f hellohttp-deploy.yaml service "hellohttp-service" created deployment.extensions "hellohttp-v1" created
到目前为止没有任何特定的针对 Istio 的内容。学习
咱们如今能够开始研究 Istio Routing。 首先,咱们须要为服务网格启用 HTTP/HTTPS 流量。 为此,咱们须要建立一个网关。 Gateway 描述了在边缘运行的负载均衡,用于接收传入或传出的 HTTP/TCP 链接。测试
让咱们建立一个hellohttp-gateway.yaml
文件:google
apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: hellohttp-gateway spec: selector: istio: ingressgateway # use istio default controller servers: - port: number: 80 name: http protocol: HTTP hosts: - "hellohttp.com"
建立 Gateway:
$ kubectl apply -f hellohttp-gateway.yaml gateway.networking.istio.io "hellohttp-gateway" created
此时,咱们为集群启用了 HTTP 流量。 咱们须要将以前建立的 Kubernetes 服务映射到 Gateway。 咱们将使用 VirtualService 执行此操做。
VirtualService 实际上将 Kubernetes 服务链接到 Istio 网关。 它还能够执行更多操做,例如定义一组流量路由规则,以便在主机被寻址时应用,但咱们不会深刻了解这些细节。
让咱们建立一个hellohttp-virtualservice.yaml
文件:
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: hellohttp-virtualservice spec: hosts: - "hellohttp.com" gateways: - hellohttp-gateway http: - route: - destination: host: hellohttp-service
请注意,VirtualService 与特定网关绑定,并定义引用 Kubernetes 服务的主机。
建立 VirtualService:
$ kubectl apply -f hellohttp-virtualservice.yaml virtualservice.networking.istio.io "hellohttp-virtualservice" created
咱们准备测试咱们的应用程序了。 咱们须要获取 Istio Ingress Gateway 的 IP 地址:
$ istio-ingressgateway NodePort 10.109.111.38 <none> 15020:32105/TCP,80:30824/TCP,443:32478/TCP,31400:32419/TCP,15443:30884/TCP 4d
当咱们在浏览器中打开NodePort-IP
时,咱们应该看到 hellohttp ASP.NET Core 应用程序:
在某些时候,您但愿将应用更新为新版本。 也许你想分割两个版本之间的流量。 您须要建立一个 DestinationRule 来定义是哪些版本,在 Istio 中称为 subset。
首先,更新 hellohttp-deploy.yaml
文件以使用 v2 版本的容器定义 v2 的 deployment:
apiVersion: v1 kind: Service metadata: name: hellohttp-service labels: app: hellohttp spec: ports: - port: 80 name: http selector: app: hellohttp --- apiVersion: apps/v1 kind: Deployment metadata: name: hellohttp-v1 spec: replicas: 1 selector: matchLabels: app: hellohttp version: v1 template: metadata: labels: app: hellohttp version: v1 spec: containers: - name: hellohttp image: busybox imagePullPolicy: IfNotPresent command: ["/bin/sh", "-c", "echo 'hello httpd v1' > /var/www/index.html; httpd -f -p 80 -h /var/www/"] ports: - containerPort: 80 --- apiVersion: apps/v1 kind: Deployment metadata: name: hellohttp-v2 spec: replicas: 1 selector: matchLabels: app: hellohttp version: v2 template: metadata: labels: app: hellohttp version: v2 spec: containers: - name: hellohttp image: busybox imagePullPolicy: IfNotPresent command: ["/bin/sh", "-c", "echo 'hello httpd v2' > /var/www/index.html; httpd -f -p 80 -h /var/www/"] ports: - containerPort: 80
建立新的 Deployment:
$ kubectl apply -f hellohttp-deploy.yaml service "hellohttp-service" unchanged deployment.extensions "hellohttp-v1" unchanged deployment.extensions "hellohttp-v2" created
若是使用 EXTERNAL-IP 刷新浏览器,您将看到应用程序的 v1 和 v2 版本交替出现:
这是符合预期的,由于两个版本都暴露在相同的 Kubernetes 服务以后:hellohttp-service。
若是您想将服务仅指向 v2,该怎么办? 这能够经过在 VirtualService 中指定 subset 来完成,但咱们须要首先在 DestinationRules 中定义这些 subset。 DestinationRule 本质上是将标签映射到 Istio 的 subset。
建立一个hellohttp-destinationrule.yaml
文件:
apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: hellohttp-destinationrule spec: host: hellohttp-service trafficPolicy: tls: mode: ISTIO_MUTUAL subsets: - name: v1 labels: version: v1 - name: v2 labels: version: v2
建立 DestinationRule:
$ kubectl apply -f hellohttp-destinationrule.yaml destinationrule.networking.istio.io "hellohttp-destinationrule" created
如今你能够从 VirtualService 来引用 v2 subset:
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: hellohttp-virtualservice spec: hosts: - "hellohttp.com" gateways: - hellohttp-gateway http: - route: - destination: host: hellohttp-service subset: v2
更新 VirtualService:
$ kubectl apply -f hellohttp-virtualservice.yaml virtualservice.networking.istio.io "hellohttp-virtualservice" configured
若是您如今继续浏览 EXTERNAL-IP,您如今应该只能看到应用程序的 v2 版本。
能够从 VirtualService 来引用v2 subset和v1 subset
[root@localhost hello-world]# cat hellohttp-virtualservice.yaml apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: hellohttp-virtualservice spec: hosts: - "hellohttp.com" gateways: - hellohttp-gateway http: - route: - destination: host: hellohttp-service subset: v1 weight: 75 - destination: host: hellohttp-service subset: v2 weight: 25
上面的配置就是经过VirtualService 调用DestinationRule 里面定义的host分类,来进行AB 版本的流量分离,进行AB 版本更新。
对于生产环境里面的版本更新能够进行header 主机头匹配,进行版本区分,基础的金丝雀发布更新版本就是这样实现的。
我想在 Istio Routing 中提到的最后一件事是 ServiceEntry。 默认状况下,Istio 中的全部外部流量都被阻止。 若是要启用外部流量,则须要建立 ServiceEntry 以列出为外部流量启用的协议和主机。 我不会在这篇文章中展现一个例子,但你能够在这里阅读更多相关内容。
但愿这篇文章对你有用! 若是您想了解更多信息,能够使用 codelab 系列如下两部分,其中全部这些概念和更多内容将在逐步的详细教程中进行说明: