目录
3.2 启动traefik ingress controller
3.7 配置whoami的服务路由 IngressRoute
1. 关于traefik
一种开源边缘路由器,支持:
- 动态配置:自动检测和更新服务的变化,配置热更新
- 服务发现:内置服务发现机制,自动检测集群中的服务变化,支持etcd、consul等多种
- 负载均衡:可以根据服务的健康状况和流量情况,自动调整请求的分配
- 原生兼容多种集群技术:Kubernetes、Docker、Docker Swarm、AWS、Mesos、Marathon
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,完成路由任务
但是在我们的场景中,已经存在nginx在管理80 443来的所有请求了,和期望的traefik管理80 443冲突,那么有两种方案:
- 更换traefik入口端口号,就可以解决端口冲突。问题:用户请求时需要携带端口号
- 继续由nginx做入口,将请求转发给traefik,做两层转发。问题:转发链路变长
最终选择了第二种,两层转发的方式,即:
3. 搭建步骤
3.1 创建crd与rbac
下面的过程是在做:
- 安装traefik crd——这里的crd是traefik自定义的k8s资源类型,对k8s做了一些扩展操作
- 创建一个ServiceAccount身份主体
- 定义ClusterRole,一个全局授权对象,声明一组权限规则,包含对其他ns中ingress和service的访问权限
- 定义一个ClusterRoleBinding,将将ClusterRole的权限绑定给ServiceAccount主体
- 这样ServiceAccount这个身份主体就拥有足够权限了,以便后续的身份权限绑定
ok开始:
我这里即将把 traefik 服务部署到 k8s ns=traefik 上,所以修改 rbac.yml 中 ClusterRoleBinding 下面的 ns 为 traefik:
再自己定义一个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/ 说明我们配置成功~
注意,这里创建的 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