Kubernetes學習記錄(六):深入理解service和Ingress
1. service
- 防止pod失聯(服務發現)
- 定義一組pod的訪問規則(負載均衡)
服務發現
假設現在是一個deployment控制器,一般為了保證高可用都會至少部署三個副本,而且三個pod都有獨立的ip地址
當一個pod掛掉之後,deployment會立刻拉取一個新的pod,但是新pod的ip地址明顯是和掛掉的那個pod不一樣
這時候service就發揮了作用,前端和後端pod不需要通過ip地址來直接通訊,而是經由service來做一個統一的管理操作
負載均衡
當我有多個副本時,客戶端傳送的請求需要具體轉發到哪個pod上,這就是負載均衡
1.1 Pod和Service的關係
- pod與service通過label-selector關聯
- 通過service實現pod的負載均衡(TCP/UDP四層,只負責IP資料包轉發)
Service看起來就像是為Pod提供了一個網路代理的功能
1.2 Service常用型別
- ClusterIP:預設設定,叢集內部使用
- NodePort:對外暴露應用
- LoadBalancer:對外暴露應用,適用於公有云
比如在一個客戶端-後端-資料庫的業務架構中,客戶端-後端、後端-資料庫之間的通訊就要選擇ClusterIP,因為這些都不需要暴露
而使用者和客戶端之間就需要使用NodePort,即我們要把客戶端的服務暴露出去
1.2.1 ClusterIP
分配一個穩定的IP地址,即VIP,只能在叢集內部訪問,同一個namesapce內的pod
最典型的ClusterIP就是k8s叢集服務的service,我們可以通過下面的指令檢視所有的svc
kubectl get svc
這個虛擬IP可以在任意一個節點、任意一個pod內訪問
1.2.2 NodePort
提供一個埠,供外部訪問,但其存在一個問題就是可以通過所有的<NodeIP+port>的形式來訪問
對外暴露的埠號從30000起,預設是叢集隨機分配的
也可以通過spec.ports.nodePort欄位來指定一個暴露埠,但注意可能會存在端口占用情況
這個暴露的埠在每個節點都會監聽,不論這個節點有沒有提供服務的pod
外界訪問任意一個node都可以獲取服務,通過 <NodeIP:NodePort> 的形式,然後統一由service來做負載均衡
比如在下面這個svc列表中,web是作為NodePort型別的,可以看到它在 PORT(S)這一項是有兩個埠號
左側是叢集內部訪問的,也就是一種ClusterIP
右邊是通過節點IP地址暴露出去的一個埠號
一般來講,生產環境中所有的node都部署在內網,即使暴露了埠,在公網上也無法訪問
這時候一般會有以下解決方案:
- 找一臺有公網IP的伺服器,使用nginx反向代理到node
- 使用外部負載均衡器,比如nginx、LVS、HAProxy做負載均衡,將流量轉發到node
1.2.3 LoadBalancer
與NodePort類似,在每個節點上啟用一個埠來暴露服務
除此之外,k8s還會請求底層雲平臺上的負載均衡器,將每個Node <NodeIP:NodePort> 作為後端新增進去
使用者通過訪問公有云上的負載均衡器來訪問node
1.3 Service代理模式
1.3.1 Iptables
iptables是Service的預設模式
iptables能做什麼?
- 阻斷IP通訊
- 埠對映NAT
- 跟蹤包的狀態
- 資料包的修改
kube-proxy元件預設實現iptables,具體來講就是實現資料包在node之間的轉發
將service相關規則來落地實現
如果使用NodePort的訪問規則的話,我們在外部訪問任意節點IP+暴露埠,採取輪詢機制找到一個提供服務的pod
NodePort:192.167.11.89:30008
-> KUBE-SVC-XXXXXX (負載均衡) --probalility 0.3333333
-> KUBE-SEP-YYYYYYY
-> -j DNAT --to-destination 10.244.2.2:80 (提供服務的Pod)
iptables的特點:
- 靈活,功能強大
- 規則遍歷匹配和更新,呈線性時延
1.3.2 IPVS
LVS就是基於ipvs模組實現的四層負載均衡器
ipvs特點:
- 工作在核心態,有更好的效能
- 排程演算法豐富:rr、wrr、lc、wlc、ip hash ...
2. Ingress
為什麼需要Ingress?
首先來看一下NodePort存在的問題:
- 一個埠只能一個服務來使用,因為在所有的Node上都暴露了這個埠
- 只支援四層的負載均衡
2.1 Ingress和Pod的關係
- 通過Service完成關聯
- 通過Ingress Controller實現Pod的負載均衡,支援TCP/UDP四層和HTTP七層
2.2 部署Ingress Controller
Ingress Controller有很多實現,官方維護的是nginx控制器,其他的主流控制器也有Traefik和Istio
官方提供了很多第三方控制器的專案地址:Ingress 控制器 | Kubernetes
我們使用官方的nginx控制器,下載好yaml之後需要修改映象源為國內映象源,修改hostNetwork: true
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.1.2/deploy/static/provider/cloud/deploy.yaml > ic.yaml
根據這個YAML檔案建立兩個pod,其實是和節點數有關,這是以DaemonSet方式部署的
2.3 設定Ingress規則
對於下面這個ingress規則,首先需要指定kind為ingress
最重要的就是service欄位,指明暴露的服務名稱和埠
同時通過域名繫結服務,如果測試的話需要修改本機hosts來訪問
2.4 Ingress根據URL路由到多個服務
比如在下面的示例中,Ingress管理了兩個service
使用者可以通過域名的方式來訪問這兩個service,其中/foo和/bar就負責路由的轉發
這個Ingress規則的YAML檔案如下所示:
Ingress規則中有兩個後端service,路由路徑分別為/foo和/bar
當我們訪問foo.bar.com/foo時,ingress就會幫我路由到service1,訪問foo.bar.com/bar時,ingress會路由到service2
其中的pathType: Prefix是字首匹配,也就是說只要是以 "/foo" 開頭的URL都會被路由到service1
匹配規則可見:Ingress | Kubernetes
2.5 Ingress Controller高可用方案
其中叢集模式更為常見,可以在公網節點上部署一個負載均衡器,比如nginx,把流量轉發給Ingress Controller
參考:
Installation Guide - NGINX Ingress Controller (kubernetes.github.io)