Atlantis
GitHub Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage

2.2 traefik与ingressroute

1. 前言

在 K8s 集群中,容器通常运行在内部的集群网络中,如果需要从外部访问到容器,最简单的做法是创建一个 service 并设置 type 为 NodePort,这样就可以使用 节点:NodePort端口 的方式访问到容器。

但 NodePort 提供的是四层端口映射,假如我们有十个监听 8080 端口的 web 服务,就需要在所有节点上开启十个端口映射到对应的这些服务,这对于大规模部署和安全管控并不友好。

既然是 web 服务,那便可以通过反向代理访问,例如使用 nginx 转发请求,如果能在集群中部署一个统一的入口,根据域名、path或者 header 转发来自外部的 HTTP/Websocket/Grpc 请求,就可以大大降低维护工作量。

K8s 定义了 ingress 这种 API 对象,用于管理外部访问到集群内服务的路由,简单来说,每一个 ingress 就相当于 nginx 的一个 http server,我们可以在其中定义七层转发规则。

ingress-controller 是负责调谐 ingress 资源的控制器,开源项目 nginx-ingress-controller 就是一个由 lua 程序和 nginx 组成的容器,它可以监听 ingress 资源变化并生成对应的转发规则,当应用层请求进入到这个容器时,就会转发到对应的 pod。

K3s 自带了一个使用 GO 语言编写的 ingress-controller: traefik,在部署阶段通过 helm chart 安装,并使用一个 LoadBalancer 类型的 service 暴露,集群中的 service-lb 组件会添加一个 iptables 规则,将宿主机的 80 和 443 端口流量转发到 traefik,这样只要配置了 ingress,用域名访问宿主机的 80 和 443 端口时,就可以请求到对应的 pod。

ingressroute 是 traefik 定义的 API 对象,相比原生 ingress 提供了更丰富的功能,例如:基于 Host、Path、Header 的匹配、重定向、重写、请求和响应中间件等。

2. 配置traefik

在 K8s 中,大部分资源都是命名空间隔离的,ingressroute 也是如此,这意味着我们需要在每个命名空间下创建转发请求的 ingressroute 和保存 SSL/TLS 证书的 secret,又增加了维护工作。

对于单节点集群,我们想再简化一下,既然已经有了可以适配所有子域名的通配符证书,那么也可以使用一个 ingressroute 管理所有的请求转发,这需要开启 traefik 的跨命名空间访问资源功能,操作如下:

执行 kubectl -n kube-system edit deploy traefik,找到 traefik 容器的参数

添加一行:- --providers.kubernetescrd.allowcrossnamespace=true,然后保存退出即可。

3. 创建ingressroute

我们在 kube-system 命名空间下创建一个名为 ingressroute 的公共资源,并引用同命名空间下的 secret:tls-cert,后续在这里配置所有域名的转发规则,在 routes 中按需添加 rule,如下:

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: ingressroute
  namespace: kube-system
spec:
  entryPoints:
  - websecure
  routes:
  - kind: Rule
    match: Host(`caddy.app.wbuntu.com`)
    services:
    - name: caddy
      namespace: app
      port: 80
  tls:
    secretName: tls-cert

上面的配置中 Host 为 caddy.app.wbuntu.com 的请求全部转发到 app 命名空间下的 caddy 服务。