Kubernetes 的外部訪問方式
前言
我們知道在 K8s 集羣內部,由於 pod 的不可靠性引入了 service 的概念,將提供相同服務若干副本的 pod 通過標籤創建一個 service ,集羣內部通過訪問該 service 通過 Endpoint 負載均衡到 pod 來實現服務請求。
那麼 K8s 如何提供外部訪問方式呢?
NodePort
每個集羣節點都會在節點上打開一個端口,並將在端口上接受到的流量重定向到基礎服務,可以通過所有節點的專用端口訪問。
如圖,可以通過所有 Node 的該 Port 訪問
使用
創建一個服務並將其類型設置爲 NodePort,通過創建 NodePort 服務,可以讓 K8s 在所有節點上保留一個端口,將傳入的連接轉發給服務部分的 pod。
apiVersion: v1
kind: Service
metadata:
name: nginx-nodeport
spec:
type: NodePort # 類型 NodePort
ports:
- port: 80 # Pod 端口
targetPort: 8080 # ClusterIP Port
nodePort: 30080 # 外部訪問 NodePort,不寫會隨機
selector:
app: nginx2
LoadBalancer
LoadBalancer 本質上來說是 NodePort 的擴展,通常需要在支持自動提供負載均衡器的雲基礎架構上運行。
使用
創建服務後,通過 external-ip 來提供訪問服務。
apiVersion: v1
kind: Service
metadata:
name: nginx-lb
spec:
type: LoadBalancer # 類型 LoadBalancer
ports:
- port: 80 # Pod 端口
targetPort: 80 # ClusterIP Port
selector:
app: nginx2
Ingress
引入 Ingress 的一個重要原因是每個 LoadBalancer 服務都需要自己的負載均衡器,以及獨立的公有 IP 地址,而 Ingress 只需要一個公網 IP 就可以爲許多服務提供訪問。當客戶端向 Ingress 發送 HTTP 請求時,Ingress 會根據請求的主機名和路徑決定請求轉發到的服務;
要想 Ingress 資源正常工作,必須要有 Ingress 控制器在集羣中運行,可以選擇不同的 Ingress 控制器,如:Nginx/Envoy/Treafik/Kong,或一些公有云提供的服務。
使用
功能迭代較快,下面提供 k8s 版本 v1.17.2,使用 nginx 作爲 ingress-controller
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: test-ingress-1
annotations:
nginx.ingress.kubernetes.io/rewrite-target: / # (1)
spec:
rules:
- host: test.example.com # (2)
http:
paths:
- path: /foo # (3)
backend:
serviceName: nginx-service # (4)
servicePort: 80
- path: /bar
backend:
serviceName: nginx-service2
servicePort: 80
(1) nginx 作爲 controller 時需要的註解,路徑匹配說明詳情見https://kubernetes.io/zh/docs/concepts/services-networking/ingress/
(2) 訪問的主機名
(3) 路徑
(4) 對應的服務
創建 Ingress 資源,當訪問 test.example.com/foo 時,轉到 nginx-service 服務,且端口爲 80;當訪問 test.example.com/bar 時,轉到 nginx-service2 服務,且端口爲 80.
*k8s v18 後,需要多加入 pathType 選項,如 Prefix,Exact。
Port Forward
除了上述幾種提供外部訪問 pod 的方式,額外描述一種在調試時快速訪問 pod 的方法:
通過 kubectl port-forward 命令,它可以在本機上開啓一個轉發端口,間接轉發到 K8s 內部的某個 Pod 的端口上。這種方式是TCP轉發,不限於HTTP。
kubectl port-forward test2-nginx 8888:80 --address 0.0.0.0 (綁定到0.0.0.0)