1.Service概述

service是kubernetes中最核心的资源对象之一,service和pod之间是通过Label串起来,相同的Service的pod的Label是一样的.同一个service下的所有pod是通过kube-proxy实现负载均衡.而每个service都会分配一个全局唯一的虚拟ip,也就cluster ip.

在该service整个生命周期内,cluster ip保持不变,而在kubernetes中还有一个dns服务,它会把service的name解析为cluster ip.

Service可以看作是一组提供相同服务的Pod对外的访问接口。借助Service,应用可以方便地实现服务发现和负载均衡。

service默认只支持4层负载均衡能力,没有7层功能。(可以通过Ingress实现)

2. service的三种工作模式

第一种: 是Userspace方式

  如下图描述,

  

k8s中service和ingress区别 k8s中service的实现方式有哪几种_Pod


  Client Pod要访问Server Pod时,它先将请求发给本机内核空间中的service规则,由它再将请求,

  转给监听在指定套接字上的kube-proxy,kube-proxy处理完请求,并分发请求到指定Server Pod后,再将请求

  递交给内核空间中的service,由service将请求转给指定的Server Pod。

  由于其需要来回在用户空间和内核空间交互通信,因此效率很差,接着就有了第二种方式.

第二种: iptables模型
  此工作方式是直接由内核中的iptables规则,接受Client Pod的请求,并处理完成后,直接转发给指定ServerPod.

k8s中service和ingress区别 k8s中service的实现方式有哪几种_nginx_02


第三种: ipvs模型

  它是直接有内核中的ipvs规则来接受Client Pod请求,并处理该请求,再有内核封包后,直接发给指定的Server Pod。

k8s中service和ingress区别 k8s中service的实现方式有哪几种_Pod_03

注:
  以上不论哪种,kube-proxy都通过watch的方式监控着kube-APIServer写入etcd中关于Pod的最新状态信息,
  它一旦检查到一个Pod资源被删除了 或 新建,它将立即将这些变化,反应再iptables 或 ipvs规则中,以便   iptables和ipvs在调度Clinet Pod请求到Server Pod时,不会出现Server Pod不存在的情况

自k8s1.1以后,service默认使用ipvs规则,若ipvs没有被激活,则降级使用iptables规则. 但在1.1以前,service
 使用的模式默认为userspace.

Service 是由 kube-proxy 组件,加上 iptables 来共同实现的.

kube-proxy 通过 iptables 处理 Service 的过程,需要在宿主机上设置相当多的 iptables 规则,如果宿主机有大量的Pod,不断刷新iptables规则,会消耗大量的CPU资源。

3. service的四种类型

1. ExternalName:
 
 用于将集群外部的服务引入到集群内部,在集群内部可直接访问来获取服务。它的值必须是 FQDN, 此FQDN为集群内部的FQDN, 即: ServiceName.Namespace.Domain.LTD.然后CoreDNS接受到该FQDN后,能解析出一个CNAME记录, 该别名记录为真正互联网上的域名.如: www.test.com, 接着CoreDNS在向互联网上的根域DNS解析该域名,获得其真实互联网IP.

2. ClusterIP:

用于为集群内Pod访问时,提供的固定访问地址,默认是自动分配地址,可使用ClusterIP关键字指定固定IP.

3. NodePort:

用于为集群外部访问Service后面Pod提供访问接入端口.
这种类型的service工作流程为:

Client----->NodeIP:NodePort----->ClusterIP:ServicePort----->PodIP:ContainerPort

4. LoadBalancer

用于当K8s运行在一个云环境内时,若该云环境支持LBaaS,则此类型可自动触发创建一个软件负载均衡器用于对Service做负载均衡调度.
因为外部所有Client都访问一个NodeIP,该节点的压力将会很大, 而LoadBalancer则可解决这个问题。而且它还直接动态监测后端Node是否被移除或新增了,然后动态更新调度的节点数。

4. 创建service:(ClusterIP方式)

apiVersion: v1
kind: Service
metadata:
  name: web-service
spec:
  ports:
    - name: http
      port: 80
      targetPort: 80
  selector:
      app: nginx
  type: ClusterIP

k8s中service和ingress区别 k8s中service的实现方式有哪几种_Server_04


k8s中service和ingress区别 k8s中service的实现方式有哪几种_nginx_05


目前该web-service还没有后端 Endpoints

创建两个后端的pod

标签必须和web-service的保持一致 app: nginx

apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment-nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: reg.westos.org/k8s/myapp:v1
        ports:
        - containerPort: 80
[kubeadm@server1 manifest]$ vim de.yaml 
[kubeadm@server1 manifest]$ kubectl apply -f de.yaml 
deployment.apps/deployment-nginx created
[kubeadm@server1 manifest]$ kubectl get pod
NAME                                READY   STATUS    RESTARTS   AGE
deployment-nginx-84f7d65dcf-5bf9q   1/1     Running   0          6s
deployment-nginx-84f7d65dcf-qjknh   1/1     Running   0          6s
test                                1/1     Running   1          3m42s
[kubeadm@server1 manifest]$

此时,我们的web-service有了两个后端

k8s中service和ingress区别 k8s中service的实现方式有哪几种_Pod_06

k8s中service和ingress区别 k8s中service的实现方式有哪几种_Pod_07


pod间内部通过访问ClusterIP分配的虚拟VIP负载到了后端的两个pod容器

ClusterIP:通过集群的内部 IP 暴露服务,选择该值,服务只能够在集群内部可以访问,这也是默认的 ServiceType

5.Headless Service “无头服务”

Headless Service不需要分配一个VIP,而是直接以DNS记录的方式解析出被代理Pod的IP地址。

