一个 service,二个IP,三个 port 

1、同一个 Pod 中 容器通信

2、同一个节点多个 Pod 之间通信

3、跨节点的pod通信

4、外部网络和 pod 之间通信

一个 service,3个IP,三个 port 

NodePort
nodeport是外部流量访问K8s的一种方式,即nodeIP:nodePort,是提供给外部流量访问K8s集群资源的一种方式。总的来说,我们可以通过在service中配置nodeport,从而使得我们可以通过集群外的机器进行访问我们的服务。

Port
port是K8s集群内部服务访问service的入口。是service暴露在Cluster上的端口,ClusterIP:Port。如下面的yaml配置文件所示,K8s集群内部节点可以通过30080端口访问Nginx服务,然而外部网络还是不能够访问到服务,因为nodePort参数没有配置。

targetPort
targetPort是容器的端口,也是最终底层的服务所提供的端口,所以说targetPod也就是Pod的端口。从port或者是nodePort进入的流量,经过路由转发之后,最终都会都通过targetPort进入到Pod中。

targetPort要与Dockerfile中暴露的端口一致。

apiVersion: v1
kind: Service
metadata:
 name: nginx-service
spec:
 type: NodePort         // 配置为NodePort,外部可以访问
 ports:
 - port: 30080          // 容器间,服务调用的端口
   targetPort: 80       // 容器暴露的端口,与Dockerfile暴露端口保持一致
   nodePort: 30001      // NodePort,外部访问的端口,如果不显示指定,k8s会随机分配一个端口
 selector:
  name: nginx-pod
 

Kubernetes集群里有三种IP地址,分别如下:

Node IP:Node节点的IP地址,即物理网卡的IP地址。
Pod IP:Pod的IP地址,即docker容器的IP地址,此为虚拟IP地址。
Cluster IP:Service的IP地址,此为虚拟IP地址。
Node IP
可以是物理机的IP(也可能是虚拟机IP)。每个Service都会在Node节点上开通一个端口,外部可以通过NodeIP:NodePort即可访问Service里的Pod,和我们访问服务器部署的项目一样,IP:端口/项目名。

在kubernetes查询Node IP:
1.kubectl get nodes
2.kubectl describe node nodeName
3.显示出来的InternalIP就是NodeIP

Pod IP
Pod IP是每个Pod的IP地址,他是Docker Engine根据docker网桥的IP地址段进行分配的,通常是一个虚拟的二层网络。

同Service下的pod可以直接根据PodIP相互通信。

不同Service下的pod在集群间pod通信要借助于 cluster ip。

pod和集群外通信,要借助于node ip。

在kubernetes查询Pod IP:
1.kubectl get pods
2.kubectl describe pod podName

Cluster IP
Service的IP地址,此为虚拟IP地址。外部网络无法ping通,只有kubernetes集群内部访问使用。

在kubernetes查询Cluster IP: kubectl -n 命名空间 get Service即可看到ClusterIP

Cluster IP是一个虚拟的IP,但更像是一个伪造的IP网络,原因有以下几点:

Cluster IP仅仅作用于Kubernetes Service这个对象,并由Kubernetes管理和分配iP地址

Cluster IP无法被ping,

Cluster IP只能结合Service Port组成一个具体的通信端口,单独的Cluster IP不具备通信的基础,并且他们属于Kubernetes集群这样一个封闭的空间。

在不同Service下的pod节点在集群间相互访问可以通过Cluster IP
 

1、同一个 Pod 中 容器通信

同一个pod内共享网络命名空间,容器之间通过访问 127.0.0.1:(端口)即可

2、同一个节点多个 Pod 之间通信

pause 容器启动之前,会为容器创建虚拟一对 ethernet 接口,一个保留在宿主机 vethxxx(插在网桥上),一个保留在容器网络命名空间内,并重命名为eth0。两个虚拟接口的两端,从一端进入,另一端出来。任何 Pod 连接到该网桥的 Pod 都可以收发数据。

