前言
K8S 中的 Ingress Controllers 並沒有實作,可以自己使用各種版本。在 Minikube 中的 Ingress Controllers 預設是用 NGINX Ingress Controller,然而 NGINX Ingress Controller 的功能非常陽春,官網有提供一系列的 Ingress Controller 給各位參考,該文章紀錄如何使用 Traefik 這個 Edge Router 作為 Ingress Controller。
正文
在操作 K8S 之前請先確定你正在操作的叢集是練習環境:
kubectl cluster-info
Traefik 這套工具可以將外部的流量吸收,並且透過自己定義的路由來將流量往內部的 Service 打。我們希望可以透過 URL 的 Path 來定義不同服務的路由,將流量打向不同的服務。
在 NGINX Ingress Controller 中要做這件事情,要在 annotations
中加上 nginx.ingress.kubernetes.io/rewrite-target: /
1 2 3 4 5 6 7 8 9 10 11
| apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: annotations: nginx.ingress.kubernetes.io/rewrite-target: / name: rewrite namespace: default spec: ... ... ...
|
避免不同 App 吃到不同的路由位置無法產生正確的回應(假設我們的服務入口都在根路徑 Ex: app-foo/
)。
但 Traefik 要達成這件事情必須透過 Middleware 這個組件(Traefik 定義的功能),簡單來說我們要把讀進來的 /path,strip 掉並且將導向到指定的 Service 上。
要使用 Traefik Middleware 有兩種方式:
- IngressRoute (CustomResourceDefinitions)
- 在 Ingress 中使用 annotation 定義
個人覺得第二點比較直覺,所以選擇第二種方式。
首先,先建立 Middleware 這個 CRD,並且做 ClusterRoleBinding:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
| apiVersion: apiextensions.k8s.io/v1beta1 kind: CustomResourceDefinition metadata: name: middlewares.traefik.containo.us
spec: group: traefik.containo.us version: v1alpha1 names: kind: Middleware plural: middlewares singular: middleware scope: Namespaced
--- 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 resources: - ingresses verbs: - get - list - watch - apiGroups: - extensions resources: - ingresses/status verbs: - update - apiGroups: - traefik.containo.us resources: - middlewares - ingressroutes - traefikservices - ingressroutetcps - ingressrouteudps - tlsoptions - tlsstores verbs: - get - list - watch
--- 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: default
|
將 Traefik 本身跑起來:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| apiVersion: v1 kind: ServiceAccount metadata: namespace: default name: traefik-ingress-controller
--- kind: Deployment apiVersion: apps/v1 metadata: namespace: default name: traefik labels: app: traefik
spec: replicas: 1 selector: matchLabels: app: traefik template: metadata: labels: app: traefik spec: serviceAccountName: traefik-ingress-controller containers: - name: traefik image: traefik:v2.2 args: - --api.insecure - --accesslog - --entrypoints.web.Address=:8000 - --providers.kubernetesingress - --providers.kubernetescrd ports: - name: web containerPort: 8000 - name: admin containerPort: 8080
|
為 Traefik 設定 Service:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| apiVersion: v1 kind: Service metadata: name: traefik
spec: ports: - protocol: TCP name: web port: 8000 - protocol: TCP name: admin port: 8080 selector: app: traefik
|
建立 Ingress 與 Middleware(stripprefix):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: yy-ingress annotations: traefik.ingress.kubernetes.io/router.entrypoints: web traefik.ingress.kubernetes.io/router.middlewares: default-stripprefix@kubernetescrd spec: rules: - host: yy.k8s http: paths: - path: / backend: serviceName: whales servicePort: 80 - path: /app backend: serviceName: whales servicePort: 80 - path: /whoami backend: serviceName: whoami servicePort: 80 - host: admin.yy.k8s http: paths: - path: / backend: serviceName: traefik servicePort: 8080
--- apiVersion: traefik.containo.us/v1alpha1 kind: Middleware metadata: name: stripprefix spec: stripPrefix: prefixes: - /app - /whoami
|
要注意的重點有:
- CRD 中的權限要記得 middwares 有被加進去。
- 要使用 Ingress,Traefik 跑起來時要加上
--providers.kubernetesingress
- 如果用 IngressRoute 跑,要加上
--providers.kubernetescrd
- annotations 中 middleware 的名字最前面需要加上 namespace(本文使用 default)
- 如果直接貼 Traefik 官網的 user-guides/crd-acme,要注意它並沒有加上
--providers.kubernetesingress
,所以無法與 Ingress 正確綁定
- 在 local 測試可以用
kubectl port-forward svc/traefik foo-port:8080
連到 dashboard 來 debug
更多詳細設定可以參考 user-guides/crd-acme,以上的設定比較精簡,此文章只有留必要部分而已。
完整的設定可以到 GitHub Repo 上面看。