service连通k8s外部

外界连通Service

        Service 的访问信息在Kubernetes集群之外,其实是无效的 
        如何从外部(Kubernetes 集群之外),访问到 Kubernetes 里创建的Service
方式1(NodePort)

        创建一个NodePort类型的service

        不显式地声明nodePort字段,Kubernetes就会为你分配随机的可用端口来设置代理.这个端口的范围默认是30000-32767

        ClusterIP模式的Service和NodePort类型的Service定义格式

        

       在NodePort 方式下,Kubernetes 会在 IP 包离开宿主机发往目的 Pod 时,对这个 IP 包做一次 SNAT 操作 .
       这条规则设置在 POSTROUTING 检查点,也就是它给即将离开这台主机的 IP 包,进行了一次 SNAT 操作 .将这个IP包的源地址替换成了这台宿主机上的 CNI 网桥地址或者宿主机本身的 IP 地址(如果 CNI 网桥不存在的话) .当然,这个SNAT 操作只需要对 Service 转发出来的 IP 包进行(否则普通的IP包就被影响了)而 iptables 做这个判断的依据,就是查看该IP包是否有一个“0x4000”的“标志
      

    当一个外部的 client 通过 node 2 的地址访问一个 Service 的时候,node 2 上的负载均衡规则,就可能把这个 IP 包转发给一个在 node 1 上的 Pod.而当 node1上的这个Pod处理完请求之后,它就会按照这个IP包的源地址发出回复.可是,如果没有做 SNAT 操作的话,这时候,被转发来的IP包的源地址就是 client 的 IP 地址.所以此时Pod 就会直接将回复发给client.对于 client 来说,它的请求明明发给了node2,收到的回复却来自node1 这个client很可能会报错

    所以,在上图中,当IP包离开node2之后,它的源IP地址就会被SNAT改成 node2的CNI网桥地址或者 node2自己的地址.这样Pod 在处理完成之后就会先回复给node2(而不是 client)然后再由node2发送给client.这也就意味着这个Pod只知道该IP包来自于node2,而不是外部的 client

   如果Pod需要明确知道所有请求的来源情况   就必须把Service的spec.externalTrafficPolicy字段设置为local,这就保证了所有Pod通过Service收到请求之后,一定可以看到真正的,外部 client 的源地址

   这个机制的实现原理也非常简单:这时候,一台宿主机上的iptables规则,会设置为只将IP包转发给运行在这台宿主机上的 Pod.所以这时候Pod 就可以直接使用源地址将回复包发出,不需要事先进行 SNAT
     

     这就意味着如果在一台宿主机上,没有任何一个被代理的Pod存在,比如上图中的node2那么你使用node2 的IP地址访问这个Service就是无效的.此时请求会直接被DROP掉

方式2(LoadBalancer)

       适合公有云上的kubernetes的服务

      公有云提供的Kubernetes服务里,都使用了一个叫作CloudProvider的转接层,来跟公有云本身的API进行对接.所以,在上述LoadBalancer类型的Service被提交后Kubernetes 就会调用CloudProvider在公有云上为你创建一个负载均衡服务,并且把被代理的Pod的IP地址配置给负载均衡服务做后端

       创建负载均衡的功能交给集群外部的系统来实现 这是和普通service的区别 普通service负载均衡的功能都是由集群内部的组件来实现的

     

 方式3(ExternalName)

     

     这种类型的Service不需要指定selector 因为响应请求的不会是集群中的Pod,而是把用户请求转发到公网中(集群外部)的某个服务器上由它进行响应

     通过Service的DNS名字访问它的时候如访问my-service.default.svc.cluster.local.那么k8s返回的就是my.database.example.com
    ExternalName类型的 Service,其实是在 kube-dns里为你添加了一条CNAME记录.这时,访问my-service.default.svc.cluster.local 就和访问 my.database.example.com 这个域名是一个效果了 
 方式4(ExternalIPs)

       Kubernetes的Service还允许你为Service分配公有IP地址

       当用户向公网(集群外的节点)中的指定的主机和端口发起请求的时候 会把请求转发到k8s由集群中的Pod对用户的请求进行响应 所以定义有selector选择相关Pod

     

    在上述 Service 中,我为它指定的 externalIPs=80.11.12.10那么此时,你就可以通过访问 80.11.12.10:80 访问到被代理的Pod了.不过,在这里Kubernetes要求externalIP必须是至少能够路由到一个Kubernetes的节点 
 

Service总结

       在理解了Kubernetes Service 机制的工作原理之后很多与Service相关的问题,其实都可以通过分析Service在宿主机上对应的 iptables 规则(或者IPVS配置)得到解决
       Kubernetes里面的Service和DNS 机制,也都不具备强多租户能力.比如,在多租户情况下,每个租户应该拥有一套独立的 Service 规则(Service 只应该看到和代理同一个租户下的 Pod)再比如DNS,在多租户情况下,每个租户应该拥有自己的kube-dns(kube-dns 只应该为同一个租户下的 Service 和 Pod 创建 DNS Entry)
posted @ 2020-02-01 10:34  不懂123  阅读(1131)  评论(0编辑  收藏  举报