概述
service服务也是Kubernetes里核心字眼对象之一,Kubernetes里的每一个service其实就是我们经常提起的微服务架构中的一个微服务,之前讲解Pod,RC等资源对象其实都是为讲解Kubernetes Service做铺垫的,下图为Pod,RC与Service的逻辑关系
可以看到上面的架构图,service服务通过标签选择器定位后端pod,前提是service的selector必须和后端Pod标签对应上才能找到相对应的Pod,而前段frontend通过service就可以访问到后端提供服务的pod了,而service默认IP类型为主要分为:
- ClusterIP:主要是为集群内部提供访问服务的
- NodePort:可以被集群外部所访问,访问方式为 宿主机:端口号
kube-proxy一直监控api service所管理的service规则,一旦监视到有变动,kube-proxy会将变动反映至规则当中,而请求的规则有3中:
- userspace
- iptables
- ipvs
下面我创建了一个nginx服务和一个对外提供服务的service,如下:
[root@master ~]# cat nginx.yaml apiVersion: v1 kind: Service metadata: name: serivce-mynginx namespace: default spec: type: NodePort selector: app: mynginx ports: - name: nginx port: 80 targetPort: 80 nodePort: 30080 --- apiVersion: apps/v1 kind: Deployment metadata: name: deploy namespace: default spec: replicas: 2 selector: matchLabels: app: mynginx template: metadata: labels: app: mynginx spec: containers: - name: nginx image: lizhaoqwe/nginx:v1 ports: - name: nginx containerPort: 80
执行yaml文件
[root@master ~]# kubectl create -f test.yaml service/serivce-mynginx created deployment.apps/deploy created
查看pod和service状态
[root@master ~]# kubectl get pods NAME READY STATUS RESTARTS AGE deploy-696bccb9fd-9zk2f 1/1 Running 0 138m deploy-696bccb9fd-vcgs5 1/1 Running 0 138m [root@master ~]# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 5d23h serivce-mynginx NodePort 10.103.92.182 <none> 80:30080/TCP 138m
验证
headless service
headless service就是无头service(也就是没有ip的service),这种无头服务对于有状态应用来说很重要,我们可以利用service的labels关联后端pod,我们访问的流量就可以直接到达pod而不再需要service负载均衡至后端pod
定义无头服务如下:
-rw-r--r-- 1 root root 1856 3月 14 01:36 redis.yaml [root@master redis]# cat redis-svc.yaml apiVersion: v1 kind: Service metadata: name: redis-service labels: app: redis spec: ports: - name: redis-port port: 6379 clusterIP: None selector: app: redis appCluster: redis-cluster
查看service对应pod的ip地址
[root@master redis]# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES redis-app-0 1/1 Running 0 13m 10.244.2.28 node2 <none> <none> redis-app-1 1/1 Running 1 16h 10.244.1.24 node1 <none> <none> redis-app-2 1/1 Running 1 16h 10.244.2.25 node2 <none> <none> redis-app-3 1/1 Running 1 16h 10.244.1.25 node1 <none> <none> redis-app-4 1/1 Running 1 16h 10.244.2.27 node2 <none> <none> redis-app-5 1/1 Running 1 16h 10.244.1.23 node1 <none> <none>
查看无头服务
[root@master redis]# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 17h redis-service ClusterIP None <none> 6379/TCP 16h
解析service服务,可以看到解析的ip都是后端关联的pod A记录
[root@master redis]# dig redis-service.default.svc.cluster.local @10.96.0.10 ; <<>> DiG 9.11.4-P2-RedHat-9.11.4-9.P2.el7 <<>> redis-service.default.svc.cluster.local @10.96.0.10 ;; global options: +cmd ;; Got answer: ;; WARNING: .local is reserved for Multicast DNS ;; You are currently testing what happens when an mDNS query is leaked to DNS ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 50817 ;; flags: qr aa rd; QUERY: 1, ANSWER: 6, AUTHORITY: 0, ADDITIONAL: 1 ;; WARNING: recursion requested but not available ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ;; QUESTION SECTION: ;redis-service.default.svc.cluster.local. IN A ;; ANSWER SECTION: redis-service.default.svc.cluster.local. 30 IN A 10.244.2.27 redis-service.default.svc.cluster.local. 30 IN A 10.244.1.23 redis-service.default.svc.cluster.local. 30 IN A 10.244.1.25 redis-service.default.svc.cluster.local. 30 IN A 10.244.2.28 redis-service.default.svc.cluster.local. 30 IN A 10.244.1.24 redis-service.default.svc.cluster.local. 30 IN A 10.244.2.25 ;; Query time: 92 msec ;; SERVER: 10.96.0.10#53(10.96.0.10) ;; WHEN: 六 3月 14 17:59:00 CST 2020 ;; MSG SIZE rcvd: 398
外部访问service的问题
为了更加深刻理解kubernetes,我们需要弄明白kubernetes里的3中IP
- NodeIP:NodeIP是kubernetes中每个节点的物理网卡IP地址,是一个真实存在的物理网络,所有属于这个网络的服务器都能通过这个网络直接通讯,包括集群外的主机访问集群内的主机也需要NodeIP
- PodIP:PodIP是每个Pod地址,它是docker engine根据docker0网桥的IP地址进行分配的,通常是一个虚拟的二层网络,所以kubernetes里的一个Pod里的容器访问另外一个Pod里的容器时,就是通过PodIP所在的虚拟二层网络进行通讯的,而真实的TCP/IP流量是通过NodeIP所在的物理网卡流出的
- ClusterIP:他是一个虚拟的IP,但更像是一个“伪造”的IP网络,原因有以下几点:
- ClusterIP仅仅作用于kubernetes service这个对象,并由kubernetes管理和分配ip地址
- ClusterIP无法被Ping,因为没有一个实体网络对象来响应
- ClusterIP只能结合service Port组成一个具体的通讯端口,如果集群外想访问需要做一些额外的操作
- 在kubernets集群内,NodeIP、PodIP和ClusterIP网之间通讯,采用的是kubernets自己设计的一种编程方式的特殊路由规则