本文发布已超过一年。较早的文章可能包含过时内容。请确认页面中的信息自发布以来未发生不正确之处。
Kong Ingress Controller 和 Service Mesh:在 Kubernetes 上设置 Ingress 到 Istio
Kubernetes 已成为容器编排及其内部服务编排的实际标准方式。但是,我们如何让集群外部的服务访问集群内部的服务呢?Kubernetes 提供了 Ingress API 对象,用于管理从外部访问集群内部的服务。
Ingress 是一组规则,它将把入站连接代理到由后端定义的端点。然而,如果没有 Ingress controller,Kubernetes 不知道如何处理 Ingress 资源,这时开源控制器就派上用场了。在本文中,我们将使用其中一种选项:Kong Ingress Controller。Kong Ingress Controller 于一年前开源,最近下载量达到一百万次。在最近发布的 0.7 版本中,还添加了服务网格支持。此版本的其他功能包括
- 内置 Kubernetes Admission Controller,它在创建或更新 Custom Resource Definitions (CRD) 时进行验证,并拒绝任何无效配置。
- 内存模式 (In-memory Mode) - 每个 Pod 的控制器主动配置其 Pod 中的 Kong 容器,这将单个 Kong 容器或控制器容器的故障影响范围限制在该 Pod 内。
- 原生 gRPC 路由 - gRPC 流量现在可以通过 Kong Ingress Controller 原生路由,并支持基于方法的路由。
如果你想更深入地了解 Kong Ingress Controller 0.7,请查阅其 GitHub 仓库。
但是让我们回到服务网格支持,因为这将是本文的主要焦点。服务网格允许组织通过将服务间通信抽象到网格层来解决与安全性、可靠性和可观测性相关的微服务挑战。但是如果我们的网格层位于 Kubernetes 内部,而我们仍然需要将某些服务暴露到集群之外呢?这时你就需要一个 Ingress controller,例如 Kong Ingress Controller。在本文中,我们将介绍如何将 Kong Ingress Controller 作为 Ingress 层部署到 Istio 网格。让我们直接开始
第一部分:在 Kubernetes 上设置 Istio
本文假设你已在 Kubernetes 上设置好 Istio。如果你需要追赶到这一点,请查阅 Istio 文档。它将引导你在 Kubernetes 上设置 Istio。
1. 安装 Bookinfo 应用
首先,我们需要为托管我们应用和 Kong 代理的命名空间打标签。要为 Bookinfo 应用所在的默认命名空间打标签,运行以下命令
$ kubectl label namespace default istio-injection=enabled
namespace/default labeled
然后创建一个新的命名空间,用于托管我们的 Kong 网关和 Ingress controller
$ kubectl create namespace kong
namespace/kong created
由于 Kong 将位于默认命名空间之外,请确保你也为 Kong 命名空间启用了 istio-injection 并打上标签
$ kubectl label namespace kong istio-injection=enabled
namespace/kong labeled
两个命名空间都必须标记为 istio-injection=enabled
。否则,默认配置不会将 sidecar 容器注入到你命名空间的 Pod 中。
现在使用以下命令部署你的 BookInfo 应用
$ kubectl apply -f http://bit.ly/bookinfoapp
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
让我们仔细检查我们的 Services 和 Pods,确保我们已正确设置所有内容
$ kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
details ClusterIP 10.97.125.254 <none> 9080/TCP 29s
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 29h
productpage ClusterIP 10.97.62.68 <none> 9080/TCP 28s
ratings ClusterIP 10.96.15.180 <none> 9080/TCP 28s
reviews ClusterIP 10.104.207.136 <none> 9080/TCP 28s
你应该看到四个新的服务:details, productpage, ratings 和 reviews。它们都没有外部 IP,所以我们将使用 Kong 网关 来暴露必要的服务。要检查 Pods,运行以下命令
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
details-v1-c5b5f496d-9wm29 2/2 Running 0 101s
productpage-v1-7d6cfb7dfd-5mc96 2/2 Running 0 100s
ratings-v1-f745cf57b-hmkwf 2/2 Running 0 101s
reviews-v1-85c474d9b8-kqcpt 2/2 Running 0 101s
reviews-v2-ccffdd984-9jnsj 2/2 Running 0 101s
reviews-v3-98dc67b68-nzw97 2/2 Running 0 101s
此命令输出有用的数据,让我们花点时间来理解它。如果你查看 READY 列,每个 Pod 都有两个容器在运行:服务容器和一个注入在其旁边的 Envoy sidecar。另一个需要强调的是,有三个 review Pods 但只有一个 review 服务。Envoy sidecar 会将流量负载均衡到包含不同版本的三个不同的 review Pods,这让我们能够对我们的更改进行 A/B 测试。在访问已部署的应用之前,我们还有一个步骤。我们需要为 productpage
服务添加一个额外的注解。要做到这一点,运行
$ kubectl annotate service productpage ingress.kubernetes.io/service-upstream=true
service/productpage annotated
API 网关 (Kong) 和服务网格 (Istio) 都可以处理负载均衡。如果没有额外的 ingress.kubernetes.io/service-upstream: "true"
注解,Kong 将尝试通过从 productpage 服务中选择自己的端点/目标来进行负载均衡。这将导致 Envoy 接收该 Pod 的 IP 作为上游本地地址,而不是服务的 Cluster IP。但我们想要服务的 Cluster IP,以便 Envoy 可以正确地负载均衡。
添加此注解后,你应该就可以访问你的 productpage 了!
$ kubectl exec -it $(kubectl get pod -l app=ratings -o jsonpath='{.items[0].metadata.name}') -c ratings -- curl productpage:9080/productpage | grep -o "<title>.*</title>"
<title>Simple Bookstore App</title>
2. 不带数据库的 Kong Kubernetes Ingress Controller
为了向世界暴露你的服务,我们将部署 Kong 作为南北流量网关。Kong 1.1 发布时带有声明性配置和无数据库模式。声明性配置允许你通过 YAML 或 JSON 文件指定所需的系统状态,而不是通过一系列 API 调用。使用声明性配置提供了几个关键优势,可以降低复杂性、提高自动化程度并增强系统性能。通过 Kong Ingress Controller,你应用于集群的任何 Ingress 规则都将自动在 Kong 代理上配置。让我们先这样设置 Kong Ingress Controller 和实际的 Kong 代理
$ kubectl apply -f https://bit.ly/k4k8s
namespace/kong configured
customresourcedefinition.apiextensions.k8s.io/kongconsumers.configuration.konghq.com created
customresourcedefinition.apiextensions.k8s.io/kongcredentials.configuration.konghq.com created
customresourcedefinition.apiextensions.k8s.io/kongingresses.configuration.konghq.com created
customresourcedefinition.apiextensions.k8s.io/kongplugins.configuration.konghq.com created
serviceaccount/kong-serviceaccount created
clusterrole.rbac.authorization.k8s.io/kong-ingress-clusterrole created
clusterrolebinding.rbac.authorization.k8s.io/kong-ingress-clusterrole-nisa-binding created
configmap/kong-server-blocks created
service/kong-proxy created
service/kong-validation-webhook created
deployment.apps/ingress-kong created
要检查 Kong Pod 是否已启动并正在运行,运行
$ kubectl get pods -n kong
NAME READY STATUS RESTARTS AGE
pod/ingress-kong-8b44c9856-9s42v 3/3 Running 0 2m26s
此 Pod 中将有三个容器。第一个容器是 Kong 网关,它将是通往你集群的 Ingress 点。第二个容器是 Ingress controller。它使用 Ingress 资源并更新代理以遵循资源中定义的规则。最后,第三个容器是由 Istio 注入的 Envoy 代理。Kong 将通过 Envoy sidecar 代理将流量路由到适当的服务。为了通过我们新部署的 Kong 网关向集群发送请求,使用 Kong 可访问的 IP 地址设置一个包含 URL 的环境变量。
$ export PROXY_URL="$(minikube service -n kong kong-proxy --url | head -1)"
$ echo $PROXY_URL
http://192.168.99.100:32728
接下来,我们需要更改一些配置,以便 sidecar Envoy 进程可以根据请求的 host/authority header 正确路由请求。运行以下命令停止路由保留 host 的行为
$ echo "
apiVersion: configuration.konghq.com/v1
kind: KongIngress
metadata:
name: do-not-preserve-host
route:
preserve_host: false
upstream:
host_header: productpage.default.svc
" | kubectl apply -f -
kongingress.configuration.konghq.com/do-not-preserve-host created
并为现有的 productpage 服务添加注解,设置 service-upstream 为 true
$ kubectl annotate svc productpage Ingress.kubernetes.io/service-upstream="true"
service/productpage annotated
现在我们已经设置好了一切,我们可以看看如何使用 Ingress 资源来帮助将外部流量路由到你的 Istio 网格内的服务。我们将创建一个 Ingress 规则,将所有路径为 /
的流量路由到我们的 productpage 服务
$ echo "
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: productpage
annotations:
configuration.konghq.com: do-not-preserve-host
spec:
rules:
- http:
paths:
- path: /
backend:
serviceName: productpage
servicePort: 9080
" | kubectl apply -f -
ingress.extensions/productpage created
就这样,Kong Ingress Controller 就能够理解你在 Ingress 资源中定义的规则,并将其路由到 productpage 服务!要查看 productpage 服务的 GUI,请在浏览器中访问 $PROXY_URL/productpage
。或者在命令行中测试,尝试
$ curl $PROXY_URL/productpage
这就是本次演示的全部内容。如果你喜欢本文中使用的技术,请查阅它们的仓库,因为它们都是开源的,并且非常乐意有更多贡献者!为了方便你,以下是它们的链接
- Kong:[GitHub] [Twitter]
- Kubernetes:[GitHub] [Twitter]
- Istio:[GitHub] [Twitter]
- Envoy:[GitHub] [Twitter]
感谢你的阅读!