本文发表于一年多前。旧文章可能包含过时内容。请检查页面中的信息自发布以来是否已变得不正确。
Kong Ingress Controller 和服务网格:在 Kubernetes 上为 Istio 设置 Ingress
Kubernetes 已成为编排容器以及容器内服务的默认方式。但是,我们如何让集群外部的服务访问集群内部的内容呢?Kubernetes 提供了 Ingress API 对象,用于管理对集群内服务的外部访问。
Ingress 是一组规则,它将入站连接代理到后端定义的端点。然而,如果没有 Ingress 控制器,Kubernetes 无法知道如何处理 Ingress 资源,这时开源控制器就可以发挥作用。在这篇文章中,我们将使用其中一个选项:Kong Ingress Controller。Kong Ingress Controller 在一年前开源,最近达到了百万下载量。在最近的 0.7 版本中,还增加了服务网格支持。此版本的其他功能包括:
- 内置的 Kubernetes Admission Controller,它在创建或更新自定义资源定义 (CRD) 时对其进行验证,并拒绝任何无效配置。
- 内存模式 - 每个 Pod 的控制器都会主动配置其 Pod 中的 Kong 容器,这将单个 Kong 容器或控制器容器的故障影响范围限制在该 Pod。中。
- 原生 gRPC 路由 - gRPC 流量现在可以通过 Kong Ingress Controller 本地路由,并支持基于方法的路由。
如果您想深入了解 Kong Ingress Controller 0.7,请查看 GitHub 仓库。
但是,让我们回到服务网格支持,因为这将是本博客文章的主要焦点。服务网格通过将服务间通信抽象到网格层来帮助组织解决与安全性、可靠性和可观测性相关的微服务挑战。但是,如果我们的网格层位于 Kubernetes 内部,而我们仍然需要将某些服务暴露到集群之外怎么办?那么您需要一个 Ingress 控制器,例如 Kong Ingress Controller。在这篇博客文章中,我们将介绍如何将 Kong Ingress Controller 作为 Ingress 层部署到 Istio 网格。让我们直接开始吧
第 0 部分:在 Kubernetes 上设置 Istio
本博客假设您已经在 Kubernetes 上设置了 Istio。如果需要在此处进行追赶,请查看 Istio 文档。它将引导您在 Kubernetes 上设置 Istio。
1. 安装 Bookinfo 应用程序
首先,我们需要标记将承载我们的应用程序和 Kong 代理的命名空间。要标记我们的默认命名空间(bookinfo 应用程序所在的位置),请运行此命令
$ kubectl label namespace default istio-injection=enabled
namespace/default labeled
然后创建一个新命名空间来托管我们的 Kong 网关和 Ingress 控制器
$ 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 网关 来暴露必要的服务。要检查 Pod,请运行以下命令
$ 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 pod 但只有一个 review 服务。Envoy sidecar 将流量负载均衡到包含不同版本的三个不同 review pod,使我们能够对更改进行 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 作为上游本地地址接收,而不是服务的集群 IP。但我们希望使用服务的集群 IP,以便 Envoy 可以正确负载均衡。
添加此功能后,您现在应该可以访问您的产品页面了!
$ 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 Gateway,它将是集群的入口点。第二个容器是 Ingress 控制器。它使用 Ingress 资源并更新代理以遵循资源中定义的规则。最后,第三个容器是 Istio 注入的 Envoy 代理。Kong 将通过 Envoy Sidecar 代理将流量路由到相应的服务。要通过我们新部署的 Kong Gateway 将请求发送到集群,请设置一个环境变量,其 URL 基于 Kong 可访问的 IP 地址。
$ export PROXY_URL="$(minikube service -n kong kong-proxy --url | head -1)"
$ echo $PROXY_URL
http://192.168.99.100:32728
接下来,我们需要更改一些配置,以便 side-car Envoy 进程可以根据请求的主机/授权头正确路由请求。运行以下命令以阻止路由保留主机
$ 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]
感谢您的阅读!