Kubernetes服务网格(第8部分):Linkerd作为入口控制器

时间:2022-04-23
本文章向大家介绍Kubernetes服务网格(第8部分):Linkerd作为入口控制器,主要内容包括Ingress Hello World、第2步:部署Hello World应用程序、第3步:创建入口资源、用TLS入口、基本概念、基础应用、原理机制和需要注意的事项等,并结合实例形式分析了其使用技巧,希望通过本文能帮助到大家理解应用这部分内容。

Linkerd旨在使应用程序内部服务间的通信安全,快速和可靠。但是,这些目标同样适用于网络的接入层(应用程序对外的服务)。在这篇文章中,我们将展示Linkerd的一个新特性,Linkerd可以充当Kubernetes入口控制器,并展示Linkerd如何处理入站流量的能力。

这是关于Linkerd,Kubernetes和服务网格的一系列文章中的一篇文章。本系列的其他部分包括:

  1. Top-line service metrics
  2. Pods are great, until they’re not
  3. Encrypting all the things
  4. Continuous deployment via traffic shifting
  5. Dogfood environments, ingress, and edge routing
  6. Staging microservices without the tears
  7. Distributed tracing made easy
  8. Linkerd as an ingress controller (本文)
  9. gRPC for fun and profit
  10. The service mesh API
  11. Egress
  12. Retry budgets, deadline propagation, and failing gracefully
  13. Autoscaling by top-line metrics

在 本系列的 前一篇文章中,我们探讨了如何通过将Linkerd部署为Kubernetes DaemonSet方式运行,并通过相应的Service VIP来接收外部请求。在这篇文章中,我们将通过利用Linkerd 0.9.1中引入的功能把Linkerd直接作为Kubernetes入口控制器来简化这个部署设置 ,这个针对小型网站部署特别方便快捷,因为不需要部署中间件。

这种部署方法可以使Linkerd与Kubernetes API紧密集成并且简单有效。然而,对于更复杂的需求,如按需TLS证书生成,SNI(Server Name Indication,即服务名称指示)或基于cookie值的路由(例如本系列第五部分讨论的员工采用的dogfooding方法 ),我们需要将Linkerd与网络接入层中间件应用程序结合使用,例如Nginx、Apache等。

那么我们先来思考下什么是Kubernetes入口控制器?入口控制器其本质上是一个网络接入层路由器,它接受来自外部的请求并将其转发到Kubernetes群集中的服务。入口控制器根据在Kubernetes的入口资源中定义的HTTP主机和路由规则来工作。

Ingress Hello World

使用linkerd-例子中的Kubernetes配置,我们可以使Linkerd作为专用入口控制器。配置遵循与我们之前在k8s守护进程上的文章相同的模式 :它部署l5d-config ConfigMap, l5d DaemonSet和l5d Service。

hello-world程序请求示意图

第1步:部署Linkerd

首先,我们来部署Linkerd。当然,您可以将其部署到默认名称空间中,但是在这里我们已经将Linkerd放在了自己的名称空间中,以便更好地分离问题:

$ kubectl create ns l5d-system # 创建名称空间
$ kubectl apply -f https://raw.githubusercontent.com/linkerd/linkerd-examples/master/k8s-daemonset/k8s/linkerd-ingress-controller.yml -n l5d-system

您可以通过运行来验证Linkerd窗格是否已启动:

$ kubectl get po -n l5d-system
NAME        READY     STATUS    RESTARTS   AGE
l5d-0w0f4   2/2       Running   0          5s
l5d-3cmfp   2/2       Running   0          5s
l5d-dj1sm   2/2       Running   0          5s

并查看管理控制台(运行该命令前需要确定您的集群支持LoadBalancer(负载均衡),入口LB(即LoadBalancer)可能需要几分钟才可以使用)。

$ L5D_SVC_IP = $(kubectl get svc l5d -n l5d-system -o jsonpath =“{.status.loadBalancer.ingress [0].*}”)
$ open http://$L5D_SVC_IP:9990 # on OS X

我们可以通过命令查看刚刚部署的ConfigMap。下面的配置内容存储在config.yaml文件中。

$ kubectl get cm l5d-config -n l5d-system -o yaml

apiVersion: v1
data:
  config.yaml: |-
    namers:
    - kind: io.l5d.k8s
    routers:
    - protocol: http
      identifier:
        kind: io.l5d.ingress
      servers:
        - port: 80
          ip: 0.0.0.0
          clearContext: true
      dtab: /svc => /#/io.l5d.k8s
    usage:
      orgId: linkerd-examples-ingress

您可以看到,此配置在端口80上定义了HTTP路由器。然后将得到的命名空间,端口和服务名称传递给Kubernetes编号器进行解析。我们还设置clearContexttrue 是为了拒绝任何不受信任的来源传入Linkerd的请求。

第2步:部署Hello World应用程序

现在部署我们的应用程序,以便我们的入口控制器可以将请求流量分发给应用程序。我们将部署一个由hello和world两个服务组成的简单应用程序。

$ kubectl apply -f https://raw.githubusercontent.com/linkerd/linkerd-examples/master/k8s-daemonset/k8s/hello-world.yml
$ kubectl apply -f https://raw.githubusercontent.com/linkerd/linkerd-examples/master/k8s-daemonset/k8s/world-v2.yml

您可以再次验证Pods已启动并正在运行:

$ kubectl get po

