Kubernetes service 種類

Po-Ching Liu
7 min readOct 2, 2024

--

筆者在2022到2024工作上多了GCP、GKE相關操作和規畫系統的經驗,也因此對於Kubernetes svc的種類以及其概念有更多的理解,僅此紀錄k8s svc實務上相關使用情境。

ClusterIP

  • 供cluster內部存取。
  • k8s 預設的service種類,宣告後會產生clusterIP,並於kubeDNS中產生對應的record,當流量經過此svc後會自動分配至後端的pod。
  • 筆者實務上用於cluster內部服務之間互相存取。

以下則是clusterIP範例。宣告後會產生對應的DNS record,規則如下 {service_name}.{namespace}.svc.cluster.local,下述範例則為my-app-svc.prod.svc.cluster.local。

apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app-deployment
namespace: prod
labels:
app: my-app
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app-container
image: my-app:1.0
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: my-app-svc
namespace: prod
spec:
type: ClusterIP
selector:
app: my-app
ports:
- name: http
port: 80
targetPort: 8080

NodePort

  • 供cluster外部存取。
  • 此類型的service宣告後會在每個node上分配宣告時的port號,讓cluster外部可以存取此服務(port號會分配30000–32767之間)。
  • 筆者實務上NodePort會搭配Ingress做使用,目的是讓外部(internet)做存取。

以下則是Ingress搭配NodePort範例。筆者因為使用GKE,因此當ingress建立時GCP會產生對應的L7 Load balancer,所以對於暴露給外部(internet)的服務會這樣去定義規範。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
namespace: prod
spec:
rules:
- host: example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-app-svc
port:
number: 80
---
apiVersion: v1
kind: Service
metadata:
name: my-app-svc
namespace: prod
spec:
type: NodePort
selector:
app: my-app
ports:
- name: http
port: 80
targetPort: 8080

LoadBalancer

  • 供cluster外部存取,通常會搭配public cloud。
  • 此類型的service通常宣告完後,以GCP來說對產生對應的Load balancer(L4),也可在service宣告要使用internal或者external的Load balancer。
  • 筆者實務上用於規劃內部cluster溝通做使用(當然也可以宣告internal ingress搭配node port做使用)。

以下則是load balance type的service,當宣告後GCP將會產生L4的Load balancer。值得注意的是,也可以將load balance宣告給VPC內部使用。

apiVersion: v1
kind: Service
metadata:
name: my-loadbalancer-service
namespace: prod
annotations:
networking.gke.io/load-balancer-type: "Internal" # For VPC internal load balancer use
spec:
type: LoadBalancer
selector:
app: my-app
ports:
- protocol: TCP
port: 80 # Port exposed by the LoadBalancer
targetPort: 8080 # Port that the application is listening on inside the pod

Headless Service

  • 供內部使用,通常搭配statefulset一起使用。
  • 將clusterIP宣告為None,就會是headless service,此時不會產生clusterIP,但會產生DNS record在kubeDNS。
  • 筆者實務上用於cluster內部服務間grpc溝通使用。

以下則是headless的service,筆者常使用在grpc client side load balance。因為grpc是長連線,因此需要使用client side load balance才能達到流量均衡散落在被呼叫的server上。

apiVersion: v1
kind: Service
metadata:
name: my-app-headless-svc
namespace: prod
spec:
clusterIP: None
selector:
app: my-app
ports:
- name: http
port: 80
targetPort: 8080

在.net使用headless service做grpc client side load balance要注意的則是record是否給對。根據 MSDN ,server的recod需給予為 dns:///my-app-headless-svc.prod.svc.cluster.local:8080。
注意 :
my-app-headless-svc.prod.svc.cluster.local 是 kubeDNS給予的,使用nslookup則可以看到svc背後select到多少個pod以及其對應IP。8080則是container的port號而非svc的port號。

--

--