Kubernetes - Service 學習紀錄

Posted by Kubeguts on 2021-05-22

Service 核心概念

由於Pods可能會不斷的被Deployment重新啟動,每次啟動都會有不一樣的internal ip address,這使得外部要呼叫Pod內的服務會變得非常麻煩

所以若要能夠使每個pod之間都能夠曉得彼此要怎麼溝通,或是前端要呼叫某個pods內的後端API,這時候Service就可以擔任一個中介的角色

Service就是扮演主要窗口

Service提供固定的ip,供對外呼叫,並且負責繫結Pods

這時候對於Pods的label定義就特別重要,因為Service要怎麼知道綁定哪個Pod,就是透過labels

  • Service透過selector認定labelmy-app的pods
要注意service的selector只能找到同一個namespace底下的pods

pic13

Service應用場景

  • 流量控管
    • 透過selector方式,可隨時切分流量
  • A/B 測試

Service 網路探討

Pods怎麼找到Service

剛剛有提到Service是透過selector,來找出Pod是否有對應的label

那Pod又是如何找到Service? 並透過Service與其他Pod溝通?

其過程是透過 kube-dns 來解析Service的DNS名稱,得到對應的cluster ip

pic17

kube-dns在k8s cluster建立後就會被建立

每次Pod建立,k8s都會在Pod的/etc/resolve.conf中,自動加入kube-dns服務的domain name以及對應的ip,所以其他的Pods可以透過 kube-dns的Service來找到正在運行的 kube-dns服務

pic15

在自己啟動的nginx pod內/etc/resovle.conf可看到 nameserver的ip就是kube-dns的cluster ip

pic16

Service又是如何找到Pods

關鍵在於透過Pods所處Node之iptable rules,下圖可以清楚了解Service透過iptable rules,查找到對應Pod內的container服務

kube-proxy會在service創建的時候,將Service的ip記錄到node內的iptables, Service透過Node的iptables找到Pods服務。

pic24

Service 種類

ClusterIP (預設值)

將service對接在cluster的內部IP,使Pod之間可以互相溝通,即便Pod再不同的Node

pic19

簡單來說就是給內部Node使用的Service

NodePort

將service對接在每一個Node的靜態IP

Service會在綁定Node的固定IP與port號,提供給外部呼叫

pic20

可以給node外部呼叫的service

LoadBalancer

將service變成load balancer角色,並需要提供一對外IP供客戶端呼叫

pic21

ExternalName

將service當作是一個與DNS介接的中介角色,當DNS換ip位置了,只要更動ExternalName這個Service,就可以不用更動每個Pod所要介接DNS的新位置

pic22

Service 使用情境

前後端套用Service與Pods的情境

分別有兩個Node,一個是前端,另外一個是後端,各自都有Service Type為NodePort
前端的service給對外呼叫,後端的Service給前端的Pods做連接

pic23

使用kubectl創建Service

創建service

1
kubectl create -f [yaml file]

更新service

1
kubectl apply -f [yaml file]

記得在create時,加上 --save-config

刪除service

1
kubectl delete -f [yaml file]

使用kubectl創建Service

創建service的範例,類型是NodePort

1
2
3
4
5
6
7
8
9
10
11
12
apiVersion: v1
kind: Service
metadata:
name: nginx-nodeport
spec:
type: NodePort
selector:
app: my-nginx
ports:
- port: 80 # Service所運行的port
targetPort: 80 # Pods內的container實際使用的port
nodePort: 31000 # 外部進來Pods的port

這邊會困惑 spec.ports中的 porttargetPortnodePort是什麼

  • port: Service所運行的port
  • targetPort: Pods內的container實際使用的port
  • nodePort: 外部進來Pods的port

diagram01

若沒有設置targetPort,那初始值會與port一樣

若要能夠讓外部呼叫到service,記得在yaml檔案設置
  1. service類型為NodePort
  2. port (service的port)與nodePort (Node的port)之映射關係

pic12

測試Service

透過 kubectl exe [pod-name] -- curl -s http://podID 來測試pod是否能夠測通

不過要事先在pod內安裝curl

1
2
3
kubectl exec [pod-name] -it sh
apk add curl
curl -s http://podIP

參考