1 Service简介

一句话:pod不能被外网访问,service是访问入口。

为了适应快速的业务需求,微服务架构已经逐渐成为主流,微服务架构的应用需要有非常好的服务编排支持,k8s中的核心要素Service便提供了一套简化的服务代理和发现机制,天然适应微服务架构,任何应用都可以非常轻易地运行在k8s中而无须对架构进行改动;

Service是Kubernetes里最核心的资源对象之一,Service定义了一个服务的访问入口地址,前端的应用(Pod)通过这个入口地址访问其背后的一组由Pod副本组成的集群实力。 Service与其后端Pod副本集群之间则是通过Label Selector来实现"缝对"。而RC的作用实际上是保证Service 的服务能力和服务质量处于预期的标准。

 

1.1 原理

  在Kubernetes中,在受到RC调控的时候,Pod副本是变化的,对于的虚拟IP也是变化的,比如发生迁移或者伸缩的时候。这对于Pod的访问者来说是不可接受的。Kubernetes中的Service是一种抽象概念,它定义了一个Pod逻辑集合以及访问它们的策略,Service同Pod的关联同样是居于Label来完成的。Service的目标是提供一种桥梁, 它会为访问者提供一个固定访问地址,用于在访问时重定向到相应的后端,这使得非 Kubernetes原生应用程序,在无须为Kubemces编写特定代码的前提下,轻松访问后端。

  Service同RC一样,都是通过Label来关联Pod的。当你在Service的yaml文件中定义了该Service的selector中的label为app:my-web,那么这个Service会将Pod-->metadata-->labeks中label为app:my-web的Pod作为分发请求的后端。当Pod发生变化时(增加、减少、重建等),Service会及时更新。这样一来,Service就可以作为Pod的访问入口,起到代理服务器的作用,而对于访问者来说,通过Service进行访问,无需直接感知Pod。

    需要注意的是,Kubernetes分配给Service的固定IP是一个虚拟IP,并不是一个真实的IP,在外部是无法寻址的。真实的系统实现上,Kubernetes是通过Kube-proxy组件来实现的虚拟IP路由及转发。所以在之前集群部署的环节上,我们在每个Node上均部署了Proxy这个组件,从而实现了Kubernetes层级的虚拟转发网络。

1.2  kubernetes中的三种IP

  • Node IP:Node节点IP地址
  • Pod IP:Pod的IP地址
  • Cluster IP:Service的IP地址

 

kubernetes的service类型 service kubernetes_Pod

 

  Node IP是Kubernetes集群中每个节点的物理网卡的IP地址,这是一个真实存在的物理网络,所有属于这个网络的服务器之间都能通过这个网络直接通讯,不管他们中间是否含有不属于Kubernetes集群中的节点。想Kubernetes之外的节点访问Kubernetes集群内的节点或者TCP/IP服务时,必须通过Node IP

  Pod IP是每个Pod的IP地址,它是Docker Engine 根据docker0网桥的IP地址段进行分配的,通常是一个虚拟的二层网络,Kubernetes要求位于不同Node上的Pod能够彼此直接通讯,所以Kubernetes里一个Pod里的容器访问另外一个Pod里的容器,就是通过Pod IP所在的虚拟二层网络进行通信,而真实的TCP/IP流量则是通过Node IP所在的物理网卡流出

  Cluster IP,它是一个IP,但更像是一个伪造的IP网络

(1)Cluster IP仅仅作用于Kubernetes Service对象,并由Kubernetes管理和分配IP地址(来源于Cluster IP地址池)
(2)Cluster IP无法被Ping,因为没有一个"实体网络对象"来影响
(3)在Kubernetes集群内,Node IP、Pod IP、Cluster IP之间的通信,采用的是Kubernetes自己设计的特殊路由规则

 

1.3 Service负载均衡

#[root@k8s-master k8s]# kubectl describe svc nginx                             
Name:                   nginx
Namespace:              default
Labels:                 <none>
Selector:               run=nginx-deployment2 #搜索标签
Type:                   NodePort #转发方式
IP:                     10.254.18.231#虚拟IP
Port:                   <unset> 80/TCP
NodePort:               <unset> 30001/TCP #node暴露端口
Endpoints:              172.16.47.2:80,172.16.47.3:80,172.16.73.2:80 + 2 more... #pod
Session Affinity:       None
No events.

 

 

