概述#
在 Service 章節,我們已經學會利用 Service 把叢集內的 Pod 暴露給外部使用。然而每個 Service 都需要綁定自己的對外連接埠,並且仰賴 Node 上的 port mapping,這代表「Service 越多,要管的 port number 也越多」。對使用者而言,網址後還要記憶連接埠號實在不夠友善,這正是 Ingress(路由守護神)登場的舞台。
什麼是 Ingress#
Ingress 可以替我們把對外的入口統一收斂在 HTTP 的 80 與 HTTPS 的 443 連接埠之上,並依照 hostname 或 pathname 將請求轉發到背後對應的 Service,等於是站在 Service 之上的一層 LoadBalancer。如此一來,前面提到 port number 雜亂的問題就被一次處理完。
Ingress 的職責#
- 路徑導流(give services externally-reachable URLs):用設定好的 hostname 與 pathname 對應到 Service,再由 Service 串到後面的 Pod。
- 流量負載均衡(load balance traffic):可以套用負載均衡演算法、後端權重等規則。
- SSL Termination:Ingress 在前面替 HTTPS 做解密,後段 Service 與 Pod 之間就能以明文溝通。
- 虛擬主機(offer name based virtual hosting):在同一個 IP 之下提供多個虛擬網域。
在 docker-desktop 上安裝 Ingress Controller#
本機環境只要套用官方提供的 Nginx Ingress 部署檔,Kubernetes 會替我們建立一個 ingress-nginx namespace 並把相關元件跑起來。
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.2.1/deploy/static/provider/cloud/deploy.yaml確認安裝結果:
kubectl get all -n ingress-nginx只要看到 ingress-nginx-controller 的 Pod 處於 Running,並且 Service 暴露出 80/443 連接埠,就代表 Ingress Controller 已經就緒。
實作一:以 defaultBackend 暴露單一 Service#
Ingress 提供 defaultBackend 設定,未匹配任何規則的流量都會被導到這個預設後端,等同於以 Ingress 統一暴露單一 Service。
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: foo-deployment
labels:
type: demo
spec:
replicas: 2
selector:
matchLabels:
type: demo
template:
metadata:
labels:
type: demo
spec:
containers:
- name: foo
image: mikehsu0618/foo
ports:
- containerPort: 8080# service.yaml
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
type: demo
type: NodePort
ports:
- protocol: TCP
port: 8000
targetPort: 8080
nodePort: 30390# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
spec:
ingressClassName: nginx
defaultBackend:
service:
name: my-service
port:
number: 8000這裡刻意把 Service type 從
LoadBalancer換成NodePort,因為對外端口已交由 Ingress 統一管理。
部署並驗證:
kubectl apply -f deployment.yaml,service.yaml,ingress.yaml
kubectl get ingress
curl localhost打到 localhost 的請求會循 Ingress → my-service → Pod 的路徑,回傳 {"data":"Hello foo"}。
實作二:Fanout 與虛擬主機#
Fanout 指的是同一個 IP 來源依照不同的 URL(host 或 path)分流到多個 Service。下面用兩個網域 foo.com 與 bar.com 各自對應到不同的 Service。
# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
spec:
ingressClassName: nginx
rules:
- host: foo.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: foo-service
port:
number: 8000
- host: bar.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: bar-service
port:
number: 8000部署完成後,可以用 kubectl describe ingress my-ingress 看到兩條 host 規則各自指向不同的 Service Endpoint。
由於是在本機跑虛擬網域,需要在 /etc/hosts 加入反向代理紀錄:
sudo vim /etc/hosts
# 新增
127.0.0.1 foo.com
127.0.0.1 bar.com實測:
curl http://foo.com # {"data":"Hello foo"}
curl http://bar.com # {"data":"Hello bar"}小結#
熟悉 Ingress 之後,本機上就有能力跑起一組「域名 + 路徑分流」的微型服務群。在 Service 之上把對外入口統一管理,是分散式系統與微服務架構走向成熟的第一步。
原文出處#
- GitHub:https://github.com/MikeHsu0618/2022-ithelp/tree/main/Day9
- iThome:https://ithelp.ithome.com.tw/articles/10288843