Traefik 基础概念说明

Traefik 是一个 开源 的边缘路由器,使发布服务变得有趣而轻松,是你整个平台的大门,拦截并匹配每一个传入的请求:它掌管着所有的匹配逻辑和路由规则,这些规则确定哪些服务处理哪些请求;传统的反向代理需要一个配置文件,其中包含路由到你服务的所有可能路由,而 Traefik 会实时检测服务并自动更新路由规则,并且可以 自动服务发现功能。

traefik-architecture

当启动 Traefik 时,需要定义 entrypoints(即入口点),然后,根据连接到这些 entrypoints 的 路由 来分析传入的请求,来查看他们是否与一组 规则 相匹配,如果匹配,则路由可能会将请求通过一系列 中间件 处理过后再转发到你的 服务上去。在了解 Traefik 之前有几个核心概念我们必须要了解:

  • Providers 用来自动发现平台上的服务,可以是编排工具、容器引擎或者 key-value 存储等,比如 Docker、Kubernetes、File
  • Entrypoints 监听传入的流量(端口等…),是网络入口点,它们定义了接收请求的端口(HTTP 或者 TCP)。
  • Routers 分析请求(host, path, headers, SSL, …),负责将传入请求连接到可以处理这些请求的服务上去。
  • Services 将请求转发给你的应用(load balancing, …),负责配置如何获取最终将处理传入请求的实际服务。
  • Middlewares 中间件,用来修改请求或者根据请求来做出一些判断(authentication, rate limiting, headers, …),中间件被附件到路由上,是一种在请求发送到你的服务之前(或者在服务的响应发送到客户端之前)调整请求的一种方法。

演示环境说明

  • Helm: v3.4.2

    • helm 自动补全

      1
      2
      3
      
      helm completion bash
      helm completion fish
      helm completion zsh
      
  • Traefik: v2.3.6

  • 操作系统: CentOS Linux release 7.9.2009

  • Kubernetes: v1.19.6

    • Master01: 192.168.8.70
    • Node01: 192.168.8.71
    • Node02: 192.168.8.72
    • Node03: 192.168.8.73

部署

演示使用 helm 在 kubernetes 中部署

1
2
3
4
5
git clone https://github.com/traefik/traefik-helm-chart
 
cd traefik-helm-chart 
 
helm show values ./traefik/  # 显示默认的 helm values.yaml 渲染配置

创建部署配置文件, 将默认配置覆盖

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
cat > prod-values.yaml << EOF
ingressRoute:
  dashboard:
    enabled: false  # 关闭渲染 dashboard,改用手动创建

# Configure ports
ports:
  web:
    port: 8000
    hostPort: 80  # 使用 hostport 模式
  websecure:
    port: 8443
    hostPort: 443  # 使用 hostport 模式

service:  
  enabled: false  # 改用 hostpath 模式后,service 渲染可取消

logs:
  general:
    level: ERROR # 设置日志级别,建议

tolerations:   
- key: "node-role.kubernetes.io/master"
  operator: "Equal"
  effect: "NoSchedule"  # 容忍污点

nodeSelector:   # 节点亲和,固定到标签 master01 节点上
  kubernetes.io/hostname: "master01"
EOF

查看完helm 部署文件后,使用命令将其部署

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
kubectl create ns traefik

cd traefik-helm-chart 

helm upgrade --install traefik -n traefik -f ./prod-values.yaml ./traefik/


$ watch kubectl get pod -n traefik   # 等待 pod 启动完成
NAME                      READY   STATUS    RESTARTS   AGE
traefik-84879ffbd-6kwv5   1/1     Running   0          68s

启动完成后,测试 curl 一下我们绑定的节点的 80 端口, 显示 404 page not found 即为正常。

image-20210117110937322

暴露 traefik dashboard

因默认的 dashboard,未做任何加密处理,我这里将使用 BasicAuth 中间件来做一层 用户认证 处理

使用 htpasswd 生成用户及密码

