Skip to content
Open Source

服務之間的連線與對外連接埠

用私有位址連到同叢集的服務,把資料庫這類不走 HTTP 的連接埠開放到網際網路,並用連線規則限制誰能連進來。

服務的 網路 分頁管三件事:私有網路 列出叢集裡其他服務連到它的位址,對外連接埠 讓叢集外的用戶端不經網域直接連進來,連線規則 決定哪些服務能連進來、它能連到哪裡。公開網域和 HTTPS 見加上公開網域與 HTTPS。

  • 有權修改專案裡的服務。由 Helm、Argo CD 或 Flux 管理的服務不能從這裡開放連接埠或加規則,要回到那個工具修改。
  • 連線規則要靠叢集的網路外掛(CNI)執行。K3s 內建的控制器支援,外掛不支援時規則建得起來,但不會擋任何連線。
  • 開放連接埠要有負載平衡器。K3s 內建的 ServiceLB 和 Zeabur 安裝程式裝的 RKE2 都有。

私有網路 的每一列是一個 Kubernetes Service,例如 web:8080。同專案的服務直接用這個位址連線,例如 http://web:8080。

從其他專案連線時,用 從其他專案連線 後面的完整位址,例如 web.demo.svc.cluster.local:8080。專案 隔離 了的話,對方專案要先在專案 設定 的 網路 加進 允許其他專案連入,見隔離其他專案。

這些位址只在叢集裡有效,網際網路連不到。

只會主動往外連的背景服務不需要私有位址。要讓其他服務或公開網域連到它,先建立 Service。私有網路 會寫出可以複製的指令,例如:

kubectl -n demo expose deployment web --port=8080

就緒檢查用的是數字連接埠時,指令會直接帶上那個連接埠。否則指令會寫 --port=<port>,執行前把 <port> 換成應用程式監聽的連接埠。

資料庫、遊戲伺服器、MQTT 這類不走 HTTP 的服務,用對外連接埠讓叢集外的用戶端連進來。

到服務 網路 的 對外連接埠,按 開放連接埠,在 連接埠 選要開放的連接埠。只有私有位址上的連接埠可以選。

按 檢查變更,確認後套用。

列表會出現每個節點的位址和連接埠,例如 203.0.113.7:5432,旁邊有複製按鈕。顯示 連接埠 5432 正在等負載平衡器分配位址。 時,負載平衡器還在處理,或節點上這個連接埠已經有別的服務在用。

ServiceLB 會在每個節點監聽同一個連接埠號碼,所以整個叢集裡同一個連接埠號碼只能開放一次。同專案已經有服務開放了同一個連接埠時,Zeabur 會拒絕。

要關閉,在那一列按 關閉,檢查後套用。

連線規則 的上方寫出目前誰能連進來,例如 web 只接受 1 個服務連入,下面分成 連入 和 連出 兩欄列出允許、部分允許或封鎖的對象。專案沒有任何規則時,所有連線都允許。

按 新增規則,選一種:

規則效果
隔離這個服務只有同專案的副本能連進來。它只能連到同專案的服務和 DNS,連不到網際網路。
允許來自公開網域的流量讓 Traefik 把公開網域的請求送進來。
允許某個服務連入…選一個同專案的服務,讓它連進來。

規則可以疊加。常見的組合是先 隔離這個服務,再加 允許來自公開網域的流量 和需要連進來的服務。

要讓隔離的服務連到外部 API,到同一頁的 IP 限制 把位址加進 能連到哪裡,見限制能連入和連出的 IP。

要刪除規則,點規則名稱進入 物件 頁,在 YAML 檢視按 刪除。

私有位址是一般的 ClusterIP Service,對外連接埠是 LoadBalancer Service,連線規則是一般的 NetworkPolicy。以下以專案 demo 為例。

apiVersion: v1
kind: Service
metadata:
name: web
namespace: demo
labels:
app.kubernetes.io/name: web
spec:
selector:
app.kubernetes.io/name: web
ports:
- name: http
port: 8080
targetPort: 8080

selector 要和 Deployment 的 Pod 標籤相同。

