【traefik】基于k8s搭建traefik, nginx与traefik共存

目录

1. 关于traefik

2. 关于nginx与trarfik的冲突

3. 搭建步骤

3.1 创建crd与rbac

3.2 启动traefik ingress controller

3.3 创建service

3.4 开放dashboard

3.5 配置api入口路由 Ingress

3.6 创建whoami服务

3.7 配置whoami的服务路由 IngressRoute


官方文档:Traefik Proxy Documentation - Traefik

1. 关于traefik

一种开源边缘路由器,支持:

  • 动态配置:自动检测和更新服务的变化,配置热更新
  • 服务发现:内置服务发现机制,自动检测集群中的服务变化,支持etcd、consul等多种
  • 负载均衡:可以根据服务的健康状况和流量情况,自动调整请求的分配
  • 原生兼容多种集群技术:Kubernetes、Docker、Docker Swarm、AWS、Mesos、Marathon

【traefik】基于k8s搭建traefik, nginx与traefik共存_第1张图片

2. 关于nginx与trarfik的冲突

背景:我们的 k8s 集群已存在一个nginx ingress controller,负责所有 namespace 路由的转发。希望在此基础上添加一个traefik,接管一部分服务的路由转发,即某一个ns由traefik管理,其他仍由nginx管理保持不变。

在没有nginx,仅traefik作为边缘路由的理想情况,期望的路由模式是:

  • traefik管理主机的80 443端口,接管所有入口请求
  • 定义好IngressRoute路由规则,将url rule与具体服务关系映射起来。比如 http://api.traefik/user/* 都转发到 user-api service 上
  • 用户发起请求时 curl http://api.traefik/user/xx,直接打到traefik上
  • traefik 根据已注册的 ingressroute 规则,将请求转发给具体svc,完成路由任务

【traefik】基于k8s搭建traefik, nginx与traefik共存_第2张图片

但是在我们的场景中,已经存在nginx在管理80 443来的所有请求了,和期望的traefik管理80 443冲突,那么有两种方案:

  • 更换traefik入口端口号,就可以解决端口冲突。问题:用户请求时需要携带端口号
  • 继续由nginx做入口,将请求转发给traefik,做两层转发。问题:转发链路变长

最终选择了第二种,两层转发的方式,即:

【traefik】基于k8s搭建traefik, nginx与traefik共存_第3张图片

3. 搭建步骤

3.1 创建crd与rbac

下面的过程是在做:

  • 安装traefik crd——这里的crd是traefik自定义的k8s资源类型,对k8s做了一些扩展操作
  • 创建一个ServiceAccount身份主体
  • 定义ClusterRole,一个全局授权对象,声明一组权限规则,包含对其他ns中ingress和service的访问权限
  • 定义一个ClusterRoleBinding,将将ClusterRole的权限绑定给ServiceAccount主体
  • 这样ServiceAccount这个身份主体就拥有足够权限了,以便后续的身份权限绑定

ok开始:

先从官网下载 crd.yml 与rbac.yml

我这里即将把 traefik 服务部署到 k8s ns=traefik 上,所以修改 rbac.yml 中 ClusterRoleBinding 下面的 ns 为 traefik:

【traefik】基于k8s搭建traefik, nginx与traefik共存_第4张图片

再自己定义一个serviceAccount.yml:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: traefik-ingress-controller
  namespace: traefik

准备好以上三个yml,就可以先创建出来了:

kubectl create ns traefik
kubectl apply -f crd.yml -f rbac.yml -f serviceAccount.yml

3.2 启动traefik ingress controller

ingress controller 负责解析 Ingress、IngressRoute 的反向代理规则,当它收到请求后就会根据规则将请求转发到对应的 Service。每种边缘路由都有自己的 ingress controller。

先准备 traefik 启动需要的配置文件 traefik.toml:

# traefik.toml

# 入口定义
[entryPoints]
  [entryPoints.http]
    address = ":80"
  [entryPoints.https]
    address = ":443"

# 日志设置
[log]
  level = "INFO"
[accessLog]

# 开启api和dashboard
[api]
  # 正式环境须为false
  insecure = true
  # 开启Dashboard, 将监听:8080
  dashboard = true

# 开启crd以做rbac授权
[providers.kubernetesCRD]

# 开启ingress处理
[providers.kubernetesIngress]

此toml文件是静态的,不会热更新,关于动态配置文件下一篇再聊。