这里生成的密钥,因还需要在 kubernetes 中作为资源对象来使用,我们还需要进行一下 ` base64 编码

1
2
3
4
yum install httpd-tools -y

htpasswd -nb admin 123456 |base64  # 生成用户密码信息,并转换为 base64
YWRtaW46JGFwcjEkYVVsUERZT2IkdEREYXUzZDN6dnowb3A2TnJNbzZDMQoK

创建资源部署清单文件

如需复制 粘贴执行,注意下面终端执行 示例中的 \ 转义符号。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
cat > authsecret-dashboard.yaml << EOF
apiVersion: v1
kind: Secret
metadata:
  name: authsecret
  namespace: traefik 
data:
  users: YWRtaW46JGFwcjEkYVVsUERZT2IkdEREYXUzZDN6dnowb3A2TnJNbzZDMQoK  
  
---
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
  name: dashboard-auth
  namespace: traefik
spec:
  basicAuth:
    secret: authsecret
    removeHeader: true
    
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: traefik-dashboard
  namespace: traefik
spec:
  entryPoints:
  - web
  routes:
  - match: Host(\`traefik.coderyzun.cyou\`)  
    kind: Rule
    services:
    - name: api@internal  # 内置资源
      kind: TraefikService 
    middlewares: 
    - name: dashboard-auth
EOF
1
kubectl apply -f authsecret-dashboard.yaml

设置域名解析

image-20210117114010165

image-20210117114623277

中间件测试

参考文档

原生中间件

Headers

headers

创建容器示例,并创建 service 资源

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
  name: v1
spec:
  ports:
    - protocol: TCP
      name: web
      port: 80
  selector:
    app: v1

---
kind: Deployment
apiVersion: apps/v1
metadata:
  name: v1
  labels:
    app: v1
spec:
  selector:
    matchLabels:
      app: v1
  template:
    metadata:
      labels:
        app: v1
    spec:
      containers:
        - name: v1
          image: containous/whoami
          ports:
            - name: web
              containerPort: 80
EOF

创建 header-middleware.yaml Middleware 资源清单

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
cat <<EOF | kubectl apply -f -
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
  name: header-v1
spec:
  headers:
    customRequestHeaders:
      X-Script-Name: "test"
    customResponseHeaders:
      X-Custom-Response-Header: "value"

---
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
  name: header-v2
spec:
  headers:
    customRequestHeaders:
      X-Script-Name: "" # Adds
    customResponseHeaders:
      X-Custom-Response-Header: "" # Removes
EOF
1
kubectl apply -f header-middleware.yaml

创建 Routers 资源清单

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
cat <<EOF | kubectl apply -f -
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: apps-header
  namespace: default
spec:
  entryPoints:
    - web
  routes:
  - match: Host(\`traefik.coderyzun.cyou\`) && PathPrefix(\`/header\`)
    kind: Rule
    services:
    - name: v1
      port: 80
    middlewares:
    - name: header-v1  
EOF

image-20210117172109153

IPWhiteList

ipwhitelist

只允许 192.168.8.153,可访问

image-20210117171701017

创建 Middleware 资源清单

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
cat << EOF | kubectl apply -f -
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
  name: ipwhitelist
spec:
  ipWhiteList:
    sourceRange:
      - 192.168.8.153
EOF

创建 routes 清单

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
cat <<EOF | kubectl apply -f -
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: apps-ipwhitelist
spec:
  entryPoints:
    - web
  routes:
  - match: Host(\`traefik.coderyzun.cyou\`) && PathPrefix(\`/ipwhitelist\`)
    kind: Rule
    services:
    - name: v1
      port: 80
    middlewares:
    - name: ipwhitelist 
EOF

image-20210117175431908

其他主机 执行 curl

image-20210117175457262

RedirectRegex

创建 v2 , deployment 和 service 资源清单

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
  name: v2
spec:
  ports:
    - protocol: TCP
      name: web
      port: 80
  selector:
    app: v2

---
kind: Deployment
apiVersion: apps/v1
metadata:
  name: v2
  labels:
    app: v2
spec:
  selector:
    matchLabels:
      app: v2
  template:
    metadata:
      labels:
        app: v2
    spec:
      containers:
        - name: v2
          image: containous/whoami
          ports:
            - name: web
              containerPort: 80
EOF

image-20210117180923331

创建 Middleware 资源清单

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
cat <<EOF | kubectl apply -f -
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
  name: redirectregex
spec:
  redirectRegex:
    regex: ^http://traefik.coderyzun.cyou/redirectregex/v1/(.*)
    replacement: http://traefik.coderyzun.cyou/redirectregex/v2/\${1}
    permanent: true   # open permanent redirection 
EOF

创建 routes 清单

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
cat <<EOF | kubectl apply -f -
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: redirectregex-appv1
  namespace: default
spec:
  entryPoints:
    - web
  routes:
  - match: Host(\`traefik.coderyzun.cyou\`) && PathPrefix(\`/redirectregex/v1\`)
    kind: Rule
    services:
    - name: v1
      port: 80
    middlewares:
    - name: redirectregex
  - match: Host(\`traefik.coderyzun.cyou\`) && PathPrefix(\`/redirectregex/v2\`)
    kind: Rule
    services:
    - name: v2
      port: 80
EOF

image-20210117180938144

测试

1
curl -I http://traefik.coderyzun.cyou/redirectregex/v1/1

image-20210117181500974