Zeabur 開放連接埠時建立 <Service 名稱>-public-<連接埠>,複製來源 Service 的 selector 和那個連接埠,類型改成 LoadBalancer。標籤 app.kubernetes.io/name 是服務名稱,刪除服務時會一起刪掉。開放 db 的 5432:

apiVersion: v1
kind: Service
metadata:
name: db-public-5432
namespace: demo
labels:
app.kubernetes.io/name: db
spec:
type: LoadBalancer
selector:
app.kubernetes.io/name: db
ports:
- name: postgres
port: 5432
targetPort: 5432
protocol: TCP

關閉就刪除這個 Service:

kubectl -n demo delete service db-public-5432

Zeabur 建立的規則都帶 app.kubernetes.io/managed-by: zeabur 標籤,名稱是 zeabur-<規則>-<服務>,超過 63 個字元會截斷。以下以服務 api 為例。

隔離這個服務:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: zeabur-isolate-api
namespace: demo
labels:
app.kubernetes.io/managed-by: zeabur
spec:
podSelector:
matchLabels:
app.kubernetes.io/name: api
policyTypes: [Ingress, Egress]
ingress:
- from:
- podSelector: {}
egress:
- to:
- podSelector: {}
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53

允許某個服務連入,這裡讓 web 連到 api:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: zeabur-allow-web-api
namespace: demo
labels:
app.kubernetes.io/managed-by: zeabur
spec:
podSelector:
matchLabels:
app.kubernetes.io/name: api
policyTypes: [Ingress]
ingress:
- from:
- podSelector:
matchLabels:
app.kubernetes.io/name: web

允許來自公開網域的流量。規則允許兩個地方的 Traefik:K3s 內建的在 kube-system,Zeabur 安裝程式裝的在有 zeabur.com/platform: "true" 標籤的 Namespace:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: zeabur-allow-ingress-api
namespace: demo
labels:
app.kubernetes.io/managed-by: zeabur
spec:
podSelector:
matchLabels:
app.kubernetes.io/name: api
policyTypes: [Ingress]
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
podSelector:
matchLabels:
app.kubernetes.io/name: traefik
- namespaceSelector:
matchLabels:
zeabur.com/platform: "true"
podSelector:
matchLabels:
app.kubernetes.io/name: traefik

刪除規則:

kubectl -n demo delete networkpolicy zeabur-isolate-api

私有網路 列出每個 Service 和它的連接埠。對外連接埠 列出每個節點的位址,資料庫會標 資料庫對外開放。連線規則 列出套用到這個服務的規則名稱,以及 連入 和 連出 各自允許誰。

kubectl -n demo get service
kubectl -n demo get networkpolicy -l app.kubernetes.io/managed-by=zeabur
kubectl -n demo run probe --rm -it --restart=Never --image=busybox:1.37 -- wget -qO- -T 3 http://api:8080

get service 的 TYPE 欄,私有位址是 ClusterIP,對外連接埠是 LoadBalancer,EXTERNAL-IP 是節點的位址。最後一行從同專案一個臨時的副本連到 api。api 隔離了而且沒有允許 probe 時,會在 3 秒後逾時。從叢集外用 nc -vz 203.0.113.7 5432 確認對外連接埠連得上。

畫面或結果接著處理
web 沒有私有位址執行畫面上的 kubectl expose 指令,或套用上面的 Service。
kubectl expose 回覆 couldn't find port via --port flag or introspection容器沒有宣告連接埠。在 --port= 後面填應用程式監聽的連接埠。
一直顯示 正在等負載平衡器分配位址節點上這個連接埠已經有別的服務在用,或叢集沒有負載平衡器。換一個連接埠,或請管理員確認 ServiceLB。
開放連接埠時回覆已有服務開放同一個連接埠同專案已經開放了這個連接埠號碼,先關閉那一個。
隔離後公開網域逾時加上 允許來自公開網域的流量。
隔離後服務連不到外部 API隔離只允許連到同專案和 DNS。在 IP 限制 的 能連到哪裡 加上外部 API 的位址。
加了規則,連線卻照樣通叢集的網路外掛不支援 NetworkPolicy。