同节点不同 pod 之间通信:通过 linux 虚拟以太网设备或者是用两个虚拟接口组成的以太网接口对不同的网络命名空间连接起来通信

3、跨节点的pod通信(CNI:容器网络接口)

CNI 是一种标准,它旨在为容器平台提供网络的标准化。不同的容器平台(比如目前的 kubernetes、mesos 和 rkt)能够通过相同的接口调用不同的网络组件。

目前kubernetes支持的CNI组件种类很多,例如:bridge calico calico-ipam dhcp flannel host-local ipvlan loopback macvlan portmap ptp sample tuning vlan。在docker中,主流的跨主机通信方案主要有一下几种:

1)基于隧道的overlay网络:按隧道类型来说,不同的公司或者组织有不同的实现方案。docker原生的overlay网络就是基于vxlan隧道实现的。ovn则需要通过geneve或者stt隧道来实现的。flannel最新版本也开始默认基于vxlan实现overlay网络。

2)基于包封装的overlay网络:基于UDP封装等数据包包装方式,在docker集群上实现跨主机网络。典型实现方案有weave、flannel的早期版本。

3)基于三层实现SDN网络:基于三层协议和路由,直接在三层上实现跨主机网络,并且通过iptables实现网络的安全隔离。典型的方案为Project Calico。同时对不支持三层路由的环境,Project Calico还提供了基于IPIP封装的跨主机网络实现

通信方式

4、外部访问集群

从集群外访问集群有多种方式,比如loadbalancer,Ingress,nodeport,nodeport和loadbalancer是service的两个基本类型,是将service直接对外暴露的方式,ingress则是提供了七层负载均衡,其基本原理将外部流量转发到内部的service,再转发到后端endpoints,在平时的使用中,我们可以依据具体的业务需求选用不同的方式。这里主要介绍nodeport和ingress方式。

Nodeport

通过将 Service 的类型设置为 NodePort,就可以在 Cluster 中的主机上通过一个指定端口暴露服务。注意通过 Cluster 中每台主机上的该指定端口都可以访问到该服务,发送到该主机端口的请求会被 Kubernetes 路由到提供服务的 Pod 上。采用这种服务类型,可以在 Kubernetes cluster 网络外通过主机 IP:端口的方式访问到服务。

 influxdb 例子:


kind: Service
apiVersion: v1
metadata:
 name: influxdb
spec:
 type: NodePort
 ports:
 - port: 8086
 nodePort: 31112
 selector:
 name: influxdb

Ingress(重点)

Ingress 是推荐在生产环境使用的方式,它起到了七层负载均衡器和 Http 方向代理的作用,可以根据不同的 url 把入口流量分发到不同的后端Service。外部客户端只看到 http://foo.bar.com 这个服务器,屏蔽了内部多个 Service 的实现方式。采用这种方式,简化了客户端的访问,并增加了后端实现和部署的灵活性,可以在不影响客户端的情况下对后端的服务部署进行调整。

其部署的 yaml 可以参考如下模板:

apiVersion: extensions/v1beta1kind: Ingressmetadata: name: test annotations: ingress.kubernetes.io/rewrite-target: /spec: rules: - host: test.name.com http: paths: - path: /test backend: serviceName: service-1 servicePort: 8118 - path: /name backend: serviceName: service-2 servicePort: 8228

ingress模板,定义通过 http://test.name.com 来访问服务,在虚拟主机http://test.name.com下面定义了两个Path,其中/test被分发到后端服务s1,/name被分发到后端服务s2。 

集群中可以定义多个ingress,来完成不同服务的转发,这里需要一个ingress controller来管理集群中的Ingress规则。Ingress Contronler 通过与 Kubernetes API 交互,动态的去感知集群中 Ingress 规则变化,然后读取它,按照自定义的规则,规则就是写明了哪个域名对应哪个service

Logo

开源、云原生的融合云平台

更多推荐