在k8s中,pod可以隨時被建立,也可以隨時被移除。
如透過Deployments
來建立時,它時可是被k8s動態的建立或是移除,因為前面文章有提到hpa或是self healing都會造成pod的異動。
每個pod都有自己的ip,只要一建立就會產生一組ip,基於這個原因,如果pod間的溝通是透過ip的話,
會變成隨時要改ip才能打到pod,因為你不會知道pod何時更動。
官方對service的解釋如下
Kubernetes Service 定義了這樣一種抽象:邏輯上的一組 Pod,一種可以訪問它們的策略 —— 通常稱為微服務。 Service 所針對的 Pods 集合通常是通過選擇算符來確定的。 要瞭解定義服務端點的其他方法,請參閱不帶選擇算符的服務。
舉個例子,考慮一個圖片處理後端,它運行了 3 個副本。 這些副本是可互換的 —— 前端不需要關心它們調用了哪個後端副本。 然而組成這一組後端程式的 Pod 實際上可能會發生變化, 前端用戶端不應該也沒必要知道,而且也不需要跟蹤這一組後端的狀態。
Service 定義的抽象能夠解耦這種關聯。
網路看到一張可以解釋上面說明的圖
圖片來源
簡單來說,有了Service這一層,對使用者來說只要認識到Service
就夠了,使用者不用了解Deployments有幾個pod,我要打哪個pod,pod ip是什麼,不用擔心我會打到無效的pod,一切都交給Service層處理
apiVersion: v1
kind: Service
metadata:
name: test-myapp #服務名稱
spec:
type: ClusterIP # Service類型:ClusterIP,NodePort,LoadBalancer,ExternalName,預設是ClusterIP
selector:
app.kubernetes.io/name=test-myapp #要被存取的pod 名稱
ports: # 在service上面可以開多個接口,只要不重覆port就好了,像是服務有支援REST或是gRPC,就可以分別開二個port出來對應Http server跟gRPC server
- protocol: TCP
port: 80
targetPort: 80
- protocol: TCP
port: 8787
targetPort: 8787
除了寫service yaml外,也可以透過kubectl expose 做到一樣的是事情
kubectl expose deployment test-myapp --type=ClusterIP --name=test-myapp
selector對應的關係圖可以參考官方這張圖,簡單說就是透過selector的label去對應Deployment
圖片來源
kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
test-myapp ClusterIP 10.182.153.226 <none> 80/TCP,8787/TCP 10m
ClusterIP
: only for cluster內部使用,也是default Service type
NodePort
: 可以讓pod透過設定好的NodePort供外部服務存取,有點像是在Node上面打個小小洞,讓外面服務可以透過這個小小洞與內部pod溝通,這種做法有幾個缺點
LoadBalancer
:如果要把服務暴露給外部使用時,就可以使用LoadBalancer模式,一般是在AKS,GKE,EKS公有雲上使用時才會使用。
ExternalName
:將服務mapping到dns名稱,因為這個沒什麼使用的情境..所以可以參加這邊的說明 官方externalname說明
透過Service就可以輕鬆的把Deployment expose出去給其他服務呼叫囉
這邊推薦一下官方的tutorials,手把手教你使用service吧服務expose出去