在前面章节中部署的 kubia 应用程序仅支持 HTTP。让我们添加 TLS 支持,这样它也可以通过 HTTPS 为客户端提供服务。你可以通过编写额外的代码来做到这一点,但是在你根本不需要接触代码的地方有一个更简单的选择。

您可以在 Sidecar 容器中与 Node.js 应用程序一起运行反向代理,并让它代表应用程序处理 HTTPS 请求。可以提供此功能的一个非常流行的软件包是 Envoy。 Envoy 代理是最初由 Lyft 构建的高性能开源服务代理,此后一直贡献给云原生计算基金会。让我们将它添加到您的 pod 中。

使用 Envoy 代理扩展 kubia Node.js 应用程序

让我简要解释一下应用程序的新架构会是什么样子。如下图所示,pod 将有两个容器——Node.js 和新的 Envoy 容器。 Node.js 容器将继续直接处理 HTTP 请求,但 HTTPS 请求将由 Envoy 处理。对于每个传入的 HTTPS 请求,Envoy 将创建一个新的 HTTP 请求,然后它将通过本地环回设备(通过 localhost IP 地址)发送到 Node.js 应用程序。
image.png
Envoy 还提供了一个基于 Web 的管理界面,这将在下一章的一些练习中证明很方便。

很明显,如果您在 Node.js 应用程序本身内实现 TLS 支持,应用程序将消耗更少的计算资源并具有更低的延迟,因为不需要额外的网络跃点,但添加 Envoy 代理可能是一个更快、更简单的解决方案。它还提供了一个很好的起点,您可以从中添加 Envoy 提供的许多其他功能,这些功能您可能永远不会在应用程序代码本身中实现。请参阅 envoyproxy.io 上的 Envoy 代理文档以了解更多信息。

将 Envoy 代理添加到 pod

您将创建一个带有两个容器的新 pod。你已经有了 Node.js 容器,但你还需要一个运行 Envoy 的容器。

创建 Envoy 容器镜像

代理的作者已经在 Docker Hub 上发布了官方的 Envoy 代理容器镜像。您可以直接使用此映像,但您需要以某种方式向容器中的 Envoy 进程提供配置、证书和私钥文件。您将在第 7 章中学习如何执行此操作。现在,您将使用已包含所有三个文件的镜像。

我已经创建了镜像并在 docker.io/luksa/kubia-ssl-proxy:1.0 提供了它,但是如果你想自己构建它,你可以在 kubia-ssl-proxy-image 目录中找到文件在本书的代码档案中。

该目录包含 Dockerfile,以及代理将用于服务 HTTPS 的私钥和证书。它还包含 envoy.conf 配置文件。在其中,您将看到代理被配置为侦听端口 8443,终止 TLS,并将请求转发到 localhost 上的端口 8080,这是 Node.js 应用程序正在侦听的地方。如前所述,代理还配置为在端口 9901 上提供管理界面。

创建 pod 清单

构建镜像后,您必须为新 pod 创建清单,如以下清单所示。

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: kubia-ssl
  5. spec:
  6. containers:
  7. - name: kubia
  8. image: luksa/kubia:1.0
  9. ports:
  10. - name: http #B
  11. containerPort: 8080 #B
  12. - name: envoy
  13. image: luksa/kubia-ssl-proxy:1.0
  14. ports:
  15. - name: https #D
  16. containerPort: 8443 #D
  17. - name: admin #E
  18. containerPort: 9901 #E

这个 pod 的名称是 kubia-ssl。它有两个容器:kubia 和 envoy。清单仅比之前的清单稍微复杂一些。唯一的新字段是端口名称,包括在内以便阅读清单的任何人都可以理解每个端口号代表什么。

创建 pod

使用命令 kubectl apply -f kubia-ssl.yaml 从清单创建 pod。然后使用 kubectl get 和 kubectl describe 命令确认 pod 的容器已成功启动。

与双容器 pod 交互

当 pod 启动时,您可以开始使用 pod 中的应用程序,检查其日志并从内部探索容器。

与应用程序通信

和以前一样,您可以使用 kubectl port-forward 来启用与 pod 中的应用程序的通信。因为它公开了三个不同的端口,所以您可以启用对所有三个端口的转发,如下所示:

  1. $ kubectl port-forward kubia-ssl 8080 8443 9901
  2. Forwarding from 127.0.0.1:8080 -> 8080
  3. Forwarding from [::1]:8080 -> 8080
  4. Forwarding from 127.0.0.1:8443 -> 8443
  5. Forwarding from [::1]:8443 -> 8443
  6. Forwarding from 127.0.0.1:9901 -> 9901
  7. Forwarding from [::1]:9901 -> 9901

首先,通过在浏览器中打开 URL http://localhost:8080 或使用 curl 来确认您可以通过 HTTP 与应用程序通信:

  1. $ curl localhost:8080
  2. Hey there, this is kubia-ssl. Your IP is ::ffff:127.0.0.1.

如果可行,您还可以尝试通过 https://localhost:8443 上的 HTTPS 访问应用程序。使用 curl 您可以执行以下操作:

  1. $ curl https://localhost:8443 --insecure
  2. Hey there, this is kubia-ssl. Your IP is ::ffff:127.0.0.1.

成功! Envoy 代理完美地处理了任务。您的应用程序现在使用 sidecar 容器支持 HTTPS。

为什么需要使用 —insecure 选项

访问服务时必须使用 —insecure 选项的原因有两个。 Envoy 代理使用的证书是自签名的,并且是为域名 example.com 颁发的。您通过本地 kubectl 代理访问服务并使用 localhost 作为 URL 中的域名,这意味着它与服务器证书中的名称不匹配。要使其匹配,您必须使用以下命令:

  1. $ curl https://example.com:8443 --resolve example.com:8443:127.0.0.1

这样可以确保证书与请求的 URL 匹配,但是由于证书是自签名的,curl 仍然无法验证服务器的合法性。您必须将服务器的证书替换为由受信任的机构签名的证书,或者使用 —insecure 标志;在这种情况下,您也无需使用 —resolve 标志。

显示具有多个容器的 pod 日志

kubia-ssl pod 包含两个容器,因此如果要显示日志,必须使用 —container 或 -c 选项指定容器的名称。例如,要查看 kubia 容器的日志,请运行以下命令:

  1. $ kubectl logs kubia-ssl -c kubia

Envoy 代理在名为 envoy 的容器中运行,因此您可以按如下方式显示其日志:

  1. $ kubectl logs kubia-ssl -c envoy

或者,您可以使用 —all-containers 选项显示两个容器的日志:

  1. $ kubectl logs kubia-ssl --all-containers

在多容器 pod 的容器中运行命令

如果您想使用 kubectl exec 命令在其中一个 pod 容器中运行 shell 或其他命令,您还可以使用 —container 或 -c 选项指定容器名称。例如,要在 envoy 容器中运行 shell,请运行以下命令:

  1. $ kubectl exec -it kubia-ssl -c envoy -- bash

如果您不提供名称,kubectl exec 默认为 pod 清单中指定的第一个容器。