Kubernetes集群 服务暴露 Traefik install ¶
1.1 什么是 traefik ? ¶
-
参考链接: https://traefik.cn/
-
是一个为了让部署微服务更加便捷而诞生的现代HTTP反向代理、负载均衡工具。
-
它支持多种后台 (Docker, Swarm, Kubernetes, Marathon, Mesos, Consul, Etcd, Zookeeper, BoltDB, Rest API, file…) 来自动化、动态的应用它的配置文件设置。
1.2 traefix 特性 ¶
- 非常快
- 无需安装其他依赖,通过Go语言编写的单一可执行文件
- 支持 Rest API
- 多种后台支持:Docker, Swarm, Kubernetes, Marathon, Mesos, Consul, Etcd, 并且还会更多
- 后台监控, 可以监听后台变化进而自动化应用新的配置文件设置
- 配置文件热更新。无需重启进程
- 正常结束http连接
- 后端断路器
- 轮询,rebalancer 负载均衡
- Rest Metrics
- 支持最小化官方docker 镜像
- 前、后台支持SSL
- 清爽的AngularJS前端页面
- 支持Websocket
- 支持HTTP/2
- 网络错误重试
- 支持Let’s Encrypt (自动更新HTTPS证书)
- 高可用集群模式
1.3 traefik 与 nginx ingress 对比 ¶
1.4 traefik 核心概念及能力 ¶
Traefik是一个边缘路由器,它会拦截外部的请求并根据逻辑规则选择不同的操作方式,这些规则决定着这些请求到底该如何处理。Traefik提供自动发现能力,会实时检测服务,并自动更新路由规则。
假设你已经在你的基础设施上部署了一堆微服务。你可能使用了一个服务发现系统(例如 etcd 或 consul)或者一个资源管理框架(swarm,Mesos/Marathon)来管理所有这些服务。 如果你想让你的用户去从互联网访问你的某些微服务, 你就必需使用虚拟hosts或前缀路径来配置一个反向代理:
- 域名 api.domain.com 将指向你的私有网络中的微服务 api
- 路径 domain.com/web 将指向你的私有网络中的微服务 web
- 域名 backoffice.domain.com 将指向你的私有网络中的微服务 backoffice ,在你的多台实例之间负载均衡
但一个微服务的结构时动态的。。。 服务在会经常被添加、移除、杀死或更新,可能一天之内就会发生许多次。 传统的反向代理原生不支持动态配置。你不可能轻易的通过热更新更改它们的配置。 这时,Træfɪk就诞生了。
我们将 Træfɪk 放大,一起看看它内部的结构:
- 请求在入口点处结束, 顾名思义, 它们是Træfɪk的网络入口(监听端口, SSL, 流量重定向...)。
- 之后流量会导向一个匹配的前端。 前端是定义入口点 到 后端之间的路由的地方。 路由是通过请求字段(Host, Path, Headers...) 来定义的,它可以匹配或否定一个请求。
- 前端 将会把请求发送到 后端。后端可以由一台或一个通过负载均衡策略配置后的多台服务器组成。
- 最后, 服务器 将转发请求到对应私有网络的微服务当中去。
总而言之,请求首先会连接到 entrypoints,然后分析这些请求是否与定义的 rules 匹配,如果匹配,则会通过一系列 middlewares ,再到对应的 services 上。
以下是几个重要的核心组件。
1. Entrypoints ¶
Entrypoints 是 Traefik 的网络入口,它定义接收请求的接口,以及是否监听 TCP 或者 UDP 。
针对http、https 和 udp 不同的配置方式:
entryPoints:
web:
address: ":80"
websecure:
address: ":443"
streaming:
address: ":1704/udp"
2. Routers ¶
- Providers 是基础组件,Traefik 的配置发现是通过它来实现的,它可以是协调器,容器引擎,云提供商或者键值存储。
- Traefik 通过查询 Providers 的 API 来查询路由的相关信息,一旦检测到变化,就会动态的更新路由。
- Routers 主要用于分析请求,并负责将这些请求连接到对应的服务上去,在这个过程中,Routers 还可以使用 Middlewares 来更新请求,比如在把请求发到服务之前添加一些 Headers。
## Dynamic configuration
http:
routers:
my-router:
rule: "Path(`/foo`)"
service: service-foo
路由可以配置不同的的规则,比如针对请求 host 和请求路径进行匹配。
rule = "Host(`example.com`) || (Host(`example.org`) && Path(`/traefik`))"
路由可以配置不同的的规则
规则 | 描述 |
---|---|
Headers(key , value ) |
请求头校验规则 |
HeadersRegexp(key , regexp ) |
请求头校验规则,value 正则匹配 |
Host(example.com , ...) |
请求域名校验规则 |
HostRegexp(example.com , {subdomain:[a-z]+}.example.com , ...) |
请求域名正则匹配规则 |
Method(GET , ...) |
请求方法校验规则,支持GET\POST\PUT\DELETE\PATCH\HEAD |
Path(/path , /articles/{cat:[a-z]+}/{id:[0-9]+} , ...) |
请求路径匹配规则,精确匹配,支持正则 |
PathPrefix(/products/ , /articles/{cat:[a-z]+}/{id:[0-9]+} ) |
请求路径前缀匹配规则,支持正则 |
Query(foo=bar , bar=baz ) |
请求参数匹配规则 |
ClientIP(10.0.0.0/16 , ::1 ) |
请求 IP 匹配规则 |
3. Middlewares ¶
-
中间件,用于对请求进行处理和转换,类似过滤器、拦截器,有些人可能把他理解成很多网关中的插件,但是其实在 Traefik 里面也有插件的概念,并且可以发布分享,可以参考 plugins.traefik.io/create。
-
Traefik 提供了多种内置的中间件,比如日志记录、重定向、身份验证和限流等第,此外,也可以根据需要自定义中间件。
-
Middlewares 用来修改请求或者根据请求来做出一些判断(authentication, rate limiting, headers, …),中间件被附件到路由上,是一种在请求发送到你的服务之前(或者在服务的响应发送到客户端之前)调整请求的一种方法。
# As a Docker Label
whoami:
# A container that exposes an API to show its IP address
image: traefik/whoami
labels:
# `foo-add-prefix` 中间件
- "traefik.http.middlewares.foo-add-prefix.addprefix.prefix=/foo"
- "traefik.http.routers.router1.middlewares=foo-add-prefix@docker"
列出一些 HTTP 中间件列表,基本上基础的网关鉴权、熔断、限流都有默认的插件。
中间件 | 描述 |
---|---|
AddPrefix | 路径添前缀 |
BasicAuth | 鉴权 |
Buffering | 缓冲 |
Chain | 中间件链,可以定义可重用的中间件组合 |
CircuitBreaker | 熔断 |
Compress | 压缩 |
Headers | 请求头操作,可以添加、删除请求头 |
IPWhiteList | IP 白名单 |
RateLimit | 限流 |
Retry | 重试 |
4. Services ( Traefik-Services ) ¶
服务指的是 Traefik 服务,每个服务都有一个唯一标识符,并可以配置不同的负载均衡规则和健康检查策略。
需要注意的是这里的服务指的是 Traefik 自身的 service,并非是我们自己的服务。
## Dynamic configuration
http:
services:
my-service:
loadBalancer:
servers:
- url: "http://<private-ip-server-1>:<private-port-server-1>/"
- url: "http://<private-ip-server-2>:<private-port-server-2>/"
根据以上的概念,实际上在 Traefik 中一个请求的流程:
- 当客户端发送请求时,请求首先会被协议处理器接收并解析。
- 请求会被路由器匹配到相应的路由规则,并根据规则将请求转发给相应的中间件链。
- 中间件链会按照顺序执行各个中间件,并根据需要对请求进行处理和转换。
- 处理完请求后,请求会被转发给相应的后端服务器。
- 后端服务器将处理完请求后的响应返回给 Traefik。
- Traefik 将响应返回给客户端。
1.5 traefik 部署 ¶
helm 部署 traefik ¶
helm repo add traefik https://helm.traefik.io/traefik
helm repo update
# deployment.replicas=3 设置Traefik部署副本数
# pilot.dashboard=false 禁用Dashboard中Pilot链接
# ingressRoute.dashboard.enabled=false 禁用默认Dashboard入口规则(将在后续步骤中手动创建)
helm upgrade --install traefik traefik/traefik \
--namespace traefik \
--create-namespace \
--set deployment.replicas=3 \
--set pilot.dashboard=false \
--set ingressRoute.dashboard.enabled=false
kubectl get all -n traefik
kubectl get svc traefik -n traefik
配置访问 traefik dashboard 路由规则 ¶
Traefik 应用已经部署完成,但是想让外部访问 Kubernetes 内部服务,还需要配置路由规则,上面部署 Traefik 时开启了 Traefik Dashboard,这是 Traefik 提供的视图看板,所以,首先配置基于 HTTP 的 Traefik Dashboard 路由规则,使外部能够访问 Traefik Dashboard。这里使用 IngressRoute方式进行演示。
Traefik 创建路由规则方法 ¶
- 原生ingress
- CRD IngressRoute
- Gateway API
通过原生 ingress 方式暴露 traefik dashboard ¶
kubectl get svc -n traefik && kubectl get endpoints -n traefik
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-nginx-traefik
namespace: traefik
spec:
ingressClassName: nginx
rules:
- host: traefik.k8s.huichengcheng.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: traefik
port:
number: 80
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: traefik-dashboard
namespace: traefik
spec:
entryPoints:
- web
routes:
- match: Host(`traefik.k8s.huichengcheng.com`) && (PathPrefix(`/dashboard`) || PathPrefix(`/api`))
kind: Rule
services:
- name: api@internal
kind: TraefikService
[root@k8smaster001 ingress]# curl -k https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/baremetal/deploy.yaml -o deploy.yaml
[root@k8smaster001 ingress]# curl -k https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/baremetal/deploy.yaml -o deploy.yaml
YAML 自定义部署 (创建包含类型定义的 Traefik CRD IngressRoute) ¶
helm虽然实现了一键安装部署,但是查看helm包的value.yaml配置发现总共有500多行配置,当需要修改配置项或者对traefik做一下自定义配置时,并不灵活。如果只是使用traefik的基础功能,推荐使用helm部署。如果想深入研究使用traefik的话,推荐使用自定义方式部署。
获取 traefik 部署前置资源清单文件 ¶
Install Traefik Resource Definitions: ¶
wget -q https://raw.githubusercontent.com/traefik/traefik/v2.11/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml -O 001-kubernetes-crd-definition-v1.yml
kubectl apply -f 001-kubernetes-crd-definition-v1.yml
Install RBAC for Traefik: ¶
002-kubernetes-crd-rbac.yml
apiVersion: v1
kind: ServiceAccount
metadata:
namespace: kube-system
name: traefik-ingress-controller
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
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.io
- traefik.containo.us
resources:
- middlewares
- middlewaretcps
- ingressroutes
- traefikservices
- ingressroutetcps
- ingressrouteudps
- tlsoptions
- tlsstores
- serverstransports
verbs:
- get
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
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
kubectl apply -f 002-kubernetes-crd-rbac.yml
创建 traefik 配置文件 ¶
由 traefik 配置多,通过 CLI 定义不方便,一般都通过配置文件对 traefik 进行参数配置,例如使用 ConfigMap 将配置挂载至 traefik 中。
003-traefik-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: traefik
namespace: kube-system
data:
traefik.yaml: |-
serversTransport:
insecureSkipVerify: true ## 略验证代理服务的 TLS 证书
api:
insecure: true ## 允许 HTTP 方式访问 API
dashboard: true ## 启用 Dashboard
debug: true ## 启用 Debug 调试模式
metrics:
prometheus: "" ## 配置 Prometheus 监控指标数据,并使用默认配置
entryPoints:
web:
address: ":80" ## 配置 80 端口,并设置入口名称为 web
websecure:
address: ":443" ## 配置 443 端口,并设置入口名称为 websecure
metrics:
address: ":8082" ## 配置 8082端口,并设置入口名称为 metrics
tcpep:
address: ":8083" ## 配置 8083端口,并设置入口名称为 tcpep,做为tcp入口
udpep:
address: ":8084/udp" ## 配置 8084端口,并设置入口名称为 udpep,做为udp入口
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:
retryAttempts: true ## 设置代理访问重试失败时,保留访问日志
minDuration: 20 ## 设置保留请求时间超过指定持续时间的访问日志
fields: ## 设置访问日志中的字段是否保留(keep 保留、drop 不保留)
defaultMode: keep ## 设置默认保留访问日志字段
names:
ClientUsername: drop
headers:
defaultMode: keep ## 设置 Header 中字段是否保留,设置默认保留 Header 中字段
names: ## 针对 Header 中特别字段特别配置保留模式
User-Agent: redact
Authorization: drop
Content-Type: keep
kubectl apply -f 003-traefik-configmap.yaml
设置节点 Label ¶
由于使用 DaemonSet 方式部署 Traefik ,所以需要为节点设置 label,当应用部署时会根据节点 Label 进行选择。
kubectl label nodes --all IngressProxy=true
kubectl get nodes --show-labels
kubectl label nodes --all IngressProxy-
部署 Traefik ¶
1. Daemonset 资源清单文件准备 ¶
本次将用 Daemonset 方式部署 traefik,便于后期扩展
本次部署通过 hostport方式 把 Pod 中容器内的80、443映射到物理机,方便集群外访问。
004-traefik-DaemonSet.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
namespace: kube-system
name: traefik
labels:
app: traefik
spec:
selector:
matchLabels:
app: traefik
template:
metadata:
labels:
app: traefik
spec:
serviceAccountName: traefik-ingress-controller
terminationGracePeriodSeconds: 1
containers:
- name: traefik
image: traefik:v2.11
args:
- --configfile=/config/traefik.yaml
volumeMounts:
- mountPath: /config
name: config
ports:
- name: web
containerPort: 80
hostPort: 80 ## 将容器端口绑定所在服务器的 80 端口
- name: websecure
containerPort: 443
hostPort: 443 ## 将容器端口绑定所在服务器的 443 端口
- name: admin
containerPort: 8080 ## Traefik Dashboard 端口
- name: tcpep
containerPort: 8083
hostPort: 8083 ## 将容器端口绑定所在服务器的 8083 端口
- name: udpep
containerPort: 8084
hostPort: 8084 ## 将容器端口绑定所在服务器的 8084 端口
protocol: UDP
volumes:
- name: config
configMap:
name: traefik
tolerations: ## 设置容忍所有污点,防止节点被设置污点
- operator: "Exists"
nodeSelector: ## 设置node筛选器,在特定label的节点上启动
IngressProxy: "true"
kubectl apply -f 004-traefik-DaemonSet.yaml
2. Service 资源清单文件准备 ¶
005-traefix-service.yaml
apiVersion: v1
kind: Service
metadata:
name: traefik
namespace: kube-system
labels:
app: traefik
app.kubernetes.io/name: traefik-dashboard
spec:
ports:
- protocol: TCP
name: web
port: 80
- protocol: TCP
name: admin
port: 8080
- protocol: TCP
name: websecure
port: 443
- protocol: TCP
name: tcpep
port: 8083
- protocol: UDP
name: udpep
port: 8084
selector:
app: traefik
kubectl apply -f 005-traefix-service.yaml
Install ingressRoutes ¶
1. 通过原生 ingress 方式暴露 traefik dashboard ¶
kubectl get svc traefik -n kube-system
kubectl get endpoints traefik -n kube-system
006-traefik-dashboard-native-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-nginx-traefik
namespace: traefik
spec:
ingressClassName: nginx
rules:
- host: traefik.k8s.huichengcheng.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: traefik
port:
number: 80
kubectl apply -f 006-traefik-dashboard-native-ingress.yaml
2. 创建 dashboard ingress route 资源清单文件 ¶
kubectl apply -f 007-traefik-dashboard-ingress-route.yaml
007-traefik-dashboard-ingress-route.yaml
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: traefik-dashboard
namespace: kube-system
spec:
entryPoints:
- web
routes:
- match: Host(`traefik.k8s.huichengcheng.com`) && (PathPrefix(`/dashboard`) || PathPrefix(`/api`))
kind: Rule
services:
- name: traefik
port: 8080
接下来我们就可以通过浏览器 http://<域名>/dashboard/(注意 URL 中的尾部斜杠,这是必须的)访问 Traefik Dashboard ,现在应该可以看到在仪表板的 Features 部分启用了 Prometheus 指标。
此外我们还可以访问 curl