- 路由流量:根據特定的路徑或主機名稱將流量路由到不同的服務。
- 加密通信:使用TLS來保護HTTP和HTTPS流量的安全傳輸。
- 負載平衡:可以將流量分配到多個後端服務,以實現負載平衡和高可用性。
- URL重新寫入:可以將流量的URL重寫為另一個URL,以提供更友好的URL。
以下是使用NodePort和Ingress時URL的差異:
使用NodePort時的URL
- https://www.xxxx.com:30015
- https://www.xxxx.com:30016
使用Ingress時的URL
- https://www.xxxx.com/web-app
- https://www.xxxx.com/web-api
💡 可以看到使用Ingress路由的方式,在辨識度上會優於使用Port的方式
💡 Ingress本身不是一種Service type而是一種介面
Nginx Ingress Controller安裝
官方的描述,使用Ingress之前必須先安裝Ingerss Controller,如果單獨創建Ingress資源是不會有任何效果的哦!目前K8s支持和維護的Controller有AWS、GCE和我們要使用的Nginx Ingress其餘的控制器可以【點我前往】參考,這裡我們就直接選擇「Nginx Ingress」作為Ingress Controller安裝指南可以【點我前往】,接著輸入以下指令部署kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.5.1/deploy/static/provider/cloud/deploy.yaml
💡 指令包含了Nginx Ingress版本號,如果需要其它版本可以【點我前往】查詢
部署完成後使用以下指令查看Ingress的Pod是否有運作
kubectl get pods --namespace=ingress-nginx
如果想要查看所有關於Ingress-nginx的資源則可以使用以下指令
kubectl get all -n ingress-nginx
可以看到Nginx Ingress啟動了Service並且指到80和443Port,所以我們可以使用localhost去瀏覽器上執行看看就可以看到404的頁面囉(由於我們還沒有指定路由規則因此404是正常的)
💡 由於還沒有指定路由規則,因此看到404是正常的
非雲K8s集群 - MetalLB安裝
K8s預設並沒有提供一個功能完整的LoadBalancer實現。因此,需要使用一些第三方的輔助工具,因此如果安裝了Ingress Controller,在LoadBalancer都會是處於一個Pending的狀態,關於這些問題的相關提問可以【點我前往】參考
💡 以下環境預設都有包含LoadBalancer實現:「雲端」、「Docker Desktop Kubernetes」、「Minikube」
因此在我們自行搭設的K8s環境下就必須要安裝額外的套件來解決負載平衡的問題,Nginx Ingress提供了第三方的套件「MetalLB」相關資訊可以【點我前往】,首先需要先安裝MetalLB,直接使用以下指令,其餘安裝資訊可以【點我前往】
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.7/config/manifests/metallb-native.yaml
安裝完成後接著是定義地址的連線池【點我前往】,我們先使用指令查看目前的Node的IP資訊
kubectl get node -A -o wide
創建一個metallb-addressconfig.yaml的檔案,將我們的Node IP設定給連線池,設定好就可以部署上去
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: default
namespace: metallb-system
spec:
addresses:
- 192.168.135.129-192.168.135.129
autoAssign: true
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: default
namespace: metallb-system
spec:
ipAddressPools:
- default
💡Ingress Controller是Run在192.168.135.129的Node身上,因此只需要為該節點配置一個IP位置即可
kubectl apply -f metallb-addressconfig.yaml
最後再查看一次Ingress的詳細狀態就可以看到External-IP的欄位不再是Pending狀態囉!
kubectl get all -n ingress-nginx
編寫Ingress定義檔
編寫定義檔之前我們先規劃Nginx Ingress的路由規則,我希望根路由可以直接連到Web APP而Web API則是在子路由之下,定義如下:
- Web APP:http://localhost
- Web API:http://localhost/api
- Web API Swagger UI:http://localhost/api/Swagger/index.html
由於Nginx Ingress的原理是反向代理,因此如果要讓Web API可以處理虛擬路徑,就必須添加兩個MiddleWare(Web API專案為ASP Dot Net Core 6.0)才行,詳細的內容可以到微軟官網查看【點我參考】或是參考大神解說【點我參考】
app.UsePathBase("/xxxx");
app.UseRouting();
💡注意!UsePathBase後一定要UseRouting才會套用路由機制哦!
💡將UsePathBase調整成環境變數方便我們在K8s定義檔去做路由的定義,我們在appSettings.json裡面內添加一個【HostUrl__PathBase】的環境變數
Swagger的部分則是需要調整SwaggerEndpoint的路徑
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("v1/swagger.json", "v1");
});
}
💡注意!v1前面不能有斜線!
2023/03/17 補充:需要在ConfigureServices方法裡正確配置Swagger,並指定basePath
services.AddSwaggerGen(options =>
{
options.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
// 設置basePath,例如:/api
options.DocumentFilter<BasePathFilter<("/api");
});
上面的BasePathFilter是一個自定義過濾器
public class BasePathFilter : IDocumentFilter
{
private readonly string _basePath;
public BasePathFilter(string basePath)
{
_basePath = basePath;
}
public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
{
swaggerDoc.Servers.Add(new OpenApiServer { Url = _basePath });
}
}
調整後定義檔請參考以下:
apiVersion: apps/v1
kind: Deployment
metadata:
name: wadweb-deployment
labels:
app: wadweb-deployment
spec:
selector:
matchLabels:
app: wadweb
replicas: 2
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
type: RollingUpdate
template:
metadata:
name: wadweb
labels:
app: wadweb
spec:
containers:
- name: wadwebapp
image: "你的registryURL/wad-web:v2.0.0"
imagePullPolicy: Always
resources:
limits:
cpu: 200m
memory: 500Mi
requests:
cpu: 100m
memory: 200Mi
ports:
- containerPort: 80
name: http
- name: wadwebapi
image: "你的registryURL/wad-web-api:v2.0.0"
imagePullPolicy: Always
resources:
limits:
cpu: 2000m
memory: 2Gi
requests:
cpu: 1000m
memory: 1Gi
env:
- name: DOTNET_RUNNING_IN_CONATINER
value: "true"
- name: ASPNETCORE_ENVIRONMENT
value: "Development"
- name: ASPNETCORE_URLS
value: "http://+:8080"
- name: ConnectionStrings__DefaultConnection
value: "Server=你的SQLServer Connection;Initial Catalog=WADREQM;Persist Security Info=False;User ID=你的SQLServer帳號;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=true;Connection Timeout=30;"
- name: Connection__Key
value: "我是密碼"
- name: HostUrl__PathBase
value: "api"
- name: HostUrl__RemoteHost
value: "http://192.168.1.34:8080"
- name: TZ
value: "Asia/Taipei"
volumeMounts:
- name: fileupload
mountPath: /app/upload
ports:
- containerPort: 8080
name: http
volumes:
- name: fileupload
hostPath:
path: /run/desktop/mnt/host/d/Kubernetes/fileupload
type: DirectoryOrCreate
restartPolicy: Always
---
apiVersion: v1
kind: Service
metadata:
name: wadweb-service
spec:
type: ClusterIP
selector:
app: wadweb
ports:
- name: wadwebapp-port
port: 80
targetPort: 80
- name: wadapiapp-port
port: 8080
targetPort: 8080
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: wadweb-ingress
# annotations:
# nginx.ingress.kubernetes.io/ssl-redirect: "false"
# nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
ingressClassName: nginx
rules:
- http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: wadweb-service
port:
number: 8080
- path: /
pathType: Prefix
backend:
service:
name: wadweb-service
port:
number: 80
---
- metadata.annotations:這裡可以設定一些Ingress的客製化功能,如果是Nginx就可以設定如:rewrite-target、ssl-redirect等等的設定,詳細內容可以參考官網【點我前往】
- nginx.ingress.kubernetes.io/rewrite-target:重寫請求的URL的路徑,在不修改或是無法修改程式碼的情況就可以使用,詳細內容可以參考官網【點我前往】
- spec.ingressClassName:設定Ingress的類別,如果沒有設定或被省略則需要配置一個默認Ingress類(默認值是nginx),詳細內容可以參考官網【點我前往】
💡 在正式環境我會直接用rewrite target,因為不是所有的服務你都可以修改,因此用rewrite target是我覺得最彈性的方式
💡設定必須和Ingress Controller定義檔裡面的環境變數「ingress-class」一樣
- spec.rules.http.paths[].path:路由路徑名稱
- spec.rules.http.paths[].pathType:路徑匹配規則,可以依照使用情景設定
- Preflix:以/為分隔的URL路徑前綴匹配,前綴符合就符合規則,匹配有區分大小寫
- Exact:精確匹配URL路徑,且區分大小寫
💡關於Preflix和Exact的詳細規則可以【點我前往】參考 - spec.rules.http.paths[].backend:設定對應的服務以及其名稱和Port
💡Web API的路由設定為/api,對應到wadweb-service服務Port是8080
Web APP則直接使用根目錄,對應到wadweb-service服務Port則是80
部署設定好的Ingress定義檔
部署後可以使用以下指令查看Ingress資源,在詳細資源裡面可以看到根路由和子路由/api的入口已經指定到我們的Service以及其對應的Port了
kubectl get ingress
kubectl describe ingress wadweb-ingress
最後打開Chrome上直接使用定義好的路由,輸入「http://localhost」和「http://localhost/api」就可以連到Web APP和Web API囉!
使用Nginx Ingress的根路由可以導向Web APP |
使用Nginx Ingress的子路由/api/Swagger/index.html則可以導向Web API Swagger UI介面 |
API的部分使用PostMan打「http://localhost/api」Web API
如果我們有好幾個服務,每個服務都有各自的Port,在管理上也真的是很麻煩,因此我們透過Nginx Ingress將外部所有的流量集中起來,再經過設定好的的路由,把流量透過Service分派到各個Pod裡面,最終我們只需要管理一個Ingress和定義好路由規則即可,而Ingress本身又有負載平衡的功能【L7 LoadBalancer】就不會因為使用LoadBalance類型的Service(每個雲服務供應商的價格都不一樣)造成成本高的問題了!
使用Nginx Ingress的子路由/api |
如果我們有好幾個服務,每個服務都有各自的Port,在管理上也真的是很麻煩,因此我們透過Nginx Ingress將外部所有的流量集中起來,再經過設定好的的路由,把流量透過Service分派到各個Pod裡面,最終我們只需要管理一個Ingress和定義好路由規則即可,而Ingress本身又有負載平衡的功能【L7 LoadBalancer】就不會因為使用LoadBalance類型的Service(每個雲服務供應商的價格都不一樣)造成成本高的問題了!
0 Comments
張貼留言