叢集內服務
一般 pod 都是根據 service 資源來進行叢集內的暴露,因為 k8s 在 pod 啟動前就已經給排程節點上的 pod 分配好 ip 地址了,因此我們並不能提前知道提供服務的 pod 的 ip 地址。那麼 service 服務提供的功能就是,使用者根本無需關心後端提供服務 pod 的數量,以及各自對應的 ip 地址。
服務資源會被 k8s 分配一個 cluster-ip 叢集 ip,只能在叢集內部可以被存取。而在叢集內 k8s 如何設定服務網路的,可以參考之前的網路服務,實際上就是利用 iptables 來進行網路的設定。除此之外 k8s 還可以設定對談的親和性,因為有可能需要請求落入容一個pod,設定服務的 sessionAffinity 屬性為 clientIP。
apiVersion: v1
kind: Service
spec:
sessionAffinity: ClientIP
這種方式會將服務代理將來自同一個 clientip 的所有請求轉發到同一個 pod 上。k8s 僅僅支援兩種形式的對談親和性服務:None和ClientIP。但是不支援 cookie 的對談親和性選項,因為 k8s 服務不是在 HTTP 層面上工作,服務處理 TCP 和 UDP 包,並不關心其中封包內容,畢竟解包封包都是需要耗費資源的。
而且同一個服務還可以暴露多個埠,比如一個 pod 中監聽兩個埠,HTTP 監聽 8080,HTTPS 監聽 8443,可以使用一個服務從埠 80 和 443 轉發到 pod 埠 8080 和 8443。比如宣告 service 暴露多個埠
apiVersion: v1 kind: Service metadata: name: kubia spec: ports: - name: http port: 80 targetPort: 8080 // pod 的8080埠對映成 80 埠 - name: https port: 443 targetPort: 8443 selector: app: kubia
叢集外暴露的服務
將服務暴露給外部使用者端的方法有以下幾種:
建立 NodePort 型別的服務
apiVersion: v1 kind: Service metadata: name: kubia-nodeport spec: type: NodePort ports: - port: 80 targetPort: 8080 nodePort: 30123 // 通過部署的叢集節點中的 30123 埠可以存取該服務 selector: app: kubia
在叢集內兩個節點暴露了 30123 埠,到達任何一個節點上埠的傳入連線將被重定向到一個隨機選擇的pod。
通過負載均衡器建立服務
k8s 必須在支援 LoadBalance 服務的環境下才能建立此型別的負載均衡器服務。宣告如下
apiVersion: v1 kind: Service metadata: name: kubia-loadbalancer spec: type: LoadBalancer ports: - port: 80 targetPort: 8080 selector: app: kubia
那麼 nodeport 和 LB 型別的有什麼不同呢?
$ kubectl get svc kubia-nodeport NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubia-nodeport NodePort 10.99.194.15 <nodes> 9000:31090/TCP 1m $ kubectl get svc kubia-nodeport NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubia-loadbalance LoadBalancer 10.99.194.15 130.211.53.173 80:32143/TCP 1m
注意的是在
nodeport 型別和 LoadBalance 型別的服務在 external-ip 不一樣的是,LB是有外部ip暴露的。通過存取 LB 的外部ip就可以存取到叢集內部服務了。
建立 Igress 服務
為什麼需要LB的服務,其實最重要的是有獨立公有 ip 地址,當用戶端向 Ingress 傳送 HTTP 請求時,Ingress 會根據請求的主機名和路徑決定請求轉發到的服務。
Ingress 通過在網路棧 http 的應用層操作,可以提供一些服務不能實現的功能,比如 cookie 的對談親和性等功能。
建立 Ingress 資源
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: kubia spec: rules: - host: kubia.example.com // ingress 將域名對映到你的服務上 http: path: / backend: serviceName: kubia-nodeport // 將請求傳送到 kubia-nodeport 服務的 80 埠 servicePort: 80
要讓 LB 正常工作,也就是通過 kubia.example.com 存取到對應的服務,必須確保在 k8s 叢集內域名解析為 Ingress 的控制器,所以這需要基礎設施的支援。
在 k8s 檢視 ingress 資源
NAME HOST ADDRESS PORTS AGE kubia kubia-example.com 192.168.99.100 80 75d
所以在叢集中需要確保這樣的解析,需要路由器支援設定
192.168.99.100 kubia.example.com
如圖,首先使用者端會對 kubia.example.com 執行 DNS 查詢,DNS 伺服器或者本地作業系統返回了 Ingress 控制器的 IP。使用者端然後向 Ingress 控制器傳送 HTTP 請求,並在 host 頭中指定 kubia.example.com。控制器從該頭部確定使用者端應該存取哪個服務,通過與該服務關聯的 endpoint 物件檢視 podip,並將請求傳送到某個 pod。
最後再說明一下將不同服務對映到相同主機的不同路徑:
- host: kubia.example.com http: paths: - path: /kubia backend: serviceName: kubia servicePort: 80 - path: /foo backend: serviceName: bar servicePort: 80