k8s使用traefik作为ingress路由的实践

之前看到博文感觉说的很乱,于是自己进行了实践,并根据官网文档配置了路由

其中包含了http请求情况的域名访问和https请求情况下的域名访问,需要注意的是,http-ingressRoute.yaml和https-ingressRoute.yaml里的命名空间,最好设置成一致,具体说明见yaml注释,其中http请求配置了路由域名yb.com(需要在你自己电脑的hosts里配置你的IP映射)访问traefik的dashboard,直接访问http://yb.com即可,如果没有结果,请检查命名空间以及服务名等信息。

traefik-ingress.yaml (取自网上,基本都一样)

---
apiVersion: v1
kind: Namespace
metadata:
  name: traefik-ingress
  labels:
    app: traefik-ingress

---
## IngressRoute
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  name: ingressroutes.traefik.containo.us
  namespace: traefik-ingress
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
  namespace: traefik-ingress
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
  namespace: traefik-ingress
spec:
  scope: Namespaced
  group: traefik.containo.us
  version: v1alpha1
  names:
    kind: Middleware
    plural: middlewares
    singular: middleware
---
## TLSOption
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  name: tlsoptions.traefik.containo.us
  namespace: traefik-ingress
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
  namespace: traefik-ingress
spec:
  scope: Namespaced
  group: traefik.containo.us
  version: v1alpha1
  names:
    kind: TraefikService
    plural: traefikservices
    singular: traefikservice
     
---   
## ServiceAccount
apiVersion: v1
kind: ServiceAccount
metadata:
  name: traefik-ingress-controller
  namespace: traefik-ingress
---
## ClusterRole
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: traefik-ingress-controller
  namespace: traefik-ingress
rules:
  - apiGroups: [""]
    resources: ["services","endpoints","secrets"]
    verbs: ["get","list","watch"]
  - apiGroups: ["extensions"]
    resources: ["ingresses"]
    verbs: ["get","list","watch"]
  - apiGroups: ["extensions"]
    resources: ["ingresses/status"]
    verbs: ["update"]
  - apiGroups: ["traefik.containo.us"]
    resources: ["middlewares"]
    verbs: ["get","list","watch"]
  - apiGroups: ["traefik.containo.us"]
    resources: ["ingressroutes"]
    verbs: ["get","list","watch"]
  - apiGroups: ["traefik.containo.us"]
    resources: ["ingressroutetcps"]
    verbs: ["get","list","watch"]
  - apiGroups: ["traefik.containo.us"]
    resources: ["tlsoptions"]
    verbs: ["get","list","watch"]
  - apiGroups: ["traefik.containo.us"]
    resources: ["traefikservices"]
    verbs: ["get","list","watch"]
---
## ClusterRoleBinding
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: traefik-ingress-controller
  namespace: traefik-ingress
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: traefik-ingress-controller
subjects:
  - kind: ServiceAccount
    name: traefik-ingress-controller
    namespace: traefik-ingress 
    
---
kind: ConfigMap
apiVersion: v1
metadata:
  name: traefik-config
  namespace: traefik-ingress
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 方式来配置路由规则
    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
    
---
apiVersion: v1
kind: Service
metadata:
  name: traefik
  namespace: traefik-ingress
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: traefik-ingress
  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.1.2
          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: 1000m
              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"
      volumes:
        - name: config
          configMap:
            name: traefik-config 
      tolerations:              ## 设置容忍所有污点,防止节点被设置污点
        - operator: "Exists"
      nodeSelector:             ## 设置node筛选器,在特定label的节点上启动
        IngressProxy: "true"

http-ingressRoute.yaml

#入口路由需要配合中间件处理前缀(这里使用的是在请求服务前删除前缀),详情看traefik官网
---
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
  name: api
  namespace: default
spec:
  stripPrefix:
    prefixes:
      - /api
    #该forceSlash选项通过/在必要时将其替换来确保所得的剥离路径不是空字符串
    #添加此选项是为了保持此中间件的初始(非直观)行为,以避免引入重大更改
    #建议显式设置forceSlash为false
    forceSlash: false

---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: http-route
  #如果入口路由的命名空间和路由的service服务相同,则不用指定service服务的命名空间,否则就需要指定
  namespace: default
spec:
  entryPoints:
    #映射端口443的https的切入点
    - web
  routes:
  - match: Host(`yb.com`) && PathPrefix(`/`)
    priority: 9
    kind: Rule
    services:
    - name: traefik
      port: 8080
      namespace: traefik-ingress
  - match: Host(`yb.com`) && PathPrefix(`/api`)
    #优先级
    priority: 10     
    kind: Rule
    services:
    - name: default-svc
      port: 8080
    middlewares:
    - name: api
      #和service服务一样,指定命名空间,找到指定的中间件
      namespace: default

https-ingressRoute.yaml

#入口路由需要配合中间件处理前缀(这里使用的是在请求服务前删除前缀),详情看traefik官网
---
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
  name: api
  namespace: default
spec:
  stripPrefix:
    prefixes:
      - /api
    #该forceSlash选项通过/在必要时将其替换来确保所得的剥离路径不是空字符串
    #添加此选项是为了保持此中间件的初始(非直观)行为,以避免引入重大更改
    #建议显式设置forceSlash为false
    forceSlash: false

---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: https-route
  #如果入口路由的命名空间和路由的service服务相同,则不用指定service服务的命名空间,否则就需要指定
  namespace: default
spec:
  entryPoints:
    #映射端口443的https的切入点
    - websecure
  #创建自签名证书(注意域名更换为自己实际的)
  #openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=yb.com"
  #将证书存储到Kubernetes Secret中
  #kubectl create secret generic https-tls --from-file=tls.crt --from-file=tls.key -n default
  tls:
    #设置证书的密钥名称
    secretName: https-tls
    namespace: default
  routes:
  - match: Host(`yb.com`) && PathPrefix(`/`)
    priority: 9
    kind: Rule
    services:
    - name: web-default-svc
      port: 80
      namespace: default
    #注意请求后端服务需要使用https请求
  - match: Host(`yb.com`) && PathPrefix(`/api`)
    #优先级
    priority: 10     
    kind: Rule
    services:
    - name: default-svc
      port: 8080
    middlewares:
    - name: api
      #和service服务一样,指定命名空间,找到指定的中间件
      namespace: default