如何在DigitalOceanKubernetes上使用大使创建API网关
作为 Write for DOnations 计划的一部分,作者选择了 Free and Open Source Fund 来接受捐赠。
介绍
Ambassador 是用于云原生应用程序的 API 网关,用于在异构服务之间路由流量并维护分散的工作流。 它充当单一入口点,支持服务发现、配置管理、路由规则和速率限制等任务。 它为您的服务提供了极大的灵活性和易于配置。
Envoy 是专为云原生应用设计的开源服务代理。 在 Kubernetes 中,Ambassador 可用于安装和管理 Envoy 配置。 Ambassador 支持零停机配置更改以及与身份验证、服务发现和 服务网格 等其他功能的集成。
在本教程中,您将使用 Helm 在 Kubernetes 集群上设置 Ambassador API 网关,并将其配置为根据路由规则将传入流量路由到各种服务。 您将配置这些规则以根据主机名或路径将流量路由到相关服务。
先决条件
在开始本指南之前,您需要以下内容:
- 配置了 kubectl 的 DigitalOcean Kubernetes 集群。 要在 DigitalOcean 上创建 Kubernetes 集群,请参阅我们的 Kubernetes 快速入门 。
- Helm 包管理器安装在本地机器上,Tiller 安装在集群上。 完成 如何使用 Helm 包管理器在 Kubernetes 集群上安装软件的第 1 步和第 2 步
- 一个完全注册的域名,至少配置了两条 A 记录。 本教程将自始至终使用
svc1.your-domain
、svc2.your-domain
和svc3.your-domain
。 您可以按照 DNS 快速入门 在 DigitalOcean 上设置您的记录。
第 1 步 — 安装大使
在本节中,您将在 Kubernetes 集群上安装 Ambassador。 可以使用 Helm 图表或通过将 YAML 配置文件传递给 kubectl
命令来安装大使。
注意: DigitalOcean Kubernetes 默认启用了RBAC,所以在使用YAML配置文件进行安装时,您需要确保使用启用RBAC的配置文件。 您可以在 Ambassador 的 文档 中找到有关通过 YAML 将 Ambassador 部署到 Kubernetes 的更多详细信息。
出于本教程的目的,您将使用 Helm 图表将 Ambassador 安装到您的集群。 遵循先决条件后,您将 Helm 安装到您的集群中。
首先,运行以下命令通过 Helm 安装 Ambassador:
helm upgrade --install --wait ambassador stable/ambassador
您将看到类似于以下内容的输出:
OutputRelease "ambassador" does not exist. Installing it now. NAME: ambassador LAST DEPLOYED: Tue Jun 18 02:15:00 2019 NAMESPACE: default STATUS: DEPLOYED RESOURCES: ==> v1/Deployment NAME READY UP-TO-DATE AVAILABLE AGE ambassador 3/3 3 3 2m39s ==> v1/Pod(related) NAME READY STATUS RESTARTS AGE ambassador-7d55c468cb-4gpq9 1/1 Running 0 2m38s ambassador-7d55c468cb-jr9zr 1/1 Running 0 2m38s ambassador-7d55c468cb-zhm7l 1/1 Running 0 2m38s ==> v1/Service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE ambassador LoadBalancer 10.245.183.114 139.59.52.164 80:30001/TCP,443:31557/TCP 2m40s ambassador-admins ClusterIP 10.245.46.43 <none> 8877/TCP 2m41s ==> v1/ServiceAccount NAME SECRETS AGE ambassador 1 2m43s ==> v1beta1/ClusterRole NAME AGE ambassador 2m41s ==> v1beta1/ClusterRoleBinding NAME AGE ambassador 2m41s ==> v1beta1/CustomResourceDefinition NAME AGE authservices.getambassador.io 2m42s consulresolvers.getambassador.io 2m41s kubernetesendpointresolvers.getambassador.io 2m42s kubernetesserviceresolvers.getambassador.io 2m43s mappings.getambassador.io 2m41s modules.getambassador.io 2m41s ratelimitservices.getambassador.io 2m42s tcpmappings.getambassador.io 2m41s tlscontexts.getambassador.io 2m42s tracingservices.getambassador.io 2m43s . . .
这将创建一个 Ambassador 部署、服务和一个负载均衡器,并附加您的 Kubernetes 集群节点。 您需要负载均衡器的 IP 将其映射到您域的 A 记录。
要获取您的 Ambassador 负载均衡器的 IP 地址,请运行以下命令:
kubectl get svc --namespace default ambassador
您将看到类似于以下内容的输出:
OutputNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE ambassador LoadBalancer your_cluster_IP your-IP-address 80:30001/TCP,443:31557/TCP 8m4s
请注意此步骤中的外部 IP your-IP-address
并映射域(通过您的域提供商)svc1.your-domain
、svc2.your-domain
和 svc3.your-domain
以指向该 IP 地址.
您可以使用 如何配置 SSL 终止 中给出的步骤,使用 DigitalOcean 负载均衡器启用 HTTPS。 建议通过负载均衡器配置 TLS 终止。 配置 TLS 终止的另一种方法是使用 Ambassador 的 TLS Support
您已经使用 Helm 在您的 Kubernetes 集群上安装了 Ambassador,Helm 在默认命名空间中创建了一个带有三个副本的 Ambassador 部署。 这还创建了一个具有公共 IP 的负载均衡器,以将所有流量路由到 API 网关。 接下来,您将为三个不同的服务创建 Kubernetes 部署,您将使用这些服务来测试此 API 网关。
第 2 步 — 设置 Web 服务器部署
在本节中,您将创建三个部署来运行三个不同的 Web 服务器容器。 您将为三个不同的 Web 服务器容器创建包含 Kubernetes 部署定义的 YAML 文件,并使用 kubectl
部署它们。
打开您喜欢的文本编辑器,为 Nginx Web 服务器创建您的第一个部署:
nano svc1-deploy.yaml
在您的文件中输入以下 yaml 配置:
svc1-deploy.yaml
apiVersion: extensions/v1beta1 kind: Deployment metadata: name: svc1 spec: replicas: 1 selector: matchLabels: app: nginx name: svc1 strategy: type: RollingUpdate template: metadata: labels: app: nginx name: svc1 spec: containers: - name: nginx image: nginx:latest ports: - name: http containerPort: 80
在这里,您定义了一个带有 nginx:latest 容器镜像的 Kubernetes Deployment
,该容器镜像将与 1
副本一起部署,称为 svc1
。 Deployment
被定义为在端口 80
处公开集群内。
保存并关闭文件。
然后运行以下命令以应用此配置:
kubectl apply -f svc1-deploy.yaml
您将看到确认创建的输出:
Outputdeployment.extensions/svc1 created
现在,创建第二个 Web 服务器部署。 打开一个名为 svc2-deploy.yaml
的文件:
nano svc2-deploy.yaml
在文件中输入以下 YAML 配置:
svc2-deploy.yaml
apiVersion: extensions/v1beta1 kind: Deployment metadata: name: svc2 spec: replicas: 1 selector: matchLabels: app: httpd name: svc2 strategy: type: RollingUpdate template: metadata: labels: app: httpd name: svc2 spec: containers: - name: httpd image: httpd:latest ports: - name: http containerPort: 80
在这里,您定义了一个带有 httpd 容器镜像的 Kubernetes Deployment
,该容器镜像将与 1
副本一起部署,称为 svc2
。
保存并关闭文件。
运行以下命令以应用此配置:
kubectl apply -f svc2-deploy.yaml
你会看到这个输出:
Outputdeployment.extensions/svc2 created
最后,对于第三次部署,打开并创建 svc3-deploy.yaml
文件:
nano svc3-deploy.yaml
将以下行添加到文件中:
svc3-deploy.yaml
apiVersion: extensions/v1beta1 kind: Deployment metadata: name: svc3 spec: replicas: 1 selector: matchLabels: app: httpbin name: svc3 strategy: type: RollingUpdate template: metadata: labels: app: httpbin name: svc3 spec: containers: - name: httpbin image: kennethreitz/httpbin:latest ports: - name: http containerPort: 80
在这里,您定义了一个带有 httpbin 容器镜像的 Kubernetes Deployment
,该容器镜像将与 1
副本一起部署,称为 svc3
。
保存并关闭文件。
最后,运行以下命令进行应用:
kubectl apply -f svc3-deploy.yaml
您将看到以下输出:
Outputdeployment.extensions/svc3 created
您已经使用 Kubernetes 部署部署了三个 Web 服务器容器。 在下一步中,您将把这些部署暴露给互联网流量。
第 3 步 — 使用带大使注释的服务公开应用程序
在本节中,您将向 Internet 公开您的 Web 应用程序,使用 Ambassador annotations 创建 Kubernetes 服务,以配置规则以将流量路由到它们。 Kubernetes 中的注解是一种向对象添加元数据的方法。 Ambassador 使用来自服务的这些注释值来配置其路由规则。
提醒一下,您需要在 DNS 记录中将您的域(例如:svc1.your-domain
、svc2.your-domain
和 svc3.your-domain
)映射到负载均衡器的公共 IP。
通过创建并打开此文件,使用 Ambassador 注解为 svc1
部署定义 Kubernetes 服务:
nano svc1-service.yaml
注意: 每个Ambassador注解块的映射名称应该是唯一的。 该映射充当每个注释块的标识符,如果重复,它将与较旧的注释块重叠。
svc1-service.yaml
apiVersion: v1 kind: Service metadata: name: svc1 annotations: getambassador.io/config: | --- apiVersion: ambassador/v1 kind: Mapping name: svc1-service_mapping host: svc1.your-domain prefix: / service: svc1:80 spec: selector: app: nginx name: svc1 ports: - name: http protocol: TCP port: 80
在此 YAML 代码中,您定义了一个带有 Ambassador 注解的 Kubernetes 服务 svc1
以将主机名 svc1.your-domain
映射到此服务。
保存并退出svc1-service.yaml
,然后执行以下命令应用此配置:
kubectl apply -f svc1-service.yaml
你会看到这个输出:
Outputservice/svc1 created
使用大使注释为 svc2
部署创建您的第二个 Kubernetes 服务。 这是使用 Ambassador 进行基于主机的路由的另一个示例:
svc2-service.yaml
将以下配置添加到文件中:
svc2-service.yaml
apiVersion: v1 kind: Service metadata: name: svc2 annotations: getambassador.io/config: | --- apiVersion: ambassador/v1 kind: Mapping name: svc2-service_mapping host: svc2.your-domain prefix: / service: svc2:80 spec: selector: app: httpd name: svc2 ports: - name: http protocol: TCP port: 80
将其另存为 svc2-service.yaml
。 在这里,您定义了另一个带有 Ambassador 注解的 Kubernetes 服务,当 Ambassador 收到任何带有 host
标头值为 svc2.your-domain
的请求时,将流量路由到 svc2
。 因此,此基于主机的路由将允许您向子域 svc2.your-domain
发送请求,该子域会将流量路由到服务 svc2
并从 httpd
Web 服务器处理您的请求.
要创建此服务,请执行以下操作:
kubectl apply -f svc2-service.yaml
您将看到以下输出:
Outputservice/svc2 created
为您的 svc3
部署创建第三个 Kubernetes 服务,并通过路径 svc2.your-domain/bin
为其提供服务。 这将为 Ambassador 配置基于路径的路由:
svc3-service.yaml
apiVersion: v1 kind: Service metadata: name: svc3 spec: selector: app: httpbin name: svc3 ports: - name: http protocol: TCP port: 80
将其保存为 svc3-service.yaml
并运行以下命令以应用配置:
kubectl apply -f svc3-service.yaml
您的输出将是:
Outputservice/svc3 created
编辑 svc2-service.yaml
以将第二个 Ambassador 注释块附加到将 /bin
路由到 svc3
服务:
nano svc2-service.yaml
svc2-service.yaml
apiVersion: v1 kind: Service metadata: name: svc2 annotations: getambassador.io/config: | --- apiVersion: ambassador/v1 kind: Mapping name: svc2-service_mapping host: svc2.your-domain prefix: / service: svc2:80 --- apiVersion: ambassador/v1 kind: Mapping name: svc3-service_mapping host: svc2.your-domain prefix: /bin service: svc3:80 spec: selector: app: httpd name: svc2 ports: - name: http protocol: TCP port: 80
您已添加第二个 Ambassador 注释块来配置以 /bin
开头的路径以映射到您的 svc3
Kubernetes 服务。 为了将 svc2.your-domain/bin
的请求路由到 svc3
,您在此处添加了第二个注释块作为主机值 svc2.your-domain
,这对于两个块都是相同的。 因此,基于路径的路由将允许您向 svc2.your-domain/bin
发送请求,该请求将由服务 svc3
接收并由本教程中的 httpbin
应用程序提供服务
现在运行以下命令以应用更改:
kubectl apply -f svc2-service.yaml
你会看到这个输出:
Outputservice/svc2 configured
您已经为这三个部署创建了 Kubernetes 服务,并添加了带有 Ambassador 注解的基于主机和基于路径的路由规则。 接下来,您将向这些服务添加高级配置,以配置路由、重定向和自定义标头。
第 4 步 — 路由的高级大使配置
在本节中,您将使用进一步的 Ambassador 注释来配置服务,以 修改标头 和 配置重定向 。
curl
域 svc1.your-domain
并检查响应头:
curl -I svc1.your-domain
您的输出将类似于以下内容:
OutputHTTP/1.1 200 OK server: envoy date: Mon, 17 Jun 2019 21:41:00 GMT content-type: text/html content-length: 612 last-modified: Tue, 21 May 2019 14:23:57 GMT etag: "5ce409fd-264" accept-ranges: bytes x-envoy-upstream-service-time: 0
此输出显示从使用 Ambassador 路由的服务接收到的标头。 您将使用大使注释将自定义标头添加到您的服务响应中,并验证新添加的标头的输出。
要将自定义标头添加到您的服务响应,请从响应中删除标头 x-envoy-upstream-service-time
并为 svc1
添加新的响应标头 x-geo-location: India
。 (您可以根据您的要求更改此标题。)
编辑文件 svc1-service.yaml
:
nano svc1-service.yaml
使用以下突出显示的行更新注释:
svc1-service.yaml
apiVersion: v1 kind: Service metadata: name: svc1 annotations: getambassador.io/config: | --- apiVersion: ambassador/v1 kind: Mapping name: svc1-service_mapping host: svc1.example.com prefix: / remove_response_headers: - x-envoy-upstream-service-time add_response_headers: x-geo-location: India service: svc1:80 spec: selector: app: nginx name: svc1 ports: - name: http protocol: TCP port: 80
在这里,您已修改 svc1
服务以删除 x-envoy-upstream-service-time
并在 HTTP 响应中添加 x-geo-location: India
标头。
应用您所做的更改:
kubectl apply -f svc1-service.yaml
您将看到以下输出:
Outputservice/svc1 configured
现在运行 curl
以验证服务响应中更新的标头:
curl -I svc1.your-domain
输出将与此类似:
OutputHTTP/1.1 200 OK server: envoy date: Mon, 17 Jun 2019 21:45:26 GMT content-type: text/html content-length: 612 last-modified: Tue, 21 May 2019 14:23:57 GMT etag: "5ce409fd-264" accept-ranges: bytes x-geo-location: India
现在编辑 svc3-service.yaml
以将您的主机名 svc3.your-domain
的请求重定向到路径 svc2.your-domain/bin
:
nano svc3-service.yaml
附加如下 YAML 所示的 Ambassador 注释块并保存:
svc3-service.yaml
apiVersion: v1 kind: Service metadata: name: svc3 annotations: getambassador.io/config: | --- apiVersion: ambassador/v1 kind: Mapping name: redirect_mapping host: svc3.your-domain prefix: / service: svc2.your-domain host_redirect: true path_redirect: /bin spec: selector: app: httpbin name: svc3 ports: - name: http protocol: TCP port: 80
您已添加 host_redirect: true
来为主机名 svc3.your-domain
配置 svc3
到 svc2.your-domain/bin
的 301 重定向响应。 host_redirect
参数向客户端发送 301 重定向响应。 如果未设置,请求将收到 200 个 HTTP 响应而不是 301 个 HTTP 响应。
现在运行以下命令以应用这些更改:
kubectl apply -f svc3-service.yaml
您将看到与以下类似的输出:
Outputservice/svc3 configured
您现在可以使用 curl
检查 svc3.your-domain
的响应:
curl -I svc3.your-domain
您的输出将类似于以下内容:
OutputHTTP/1.1 301 Moved Permanently location: http://svc2.your-domain/bin date: Mon, 17 Jun 2019 21:52:05 GMT server: envoy transfer-encoding: chunked
输出是请求响应服务 svc3.your-domain
的 HTTP 标头,表明您的服务注释中的 host_redirect: true
配置已正确提供 HTTP 状态代码:301 Moved Permanently
。
您已使用大使注释配置服务以修改 HTTP 标头并配置重定向。 接下来,您将向 Ambassador API 网关服务添加全局配置。
第 5 步 — 设置大使全局配置
在本节中,您将编辑大使服务以添加全局 GZIP 压缩配置。 GZIP 压缩将压缩 HTTP 资产大小并减少网络带宽需求,从而加快 Web 客户端的响应时间。 此配置会影响通过大使 API 网关路由的所有流量。 同样,您可以使用 Ambassador 配置其他全局模块,这使您可以在全局级别为 Ambassador 启用特殊行为。 可以使用注解将这些全局配置应用于大使服务。 您可以参考 Ambassador 的全局配置 文档了解更多信息。
以下 kubectl edit
命令将打开默认编辑器,即 vim。 例如,要使用 nano,您可以将环境变量 KUBE_EDITOR
设置为 nano:
export KUBE_EDITOR="nano"
编辑大使服务:
kubectl edit service ambassador
现在将突出显示的行添加到 GZIP 压缩的新注释块中:
编辑大使服务
apiVersion: v1 kind: Service metadata: annotations: getambassador.io/config: | --- apiVersion: ambassador/v1 kind: Module name: ambassador config: service_port: 8080 --- apiVersion: ambassador/v0 kind: Module name: ambassador config: gzip: memory_level: 5 min_content_length: 256 compression_level: BEST compression_strategy: DEFAULT content_type: - application/javascript - application/json - text/html - text/plain disable_on_etag_header: false remove_accept_encoding_header: false creationTimestamp: "2019-06-17T20:45:04Z" labels: app.kubernetes.io/instance: ambassador app.kubernetes.io/managed-by: Tiller app.kubernetes.io/name: ambassador helm.sh/chart: ambassador-2.8.2 name: ambassador namespace: default resourceVersion: "2153" . . .
您已将 Ambassador 注释块添加到您的 Ambassador 服务并为 API 网关全局配置 GZIP。 此处包含用于控制 memory_level
使用的内部内存量的配置,该值可以是 1 到 9 之间的值。 设置为 BEST
的 compression_level
以更高的延迟为代价确保更高的压缩率。 使用 min_content_length
已将最小响应长度配置为 256
字节。 对于 content_type
,您特别包含了一组产生压缩的 媒体类型 (以前的 MIME 类型)。 最后,您将最后两个配置添加为 false
以允许压缩。
您可以在 Envoy 的 GZIP 页面 上阅读有关 GZIP 压缩的更多信息。
此服务中的任何更改都将作为 API 网关的全局配置应用。
退出编辑器后,您将看到类似于以下内容的输出:
Outputservice/ambassador edited
使用 curl
检查 svc1.your-domain
以获取具有值 gzip
的 content-encoding
标头:
curl --compressed -i http://svc1.example.com
输出将与此类似:
OutputHTTP/1.1 200 OK server: envoy date: Mon, 17 Jun 2019 22:25:35 GMT content-type: text/html last-modified: Tue, 21 May 2019 14:23:57 GMT accept-ranges: bytes x-geo-location: India vary: Accept-Encoding content-encoding: gzip transfer-encoding: chunked <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html>
在这里您可以看到 Nginx 的默认 HTML 页面,其响应标头显示接收到的响应的 content-encoding
是 gzip
压缩的。
您已将全局配置添加到 Ambassador,以便为跨 API 网关的选定内容类型响应启用 GZIP 配置。
结论
您已使用 Ambassador 为您的 Kubernetes 集群成功设置 API 网关。 您现在可以使用基于主机和路径的路由、自定义标头和全局 GZIP 压缩来公开您的应用程序。
有关大使注解和配置参数的更多信息,请阅读 Ambassador 的官方文档。