基本情況介紹
一、service
Kubernetes中一個應用服務會有一個或多個例項,每個例項(Pod)的IP地址由網路外掛動態隨機分配(Pod重啟後IP地址會改變)。為遮蔽這些後端例項的動態變化和對多例項的負載均衡,引入了 Service這個資源物件。
type 型別
根據建立 Service 的 type 型別不同,主要分為幾下幾種:
ClusterIP:透過為 Kubernetes 的 Service 分配一個叢集內部可訪問的固定虛擬IP(Cluster IP),實現叢集內的訪問;
NodePort:將 service 的 port 對映到叢集內每個節點的相同一個埠,實現透過 nodeIP:nodePort 從叢集外訪問服務;
LoadBalance:向所使用的公有云申請一個負載均衡器(負載均衡器後端對映到各節點的 nodePort),實現從叢集外透過 LB 訪問服務;
Port
Service 中主要涉及三種 Port:
port 表示 service 暴露在 clusterIP 上的埠,clusterIP:Port 是提供給叢集內部訪問 kubernetes 服務的入口;
NodePort:提供給從叢集外部訪問 kubernetes 服務的入口;
TargetPort:容器port,targetPort 是 pod 上的埠,從 port 和 nodePort 上到來的資料最終經過 kube-proxy 流入到後端 pod 的 targetPort 上進入容器。
port 和 nodePort 都是 service 的埠,前者暴露給從叢集內訪問服務,後者暴露給從叢集外訪問服務。從這兩個埠到來的資料都需要經過反向代理 kube-proxy 流入後端具體 pod 的 targetPort,從而進入到 pod 上的容器內。
IP
使用 Service 服務會涉及到幾種 IP:
Cluster IP:虛擬地址,由 kube-proxy 使用 iptables 規則重新定向到其本地埠,再均衡到後端Pod。當 kube-proxy 發現一個新的 service 後,它會在本地節點開啟一個任意埠,建立相應的iptables 規則,重定向服務的 clusterIP 和 port 到這個新建的埠,開始接受到達這個服務的連線。
Pod IP:每個 Pod 啟動時,會自動建立一個映象為 gcr.io/google_containers/pause 的容器,Pod內部其他容器的網路模式使用container模式,指定為 pause 容器的ID(network_mode: “container:pause 容器ID”),使得 Pod 內所有容器共享 pause 容器的網路,與外部的通訊經由此容器代理,pause容器的 IP 也可以稱為Pod IP。
Node IP:將服務作為一個應用程式內部的層次,使的服務可以從叢集外部訪問,指定 service 的spec.type=NodePort,透過 nodeip:nodeport 從叢集外訪問服務。
工作方式
定義服務的時候透過 selector 指定服務對應的 pods,根據 pods 的地址創建出 endpoints 作為服務後端;Endpoints Controller 會 watch Service 以及 pod 的變化,維護對應的 Endpoint 資訊。kube-proxy根據 Service 和 Endpoint 來維護本地的路由規則。當 Endpoint 發生變化,即 Service 以及關聯的pod發生變化,kube-proxy 都會在每個節點上更新 iptables,實現一層負載均衡。
MetalLB 基本介紹
官方文件地址:https://metallb.universe.tf/
該專案釋出於 2017 年底,當前處於 Beta 階段。
MetalLB完全支援的網路外掛Canal、Cilium、Flannel、Kube-ovn等。如果kube-proxy執行在IPVS模式先,需要設定strictARP: true
(後面會詳細闡述)
Kubernetes不提供網路負載均衡器的實現(LoadBalancer型別的服務)用於裸機叢集。Kubernetes附帶的Network LB的實現都是呼叫各種IaaS平臺(GCP,AWS,Azure等)的粘合程式碼。如果您未在受支援的IaaS平臺(GCP,AWS,Azure等)上執行,則LoadBalancers在建立時將無限期保持“待處理”狀態。
裸機叢集運營商只剩下兩個較小的工具,即“ NodePort”和“ externalIPs”服務,可將使用者流量引入其叢集。這兩個選項在生產用途上都有很大的缺點,這使裸金屬叢集成為Kubernetes生態系統中的二等公民。
MetalLB旨在透過提供與標準網路裝置整合的Network LB實現來解決這種不平衡問題,從而使裸機群集上的外部服務也儘可能“正常執行”。
簡單來說:在裸機叢集上(不是公有云廠商的主機,比如阿里雲,騰訊雲)部署k8s後,外部網路訪問集群裡的服務,透過ingress-nginx的形式,但是這個ingress-nginx的服務service埠型別對外暴露只能使用“ NodePort”和“ externalIPs”服務,不能使用LoadBalancer的,使用MetalLB則可以解決這個問題,使ingress-nginx的service埠型別對外暴露使用LoadBalancer的形式(不用使用雲廠商提供的負載均衡器)
MetalLB是 Kubernetes 叢集中關於LoadBalancer的一個具體實現,主要用於暴露k8s叢集的服務到叢集外部訪問。由兩個共同提供此服務的工作負載(workload):地址分配和外部公告;對應的就是在 k8s中部署的 controller 和 speaker。
Metallb 會在 Kubernetes 內執行,監控服務物件的變化,一旦察覺有新的 LoadBalancer 服務執行,並且沒有可申請的負載均衡器之後,就會完成兩部分的工作:
1.地址分配,使用者需要在配置中提供一個地址池,Metallb 將會在其中選取地址分配給服務。
2.地址廣播,根據不同配置,Metallb 會以二層(ARP/NDP)或者 BGP 的方式進行地址的廣播。
地址分配(address allocation)
需要給 MetalLB 分配一段 IP,接著它會根據 service 中的相關配置來給LoadBalancer的服務分配IP,LoadBalancer的IP可以手動指定,也可以讓MetalLB自動分配;同時還可以在 MetalLB 的configmap中配置多個 IP 段,並且單獨設定每個 IP 段是否開啟自動分配。
地址分配(address allocation)主要就是由作為 deployment 部署的 controller 來實現,它負責監聽叢集中的 service 狀態並且分配 IP。
外部公告(external announcement)
外部公告的主要功能就是要把服務型別為LoadBalancer的服務的IP公佈到網路中去,確保客戶端能夠正常訪問到這個 IP 。MetalLB 對此的實現方式主要有三種:ARP/NDP和BGP;其中 ARP/NDP 分別對應IPv4/IPv6 協議的 Layer2 模式,BGP路由協議則是對應 BGP 模式。
外部公告主要就是由作為daemonset部署的speaker來實現,它負責在網路中釋出 ARP/NDP 報文或者是和 BGP 路由器建立連線併發布 BGP 報文。
工作原理
Metallb 包含兩個元件,Controller 和 Speaker,Controller 為 Deployment 部署方式,而 Speaker 則採用 Daemonset 方式部署到叢集內部各個Node節點。
具體的工作原理如下圖所示,Controller 負責監聽 Service 變化,當 Service 配置為 LoadBalancer 模式時,從 IP 池分配給到相應的 IP 地址並對該 IP 的生命週期進行管理。Speaker 則會依據選擇的協議進行相應的廣播或應答,實現 IP 地址的通訊響應。當業務流量透過 TCP/UDP 協議到達指定的 Node 時,由Node 上面執行的 Kube-Proxy 元件對流量進行處理,並分發到對應服務的 Pod 上面。
安裝
安裝之前的準備檢查工作
如果您在IPVS模式下使用kube-proxy,則從Kubernetes v1.14.2開始,您必須啟用嚴格的ARP模式。請注意,如果您將kube-router用作服務代理,則不需要此設定,因為預設情況下它啟用了嚴格的arp。
您可以透過在當前叢集中編輯kube-proxy配置來實現:
# kubectl edit configmap -n kube-system kube-proxy
並修改如下圖內容
apiVersion:kubeproxy.config.k8s.io/v1alpha1
kind:KubeProxyConfiguration
mode:"ipvs"# 這個在安裝時預設選擇了ipvs
ipvs:
strictARP:true# 修改這個
更新kube-proxy pod
# kubectl
get
pod
-
n kube
-
system
|
grep kube
-
proxy
|
awk '{system(
"kubectl delete pod "$1" -n kube-system"
)}'
另外一種修改生效方式:
# see what changes would be made, returns nonzero returncode if different
kubectl get configmap kube-proxy -n kube-
system
-o yaml | \
sed -e
"s/strictARP: false/strictARP: true/"
| \
kubectl diff -f - -n kube-
system
# actually apply the changes, returns nonzero returncode on errors only
kubectl get configmap kube-proxy -n kube-
system
-o yaml | \
sed -e
"s/strictARP: false/strictARP: true/"
| \
kubectl apply -f - -n kube-
system
安裝
# mkdir
metallb &&
cdcd
metallb/
#
wget https://github.com/metallb/metallb/blob/main/config/manifests/metallb-native.yaml
#
vim metallb-native.yaml
#檢視裡面需要的映象
提前將映象下載好,上傳至私有倉庫 (quay.io是Red Hat運營的映象庫,雖然沒有被牆,但下載還是比較慢。可以從這個裡面找到使用映象的最新版本,然後再使用自己的github代理拉取,推送到自己的dockerhub倉庫裡)
(下載quay.io的映象,可以參考這個文章:https://www.cnblogs.com/hahaha111122222/p/17097890.html)
使用私庫裡的映象,需要修改metallb-native.yaml檔案中使用的映象名
Metallb 安裝,會生成自己的名稱空間以及 RBAC 配置。
# kubectl apply
-
f metallb
-
native.yaml
# kubectl
-
n metallb
-systemgetall
建立金鑰,否則會出現報錯
===
》 這一步沒看懂要幹啥,可以暫不操作的
# kubectl
create
secret generic
-
n metallb
-system
memberlist
--from-literal=secretkey="$(openssl rand -base64 128)"
# kubectl
-
n metallb
-systemget
secrets
配置
接下來我們要生成一個 Configmap 檔案,為 Metallb 設定網址範圍以及協議相關的選擇和配置,這裡以一個簡單的二層配置為例:
# vim config.yml
apiVersion:v1
kind:ConfigMap
metadata:
namespace:metallb-system
name:config
data:
config:
|
address-pools:
- name: default
protocol: layer2
addresses:
- 172.25.1.100-172.25.1.200
# kubectl apply -f config.yml
注意:這裡的 IP 地址範圍需要跟叢集實際情況相對應。(跟叢集主機節點的私網IP對應,可以理解成同網段尚未使用的IP所在網段範圍)
注意: 新版本使用的配置檔案內容有變化,網址:https://metallb.universe.tf/configuration/_advanced_l2_configuration/
測試
我們建立一個svc進行測試
# vim nginx.yaml
apiVersion:v1
kind:Service
metadata:
name:nginx-svc
spec:
selector:
app:nginx
ports:
-protocol:TCP
port:80
targetPort:80
#externalIPs:
#- 172.25.2.100
#clusterIP: None
#type: NodePort
type:LoadBalancer#指定一個 LoadBalancer 型別的 Service
---
apiVersion:apps/v1
kind:Deployment
metadata:
name:demo
spec:
replicas:3
selector:
matchLabels:
app:nginx
template:
metadata:
labels:
app:nginx
spec:
containers:
-name:nginx
image:myapp:v1
可以看到我們部署的nginx-svc已經分配到了一個地址池中的ip
metallb跟ingress結合起來使用
對於ingress的yaml檔案,可以複製過來進行修改,需要修改網路模式
從DeamonSet 型別修改成 Deployment型別
生效並檢視
# kubectl apply -f deploy.yaml
# kubectl -n ingress-nginx get all
此時訪問路徑為:user -> vip(metallb) -> ingress-nginx -> svc -> pod
示例
# cat nginx-svc.yml
apiVersion:v1
kind:Service
metadata:
name:nginx-svc
spec:
selector:
app:nginx
ports:
-protocol:TCP
port:80
targetPort:80
type:LoadBalancer
---
apiVersion:apps/v1
kind:Deployment
metadata:
name:deployment
spec:
replicas:3
selector:
matchLabels:
app:nginx
template:
metadata:
labels:
app:nginx
spec:
containers:
-name:nginx
image:myapp:v1
# cat ingress-demo.yml
apiVersion:networking.k8s.io/v1beta1
kind:Ingress
metadata:
name:nginx-test
spec:
# tls:
# - hosts:
# - www1.westos.org
# secretName: tls-secret
rules:
-host:www1.westos.org
http:
paths:
-path:/
backend:
serviceName:nginx-svc
servicePort:80
# kubectl apply -f nginx-svc.yml
# kubectl apply -f ingress-demo.yml
# kubectl get ingress
# kubectl describe ingress nginx-test
# kubectl get svc nginx-svc
這裡需要給這個ip做好地址解析,然後在外部訪問域名檢視效果。
calico網路外掛
calico簡介:
flannel實現的是網路通訊,calico的特性是在pod之間的隔離。
透過BGP路由,但大規模端點的拓撲計算和收斂往往需要一定的時間和計算資源。純三層的轉發,中間沒有任何的NAT和overlay,轉發效率最好。
Calico 僅依賴三層路由可達。Calico 較少的依賴性使它能適配所有 VM、Container、白盒或者混合環境場景。
calico網路架構
Felix:監聽ECTD中心的儲存獲取事件,使用者建立pod後,Felix負責將其網絡卡、IP、MAC都設定好,然後在核心的路由表裡面寫一條,註明這個IP應該到這張網絡卡。同樣如果使用者制定了隔離策略,Felix同樣會將該策略建立到ACL中,以實現隔離。
BIRD:一個標準的路由程式,它會從核心裡面獲取哪一些IP的路由發生了變化,然後透過標準BGP的路由協議擴散到整個其他的宿主機上,讓外界都知道這個IP在這裡,路由的時候到這裡來。
IPIP工作模式:適用於互相訪問的pod不在同一個網段中,跨網段訪問的場景。
BGP工作模式:適用於互相訪問的pod在同一個網段,適用於大型網路。
連結:https://www.cnblogs.com/hahaha111122222/p/17222696.html
(版權歸原作者所有,侵刪)
文末福利一
全款節省高至 4500 元!
直播間專屬禮包+3倍積分!
贈實戰專題
獎學金等你來拿!高達 500 元。
贈送阿里云云計算 ACP 考試券(價值 1200 元)
活動期間報名,送鑽石學習卡。
文末福利二
【AI大模型】訓練營(有回放)
馬哥教育創始人 馬哥親講
無論你是渴望提升技術能力的 IT 工程師,
還是希望深入瞭解大模型應用的運維人員或開發者,
本次大模型訓練營公開課都將為你提供寶貴的學習機會。
內容乾貨,還有現場抽獎和免費資料可領取↑
趕緊掃描下方二維碼,報名直播吧↑(有回放)