本文将通过非常详细的操作步骤,向大家一步步地展示了如何使用 Istio Service Mesh 和 Apache APISIX,将启用 Service Mesh 的 Kubernetes 集群中服务暴露至集群外。
#
Service Mesh 简介随着云原生技术的火热发展,Service Mesh 逐渐在微服务领域流行起来。当下 Service Mesh 比较流行的实现方案是 Istio 和 Linkerd。
下图为 Service Mesh 示意图,通过引入 Sidecar Proxy 来完成微服务之间的互联及通信。
通过上图我们可以看出 Service Mesh 比较侧重传统意义上的东西向流量,即服务间的流量。当我们将 Service Mesh 与 Kubernetes 配合使用时,东西向流量对应的则是 Kubernetes 集群内的流量。
回到真实使用场景下,我们不会只接触到包含 Kubernetes 集群内的流量,大多数情况下都需要将一些服务暴露到集群外,供用户或其他服务使用。但将 Kubernetes 集群中的服务暴露到集群外时,我们就必须要考虑诸如安全性和可观测性等相关因素。
接下来我们将通过使用 Istio Service Mesh 和 Apache APISIX,为大家演示如何将启用 Service Mesh 的 Kubernetes 集群中服务安全暴露至集群外。
#
第一步:准备 Kubernetes 集群这里我们使用 Kind 在本地创建一个临时集群用于演示。关于如何通过 Kind 命令进行安装可参考官方文档。
以下为用于创建演示集群所使用的 yaml 配置文件,将其保存为 kind-config.yaml
。
kind: ClusterapiVersion: kind.x-k8s.io/v1alpha4nodes:- role: control-plane- role: worker- role: worker- role: worker
然后使用此配置文件创建一个集群。
(MoeLove) ➜ kind create cluster --config kind-config.yamlCreating cluster "kind" ... ✓ Ensuring node image (kindest/node:v1.22.2) 🖼 ✓ Preparing nodes 📦 📦 📦 📦 ✓ Writing configuration 📜 ✓ Starting control-plane 🕹️ ✓ Installing CNI 🔌 ✓ Installing StorageClass 💾 ✓ Joining worker nodes 🚜Set kubectl context to "kind-kind"You can now use your cluster with:
kubectl cluster-info --context kind-kind
Not sure what to do next? 😅 Check out https://kind.sigs.k8s.io/docs/user/quick-start/
#
第二步:部署 Istio在 Kubernetes 集群创建完毕后,我们来进行 Istio 的相关部署。
这里先创建一个名为 apisix-istio
的目录,进入该目录后进行如下操作。
(MoeLove) ➜ mkdir apisix-istio(MoeLove) ➜ cd apisix-istio(MoeLove) ➜ curl -sL https://istio.io/downloadIstio | sh -
Downloading istio-1.12.1 from https://github.com/istio/istio/releases/download/1.12.1/istio-1.12.1-linux-amd64.tar.gz ...
Istio 1.12.1 Download Complete!
Istio has been successfully downloaded into the istio-1.12.1 folder on your system.
Next Steps:See https://istio.io/latest/docs/setup/install/ to add Istio to your Kubernetes cluster.
To configure the istioctl client tool for your workstation,add the /root/apisix-istio/istio-1.12.1/bin directory to your environment path variable with: export PATH="$PATH:/root/apisix-istio/istio-1.12.1/bin"
Begin the Istio pre-installation check by running: istioctl x precheck
Need more information? Visit https://istio.io/latest/docs/setup/install/
上述操作执行完毕,会在当前目录下创建出一个新目录。我们可以按照以上命令的输出继续进行操作。
(MoeLove) ➜ lsistio-1.12.1(MoeLove) ➜ export PATH="$PATH:/root/apisix-istio/istio-1.12.1/bin"(MoeLove) ➜ istioctl x precheck✔ No issues found when checking the cluster. Istio is safe to install or upgrade! To get started, check out https://istio.io/latest/docs/setup/getting-started/
接下来开始进行真正的部署操作。将其设置 --set profile=minimal
进行最小化安装即可。
(MoeLove) ➜ istioctl install --set profile=minimal -y✔ Istio coreinstalled
✔ Istiodinstalled
✔ Installationcomplete
Making this installation the default for injection and validation.
Thank you for installing Istio 1.12. Please take a few minutes to tell us about your install/upgrade experience! https://forms.gle/FegQbc9UvePd4Z9z7
最后检查当前的部署状态,可以看到 Pod 已经在运行中了。
(MoeLove) ➜ kubectl -n istio-system get podsNAME READY STATUS RESTARTS AGEistiod-58d79b7bff-g66cv 1/1 Running 0 1m
#
第三步:部署 Apache APISIX接下来我们进行 Apache APISIX 的相关部署。
首先创建名为 apisix-istio
的 Namespace 并开启自动注入。
(MoeLove) ➜ kubectl create ns apisix-istionamespace/apisix-istio created(MoeLove) ➜ kubectl label namespace apisix-istio istio-injection=enablednamespace/apisix-istio labeled
接下来添加 Helm Repo 并使用 Helm 进行 Apache APISIX 和 Apache APISIX Ingress Controller 的部署。
(MoeLove) ➜ helm repo add apisix https://charts.apiseven.com"apisix" has been added to your repositories(MoeLove) ➜ helm install apisix-istio apisix/apisix --set gateway.type=NodePort --set ingress-controller.enabled=true --set ingress-controller.config.apisix.serviceNamespace=apisix-istio --set ingress-controller.config.apisix.serviceName=apisix-istio-admin --namespace apisix-istioNAME: apisix-istioLAST DEPLOYED: Wed Dec 15 14:16:33 2021NAMESPACE: apisix-istioSTATUS: deployedREVISION: 1TEST SUITE: NoneNOTES:1. Get the application URL by running these commands: export NODE_PORT=$(kubectl get --namespace apisix-istio -o jsonpath="{.spec.ports[0].nodePort}" services apisix-istio-gateway) export NODE_IP=$(kubectl get nodes --namespace apisix-istio -o jsonpath="{.items[0].status.addresses[0].address}") echo http://$NODE_IP:$NODE_PORT
执行完上述命令后,可通过执行以下命令等待所有 Pod 均正常运行。
(MoeLove) ➜ kubectl -n apisix-istio wait --for=condition=Ready pods --allpod/apisix-istio-7bdfcb4bd9-89jcn condition metpod/apisix-istio-etcd-0 condition metpod/apisix-istio-etcd-1 condition metpod/apisix-istio-etcd-2 condition metpod/apisix-istio-ingress-controller-5fcbb75b8c-b4nnc condition met
可以看到当前 Pod 全部的已经正常运行了。接下来我们进行相关测试和验证。
#
测试环节#
简单测试在之前使用 Helm 部署 Apache APISIX 时,我们将服务暴露方式选择为 NodePort
,所以接下来就可以使用以下命令直接访问到 Apache APISIX。
(MoeLove) ➜ export NODE_PORT=$(kubectl get --namespace apisix-istio -o jsonpath="{.spec.ports[0].nodePort}" services apisix-istio-gateway)(MoeLove) ➜ export NODE_IP=$(kubectl get nodes --namespace apisix-istio -o jsonpath="{.items[0].status.addresses[0].address}")(MoeLove) ➜ curl http://$NODE_IP:$NODE_PORT{"error_msg":"404 Route Not Found"}
注意,在使用 curl
命令请求时我们增加一个 -v
选项,查看一下请求的响应头。
(MoeLove) ➜ curl -v http://$NODE_IP:$NODE_PORT* Rebuilt URL to: http://172.20.0.2:31225/* Trying 172.20.0.2...* TCP_NODELAY set* Connected to 172.20.0.2 (172.20.0.2) port 31225 (#0)> GET / HTTP/1.1> Host: 172.20.0.2:31225> User-Agent: curl/7.58.0> Accept: */*>< HTTP/1.1 404 Not Found< date: Wed, 15 Dec 2021 14:31:40 GMT< content-type: text/plain; charset=utf-8< server: istio-envoy< x-envoy-upstream-service-time: 1< x-envoy-decorator-operation: apisix-istio-gateway.apisix-istio.svc.cluster.local:80/*< transfer-encoding: chunked<{"error_msg":"404 Route Not Found"}* Connection #0 to host 172.20.0.2 left intact
从上述的输出结果中可以看到,响应头中包含如下内容:
< server: istio-envoy< x-envoy-upstream-service-time: 1< x-envoy-decorator-operation: apisix-istio-gateway.apisix-istio.svc.cluster.local:80/*
这说明 Istio 的自动注入已经成功,当前直接进行交互的并不是 Apache APISIX 而是 Istio 的 Sidecar。
#
BookInfo 部署测试接下来我们使用 Istio 自带的 BookInfo 示例程序进行相关测试验证。
首先创建一个 Namespace,并开启 Istio 的自动注入。
(MoeLove) ➜ kubectl create ns bookinfonamespace/bookinfo created(MoeLove) ➜ kubectl label namespace bookinfo istio-injection=enablednamespace/bookinfo labeled
然后进行 BookInfo 部署,相关部署文件在上述安装 Istio 过程中会自动创建在目录中。
(MoeLove) ➜ kubectl -n bookinfo apply -f istio-1.12.1/samples/bookinfo/platform/kube/bookinfo.yamlservice/details createdserviceaccount/bookinfo-details createddeployment.apps/details-v1 createdservice/ratings createdserviceaccount/bookinfo-ratings createddeployment.apps/ratings-v1 createdservice/reviews createdserviceaccount/bookinfo-reviews created`deployment.apps/reviews-v1 createddeployment.apps/reviews-v2 createddeployment.apps/reviews-v3 createdservice/productpage createdserviceaccount/bookinfo-productpage createddeployment.apps/productpage-v1 created
等待所有 Pod 正常运行。
(MoeLove) ➜ kubectl -n bookinfo get podsNAME READY STATUS RESTARTS AGEdetails-v1-96cf758d8-qr6p9 2/2 Running 0 64sproductpage-v1-5f75dfbfb-22hcw 2/2 Running 0 64sratings-v1-779dbc4fdd-jt5zp 2/2 Running 0 64sreviews-v1-ffbbf7fc8-kxvrr 2/2 Running 0 64sreviews-v2-54546c6f84-pnjkn 2/2 Running 0 64sreviews-v3-74d6bf84cd-h4r9z 2/2 Running 0 63s
现在我们可以使用 Apache APISIX 将服务暴露到 Kubernetes 集群外了。使用如下内容创建一条路由配置,保存为 productpage-ar.yaml
。
apiVersion: apisix.apache.org/v2beta2kind: ApisixRoutemetadata: name: productpagespec: http: - name: rule1 match: hosts: - apisix-istio.dev paths: - /* backends: - serviceName: productpage servicePort: 9080
备注
以上配置可理解为:创建一条路由,设置域名为 apisix-istio.dev
并将所有请求流量均转发至 productpage
服务的 9080
端口。
然后创建此资源:
(MoeLove) ➜ kubectl -n bookinfo apply -f productpage-ar.yamlapisixroute.apisix.apache.org/productpage created
携带我们刚才配置的域名再次请求 Apache APISIX ,可以看到返回了 200
相关提示。
(MoeLove) ➜ curl -I -H "HOST: apisix-istio.dev" http://$NODE_IP:$NODE_PORT/HTTP/1.1 200 OKcontent-type: text/html; charset=utf-8content-length: 1683date: Wed, 15 Dec 2021 15:47:30 GMTx-envoy-upstream-service-time: 7server: istio-envoyx-envoy-decorator-operation: apisix-istio-gateway.apisix-istio.svc.cluster.local:80/*
之后可以通过 port-forward
的方式将 Apache APISIX 端口暴露出来。
(MoeLove) ➜ kubectl -n apisix-istio port-forward --address 0.0.0.0 svc/apisix-istio-gateway 8080:80Forwarding from 0.0.0.0:8080 -> 9080
最后在浏览器中设置 HOST: apisix-istio.dev
的 Header 并尝试进行请求,就可以得到如下所示的正确页面了。
#
可视化处理利器:KialiKiali 是一个可以对 Istio 进行可视化的工具,可作为 Istio add-on 进行安装。
在这里直接使用 Istio 携带的 addons
目录中的配置文件进行部署。
(MoeLove) ➜ kubectl -n istio-system apply -f istio-1.12.1/samples/addons/serviceaccount/grafana createdconfigmap/grafana createdservice/grafana createddeployment.apps/grafana createdconfigmap/istio-grafana-dashboards createdconfigmap/istio-services-grafana-dashboards createddeployment.apps/jaeger createdservice/tracing createdservice/zipkin createdservice/jaeger-collector createdserviceaccount/kiali createdconfigmap/kiali createdclusterrole.rbac.authorization.k8s.io/kiali-viewer createdclusterrole.rbac.authorization.k8s.io/kiali createdclusterrolebinding.rbac.authorization.k8s.io/kiali createdrole.rbac.authorization.k8s.io/kiali-controlplane createdrolebinding.rbac.authorization.k8s.io/kiali-controlplane createdservice/kiali createddeployment.apps/kiali createdserviceaccount/prometheus createdconfigmap/prometheus createdclusterrole.rbac.authorization.k8s.io/prometheus createdclusterrolebinding.rbac.authorization.k8s.io/prometheus createdservice/prometheus createddeployment.apps/prometheus created
等待 Pod 正常运行后查看:
(MoeLove) ➜ kubectl -n istio-system get podsNAME READY STATUS RESTARTS AGEgrafana-6ccd56f4b6-wq6k5 1/1 Running 0 2m12sistiod-58d79b7bff-g66cv 1/1 Running 0 42mjaeger-5d44bc5c5d-84ksf 1/1 Running 0 2m11skiali-79b86ff5bc-w457g 1/1 Running 0 2m3sprometheus-64fd8ccd65-2mjcc 2/2 Running 0 2m9s
接下来执行以下命令进行 Kiali 的端口转发并在浏览器中进行访问。当然使用上述 port-forward
的方式也是一样的。
(MoeLove) ➜ istioctl dashboard kiali --address 0.0.0.0 --port 9999 --browser=falsehttp://0.0.0.0:9999/kialiskipping opening a browser
在浏览器中打开 http://0.0.0.0:9999/kiali
,同时尝试多次通过 Apache APISIX 访问 BookInfo 服务,即可看到如下效果。
点击 Graph ,将 Namespace 选择为 BookInfo。在测试访问 BookInfo 应用的过程中,可看到如下所示效果。可以看到流量从 Apache APISIX 进来,然后流向应用程序的各个组件。
至此,全部流程结束。我们已经成功地使用 Apache APISIX 和 Apache APISIX Ingress Controller,将开启 Service Mesh 的 Kubernetes 集群中的服务安全地暴露出来了。
#
总结本文通过非常详细的操作步骤,向大家一步步地展示了如何使用 Istio Service Mesh 和 Apache APISIX,将启用 Service Mesh 的 Kubernetes 集群中服务暴露至集群外。后续也可以通过 Apache APISIX 丰富的插件能力提供更多安全防护或流量控制。
希望通过以上的细节教学,可以帮助大家在使用 Apache APISIX 时更方便地实现与 Istio 等方案进行集成。