通过以前的学习,我们已经能够通过控制器来创建一组Pod来提供具有高可用性的服务。虽然每个Pod都会分配一个单独的Pod IP,然而却存在如下两问题:
Pod IP仅仅是集群内可见的虚拟IP,外部无法访问。
Pod IP会随着Pod的销毁而消失,当ReplicaSet对Pod进行动态伸缩时,Pod IP可能随时随地都会变化,这样对于我们访问这个服务带来了难度。
因此,Kubernetes中的Service对象就是解决以上问题的实现服务发现
核心关键。
service解决的问题:
让集群外部的主机访问到集群内部的pod(容器),也就是提供的业务,如何发布出去,当pod进行自动伸缩时,如何让新增的pod被自动的发现,并且进行自动的负载均衡。
它是交互etcd的,信息都持久化的存储在etcd中。etcd是通过堆栈的形式部署的,并不具备高可用。可以通过kubectl get -n kube-system
来查看etcd.
客户端在访问api-server的时候,和etcd进行交互。
etcd是什么?
k8s集群使用etcd作为它的数据后端,etcd是一种无状态的分布式数据存储集群. 数据以key-value的形式存储在其中.
etcd应用场景
1.用于服务发现,服务发现(ServiceDiscovery)要解决的是分布式系统中最常见的问题之一,即在同一个分布式集群中的进程或服务如何才能找到对方并建立连接。
要解决服务发现的问题,需要具备下面三种必备属性。
1.一个强一致性、高可用的服务存储目录。
基于Ralf算法的etcd天生就是这样一个强一致性、高可用的服务存储目录。
2.一种注册服务和健康服务健康状况的机制。
用户可以在etcd中注册服务,并且对注册的服务配置key TTL,
定时保持服务的心跳以达到监控健康状态的效果。
3.一种查找和连接服务的机制。
通过在etcd指定的主题下注册的服务业能在对应的主题下查找到。
为了确保连接,我们可以在每个服务机器上都部署一个proxy模式的etcd,
这样就可以确保访问etcd集群的服务都能够互相连接。
第一种: 是Userspace方式
如下图描述, Client Pod要访问Server Pod时,它先将请求发给本机内核空间中的service规则,由它再将请求,转给监听在指定套接字上的kube-proxy,kube-proxy处理完请求,并分发请求到指定Server Pod后,再将请求递交给内核空间中的service,由service将请求转给指定的Server Pod。
由于其需要来回在用户空间和内核空间交互通信,因此效率很差,接着就有了第二种方式.
第二种: iptables模型
此工作方式是直接由内核中的iptables规则,接受Client Pod的请求,并处理完成后,直接转发给指定ServerPod。
第三种: ipvs模型
它是直接有内核中的ipvs规则来接受Client Pod请求,并处理该请求,再有内核封包后,直接发给指定的Server Pod。
注意:
以上不论哪种,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同其他Kubernetes对象一样,也是通过yaml或json文件进行定义。
此外,它和其他Controller对象一样,通过Label Selector来确定一个Service将要使用哪些Pod。
用于为集群内Pod访问时,提供的固定访问地址,默认是自动分配地址,可使用ClusterIP关键字指定固定IP.
用于为集群外部访问Service后面Pod提供访问接入端口.
这种类型的service工作流程为:
Client----->NodeIP:NodePort----->ClusterIP:ServicePort----->PodIP:ContainerPort
用于当K8s运行在一个云环境内时,若该云环境支持LBaaS,则此类型可自动触发创建一个软件负载均衡器用于对Service做负载均衡调度.
因为外部所有Client都访问一个NodeIP,该节点的压力将会很大, 而LoadBalancer则可解决这个问题。
而且它还直接动态监测后端Node是否被移除或新增了,然后动态更新调度的节点数。
用于将集群外部的服务引入到集群内部,在集群内部可直接访问来获取服务。
它的值必须是 FQDN, 此FQDN为集群内部的FQDN, 即: ServiceName.Namespace.Domain.LTD.
然后CoreDNS接受到该FQDN后,能解析出一个CNAME记录, 该别名记录为真正互联网上的域名.
如: www.test.com, 接着CoreDNS在向互联网上的根域DNS解析该域名,获得其真实互联网IP.
实验环境
主机名(IP) 服务
ser1(172.25.2.2) harbor仓库
ser2(172.25.2.3) master
ser3(172.25.2.4) node1
ser4(172.25.2.5) node2
关闭上述主机的防火墙,selinux,设置每台主机可以上网
我们先来看一下,默认的clusterip模式
运行一个容器,可以访问后端的两个pod
2.
3.连接访问时发现报错
改正端口
测试成功
1.2.截图遗失了,可以看上面的图
3.
4.
5.6.7.
1.在集群node节点ser3中发现
2.在所有节点安装ipvsadm(master节点+node节点),这里不再赘述
3.可以在部署k8s集群的时候,就安装上lvs模块
4.在master节点,设置集群的 lvs模式
1)2)3)将模式改为ipvs模式
4.删除原来的pod
5.在每个节点上发现,lvs的策略自动出现
6.
7.测试自动发现