Service的虚拟IP是由Kubernetes虚拟出来的内部网络,外部是无法寻址到的。但是有些服务又需要被外部访问到,例如web前段。这时候就需要加一层网络转发,即外网到内网的转发。Kubernetes提供了NodePort、LoadBalancer、Ingress三种方式。

    NodePort,在之前的Guestbook示例中,已经延时了NodePort的用法。NodePort的原理是,Kubernetes会在每一个Node上暴露出一个端口:nodePort,外部网络可以通过(任一Node)[NodeIP]:[NodePort]访问到后端的Service。

    LoadBalancer,在NodePort基础上,Kubernetes可以请求底层云平台创建一个负载均衡器,将每个Node作为后端,进行服务分发。该模式需要底层云平台(例如GCE)支持。

    Ingress,是一种HTTP方式的路由转发机制,由Ingress Controller和HTTP代理服务器组合而成。Ingress Controller实时监控Kubernetes API,实时更新HTTP代理服务器的转发规则。HTTP代理服务器有GCE Load-Balancer、HaProxy、Nginx等开源方案。

 

 

2 Service样例

2.1 查看现有的pod和deployment标签

[root@k8s-master k8s]# kubectl get rs -o wide      
NAME                           DESIRED   CURRENT   READY     AGE       CONTAINER(S)        IMAGE(S)                          SELECTOR
nginx-deployment2-3516246156   5         5         5         19h       nginx-deployment2   192.168.0.136:5000/nginx:1.15     pod-template-hash=3516246156,run=nginx-deployment2
nginx-deployment2-3766659668   0         0         0         19h       nginx-deployment2   192.168.0.136:5000/nginx:latest   pod-template-hash=3766659668,run=nginx-deployment2
[root@k8s-master k8s]# kubectl get pods -o wide  
NAME                                 READY     STATUS    RESTARTS   AGE       IP            NODE
nginx-deployment2-3516246156-0x490   1/1       Running   0          18h       172.16.47.2   k8s-node-2
nginx-deployment2-3516246156-827rs   1/1       Running   0          18h       172.16.73.4   k8s-node-1
nginx-deployment2-3516246156-fsb4k   1/1       Running   0          1h        172.16.47.3   k8s-node-2
nginx-deployment2-3516246156-g2c5q   1/1       Running   0          1h        172.16.73.3   k8s-node-1
nginx-deployment2-3516246156-k09ch   1/1       Running   0          18h       172.16.73.2   k8s-node-1
[root@k8s-master k8s]#
[root@k8s-master k8s]# kubectl describe deployment nginx-deployment2 | grep Selector
Selector:               run=nginx-deployment2
[root@k8s-master k8s]#

 

2.2 根据deployment的Selector创建svc文件并启动

[root@k8s-master k8s]# cat myweb-svc.yaml 
apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  type: NodePort
  ports:
    - port: 80
      nodePort: 30001
  selector:  #标签选择器
    run: nginx-deployment2  
[root@k8s-master nginx]# kubectl create -f myweb-svc.yaml 
service "nginx" created

 

2.3 查看service状态

[root@k8s-master k8s]# kubectl get svc -o wide          
NAME         CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE       SELECTOR
kubernetes   10.254.0.1     <none>        443/TCP        3d        <none>
nginx        10.254.129.3   <nodes>       80:30001/TCP   52s       run=nginx-deployment2
[root@k8s-master k8s]# kubectl describe svc nginx 
Name:                   nginx
Namespace:              default
Labels:                 <none>
Selector:               run=nginx-deployment2
Type:                   NodePort
IP:                     10.254.129.3
Port:                   <unset> 80/TCP
NodePort:               <unset> 30001/TCP
Endpoints:              172.16.47.2:80,172.16.47.3:80,172.16.73.2:80 + 2 more...
Session Affinity:       None
No events.
[root@k8s-master k8s]# kubectl get pods -o wide   
NAME                                 READY     STATUS    RESTARTS   AGE       IP            NODE
nginx-deployment2-3516246156-0x490   1/1       Running   0          19h       172.16.47.2   k8s-node-2
nginx-deployment2-3516246156-827rs   1/1       Running   0          19h       172.16.73.4   k8s-node-1
nginx-deployment2-3516246156-fsb4k   1/1       Running   0          1h        172.16.47.3   k8s-node-2
nginx-deployment2-3516246156-g2c5q   1/1       Running   0          1h        172.16.73.3   k8s-node-1
nginx-deployment2-3516246156-k09ch   1/1       Running   0          19h       172.16.73.2   k8s-node-1
[root@k8s-master k8s]#

 

