Traefik Kubernetes 初試_Kubernetes中文社群
traefik 是一個前端負載均衡器,對於微服務架構尤其是 kubernetes 等編排工具具有良好的支援;同 nginx 等相比,traefik 能夠自動感知後端容器變化,從而實現自動服務發現;今天小試了一下,在此記錄一下使用過程
一、Kubernetes 服務暴露介紹
從 kubernetes 1.2 版本開始,kubernetes提供了 Ingress 物件來實現對外暴露服務;到目前為止 kubernetes 總共有三種暴露服務的方式:
- LoadBlancer Service
- NodePort Service
- Ingress
1.1、LoadBlancer Service
LoadBlancer Service 是 kubernetes 深度結合雲平臺的一個元件;當使用 LoadBlancer Service 暴露服務時,實際上是通過向底層雲平臺申請建立一個負載均衡器來向外暴露服務;目前 LoadBlancer Service 支援的雲平臺已經相對完善,比如國外的 GCE、DigitalOcean,國內的 阿里雲,私有云 Openstack 等等,由於 LoadBlancer Service 深度結合了雲平臺,所以只能在一些雲平臺上來使用
1.2、NodePort Service
NodePort Service 顧名思義,實質上就是通過在叢集的每個 node 上暴露一個埠,然後將這個埠對映到某個具體的 service 來實現的,雖然每個 node 的埠有很多(0~65535),但是由於安全性和易用性(服務多了就亂了,還有埠衝突問題)實際使用可能並不多
1.3、Ingress
Ingress 這個東西是 1.2 後才出現的,通過 Ingress 使用者可以實現使用 nginx 等開源的反向代理負載均衡器實現對外暴露服務,以下詳細說一下 Ingress,畢竟 traefik 用的就是 Ingress
使用 Ingress 時一般會有三個元件:
- 反向代理負載均衡器
- Ingress Controller
- Ingress
1.3.1、反向代理負載均衡器
反向代理負載均衡器很簡單,說白了就是 nginx、apache 什麼的;在叢集中反向代理負載均衡器可以自由部署,可以使用 Replication Controller、Deployment、DaemonSet 等等,不過個人喜歡以 DaemonSet 的方式部署,感覺比較方便
1.3.2、Ingress Controller
Ingress Controller 實質上可以理解為是個監視器,Ingress Controller 通過不斷地跟 kubernetes API 打交道,實時的感知後端 service、pod 等變化,比如新增和減少 pod,service 增加與減少等;當得到這些變化資訊後,Ingress Controller 再結合下文的 Ingress 生成配置,然後更新反向代理負載均衡器,並重新整理其配置,達到服務發現的作用
1.3.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 已經無卵用了,所以整體架構如下
2.1、部署 Traefik
已經從大體上搞懂了 Ingress 和 traefik,那麼部署起來就很簡單
2.1.1、部署 Daemon Set
首先以 Daemon Set 的方式在每個 node 上啟動一個 traefik,並使用 hostPort 的方式讓其監聽每個 node 的 80 埠(有沒有感覺這就是個 NodePort? 不過區別就是這個 Port 後面有負載均衡器 –>手動微笑)
kubectl create -f traefik.ds.yanl
# Daemon set 檔案如下
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
name: traefik-ingress-lb
namespace: kube-system
labels:
k8s-app: traefik-ingress-lb
spec:
template:
metadata:
labels:
k8s-app: traefik-ingress-lb
name: traefik-ingress-lb
spec:
terminationGracePeriodSeconds: 60
hostNetwork: true
restartPolicy: Always
containers:
- image: traefik
name: traefik-ingress-lb
resources:
limits:
cpu: 200m
memory: 30Mi
requests:
cpu: 100m
memory: 20Mi
ports:
- name: http
containerPort: 80
hostPort: 80
- name: admin
containerPort: 8580
args:
- --web
- --web.address=:8580
- --kubernetes
其中 traefik 監聽 node 的 80 和 8580 埠,80 提供正常服務,8580 是其自帶的 UI 介面,原本預設是 8080,因為環境裡埠衝突了,所以這裡臨時改一下
2.1.2、部署 Ingress
從上面的長篇大論已經得知了 Ingress Controller 是無需部署的,所以直接部署 Ingress 即可
kubectl create -f traefik.ing.yaml
# Ingress 檔案如下
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: traefik-ingress
spec:
rules:
- host: traefik.www.test.com
http:
paths:
- path: /
backend:
serviceName: test-www
servicePort: 8080
- host: traefik.api.test.com
http:
paths:
- path: /
backend:
serviceName: test-api
servicePort: 8080
實際上事先叢集中已經存在了相應的名為 test-www 和 test-api 的 service,對應的 service 後端也有很多 pod;所以這裡就不在具體寫部署實際業務容器(test-www、test-api)的過程了,各位測試時,只需要把這個 test 的 service 替換成自己業務的 service 即可
2.1.3、部署 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