域名格式:$(servicename).$(namespace).svc.cluster.local

无头服务,不分配ip地址,使用域名

apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
spec:
  ports:
    - name: http
      port: 80
      targetPort: 80
  selector:
      app: nginx
  clusterIP: None

k8s中service和ingress区别 k8s中service的实现方式有哪几种_Server_08

k8s中service和ingress区别 k8s中service的实现方式有哪几种_Pod_09

以DNS记录的方式解析出被代理Pod的IP地址。

k8s中service和ingress区别 k8s中service的实现方式有哪几种_nginx_10


通过这种方式实现访问,即使在后端pod滚动更新之后依然可以通过DNS进行解 析

6. 将service的工作模式改为lvs(ipvs)

k8s中service和ingress区别 k8s中service的实现方式有哪几种_Pod_11

当pod创建的越来越多时,iptables的刷新频率就会越来越大,刷新策略会对cpu造成一定 的压力

使用lvs来实现pod的负载均衡,直接使用linux内核

在所有节点安装ipvsadm

当前没有任何策略

k8s中service和ingress区别 k8s中service的实现方式有哪几种_nginx_12


将模式改为ipvs模式

kubectl -n kube-system cm kube-proxy

k8s中service和ingress区别 k8s中service的实现方式有哪几种_nginx_13


删除原来的 kube-system pod

k8s中service和ingress区别 k8s中service的实现方式有哪几种_Server_14

发现又重新新建了三个kube-system 的pod

k8s中service和ingress区别 k8s中service的实现方式有哪几种_Pod_15


在每个节点上发现,lvs的策略自动出现

k8s中service和ingress区别 k8s中service的实现方式有哪几种_nginx_16


k8s中service和ingress区别 k8s中service的实现方式有哪几种_nginx_17

创建一个pod,内部访问web-service的虚拟VIP实现了对pod的负载

k8s中service和ingress区别 k8s中service的实现方式有哪几种_nginx_18

7. Flannel vxlan模式跨主机通信原理

k8s中service和ingress区别 k8s中service的实现方式有哪几种_nginx_19


在每个node节点上发现kube-ipvs0的接口,只要创建一个service,就会加一个,10.100.84.9就是server2上创建的service的VIP地址

三个节点相同

k8s中service和ingress区别 k8s中service的实现方式有哪几种_nginx_20


2个container需要跨主机通信

那么,server2和server3两个node是如何实现跨主机通信的呢?

k8s中service和ingress区别 k8s中service的实现方式有哪几种_Pod_21

cni0容器网络接口(k8s)和docker0差不多

vxlan模式跨主机通信过程:

通过ip add命令查看到容器在物理机上的veth卡。

因为这里使用了cni接口标准,这个veth卡会桥接在cni0的网桥上。这个我们可以通过brctl show进行查看

数据包走到了cni0的网桥后,根据已知的目标ip,10.244.2.6,可以查找路由表,根据路由和掩码,选择对应的iface,也就是flannel.1。且下一跳,也就是10.244.2.0。

k8s中service和ingress区别 k8s中service的实现方式有哪几种_Pod_22


进入到flannel.1如何知道应该发向哪个物理机呢。这个时候,其实是通过arp来获取。可以通过arp命令查看到对应的mac地址。

k8s中service和ingress区别 k8s中service的实现方式有哪几种_Server_23

这个mac地址在vxlan中,可以通过bridge fdb show来进行查看。可以看到,如果是发向ae:39:2b:5e:b1:d0 的地址,则目标机器在172.25.254.3机器上。则数据就会流转到172.25.254.3上了。经过vxlan封包后的数据包就会经过eth0设备发向到172.25.254.3上。

k8s中service和ingress区别 k8s中service的实现方式有哪几种_nginx_24

在172.25.254.3上,首先经过了iptables链,而后在flannel.1的Iface上则接收到该数据包。这里我们可以看到,flannel.1的mac地址就是ae:39:2b:5e:b1:d0。

k8s中service和ingress区别 k8s中service的实现方式有哪几种_nginx_25

到达flannel.1后,根据路由表,查看10.244.2.6的路由应送到server3的cni0的网桥上。

k8s中service和ingress区别 k8s中service的实现方式有哪几种_Server_26


这里我们查看cni0的网桥信息。

k8s中service和ingress区别 k8s中service的实现方式有哪几种_Server_27


到达网桥后,就可以根据地址将数据送到10.244.2.26的对应的veth上,进而在容器中收到对应的数据包了。

以上就是两个处于不同物理机上的容器间发送数据包的流程。相比较来说,从容器到物理机的ping就简单多了。这个流程就是veth->cni0->eth0->对端物理机ip。这里就不详细叙述了。

同一台物理机上不同容器的ping只需要经过cni0的网桥就可以了。

8. nodeport

[kubeadm@server1 manifest]$ kubectl edit svc web-service 
service/web-service edited
[kubeadm@server1 manifest]$

k8s中service和ingress区别 k8s中service的实现方式有哪几种_Server_28


k8s中service和ingress区别 k8s中service的实现方式有哪几种_Pod_29

k8s中service和ingress区别 k8s中service的实现方式有哪几种_Pod_30

k8s中service和ingress区别 k8s中service的实现方式有哪几种_Pod_31

9. ExternalName

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  type:  ExternalName
  externalName: www.baidu.com

用于让pod去访问集群外部的资源

k8s中service和ingress区别 k8s中service的实现方式有哪几种_Server_32


pod内部可以正常访问

k8s中service和ingress区别 k8s中service的实现方式有哪几种_nginx_33