精华内容
下载资源
问答
  • Consul服务注册与服务发现机制

    千次阅读 2019-06-25 15:43:02
    1、什么是服务注册中心? 顾名思义,假设你有一个分布式系统,里面包含了多个服务,部署在不同的机器上,然后这些不同机器上的服务之间要互相调用。...现在订单服务是想要调用库存服务,但是他并不知道库存服务在...

    1、什么是服务注册中心?

    顾名思义,假设你有一个分布式系统,里面包含了多个服务,部署在不同的机器上,然后这些不同机器上的服务之间要互相调用。

    举个现实点的例子吧,比如电商系统里的订单服务需要调用库存服务,如下图所示。

    现在的问题在于,订单服务在192.168.31.154这台机器上,库存服务在192.137.1.33这台机器上。

    现在订单服务是想要调用库存服务,但是他并不知道库存服务在哪台机器上啊!毕竟人家都是在不同机器上的。

    所以这个时候就需要服务注册中心出场了,这个时候你的系统架构中需要引入独立部署在一台机器上的服务注册中心,如下图所示。

    然后订单服务、库存服务之类的兄弟,都需要配置上服务注册中心部署在哪台机器上,比如192.168.31.45这台机器。

    接着订单服务、库存服务他们自己启动的时候,就得发送请求到到服务注册中心上去进行服务注册。也就是说,得告诉服务注册中心,自己是哪个服务,然后自己部署在哪台机器上。然后服务注册中心会把大家注册上来的信息放在注册表里,如下图。

           接着订单服务假如想要调用库存服务,那么就找服务注册中心问问:能不能告诉我库存服务部署在哪台机器上?服务注册中心是知道这个信息的,所以就会告诉订单服务:库存服务部署在192.1371.133这台机器上,你就给这台机器发送请求吧。然后,订单服务就可以往库存服务的那台机器发送请求了,完成了服务间的调用。整个过程,如下图所示:

           上述就是服务注册中心的作用、地位以及意义,现在大家应该知道服务注册中心的作用了吧。好!接着我们就来看看Consul作为服务注册中心,他的架构设计原理是什么?

    2、Consul服务注册中心的整体架构

           如果要基于Consul作为服务注册中心,那么首先必须在每个服务所在的机器上部署一个Consul Agent,作为一个服务所在机器的代理。然后还得在多台机器上部署Consul Server,这就是核心的服务注册中心。这个Consul Agent可以用来收集你的服务信息然后发送给Consul Server,还会对你的服务不停的发送请求检查他是否健康。然后你要发现别的服务的时候,Consul Agent也会帮你转发请求给Consul Server,查询其他服务所在机器。Consul Server一般要求部署3~5台机器,以保证高可用以及数据一致性。他们之间会自动实现数据同步,而且Consul Server集群会自动选举出一台机器作为leader,其他的Consul Server就是follower。咱们看下面的图,先感受一下这个Consul他整体的架构。

    3、Consul如何通过Raft协议实现强一致性?

          Eureka服务注册中心是不保证数据一致性的。这样的话,很可能你注册的服务,其他人是发现不了的,或者很迟才能发现。

    OK,那么这里就来讨论一下Consul是如何实现数据一致性的。首先,大家知道Consul Server是部署集群的,而且他会选举出来一台Server作为Leader。

          接下来各个服务发送的注册请求都会落地给Leader,由Leader同步给其他Follower。所以首先第一点,Leader Server是绝对有最新的服务注册信息的,是不是?比如库存服务发起注册了,那么Leader Server上一定有库存服务的注册信息。接着如果比如订单服务要发现库存服务的话,这个查询请求会发送给Leader Server。这样服务注册和发现,都是通过一台Leader Server来进行的,就可以保证服务注册数据的强一致性了,大家看下图。

           接着大家想,假如说库存服务在注册的时候数据刚写到Leader Server,结果Leader Server就宕机了,这时候怎么办?那么此时这条注册数据就丢失了,订单服务就没法发现那个库存服务了。没关系,这里Consul会基于Raft协议来解决这个问题

           首先,库存服务注册到Leader Server的时候,会采取Raft协议,要求必须让Leader Server把这条注册数据复制给大部分的Follower Server才算成功。这就保证了,如果你认为自己注册成功了,那么必然是多台Consul Server都有这条注册数据了。如果你刚发送给Leader Server他自己就宕机了,那么这次注册会认为失败。此时,Consul Server集群会重新选举一个Leader Server出来,你需要再次重新注册。这样就可以保证你注册成功的数据绝对不会丢,然后别人发现服务的时候一定可以从Leader Server上获取到最新的强一致的注册数据。

    整个过程,如下图所示:

    上面的图就可以看到,只要你注册的时候基于Raft协议强制同步到大多数Server,哪怕是Leader挂了,也会选举新的Leader。这样就可以让别人从新的Leader Server来发现你这个服务,所以数据是绝对强一致的。

    4、Consul如何通过Agent实现分布式健康检查?

          最后说说Consul是如何通过各个服务机器上部署Agent来实现分布式健康检查的。集中式的心跳机制,比如传统的Eureka,是让各个服务都必须每隔一定时间发送心跳到Eureka Server。如果一段时间没收到心跳,那么就认为这个服务宕机了。

          但是这种集中式的心跳机制会对Eureka Server造成较大的心跳请求压力,实际上平时Eureka Server接收最多的请求之一就是成千上万服务发送过来的心跳请求。

         所以Consul在这块进行了架构优化,引入了Agent概念。

          每个机器上的Consul Agent会不断的发送请求检查服务是否健康,是否宕机。如果服务宕机了,那么就会通知Consul Server。怎么样?是不是发现各个服务自己不用再发送心跳请求去Server了?减小了Server这部分的压力吧?没错,这就是Consul基于Agent实现的分布式健康检查机制,可以大幅度的减小Server端的压力。这样一来,哪怕你就部署个三五台机器,可以轻松支持成千上万个服务。咱们再来一张图,一起来看看:

     

    展开全文
  • 第四篇:服务发现机制

    万次阅读 2017-07-15 13:58:45
    本文出自Service Discovery in a Microservices Architecture,作者 Chris Richardson, 写于2015年5月19日这是本系列文章的第四篇。 第一篇文章:介绍微服务架构并...本文我们继续探索与服务发现紧密联系的有关问题。

    本文出自Service Discovery in a Microservices Architecture,作者 Chris Richardson, 写于2015年5月19日

    这是本系列文章的第四篇。

    本文我们继续探索与服务发现紧密联系的有关问题。

    一、为什么使用服务发现?

    想象一下编写代码调用REST或者Thrift API的服务,为了实现这个调用,你的代码需要知道服务实例的网络位置(IP 地址和端口)。在运行在物理硬件的传统应用中,服务实例的网络位置是相对静止的。例如,代码可以从配置文件中读取网络位置,这个配置文件偶尔会更新。

    但是,在现代基于云的微服务应用中,这是非常难以解决的问题,正如图4-1显示的一样:

    服务实例被动态地赋予网路位置。另外,由于自动伸缩、故障和升级,服务实例集合经常会动态改变。所以客户端代码需要使用详细设计的服务发现机制。

    这里写图片描述

    图4-1 客户端或者API网关需要帮助发现服务

    有两种主要的服务发现机制:客户端发现机制服务端发现机制。首先来看一下客户端发现机制。

    二、客户端发现模式

    当使用客户端发现模式时,客户端负责确定可用服务实例的网络位置并且对通过它们的请求进行负载均衡客户端查询服务注册中心,服务注册中心是一个可用服务实例的数据库。客户端接着使用负载均衡算法选择可用的服务实例中的一个并把这个请求路由到该实例

    图4-2显示这个模式的结构:

    这里写图片描述

    图4-2 客户端执行服务发现的任务

    当服务实例启动的时候,它的网络地址被注册到服务注册中心。当该实例终止的时候,该地址从服务注册中心移除服务实例的注册通常使用心跳机制定期刷新

    Netflix OSS 为客户端发现模式提供了很好的例证。Netflix Eureka 是一个服务注册中心,它提供了REST API来管理服务实例的注册和可用实例的查询。Netflix Ribbon是一个和Eureka共同工作的IPC客户端,它负责将请求负载均衡到可用的服务实例上。后面我们会深入讨论Eureka。

    客户端发现模式有很多的缺点和优点。

    优点:

    • 这个模式相对更直接一点,除了服务注册中心,没有要改变的地方;
    • 并且,因为客户端了解可用的服务实例,它能做出智能、针对特定应用的负载均衡决策,比如使用一致性哈希。

    缺点:

    • 这种模式的一个重要的缺陷是它将客户端与服务注册中心耦合在一起。你必须为服务客户端使用的每种编程语言和框架都实现服务发现逻辑;

    了解了客户端发现机制,让我们继续探索一下服务端发现模式。

    三、服务端发现模式

    另外一种到服务注册中心的途径是服务端发现模式 。图4-3 显示了这种模式的结构。

    这里写图片描述

    图4-3 服务注册中心也可以由服务器处理

    客户端通过负载均衡器向服务发送请求负载均衡器查询服务注册中心并路由每个请求到可用的服务实例。与客户端发现机制一样,服务实例也需要向服务注册中心注册和注销

    AWS Elastic Load Balancer (ELB) 是服务端发现路由器的一个例证。ELB通常用来对外部的因特网流量进行负载均衡。但是,你也可以在内部使用ELB进行到虚拟私有云(virtual private cloud ,VPC)的负载均衡。

    客户端使用ELB的域名来发送HTTP或者TCP请求。ELB将流量负载均衡地路由到一系列注册的Elastic Compute Cloud (EC2)实例,或者EC2 Container Service (ECS) 容器。不存在独立可见的服务注册中心。EC2实例和ECS容器直接注册到ELB本身。

    HTTP服务器和负载均衡器,比如NGINX Plus和NGINX,也可以用作服务端发现机制中的负载均衡器。例如,这篇文章描述了使用Consul Template动态地更新NGINX反向代理服务器的配置。Consul Template是一个可以根据存储在Consul service registry的数据定期重新生成任意配置文件的工具。无论什么时候文件改变,它都会运行任意的shell命令。在上面的文章中描述的例子中,Consul Template生成了一个nginx.conf的配置文件,用于配置反向代理,接着运行命令告诉NGINX重新加载该配置文件。一个更加复杂的实现,比如使用NGINX的HTTP API或者DNS也能动态地更新NGINX Plus的配置 。

    一些部署环境,比如KubernetesMarathon在集群的每个主机上都会运行代理。代理扮演服务端发现机制中的负载均衡器的角色。为了给服务发请求,客户端通过代理使用主机IP和服务的端口号路由请求。代理接着转发该请求到运行在集群上的可用服务实例。

    服务端发现模式有几个优点和缺点。

    优点:

    • 服务发现的细节从客户端抽象出来,客户端只需要给负载均衡器发请求即可。这种方式避免为服务客户端使用的每种编程语言和框架都实现服务发现逻辑;
    • 正如上文所说,一些部署环境免费提供了这种功能

    缺点:

    • 除非部署环境提供负载均衡器,否则它又是另一个需要设置和管理的高度可用的系统组件

    四、服务注册中心

    服务注册中心是服务发现机制中的核心部分。它是一个包含服务实例网络位置的数据库。服务注册中心需要高度可用并实时更新。客户端可以缓存从服务注册中心获取的网络位置。但是,信息最终会过期,导致客户端不能发现服务实例。于是,服务注册中心可以使用复制协议来维护一致性的服务器集群。

    上文提到,Netflix Eureka是服务注册中心的很好的例证。它提供REST API来注册和查询服务实例。服务实例通过POST请求来注册它的网络地址,每隔30s,它都要通过PUT请求来刷新它的注册信息。当服务实例发送HTTP 的DELETE请求,或者注册(包括刷新)超时的时候,该注册信息都会从服务注册中心移除。如你所想,客户端可以通过使用HTTPGET请求来获取已经注册的服务实例。

    Netflix通过在每个Amazon EC2可用区域运行一个或者多个Eureka服务器来实现高可用性。每个Eureka服务器运行在有弹性IP地址的EC2实例上。使用DNSTEXT记录来存储Eureka集群的配置,这个配置是从可用区域到Eureka服务器的网络地址的列表的映射表,当Eureka服务器启动的时候,它查询DNS来获取Eureka集群配置,定位它的伙伴,分配给自己一个没有使用的弹性IP地址

    Eureka客户端、服务和服务客户端通过查询DNS来发现Eureka服务器的网络地址。客户端更希望使用在相同可用区域里的Eureka服务器。但是,如果没有可用的,就需要使用别的可用区域的里的Eureka服务器。

    服务注册中心的其他例子:

    • etcd:高度可用,分布式,一致性的键值存储,用来共享配置或作为服务注册中心。Kubernetes和Cloud Foundry 这两个著名的项目使用了它;
    • Consul:一个发现和配置服务的工具,提供了API允许客户端注册并发现服务,也能通过健康检查来确定服务的可用性;
    • Apache ZooKeeper:用于分布式应用的广泛使用的、高性能的协调服务。开始作为Hadoop的子项目,但是现在是一个独立的顶级项目;

    正如前面提到的,一些系统,比如Kubernetes,Marathon和AWS不需要显式的服务注册中心,而是作为基础设施的内置的一部分。

    我们已经了解了服务注册中心的概念,继续看看服务实例是如何注册到服务注册中心的。

    五、服务注册选项

    如上所述,服务实例必须从服务注册中心注册和注销。有很多种方式可以处理注册和注销操作:

    首先看一下自我注册模式。

    5.1自我注册模式

    当使用自我注册模式时,服务实例自己负责从服务注册中心注册和注销。并且如果必要的话,服务实例要发送心跳请求来防止注册过期。图4-4显示了这种模式的结构:

    这里写图片描述

    图4-4 服务可以自己完成注册

    这种方法的一个例证是Netflix OSS Eureka client 。Eureka client可以处理服务实例注册和注销的所有方面的事情。Spring Cloud project 实现了多种模式,包括服务注册中心,使得自动注册服务实例到Eureka很容易。你只要在Java配置类中添加@EnableEurekaClient注解即可。

    自我注册模式也有很多优点和缺点。

    优点:

    • 相对简单,并且不要求额外的系统组件;

    缺点:

    • 将服务实例和服务注册中心耦合,导致为服务使用的每种编程语言和框架都实现服务注册逻辑;

    可以替代的方法是第三方注册模式,它将服务和服务注册中心解耦,

    5.2第三方注册模式

    当使用第三方注册模式时,服务实例不负责注册自己到服务注册中心。 而是通过其他称为服务注册组件的系统组件来处理服务注册。服务注册组件通过轮询部署环境或者订阅事件来追踪运行实例的集合的变化。当它注意到有新的可用的服务实例时,就会将该实例注册到服务注册中心。服务注册组件也可以注销终止的服务实例。

    图4-5 显示了这种模式的结构:

    这里写图片描述

    图4-5 独立的注册组件服务负责注册其他的服务

    服务注册组件的一个例证是开源的Registrator工程。它会自动的注册和注销部署为Docker容器的服务实例。注册组件支持多种服务注册中心,比如etcd和Consul。

    另外一个服务注册中心的例证是NetflixOSS Prana 。主要用于非JVM语言编写的服务,它是一个和服务实例并行运行的sidecar应用。Prana使用Netflix Eureka来注册和注销服务实例。

    服务注册组件在一些部署环境中是内建的组件。由Autoscaling Group 创建的EC2实例可以自动的注册到ELB。Kubernetes 服务会自动注册并被发现可用。

    第三方注册模式也有很多的缺点和优点。

    优点:

    • 一个主要的优点是服务与服务注册中心解耦,不需要为服务使用的每种编程语言和框架都实现服务注册逻辑。服务注册逻辑通过一个专门的服务以集中的方式处理;

    缺点:

    • 除非该注册组件在部署环境中内建,需要设置和管理一个高可用的系统组件

    六、总结

    在微服务架构中,运行的服务实例集合是动态变化的。实例也被动态的赋予网络地址。于是为了客户端能够给服务发送请求,就必须使用服务发现机制。

    服务发现机制中的核心部分是服务注册中心。服务注册中心是可用服务实例的数据库。服务注册中心提供管理API和查询API。服务实例使用管理API从服务注册中心注册和注销。系统组件使用查询API来发现可用的服务实例。

    服务从服务注册中心注册和注销有两种方式:

    在一些部署环境中,需要使用比如Netflix Eureka, etcd, 或者Apache ZooKeeper等设置自己的服务发现基础设施。在一些其他的部署环境中,服务发现机制是内建的。例如,KubernetesMarathon自己处理服务的注册和注销。它们也在每个集群主机上运行一个代理,这个集群主机扮演了服务端发现机制中的路由器的角色。

    HTTP 反向代理和负载均衡器比如NGINX也能用作服务端发现种的负载均衡器。服务注册中心可以给NGINX推送路由信息并且优雅的完成配置更新。例如可以使用Consul Template。NGINX Plus 支持更多的配置动态更新机制– 它可以使用DNS从服务注册中心拉取有关服务实例的信息,它也提供了API来远程完成配置重构。

    展开全文
  • 服务发现机制Kubernetes提供了两种发现Service的方法:1.环境变量当Pod运行的时候,Kubernetes会将之前存在的Service的信息通过环境变量写到Pod中。这种方法要求Pod必须要在Service之后启动。在Service之前启动的Pod...

    服务发现机制

    Kubernetes提供了两种发现Service的方法:

    1.环境变量

    当Pod运行的时候,Kubernetes会将之前存在的Service的信息通过环境变量写到Pod中。

    这种方法要求Pod必须要在Service之后启动。

    在Service之前启动的Pod就不会有该Service的环境变量。

    采用DNS的方式就没有这个限制。

    2.DNS

    当有新的Service创建时,就会自动生成一条DNS记录。

    使用这种方法,需要安装Cluster DNS。

    Kubernetes1.2.7版本下Cluster DNS的安装

    阅读github上官方源码发现:
    Cluster DNS自Kubernetes1.3版本开始,结构发生了变化。这里先以1.2.7版本作为研究。

    1.2.7版本中,Cluster DNS主要包含如下几项:

    1)SkyDNS
    提供DNS解析服务。
    2)Etcd
    用于DNS的存储。
    3)Kube2sky
    监听Kubernetes,当有新的Service创建时,将其注册到etcd上。
    4)healthz
    提供对skydns服务的健康检查功能。

    安装过程参考官方github文档。

    在Master服务器上下载Kubernetes发布包

    Cluster DNS在Kubernetes发布包的cluster/addons/dns目录下

    yum -y install wget
    wget https://codeload.github.com/kubernetes/kubernetes/tar.gz/v1.2.7
    tar zxvf v1.2.7
    cd kubernetes-1.2.7/cluster/addons/dns

    需要注意,skydns服务使用的clusterIP需要我们指定一个固定的IP地址,每个Node的kubelet进程都将使用这个IP地址,不能通过Kuberneters自动给skydns分配。

    通过环境变量,配置参数

    export DNS_SERVER_IP="10.254.10.2"
    export DNS_DOMAIN="cluster.local"
    export DNS_REPLICAS=1

    设置 Cluster DNS Service的IP为 10.254.10.2(不能和已分配的IP重复),Cluster DNS的本地域为 cluster.local。

    修改每台Node上的kubelet启动参数

    vim /etc/kubernetes/kubelet

    在KUBELET_ARGS里增加:

    --cluster_dns=10.254.10.2 
    --cluster_domain=cluster.local

    cluster_dns为DNS服务的ClusterIP地址
    cluster_domain为DNS服务中设置的域名

    重启kubelet服务

    systemctl restart kubelet

    生成dns-rc.yaml和dns-svc.yaml

    kubernetes-1.2.7/cluster/addons/dns目录下。

    这里写图片描述

    skydns-rc.yaml.in和skydns-svc.yaml.in是两个模板文件,通过设置的环境变量修改其中的相应属性值,可以生成Replication Controller和Service的定义文件。

    生成Replication Controller的定义文件dns-rc.yaml创建RC

    sed -e "s/{{ pillar\['dns_replicas'\] }}/${DNS_REPLICAS}/g;s/{{ pillar\['dns_domain'\] }}/${DNS_DOMAIN}/g" \skydns-rc.yaml.in > dns-rc.yaml

    需要注意kube2sky需要ServiceAccount来调用Kubernetes API。
    而ServiceAccount的使用需要对Kubernetes集群进行安全认证,否则可能会导致RC无法自动创建Pod等错误

    这里有两种解决办法:

    (1)选择禁用ServiceAccount。编辑/etc/kubernetes/apiserver。
    去除 KUBE_ADMISSION_CONTROL中的SecurityContextDeny,ServiceAccount,并重启kube-apiserver.service服务

    #vim /etc/kubernetes/apiserver
    KUBE_ADMISSION_CONTROL="--admission_control=NamespaceLifecycle,NamespaceExists,LimitRanger,ResourceQuota"
    #systemctl restart kube-apiserver.service

    而关闭ServiceAccount,需要在kube2sky显示指定Kubernetes API的URL
    (2)对集群进行安全认证,参考kubernetes学习记录(9)——集群基于CA签名的安全设置 ,不需要对kube2sky显示指定Kubernetes API的URL

    修改生成的dns-rc.yaml,设置Kube2sky的启动参数如下:

    args:
      - --domain=cluster.local
      #如果已经进行CA认证,则可以不指定kube_master_url
      - --kube-master-url=http://192.168.121.143:8080

    这里特别注意:
    在设置Kube2sky的启动参数时
    《Kubernetes实战》和某些技术博客中
    将“- –domain”和“- –kube-master-url”错误地写成了“- -domain”和“ - -kube-master-url”,均少了一个“-”

    导致,Kube2sky的pod在启动过程中,报CrashLoopBackOff的错误。

    建议将dns-rc.yaml里镜像的下载地址gcr.io改成index.tenxcloud.com,能够加速下载。

    最终的dns-rc.yaml如下

    apiVersion: v1
    kind: ReplicationController
    metadata:
      name: kube-dns-v11
      namespace: kube-system
      labels:
        k8s-app: kube-dns
        version: v11
        kubernetes.io/cluster-service: "true"
    spec:
      replicas: 1
      selector:
        k8s-app: kube-dns
        version: v11
      template:
        metadata:
          labels:
            k8s-app: kube-dns
            version: v11
            kubernetes.io/cluster-service: "true"
        spec:
          containers:
          - name: etcd
            image: index.tenxcloud.com/google_containers/etcd-amd64:2.2.1
            resources:
              # TODO: Set memory limits when we've profiled the container for large
              # clusters, then set request = limit to keep this container in
              # guaranteed class. Currently, this container falls into the
              # "burstable" category so the kubelet doesn't backoff from restarting it.
              limits:
                cpu: 100m
                memory: 500Mi
              requests:
                cpu: 100m
                memory: 50Mi
            command:
            - /usr/local/bin/etcd
            - -data-dir
            - /var/etcd/data
            - -listen-client-urls
            - http://127.0.0.1:2379,http://127.0.0.1:4001
            - -advertise-client-urls
            - http://127.0.0.1:2379,http://127.0.0.1:4001
            - -initial-cluster-token
            - skydns-etcd
            volumeMounts:
            - name: etcd-storage
              mountPath: /var/etcd/data
          - name: kube2sky
            image: index.tenxcloud.com/google_containers/kube2sky:1.14
            resources:
              # TODO: Set memory limits when we've profiled the container for large
              # clusters, then set request = limit to keep this container in
              # guaranteed class. Currently, this container falls into the
              # "burstable" category so the kubelet doesn't backoff from restarting it.
              limits:
                cpu: 100m
                # Kube2sky watches all pods.
                memory: 200Mi
              requests:
                cpu: 100m
                memory: 50Mi
            livenessProbe:
              httpGet:
                path: /healthz
                port: 8080
                scheme: HTTP
              initialDelaySeconds: 60
              timeoutSeconds: 5
              successThreshold: 1
              failureThreshold: 5
            readinessProbe:
              httpGet:
                path: /readiness
                port: 8081
                scheme: HTTP
              # we poll on pod startup for the Kubernetes master service and
              # only setup the /readiness HTTP server once that's available.
              initialDelaySeconds: 30
              timeoutSeconds: 5
            args:
            # command = "/kube2sky"
            #特别注意
            #- -domain=cluster.local是错误的写法
            #- -kube-master-url=http://192.168.121.143:8080是错误的设置
            #会导致CrashLoopBackOff的错误
            #如果已经进行CA认证,则可以不指定kube-master-url
            - --domain=cluster.local
            - --kube-master-url=http://192.168.121.143:8080
          - name: skydns
            image: index.tenxcloud.com/google_containers/skydns:2015-10-13-8c72f8c
            resources:
              # TODO: Set memory limits when we've profiled the container for large
              # clusters, then set request = limit to keep this container in
              # guaranteed class. Currently, this container falls into the
              # "burstable" category so the kubelet doesn't backoff from restarting it.
              limits:
                cpu: 100m
                memory: 200Mi
              requests:
                cpu: 100m
                memory: 50Mi
            args:
            # command = "/skydns"
            - -machines=http://127.0.0.1:4001
            - -addr=0.0.0.0:53
            - -ns-rotate=false
            - -domain=cluster.local.
            ports:
            - containerPort: 53
              name: dns
              protocol: UDP
            - containerPort: 53
              name: dns-tcp
              protocol: TCP
          - name: healthz
            image: index.tenxcloud.com/google_containers/exechealthz:1.0
            resources:
              # keep request = limit to keep this container in guaranteed class
              limits:
                cpu: 10m
                memory: 20Mi
              requests:
                cpu: 10m
                memory: 20Mi
            args:
            - -cmd=nslookup kubernetes.default.svc.cluster.local 127.0.0.1 >/dev/null
            - -port=8080
            ports:
            - containerPort: 8080
              protocol: TCP
          volumes:
          - name: etcd-storage
            emptyDir: {}
          dnsPolicy: Default  # Don't use cluster DNS.

    通过定义文件dns-rc.yaml创建Cluster DNS Replication Controller

    kubectl create -f dns-rc.yaml

    验证Cluster DNS Pod是否创建运行成功:

    kubectl get pod --namespace=kube-system -o wide

    这里写图片描述

    生成Service的定义文件dns-svc.yaml创建Service

    sed -e "s/{{ pillar\['dns_server'\] }}/${DNS_SERVER_IP}/g" \skydns-svc.yaml.in > dns-svc.yaml
    apiVersion: v1
    kind: Service
    metadata:
      name: kube-dns
      namespace: kube-system
      labels:
        k8s-app: kube-dns
        kubernetes.io/cluster-service: "true"
        kubernetes.io/name: "KubeDNS"
    spec:
      selector:
        k8s-app: kube-dns
      clusterIP: 10.254.10.2
      ports:
      - name: dns
        port: 53
        protocol: UDP
      - name: dns-tcp
        port: 53
        protocol: TCP

    根据dns-svc.yaml创建Cluster DNS Service

    kubectl create -f dns-svc.yaml

    查询验证Cluster DNS Service

    kubectl get svc --namespace=kube-system -o wide

    这里写图片描述

    创建Pod验证Cluster DNS

    使用一个带有nslookup的工具来验证DNS是否能够正常工作:
    busybox.yaml

    apiVersion: v1
    kind: Pod
    metadata:
      name: busybox
      namespace: default
    spec:
      containers:
      - name: busybox
        image: index.tenxcloud.com/google_containers/busybox
        command:
          - sleep
          - "3600"
    #kubectl create -f busybox.yaml
    #kubectl exec busybox -- nslookup kubernetes.default.svc.cluster.local

    发现报错

    Error from server: error dialing backend: dial tcp 192.168.121.144:10250: getsockopt: connection refused

    调试解决该问题的过程:
    1)在192.168.121.144上执行

    ip addr

    发现没有flanneld网桥。
    《kubernetes学习记录(4)——创建kubernetes覆盖网络》忘记设置flanneld开机自启了,博客中已修改。
    重启flanneld网桥,仍报错。
    (所以这里flanneld是否需要开机自启还不确定)
    2)在Master上执行

    #curl 192.168.121.144:10250
    curl: (7) Failed connect to 192.168.121.144:10250; Connection refused

    端口无法连接。
    10250是kubelet的端口。
    在Node上检查/etc/kubernetes/kubelet。
    经过多方对比和测试发现。
    KUBELET_ADDRESS需要修改为node ip。
    最终的/etc/kubernetes/kubelet内容(未经过CA验证版)如下:

    KUBELET_ADDRESS="--address=192.168.121.145"
    # The port for the info server to serve on
    # KUBELET_PORT="--port=10250"
    # You may leave this blank to use the actual hostname
    KUBELET_HOSTNAME="--hostname-override=192.168.121.145"
    # location of the api-server
    KUBELET_API_SERVER="--api-servers=http://192.168.121.143:8080"
    # pod infrastructure container
    KUBELET_POD_INFRA_CONTAINER="--pod-infra-container-image=registry.access.redhat.com/rhel7/pod-infrastructure:latest"
    # Add your own!
    KUBELET_ARGS="--cluster_dns=10.254.10.2 --cluster_domain=cluster.local"

    重启kubelet。
    最后重新执行

    kubectl exec busybox -- nslookup kubernetes.default.svc.cluster.local

    这里写图片描述

    总结

    网上的各种安装教程和配置教程多多少少都存在一些问题,不能完全相信书籍和教程,我的博客里估计也有很多的坑。慢慢学习中。

    展开全文
  • Eureka和Zookeeper作为服务发现和治理组件的对比,以及他们在各自系统中的作用机制

    SpringCloud和Dubbo都是当下流行的RPC框架,各自都集成了服务发现和治理组件。SpringCloud用Eureka,Dubbo用Zookeeper,这篇博客就将将这两个组件在各自系统中的作用机制的区别。

    1.注册的服务的区别

    Dubbo是基于java接口及Hession2序列化的来实现传输的,Provider对外暴露接口,Consumer根据接口的规则调用。也就是Provider向Zookeeper注册的是接口信息,Consumer从Zookeeper发现的是接口的信息,通过接口的name,group,version来匹配调用。Consumer只关注接口是否匹配,而对此接口属于什么应用不关心。当然接口的注册信息里会包含应用的ip,hostname等。

    SpringCloud的服务发现是基于Http协议来实现的,Provider对外暴露的是应用信息,比如应用名称,ip地址等等,Consumer发现的是应用的信息,当调用的时候随机选择一个Provider的IP地址,应用名称,然后依据Http协议发送请求。Consumer关注的是应用名称,根据应用名称来决定调用的是哪个服务集群,然后对此名称对应的服务集群做负载均衡。Provider接受到请求后,根据内置的SpringMVC来匹配路由处理请求。

    2 . Server集群服务信息同步的区别

    Dubbo使用Zookeeper做服务发现和治理,Zookeeper是一个分布式协调框架,其有很多很实用的功能,服务发现仅仅是其中的一个。Zookeeper基于著名的CAP理论中的C(一致性),P(分区可用性)实现,它的ZAB(zookeeper atomic broadcast protocol)协议,保证了集群里状态的一致性。Client的每一个事务操作都由Leader广播给所有Follower,当超过半数的Follower都返回执行成功后,才执行事务的ack。对于因网络崩溃或者宕机等问题而执行失败的zookeeper节点,zookeeper会基于zab的崩溃恢复机制来处理,这里不再讲述。每一个操作都需要过半数的zookeeper节点执行成功才确认成功,那么当zookeeper集群过半数节点出现问题时,服务发现功能就不可用。

    SpringCloud使用Eureka做服务发现和治理,它是一个专门用于服务发现和治理的框架,其基于CAP理论中的A(可用性),P(分区可用性)实现。EurekaServer节点间的服务信息同步是基于异步Http实现的。每隔Server节点在接收Client的服务请求时,立即处理请求,然后将此次请求的信息拷贝,封装成一个Task,存入Queue中。Server初始化时会启动一个线程定期的从TaskQueue中批量提取Task,然后执行。服务同步不保证一定成功,虽然有失败重试,但超过一定时限后就放弃同步。当然其有一个特性,当服务丢失后,同步的操作返回400,404后会立即将最新的服务信息同步过去,因此即使中途同步失败,不会对后续的同步有影响。

    3 . 服务更新机制的区别

    Dubbo使用Zookeeper做服务发现和治理,订阅Zookeeper下相应的znode。当节点发生变化,比如有新的元素增加,或者旧的元素移除,Zookeeper会通知所有订阅此节点的Client,将当前的全量数据同步给各Client,Dubbo里根据最新的数据来做相应处理,移除下线的,初始化新增的。每次更新都同步全量数据

    Eureka在启动时向Server进行一次全量拉取,获取所有的可用服务信息,之后默认情况下都是进行增量拉取。Server会将有变化的服务信息放在一个Queue里,Client每次同步时仅获取增量信息,根据信息里的操作类型,服务信息来对当前持有的服务做相应的处理,移除下线的,初始化新增的等。每次更新仅同步增量数据,也就是更新的数据

    4 . 服务更新反馈机制的区别

    Dubbo订阅Zookeeper下相应的节点,当节点的状态发生改变时,Zookeeper会立即反馈订阅的Client,实时性很高。

    Eureka Server在接收到Client的更新操作,或者移除服务信息时,仅仅会将更新消息存放入recentlyChangedQueue中,不会主动的反馈其他Client。其他Client只有在拉取服务增量信息时才会感知到某个服务的更新,延时最大为30S,也就是拉取周期。

    5 . 服务信息回收机制的区别

    Dubbo Provider初始化时会创建一个Zookeeper Client,专门用于与Zookeeper集群交互。维持与集群间的长连接,定时发送心跳,维护Zookeeper上自身节点的存在。节点类型是临时节点,也就是当心跳超时或者长连接断开时,会立即移除Provider对应的节点。
    Dubbo Consumer初始化时也会创建一个Zookeeper Client,专门用于与Zookeeper集群交互。维持长连接,创建EvenetListener,监听Provider节点的变动情况。当Provider节点新增或者移除时,Zookeeper会广播这个事件,然后将此节点的当前值(剩下的所有接口信息)发送给那些注册了此节点监听器的Client。Consumer获取到对应Provider节点下的所有接口信息后,移除已下线的,创建新增的。
    Zookeeper对服务信息的维护实时性和一致性比较高,但也可能因为网络问题或者集群问题导致服务不可用。

    SpringCloud的服务信息回收仅基于心跳超时,与长连接无关。当心跳超时后,EurekaServer回收服务信息,然后将此动作同步给其他Server节点。当然可能一个服务信息会存在多个Server上,多次回收操作的同步具备幂等性。也就是说服务回收只需要通知一个Server节点就可以了,回收动作会通过Server节点传播开来。EurekaServer能够回收服务信息由个重要前提:上一分钟内正常发送心跳的服务的比列超过总数的85%,如果因为网络波动等原因造成大量服务的心跳超时,那么EurekaServer会触发自我保护机制,放弃回收那些心跳超时的服务信息。服务发现组件应该优先保证可用性,Consumer能够发现Provider,即使发现的是非可用的Provider,但因为Conusmer一般具备容错机制,不会对服务的正常调用有太多影响。从这点上看Eureka的服务发现机制要比Zookeeper稍微合理一点的。

    6 . 节点性质的区别

    Dubbo只有Consumer订阅Provider节点,也就是Consumer发现Provider节点信息

    Eureka不区分Consumer或者Provider,两者都统称为Client,一个Client内可能同时含有Provider,Consumer,通过服务发现组件获取的是其他所有的Client节点信息,在调用时根据应用名称来筛选节点

    7 . 使用方式的区别

    Dubbo使用Zookeeper作为服务发现和治理的组件,所以需要搭建Zookeeper集群作为依赖。

    SpringCloud使用Eureka作为服务发现和治理组件,在Spring应用中整合Eureka还是很简单的,引入依赖,加个注解,指定集群Server的serviceUrl,其他的都可以使用默认配置即可,启动应用,Eureka集群就搭建好了。同时配合SpringCloudConfg,能够统一管理Eureka的集群配置信息,可以动态的增加或减少EurekaServer的集群节点。Eurerka会每隔15分钟根据配置上的集群信息重新生成集群节点,覆盖之前的。这种机制比Zookeeper要更优秀一些,毕竟Eureka算是Spring生态里的一环,已经被整合的非常好了,能够以很多匪夷所思的方式来使用。

    展开全文
  • 微服务系统中的服务发现机制

    万次阅读 2016-07-13 00:05:31
    为什么要使用服务发现? 我们可以想象一下,当我们需要远程的访问REST API或者Thrift API时,我们必须得知道服务的网络地址(IP Address和port)。传统的应用程序都是运行在固定的物理机器上,IP Address和端口号...
  • 如果负载均衡器挂了,所有服务都不能被访问。就算负载均衡器是高可用的,它也会成为整个应用的瓶颈。 限制了水平扩展。单节点的负载均衡器能力是有限的。负载均衡器有两点制约: 冗余模型和许可证费用。大部分的...
  • Istio:服务发现和Pilot的架构机制

    千次阅读 2020-01-11 23:03:09
    Istio服务发现 Istio服务配置 stio服务发现&规则管理与Kubernetes结合 ShowCase Istio架构&Pilot介绍 Istio架构 Pilot功能 服务发现 服务配置 Istio服务发现 服务发现基本原理 a.app 88.88....
  • RegistryDirectory,基于注册中心的服务发现,本文将重点探讨Dubbo是如何实现服务的自动注册与发现。从上篇文章,得知在消息消费者在创建服务调用器(Invoker)【消费者在初始时】时需要根据不同的协议,例如dubbo、...
  • 在微服务架构或分布式环境下,服务注册与发现技术不可或缺​,这也是程序员进阶之路必须要掌握的核心技术之一,本文通过图解的方式带领大家轻轻松松掌握。 一、引入服务注册与发现组件的原因 先来看一个问题,...
  • 服务调用者要在众多的微服务中调用具体的服务提供者,必然涉及到负载均衡的问题,根据负载均衡的实现可以分为集中式LB、进程内LB和独立进程LB。 集中式LB LB上有所有的服务地址配置,当服务消费者调用某个服务的...
  • 如何理解服务注册和服务发现

    千次阅读 2019-05-06 11:49:28
    三者的关系是:通过服务注册机制将启动服务的信息上传至服务注册表,服务发现机制通过服务注册表实时获取可用服务的信息。 服务注册的方式包括:自注册和第三方注册。自注册的意思是当服务启动时,服务自动将信息...
  • istio:服务发现和pilot架构机制

    千次阅读 2019-10-18 17:52:25
    之前看到过华为istio的一系列课程,在这里做一下分享,随着自己对istio的认知不断提升,回头看这些片子很有意义。...服务发现的原理可以查看我之前的博文 kubernetes服务发现 ...
  • 服务器心跳机制

    千次阅读 2019-02-17 11:32:46
    心跳机制是定时发送一个自定义的结构体(心跳包),让对方知道自己还活着,以确保连接的有效性的机制。 应用场景: 在长连接下,有可能很长一段时间都没有数据往来。理论上说,这个连接是一直保持连接的,但是实际...
  • Openstack中的服务是分布式部署,因此,各个服务的启停状态,决定了此系统的可用性。我们可以 通过openstack提供的接口来查看服务的运行状态,比如: nova service的相关配置 Nova相关的配置项都nova/conf这个目录...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 565,578
精华内容 226,231
关键字:

服务发现机制