2.4 外网访问测试

kubernetes的service类型 service kubernetes_IP_02

kubernetes的service类型 service kubernetes_IP_03

 

 

 

 

2.5  为什么是30001端口?

 

Service从30000开始随机分配,默不填写,自分配30000-32767内任意一端口

 

我们修改成1000端口

 

[root@k8s-master k8s]# cat myweb-svc.yaml 
apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  type: NodePort
  ports:
    - port: 80
      nodePort: 1000
  selector:  #标签选择器
    run: nginx-deployment2  
[root@k8s-master k8s]#
[root@k8s-master k8s]# kubectl create -f myweb-svc.yaml    
The Service "nginx" is invalid: spec.ports[0].nodePort: Invalid value: 1000: provided port is not in the valid range. The range of valid ports is 30000-32767

 

2.6 Svc缩容—通过修改deployment修改副本数为1

[root@k8s-master k8s]# kubectl scale deployment nginx-deployment2 --replicas=1
k8s]# kubectl get pods -o wide
NAME                                 READY     STATUS    RESTARTS   AGE       IP            NODE
nginx-deployment2-3516246156-k09ch   1/1       Running   0          19h       172.16.73.2   k8s-node-1
[root@k8s-master k8s]#
#只有一个节点也不影响访问的
[root@k8s-master k8s]# curl -s -I 192.168.0.138:30023| grep 200
HTTP/1.1 200 OK
[root@k8s-master k8s]# curl -s -I 192.168.0.137:30023| grep 200 
HTTP/1.1 200 OK
[root@k8s-master k8s]#

 

2.7 Svc扩容—通过修改deployment修改副本数为6

[root@k8s-master k8s]# kubectl scale deployment nginx-deployment2 --replicas=6
deployment "nginx-deployment2" scaled
[root@k8s-master k8s]# kubectl get pods -o wide   
NAME                                 READY     STATUS    RESTARTS   AGE       IP            NODE
nginx-deployment2-3516246156-bc7pq   1/1       Running   0          36s       172.16.73.3   k8s-node-1
nginx-deployment2-3516246156-k09ch   1/1       Running   0          19h       172.16.73.2   k8s-node-1
nginx-deployment2-3516246156-l5p51   1/1       Running   0          37s       172.16.47.3   k8s-node-2
nginx-deployment2-3516246156-llhsn   1/1       Running   0          37s       172.16.73.4   k8s-node-1
nginx-deployment2-3516246156-sgpgj   1/1       Running   0          37s       172.16.47.4   k8s-node-2
nginx-deployment2-3516246156-txf3s   1/1       Running   0          37s       172.16.47.2   k8s-node-2
[root@k8s-master k8s]#

 

2.8 负载均衡测试

 

[root@k8s-master ~]# kubectl get  pod -o wide                                  
NAME                                 READY     STATUS    RESTARTS   AGE       IP            NODE
nginx-deployment2-3516246156-gjkml   1/1       Running   0          9m        172.16.73.3   k8s-node-1
nginx-deployment2-3516246156-nchs3   1/1       Running   0          9m        172.16.47.2   k8s-node-2
[root@k8s-master ~]# kubectl exec -it nginx-deployment2-3516246156-gjkml /bin/bash
root@nginx-deployment2-3516246156-gjkml:/# echo 'web01' > /usr/share/nginx/html/index.html 
root@nginx-deployment2-3516246156-gjkml:/# 
root@nginx-deployment2-3516246156-gjkml:/# ^C
root@nginx-deployment2-3516246156-gjkml:/# exit
[root@k8s-master ~]# kubectl exec -it nginx-deployment2-3516246156-nchs3 /bin/bash
root@nginx-deployment2-3516246156-nchs3:/# echo 'web02' > /usr/share/nginx/html/index.html
root@nginx-deployment2-3516246156-nchs3:/# ^C
root@nginx-deployment2-3516246156-nchs3:/# exit
[root@k8s-master ~]#

kubernetes的service类型 service kubernetes_nginx_04

 

 

kubernetes的service类型 service kubernetes_IP_05

 

[root@k8s-master ~]# curl http://192.168.0.137:30023/
web01
[root@k8s-master ~]# curl http://192.168.0.137:30023/
web02
[root@k8s-master ~]# curl http://192.168.0.138:30023/
web01
[root@k8s-master ~]# curl http://192.168.0.138:30023/
web01
[root@k8s-master ~]# curl http://192.168.0.138:30023/
web02
[root@k8s-master ~]#