NAME             READY     STATUS    RESTARTS   AGE
hello-0v0vx      1/1       Running   0          5s
hello-84wfp      1/1       Running   0          5s
hello-mrcfr      1/1       Running   0          5s
world-v1-105tl   1/1       Running   0          5s
world-v1-1t6jc   1/1       Running   0          5s
world-v1-htwsw   1/1       Running   0          5s
world-v2-5tl10   1/1       Running   0          5s
world-v2-6jc1t   1/1       Running   0          5s
world-v2-wswht   1/1       Running   0          5s

此时,如果您尝试发送入口请求,则会看到如下所示的内容:

$ curl  $ L5D_SVC_IP

Unknown destination: Request("GET /", from /184.23.234.210:58081) / no ingress rule matches

第3步:创建入口资源

为了使我们的Linkerd入口控制器正常工作,我们需要创建一个使用Linkerd作为接入层路由的入口资源

$ kubectl apply -f https://raw.githubusercontent.com/linkerd/linkerd-examples/master/k8s-daemonset/k8s/hello-world-ingress.yml

验证资源是否创建成功:

$ kubectl get ingress

NAME          HOSTS      ADDRESS   PORTS     AGE
hello-world   world.v2             80        7s

这样“你好,世界”的入口资源就引用了我们的后端程序(所以我们仅用了 world-v1world-v2 这个demo):

apiVersion : extensions / v1beta1
kind: Ingress
metadata:
  name: hello-world
  annotations:
      kubernetes.io/ingress.class: "linkerd"
spec:
  backend:
    serviceName: world-v1
    servicePort: http
  rules:
  - host: world.v2
    http:
      paths:
      - backend:
          serviceName: world-v2
          servicePort: http

资源

  • 如果请求与任何定义的规则不匹配,则指定world-v1为默认路由。
  • 其中包含world.v2主机header的所有请求都将被路由到world-v2服务。
  • kubernetes.io/ingress.class 注释设置为“linkerd”。请注意,只有在群集中运行多个入口控制器时,才需要此注释。GCE(Google Compute Engine)默认运行一个; 您可以按照这些说明选择禁用它 。

至此!您可以通过分配给l5d服务负载均衡器的IP来验证这些规则。

$ curl  $ L5D_SVC_IP
world (10.0.4.7)!
$ curl -H "Host: world.v2" $L5D_SVC_IP
earth (10.0.1.5)!

虽然这个例子是以全新的实例开始的,但是将入口标识符路由器添加到预先存在的链接设置也很简单。此外,尽管我们在此使用了一个DaemonSet(与Kubernetes系列的其余服务网格保持一致),但对使用Kubernetes 部署此demo也同样适用。使用Kubernetes部署留给读者一个练习。

用TLS入口

Linkerd已经支持群集内客户端和服务器的TLS。本系列的第三部分详细介绍了如何设置TLS 。在该入口控制器配置,Linkerd需要的TLS证书是由名为ingress-certsKubernetes secret定义 ,并遵循 描述为入口的用户指南的一部分的格式。请注意,不要将TLS部分指定为入口资源的一部分:Linkerd不支持入口资源配置中有关TLS的设置。所有的TLS配置都需要在l5d-configConfigMap中配置的。

Linkerd配置保持不变,更改服务器端口443并添加TLS文件路径:

  ...
    servers:
  - port: 443
    ip: 0.0.0.0
    clearContext: true
    tls:
      certPath: /io.buoyant/linkerd/certs/tls.crt
      keyPath: /io.buoyant/linkerd/certs/tls.key
  ...

l5d DaemonSet现在以ingress-certs名字安装一个秘密卷:

    spec:
      volumes:
      - name: certificates
        secret:
          secretName: ingress-certs
      ...
      containers:
          - name: l5d
        ...
        ports:
        - name: tls
          containerPort: 443
          hostPort: 443
        ...
        volumeMounts:
           - name: "certificates"
          mountPath: "/io.buoyant/linkerd/certs"
          readOnly: true
        ...

并更改的服务配置开放端口 443

创建Secret证书,删除原本的DaemonSet和ConfigMap,并重新载入入口控制器配置:

$ kubectl apply -f https://raw.githubusercontent.com/linkerd/linkerd-examples/master/k8s-daemonset/k8s/ingress-certificates.yml -n l5d-system
$ kubectl delete ds/l5d configmap/l5d-config -n l5d-system
$ kubectl apply -f https://raw.githubusercontent.com/linkerd/linkerd-examples/master/k8s-daemonset/k8s/linkerd-tls-ingress-controller.yml -n l5d-system

你现在应该可以做一个加密的请求(HTTPS):

# Example requires this development cert: https://raw.githubusercontent.com/linkerd/linkerd-examples/master/k8s-daemonset/certificates/cert.pem
# The cert expects "hello.world" host, so we add an /etc/hosts entry, eg:
# 104.198.196.230 hello.world
# where "104.198.196.230" is the ip stored in $L5D_SVC_IP
$ curl --cacert cert.pem -H "Host: world.v2" https://hello.world
$ earth (10.0.1.5)!

结论

Linkerd作为接入层路由器提供了许多好处。除了本文中介绍的动态路由和TLS终结外,它还 集中了连接动态负载均衡断路器和支持分布式跟踪。使用本文中引用的Linkerd入口控制器和Kubernetes配置,您可以使用易于使用的Kubernetes原生方法访问所有这些功能。最重要的是,这种方法可与服务网格的其余部分无缝协作,从而在几乎任何云架构中实现可操作性,可见性和高可用性。

ingress identifier是新功能,所以我们很想得到你从入口控制器想要什么功能。你可以在 Linkerd社区松弛或在Linkerd话语找到我们。