1 traefik核心概念
Traefik是一个为了让部署微服务更加便捷而诞生的现代HTTP反向代理、负载均衡工具。 它支持多种后台 (Docker, Swarm, Kubernetes, Marathon, Mesos, Consul, Etcd, Zookeeper, BoltDB, Rest API, file…) 来自动化、动态的应用它的配置文件设置。
1.1 traefik核心组件
Providers: 用来自动发现平台上的服务,可以是编排工具、容器引擎或者 key-value 存储等,比如 Docker、Kubernetes、File Entrypoints: 监听传入的流量(端口等…),是网络入口点,它们定义了接收请求的端口(HTTP 或者 TCP)。 Routers: 分析请求(host, path, headers, SSL, …),负责将传入请求连接到可以处理这些请求的服务上去。 Services: 将请求转发给你的应用(load balancing, …),负责配置如何获取最终将处理传入请求的实际服务。 Middlewares: 中间件,用来修改请求或者根据请求来做出一些判断(authentication, rate limiting, headers, …),中间件被附件到路由上,是一种在请求发送到你的服务之前(或者在服务的响应发送到客户端之前)调整请求的一种方法。 Traefik v2.4中增加了对 Kubernetes Gateway API 的支持、那么什么是 Kubernetes Gateway API 呢?Gateway API 是由 SIG-NETWORK 社区管理的一个开源项目;该项目的目标是在 Kubernetes 生态系统内发展服务网络 API;网关 API 提供了用于暴露 Kubernetes 应用程序的 Service、Ingress 等。Gateway API 旨在通过提供可表达的,可扩展的,面向角色的接口来改善服务网络,这些接口已由许多供应商实施并获得了广泛的行业支持;网关 API 是 API 资源(服务、网关类、网关、HTTPRoute、TCPRoute等)的集合、这些资源共同为各种网络用例建模。其实 Traefik 除了支持我们手动配置 TLS 证书之外,还支持自动生成 TLS 证书
1.2 Nginx-Ingress和traefik区别
k8s 是通过一个又一个的 controller 来负责监控、维护集群状态。Ingress Controller 就是监控 Ingress 路由规则的一个变化,然后跟 k8s 的资源操作入口 api-server 进行通信交互。K8s 并没有自带 Ingress Controller,它只是一种标准,具体实现有多种,需要自己单独安装,常用的是 Nginx Ingress Controller 和 Traefik Ingress Controller。 Ingress Controller 收到请求,匹配 Ingress 转发规则,匹配到了就转发到后端 Service,而 Service 可能代表的后端 Pod 有多个,选出一个转发到那个 Pod,最终由那个 Pod 处理请求。
- traefik优点
速度快
不需要安装其他依赖,使用 GO 语言编译可执行文件
支持最小化官方 Docker 镜像
支持多种后台,如 Docker, Swarm mode, Kubernetes, Marathon, Consul, Etcd, Rancher, Amazon ECS 等等
支持 REST API
配置文件热重载,不需要重启进程
支持自动熔断功能
支持轮训、负载均衡
提供简洁的 UI 界面
支持 Websocket, HTTP/2, GRPC
自动更新 HTTPS 证书
支持高可用集群模式
- Nginx和Traefik横向对比
Nginx Ingress | Traefik ingress | |
---|---|---|
协议 | http/https、http2、grpc、tcp/udp | http/https、http2、grpc、tcp、tcp+tls |
路由匹配 | host、path | host、path、headers、query、path prefix、method |
命名空间支持 | - | 共用或指定命名空间 |
部署策略 | - | 金丝雀部署、蓝绿部署、灰度部署 |
upstream探测 | 重试、超时、心跳探测 | 重试、超时、心跳探测、熔断 |
负载均衡算法 | RR、会话保持、最小连接、最短时间、一致性hash | WRR、动态RR、会话保持 |
优点 | 简单易用,易接入 | 部署容易,支持众多的后端,内置WebUI |
缺点 | 没有解决nginx reload,插件多,但是扩展性能查差 | 这么一看好像没啥缺点 |
2 部署traefik
2.1 创建 CRD 资源
在Traefik v2.0版本后,开始使用 CRD(Custom Resource Definition)来完成路由配置等,所以需要提前创建CRD资源。 - crd资源清单
[root@tech04 2.4]# cat traefik-crd.yaml
## IngressRoute
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: ingressroutes.traefik.containo.us
spec:
scope: Namespaced
group: traefik.containo.us
version: v1alpha1
names:
kind: IngressRoute
plural: ingressroutes
singular: ingressroute
---
## IngressRouteTCP
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: ingressroutetcps.traefik.containo.us
spec:
scope: Namespaced
group: traefik.containo.us
version: v1alpha1
names:
kind: IngressRouteTCP
plural: ingressroutetcps
singular: ingressroutetcp
---
## Middleware
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: middlewares.traefik.containo.us
spec:
scope: Namespaced
group: traefik.containo.us
version: v1alpha1
names:
kind: Middleware
plural: middlewares
singular: middleware
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: tlsoptions.traefik.containo.us
spec:
scope: Namespaced
group: traefik.containo.us
version: v1alpha1
names:
kind: TLSOption
plural: tlsoptions
singular: tlsoption
---
## TraefikService
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: traefikservices.traefik.containo.us
spec:
scope: Namespaced
group: traefik.containo.us
version: v1alpha1
names:
kind: TraefikService
plural: traefikservices
singular: traefikservice
---
## TraefikTLSStore
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: tlsstores.traefik.containo.us
spec:
scope: Namespaced
group: traefik.containo.us
version: v1alpha1
names:
kind: TLSStore
plural: tlsstores
singular: tlsstore
---
## IngressRouteUDP
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: ingressrouteudps.traefik.containo.us
spec:
scope: Namespaced
group: traefik.containo.us
version: v1alpha1
names:
kind: IngressRouteUDP
plural: ingressrouteudps
singular: ingressrouteudp
- 创建RBAC权限
# cat traefik-rbac.yaml
## ServiceAccount
apiVersion: v1
kind: ServiceAccount
metadata:
namespace: kube-system
name: traefik-ingress-controller
---
## ClusterRole
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: traefik-ingress-controller
rules:
- apiGroups:
- ""
resources:
- services
- endpoints
- secrets
verbs:
- get
- list
- watch
- apiGroups:
- extensions
- networking.k8s.io
resources:
- ingresses
- ingressclasses
verbs:
- get
- list
- watch
- apiGroups:
- extensions
- networking.k8s.io
resources:
- ingresses/status
verbs:
- update
- apiGroups:
- traefik.containo.us
resources:
- ingressroutes
- ingressroutetcps
- ingressrouteudps
- middlewares
- tlsoptions
- tlsstores
- traefikservices
- serverstransports
verbs:
- get
- list
- watch
- apiGroups:
- networking.x-k8s.io
resources:
- gatewayclasses
- gatewayclasses/status
- gateways
verbs:
- get
- list
- watch
- apiGroups:
- networking.x-k8s.io
resources:
- gatewayclasses/status
verbs:
- get
- patch
- update
- apiGroups:
- networking.x-k8s.io
resources:
- gateways/status
verbs:
- get
- patch
- update
- apiGroups:
- networking.x-k8s.io
resources:
- httproutes
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- networking.x-k8s.io
resources:
- httproutes/status
verbs:
- get
- patch
- update
---
## ClusterRoleBinding
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: traefik-ingress-controller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: traefik-ingress-controller
subjects:
- kind: ServiceAccount
name: traefik-ingress-controller
namespace: kube-system
- 创建 Traefik CRD ,rbac资源
kubectl apply -f traefik-crd.yaml
kubectl apply -f traefik-rbac.yaml
2.2 创建Traefik配置文件
下面配置中可以通过配置kubernetesCRD与kubernetesIngress和kubernetesGateway三项参数,让 Traefik 支持 CRD、Ingress与kubernetesGateway三种路由配置方式。
[root@tech04 2.4]# cat traefik-config.yaml
kind: ConfigMap
apiVersion: v1
metadata:
name: traefik-config
namespace: kube-system
data:
traefik.yaml: |-
ping: "" ## 启用 Ping
serversTransport:
insecureSkipVerify: true ## Traefik 忽略验证代理服务的 TLS 证书
api:
insecure: true ## 允许 HTTP 方式访问 API
dashboard: true ## 启用 Dashboard
debug: false ## 启用 Debug 调试模式
metrics:
prometheus: "" ## 配置 Prometheus 监控指标数据,并使用默认配置
entryPoints:
web:
address: ":80" ## 配置 80 端口,并设置入口名称为 web
websecure:
address: ":443" ## 配置 443 端口,并设置入口名称为 websecure
providers:
kubernetesCRD: "" ## 启用 Kubernetes CRD 方式来配置路由规则
kubernetesIngress: "" ## 启用 Kubernetes Ingress 方式来配置路由规则
kubernetesGateway: "" ## 启用 Kubernetes Gateway API
experimental:
kubernetesGateway: true ## 允许使用 Kubernetes Gateway API
log:
filePath: "" ## 设置调试日志文件存储路径,如果为空则输出到控制台
level: error ## 设置调试日志级别
format: json ## 设置调试日志格式
accessLog:
filePath: "" ## 设置访问日志文件存储路径,如果为空则输出到控制台
format: json ## 设置访问调试日志格式
bufferingSize: 0 ## 设置访问日志缓存行数
filters:
#statusCodes: ["200"] ## 设置只保留指定状态码范围内的访问日志
retryAttempts: true ## 设置代理访问重试失败时,保留访问日志
minDuration: 20 ## 设置保留请求时间超过指定持续时间的访问日志
fields: ## 设置访问日志中的字段是否保留(keep 保留、drop 不保留)
defaultMode: keep ## 设置默认保留访问日志字段
names: ## 针对访问日志特别字段特别配置保留模式
ClientUsername: drop
headers: ## 设置 Header 中字段是否保留
defaultMode: keep ## 设置默认保留 Header 中字段
names: ## 针对 Header 中特别字段特别配置保留模式
User-Agent: redact
Authorization: drop
Content-Type: keep
#tracing: ## 链路追踪配置,支持 zipkin、datadog、jaeger、instana、haystack 等
# serviceName: ## 设置服务名称(在链路追踪端收集后显示的服务名)
# zipkin: ## zipkin配置
# sameSpan: true ## 是否启用 Zipkin SameSpan RPC 类型追踪方式
# id128Bit: true ## 是否启用 Zipkin 128bit 的跟踪 ID
# sampleRate: 0.1 ## 设置链路日志采样率(可以配置0.0到1.0之间的值)
# httpEndpoint: http://localhost:9411/api/v2/spans ## 配置 Zipkin Server 端点
kubectl apply -f traefik-config.yaml
configmap/traefik-config created
2.3 设置节点Label标签
节点设置 Label 标签
kubectl label nodes tech04 IngressProxy=true
kubectl label nodes tech05 IngressProxy=true
kubectl label nodes tech06 IngressProxy=true
查看节点是否设置 Label 成功
[root@tech04 2.4]# kubectl get nodes --show-labels
NAME STATUS ROLES AGE VERSION LABELS
tech04 Ready control-plane,master 45d v1.20.9 IngressProxy=true,beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=tech04,kubernetes.io/os=linux,n
ode-role.kubernetes.io/control-plane=,node-role.kubernetes.io/master=
tech05 Ready <none> 45d v1.20.9 IngressProxy=true,beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=tech05,kubernetes.io/os=linux
tech06 Ready <none> 45d v1.20.9 IngressProxy=true,beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=tech06,kubernetes.io/os=linux
删除标签
kubectl label nodes tech04 IngressProxy-
2.4 安装Kubernetes Gateway CRD资源
Kubernetes 集群上默认没有安装 Service APIs,我们需要提前安装 Gateway API 的 CRD 资源,需要确保在 Traefik 安装之前启用 Service APIs 资源。
kubectl apply -k "github.com/kubernetes-sigs/service-apis/config/crd?ref=v0.1.0"
2.5 创建Traefik
apiVersion: v1
kind: Service
metadata:
name: traefik
namespace: kube-system
labels:
app: traefik
spec:
ports:
- name: web
port: 80
- name: websecure
port: 443
- name: admin
port: 8080
selector:
app: traefik
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: traefik-ingress-controller
namespace: kube-system
labels:
app: traefik
spec:
selector:
matchLabels:
app: traefik
template:
metadata:
name: traefik
labels:
app: traefik
spec:
serviceAccountName: traefik-ingress-controller
terminationGracePeriodSeconds: 1
containers:
- image: traefik:v2.4.13
name: traefik-ingress-lb
ports:
- name: web
containerPort: 80
hostPort: 80 ## 将容器端口绑定所在服务器的 80 端口
- name: websecure
containerPort: 443
hostPort: 443 ## 将容器端口绑定所在服务器的 443 端口
- name: admin
containerPort: 8080 ## Traefik Dashboard 端口
resources:
limits:
cpu: 2000m
memory: 1024Mi
requests:
cpu: 1000m
memory: 1024Mi
securityContext:
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE
args:
- --configfile=/config/traefik.yaml
volumeMounts:
- mountPath: "/config"
name: "config"
readinessProbe:
httpGet:
path: /ping
port: 8080
failureThreshold: 3
initialDelaySeconds: 10
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 5
livenessProbe:
httpGet:
path: /ping
port: 8080
failureThreshold: 3
initialDelaySeconds: 10
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 5
volumes:
- name: config
configMap:
name: traefik-config
tolerations: ## 设置容忍所有污点,防止节点被设置污点
- operator: "Exists"
nodeSelector: ## 设置node筛选器,在特定label的节点上启动
IngressProxy: "true"
创建 Traefik
kubectl apply -f traefik-deploy.yaml
2.6 创建 Traefik Ingress 路由规则
[root@tech04 2.4]# cat traefik-dashboard-in.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: traefik-dashboard-ingress
namespace: kube-system
annotations:
kubernetes.io/ingress.class: traefik
traefik.ingress.kubernetes.io/router.entrypoints: web
spec:
rules:
- host: traefik.unionpaysmart.com
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: traefik
port:
number: 8080
[root@tech04 2.4]# kubectl apply -f traefik-dashboard-in.yaml -n kube-system
ingress.networking.k8s.io/traefik-dashboard-ingress created
访问traefik界面验证
2.7 使用CRD方式配置Traefik路由规则
cat traefik-dashboard-route.yaml
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: traefik-dashboard-route
namespace: kube-system
spec:
entryPoints:
- web
routes:
- match: Host(`traefik-test.devopstack.cn`)
kind: Rule
services:
- name: traefik
port: 8080
验证
kubectl get ingressroutes.traefik.containo.us -n kube-system
NAME AGE
traefik-dashboard-route 5m8s
2.8 使用Kubernetes Gateway API
在Traefik v2.4版本后支持Kubernetes Gateway API提供的CRD方式创建路由规则. GatewayClass: GatewayClass 是基础结构提供程序定义的群集范围的资源。此资源表示可以实例化的网关类。一般该资源是用于支持多个基础设施提供商用途的,这里我们只部署一个即可。 Gateway: Gateway 与基础设施配置的生命周期是 1:1。当用户创建网关时,GatewayClass 控制器会提供或配置一些负载平衡基础设施。 HTTPRoute: HTTPRoute 是一种网关 API 类型,用于指定 HTTP 请求从网关侦听器到 API 对象(即服务)的路由行为。
2.8.1 创建GatewayClass
[root@tech04 Gateway]# cat kubernetes-gatewayclass.yaml
apiVersion: networking.x-k8s.io/v1alpha1
kind: GatewayClass
metadata:
name: traefik
spec:
controller: traefik.io/gateway-controller
2.8.2 配置HTTP路由规则
创建Gateway资源
cat http-gateway.yaml
apiVersion: networking.x-k8s.io/v1alpha1
kind: Gateway
metadata:
name: http-gateway
namespace: kube-system
spec:
gatewayClassName: traefik
listeners:
- protocol: HTTP
port: 80
routes:
kind: HTTPRoute
namespaces:
from: All
selector:
matchLabels:
app: traefik
创建 HTTPRoute 资源
cat traefik-httproute.yaml
apiVersion: networking.x-k8s.io/v1alpha1
kind: HTTPRoute
metadata:
name: traefik-dashboard-httproute
namespace: kube-system
labels:
app: traefik
spec:
hostnames:
- "traefik.devopstack.cn"
rules:
- matches:
- path:
type: Prefix
value: /
forwardTo:
- serviceName: traefik
port: 8080
weight: 1
创建资源
[root@tech04 Gateway]# kubectl apply -f http-gateway.yaml
gateway.networking.x-k8s.io/http-gateway created
[root@tech04 Gateway]# kubectl apply -f traefik-httproute.yaml
httproute.networking.x-k8s.io/traefik-dashboard-httproute created
kubectl get httproutes.networking.x-k8s.io -n kube-system
NAME HOSTNAMES
traefik-dashboard-httproute ["traefik.devopstack.cn"]
访问验证
2.8.3 配置HTTPS路由规则(Kubernetes traefik dashboard为例)
创建私有证书 tls.key、tls.crt 文件
创建自签名证书
[root@tech04 Gateway]# openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=traefik.devopstack.cn"
将证书存储到 Kubernetes Secret 中
[root@tech04 Gateway]# kubectl create secret generic my-traefik-tls --from-file=tls.crt --from-file=tls.key -n kube-system
创建 Gateway
cat https-gateway.yaml
kind: Gateway
metadata:
name: https-gateway
namespace: kube-system
spec:
gatewayClassName: traefik
listeners:
- protocol: HTTPS
port: 443
hostname: traefik.devopstack.cn
tls:
certificateRef:
kind: Secret
group: core
name: my-traefik-tls
routeOverride:
certificate: Deny
routes:
kind: HTTPRoute
namespaces:
from: All
selector:
matchLabels:
app: traefik
创建 HTTPRoute
cat traefik-httpsroute.yaml
apiVersion: networking.x-k8s.io/v1alpha1
kind: HTTPRoute
metadata:
name: kubernetes-dashboard-httproute
namespace: kube-system
labels:
app: traefik
spec:
hostnames:
- "traefik.devopstack.cn"
rules:
- matches:
- path:
type: Prefix
value: /
forwardTo:
- serviceName: traefik
port: 8080
weight: 1
创建资源
[root@tech04 Gateway]# kubectl apply -f https-gateway.yaml
gateway.networking.x-k8s.io/https-gateway created
[root@tech04 Gateway]# kubectl apply -f traefik-httpsroute.yaml
httproute.networking.x-k8s.io/kubernetes-dashboard-httproute created
验证
[root@tech04 Gateway]# kubectl get gateways.networking.x-k8s.io -n kube-system
NAME CLASS
https-gateway traefik
[root@tech04 Gateway]# kubectl get httproutes.networking.x-k8s.io -n kube-system
NAME HOSTNAMES
kubernetes-dashboard-httproute ["traefik.devopstack.cn"]
浏览器访问
2.9 中间件的使用
什么是Traefik Middlewares中间件 中间件是 Traefik2.0 中一个非常有特色的功能,可以根据自己的各种需求去选择不同的中间件来满足服务,Traefik 官方已经内置了许多不同功能的中间件,其中一些可以修改请求,头信息,一些负责重定向,一些添加身份验证等等,而且中间件还可以通过链式组合的方式来适用各种情况。 Traefik Middlewares支持的功能如下 重试、压缩、缓冲、断路器 header 管理、错误页、中间件链 服务限流、同一主机并发请求限制 基本认证、IP 白名单、摘要认证、转发鉴权验证 regex 请求重定向、scheme 请求重定向、请求 URL 替换、regex 请求 URL 替换、删除 URL 前缀、regex 删除 URL 前缀、添加 URL 前缀
2.9.1 通过Middleware配置http强制跳转https
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: redirect-https
spec:
redirectScheme:
scheme: https
cat traefik-httproute-crd.yaml
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: traefik-dashboard-route
namespace: kube-system
spec:
entryPoints:
- web
routes:
- match: Host(`traefik.devopstack.cn`)
kind: Rule
services:
- name: traefik
port: 8080
middlewares:
- name: redirect-https
验证
[root@tech04 2.4]# kubectl get middlewares.traefik.containo.us -n kube-system
NAME AGE
redirect-https 18m
2.9.2 去除请求路径前缀中间件
例如,有一个路由规则中配置的域名路径为 “{host}/one”,traefik 进行路由规则进行流量转发时,也会带上这个前缀作为相对路径发送到后端服务中,而对后端服务来说,一般都是以 “/” 根路径作为相对路径的,如果带上这个路径到后端服务中,那么后端服务则变成以 “/one” 作为相对路径,显然,这样会导致状态码 404 错误。所以,很多时候我们需要去掉这个前缀。
使用去除前缀中间件去除前缀,方便配置一个域名多个二级路径这种需求,中间件写法如下:
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: test-stripprefix
spec:
stripPrefix:
prefixes:
- /one
2.9.3 转发鉴权验证中间件
在 traefik 中支持简单的第三方鉴权,当访问某个服务路由规则匹配后,则可以使用该转发鉴权验证中间件将请求转发到第三方服务进行鉴权。当第三方鉴权服务返回 Http 200 状态码 traeifk 则认为有权限访问后续服务,不拦截。如果鉴权服务返回非 200 状态码 traefik 认为无权访问,进行拦截。这种中间件的写法如下:
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: test-auth
spec:
forwardAuth:
address: https://example.com/auth
trustForwardHeader: true
注释:
address:将权限鉴定转发到第三方进行验证,设置转发的地址。
trustForwardHeader:信任全部 X-Forwarded-* headers 信息。
实例:
创建转发鉴权中间件
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: authentication-middleware ##设置中间件名称
namespace: mydlqcloud ##指定 Namespace
spec:
forwardAuth:
address: "http://auth-service/auth"
trustForwardHeader: true
(2)、创建路由规则并使用中间件
CRD 方式:
## IngressRoute
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: test-route
namespace: mydlqcloud
spec:
entryPoints:
- web
routes:
- match: Host(`demo.devopstack.cn`) && PathPrefix(`/foo`)
kind: Rule
services:
- name: test-service
port: 80
middlewares:
- name: authentication-middleware
Ingress 方式:
## IngressRoute
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test-ingress
namespace: mydlqcloud
annotations:
kubernetes.io/ingress.class: traefik
traefik.ingress.kubernetes.io/router.entrypoints: web
traefik.ingress.kubernetes.io/router.middlewares: mydlqcloud-authentication-middleware@kubernetescrd
spec:
rules:
- host: demo.devopstack.cn
http:
paths:
- path: /foo
backend:
serviceName: test-service
servicePort: 80
2.9.4 Traefik路由规则中使用多个Traefik Middlewares
1、创建转发鉴权与去除前缀中间件
## Middleware1
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: authentication-middleware ##设置中间件名称
namespace: mydlqcloud ##指定 Namespace
spec:
forwardAuth:
address: "http://auth-service/auth"
trustForwardHeader: true
---
## Middleware2
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: regex-stripprefix-middleware
namespace: mydlqcloud
spec:
stripPrefixRegex:
regex:
- ^/[a-zA-Z0-9-]+ ##设置正则表达式
2、创建路由规则并使用中间件
CRD 方式:
## IngressRoute
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: test-route
namespace: mydlqcloud ##指定 Namespace
spec:
entryPoints:
- web
routes:
- match: Host(`demo.devopstack.cn`) && PathPrefix(`/foo`)
kind: Rule
services:
- name: test-service
port: 80
middlewares:
- name: authentication-middleware ##指定使用的中间件1
- name: regex-stripprefix-middleware ##指定使用的中间件2
Ingress 方式:
## IngressRoute
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test-ingress
namespace: mydlqcloud ##指定 Namespace
annotations:
kubernetes.io/ingress.class: traefik
traefik.ingress.kubernetes.io/router.entrypoints: web
##指定使用的 Middleware,规则是 {namespace名称}-{middleware名称}@{资源类型},如果使用多个中间件,则逗号隔开
traefik.ingress.kubernetes.io/router.middlewares: mydlqcloud-authentication-middleware@kubernetescrd,mydlqcloud-regex-stripprefix-middleware@kubernetescrd
spec:
rules:
- host: demo.devopstack.cn
http:
paths:
- path: /foo
backend:
serviceName: test-service
servicePort: 80
参考文档:
https://doc.traefik.io/traefik/middlewares
2.9.5 ip白名单
apiVersion: traefik.containo.us/v1alpha1
kind: MiddlewareTCP
metadata:
name: test-ipwhitelist
spec:
ipWhiteList:
sourceRange:
- 127.0.0.1/32
- 192.168.1.7
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: test-ipwhitelist
spec:
ipWhiteList:
sourceRange:
- 127.0.0.1/32
- 192.168.1.7
3 基于traefik的灰度发布
Traefik2.0的一个更强大的功能就是灰度发布,灰度发布我们有时候也会称为金丝雀发布(Canary),主要就是让一部分测试的服务也参与到线上去,经过测试观察看是否符号上线要求。 我们需要创建两组pod,我们希望通过Traefik来控制我们的流量,将3⁄4的流量路由到appv1,1/4 的流量路由到appv2去,这个时候就可以利用Traefik2.0中提供的带权重的轮询(WRR)来实现该功能
实例演示
需要创建两组pod,然后通过Traefik来控制我们的流量,将3⁄4的流量路由到appv1,1/4的流量路由到 appv2,这个时候就可以利用Traefik中提供的带权重的轮询(WRR)来实现该功能,首先在 Kubernetes集群中部署上面的两个服务。为了对比结果我们这里提供的两个服务一个是whoami,一个是nginx,方便测试。
cat nginx-appv1.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: appv1
namespace: default
spec:
selector:
matchLabels:
app: appv1
template:
metadata:
labels:
use: test
app: appv1
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
lifecycle:
postStart:
exec:
command: ["/bin/sh", "-c", "echo Hello v1 > /usr/share/nginx/html/index.html"]
ports:
- containerPort: 80
name: portv1
---
apiVersion: v1
kind: Service
metadata:
name: appv1
namespace: default
spec:
selector:
app: appv1
ports:
- name: http
port: 80
targetPort: portv1
cat nginx-appv2.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: appv2
namespace: default
spec:
selector:
matchLabels:
app: appv2
template:
metadata:
labels:
use: test
app: appv2
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
lifecycle:
postStart:
exec:
command: ["/bin/sh", "-c", "echo Hello v2 > /usr/share/nginx/html/index.html"]
ports:
- containerPort: 80
name: portv2
---
apiVersion: v1
kind: Service
metadata:
name: appv2
namespace: default
spec:
selector:
app: appv2
ports:
- name: http
port: 80
targetPort: portv2
kubectl get pods -l use=test -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
appv1-6c4d4fff84-9vd9j 1/1 Running 0 5h34m 10.244.2.62 tech06 <none> <none>
appv2-6d7b8565cc-z2q5p 1/1 Running 0 5h34m 10.244.2.61 tech06 <none> <none>
通过TraefikService的CRD资源配置WRR
cat nginx-wrr.yaml
---
apiVersion: traefik.containo.us/v1alpha1
kind: TraefikService
metadata:
name: app-wrr
spec:
weighted:
services:
- name: appv1
weight: 1
port: 80
kind: Service
- name: appv2
weight: 3
port: 80
kind: Service
灰度发布的服务创建一个 IngressRoute 资源对象:(ingressroute.yaml)
cat nginx-ingressroute.yaml
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: wrringressroute
namespace: default
spec:
entryPoints:
- web
routes:
- match: Host(`nginx.devopstack.cn`)
kind: Rule
services:
- name: app-wrr
kind: TraefikService
[root@tech04 huidu]# kubectl get ingressroutes.traefik.containo.us
NAME AGE
wrringressroute 3h1m
[root@tech04 huidu]# kubectl get traefikservices.traefik.containo.us app-wrr
NAME AGE
app-wrr 3h1m
验证如下
suixiaofeng@suixiaofeng-System-Product-Name:~curl http://nginx.devopstack.cn
Hello v2
suixiaofeng@suixiaofeng-System-Product-Name:~ curl http://nginx.devopstack.cn
Hello v2
suixiaofeng@suixiaofeng-System-Product-Name:~curl http://nginx.devopstack.cn
Hello v2
suixiaofeng@suixiaofeng-System-Product-Name:~ curl http://nginx.devopstack.cn
Hello v1
通过灰度发布 可以按照权重把流量导入到新版本里.
4 基于traefik的流量复制功能
Traefik 2.0还引入了流量镜像服务,是一种可以将流入流量复制并同时将其发送给其他服务的方法,镜像服务可以获得给定百分比的请求同时也会忽略这部分请求的响应。在traefik 2.0中只能通过FileProvider进行配置,在2.1 版本中可以通过TraefikService资源对象来进行配置.
cat mirror-ingress-route.yaml
apiVersion: traefik.containo.us/v1alpha1
kind: TraefikService
metadata:
name: app-mirror
spec:
mirroring:
name: appv1 # 发送 100% 的请求到 K8S 的 Service "v1"
port: 80
mirrors:
- name: appv2 # 然后复制 50% 的请求到 v2
percent: 50
port: 80
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: mirror-ingress-route
namespace: default
spec:
entryPoints:
- web
routes:
- match: Host(`mirror.devopstack.cn`)
kind: Rule
services:
- name: app-mirror
kind: TraefikService # 使用声明的 TraefikService 服务,而不是 K8S 的 Service
验证:
suixiaofeng@suixiaofeng-System-Product-Name:~curl mirror.devopstack.cn
Hello v1
suixiaofeng@suixiaofeng-System-Product-Name:~ curl mirror.devopstack.cn
Hello v1
suixiaofeng@suixiaofeng-System-Product-Name:~curl mirror.devopstack.cn
Hello v1
suixiaofeng@suixiaofeng-System-Product-Name:~ curl mirror.devopstack.cn
Hello v1
kubectl logs -f appv1-6c4d4fff84-9vd9j
10.244.2.1 - - [24/Sep/2021:10:16:32 +0000] "GET / HTTP/1.1" 200 9 "-" "curl/7.58.0" "192.168.90.4"
10.244.2.1 - - [24/Sep/2021:10:16:33 +0000] "GET / HTTP/1.1" 200 9 "-" "curl/7.58.0" "192.168.90.4"
10.244.2.1 - - [24/Sep/2021:10:16:34 +0000] "GET / HTTP/1.1" 200 9 "-" "curl/7.58.0" "192.168.90.4"
10.244.2.1 - - [24/Sep/2021:10:16:35 +0000] "GET / HTTP/1.1" 200 9 "-" "curl/7.58.0" "192.168.90.4"
kubectl logs -f appv2-6d7b8565cc-z2q5p
10.244.2.1 - - [24/Sep/2021:10:16:32 +0000] "GET / HTTP/1.1" 200 9 "-" "curl/7.58.0" "192.168.90.4"
10.244.2.1 - - [24/Sep/2021:10:16:34 +0000] "GET / HTTP/1.1" 200 9 "-" "curl/7.58.0" "192.168.90.4"
如上,appv2复制了50%的流量.
5 基于traefik的tcp服务代理
Traefik2.x 已经支持了TCP服务的. 简单TCP服务,以redis服务为例,使用traefik转发端口
[root@tech04 tcp]# cat redis.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis
spec:
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: redis:4
ports:
- containerPort: 6379
protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
name: redis
spec:
ports:
- port: 6379
targetPort: 6379
selector:
app: redis
暴露TCP服务
由于Traefik中使用TCP路由配置需要SNI,而SNI又是依赖TLS的,所以我们需要配置证书才行,但是如果没有证书的话,我们可以使用通配符 * 进行配置,我们这里创建一个IngressRouteTCP类型的 CRD对象。在之前安装的时候crd文件里面已经加入了对应的crd资源。我在使用traefik 2.1版本的时候写入域名是可以成功的。
[root@tech04 tcp]# cat redis-ingressroute-tcp.yaml
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRouteTCP
metadata:
name: redis-traefik-tcp
spec:
entryPoints:
- redis
routes:
- match: HostSNI(`redis.devopstack.cn`)
services:
- name: redis
port: 6379
注意:entryPoints部分,是根据我们启动的Traefik的静态配置中的entryPoints来决定的,我们当然可以使用前面我们定义得80和443这两个入口点,但是也可以可以自己添加一个用于redis服务的专门入口点,基于helm部署的traefik更新values-prod.yaml文件,新增redis这个入口点:
# values-prod.yaml
# Configure ports
ports:
web:
port: 8000
hostPort: 80
websecure:
port: 8443
hostPort: 443
redis:
port: 6379
hostPort: 6379
然后更新 Traefik 即可:
helm upgrade --install traefik --namespace=kube-system ./traefik -f ./values-prod.yaml
yaml方式安装的修改方式
[root@tech04 2.4]# cat traefik-deploy.yaml |grep -A 3 redis
- name: redis
containerPort: 6379
hostPort: 6379
[root@tech04 2.4]# cat traefik-config.yaml |grep -C 10 redis
entryPoints:
web:
address: ":80" ## 配置 80 端口,并设置入口名称为 web
websecure:
address: ":443" ## 配置 443 端口,并设置入口名称为 websecure
redis:
address: ":6379"
kubectl apply -f traefik-config.yaml
kubectl delete -f traefik-deploy.yaml
kubectl apply -f traefik-deploy.yaml
验证:
[root@tech04 tcp]# kubectl get ingressroutetcps.traefik.containo.us
NAME AGE
redis-traefik-tcp 4m12s
- 我的微信
- 这是我的微信扫一扫
- 我的微信公众号
- 我的微信公众号扫一扫