一、先來介紹下Ingress
Ingress 這個東西是 1.2 後纔出現的,通過 Ingress 用戶可以實現使用 nginx 等開源的反向代理負載均衡器實現對外暴露服務,以下詳細說一下 Ingress,畢竟 traefik 用的就是 Ingress
使用 Ingress 時一般會有三個組件:
反向代理負載均衡器
Ingress Controller
Ingress
1.1、反向代理負載均衡器
反向代理負載均衡器很簡單,說白了就是 nginx、apache 什麼的;在集羣中反向代理負載均衡器可以自由部署,可以使用 Replication Controller、Deployment、DaemonSet 等等,不過個人喜歡以 DaemonSet 的方式部署,感覺比較方便
1.2、Ingress Controller
Ingress Controller 實質上可以理解爲是個監視器,Ingress Controller 通過不斷地跟 kubernetes API 打交道,實時的感知後端 service、pod 等變化,比如新增和減少 pod,service 增加與減少等;當得到這些變化信息後,Ingress Controller 再結合下文的 Ingress 生成配置,然後更新反向代理負載均衡器,並刷新其配置,達到服務發現的作用
1.3、Ingress
Ingress 簡單理解就是個規則定義;比如說某個域名對應某個 service,即當某個域名的請求進來時轉發給某個 service;這個規則將與 Ingress Controller 結合,然後 Ingress Controller 將其動態寫入到負載均衡器配置中,從而實現整體的服務發現和負載均衡
有點懵逼,那就看圖
從上圖中可以很清晰的看到,實際上請求進來還是被負載均衡器攔截,比如 nginx,然後 Ingress Controller 通過跟 Ingress 交互得知某個域名對應哪個 service,再通過跟 kubernetes API 交互得知 service 地址等信息;綜合以後生成配置文件實時寫入負載均衡器,然後負載均衡器 reload 該規則便可實現服務發現,即動態映射
瞭解了以上內容以後,這也就很好的說明了我爲什麼喜歡把負載均衡器部署爲 Daemon Set;因爲無論如何請求首先是被負載均衡器攔截的,所以在每個 node 上都部署一下,同時 hostport 方式監聽 80 端口;那麼就解決了其他方式部署不確定 負載均衡器在哪的問題,同時訪問每個 node 的 80 都能正確解析請求;如果前端再 放個 nginx 就又實現了一層負載均衡
二、Traefik 使用
由於微服務架構以及 Docker 技術和 kubernetes 編排工具最近幾年纔開始逐漸流行,所以一開始的反向代理服務器比如 nginx、apache 並未提供其支持,畢竟他們也不是先知;所以纔會出現 Ingress Controller 這種東西來做 kubernetes 和前端負載均衡器如 nginx 之間做銜接;即 Ingress Controller 的存在就是爲了能跟 kubernetes 交互,又能寫 nginx 配置,還能 reload 它,這是一種折中方案;而最近開始出現的 traefik 天生就是提供了對 kubernetes 的支持,也就是說 traefik 本身就能跟 kubernetes API 交互,感知後端變化,因此可以得知: 在使用 traefik 時,Ingress Controller 已經無卵用了,所以整體架構如下
關於traefik 簡介:
traefik 是一個前端負載均衡器,對於微服務架構尤其是 kubernetes 等編排工具具有良好的支持;
同 nginx 等相比,traefik 能夠自動感知後端容器變化,從而實現自動服務發現。
traefik部署在k8s上分爲daemonset和deployment兩種方式各有優缺點:
daemonset 能確定有哪些node在運行traefik,所以可以確定的知道後端ip,但是不能方便的伸縮
deployment 可以更方便的伸縮,但是不能確定有哪些node在運行traefik所以不能確定的知道後端ip
一般部署兩種不同類型的traefik:
面向內部(internal)服務的traefik,建議可以使用deployment的方式
面向外部(external)服務的traefik,建議可以使用daemonset的方式
建議使用traffic-type標籤
traffic-type: external
traffic-type: internal
traefik相應地使用labelSelector
traffic-type=internal
traffic-type=external
已經從大體上搞懂了 Ingress 和 traefik,那麼部署起來就很簡單
安裝
mkdir traefik && cd traefik
wget https://raw.githubusercontent.com/containous/traefik/master/examples/k8s/traefik-rbac.yaml
# 配置rbac
kubectl apply -f traefik-rbac.yaml
# 以下兩種方式選擇一個
# 80 提供正常服務,8080 是其自帶的 UI 界面
# 以daemonset方式啓動traefik
# 會在所有node節點啓動一個traefik並監聽在80端口
# master節點不會啓動traefik
wget https://raw.githubusercontent.com/containous/traefik/master/examples/k8s/traefik-ds.yaml
kubectl apply -f traefik-ds.yaml
# 以deployment方式啓動traefik
wget https://raw.githubusercontent.com/containous/traefik/master/examples/k8s/traefik-deployment.yaml
kubectl apply -f traefik-deployment.yaml
# 查看狀態
kubectl get pods -n kube-system
# 訪問測試,如果有響應說明安裝正確
# 應該返回404
# 如果以daemonset方式啓動traefik使用如下方式驗證
# 11.11.11.112爲任何一個node節點的ip
curl 11.11.11.112
# 如果以deployment方式啓動traefik
# 訪問node:nodeport或者集羣ip驗證
部署Træfik Web UI
wget https://raw.githubusercontent.com/containous/traefik/master/examples/k8s/ui.yaml
kubectl apply -f ui.yaml
# 訪問webui
# 需要先配置host
# 11.11.11.112爲任何一個node節點的ip
11.11.11.112 traefik-ui.minikube
# 瀏覽器訪問如下地址
http://traefik-ui.minikube/
使用basic驗證
# 生成加密密碼,如果沒有安裝htpasswd可以在線生成
# https://tool.lu/htpasswd/
htpasswd -c ./auth myusername
cat auth
myusername:$apr1$78Jyn/1K$ERHKVRPPlzAX8eBtLuvRZ0
# 從密碼文件創建secret
# monitoring必須和ingress rule處於同一個namespace
kubectl create secret generic mysecret --from-file auth --namespace=monitoring
# 創建ingress
cat >prometheus-ingress.yaml<<EOF
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: prometheus-dashboard
namespace: monitoring
annotations:
kubernetes.io/ingress.class: traefik
ingress.kubernetes.io/auth-type: "basic"
ingress.kubernetes.io/auth-secret: "mysecret"
spec:
rules:
- host: dashboard.prometheus.example.com
http:
paths:
- backend:
serviceName: prometheus
servicePort: 9090
EOF
kubectl create -f prometheus-ingress.yaml -n monitoring
官方實例
1. 根據域名(host)路由
# deployment
wget https://raw.githubusercontent.com/containous/traefik/master/examples/k8s/cheese-deployments.yaml
kubectl apply -f cheese-deployments.yaml
# service
wget https://raw.githubusercontent.com/containous/traefik/master/examples/k8s/cheese-services.yaml
kubectl apply -f cheese-services.yaml
# ingress
wget https://raw.githubusercontent.com/containous/traefik/master/examples/k8s/cheese-ingress.yaml
kubectl apply -f cheese-ingress.yaml
# 查看狀態
kubectl get pods
kubectl get svc
kubectl get ingress
# 測試
# 配置hosts
11.11.11.112 stilton.minikube cheddar.minikube wensleydale.minikube
# 瀏覽器訪問測試
http://stilton.minikube/
http://cheddar.minikube/
http://wensleydale.minikube/
2. 根據路徑(path)路由
# 使用新的ingress
wget https://raw.githubusercontent.com/containous/traefik/master/examples/k8s/cheeses-ingress.yaml
kubectl apply -f cheeses-ingress.yaml
# 測試
# 配置hosts
11.11.11.112 cheeses.minikube
# 瀏覽器訪問測試
http://cheeses.minikube/stilton/
http://cheeses.minikube/cheddar/
http://cheeses.minikube/wensleydale/
3. 指定路由優先級
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: wildcard-cheeses
annotations:
traefik.frontend.priority: "1"
spec:
rules:
- host: *.minikube
http:
paths:
- path: /
backend:
serviceName: stilton
servicePort: http
kind: Ingress
metadata:
name: specific-cheeses
annotations:
traefik.frontend.priority: "2"
spec:
rules:
- host: specific.minikube
http:
paths:
- path: /
backend:
serviceName: stilton
servicePort: http
參考文檔
https://docs.traefik.io/user-guide/kubernetes/
https://mritd.me/2016/12/06/try-traefik-on-kubernetes/
部署 Traefik UI
traefik 本身還提供了一套 UI 供我們使用,其同樣以 Ingress 方式暴露,只需要創建一下即可
kubectl create -f ui.yaml
# ui yaml 如下
---
apiVersion: v1
kind: Service
metadata:
name: traefik-web-ui
namespace: kube-system
spec:
selector:
k8s-app: traefik-ingress-lb
ports:
- name: web
port: 80
targetPort: 8580
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: traefik-web-ui
namespace: kube-system
spec:
rules:
- host: traefik-ui.local
http:
paths:
- path: /
backend:
serviceName: traefik-web-ui
servicePort: web
2.1.4、訪問測試
都創建無誤以後,只需要將待測試的域名解析到任意一臺 node 上即可,頁面就不截圖了,截圖就暴露了…..下面來兩張 ui 的
2.2、健康檢查
關於健康檢查,測試可以使用 kubernetes 的 Liveness Probe 實現,如果 Liveness Probe檢查失敗,則 traefik 會自動移除該 pod,以下是一個 示例
test 的 deployment,健康檢查方式是 cat /tmp/health,容器啓動 2 分鐘後會刪掉這個文件,模擬健康檢查失敗
apiVersion: v1
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: test
namespace: default
labels:
test: alpine
spec:
replicas: 1
selector:
matchLabels:
test: alpine
template:
metadata:
labels:
test: alpine
name: test
spec:
containers:
- image: mritd/alpine:3.4
name: alpine
resources:
limits:
cpu: 200m
memory: 30Mi
requests:
cpu: 100m
memory: 20Mi
ports:
- name: http
containerPort: 80
args:
command:
- "bash"
- "-c"
- "echo ok > /tmp/health;sleep 120;rm -f /tmp/health"
livenessProbe:
exec:
command:
- cat
- /tmp/health
initialDelaySeconds: 20
test 的 service
apiVersion: v1
kind: Service
metadata:
name: test
labels:
name: test
spec:
ports:
- port: 8123
targetPort: 80
selector:
name: test
test 的 Ingress
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test
spec:
rules:
- host: test.com
http:
paths:
- path: /
backend:
serviceName: test
servicePort: 8123
全部創建好以後,進入 traefik ui 界面,可以觀察到每隔 2 分鐘健康檢查失敗後,kubernetes 重建 pod,同時 traefik 會從後端列表中移除這個 pod
2