导航

ucloud k8s部署traefik的forward-auth

Posted on 2020-08-03 17:02  Morya  阅读(926)  评论(0编辑  收藏  举报

ucloud k8s部署traefik的forward-auth

作者:morya
时间:2020-0915
协议:创作共享2.0

traefik是一个开源边界路由器。 opensource edge router

流程图

失败流程

sequenceDiagram user ->> traefik: curl -H X-Uid:10 api.domain.cn traefik ->> authsvc: curl -H X-Uid:10 my-forward-auth/auth authsvc -->> traefik: 401 auth failed traefik -->> user: 401 auth failed

成功流程

sequenceDiagram user ->> traefik: curl -H X-Uid:100 api.domain.cn/whoami traefik ->> authsvc: curl -H X-Uid:100 my-forward-auth/auth authsvc -->> traefik: 200 auth succ traefik ->> api: curl -H X-Uid:100 -H X-Secret:blaa -H X-Auth-User:somebody whoami api -->> traefik: query response traefik -->> user: query response

部署traefik

The Traefik Chart from Helm's default charts repository is still using Traefik v1.7.

helm默认的repo中traefik charts是1.7,traefik当前已经是v2.2版本。 date:2020-0803

helm repo add traefik https://containous.github.io/traefik-helm-chart

调整配置 (适配ucloud uk8s平台)

# values.yaml
service:
  enabled: true
  type: LoadBalancer
  # Additional annotations (e.g. for cloud provider specific config)
  annotations:
    "service.beta.kubernetes.io/ucloud-load-balancer-type": "outer"
    # 代表ULB网络类型,outer为外网,inner为内网;outer为默认值,此处可省略。
    "service.beta.kubernetes.io/ucloud-load-balancer-vserver-protocol": "tcp"
    # 表示ULB协议类型,tcp与udp等价,表示ULB4;http与httpS等价,表示ULB7;tcp为默认值,此处可省略。
    "service.beta.kubernetes.io/ucloud-load-balancer-eip-paymode": traffic
    # 支持traffic、bandwidth、sharebandwidth,默认为bandwidth
    "service.beta.kubernetes.io/ucloud-load-balancer-eip-bandwidth": "145"
    # bandwidth下默认为10Mpbs,建议显式声明带宽大小,避免费用超标。
    "service.beta.kubernetes.io/ucloud-load-balancer-eip-chargetype": "dynamic" # 付费模式,支持month,year,dynamic,默认为month
    "service.beta.kubernetes.io/ucloud-load-balancer-eip-quantity": "1"     # 付费时长,默认为1,chargetype为dynimic时无效
  # Additional entries here will be added to the service spec. Cannot contains
  # type, selector or ports entries.
  spec:
    externalTrafficPolicy: Local

安装traefik

helm install traefik traefik/traefik --values=values.yaml

配置traefik

  • 构建和部署auth-svc
  • 配置crd
    • 配置middleware-forward-auth
    • 配置ingress-route

auth-svc

代码

package main

import (
	"flag"
	"fmt"
	"log"
	"net/http"
	"os"
	"strconv"
)

var (
	flagListen = flag.String("listen", ":80", "listen address")
)

func onAuth(w http.ResponseWriter, req *http.Request) {
	uid, _ := strconv.ParseInt(req.Header.Get("X-Uid"), 10, 64)
	if uid != 100 {
		w.WriteHeader(http.StatusUnauthorized)
		fmt.Fprint(w, "auth failed")
		return
	}

	h := w.Header()
	h.Add("X-Secret", "blaa")
	h.Add("X-Auth-User", "somebody")
	fmt.Fprint(w, "auth pass")
}

func main() {
	flag.Parse()
	log.SetOutput(os.Stderr)
	log.SetFlags(log.LstdFlags | log.Lshortfile)

	http.HandleFunc("/auth", onAuth)
	http.ListenAndServe(*flagListen, nil)
}

部署auth-svc

apiVersion: v1
kind: Service
metadata:
  name: my-forward-auth
  namespace: dev
  labels:
    app: my-forward-auth
spec:
  ports:
  - port: 80
    targetPort: 80
  selector:
    app: my-forward-auth

---

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-forward-auth
  namespace: dev
spec:
  selector:
    matchLabels:
      app: my-forward-auth
  replicas: 1
  template:
    metadata:
      labels:
        app: my-forward-auth
    spec:
      containers:
      - name: my-forward-auth
        image: somebody/my-forward-auth
        imagePullPolicy: Always
        command:
          - '/app'
          - '-listen=:80'
        ports:
        - containerPort: 80

配置crd

配置middleware

apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
  name: forward-auth
spec:
  forwardAuth:
    address: http://my-forward-auth.dev/auth ## 如果traefik和auth在不同namespace,需明确指定
    trustForwardHeader: true
    authResponseHeaders:
      - X-Auth-User
      - X-Secret
kubectl apply -f middleware.yaml

配置IngressRoute

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: my-forward-auth-test
  namespace: default

spec:
  entryPoints:
    - web
    # - websecure

  routes:
    - kind: Rule
      match: Host(`api.domain.cn`) && PathPrefix(`/`)
      middlewares:
      - name: forward-auth
        namespace: default # IngressRoute 和 forward-auth 不一定在一个namespace
      services:
        - kind: Service
          namespace: dev2  ## 自定义名字空间
          name: whoami  ## 此处服务需要自己实现
          port: 80
kubectl apply -f ingress-route.yaml

部署api服务

apiVersion: v1
kind: Service
metadata:
  name: whoami
  labels:
    app: whoami
spec:
  ports:
  - port: 80
    targetPort: 80
  selector:
    app: whoami

---

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

关键特征

  • 鉴权中间件服务,仅通过GET请求接收traefik转送的auth
  • 请求不携带body
  • 原始请求的HEADERS一概携带到middleware来
  • 如果经过多层forward-auth-middleware auth01,auth02附带的headers会传递到后续service中
  • 原始请求的关键信息 URI 等,通过 X-Forwarded-xxx 携带到middleware中
    • X-Forwarded-Uri: /api/auth/login/somebody
    • X-Forwarded-Method: POST