Headless Services 簡介

有時不需要或不想要負載均衡,以及單獨的 Service IP。 遇到這種情況,可以通過指定 Cluster IP(spec.clusterIP)的值為 “None” 來創建 Headless Service。

您可以使用 headless Service 與其他服務發現機制進行接口,而不必與 Kubernetes 的實現捆綁在一起。

對這 headless Service 並不會分配 Cluster IP,kube-proxy 不會處理它們,而且平台也不會為它們進行負載均衡和路由。 DNS 如何實現自動配置,依賴於 Service 是否定義了 selector。

Lable Secector:

  • 配置 Selector:對定義了 selector 的 Headless Service,Endpoint 控制器在 API 中創建了 Endpoints 記錄,並且修改 DNS 配置返回 A 記錄(地址),通過這個地址直接到達 Service 的後端 Pod上。見下圖:
  • K8S headless service服務詳解_nginx

  • 不配置 Selector:對沒有定義 selector 的 Headless Service,Endpoint 控制器不會創建 Endpoints 記錄。

Service(iptables 代理模式)簡介

這種模式,kube-proxy 會監視 Kubernetes 控制節點對 Service 對象和 Endpoints 對象的添加和移除。 對每個 Service,它會安裝 iptables 規則,從而捕獲到達該 ServiceclusterIP 和端口的請求,進而將請求重定向到 Service 任意一組 backend pod 中。 對於每個 Endpoints 對象,它也會安裝 iptables 規則,這個規則會選擇一個 backend pod 組合。

默認的策略是,kube-proxy 在 iptables 模式下隨機選擇一個 backend pod

下面是一個簡圖:

K8S headless service服務詳解_IP_02

Headless Services 創建

$ vim headless_service.yaml
$ kubectl apply -f headless_service.yaml

headless_service.yaml 配置如下

apiVersion: v1
kind: Service
metadata:
name: nginx-test
labels:
app: nginx_test
spec:
ports:
- port: 80
name: nginx-web
# clusterIP 設置為 None
clusterIP: None
selector:
app: nginx_test
---
apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
name: nginx-web
spec:
serviceName: "nginx-test"
replicas: 2
template:
metadata:
labels:
app: nginx_test
spec:
containers:
- name: nginx-test
image: nginx:1.11
ports:
- containerPort: 80
name: nginx-web

Headless Services 驗證

# 查看 statefulsets nginx-web
$ kubectl get statefulsets nginx-web
NAME        READY   AGE
nginx-web   2/2     93m
# 查看 pods 
$ kubectl get pods -o wide | grep nginx-web
nginx-web-0                         1/1     Running   0          96m    192.168.40.103   it-zabbix   <none>           <none>
  nginx-web-1                         1/1     Running   0          96m    192.168.40.96    it-zabbix   <none>           <none>
    # 顯示 nginx-test Headless Services 詳細信息
    $ kubectl describe svc nginx-test
    Name:              nginx-test
    Namespace:         default
    Labels:            app=nginx_test
    Annotations:       kubectl.kubernetes.io/last-applied-configuration:
    {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"labels":{"app":"nginx_test"},"name":"nginx-test","namespace":"default"},...
    Selector:          app=nginx_test
    Type:              ClusterIP
    IP:                None
    Port:              nginx-web  80/TCP
    TargetPort:        80/TCP
    Endpoints:         192.168.40.103:80,192.168.40.96:80
    Session Affinity:  None
    Events:            <none>
      # 測試 service 域名是否解析出兩個 pod ip
      $ nslookup nginx-test.default.svc.cluster.local 192.168.16.2
      Server:		192.168.16.2
      Address:	192.168.16.2#53
      Name:	nginx-test.default.svc.cluster.local
      Address: 192.168.40.103
      Name:	nginx-test.default.svc.cluster.local
      Address: 192.168.40.96
      # 測試 pod 域名是否解析出對應的 pod ip
      $ nslookup nginx-web-0.nginx-test.default.svc.cluster.local 192.168.16.2
      Server:		192.168.16.2
      Address:	192.168.16.2#53
      Name:	nginx-web-0.nginx-test.default.svc.cluster.local
      Address: 192.168.40.103
      $ nslookup nginx-web-1.nginx-test.default.svc.cluster.local 192.168.16.2
      Server:		192.168.16.2
      Address:	192.168.16.2#53
      Name:	nginx-web-1.nginx-test.default.svc.cluster.local
      Address: 192.168.40.96

Headless Services 應用場景

  • 第一種:自主選擇權,有時候 client 想自己來決定使用哪個Real Server,可以通過查詢DNS來獲取 Real Server 的信息。
  • 第二種:Headless Service 的對應的每一個 Endpoints,即每一個Pod,都會有對應的DNS域名,這樣Pod之間就可以互相訪問