在本文中,我们将向您展示如何使用linkerd作为服务网格,将TLS添加到所有服务到服务的HTTP调用中,而不用修改任何应用程序代码。
注意:这是关于linkerd,Kubernetes和服务网格的一系列文章之一。本系列的其他部分包括:
在本系列的第一部分中,我们向您展示了如何将 linkerd作为服务网格进行安装时,如何 轻松监控关键服务指标(成功率,延迟和请求率)。在本文中,我们将向您展示服务网格方法的另一个好处:它允许您将应用程序的协议与线路上使用的协议分离。换句话说,应用程序可以用一个协议,但是实际上传输时用到另一个协议。
在不需要数据转换的情况下,linkerd可以使用这个解耦来自动完成协议升级。linkerd可以做的各种协议升级的例子包括HTTP/1.x到HTTP/2,为了使用到 多路复用,以及本文的内容,HTTP到HTTPS。
当linkerd作为Kubernetes上的服务网格部署时,我们 使用DaemonSets在每个主机上放置一个链接实例。对于HTTP服务,pods可以使用http_proxy
环境变量将HTTP流量发送到其本地主机的linkerd 。(对于非HTTP流量,集成稍微复杂一些。)
在几个月前的博客文章中,我们向您展示了使用linkerd在TLS中“包装”HTTP调用的基本模式, 方法 是在连接的两端都进行代理,包括始发和终止TLS。但是,现在我们已经完成了服务网格部署,事情要简单得多。加密所有跨主机通信主要是为服务网格提供TLS证书。
我们来看一个例子。前两个步骤与我们在本系列的第一部分中所做的相同 - 我们将安装linkerd作为服务网格,并安装一个简单的微服务“hello world”应用程序。如果你已经这样做了,你可以直接跳到 步骤3。
我们可以使用这个Kubernetes配置将链接器作为服务网格安装在我们的Kubernetes集群上 。这将在默认的Kubernetes命名空间中将链接器安装为一个DaemonSet(即每个主机一个实例):
kubectl apply -f https://raw.githubusercontent.com/linkerd/linkerd-examples/master/k8s-daemonset/k8s/linkerd.yml
您可以通过查看linkerd的管理页面来确认安装是否成功(请注意,分配IP可能需要几分钟时间):
INGRESS_LB=$(kubectl get svc l5d -o jsonpath="{.status.loadBalancer.ingress[0].*}")
open http://$INGRESS_LB:9990 # on OS X
使用hello-world配置安装两个服务“hello”和“world” 。这将把服务安装到默认的命名空间中:
kubectl apply -f https://raw.githubusercontent.com/linkerd/linkerd-examples/master/k8s-daemonset/k8s/hello-world.yml
这两个服务共同组成一个高度可扩展的“hello world”微服务(hello服务当然必须调用world服务来完成请求)。
在这一点上,我们实际上有了一个正常运行的服务网格和一个使用它的应用程序。您可以通过linkerd的公网IP发送数据包流量来查看整个设置:
http_proxy=$INGRESS_LB:4140 curl -s http://hello
如果一切正常,你应该看到字符串“Hello world”。
现在已经安装了linkerd,我们用它来加密流量。我们将在每台主机上放置TLS证书,并配置linkerd以将这些证书用于TLS。
我们将使用我们自己生成的全局证书(网格证书)。由于此证书不受公共DNS名称限制,因此我们不需要使用“ Let‘s Encrypt”等服务 。我们可以生成我们自己的CA证书,并使用它来签署我们的网格证书(“自签名”)。我们将分配三个东西到每个Kubernetes主机:CA证书,网格密钥和网格证书。
以下脚本使用我们生成的示例证书。 请不要在生产中使用这些证书。有关如何生成自己的自签名证书的说明,请参阅我们以前的帖子,在这里我们有 关于如何生成自己的证书的说明)。
我们准备更新linkerd来加密流量。我们将把样品证书 作为Kubernetes 密钥分发 。
kubectl apply -f https://raw.githubusercontent.com/linkerd/linkerd-examples/master/k8s-daemonset/k8s/certificates.yml
现在我们将配置linkerd来使用这些证书,配置并重新启动它:
kubectl delete ds/l5d configmap/l5d-config
kubectl apply -f https://raw.githubusercontent.com/linkerd/linkerd-examples/master/k8s-daemonset/k8s/linkerd-tls.yml
此时,linkerd应该使用TLS加密了这些服务之间的所有通信。我们通过运行和以前一样的命令来验证它:
http_proxy=$INGRESS_LB:4140 curl -s http://hello
如果一切正常,你仍然应该看到字符串“Hello world” ,hello和world服务之间的通信正在被加密。我们可以通过直接向端口4141发送HTTPS请求来验证这一点,其中linkerd正在侦听来自其他链接实例的请求:
curl -skH 'l5d-dtab: /svc=>/#/io.l5d.k8s/default/admin/l5d;' https://$INGRESS_LB:4141/admin/ping
在这里,我们使用curl做一个HTTPS调用,并告诉它跳过TLS验证(因为curl目的是浏览一个网站,而不是作为网络链接器)。我们还添加了 dtab override, 以将请求路由到链接实例自己的管理界面。如果一切顺利的话,你应该再次看到一个“pong”回应。恭喜!您已经加密了您的跨服务流量。
在这篇文章中,我们展示了如何使用链接器之类的服务网格来透明地加密Kubernetes集群中的所有跨节点通信。我们还使用TLS来确保链接实例能够验证他们正在与其他链接实例交谈,防止中间人攻击(和配置错误!)。当然,对于应用程序这些操作是透明的。
TLS是一个复杂的话题,为了使演示变得简单快捷,我们已经掩盖了一些重要的安全考虑。请确保您在生产群集上尝试此操作之前,花时间充分理解所涉及的步骤。
最后,将TLS添加到通信基板只是使用服务网格可以完成的许多事情之一。请务必查看本系列其余文章以获取更多信息!
为了获得关于linkerd的这个或其他方面的帮助,请随时到我们的 linkerd社区Slack提问,在linkerd discourse上发表一个话题 ,或直接与我们联系!