然后就可以根据toml配置文件创建出configmap:

kubectl -n traefik create cm traefik-config --from-file=traefik.toml

再定义 traefik 的 deployment:

# deployment.yml 

kind: Deployment
apiVersion: apps/v1
metadata:
  name: traefik-ingress-controller
  namespace: traefik
  labels:
    app: traefik
spec:
  replicas: 1
  selector:
    matchLabels:
      app: traefik
  template:
    metadata:
      labels:
        app: traefik
    spec:
      serviceAccountName: traefik-ingress-controller  # 指定serviceAccount以获得其他ns的访问权限
      containers:
        - name: traefik-ingress-controller
          image: traefik:v2.11.0
          volumeMounts:
            - name: traefik-config
              mountPath: /etc/traefik/traefik.toml
              subPath: traefik.toml
          env:
            - name: TZ  # 顺便配个时区,方便看日志
              value: "Asia/Shanghai"
      volumes:
        - name: traefik-config  # 挂载配置文件
          configMap:
            name: traefik-config

推到k8s上: 

kubectl apply -f deployment.yml

然后检查以下 pod 状态是否正常,Running即可。

3.3 创建service

准备service.yml,开放 traefik 的端口给k8s集群:

# service.yml

apiVersion: v1
kind: Service
metadata:
  name: traefik-svc
  namespace: traefik
spec:
  selector:
    app: traefik
  type: ClusterIP
  ports:
    - name: http
      port: 80
      targetPort: 80
    - name: https
      port: 443
      targetPort: 443
    - name: admin
      port: 8080
      targetPort: 8080

3.4 开放dashboard

创建一个 ingress-dashboard.yml 以开放 dashboard:

# ingress-dashboard.yml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: traefik-dashboard
  namespace: traefik
spec:
  rules:
    - host: ui.traefik
      http:
        paths:
          - path: /dashboard
            pathType: Prefix
            backend:
              service:
                name: traefik-svc  # 对应svc name
                port:
                  number: 8080  # dashboard端口8080
kubectl apply -f service.yml -f ingress-dashboard.yml

可以访问控制台啦 http://ui.traefik/dashboard/ 说明我们配置成功~

【traefik】基于k8s搭建traefik, nginx与traefik共存_第5张图片

注意,这里创建的 ingress 是由 nginx ingress controller 接管的哦,请求直接到nginx,由nginx转发给traefik 8080端口。 

3.5 配置api入口路由 Ingress

上面我们仅仅开放了traefik的可视化页面,我们的最终目的是对所有api请求进行管理,还需要再配置api的规则。

api的入口规则定义是Ingress类型,与dashboard类似,也就是第一层转发的nginx入口路由:

# ingress-api.yml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: traefik-api
  namespace: traefik
spec:
  rules:
    - host: api.traefik
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: traefik-svc
                port:
                  number: 80
kubectl apply -f ingress-api.yml

3.6 创建whoami服务

我们先创建一个测试服务 whoami 作为业务服务:

# whoami.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: whoami
  namespace: apps
spec:
  selector:
    matchLabels:
      run: whoami
  replicas: 2
  template:
    metadata:
      labels:
        run: whoami
    spec:
      containers:
      - name: whoami
        image: containous/whoami
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: whoami
  namespace: apps
  labels:
    run: whoami
spec:
  selector:
    run: whoami
  type: ClusterIP
  ports:
   - port: 80
     targetPort: 80
kubectl apply -f whoami.yml

3.7 配置whoami的服务路由 IngressRoute

为 treafik 定义这个服务的 ingressroute 路由规则,这是第二层路由:

# ingressroute.yml

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: traefik-route
  namespace: apps
  labels:
    run: whoami
spec:
  entryPoints:
    - http
  routes:
    - match: Host(`api.traefik`) && PathPrefix(`/whoami`)
      kind: Rule
      services:
        - name: whoami
          port: 80
kubectl apply -f ingressroute.yml

大功告成,来验证一下:

curl http://api.traefik/whoami/test

正常请求即为成功~

可以看到traefik有日志输出:

[02/May/2024:16:29:52 +0000] "GET /whoami/test HTTP/1.1" 200 400 "-" "-" 13 "apps-traefik-route-282ee8b04349ccb17131@kubernetescrd" "http://10.244.0.9:80" 0ms

你可能感兴趣的:(网关与代理,kubernetes,容器,云原生,docker)