一、service的必要性

对于k8s,pod不需要是robust的,因为可以通过controller来动态创建和销毁pod来保证应用整体的健壮性。由于每个pod都有自己的地址,所以当controller用新pod替代发生故障的pod时,新pod会分配新的ip地址。那么会导致ip地址发生变化,这时候就需要使用service来维护一个对外网络。
Kubernetes Service从逻辑上代表了一组Pod, 具体是哪些Pod则是由label来挑选的。 Service有自己的IP, 而且这个IP是不变的。 客户端只需要访问Service的IP, Kubernetes则负责建立和维护Service与Pod的映射关系。 无论后端Pod如何变化, 对客户端不会有任何影响, 因为Service没有变。

二、创建一个service

首先先创建一个deployment,记得加上selector
在这里插入图片描述
在这里插入图片描述
创建成功!
例行检查一下pod的情况,kubectl get pod -o wide
在这里插入图片描述
pod分配了各自的ip,这些ip只能被集群中的容器和节点访问
在master节点进行查询
在node节点进行查询
接着我们来创建一个service,老办法,先查询一下service的版本

kubectl api-resources | grep Service

在这里插入图片描述
创建service的yml文件
在这里插入图片描述
字段解释:
selector指明挑选那些label为run:httpd的pod作为service的后端
service的8080端口映射到pod的80端口,使用tcp协议

检查一下service的状况,
在这里插入图片描述
经操作,发现连接不到这个服务,查书才知道,原来service是通过selector指明挑选那些label为run:httpd的pod作为service的后端
在这里插入图片描述

而在上面的deployment文件中,我将label设置为app:httpd,所以service不能成功挑选。修改后如下:
修改了selector的内容
重新尝试访问,果然成功了
在这里插入图片描述
总结:service是创建了一个统一的访问接口,对内屏蔽了各个容器的具体接口,只需要关注service的接口即可使用。
如果需要从外部访问service的话,还得再进行别的设置此时就该NodePort出场了

利用kubectl describe可以查看httpd-svc和pod的对应关系,
在这里插入图片描述
Endpoints罗列了三个Pod的IP和端口。 我们知道Pod的IP是在容器中配置的, 那么Service的Cluster IP又是配置在哪里的呢?CLUSTERIP又是如何映射到Pod IP的呢?答案就是通过iptables这尊大佛

三、cluster ip底层实现

通过iptables-save命令查询具体的iptables规则
在这里插入图片描述
在这里插入图片描述
这两条规则是:
(1)如果Cluster内的Pod(源地址来自10.244.0.0/16) 要访问httpd-svc, 则允许。
(2)其他源地址访问httpd-svc, 跳转到规则KUBE-SVC-IYRDZZKXS5EOQ6Q6
KUBE-SVC-IYRDZZKXS5EOQ6Q6的规则是
在这里插入图片描述
(1)1/3跳转到
在这里插入图片描述

(2)1/3概率(剩下2/3的一半)跳转到
在这里插入图片描述

(3)1/3概率跳转到
在这里插入图片描述
总结:iptables将访问service的流量转发到后端pod,而且使用类似轮询的负载均衡策略。而且cluter的每一个节点都配置了相同的iptables规则,这样就可以确保整个cluster都能够通过service的clusterip访问service
在这里插入图片描述

四、dns访问service

kubeadm部署时会默认安装kube-dns组件
在这里插入图片描述
每当有新的service被创建,就会添加该service的dns记录。cluster的pod可以通过service_name.namespace_name访问service
尝试使用http-svc.default访问service httpd-svc
在这里插入图片描述

五、外网访问service

除了Cluster内部可以访问Service, 很多情况下我们也希望应用的Service能够暴露给Cluster外部。 Kubernetes提供了多种类型的Service, 默认是ClusterIP。

  • ClusterIP
    Service通过Cluster内部的IP对外提供服务, 只有Cluster内的节点和Pod可访问, 这是默认的Service类型, 前面实验中的Service都是ClusterIP。(对内的)
  • NodePort
    Service通过Cluster节点的静态端口对外提供服务。 Cluster外部可以通过(这里的node是指node主机的ip,不是指kubectl get pods -o wide打输出的node ip):访问Service。(对外的)
  • LoadBalancer
    Service利用cloud provider特有的load balancer对外提供服务,cloud provider负责将load balancer的流量导向Service。 目前支持的cloud provider有GCP、 AWS、 Azur等

写文件创建nodeport
在这里插入图片描述
selector记得和deployment的label对应

执行后我们来看看情况,
在这里插入图片描述
(1)external-ip为none,指不可以通过cluster每个节点自身的ip去访问service
当external-ip为nodes时,才可以通过访问节点ip进行访问service
(2)port(s)为8080:30331。8080是clusterip监听的端口,30331是节点上监听的端口。k8s会从30000-32767中分配一个可用的端口,每个节点都会监听此端口并将请求转发给service。(每个节点是指物理节点,是指kubectl get node的点 )

下面将从cluster内和cluster外进行测试访问:
cluster内:
直接对serviceip+对内暴露port进行访问
在这里插入图片描述
cluster外:
利用节点ip+对外暴露的port进行访问
在这里插入图片描述
在这里插入图片描述
接下来我们来研究一下k8s如何实现将nodeip:nodeport映射到pod上,还是利用iptables-save来查询,找到nodeport对应的信息
在这里插入图片描述
访问当前节点30331的端口的请求,会应用规则KUBE-SVC-IYRDZZKXS5EOQ6Q6。我们来找一下对应的规则内容
在这里插入图片描述
其作用和上面提到的类似,也就是负载均衡到每一个pod上。

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