k8s的无头服务
Headless Services是一种特殊的service,其spec:clusterIP表示为None,这样在实际运行时就不会被分配ClusterIP,也被称为无头服务,通过DNS解析提供服务发现。与普通服务不同的是Headless Services不提供负载均衡功能,每个Pod都有唯一的DNS记录,直接映射到其IP地址,适用于有状态应用的场景,如与StatefulSet一起部署数据库。这种服务使得直接访问单个Pod成为可能,而不经过负载均衡器。
因为 Headless Service 属于 Service ClusterIp 类型,所以在讲解Headless Service前,先简单说下 Service 和服务发现。
构建镜像
[root@chenby ~]# cat > Dockerfile <<EOF
FROM nginx
RUN echo '这是一个本地构建的nginx镜像,第一版' > /usr/share/nginx/html/index.html
EOFdocker build -t z.oiox.cn:18082/library/cby:v1 .docker push z.oiox.cn:18082/library/cby:v1
编写yaml文件
我这里只是创建了一个最简单的容器,由StatefulSet控制器来管理,同时创建了无头服务的svc
cat > cby.yaml <<EOF
apiVersion: v1
kind: Service
metadata:name: nginxlabels:app: nginx
spec:ports:- port: 80name: webclusterIP: None #这使得服务成为无头服务selector:app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:name: web
spec:serviceName: "nginx"replicas: 2selector:matchLabels:app: nginxtemplate:metadata:labels:app: nginxspec:containers:- name: nginximage: z.oiox.cn:18082/library/cby:v1ports:- containerPort: 80name: web
EOF
查看已经创建的资源
[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内容
statefulsets控制器是可以将存储持久化的,我这里没做存储持久化,这里就进入容器内进行修改页面信息
kubectl exec web-1 -- sh -c 'echo 这是一个本地构建的nginx镜像,第二版 > /usr/share/nginx/html/index.html'
测试修改是否成功
[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
这是一个本地构建的nginx镜像,第一版
[root@k8s-master01 ~]#
[root@k8s-master01 ~]# curl 10.0.3.243
这是一个本地构建的nginx镜像,第二版
[root@k8s-master01 ~]#
[root@k8s-master01 ~]#
查看svc的详细
这里可以看到Endpoints已经关联到了后端的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 ~]#
创建busybox测试容器
cat<<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:name: busyboxnamespace: default
spec:containers:- name: busyboximage: docker-ce.chenby.cn/library/busybox:1.28command:- sleep- "3600"imagePullPolicy: IfNotPresentrestartPolicy: Always
EOF
进入测试容器
[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
/ #
/ #
/ #
/ #
进行访问性测试
[root@k8s-master01 ~]# kubectl exec -ti nginx-demo-cccbdc67f-6nkgd -- sh
/ #
/ #
/ # curl nginx.default.svc.cluster.local
这是一个本地构建的nginx镜像,第二版
/ # curl nginx.default.svc.cluster.local
这是一个本地构建的nginx镜像,第一版
/ #
/ #
/ #
/ # curl web-0.nginx.default.svc.cluster.local
这是一个本地构建的nginx镜像,第一版
/ # curl web-0.nginx.default.svc.cluster.local
这是一个本地构建的nginx镜像,第一版
/ # curl web-0.nginx.default.svc.cluster.local
这是一个本地构建的nginx镜像,第一版
/ #
/ #
/ #
/ # curl web-1.nginx.default.svc.cluster.local
这是一个本地构建的nginx镜像,第二版
/ # curl web-1.nginx.default.svc.cluster.local
这是一个本地构建的nginx镜像,第二版
/ # curl web-1.nginx.default.svc.cluster.local
这是一个本地构建的nginx镜像,第二版
总结
在某些场景中,无需对外提供访问能力,只需要在内部找到自己想找到的Pod资源时,可以通过Headless Service来实现。这种不具有ClusterIP的Service资源就是Headless Service,该 Service 的请求流量不需要 kube-proxy 处理,也不会有负载均衡和路由规则,而是由ClusterDNS的域名解析机制直接去访问固定的Pod资源。
既然是Headless Service,那首先它是Service,一般的Service能被内部和外部访问。之所以叫Headless Service,是因为只对内提供访问,既然只对内访问,那肯定就需要提供稳定的访问能力了,否则就没什么作用了。比如说拥有固定的Pod名称和存储,所以一般会结合StatefulSet一起使用,用来部署有状态的应用。
如果想让部署的有状态应用暴露给集群外部客户端访问的话,可以新建个普通(有ClusterIP)的服务,通过标签选择关联有状态服务实例。
关于
https://www.oiox.cn/
https://www.oiox.cn/index.php/start-page.html
CSDN、GitHub、51CTO、知乎、开源中国、思否、掘金、简书、华为云、阿里云、腾讯云、哔哩哔哩、今日头条、新浪微博、个人博客
全网可搜《小陈运维》
文章主要发布于微信公众号