我们将会继续使用 Kubernetes 入门文章 中的样例,它较为复杂,足以通过实践展示 Istio 的特性。
这个应用由四个微服务组成:
在图 6 中,除了服务之外,我们还看到了 Ingress Controller,在 Kubernetes 中,它会将传入的请求路由至对应的服务,Istio 采用了类似的概念,名为 Ingress Gateway,在本文后续的内容中,我们将会对其进行介绍。
如果要要跟着本文一起练习的话,读者可以 clone 该 GitHub 仓库 istio-mastery ,其中包含了适用于 Kubernetes 和 Istio 的应用程序与 manifest。
注入可以 自动 或 手动 完成。如果要启用自动化的 Sidecar 注入,我们需要使用 istio-injection=enabled
来标记命名空间,这可以通过执行如下的命令来实现:
复制代码
$ kubectl label namespacedefaultistio-injection=enabled namespace/defaultlabeled
现在,默认命名空间中部署的所有 pod 都将会被注入 sidecar。切换至 [istio-mastery]
仓库的根目录,并执行如下的命令:
复制代码
$ kubectl apply -f resource-manifests/kube persistentvolumeclaim/sqlite-pvc created deployment.extensions/sa-feedback created service/sa-feedback created deployment.extensions/sa-frontend created service/sa-frontend created deployment.extensions/sa-logic created service/sa-logic created deployment.extensions/sa-web-appcreated service/sa-web-appcreated
执行如下的命令并检查 Ready 列,我们会看到“2/2”,这表明第二个容器已经注入进来了。
复制代码
$ kubectlgetpods NAME READY STATUS RESTARTS AGE sa-feedback-55f5dc4d9c-c9wfv2/2Running012m sa-frontend-558f8986-hhkj92/2Running012m sa-logic-568498cb4d-s9ngt2/2Running012m sa-web-app-599cf47c7c-s7cvd2/2Running012m
服务已经启动并运行了,每个容器都包含了 sidecar 代理,如图 7 所示。
但是,要访问服务,我们需要允许传入的流量进入集群,也就是所谓的 Ingress 流量。
允许流量进入集群的一个最佳实践就是使用 Istio 的 Ingress 网关,它处于集群的边缘并且靠近传入的流量,它能够实现 Istio 的多项特性,比如路由、安全和监控。
在 Istio 安装的时候,Ingress 网关组件以及将其暴露给外部的服务已经安装到了集群中,我们可以通过如下的命令获取它的外部 IP:
复制代码
$ kubectlgetsvc -n istio-system -listio=ingressgateway NAMETYPECLUSTER-IP EXTERNAL-IP PORT(S) istio-ingressgateway LoadBalancer 10.0.132.127 13.93.30.120 80:31380/TCP,443[...]
在本文后续的内容中,我们将会通过该 IP(将其称为 EXTERNAL-IP
)访问应用程序,为了便利起见,我们通过下面的命令将其保存到变量中:
复制代码
$EXTERNAL_IP=$(kubectlgetsvc -n istio-system / -lapp=istio-ingressgateway / -ojsonpath='{.items[0].status.loadBalancer.ingress[0].ip}')
如果你在浏览器中访问该 IP 的话,将会看到服务不可用的错误,默认情况下,在我们定义网关之前,Istio 会阻止所有传入的流量。
网关是一种 Kubernetes 自定义资源定义(Kubernetes Custom Resource Definition),它是我们在集群中安装 Istio 时所定义的,借助它,我们能够指定允许传入流量的端口、协议和主机。
在我们的场景中,我们想要为所有主机开放 80 端口。我们可以通过如下的定义来进行配置:
复制代码
apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: http-gateway spec: selector: istio: ingressgateway servers: -port: number:80 name: http protocol: HTTP hosts: -"*"
除了 istio: ingressgateway
选择器之外,所有配置项的含义均不言自明。通过使用这个选择器,我们可以指定哪个 Ingress 网关使用该配置,在我们的场景中,也就是在 Istio 安装时的默认 Ingress 网关控制器。
通过执行如下的命令,应用该配置:
复制代码
$ kubectl apply -f resource-manifests/istio/http-gateway.yaml gateway.networking.istio.io"http-gateway"created
网关允许我们访问 80 端口,但是它还不知道要将请求路由至何处,而这一功能是通过 Virtual Service 来实现的。
VirtualService 能够指导 Ingress 网关如何路由允许进入集群的请求。
对于我们的应用来说,通过 http-gateway 的请求必须要路由至 sa-frontend 、 sa-web-app 和 sa-feedback 服务(如图 8 所示)。
现在,我们拆分一下应该路由至 SA-Frontend 的请求:
/ /static/* ^.*/.(ico|png|jpg)$
这样,我们就会得到如下的配置:
复制代码
kind: VirtualService metadata: name: sa-external-services spec: hosts: -"*" gateways: - http-gateway #1 http: -match: -uri: exact: / -uri: exact: /callback -uri: prefix: /static -uri: regex:'^.*/.(ico|png|jpg)$' route: -destination: host: sa-frontend #2 port: number:80
这里的重点在于:
注意:上面的配置在 sa-virtualservice-external.yaml
文件中,它还包含了路由至 SA-WebApp 和 SA-Feedback 的配置,但是简洁期间,我们将其省略了。
通过执行如下的命令,应用 VirtualService:
复制代码
$ kubectl apply -f resource-manifests/istio/sa-virtualservice-external.yaml virtualservice.networking.istio.io"sa-external-services"created
注意:当我们应用该资源时(其实所有的 Istio 资源均如此),Kubernetes API Server 会创建一个新的事件,该事件会被 Istio 的控制平面接收到,然后会将新的配置应用到每个 pod 的 envoy 代理上。Ingress Gateway 控制器是 Control Plane 配置的另外一个 Envoy,如图 9 所示。
现在,我们可以通过 http://{{EXTERNAL-IP}}/
访问情感分析应用了。如果你遇到 Not Found 状态的话,请不要担心,有时候配置生效并更新 envoy 缓存会耗费一点时间。
在转入下一部分之前,你需要使用该应用生成一些流量。
系列回顾
通过 Istio 重新实现微服务 (一):认识 Istio
通过 Istio 重新实现微服务 (二):Istio 实践