k8s的無頭服務(wù)
Headless Services是一種特殊的service,其spec:clusterIP表示為None,這樣在實(shí)際運(yùn)行時(shí)就不會(huì)被分配ClusterIP,也被稱為無頭服務(wù),通過DNS解析提供服務(wù)發(fā)現(xiàn)。與普通服務(wù)不同的是Headless Services不提供負(fù)載均衡功能,每個(gè)Pod都有唯一的DNS記錄,直接映射到其IP地址,適用于有狀態(tài)應(yīng)用的場(chǎng)景,如與StatefulSet一起部署數(shù)據(jù)庫。這種服務(wù)使得直接訪問單個(gè)Pod成為可能,而不經(jīng)過負(fù)載均衡器。
因?yàn)?Headless Service 屬于 Service ClusterIp 類型,所以在講解Headless Service前,先簡單說下 Service 和服務(wù)發(fā)現(xiàn)。
構(gòu)建鏡像
[root@chenby ~]# cat > Dockerfile <<EOF
FROM nginx
RUN echo '這是一個(gè)本地構(gòu)建的nginx鏡像,第一版' > /usr/share/nginx/html/index.html
EOF
docker build -t z.oiox.cn:18082/library/cby:v1 .
docker push z.oiox.cn:18082/library/cby:v1
編寫yaml文件
我這里只是創(chuàng)建了一個(gè)最簡單的容器,由StatefulSet控制器來管理,同時(shí)創(chuàng)建了無頭服務(wù)的svc
cat > cby.yaml <<EOF
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
ports:
- port: 80
name: web
clusterIP: None #這使得服務(wù)成為無頭服務(wù)
selector:
app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
serviceName: "nginx"
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: z.oiox.cn:18082/library/cby:v1
ports:
- containerPort: 80
name: web
EOF
查看已經(jīng)創(chuàng)建的資源
[root@k8s-master01 ~]# kubectl get statefulsets
NAME READY AGE
web 2/2 12m
[root@k8s-master01 ~]#
[root@k8s-master01 ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 12m
web-1 1/1 Running 0 12m
[root@k8s-master01 ~]#
[root@k8s-master01 ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx ClusterIP None <none> 80/TCP 12m
[root@k8s-master01 ~]#
修改web-1的html內(nèi)容
statefulsets控制器是可以將存儲(chǔ)持久化的,我這里沒做存儲(chǔ)持久化,這里就進(jìn)入容器內(nèi)進(jìn)行修改頁面信息
kubectl exec web-1 -- sh -c 'echo 這是一個(gè)本地構(gòu)建的nginx鏡像,第二版 > /usr/share/nginx/html/index.html'
測(cè)試修改是否成功
[root@k8s-master01 ~]# kubectl get pod -o wide |grep web
web-0 1/1 Running 0 40m 10.0.0.28 k8s-node02 <none> <none>
web-1 1/1 Running 0 40m 10.0.3.243 k8s-node01 <none> <none>
[root@k8s-master01 ~]#
[root@k8s-master01 ~]#
[root@k8s-master01 ~]# curl 10.0.0.28
這是一個(gè)本地構(gòu)建的nginx鏡像,第一版
[root@k8s-master01 ~]#
[root@k8s-master01 ~]# curl 10.0.3.243
這是一個(gè)本地構(gòu)建的nginx鏡像,第二版
[root@k8s-master01 ~]#
[root@k8s-master01 ~]#
查看svc的詳細(xì)
這里可以看到Endpoints已經(jīng)關(guān)聯(lián)到了后端的pod容器
[root@k8s-master01 ~]# kubectl describe svc nginx
Name: nginx
Namespace: default
Labels: app=nginx
Annotations: <none>
Selector: app=nginx
Type: ClusterIP
IP Family Policy: SingleStack
IP Families: IPv4
IP: None
IPs: None
Port: web 80/TCP
TargetPort: 80/TCP
Endpoints: 10.0.0.28:80,10.0.3.243:80
Session Affinity: None
Internal Traffic Policy: Cluster
Events: <none>
[root@k8s-master01 ~]#
創(chuàng)建busybox測(cè)試容器
cat<<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: busybox
namespace: default
spec:
containers:
- name: busybox
image: docker-ce.chenby.cn/library/busybox:1.28
command:
- sleep
- "3600"
imagePullPolicy: IfNotPresent
restartPolicy: Always
EOF
進(jìn)入測(cè)試容器
[root@k8s-master01 ~]# kubectl exec -ti busybox -- sh
/ #
/ #
/ # ping nginx.default.svc.cluster.local
PING nginx.default.svc.cluster.local (10.0.0.28): 56 data bytes
64 bytes from 10.0.0.28: seq=0 ttl=63 time=0.066 ms
64 bytes from 10.0.0.28: seq=1 ttl=63 time=0.077 ms
64 bytes from 10.0.0.28: seq=2 ttl=63 time=0.070 ms
^C
--- nginx.default.svc.cluster.local ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.066/0.071/0.077 ms
/ #
/ #
/ #
/ # ping web-0.nginx.default.svc.cluster.local
PING web-0.nginx.default.svc.cluster.local (10.0.0.28): 56 data bytes
64 bytes from 10.0.0.28: seq=0 ttl=63 time=0.046 ms
64 bytes from 10.0.0.28: seq=1 ttl=63 time=0.079 ms
64 bytes from 10.0.0.28: seq=2 ttl=63 time=0.064 ms
^C
--- web-0.nginx.default.svc.cluster.local ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.046/0.063/0.079 ms
/ #
/ #
/ #
/ # ping web-1.nginx.default.svc.cluster.local
PING web-1.nginx.default.svc.cluster.local (10.0.3.243): 56 data bytes
64 bytes from 10.0.3.243: seq=0 ttl=63 time=0.369 ms
64 bytes from 10.0.3.243: seq=1 ttl=63 time=0.373 ms
64 bytes from 10.0.3.243: seq=2 ttl=63 time=0.328 ms
^C
--- web-1.nginx.default.svc.cluster.local ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.328/0.356/0.373 ms
/ #
/ #
/ #
/ #
/ # cat /etc/hosts
# Kubernetes-managed hosts file.
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
fe00::0 ip6-mcastprefix
fe00::1 ip6-allnodes
fe00::2 ip6-allrouters
10.0.0.238 busybox
/ #
/ #
/ #
/ #
進(jìn)行訪問性測(cè)試
[root@k8s-master01 ~]# kubectl exec -ti nginx-demo-cccbdc67f-6nkgd -- sh
/ #
/ #
/ # curl nginx.default.svc.cluster.local
這是一個(gè)本地構(gòu)建的nginx鏡像,第二版
/ # curl nginx.default.svc.cluster.local
這是一個(gè)本地構(gòu)建的nginx鏡像,第一版
/ #
/ #
/ #
/ # curl web-0.nginx.default.svc.cluster.local
這是一個(gè)本地構(gòu)建的nginx鏡像,第一版
/ # curl web-0.nginx.default.svc.cluster.local
這是一個(gè)本地構(gòu)建的nginx鏡像,第一版
/ # curl web-0.nginx.default.svc.cluster.local
這是一個(gè)本地構(gòu)建的nginx鏡像,第一版
/ #
/ #
/ #
/ # curl web-1.nginx.default.svc.cluster.local
這是一個(gè)本地構(gòu)建的nginx鏡像,第二版
/ # curl web-1.nginx.default.svc.cluster.local
這是一個(gè)本地構(gòu)建的nginx鏡像,第二版
/ # curl web-1.nginx.default.svc.cluster.local
這是一個(gè)本地構(gòu)建的nginx鏡像,第二版
總結(jié)
在某些場(chǎng)景中,無需對(duì)外提供訪問能力,只需要在內(nèi)部找到自己想找到的Pod資源時(shí),可以通過Headless Service來實(shí)現(xiàn)。這種不具有ClusterIP的Service資源就是Headless Service,該 Service 的請(qǐng)求流量不需要 kube-proxy 處理,也不會(huì)有負(fù)載均衡和路由規(guī)則,而是由ClusterDNS的域名解析機(jī)制直接去訪問固定的Pod資源。
既然是Headless Service,那首先它是Service,一般的Service能被內(nèi)部和外部訪問。之所以叫Headless Service,是因?yàn)橹粚?duì)內(nèi)提供訪問,既然只對(duì)內(nèi)訪問,那肯定就需要提供穩(wěn)定的訪問能力了,否則就沒什么作用了。比如說擁有固定的Pod名稱和存儲(chǔ),所以一般會(huì)結(jié)合StatefulSet一起使用,用來部署有狀態(tài)的應(yīng)用。
如果想讓部署的有狀態(tài)應(yīng)用暴露給集群外部客戶端訪問的話,可以新建個(gè)普通(有ClusterIP)的服務(wù),通過標(biāo)簽選擇關(guān)聯(lián)有狀態(tài)服務(wù)實(shí)例。