目錄
一、概述
版本對比圖
二、 Ingress應用案例
2.1 環境準備
2.2 驗證-NodePort模式
設置Http代理
2.3 驗證-LoadBalancer模式
修改ARP模式,啟用嚴格ARP模式
搭建metallb支持LoadBalancer
普通的service測試
ingress訪問測試:
一、概述
Service對集群之外暴露服務的主要方式有兩種:NotePort和LoadBalancer,但是這兩種方式,都有一定的缺點:
-
NodePort方式的缺點是會占用很多集群機器的端口,那么當集群服務變多的時候,這個缺點就愈發明顯。
-
LB方式的缺點是每個service需要一個LB,浪費、麻煩,并且需要kubernetes之外設備的支持。
基于這種現狀,kubernetes提供了Ingress資源對象,Ingress只需要一個NodePort或者一個LB就可以滿足暴露多個Service的需求。工作機制大致如下圖表示:
實際上,Ingress相當于一個7層的負載均衡器,是kubernetes對反向代理的一個抽象,它的工作原理類似于Nginx,可以理解成在Ingress里建立諸多映射規則,Ingress Controller通過監聽這些配置規則并轉化成Nginx的反向代理配置 , 然后對外部提供服務。在這里有兩個核心概念:
-
ingress:kubernetes中的一個對象,作用是定義請求如何轉發到service的規則
-
ingress controller:具體實現反向代理及負載均衡的程序,對ingress定義的規則進行解析,根據配置的規則來實現請求轉發,實現方式有很多,比如Nginx, Contour, Haproxy等等
Ingress(以Nginx為例)的工作原理如下:
-
用戶編寫Ingress規則,說明哪個域名對應kubernetes集群中的哪個Service
-
Ingress控制器動態感知Ingress服務規則的變化,然后生成一段對應的Nginx反向代理配置
-
Ingress控制器會將生成的Nginx配置寫入到一個運行著的Nginx服務中的pod,并動態更新
-
到此為止,其實真正在工作的就是一個Nginx了,內部配置了用戶定義的請求轉發規則
版本對比圖
二、 Ingress應用案例
2.1 環境準備
搭建ingress環境
# 創建文件夾
[root@k8s-master01 ~]# mkdir ingress-controller
[root@k8s-master01 ~]# cd ingress-controller/
?
# 獲取ingress-nginx,本次案例使用的是1.12.0版本
[root@k8s-master01 ingress-controller]# wget https://github.com/kubernetes/ingress-nginx/releases/tag/controller-v1.12.0/ingress-nginx-controller-v1.12.0.zip
[root@k8s-master01 ingress-controller]# unzip ingress-nginx-controller-v1.12.0.zip
[root@k8s-master01 ingress-controller]# cd ingress-nginx-controller-v1.12.0/deploy/static/provider/cloud
[root@k8s-master01 cloud]# ls
deploy.yaml kustomization.yaml
?
#####外部訪問策略:
externalTrafficPolicy: Local
### Cluster:流量會在集群內的所有節點之間進行負載均衡,可能會導致網絡跳轉,即流量可能會先到達一個節點,然后再被轉發到其他節點上的服務實例。
### Local:流量只會被轉發到接收請求的節點上的服務實例,這樣可以避免額外的網絡跳轉,但可能會導致某些節點上的服務實例接收不到流量,尤其是當服務實例在集群中分布不均勻時。
##查看并修改鏡像源為如下:
?
[root@k8s-master01 cloud]# cat deploy.yaml | grep -n image
445: ? ? ? image: registry.k8s.io/ingress-nginx/controller:v1.12.0
547: ? ? ? image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v1.5.0
601: ? ? ? image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v1.5.0
?#########部署#############
[root@k8s-master01 cloud]# kubectl apply -f deploy.yaml
namespace/ingress-nginx created
serviceaccount/ingress-nginx created
serviceaccount/ingress-nginx-admission created
role.rbac.authorization.k8s.io/ingress-nginx created
role.rbac.authorization.k8s.io/ingress-nginx-admission created
clusterrole.rbac.authorization.k8s.io/ingress-nginx created
clusterrole.rbac.authorization.k8s.io/ingress-nginx-admission created
rolebinding.rbac.authorization.k8s.io/ingress-nginx created
rolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
configmap/ingress-nginx-controller created
service/ingress-nginx-controller created
service/ingress-nginx-controller-admission created
deployment.apps/ingress-nginx-controller created
job.batch/ingress-nginx-admission-create created
job.batch/ingress-nginx-admission-patch created
ingressclass.networking.k8s.io/nginx created
validatingwebhookconfiguration.admissionregistration.k8s.io/ingress-nginx-admission created
[root@k8s-master01 cloud]# kubectl -n ingress-nginx get pod
NAME ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? READY ? STATUS ? ? RESTARTS ? AGE
ingress-nginx-admission-create-sgksd ? ? ? ?0/1 ? ? Completed ? 0 ? ? ? ? 77s
ingress-nginx-admission-patch-f4rdc ? ? ? ? 0/1 ? ? Completed ? 1 ? ? ? ? 77s
ingress-nginx-controller-565cc5ddd9-2qwnm ? 1/1 ? ? Running ? ? 0 ? ? ? ? 77s
?
[root@k8s-master01 cloud]# kubectl -n ingress-nginx get svc
NAME ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? TYPE ? ? ? ? ? CLUSTER-IP ? ? EXTERNAL-IP ? PORT(S) ? ? ? ? ? ? ? ? ? ? AGE
ingress-nginx-controller ? ? ? ? ? ? LoadBalancer ? 10.10.103.132 ? <pending> ? ? 80:31502/TCP,443:31020/TCP ? 96s
ingress-nginx-controller-admission ? ClusterIP ? ? ?10.10.227.21 ? <none> ? ? ? ?443/TCP ? ? ? ? ? ? ? ? ? ? 96s
?
?
##查看集群已經存在的nginx類型
[root@k8s-master01 cloud]# kubectl get ingressclass
NAME ? CONTROLLER ? ? ? ? ? ? PARAMETERS ? AGE
nginx ? k8s.io/ingress-nginx ? <none> ? ? ? 2m53s
2.2 驗證-NodePort模式
準備service和pod
創建nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:labels:app: nginx-deployname: nginx-deploy
spec:replicas: 3selector:matchLabels:app: nginx-deploytemplate:metadata:labels:app: nginx-deployspec:containers:- image: nginx:latestimagePullPolicy: IfNotPresentname: nginxports:- containerPort: 80
---
?
apiVersion: v1
kind: Service
metadata:labels:app: nginx-deployname: nginx-svc
spec:ports:- port: 80protocol: TCPtargetPort: 80selector:app: nginx-deploytype: ClusterIP
?# 創建
[root@k8s-master01 ingress-controller]# kubectl apply -f nginx.yaml
deployment.apps/nginx-deploy created
service/nginx-svc created
?
?
# 查看
[root@k8s-master01 ingress-controller]# kubectl get pod
NAME ? ? ? ? ? ? ? ? ? ? ? ? ? READY ? STATUS ? RESTARTS ? AGE
nginx-deploy-7c7b68644b-26jtl ? 1/1 ? ? Running ? 0 ? ? ? ? 20s
nginx-deploy-7c7b68644b-5jsmb ? 1/1 ? ? Running ? 0 ? ? ? ? 20s
nginx-deploy-7c7b68644b-rjc4r ? 1/1 ? ? Running ? 0 ? ? ? ? 20s
?
[root@k8s-master01 ingress-controller]# kubectl get svc
NAME ? ? ? ? TYPE ? ? ? CLUSTER-IP ? ? EXTERNAL-IP ? PORT(S) ? AGE
kubernetes ? ClusterIP ? 10.10.0.1 ? ? <none> ? ? ? ?443/TCP ? 13d
nginx-svc ? ClusterIP ? 10.10.199.33 ? <none> ? ? ? ?80/TCP ? 36s
修改ingress代理模式
[root@k8s-master01 ingress-controller]# kubectl -n ingress-nginx edit svc ingress-nginx-controller 49 ? type: NodePort50 status:51 ? loadBalancer: {}
##查看
[root@k8s-master01 ingress-controller]# kubectl -n ingress-nginx get svc
NAME ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? TYPE ? ? ? CLUSTER-IP ? ? EXTERNAL-IP ? PORT(S) ? ? ? ? ? ? ? ? ? ? AGE
ingress-nginx-controller ? ? ? ? ? ? NodePort ? ?10.10.103.132 ? <none> ? ? ? ?80:31502/TCP,443:31020/TCP ? 10m
ingress-nginx-controller-admission ? ClusterIP ? 10.10.227.21 ? <none> ? ? ? ?443/TCP ? ? ? ? ? ? ? ? ? ? 10m
設置Http代理
創建ingress-http.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress # 創建一個類型為Ingress的資源
metadata:name: nginx-ingress # 這個資源的名字為 nginx-ingress
spec:ingressClassName: nginx # 使用nginxrules:- host: nginx.jx.com # 訪問此內容的域名http:paths:- backend:service:name: nginx-svc # 對應nginx的服務名字,該規則的namespace必須與service的一致port:number: 80 # 訪問的端口path: / # 匹配規則pathType: Prefix # 匹配類型,這里為前綴匹配
?
######
#Exact(精確匹配):
#當 PathType 的值為 Exact 時,意味著服務的路由規則將僅在傳入請求的路徑與指定的路徑完全相同時才會被匹配。
#例如,如果一個服務的路徑配置為 /api/v1/resource 且 PathType 為 Exact,那么只有當請求的路徑是 /api/v1/resource 時,該服務才會被選中處理請求,多一個字符或少一個字符都不會匹配,包括 /api/v1/resource/ 或者 /api/v1/resource?id=1 這樣的請求路徑都不會被該服務處理,這是一種非常嚴格的精確匹配規則。
#Prefix(前綴匹配):
#當 PathType 的值為 Prefix 時,服務將匹配以指定路徑作為前綴的請求路徑。
#例如,如果一個服務的路徑配置為 /api/v1 且 PathType 為 Prefix,那么 /api/v1、/api/v1/resource、/api/v1/resource/1 等以 /api/v1 開頭的請求路徑都會被該服務處理,只要請求路徑以 /api/v1 開頭,該服務就會處理該請求,而不要求請求路徑完全等于 /api/v1。# 創建
[root@k8s-master01 ~]# kubectl create -f ingress-http.yaml
ingress.extensions/ingress-http created
?
# 查看
[root@k8s-master01 ingress-controller]# kubectl get ingress nginx-ingress
NAME ? ? ? ? ? CLASS ? HOSTS ? ? ? ? ADDRESS ? ? ? ? PORTS ? AGE
nginx-ingress ? nginx ? nginx.jx.com ? 10.10.103.132 ? 80 ? ? 31s
?
?
?
# 查看詳情
[root@k8s-master01 ~]# kubectl describe ingress nginx-ingress
Name: ? ? ? ? ? ? nginx-ingress
Labels: ? ? ? ? ? <none>
Namespace: ? ? ? default
Address: ? ? ? ? ?10.10.26.150
Ingress Class: ? nginx
Default backend: <default>
Rules:Host ? ? ? ? Path Backends---- ? ? ? ? ?---- ?--------nginx.jx.com ?/ ? nginx-svc:80 (172.16.69.202:80,172.16.79.74:80,172.16.79.75:80)
Annotations: ? <none>
Events:Type ? Reason Age ? ? ? ? ? ? ? ? From ? ? ? ? ? ? ? ? ? ? Message---- ? ?------ ?---- ? ? ? ? ? ? ? ?---- ? ? ? ? ? ? ? ? ? ? ?-------Normal Sync ? 9m2s (x2 over 14m) nginx-ingress-controller Scheduled for sync
?
[root@k8s-master ~]# kubectl -n ingress-nginx get po -o wide
NAME ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? READY ? STATUS ? ? RESTARTS ? AGE ? IP ? ? ? ? ? ? ? NODE ? ? ? NOMINATED NODE ? READINESS GATES
ingress-nginx-admission-create-qmdj9 ? ? ? ?0/1 ? ? Completed ? 0 ? ? ? ? 21m ? 10.244.36.89 ? ? k8s-node1 ? <none> ? ? ? ? ? <none>
ingress-nginx-admission-patch-htkxb ? ? ? ? 0/1 ? ? Completed ? 0 ? ? ? ? 21m ? 10.244.36.90 ? ? k8s-node1 ? <none> ? ? ? ? ? <none>
ingress-nginx-controller-7d7455dcf8-5s9q5 ? 1/1 ? ? Running ? ? 0 ? ? ? ? 21m ? 10.244.169.157 ? k8s-node2 ? <none> ? ? ? ? ? <none>
?
#在訪問節點寫入hosts解析記錄,由于ingress-controller運行再node2節點,所以hosts要寫成node2的節點IP地址
127.0.0.1 ? localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 ? ? ? ? localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.158.17 nginx.jx.com
?
##測試,只能使用域名訪問
[root@k8s-master01 ingress-controller]# curl nginx.jx.com:31502
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
?
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
?
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
2.3 驗證-LoadBalancer模式
修改ARP模式,啟用嚴格ARP模式
# 執行修改操作
kubectl get configmap kube-proxy -n kube-system -o yaml | \
sed -e "s/strictARP: false/strictARP: true/" | \
kubectl apply ?-f - -n kube-system#或者
kubectl get configmap kube-proxy -n kube-system -o yaml | sed -e "s/strictARP: false/strictARP: true/" | kubectl apply ?-f - -n kube-system
#查看修改結果
kubectl edit configmap -n kube-system kube-proxy
為什么要修改嚴格模式?
-
避免 ARP 沖突
-
在默認情況下,容器網絡可能會出現一些非預期的 ARP 行為。在 Load Balancer 模式下,流量需要準確地被分發到后端的 Pod。如果不啟用嚴格 ARP 模式,可能會出現多個 Pod 響應同一個 ARP 請求的情況。
-
例如,假設在一個集群中有多個 Pod 提供相同的服務,并且它們在同一個子網中。如果沒有嚴格的 ARP 控制,負載均衡器可能會收到來自多個 Pod 的 ARP 響應,導致流量分發混亂,影響服務的正常運行。
-
-
確保流量正確分發
-
嚴格 ARP 模式可以確保只有正確的后端 Pod 響應 ARP 請求。這樣,負載均衡器能夠準確地將流量發送到預期的 Pod。
-
以一個 Web 應用程序為例,當外部用戶通過負載均衡器訪問該應用時,負載均衡器需要將請求發送到正確的 Web 服務器 Pod。通過啟用嚴格 ARP 模式,就像是給每個 Pod 一個 “專屬標簽”,只有擁有該標簽(正確 MAC 地址)的 Pod 才會響應 ARP 請求,從而保證請求能夠準確無誤地到達提供服務的 Pod。
-
-
增強網絡安全性和穩定性
-
限制 ARP 響應可以防止惡意的 Pod 或者受到攻擊的 Pod 干擾網絡通信。如果一個被入侵的 Pod 隨意響應 ARP 請求,可能會導致中間人攻擊或者流量劫持等安全問題。
-
嚴格 ARP 模式可以防止這種情況的發生,使得網絡通信更加安全和穩定。例如,在一個多租戶的 Kubernetes 集群環境中,不同租戶的 Pod 之間通過嚴格的 ARP 模式來隔離網絡通信,避免租戶之間的相互干擾和安全威脅。
-
搭建metallb支持LoadBalancer
Metallb 在 Kubernetes 中的作用主要是為沒有運行在如 AWS、GCP 等具有完善網絡服務的云平臺上的集群,提供網絡負載均衡器的實現。
-
實現 LoadBalancer 服務類型:在 Kubernetes 中,Service 有多種類型,其中 LoadBalancer 類型通常需要外部的負載均衡器支持。Metallb 可以在缺乏原生云平臺負載均衡支持的環境下,模擬實現 LoadBalancer 類型的 Service。它能夠為應用提供可從集群外部訪問的固定 IP 地址。
-
IP 地址分配與管理:負責在指定的 IP 地址范圍(IP address pool)內,為 LoadBalancer 類型的 Service 分配 IP 地址,并確保這些 IP 地址的正確映射和管理,使外部流量能夠準確地路由到相應的 Kubernetes 服務后端 Pod。
-
提供高可用的網絡連接:通過實現 BGP(Border Gateway Protocol)或 Layer2 模式的負載均衡機制,確保即使在節點故障或網絡波動的情況下,也能維持應用的外部網絡連接的穩定性和可靠性。
#版本
metallb-0.14.8
cd /root/metallb-0.14.8/config/manifests
kubectl apply -f metallb-native.yaml
##編寫地址段分配configmap
#創建IP地址池
cat >IPAddressPool.yaml<<EOF
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:name: planip-pool #這里與下面的L2Advertisement的ip池名稱需要一樣namespace: metallb-system
spec:addresses:- 192.168.158.135-192.168.158.150 #自定義ip段
EOF
#關聯IP地址池
cat >L2Advertisement.yaml<<EOF
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:name: planip-poolnamespace: metallb-system
spec:ipAddressPools:- planip-pool #這里需要跟上面ip池的名稱保持一致
EOF
?
?
####
?
?
?
kubectl apply -f IPAddressPool.yaml
kubectl apply -f L2Advertisement.yaml
?
?
[root@k8s-master01 manifests]# kubectl -n metallb-system get pod
NAME ? ? ? ? ? ? ? ? ? ? ? ? READY ? STATUS ? RESTARTS ? AGE
controller-7476b58756-q7cql ? 1/1 ? ? Running ? 0 ? ? ? ? 6m
speaker-55l64 ? ? ? ? ? ? ? ? 1/1 ? ? Running ? 0 ? ? ? ? 6m
speaker-8jjg8 ? ? ? ? ? ? ? ? 1/1 ? ? Running ? 0 ? ? ? ? 6m1s
普通的service測試
[root@k8s-master01 ingress-controller]# cat nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:labels:app: nginx-deploy1name: nginx-deploy1
spec:replicas: 3selector:matchLabels:app: nginx-deploy1template:metadata:labels:app: nginx-deploy1spec:containers:- image: nginximagePullPolicy: IfNotPresentname: nginx1ports:- containerPort: 80
---
?
apiVersion: v1
kind: Service
metadata:labels:app: nginx-deploy1name: nginx-svc1
spec:ports:- port: 80protocol: TCPtargetPort: 80selector:app: nginx-deploy1type: LoadBalancer
##提交
[root@k8s-master01 ingress-controller]# kubectl apply -f nginx.yaml
##查看
[root@k8s-master01 ingress-controller]# kubectl get pod
NAME ? ? ? ? ? ? ? ? ? ? ? ? ? READY ? STATUS ? RESTARTS ? AGE
nginx-deploy-5f87d95c-7ph78 ? ? 1/1 ? ? Running ? 0 ? ? ? ? 50m
nginx-deploy-5f87d95c-dswvq ? ? 1/1 ? ? Running ? 0 ? ? ? ? 50m
nginx-deploy-5f87d95c-vk9vg ? ? 1/1 ? ? Running ? 0 ? ? ? ? 50m
nginx-deploy1-c8d58b5c7-7dfrd ? 1/1 ? ? Running ? 0 ? ? ? ? 12m
nginx-deploy1-c8d58b5c7-d2hd7 ? 1/1 ? ? Running ? 0 ? ? ? ? 12m
nginx-deploy1-c8d58b5c7-pfvhn ? 1/1 ? ? Running ? 0 ? ? ? ? 12m
?
?
[root@k8s-master ingress]# kubectl get svc
NAME ? ? ? ? TYPE ? ? ? ? ? CLUSTER-IP ? ? ? EXTERNAL-IP ? ? ? PORT(S) ? ? ? AGE
kubernetes ? ClusterIP ? ? ?10.96.0.1 ? ? ? <none> ? ? ? ? ? ?443/TCP ? ? ? 8d
nginx-svc ? ClusterIP ? ? ?10.110.232.77 ? <none> ? ? ? ? ? ?80/TCP ? ? ? ? 95m
nginx-svc1 ? LoadBalancer ? 10.107.207.235 ? 192.168.158.136 ? 80:30099/TCP ? 10m
?
##測試訪問
[root@k8s-master01 ingress-controller]# curl 192.168.158.136
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
?
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
?
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
?
apiVersion: networking.k8s.io/v1
kind: Ingress # 創建一個類型為Ingress的資源
metadata:name: nginx-ingress # 這個資源的名字為 nginx-ingress
spec:ingressClassName: nginx # 使用nginxrules:- host: nginx.jx.com # 訪問此內容的域名http:paths:- backend:service:name: nginx-svc # 對應nginx的服務名字port:number: 80 # 訪問的端口path: / # 匹配規則pathType: Prefix # 匹配類型,這里為前綴匹配- host: nginx2.jx.com # 訪問此內容的域名http:paths:- backend:service:name: nginx-svc1 # 對應nginx的服務名字port:number: 80 # 訪問的端口path: / # 匹配規則pathType: Prefix # 匹配類型,這里為前綴匹配
修改ingress模式:
[root@k8s-master01 ~]# kubectl -n ingress-nginx edit svc ingress-nginx-controllertype: LoadBalancer
status:loadBalancer: {}
ingress訪問測試:
使用域名直接訪問即可!!!
curl nginx.jx.com
curl nginx2.jx.com