k8s基础进阶之外部服务发现之Traefik2.4结合CRD

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界面验证
k8s基础进阶之外部服务发现之Traefik2.4结合CRD

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"]

访问验证
k8s基础进阶之外部服务发现之Traefik2.4结合CRD

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"]
浏览器访问

k8s基础进阶之外部服务发现之Traefik2.4结合CRD

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

k8s基础进阶之外部服务发现之Traefik2.4结合CRD

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资源对象来进行配置.
k8s基础进阶之外部服务发现之Traefik2.4结合CRD

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

k8s基础进阶之外部服务发现之Traefik2.4结合CRD k8s基础进阶之外部服务发现之Traefik2.4结合CRD
  • 我的微信
  • 这是我的微信扫一扫
  • weinxin
  • 我的微信公众号
  • 我的微信公众号扫一扫
  • weinxin
avatar

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: