重磅 | 微软Service Fabric正式开源,入局第三代微服务框架争霸!

ServiceMesh小数 发表了文章 • 0 个评论 • 966 次浏览 • 2018-03-16 10:03 • 来自相关话题

小数话:

今天一早 Service Mesh 微信交流群里传来了微软 Service Fabric 项目正式开源的消息,引起了大家广泛关注和讨论。小数为大家整理了目前有关 Service Fabric 开源的一些内容和原博客翻译,其中以下导读部分及结论部分感谢@张善友先生的贡献,该部分转自其知乎账号https://zhuanlan.zhihu.com/p/34574512 

 
导读 
 
微软的 Azure Service Fabric 的官方博客在2017.3.14日发布了一篇博客《Service Fabric .NET SDK goes open source 》,详见下面原文翻译。介绍了社区呼声最高的 Service Fabric 的开源情况以及当前的情况,当时开源了 Service Fabric 的 .NET SDK 部分,社区一直在期盼着 Service Fabric 的正式开源,经过了一年漫长的等待,2018年3月14日微软终于开源了 Service Fabric,而且是以 MIT 许可下开放源代码。
 
目前微软在 Github 上的开源地址是 https://github.com/Microsoft/service-fabric ,目前的代码构建适用于 Linux 的 Service Fabric,运行基本测试,有问题可以在上面提交 Issue和 PR 了,Windows 构建环境以及完整的 CI 环境还没有迁移过来,看到代码还是3个小时前初始化的。Windows内部为 Service Fabric 开发了将近十年的内部服务,其中大部分时间都是微软内部平台,比如 Office365,Azure Stack 平台等,这意味着我们有近十年的内部微软工具可以在迁移之前完成迁移和流程细化,逐步全部开源,以后全部开发都在开源模式下进行开发工作。

 
 原文翻译 
 
我们很高兴地宣布 Service Fabric 将在 MIT 许可下开放源代码,在未来几个月内,我们将在GitHub上过渡到一个完全开放的开发过程。
 
我们听到了很多关于能够参与到你所依赖的平台的开发和方向上,以运行你的关键任务应用程序的重要性。由于这个原因,我们在 GitHub 和 Stack Overflow 上保持活跃,开放源码平台使这种协作更好的自然演进。这就是为什么我们致力于将我们的整个开发和规划过程转移到 GitHub上,从而使Service Fabric成为一个成功的开源项目。在GitHub上,我们可以与社区与社区开放式协作,使Service Fabric更好地为每个人服务。
 
 
 
Where we are now
 
至此,我们已经在 GitHub 上使用了 Linux 构建和测试工具,这意味着你可以克隆repo,为 Linux 构建 Service Fabric,运行基本测试,打开问题,并提交pull请求。我们正在努力使 Windows 构建环境也迁移到一个完整的 CI 环境中。
 
这里有一点历史。我们在 Windows 内部为 Service Fabric 开发了将近十年的时间,其中大部分时间都是微软内部平台,这意味着我们有近十年的内部微软工具来迁移和处理, 可以把一些东西用在 GitHub 上。 当我们几年前开始研究 Linux 支持时,我们是一个公共产品,并且已经计划开源,所以我们尽可能使用通用的公共可用工具。
 
现在,您可以为Linux编译和测试 Service Fabric,从底层的集群和联合层一直到流程和容器的激活。我们也在为贡献而开放,尽管我们的步伐有限,我们也为开放捐款开放,尽管我们将所有事情都公开化,但速度有限。
 
 
 
How we got here
 
去年的这个时候,我们开放了 Service Fabric 的源代码部分,包括 Reliable Services,Reliable Actors 和我们的 ASP.NET Core 集成库。 从那时起,我们已经慢慢地将 Service Fabric 的其他小部分移动到了 GitHub,包括 Service Fabric Explorer 和 SF CLI。 在那段时间里,我们花了很多时间来制定一个将所有 Service Fabric 转换为开源代码的计划。
 
我们在这个项目上投入了大量资金,我们希望它能增长。许多微软都在使用服务架构,包括Azure基础设施服务和大型解决方案,如 Azure SQL DB、Azure Cosmos DB 和 Cortana。这是我们大规模分布式应用程序的秘诀。只是这个秘诀不再是我们的了。自从我们在2015年公开发布了服务架构以来,微软以外的许多其他公司也开始依赖于 Service Fabric,以满足其关键的、大规模的应用程序。
 
 
 
What's next and how you can join in on the fun
 
对于 Service Fabric 和团队来说,这是我们向开放式开发过渡的一大步。 我们现在主要关注的是将 Service Fabric 的整个构建,测试和开发流程移至 GitHub。 虽然我们正在致力于此,但创新并不止于此,我们将继续定期发布新功能,我们将继续定期发布新特性、bug修复和支持。
 
 
我们的下一个主要步骤有两方面:
转向开放发展。 我们将把问题跟踪和我们自己的开发转移到 GitHub上。 我们的目标是使工作重点明确,并将工作与明确的项目路线图相结合,并制定明确的治理和贡献指导。 我们立即欢迎捐助,但我们还没有达到全速,所以请耐心等待我们改进过程和指导方针。
 
针对 Windows 和 Linux 的完整构建,测试和 CI 管道。 如果没有这个,我们就不能做很多事情,所以我们专注于把所有的事情都安排好。 如果你有兴趣帮助我们设置(或者你只是喜欢构建和测试自动化),请转到 Microsoft / service-fabric 回购站,我们正在跟踪该设备的工作。
 
当我们朝着这些更大的里程碑前进时,我们将不断地改进 repo。我们会定期在博客和 Service Fabric 回购库中更新进度,因此请务必马上查看,我们将在 GitHub 上看到你!
 
 
 
常见问题
 
1.Service Fabric 的哪些部分正在开源?
整个 Service Fabric 运行时都在 GitHub 上开源 ——构建和运行 Service Fabric 所需的一切。最初,我们将有一个适用于 Linux 的构建环境,并且很快就会有 Windows。
 
 
2.我可以构建并运行所有 Service Fabric 吗?
您现在可以为Linux构建和运行 Service Fabric。Windows 工具的完整构建和测试环境尚不可用,但我们正在努力将所有内容都发布到 GitHub 上。请注意 repo 的更新。
 
 
3.Azure Service Fabric和其它独立产品将会发生什么?他们还会得到微软的支持吗?
绝对的。我们将继续为微软提供的所有服务产品提供同样的支持,包括 Azure 的 Service Fabric 和其它所有独立的产品。
 
 
4.我有个一直想要构建的新功能。既然你们已经开源,那我现在可以开始与团队一起工作吗?
当然,我们很乐意与你合作。你可以先在 GitHub 上打开一个话题,然后我们就从那里开始。请注意,我们仍在过渡,目前的开源项目的重点是要建立项目环境,所以请耐心等待,因为我们还没有达到全速。
 
 
5.这仍然是微软拥有的,还是会捐赠给 CNCF 或 .NET 基金会?
微软拥有该项目,Service Fabric 团队将是决定项目方向的管理机构。作为理事机构,我们有责任遵循社区的指导。也就是说,我们不排除将来捐赠给基金会的可能性。

 
 结论 
 
Service Fabric 会带来如下好处:
支持创建无状态和有状态的微服务,通过云平台来伸缩他们,以应对高复杂度、低延迟、数据密集的情况;通过应用程序级别的感知和洞察,为微服务带来编排和自动化的优势;解决分布式系统诸如状态管理这样的难点,为开发人员提供应用程序生命周期管理的能力以便随着业务的增长无需重构系统架构;相关工具会集成到 Visual Studio 中,也会提供相应命令行工具,以便开发人员能够快速和轻易地上手;同时支持 .NET和 Java,这个特性特别适合目前国内原来很多投资于 .NET 平台,被人忽悠爬上了 Java  “贼船”,看到了 .NET Core,想回来的可以回来了。
 
开源微服务框架从 第一代 Dubbo 到 第二代 Spring Cloud 到 第三代 基于ServiceMesh 的 Service Fabric、Istio、Conduit三国争霸。
 
 
 
图片来自网友贡献
data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWNgYGBgAAAABQABh6FO1AAAAABJRU5ErkJggg==
 

 

 

 

 

 
 
 
 推荐阅读
 
使用Istio简化微服务系列二:如何通过HTTPS与外部服务进行通信?
使用Istio简化微服务系列一:如何用Isito解决Spring Cloud Netflix部署微服务
采用Istio实现灰度发布,给运维人员一支强心剂

 

 
ServiceMesh微信交流群:
添加微信xiaoshu062,备注:服务网格,即可加入Service Mesh微信交流群。
 
社区活动:
3月31日(周六),数人云联合ServiceComb社区,并由ServiceMesh社区支持,开启meetup系列活动 Building Microservice 第2期 北京站 :微服务,从架构到发布,已经开始报名啦,点击链接报名啦 查看全部
小数话:

今天一早 Service Mesh 微信交流群里传来了微软 Service Fabric 项目正式开源的消息,引起了大家广泛关注和讨论。小数为大家整理了目前有关 Service Fabric 开源的一些内容和原博客翻译,其中以下导读部分及结论部分感谢@张善友先生的贡献,该部分转自其知乎账号https://zhuanlan.zhihu.com/p/34574512 

 
导读 
 
微软的 Azure Service Fabric 的官方博客在2017.3.14日发布了一篇博客《Service Fabric .NET SDK goes open source 》详见下面原文翻译。介绍了社区呼声最高的 Service Fabric 的开源情况以及当前的情况,当时开源了 Service Fabric 的 .NET SDK 部分,社区一直在期盼着 Service Fabric 的正式开源,经过了一年漫长的等待,2018年3月14日微软终于开源了 Service Fabric,而且是以 MIT 许可下开放源代码。
 
目前微软在 Github 上的开源地址是 https://github.com/Microsoft/service-fabric ,目前的代码构建适用于 Linux 的 Service Fabric,运行基本测试,有问题可以在上面提交 Issue和 PR 了,Windows 构建环境以及完整的 CI 环境还没有迁移过来,看到代码还是3个小时前初始化的。Windows内部为 Service Fabric 开发了将近十年的内部服务,其中大部分时间都是微软内部平台,比如 Office365,Azure Stack 平台等,这意味着我们有近十年的内部微软工具可以在迁移之前完成迁移和流程细化,逐步全部开源,以后全部开发都在开源模式下进行开发工作。

 
 原文翻译 
 
我们很高兴地宣布 Service Fabric 将在 MIT 许可下开放源代码,在未来几个月内,我们将在GitHub上过渡到一个完全开放的开发过程。
 
我们听到了很多关于能够参与到你所依赖的平台的开发和方向上,以运行你的关键任务应用程序的重要性。由于这个原因,我们在 GitHub 和 Stack Overflow 上保持活跃,开放源码平台使这种协作更好的自然演进。这就是为什么我们致力于将我们的整个开发和规划过程转移到 GitHub上,从而使Service Fabric成为一个成功的开源项目。在GitHub上,我们可以与社区与社区开放式协作,使Service Fabric更好地为每个人服务。
 
 
 
Where we are now
 
至此,我们已经在 GitHub 上使用了 Linux 构建和测试工具,这意味着你可以克隆repo,为 Linux 构建 Service Fabric,运行基本测试,打开问题,并提交pull请求。我们正在努力使 Windows 构建环境也迁移到一个完整的 CI 环境中。
 
这里有一点历史。我们在 Windows 内部为 Service Fabric 开发了将近十年的时间,其中大部分时间都是微软内部平台,这意味着我们有近十年的内部微软工具来迁移和处理, 可以把一些东西用在 GitHub 上。 当我们几年前开始研究 Linux 支持时,我们是一个公共产品,并且已经计划开源,所以我们尽可能使用通用的公共可用工具。
 
现在,您可以为Linux编译和测试 Service Fabric,从底层的集群和联合层一直到流程和容器的激活。我们也在为贡献而开放,尽管我们的步伐有限,我们也为开放捐款开放,尽管我们将所有事情都公开化,但速度有限。
 
 
 
How we got here
 
去年的这个时候,我们开放了 Service Fabric 的源代码部分,包括 Reliable Services,Reliable Actors 和我们的 ASP.NET Core 集成库。 从那时起,我们已经慢慢地将 Service Fabric 的其他小部分移动到了 GitHub,包括 Service Fabric Explorer 和 SF CLI。 在那段时间里,我们花了很多时间来制定一个将所有 Service Fabric 转换为开源代码的计划。
 
我们在这个项目上投入了大量资金,我们希望它能增长。许多微软都在使用服务架构,包括Azure基础设施服务和大型解决方案,如 Azure SQL DB、Azure Cosmos DB 和 Cortana。这是我们大规模分布式应用程序的秘诀。只是这个秘诀不再是我们的了。自从我们在2015年公开发布了服务架构以来,微软以外的许多其他公司也开始依赖于 Service Fabric,以满足其关键的、大规模的应用程序。
 
 
 
What's next and how you can join in on the fun
 
对于 Service Fabric 和团队来说,这是我们向开放式开发过渡的一大步。 我们现在主要关注的是将 Service Fabric 的整个构建,测试和开发流程移至 GitHub。 虽然我们正在致力于此,但创新并不止于此,我们将继续定期发布新功能,我们将继续定期发布新特性、bug修复和支持。
 
 
我们的下一个主要步骤有两方面:
  • 转向开放发展。 我们将把问题跟踪和我们自己的开发转移到 GitHub上。 我们的目标是使工作重点明确,并将工作与明确的项目路线图相结合,并制定明确的治理和贡献指导。 我们立即欢迎捐助,但我们还没有达到全速,所以请耐心等待我们改进过程和指导方针。

 
  • 针对 Windows 和 Linux 的完整构建,测试和 CI 管道。 如果没有这个,我们就不能做很多事情,所以我们专注于把所有的事情都安排好。 如果你有兴趣帮助我们设置(或者你只是喜欢构建和测试自动化),请转到 Microsoft / service-fabric 回购站,我们正在跟踪该设备的工作。

 
当我们朝着这些更大的里程碑前进时,我们将不断地改进 repo。我们会定期在博客和 Service Fabric 回购库中更新进度,因此请务必马上查看,我们将在 GitHub 上看到你!
 
 
 
常见问题
 
1.Service Fabric 的哪些部分正在开源?
整个 Service Fabric 运行时都在 GitHub 上开源 ——构建和运行 Service Fabric 所需的一切。最初,我们将有一个适用于 Linux 的构建环境,并且很快就会有 Windows。
 
 
2.我可以构建并运行所有 Service Fabric 吗?
您现在可以为Linux构建和运行 Service Fabric。Windows 工具的完整构建和测试环境尚不可用,但我们正在努力将所有内容都发布到 GitHub 上。请注意 repo 的更新。
 
 
3.Azure Service Fabric和其它独立产品将会发生什么?他们还会得到微软的支持吗?
绝对的。我们将继续为微软提供的所有服务产品提供同样的支持,包括 Azure 的 Service Fabric 和其它所有独立的产品。
 
 
4.我有个一直想要构建的新功能。既然你们已经开源,那我现在可以开始与团队一起工作吗?
当然,我们很乐意与你合作。你可以先在 GitHub 上打开一个话题,然后我们就从那里开始。请注意,我们仍在过渡,目前的开源项目的重点是要建立项目环境,所以请耐心等待,因为我们还没有达到全速。
 
 
5.这仍然是微软拥有的,还是会捐赠给 CNCF 或 .NET 基金会?
微软拥有该项目,Service Fabric 团队将是决定项目方向的管理机构。作为理事机构,我们有责任遵循社区的指导。也就是说,我们不排除将来捐赠给基金会的可能性。

 
 结论 
 
Service Fabric 会带来如下好处:
  • 支持创建无状态和有状态的微服务,通过云平台来伸缩他们,以应对高复杂度、低延迟、数据密集的情况;
  • 通过应用程序级别的感知和洞察,为微服务带来编排和自动化的优势;
  • 解决分布式系统诸如状态管理这样的难点,为开发人员提供应用程序生命周期管理的能力以便随着业务的增长无需重构系统架构;
  • 相关工具会集成到 Visual Studio 中,也会提供相应命令行工具,以便开发人员能够快速和轻易地上手;
  • 同时支持 .NET和 Java,这个特性特别适合目前国内原来很多投资于 .NET 平台,被人忽悠爬上了 Java  “贼船”,看到了 .NET Core,想回来的可以回来了。

 
开源微服务框架从 第一代 Dubbo 到 第二代 Spring Cloud 到 第三代 基于ServiceMesh 的 Service Fabric、Istio、Conduit三国争霸。
 
 
 
图片来自网友贡献
data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWNgYGBgAAAABQABh6FO1AAAAABJRU5ErkJggg==
 

 

 

 

 

 
 
 
 推荐阅读
 
使用Istio简化微服务系列二:如何通过HTTPS与外部服务进行通信?
使用Istio简化微服务系列一:如何用Isito解决Spring Cloud Netflix部署微服务
采用Istio实现灰度发布,给运维人员一支强心剂

 

 
ServiceMesh微信交流群:
添加微信xiaoshu062,备注:服务网格,即可加入Service Mesh微信交流群。
 
社区活动:
3月31日(周六),数人云联合ServiceComb社区,并由ServiceMesh社区支持,开启meetup系列活动 Building Microservice 第2期 北京站 :微服务,从架构到发布,已经开始报名啦,点击链接报名啦

使用Istio简化微服务系列二:如何通过HTTPS与外部服务进行通信?

Istio小数 发表了文章 • 0 个评论 • 372 次浏览 • 2018-03-15 14:08 • 来自相关话题

作者:Nithin Mallya

翻译:狄卫华

原文:Simplifying Microservices with Istio in Google Kubernetes Engine — Part II

原文链接:https://medium.com/google-clou ... 33089


在本系列第一部分(使用Istio简化微服务系列一:如何用Isito解决Spring Cloud Netflix部署微服务),我们展示了如何使用 Istio 简化我们微服务间的通信。

在这一部分中,我们将看到 Istio 服务网格中的服务是如何通过HTTPS与外部服务进行通信的。





 
图1:微服务通信模型的逻辑视图

在上面的图1,PetService(直接与 PetDetailsService 和 PetMedicalHistoryService 服务进行通信)现在将也会调用外部的服务,外部服务位于 https://thedogapi.co.uk,返回 dog 图片的 url 地址。


Istio 服务网格与外部的服务通信展示在下面的图 2 所示。

与往常一样,在服务网格内的服务通信通过HTTP协议代理

与使用 HTTPS 协议的外部服务通信,内部服务仍然是发送 HTTP 请求,HTTP 请求会被以边车(sidecar)方式部署的代理所拦截,并作为 TLS 协议的发起方与外部的服务在加密通道上进行通信






图2: Istio 服务网格展示与外部服务通信


Github repo(https://github.com/nmallya/istiodemo)

petservice 代码如下所示:







备注:展示我们如何调用 DogAPI https,地址http://api.thedogapi.co.uk:443/v2/dog.php


让我们看一下当运行以下命令时会发生什么?其中 108.59.82.93 为 入口(Ingress)IP 地址 (参见 第一部分)


curl http://108.59.82.93/pet/123

响应内容如下:

{

  "petDetails": {

    "petName": "Maximus",

    "petAge": 5,

    "petOwner": "Nithin Mallya",

    "petBreed": "Dog"

  },

  "petMedicalHistory": {

    "vaccinationList": [

      "Bordetella, Leptospirosis, Rabies, Lyme Disease"

    ]

  },

  "dogAPIResponse": {

    "message": "request to https://api.thedogapi.co.uk/v2/dog.php failed, reason: read ECONNRESET",

    "type": "system",

    "errno": "ECONNRESET",

    "code": "ECONNRESET"

  }

}


你会注意到当 petservice 访问位于 https://api.thedogapi.co.uk 的外部服务时,上述的响应内容中 dogAPIResponse(不是最原始的名字)部分有一个错误信息。

这是因为所有外部的流量(egress)在默认情况下被阻止。在前面的文章中解释过边车(sidecar)代理只允许集群内的通信。


备注:正如我在第一部分提及的那样,当我们想要管控服务与外部服务通信的方式和阻止任何未经授权的访问的时候,这个限制非常有用。

> 医疗保健/金融系统可以特别利用此功能来保护 PHI / PII 数据不会被无意地甚至恶意地从内部服务中共享。

为了启用出口(egress)流量,你需要创建如下所示的出口规则(egress rule):

cat <<EOF | istioctl create -f -

apiVersion: config.istio.io/v1alpha2

kind: EgressRule

metadata:

  name: dogapi-egress-rule

spec:

  destination:

    service: api.thedogapi.co.uk

  ports:

    - port: 443

      protocol: https

EOF

为了检查该出口规则(egress rule)是否已被创建,你可以运行下面的命令,你应该看到出口规则(egress rule)dogapi-egress-rule 已经被创建。

kubectl get egressrule

NAME                 AGE

dogapi-egress-rule   5m

我们再次运行上面的 curl 命令:

$ curl http://108.59.82.93/pet/123

{

  "petDetails": {

    "petName": "Maximus",

    "petAge": 5,

    "petOwner": "Nithin Mallya",

    "petBreed": "Dog"

  },

  "petMedicalHistory": {

    "vaccinationList": [

      "Bordetella, Leptospirosis, Rabies, Lyme Disease"

    ]

  },

  "dogAPIResponse": {

    "count": 1,

    "api_version": "v2",

    "error": null,

    "data": [

      {

        "id": "rCaz-LNuzCC",

"url": "https://i.thedogapi.co.uk/rCaz-LNuzCC.jpg",

        "time": "2017-08-30T21:43:03.0",

        "format": "jpg",

        "verified": "1",

        "checked": "1"

      }

    ],

    "response_code": 200

  }

}

结论:我们看到如何通过创建明确规则,来启用从服务网格(service mesh )到外部服务的通信。

在后续的文章中,我们将会看到如何实施其他重要的任务比如流量路由(traffic routing)和流量变化(ramping),使用断路器(circuit breaker)等。


资源:
1. 本系列文章的第 I 部分:使用Istio简化微服务系列一:如何用Isito解决Spring Cloud Netflix部署微服务

2. Istio 官方地址 <https://istio.io/>

3. DevOxx 的RayTsang的Istio演讲材料: <https://www.youtube.com/watch% ... gt%3B

4. 案例的Github: <https://github.com/nmallya/istiodemo>

5. Kubernetes: <https://kubernetes.io/>

6. DogAPI 网址: <https://thedogapi.co.uk/>



ServiceMesh微信交流群:

添加微信xiaoshu062,备注:服务网格,即可加入Service Mesh微信交流群。

 
 
 
  查看全部
作者:Nithin Mallya

翻译:狄卫华

原文:Simplifying Microservices with Istio in Google Kubernetes Engine — Part II

原文链接:https://medium.com/google-clou ... 33089


在本系列第一部分(使用Istio简化微服务系列一:如何用Isito解决Spring Cloud Netflix部署微服务),我们展示了如何使用 Istio 简化我们微服务间的通信。

在这一部分中,我们将看到 Istio 服务网格中的服务是如何通过HTTPS与外部服务进行通信的。

1.jpeg

 
图1:微服务通信模型的逻辑视图

在上面的图1,PetService(直接与 PetDetailsService 和 PetMedicalHistoryService 服务进行通信)现在将也会调用外部的服务,外部服务位于 https://thedogapi.co.uk,返回 dog 图片的 url 地址。


Istio 服务网格与外部的服务通信展示在下面的图 2 所示。

与往常一样,在服务网格内的服务通信通过HTTP协议代理

与使用 HTTPS 协议的外部服务通信,内部服务仍然是发送 HTTP 请求,HTTP 请求会被以边车(sidecar)方式部署的代理所拦截,并作为 TLS 协议的发起方与外部的服务在加密通道上进行通信

2.jpeg


图2: Istio 服务网格展示与外部服务通信


Github repo(https://github.com/nmallya/istiodemo)

petservice 代码如下所示:


3.png


备注:展示我们如何调用 DogAPI https,地址http://api.thedogapi.co.uk:443/v2/dog.php


让我们看一下当运行以下命令时会发生什么?其中 108.59.82.93 为 入口(Ingress)IP 地址 (参见 第一部分)


curl http://108.59.82.93/pet/123

响应内容如下:

{

  "petDetails": {

    "petName": "Maximus",

    "petAge": 5,

    "petOwner": "Nithin Mallya",

    "petBreed": "Dog"

  },

  "petMedicalHistory": {

    "vaccinationList": [

      "Bordetella, Leptospirosis, Rabies, Lyme Disease"

    ]

  },

  "dogAPIResponse": {

    "message": "request to https://api.thedogapi.co.uk/v2/dog.php failed, reason: read ECONNRESET",

    "type": "system",

    "errno": "ECONNRESET",

    "code": "ECONNRESET"

  }

}


你会注意到当 petservice 访问位于 https://api.thedogapi.co.uk 的外部服务时,上述的响应内容中 dogAPIResponse(不是最原始的名字)部分有一个错误信息。

这是因为所有外部的流量(egress)在默认情况下被阻止。在前面的文章中解释过边车(sidecar)代理只允许集群内的通信。


备注:正如我在第一部分提及的那样,当我们想要管控服务与外部服务通信的方式和阻止任何未经授权的访问的时候,这个限制非常有用。

> 医疗保健/金融系统可以特别利用此功能来保护 PHI / PII 数据不会被无意地甚至恶意地从内部服务中共享。

为了启用出口(egress)流量,你需要创建如下所示的出口规则(egress rule):

cat <<EOF | istioctl create -f -

apiVersion: config.istio.io/v1alpha2

kind: EgressRule

metadata:

  name: dogapi-egress-rule

spec:

  destination:

    service: api.thedogapi.co.uk

  ports:

    - port: 443

      protocol: https

EOF

为了检查该出口规则(egress rule)是否已被创建,你可以运行下面的命令,你应该看到出口规则(egress rule)dogapi-egress-rule 已经被创建。

kubectl get egressrule

NAME                 AGE

dogapi-egress-rule   5m

我们再次运行上面的 curl 命令:

$ curl http://108.59.82.93/pet/123

{

  "petDetails": {

    "petName": "Maximus",

    "petAge": 5,

    "petOwner": "Nithin Mallya",

    "petBreed": "Dog"

  },

  "petMedicalHistory": {

    "vaccinationList": [

      "Bordetella, Leptospirosis, Rabies, Lyme Disease"

    ]

  },

  "dogAPIResponse": {

    "count": 1,

    "api_version": "v2",

    "error": null,

    "data": [

      {

        "id": "rCaz-LNuzCC",

"url": "https://i.thedogapi.co.uk/rCaz-LNuzCC.jpg",

        "time": "2017-08-30T21:43:03.0",

        "format": "jpg",

        "verified": "1",

        "checked": "1"

      }

    ],

    "response_code": 200

  }

}

结论:我们看到如何通过创建明确规则,来启用从服务网格(service mesh )到外部服务的通信。

在后续的文章中,我们将会看到如何实施其他重要的任务比如流量路由(traffic routing)和流量变化(ramping),使用断路器(circuit breaker)等。


资源:
1. 本系列文章的第 I 部分:使用Istio简化微服务系列一:如何用Isito解决Spring Cloud Netflix部署微服务

2. Istio 官方地址 <https://istio.io/>

3. DevOxx 的RayTsang的Istio演讲材料: <https://www.youtube.com/watch% ... gt%3B

4. 案例的Github: <https://github.com/nmallya/istiodemo>

5. Kubernetes: <https://kubernetes.io/>

6. DogAPI 网址: <https://thedogapi.co.uk/>



ServiceMesh微信交流群:

添加微信xiaoshu062,备注:服务网格,即可加入Service Mesh微信交流群。

 
 
 
 

使用Istio简化微服务系列一:如何用Isito解决Spring Cloud Netflix部署微服务的挑战?

Istio小数 发表了文章 • 0 个评论 • 890 次浏览 • 2018-03-13 10:13 • 来自相关话题

作者:Nithin Mallya
翻译:姚炳雄
原文:Simplifying Microservices with Istio in Google Kubernetes Engine — Part I
概述
Istio 简化了服务间的通信,流量涨落,容错,性能监控,跟踪等太多太多。如何利用它来帮我们从各微服务中抽象萃取出基础架构和功能切面? 

我写的这些关于 Istio 的文章是 Istio官网文档的子集。读官网文档可了解更多。 

注意::如果你很熟悉微服务,请跳过背景介绍这段。


在本系列的第一部分,将涵盖如下内容:
背景: 单体应用及微服务介绍 
 
Spring Cloud Netflix Stack及其优势 
 
Istio 介绍
 
Istio的服务-服务通信举例 




背景

过去,我们运维着“能做一切”的大型单体应用程序。 这是一种将产品推向市场的很好的方式,因为刚开始我们也只需要让我们的第一个应用上线。而且我们总是可以回头再来改进它的。部署一个大应用总是比构建和部署多个小块要容易。


然而,这样的应用开发将导致“爆炸式的”工作量(我们经过数月的工作后将再次部署整个应用),并且增量变更将因为构建/测试/部署/发布周期等的复杂特性而来来回回折腾很长时间。但是,如果你是产品负责人,尤其是在部署一个新版本后发现一个严重的 Bug,那么这就不仅仅是多少钱的问题。 这甚至可能导致整个应用回滚。相对于比较小的组件来说,将这样的一个大型应用部署到云上并弹性扩展它们也并不容易。


进入微服务微服务是运行在自己的进程中的可独立部署的服务套件。 他们通常使用 HTTP 资源进行通信,每个服务通常负责整个应用中的某一个单一的领域。 在流行的电子商务目录例子中,你可以有一个商品条目服务,一个审核服务和一个评价服务,每个都只专注一个领域。


用这种方法来帮助分布式团队各自贡献各种服务,而不需要在每个服务变更时去构建/测试/部署整个应用,而且调试也无需进入彼此的代码。 将服务部署到云上也更容易,因为独立的服务就能按需进行自动弹性扩展。


用这种方法让多语言服务(使用不同语言编写的服务)也成为可能,这样我们就可以让 Java/C++  服务执行更多的计算密集型工作,让 Rails / Node.js 服务更多来支持前端应用等等。



Spring Cloud Netflix:

随着微服务的流行,简化服务的创建和管理的框架如雨后春笋。 我个人在2015年最喜欢的是 Netflix OSS 栈(Spring Cloud Netflix),它让我用一个非常简单的方式,通过 Spring Tool Suite IDE 来创建 Java 微服务。


我可以通过 Netflix 套件获得以下功能(图1):
通过 Eureka 进行服务注册- 用于注册和发现服务
 
用 Ribbon 做客户端的负载均衡- 客户端可以选择将其请求发送到哪个服务器。
 
声明 REST 客户端 Feign 与其他服务交谈。在内部,使用 Ribbon。
 
API 网关用 Zuul —单一入口点来管理所有 API 调用,并按路由规则路由到微服务。
 
Hystrix 做熔断器 — 处理容错能力以及在短时间内关闭通信信道(断开回路)并在目标服务宕机时返回用户友好的响应。
 
用 Hystrix 和 Turbine 做仪表板 —— 可视化流量和熔断







图1: Spring Cloud Netflix 实现微服务


当然,这种构建和部署应用的方法也带来了它的挑战。


挑战

部署:怎样才能通过一种统一一致的方式将我们的服务部署到云中,并确保它们始终可用,并让它们按需进行自动弹性扩展?

横切关注点:如何对每个微服务代码改动很少甚至不改代码的情况下能获得更多我们所看到的 Spring Cloud Netflix 中所实现的功能? 另外,如何处理用不同语言编写的服务?



解决方案

部署:Kubernetes 已经为在 Google Kubernetes Engine(GKE)中高效部署和编排 Docker 容器铺平了道路。 Kubernetes 抽象出基础架构,并让我们通过 API 与之进行交互。 请参阅本文末尾的链接以获取更多详细信息。


横切关注点:我们可以用 Istio。 Istio 官网上的解释称:“ Istio 提供了一种简单的方法,来创建一个提供负载均衡、服务间认证、监控等的服务网络,且不需要对服务代码进行任何更改。 通过在整个环境中部署专门的 sidecar 代理服务,来拦截微服务间的所有网络通信,整个配置和管理通过 Istio的控制面板来做。”


Istio介绍:换句话说,通过Istio,我们可以创建我们的微服务,并将它们与“轻量级 Sidecar 代理”一起部署(下图2),以处理我们的许多横切需求,例如:
 
服务到服务的通信
 
追踪
 
熔断(类 Hystrix 功能)和重试
 
性能监控和仪表板(类似于 Hystrix 和 Turbine 仪表板)
 
流量路由(例如:发送 x% 流量到 V2 版本的应用实例),金丝雀部署
 
一个额外的红利(特别是如果您正在处理医疗保健中的 PHI 等敏感数据时)出站(Istio 服务网格之外的外部可调用服务)需要明确配置,并且可以阻止在服务网格之外的做特殊调用的服务。






 
图2: 用 Envoy 代理来做多语言服务间的通信

在上图2中,我们已经去掉了图1中的许多组件,并添加了一个新组件(Envoy Proxy)。 任何服务(A)如需与另一个服务(B)交谈,则提前对它的代理做路由规则预配置,以路由到对方的代理进行通信。 代理与代理交谈。 由于所有通信都是通过代理进行的,所以很容易监控流量,收集指标,根据需要使用熔断规则等。对横切面的声明式的配置规则和策略,无需更改任何服务代码,让我们可以更专注于最重要的事情:构建高业务价值的高质量的服务。


从高的层面看,Istio 有如下组件:
Envoy:一个高性能,低空间占用的代理,支持服务之间的通信,并有助于负载平衡,服务发现等; 混合器:负责整个生态(服务网格)中所有服务的访问控制策略,并收集通过 Envoy 或其他服务发送的遥测信息;
 
Pilot:帮助发现服务,流量缓慢调整和容错(熔断,重试等);Istio-Auth :用于服务间认证以及都使用 TLS 的终端用户认证。本文中的示例不使用 Istio-Auth。

 
 
用Istio进行服务—服务通信:

让我们在练习中了解它!

我们将举一个简单的例子,展示3个通过 Envoy 代理进行通信的微服务。它们已经用 Node.js 写好,但如前述,你可以用任何语言。






图3: 用于提取宠物细节的3个微服务的逻辑视图
 
宠物服务:通过调用 PetDetailsService 和 PetMedicalHistoryService 来返回宠物的信息和病史。 它将在9080端口上运行。

宠物详细信息服务:返回宠物信息,如姓名,年龄,品种,拥有者等,它将在端口9081上运行。

宠物医疗历史信息服务:返回宠物的病史(疫苗接种)。 它将在9082端口运行。


步骤:
在 GKE中创建一个 Kubernetes 集群(我叫 nithinistiocluster)。 
确保缺省服务帐户具有以下权限:roles / container.admin(Kubernetes Engine Admin)。

按照 https://istio.io/docs/setup/ku ... .html  中的说明安装 istio。


1. 现在,我们准备将我们的应用程序(上述3个服务)部署到 GKE,并将边车代理注入到部署中。

2. 在 github 仓库中,您将看到4个目录(安装各种组件时创建的istio目录和我的微服务的3个目录)。

3.对于每个微服务,我在 petinfo.yaml 文件的 kube 目录中创建了相应的 Kubernete s部署和服务。 服务名为宠物服务,宠物详细信息服务和宠物医疗历史信息服务。 由于PetServic e可以公开访问,因此它有一个指向 petservice 的 Kubernetes Ingress。

4. 你可以转到每个服务目录,在 deploy.sh 文件中更新项目和群集名称并运行它。 它构建服务,创建 Docker 镜像,将其上传到Google Container Registry,然后运行 istioct l 以注入 Envoy 代理。 例如,对于 PetService,它看起来像:

#!/usr/bin/env bash
export PROJECT=nithinistioproject export CONTAINER_VERSION=feb4v2 export IMAGE=gcr.io/$PROJECT/petservice:$CONTAINER_VERSION export BUILD_HOME=.
gcloud config set project $PROJECT gcloud container clusters get-credentials nithinistiocluster --zone us-central1-a --project $PROJECT
echo $IMAGE docker build -t petservice -f "${PWD}/Dockerfile" $BUILD_HOME echo 'Successfully built ' $IMAGE
docker tag petservice $IMAGE echo 'Successfully tagged ' $IMAGE
#push to google container registry gcloud docker -- push $IMAGE echo 'Successfully pushed to Google Container Registry ' $IMAGE
# inject envoy proxy kubectl apply -f <(istioctl kube-inject -f "${PWD}/kube/petinfo.yaml")


在上面的代码中,高亮显示的行显示了我们如何使用 Istio 命令行工具(istioctl)来将代理注入到我们的各种 Kubernetes 部署中。


Petservice 目录下的 petinfo.yaml 文件包含服务、部署和 Ingress的配置。 看起来像:

apiVersion: v1 kind: Service metadata:  name: petservice  labels:    app: petservice spec:  ports:  - port: 9080    name: http  selector:    app: petservice --- apiVersion: extensions/v1beta1 kind: Deployment metadata:  name: petservice-v1 spec:  replicas: 1  template:    metadata:      labels:        app: petservice        version: v1    spec:      containers:      - name: petservice        image: gcr.io/nithinistioproject/petservice:feb4v2        imagePullPolicy: IfNotPresent        ports:        - containerPort: 9080 ---
########################################################################### # Ingress resource (gateway) ########################################################################## apiVersion: extensions/v1beta1 kind: Ingress metadata:  name: gateway  annotations:    kubernetes.io/ingress.class: "istio" spec:  rules:  - http:      paths:      - path: /pet/.*        backend:          serviceName: petservice          servicePort: 9080 ---


一旦运行了 deploy.sh,就可以通过执行以下命令来检查确认部署、服务和 Ingress 是否已经创建:

mallyn01$ kubectl get deployment
NAME                          DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
petdetailsservice-v1          1         1         1            1           1h
petmedicalhistoryservice-v1   1         1         1            1           58m
petservice-v1                 1         1         1            1           54m
mallyn01$ kubectl get service
NAME                       TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
kubernetes                 ClusterIP   10.51.240.1    <none>        443/TCP    2d
petdetailsservice          ClusterIP   10.51.255.10   <none>        9081/TCP   1h
petmedicalhistoryservice   ClusterIP   10.51.244.19   <none>        9082/TCP   59m
petservice                 ClusterIP   10.51.242.18   <none>        9080/TCP   1h
petservice mallyn01$ kubectl get ing
NAME      HOSTS     ADDRESS        PORTS     AGE
gateway   *         108.59.82.93   80        1h
mallyn01$ kubectl get pods
NAME                                           READY     STATUS    RESTARTS   AGE
petdetailsservice-v1-5bb8c65577-jmn6r          2/2       Running   0          12h
petmedicalhistoryservice-v1-5757f98898-tq5j8   2/2       Running   0          12h
petservice-v1-587696b469-qttqk                 2/2       Running   0          12h


当查看控制台中 pod 的信息,即使你只为每个容器部署了一项服务,但仍会注意到有2/2个容器正在运行。 另一个容器是 istioctl 命令注入的边车代理。

5. 一旦上述所有内容都运行完毕,您可以使用 Ingress 的 IP 地址去调用示例端点来获取 Pet 的详细信息。


mallyn01$ curl http://108.59.82.93/pet/123
{  "petDetails": {    "petName": "Maximus",    "petAge": 5,    "petOwner": "Nithin Mallya",    "petBreed": "Dog"  },  "petMedicalHistory": {    "vaccinationList": [      "Bordetella, Leptospirosis, Rabies, Lyme Disease"    ]  } }


注意: 由于 PetService 调用 PetDetailsService 和 PetMedicalHistoryService,实际的调用将如下所示:fetch('http://petdetailsservice:9081/pet/123/details')          .then(res => res.text())          .then(body => console.log(body));        ;
fetch('http://petmedicalhistoryservice:9082/pet/123/medicalhistory')          .then(res => res.text())          .then(body => console.log(body)); ;



结论:
我们覆盖了大量内容 (但这只是第一部分!!)

在随后的部分中,将详细介绍如何使用其他 Istio 特性,例如将流量逐步迁移到一个新升级的版本上,使用性能监控仪表板等等。

特别感谢 Ray Tsang 的关于 Istio 的演讲材料 。



资源:
1. The Istio home page https://istio.io/

2. DevOxx 的Ray Tsang的 Istio 演讲材料: https://www.youtube.com/watch% ... D231s

3. 案例的Github link: https://github.com/nmallya/istiodemo

4. Kubernetes: https://kubernetes.io/

5. 微服务:  https://martinfowler.com/artic ... .html

6. Spring Cloud Netflix: https://github.com/spring-clou ... tflix


原文链接:https://medium.com/google-clou ... 922b8









推荐阅读
采用Istio实现灰度发布,给运维人员一支强心剂
构建分布式微服务系统,如何基于代理的服务网格做“减法”?
实用指南 | 基于Kubernetes, GRPC 和 Linkerd 构建可扩展微服务
万字长文 | 如何构建安全的微服务应用,先要解决这两个问题
实例 | 当Istio遇见Jaeger,如何解决端到端分布式追踪问题?


ServiceMesh微信交流群:

添加微信xiaoshu062,备注:服务网格,即可加入Service Mesh微信交流群。


社区活动:

3月31日(周六),数人云联合ServiceComb社区,并由ServiceMesh社区支持,开启meetup系列活动 Building Microservice 第2期 北京站 :微服务,从架构到发布,已经开始报名啦,点击链接快来报名~ 查看全部
作者:Nithin Mallya
翻译:姚炳雄
原文:Simplifying Microservices with Istio in Google Kubernetes Engine — Part I
概述
Istio 简化了服务间的通信,流量涨落,容错,性能监控,跟踪等太多太多。如何利用它来帮我们从各微服务中抽象萃取出基础架构和功能切面? 

我写的这些关于 Istio 的文章是 Istio官网文档的子集。读官网文档可了解更多。 

注意::如果你很熟悉微服务,请跳过背景介绍这段。


在本系列的第一部分,将涵盖如下内容:
  • 背景: 单体应用及微服务介绍 

 
  • Spring Cloud Netflix Stack及其优势 

 
  • Istio 介绍

 
  • Istio的服务-服务通信举例 





背景

过去,我们运维着“能做一切”的大型单体应用程序。 这是一种将产品推向市场的很好的方式,因为刚开始我们也只需要让我们的第一个应用上线。而且我们总是可以回头再来改进它的。部署一个大应用总是比构建和部署多个小块要容易。


然而,这样的应用开发将导致“爆炸式的”工作量(我们经过数月的工作后将再次部署整个应用),并且增量变更将因为构建/测试/部署/发布周期等的复杂特性而来来回回折腾很长时间。但是,如果你是产品负责人,尤其是在部署一个新版本后发现一个严重的 Bug,那么这就不仅仅是多少钱的问题。 这甚至可能导致整个应用回滚。相对于比较小的组件来说,将这样的一个大型应用部署到云上并弹性扩展它们也并不容易。


进入微服务微服务是运行在自己的进程中的可独立部署的服务套件。 他们通常使用 HTTP 资源进行通信,每个服务通常负责整个应用中的某一个单一的领域。 在流行的电子商务目录例子中,你可以有一个商品条目服务,一个审核服务和一个评价服务,每个都只专注一个领域。


用这种方法来帮助分布式团队各自贡献各种服务,而不需要在每个服务变更时去构建/测试/部署整个应用,而且调试也无需进入彼此的代码。 将服务部署到云上也更容易,因为独立的服务就能按需进行自动弹性扩展。


用这种方法让多语言服务(使用不同语言编写的服务)也成为可能,这样我们就可以让 Java/C++  服务执行更多的计算密集型工作,让 Rails / Node.js 服务更多来支持前端应用等等。



Spring Cloud Netflix:

随着微服务的流行,简化服务的创建和管理的框架如雨后春笋。 我个人在2015年最喜欢的是 Netflix OSS 栈(Spring Cloud Netflix),它让我用一个非常简单的方式,通过 Spring Tool Suite IDE 来创建 Java 微服务。


我可以通过 Netflix 套件获得以下功能(图1):
  • 通过 Eureka 进行服务注册- 用于注册和发现服务

 
  • 用 Ribbon 做客户端的负载均衡- 客户端可以选择将其请求发送到哪个服务器。

 
  • 声明 REST 客户端 Feign 与其他服务交谈。在内部,使用 Ribbon。

 
  • API 网关用 Zuul —单一入口点来管理所有 API 调用,并按路由规则路由到微服务。

 
  • Hystrix 做熔断器 — 处理容错能力以及在短时间内关闭通信信道(断开回路)并在目标服务宕机时返回用户友好的响应。

 
  • 用 Hystrix 和 Turbine 做仪表板 —— 可视化流量和熔断



1.jpeg


图1: Spring Cloud Netflix 实现微服务


当然,这种构建和部署应用的方法也带来了它的挑战。


挑战

部署:怎样才能通过一种统一一致的方式将我们的服务部署到云中,并确保它们始终可用,并让它们按需进行自动弹性扩展?

横切关注点:如何对每个微服务代码改动很少甚至不改代码的情况下能获得更多我们所看到的 Spring Cloud Netflix 中所实现的功能? 另外,如何处理用不同语言编写的服务?



解决方案

部署:Kubernetes 已经为在 Google Kubernetes Engine(GKE)中高效部署和编排 Docker 容器铺平了道路。 Kubernetes 抽象出基础架构,并让我们通过 API 与之进行交互。 请参阅本文末尾的链接以获取更多详细信息。


横切关注点:我们可以用 Istio。 Istio 官网上的解释称:“ Istio 提供了一种简单的方法,来创建一个提供负载均衡、服务间认证、监控等的服务网络,且不需要对服务代码进行任何更改。 通过在整个环境中部署专门的 sidecar 代理服务,来拦截微服务间的所有网络通信,整个配置和管理通过 Istio的控制面板来做。”


Istio介绍:换句话说,通过Istio,我们可以创建我们的微服务,并将它们与“轻量级 Sidecar 代理”一起部署(下图2),以处理我们的许多横切需求,例如:
 
  • 服务到服务的通信

 
  • 追踪

 
  • 熔断(类 Hystrix 功能)和重试

 
  • 性能监控和仪表板(类似于 Hystrix 和 Turbine 仪表板)

 
  • 流量路由(例如:发送 x% 流量到 V2 版本的应用实例),金丝雀部署

 
  • 一个额外的红利(特别是如果您正在处理医疗保健中的 PHI 等敏感数据时)出站(Istio 服务网格之外的外部可调用服务)需要明确配置,并且可以阻止在服务网格之外的做特殊调用的服务。



2.jpeg

 
图2: 用 Envoy 代理来做多语言服务间的通信

在上图2中,我们已经去掉了图1中的许多组件,并添加了一个新组件(Envoy Proxy)。 任何服务(A)如需与另一个服务(B)交谈,则提前对它的代理做路由规则预配置,以路由到对方的代理进行通信。 代理与代理交谈。 由于所有通信都是通过代理进行的,所以很容易监控流量,收集指标,根据需要使用熔断规则等。对横切面的声明式的配置规则和策略,无需更改任何服务代码,让我们可以更专注于最重要的事情:构建高业务价值的高质量的服务。


从高的层面看,Istio 有如下组件:
  • Envoy:一个高性能,低空间占用的代理,支持服务之间的通信,并有助于负载平衡,服务发现等;
  •  混合器:负责整个生态(服务网格)中所有服务的访问控制策略,并收集通过 Envoy 或其他服务发送的遥测信息;

 
  • Pilot:帮助发现服务,流量缓慢调整和容错(熔断,重试等);
  • Istio-Auth :用于服务间认证以及都使用 TLS 的终端用户认证。本文中的示例不使用 Istio-Auth。


 
 
用Istio进行服务—服务通信:

让我们在练习中了解它!

我们将举一个简单的例子,展示3个通过 Envoy 代理进行通信的微服务。它们已经用 Node.js 写好,但如前述,你可以用任何语言。

3.jpeg


图3: 用于提取宠物细节的3个微服务的逻辑视图
 
宠物服务:通过调用 PetDetailsService 和 PetMedicalHistoryService 来返回宠物的信息和病史。 它将在9080端口上运行。

宠物详细信息服务:返回宠物信息,如姓名,年龄,品种,拥有者等,它将在端口9081上运行。

宠物医疗历史信息服务:返回宠物的病史(疫苗接种)。 它将在9082端口运行。


步骤:
在 GKE中创建一个 Kubernetes 集群(我叫 nithinistiocluster)。 
确保缺省服务帐户具有以下权限:roles / container.admin(Kubernetes Engine Admin)。

按照 https://istio.io/docs/setup/ku ... .html  中的说明安装 istio。


1. 现在,我们准备将我们的应用程序(上述3个服务)部署到 GKE,并将边车代理注入到部署中。

2. 在 github 仓库中,您将看到4个目录(安装各种组件时创建的istio目录和我的微服务的3个目录)。

3.对于每个微服务,我在 petinfo.yaml 文件的 kube 目录中创建了相应的 Kubernete s部署和服务。 服务名为宠物服务,宠物详细信息服务和宠物医疗历史信息服务。 由于PetServic e可以公开访问,因此它有一个指向 petservice 的 Kubernetes Ingress。

4. 你可以转到每个服务目录,在 deploy.sh 文件中更新项目和群集名称并运行它。 它构建服务,创建 Docker 镜像,将其上传到Google Container Registry,然后运行 istioct l 以注入 Envoy 代理。 例如,对于 PetService,它看起来像:

#!/usr/bin/env bash
export PROJECT=nithinistioproject export CONTAINER_VERSION=feb4v2 export IMAGE=gcr.io/$PROJECT/petservice:$CONTAINER_VERSION export BUILD_HOME=.
gcloud config set project $PROJECT gcloud container clusters get-credentials nithinistiocluster --zone us-central1-a --project $PROJECT
echo $IMAGE docker build -t petservice -f "${PWD}/Dockerfile" $BUILD_HOME echo 'Successfully built ' $IMAGE
docker tag petservice $IMAGE echo 'Successfully tagged ' $IMAGE
#push to google container registry gcloud docker -- push $IMAGE echo 'Successfully pushed to Google Container Registry ' $IMAGE
# inject envoy proxy kubectl apply -f <(istioctl kube-inject -f "${PWD}/kube/petinfo.yaml")


在上面的代码中,高亮显示的行显示了我们如何使用 Istio 命令行工具(istioctl)来将代理注入到我们的各种 Kubernetes 部署中。


Petservice 目录下的 petinfo.yaml 文件包含服务、部署和 Ingress的配置。 看起来像:

apiVersion: v1 kind: Service metadata:  name: petservice  labels:    app: petservice spec:  ports:  - port: 9080    name: http  selector:    app: petservice --- apiVersion: extensions/v1beta1 kind: Deployment metadata:  name: petservice-v1 spec:  replicas: 1  template:    metadata:      labels:        app: petservice        version: v1    spec:      containers:      - name: petservice        image: gcr.io/nithinistioproject/petservice:feb4v2        imagePullPolicy: IfNotPresent        ports:        - containerPort: 9080 ---
########################################################################### # Ingress resource (gateway) ########################################################################## apiVersion: extensions/v1beta1 kind: Ingress metadata:  name: gateway  annotations:    kubernetes.io/ingress.class: "istio" spec:  rules:  - http:      paths:      - path: /pet/.*        backend:          serviceName: petservice          servicePort: 9080 ---


一旦运行了 deploy.sh,就可以通过执行以下命令来检查确认部署、服务和 Ingress 是否已经创建:

mallyn01$ kubectl get deployment
NAME                          DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
petdetailsservice-v1          1         1         1            1           1h
petmedicalhistoryservice-v1   1         1         1            1           58m
petservice-v1                 1         1         1            1           54m
mallyn01$ kubectl get service
NAME                       TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
kubernetes                 ClusterIP   10.51.240.1    <none>        443/TCP    2d
petdetailsservice          ClusterIP   10.51.255.10   <none>        9081/TCP   1h
petmedicalhistoryservice   ClusterIP   10.51.244.19   <none>        9082/TCP   59m
petservice                 ClusterIP   10.51.242.18   <none>        9080/TCP   1h
petservice mallyn01$ kubectl get ing
NAME      HOSTS     ADDRESS        PORTS     AGE
gateway   *         108.59.82.93   80        1h
mallyn01$ kubectl get pods
NAME                                           READY     STATUS    RESTARTS   AGE
petdetailsservice-v1-5bb8c65577-jmn6r          2/2       Running   0          12h
petmedicalhistoryservice-v1-5757f98898-tq5j8   2/2       Running   0          12h
petservice-v1-587696b469-qttqk                 2/2       Running   0          12h


当查看控制台中 pod 的信息,即使你只为每个容器部署了一项服务,但仍会注意到有2/2个容器正在运行。 另一个容器是 istioctl 命令注入的边车代理。

5. 一旦上述所有内容都运行完毕,您可以使用 Ingress 的 IP 地址去调用示例端点来获取 Pet 的详细信息。


mallyn01$ curl http://108.59.82.93/pet/123
{  "petDetails": {    "petName": "Maximus",    "petAge": 5,    "petOwner": "Nithin Mallya",    "petBreed": "Dog"  },  "petMedicalHistory": {    "vaccinationList": [      "Bordetella, Leptospirosis, Rabies, Lyme Disease"    ]  } }


注意: 由于 PetService 调用 PetDetailsService 和 PetMedicalHistoryService,实际的调用将如下所示:fetch('http://petdetailsservice:9081/pet/123/details')          .then(res => res.text())          .then(body => console.log(body));        ;
fetch('http://petmedicalhistoryservice:9082/pet/123/medicalhistory')          .then(res => res.text())          .then(body => console.log(body)); ;



结论:
我们覆盖了大量内容 (但这只是第一部分!!)

在随后的部分中,将详细介绍如何使用其他 Istio 特性,例如将流量逐步迁移到一个新升级的版本上,使用性能监控仪表板等等。

特别感谢 Ray Tsang 的关于 Istio 的演讲材料 。



资源:
1. The Istio home page https://istio.io/

2. DevOxx 的Ray Tsang的 Istio 演讲材料: https://www.youtube.com/watch% ... D231s

3. 案例的Github link: https://github.com/nmallya/istiodemo

4. Kubernetes: https://kubernetes.io/

5. 微服务:  https://martinfowler.com/artic ... .html

6. Spring Cloud Netflix: https://github.com/spring-clou ... tflix


原文链接:https://medium.com/google-clou ... 922b8









推荐阅读
采用Istio实现灰度发布,给运维人员一支强心剂
构建分布式微服务系统,如何基于代理的服务网格做“减法”?
实用指南 | 基于Kubernetes, GRPC 和 Linkerd 构建可扩展微服务
万字长文 | 如何构建安全的微服务应用,先要解决这两个问题
实例 | 当Istio遇见Jaeger,如何解决端到端分布式追踪问题?


ServiceMesh微信交流群:

添加微信xiaoshu062,备注:服务网格,即可加入Service Mesh微信交流群。


社区活动:

3月31日(周六),数人云联合ServiceComb社区,并由ServiceMesh社区支持,开启meetup系列活动 Building Microservice 第2期 北京站 :微服务,从架构到发布,已经开始报名啦,点击链接快来报名~

采用Istio实现灰度发布,给运维人员一支强心剂

Istio小数 发表了文章 • 0 个评论 • 454 次浏览 • 2018-03-12 10:38 • 来自相关话题

 
作者简介:
      赵化冰是一名程序员及开源软件爱好者,目前在NFV&SDN编排开源社区ONAP担任MSB项目PTL,致力于高性能,高可用性微服务架构在编排领域的应用。
      博客链接:http://zhaohuabing.com/ 
 
 
目录 
一、灰度发布(又名金丝雀发布)介绍
二、Istio实现灰度发布(金丝雀发布)的原理
三、操作步骤
测试环境安装部署V1版本的服务部署V2版本的reviews服务将测试流量导入到V2版本的reviews服务将部分生产流量导入到V2版本的reviews服务将所有生产流量导入到到V2版本的reviews服务删除V1版本的reviews服务
四、参考
 
 
一、灰度发布(又名金丝雀发布)介绍
 
当应用上线以后,运维面临的一大挑战是如何能够在不影响已上线业务的情况下进行升级。做过产品的同学都清楚,不管在发布前做过多么完备的自动化和人工测试,在发布后都会出现或多或少的故障。根据墨菲定律,可能会出错的版本发布一定会出错。
 
“ANYTHING THAT CAN GO WRONG WILL GO WRONG” –MURPHY’S LAW
 
因此我们不能寄希望于在线下测试时发现所有潜在故障。在无法百分百避免版本升级故障的情况下,需要通过一种方式进行可控的版本发布,把故障影响控制在可以接受的范围内,并可以快速回退。
 
可以通过灰度发布(又名金丝雀发布)来实现业务从老版本到新版本的平滑过渡,并避免升级过程中出现的问题对用户造成的影响。
 
“金丝雀发布”的来源于矿工们用金丝雀对矿井进行空气测试的做法。以前矿工挖煤的时候,矿工下矿井前会先把金丝雀放进去,或者挖煤的时候一直带着金丝雀。金丝雀对甲烷和一氧化碳浓度比较敏感,会先报警。所以大家都用“金丝雀”来搞最先的测试。
 
下图中,左下方的少部分用户就被当作“金丝雀”来用于测试新上线的1.1版本。如果新版本出现问题,“金丝雀”们会报警,但不会影响其他用户业务的正常运行。






灰度发布(金丝雀发布)的流程如下:
准备和生产环境隔离的“金丝雀”服务器。将新版本的服务部署到“金丝雀”服务器上。对“金丝雀”服务器上的服务进行自动化和人工测试。测试通过后,将“金丝雀”服务器连接到生产环境,将少量生产流量导入到“金丝雀”服务器中。如果在线测试出现问题,则通过把生产流量从“金丝雀”服务器中重新路由到老版本的服务的方式进行回退,修复问题后重新进行发布。如果在线测试顺利,则逐渐把生产流量按一定策略逐渐导入到新版本服务器中。待新版本服务稳定运行后,删除老版本服务。
 
 
 
二、Istio实现灰度发布的原理
 
从上面的流程可以看到,如果要实现一套灰度发布的流程,需要应用程序和运维流程对该发布过程进行支持,工作量和难度的挑战是非常大的。虽然面对的问题类似,但每个企业或组织一般采用不同的私有化实现方案来进行灰度发布,为解决该问题导致研发和运维花费了大量的成本。
 
Istio通过高度的抽象和良好的设计采用一致的方式解决了该问题,采用sidecar对应用流量进行了转发,通过Pilot下发路由规则,可以在不修改应用程序的前提下实现应用的灰度发布。
 
备注:采用kubernetes的滚动升级(rolling update)功能也可以实现不中断业务的应用升级,但滚动升级是通过逐渐使用新版本的服务来替换老版本服务的方式对应用进行升级,在滚动升级不能对应用的流量分发进行控制,因此无法采用受控地把生产流量逐渐导流到新版本服务中,也就无法控制服务升级对用户造成的影响。
 
采用Istio后,可以通过定制路由规则将特定的流量(如指定特征的用户)导入新版本服务中,在生产环境下进行测试,同时通过渐进受控地导入生产流量,可以最小化升级中出现的故障对用户的影响。并且在同时存在新老版本服务时,还可根据应用压力对不同版本的服务进行独立的缩扩容,非常灵活。采用Istio进行灰度发布的流程如下图所示:data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWNgYGBgAAAABQABh6FO1AAAAABJRU5ErkJggg==
 
 
 
三、操作步骤
 
下面采用Istion自带的BookinfoInfo示例程序来试验灰度发布的流程。

1.测试环境安装
 
首先参考手把手教你从零搭建Istio及Bookinfo示例程序安装Kubernetes及Istio控制面。
 
因为本试验并不需要安装全部3个版本的reviews服务,因此如果已经安装了该应用,先采用下面的命令卸载。
 
istio-0.2.10/samples/bookinfo/kube/cleanup.sh
 

2.部署V1版本的服务
 
首先只部署V1版本的Bookinfo应用程序。由于示例中的yaml文件中包含了3个版本的reviews服务,我们先将V2和V3版本的Deployment从yaml文件istio-0.2.10/samples/bookinfo/kube/bookinfo.yaml中删除。
 
从Bookinfo.yaml中删除这部分内容:
 [size=12]apiVersion: extensions/v1beta1
kind: Deployment
metadata:
 name: reviews-v2
spec:
 replicas: 1
 template:
   metadata:
     labels:
       app: reviews
       version: v2
   spec:
     containers:
     - name: reviews
       image: istio/examples-bookinfo-reviews-v2:0.2.3
       imagePullPolicy: IfNotPresent
       ports:
       - containerPort: 9080
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
 name: reviews-v3
spec:
 replicas: 1
 template:
   metadata:
     labels:
       app: reviews
       version: v3
   spec:
     containers:
     - name: reviews
       image: istio/examples-bookinfo-reviews-v3:0.2.3
       imagePullPolicy: IfNotPresent
       ports:
       - containerPort: 9080    
---         [/size]
部署V1版本的Bookinfo程序。
 [size=12]kubectl apply -f <(istioctl kube-inject -f istio-0.2.10/samples/bookinfo/kube/bookinfo.yaml)[/size]
通过kubectl命令行确认pod部署,可以看到只有V1版本的服务。[size=12]kubectl get pods

NAME                                             READY    STATUS     RESTARTS   AGE
details-v1-3688945616-nhkqk           2/2         Running      0                2m
productpage-v1-2055622944-m3fql  2/2         Running      0                2m
ratings-v1-233971408-0f3s9             2/2         Running      0                2m
reviews-v1-1360980140-0zs9z          2/2         Running      0                2m[/size]
 
在浏览器中打开应用程序页面,地址为istio-ingress的External IP。由于V1版本的reviews服务并不会调用rating服务,因此可以看到Product 页面显示的是不带星级的评价信息。

http://10.12.25.116/productpage

 
此时系统中微服务的部署情况如下图所示(下面的示意图均忽略和本例关系不大的details和ratings服务):





 
 
3.部V2版本的reviews服务
 
在部署V2版本的reviews服务前,需要先创建一条缺省路由规则route-rule-default-reviews.yaml,将所有生产流量都导向V1版本,避免对线上用户的影响。[size=12]apiVersion: config.istio.io/v1alpha2
kind: RouteRule
metadata:
 name: reviews-default
spec:
 destination:
   name: reviews
 precedence: 1
 route:
 - labels:
     version: v1[/size] 
启用该路由规则。[size=12]istioctl create -f route-rule-default-reviews.yaml -n default[/size]
 
创建一个V2版本的部署文件bookinfo-reviews-v2.yaml,内容如下[size=12]apiVersion: extensions/v1beta1
kind: Deployment
metadata:
 name: reviews-v2
spec:
 replicas: 1
 template:
   metadata:
     labels:
       app: reviews
       version: v2
   spec:
     containers:
     - name: reviews
       image: istio/examples-bookinfo-reviews-v2:0.2.3
       imagePullPolicy: IfNotPresent
       ports:
       - containerPort: 9080[/size]
 
部署V2版本的reviews服务。[size=12]kubectl apply -f <(istioctl kube-inject -f  bookinfo-reviews-v2.yaml)[/size]
 
此时系统中部署了V1和V2两个版本的reviews服务,但所有的业务流量都被规则reviews-default导向了V1,如下图所示:





 
 
4.将测试流量导入到V2版本的reviews服务
 
在进行模拟测试时,由于测试环境和生产环境的网络,服务器,操作系统等环境存在差异,很难完全模拟生产环境进行测试。为了减少环境因素的对测试结果的影响,我们希望能在生产环境中进行上线前的测试,但如果没有很好的隔离措施,可能会导致测试影响已上线的业务,对企业造成损失。
 
通过采用Istio的路由规则,可以在类生产环境中进行测试,又完全隔离了线上用户的生产流量和测试流量,最小化模拟测试对已上线业务的影响。如下图所示:






创建一条规则,将用户名为 test-user 的流量导入到V2[size=12]apiVersion: config.istio.io/v1alpha2
kind: RouteRule
metadata:
 name: reviews-test-user
spec:
 destination:
   name: reviews
 precedence: 2
 match:
   request:
     headers:
       cookie:
         regex: "^(.*?;)?(user=test-user)(;.*)?$"
 route:
 - labels:
     version: v2[/size]
 
注意:precedence属性用于设置规则的优先级,在同时存在多条规则的情况下,优先级高的规则将先执行。这条规则的precedence设置为2,以确保其在缺省规则之前运行,将test-user用户的请求导流到V2版本reviews服务中。
 
启用该规则。[size=12]istioctl create -f route-rule-test-reviews-v2.yaml -n default[/size]
以test-user用户登录,可以看到V2版本带星级的评价页面。






注销test-user,只能看到V1版本不带星级的评价页面。如下图所示: 





 
 
5.将部分生产流量导入到V2版本的reviews服务
 
在线上模拟测试完成后,如果系统测试情况良好,可以通过规则将一部分用户流量导入到V2版本的服务中,进行小规模的“金丝雀”测试。
 
修改规则route-rule-default-reviews.yaml,将50%的流量导入V2版本。

备注:本例只是描述原理,因此为简单起见,将50%流量导入V2版本,在实际操作中,更可能是先导入较少流量,然后根据监控的新版本运行情况将流量逐渐导入,如采用5%,10%,20%,50% …的比例逐渐导入。

[size=12]apiVersion: config.istio.io/v1alpha2
kind: RouteRule
metadata:
 name: reviews-default
spec:
 destination:
   name: reviews
 precedence: 1
 route:
 - labels:
     version: v1
   weight: 50
 - labels:
     version: v2
   weight: 50[/size][size=12]istioctl replace -f route-rule-default-reviews.yaml -n default[/size]
 
此时系统部署如下图所示:





 
 6.将所有生产流量导入到到V2版本的reviews服务
 
如果新版本的服务运行正常,则可以将所有流量导入到V2版本。[size=12]apiVersion: config.istio.io/v1alpha2
kind: RouteRule
metadata:
 name: reviews-default
spec:
 destination:
   name: reviews
 precedence: 1
 route:
 - labels:
     version: v2
   weight: 100[/size][size=12]istioctl replace -f route-rule-default-reviews.yaml -n default[/size]
 
系统部署如下图所示:






此时不管以任何用户登录,都只能看到V2版本带星级的评价页面,如下图所示:






备注:如果灰度发布的过程中新版本的服务出现问题,则可以通过修改路由规则,将流量重新导入到V1版本的服务中,将V2版本故障修复后再进行测试。

  
 
7.删除V1版本的reviews服务
 
待V2版本上线稳定运行后,删除V1版本的reviews服务和测试规则。[size=12]kubectl delete pod reviews-v1-1360980140-0zs9z

istioctl delete -f route-rule-test-reviews-v2.yaml -n default[/size] 
四、参考
Istio官方文档 查看全部
 
作者简介:
      赵化冰是一名程序员及开源软件爱好者,目前在NFV&SDN编排开源社区ONAP担任MSB项目PTL,致力于高性能,高可用性微服务架构在编排领域的应用。
      博客链接:http://zhaohuabing.com/ 
 
 
目录 
一、灰度发布(又名金丝雀发布)介绍
二、Istio实现灰度发布(金丝雀发布)的原理
三、操作步骤
  1. 测试环境安装
  2. 部署V1版本的服务
  3. 部署V2版本的reviews服务
  4. 将测试流量导入到V2版本的reviews服务
  5. 将部分生产流量导入到V2版本的reviews服务
  6. 将所有生产流量导入到到V2版本的reviews服务
  7. 删除V1版本的reviews服务

四、参考
 
 
一、灰度发布(又名金丝雀发布)介绍
 
当应用上线以后,运维面临的一大挑战是如何能够在不影响已上线业务的情况下进行升级。做过产品的同学都清楚,不管在发布前做过多么完备的自动化和人工测试,在发布后都会出现或多或少的故障。根据墨菲定律,可能会出错的版本发布一定会出错。
 
“ANYTHING THAT CAN GO WRONG WILL GO WRONG” –MURPHY’S LAW
 
因此我们不能寄希望于在线下测试时发现所有潜在故障。在无法百分百避免版本升级故障的情况下,需要通过一种方式进行可控的版本发布,把故障影响控制在可以接受的范围内,并可以快速回退。
 
可以通过灰度发布(又名金丝雀发布)来实现业务从老版本到新版本的平滑过渡,并避免升级过程中出现的问题对用户造成的影响。
 
“金丝雀发布”的来源于矿工们用金丝雀对矿井进行空气测试的做法。以前矿工挖煤的时候,矿工下矿井前会先把金丝雀放进去,或者挖煤的时候一直带着金丝雀。金丝雀对甲烷和一氧化碳浓度比较敏感,会先报警。所以大家都用“金丝雀”来搞最先的测试。
 
下图中,左下方的少部分用户就被当作“金丝雀”来用于测试新上线的1.1版本。如果新版本出现问题,“金丝雀”们会报警,但不会影响其他用户业务的正常运行。

1.PNG


灰度发布(金丝雀发布)的流程如下:
  • 准备和生产环境隔离的“金丝雀”服务器。
  • 将新版本的服务部署到“金丝雀”服务器上。
  • 对“金丝雀”服务器上的服务进行自动化和人工测试。
  • 测试通过后,将“金丝雀”服务器连接到生产环境,将少量生产流量导入到“金丝雀”服务器中。
  • 如果在线测试出现问题,则通过把生产流量从“金丝雀”服务器中重新路由到老版本的服务的方式进行回退,修复问题后重新进行发布。
  • 如果在线测试顺利,则逐渐把生产流量按一定策略逐渐导入到新版本服务器中。
  • 待新版本服务稳定运行后,删除老版本服务。

 
 
 
二、Istio实现灰度发布的原理
 
从上面的流程可以看到,如果要实现一套灰度发布的流程,需要应用程序和运维流程对该发布过程进行支持,工作量和难度的挑战是非常大的。虽然面对的问题类似,但每个企业或组织一般采用不同的私有化实现方案来进行灰度发布,为解决该问题导致研发和运维花费了大量的成本。
 
Istio通过高度的抽象和良好的设计采用一致的方式解决了该问题,采用sidecar对应用流量进行了转发,通过Pilot下发路由规则,可以在不修改应用程序的前提下实现应用的灰度发布。
 
备注:采用kubernetes的滚动升级(rolling update)功能也可以实现不中断业务的应用升级,但滚动升级是通过逐渐使用新版本的服务来替换老版本服务的方式对应用进行升级,在滚动升级不能对应用的流量分发进行控制,因此无法采用受控地把生产流量逐渐导流到新版本服务中,也就无法控制服务升级对用户造成的影响。
 
采用Istio后,可以通过定制路由规则将特定的流量(如指定特征的用户)导入新版本服务中,在生产环境下进行测试,同时通过渐进受控地导入生产流量,可以最小化升级中出现的故障对用户的影响。并且在同时存在新老版本服务时,还可根据应用压力对不同版本的服务进行独立的缩扩容,非常灵活。采用Istio进行灰度发布的流程如下图所示:data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWNgYGBgAAAABQABh6FO1AAAAABJRU5ErkJggg==
 
 
 
三、操作步骤
 
下面采用Istion自带的BookinfoInfo示例程序来试验灰度发布的流程。

1.测试环境安装
 
首先参考手把手教你从零搭建Istio及Bookinfo示例程序安装Kubernetes及Istio控制面。
 
因为本试验并不需要安装全部3个版本的reviews服务,因此如果已经安装了该应用,先采用下面的命令卸载。
 
istio-0.2.10/samples/bookinfo/kube/cleanup.sh
 

2.部署V1版本的服务
 
首先只部署V1版本的Bookinfo应用程序。由于示例中的yaml文件中包含了3个版本的reviews服务,我们先将V2和V3版本的Deployment从yaml文件istio-0.2.10/samples/bookinfo/kube/bookinfo.yaml中删除。
 
从Bookinfo.yaml中删除这部分内容:
 
[size=12]apiVersion: extensions/v1beta1
kind: Deployment
metadata:
 name: reviews-v2
spec:
 replicas: 1
 template:
   metadata:
     labels:
       app: reviews
       version: v2
   spec:
     containers:
     - name: reviews
       image: istio/examples-bookinfo-reviews-v2:0.2.3
       imagePullPolicy: IfNotPresent
       ports:
       - containerPort: 9080
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
 name: reviews-v3
spec:
 replicas: 1
 template:
   metadata:
     labels:
       app: reviews
       version: v3
   spec:
     containers:
     - name: reviews
       image: istio/examples-bookinfo-reviews-v3:0.2.3
       imagePullPolicy: IfNotPresent
       ports:
       - containerPort: 9080    
---         [/size]

部署V1版本的Bookinfo程序。
 
[size=12]kubectl apply -f <(istioctl kube-inject -f istio-0.2.10/samples/bookinfo/kube/bookinfo.yaml)[/size]

通过kubectl命令行确认pod部署,可以看到只有V1版本的服务。
[size=12]kubectl get pods

NAME                                             READY    STATUS     RESTARTS   AGE
details-v1-3688945616-nhkqk           2/2         Running      0                2m
productpage-v1-2055622944-m3fql  2/2         Running      0                2m
ratings-v1-233971408-0f3s9             2/2         Running      0                2m
reviews-v1-1360980140-0zs9z          2/2         Running      0                2m[/size]

 
在浏览器中打开应用程序页面,地址为istio-ingress的External IP。由于V1版本的reviews服务并不会调用rating服务,因此可以看到Product 页面显示的是不带星级的评价信息。

http://10.12.25.116/productpage

 
此时系统中微服务的部署情况如下图所示(下面的示意图均忽略和本例关系不大的details和ratings服务):

2.gif

 
 
3.部V2版本的reviews服务
 
在部署V2版本的reviews服务前,需要先创建一条缺省路由规则route-rule-default-reviews.yaml,将所有生产流量都导向V1版本,避免对线上用户的影响。
[size=12]apiVersion: config.istio.io/v1alpha2
kind: RouteRule
metadata:
 name: reviews-default
spec:
 destination:
   name: reviews
 precedence: 1
 route:
 - labels:
     version: v1[/size]
 
启用该路由规则。
[size=12]istioctl create -f route-rule-default-reviews.yaml -n default[/size]

 
创建一个V2版本的部署文件bookinfo-reviews-v2.yaml,内容如下
[size=12]apiVersion: extensions/v1beta1
kind: Deployment
metadata:
 name: reviews-v2
spec:
 replicas: 1
 template:
   metadata:
     labels:
       app: reviews
       version: v2
   spec:
     containers:
     - name: reviews
       image: istio/examples-bookinfo-reviews-v2:0.2.3
       imagePullPolicy: IfNotPresent
       ports:
       - containerPort: 9080[/size]

 
部署V2版本的reviews服务。
[size=12]kubectl apply -f <(istioctl kube-inject -f  bookinfo-reviews-v2.yaml)[/size]

 
此时系统中部署了V1和V2两个版本的reviews服务,但所有的业务流量都被规则reviews-default导向了V1,如下图所示:

3.PNG

 
 
4.将测试流量导入到V2版本的reviews服务
 
在进行模拟测试时,由于测试环境和生产环境的网络,服务器,操作系统等环境存在差异,很难完全模拟生产环境进行测试。为了减少环境因素的对测试结果的影响,我们希望能在生产环境中进行上线前的测试,但如果没有很好的隔离措施,可能会导致测试影响已上线的业务,对企业造成损失。
 
通过采用Istio的路由规则,可以在类生产环境中进行测试,又完全隔离了线上用户的生产流量和测试流量,最小化模拟测试对已上线业务的影响。如下图所示:

4.PNG


创建一条规则,将用户名为 test-user 的流量导入到V2
[size=12]apiVersion: config.istio.io/v1alpha2
kind: RouteRule
metadata:
 name: reviews-test-user
spec:
 destination:
   name: reviews
 precedence: 2
 match:
   request:
     headers:
       cookie:
         regex: "^(.*?;)?(user=test-user)(;.*)?$"
 route:
 - labels:
     version: v2[/size]

 
注意:precedence属性用于设置规则的优先级,在同时存在多条规则的情况下,优先级高的规则将先执行。这条规则的precedence设置为2,以确保其在缺省规则之前运行,将test-user用户的请求导流到V2版本reviews服务中。
 
启用该规则。
[size=12]istioctl create -f route-rule-test-reviews-v2.yaml -n default[/size]

以test-user用户登录,可以看到V2版本带星级的评价页面。

5.PNG


注销test-user,只能看到V1版本不带星级的评价页面。如下图所示: 

6.PNG

 
 
5.将部分生产流量导入到V2版本的reviews服务
 
在线上模拟测试完成后,如果系统测试情况良好,可以通过规则将一部分用户流量导入到V2版本的服务中,进行小规模的“金丝雀”测试。
 
修改规则route-rule-default-reviews.yaml,将50%的流量导入V2版本。


备注:本例只是描述原理,因此为简单起见,将50%流量导入V2版本,在实际操作中,更可能是先导入较少流量,然后根据监控的新版本运行情况将流量逐渐导入,如采用5%,10%,20%,50% …的比例逐渐导入。


[size=12]apiVersion: config.istio.io/v1alpha2
kind: RouteRule
metadata:
 name: reviews-default
spec:
 destination:
   name: reviews
 precedence: 1
 route:
 - labels:
     version: v1
   weight: 50
 - labels:
     version: v2
   weight: 50[/size]
[size=12]istioctl replace -f route-rule-default-reviews.yaml -n default[/size]

 
此时系统部署如下图所示:

7.PNG

 
 6.将所有生产流量导入到到V2版本的reviews服务
 
如果新版本的服务运行正常,则可以将所有流量导入到V2版本。
[size=12]apiVersion: config.istio.io/v1alpha2
kind: RouteRule
metadata:
 name: reviews-default
spec:
 destination:
   name: reviews
 precedence: 1
 route:
 - labels:
     version: v2
   weight: 100[/size]
[size=12]istioctl replace -f route-rule-default-reviews.yaml -n default[/size]

 
系统部署如下图所示:

8.PNG


此时不管以任何用户登录,都只能看到V2版本带星级的评价页面,如下图所示:

9.PNG


备注:如果灰度发布的过程中新版本的服务出现问题,则可以通过修改路由规则,将流量重新导入到V1版本的服务中,将V2版本故障修复后再进行测试。


  
 
7.删除V1版本的reviews服务
 
待V2版本上线稳定运行后,删除V1版本的reviews服务和测试规则。
[size=12]kubectl delete pod reviews-v1-1360980140-0zs9z

istioctl delete -f route-rule-test-reviews-v2.yaml -n default[/size]
 
四、参考
  • Istio官方文档

构建分布式微服务系统,如何基于代理的服务网格做“减法”?

ServiceMesh小数 发表了文章 • 0 个评论 • 559 次浏览 • 2018-03-08 10:09 • 来自相关话题

 
 
 作者:Emil Kirschner

翻译:张晔

原文:Proxy Based Service Mesh

地址:https://medium.com/%40entzik/p ... 4c198




基于代理的服务网格是一种新兴技术,通过使用专用代理在容器编排级别提供横切式的基础设施功能,如服务发现、负载平衡、断路器、度量监控、分布式跟踪等,从而简化分布式微服务系统的构建。 通过消除服务中的样板代码,可自由地使用任何技术和任何编程语言。

如果想建立一个分布式的微服务系统,通常必须寻找一组提供服务发现、负载平衡和断路器的组件或框架,然后必须专门制定服务来适配这些组件或框架。 通常这些组件或框架或多或少与特定语言或框架相关联。

例如 Netflix OSS 与 Spring Cloud Netflix 一起使用则非常容易。 只需在 Spring Boot 应用中添加一些注解,即可启动 Zuul 代理和 Eureka 服务器。 通过添加另一组不同的注解,则可以将微服务标记为 Eureka 客户端,且在注册后即可使用。 如果您需要调用下游服务则使用 Feign。 并且可以使用 Hystrix 来保护下游调用。

然而,只要离开了 Java / Spring Boot 领域,事情就会变得复杂起来。

如果需要使用 C ++ 或 Go 来编写服务,则需要自行构建与 Netflix OS S的集成。 这会产生更多的样板代码,每次使用一种新的语言到技术栈时都必须这样做一遍。


服务网格

容器和容器编排技术的兴起使得新的基础架构成为了可能,使我们能够摆脱服务发现/负载平衡/断路器框架的束缚。 这个新的基础设施就是“服务网格” —— 当说它新的时候,我的意思是在撰写本文时(2017年11月),它甚至还没有维基百科页面。

那服务网格是什么呢? 服务网格是一个基础架构层 ,主要是一个代理集合,每个逻辑服务都有一个代理 , 与 Docker Swarm 或 Kubernetes 等容器编排解决方案集成,并提供服务发现,负载平衡,断路器,故障注入,安全,监控,跟踪以及更多以非侵入性的方式提供的开箱即用功能。

由于服务网格在容器级别运行,它并不关心使用什么技术或编程语言来编写微服务。 你可以将微服务使用 Java,C ++,Rust,Go,NodeJS 来编写简单 HTTP 服务器,这些都已不再重要。

可以将服务网格有效地视为分布式容器化应用基础架构级的面向切面编程。 服务网格中的代理就像 AOP 中的一个切面。 它们包裹了一个容器化的微服务,就像 AspectJ 切面可以包裹和测试 Java 方法一样,通过分离横切关注点来简化系统。



乾坤内境

以非侵入方式免费获得所有这些是很酷的,但它是如何工作的? 让我们逐一展开:


服务发现和负载均衡

服务网格将 hook 到编排层 ,Docker Swarm 或 Kubernetes,并在每次启动和停止容器时收到通知。

当启动第一个带有 “service1” 实例的容器时,服务网格将创建一个代理并应用 iptables 配置,该配置将捕获所有到 “service1” 的流量并对其进行管理。 随着更多的 “service1” 实例出现,服务网格将被通知,并将新实例添加到代理的配置中。

当流量流入时,代理将提供:
通过配置软件定义网络来解析主机名 “service1” 到自身的服务发现;通过将传入请求平均分配给可用服务实例来实现负载平衡;


这两个功能有效地取代了 Netflix OSS 技术栈中的 Eureka 和 Ribbon。


断路器

断路器是一种快速失败机制。 如果底层服务实例变慢并且在配置的时间内没有对调用响应,则断路器将使请求失败,并向客户端返回适当的错误码。 客户端然后可以重试并最终到达更具响应力的实例。 这提供了更好的用户体验。

通常情况下,响应慢的实例将被标记为非活动状态,并在接收任何流量之前一段时间后才能恢复。

同样在服务网格中,位于服务的所有实例前的代理充当了断路器。 这有效地取代了 Netflix OSS 技术栈中的 Hystrix 断路器。


故障注入

分布式云原生应用必须设计为容错的。 应用在云中运行的硬件可能随时出现故障,可以取出机器进行定期维护,任何服务的任何实例可能随时无响应。 当这样的事件下游服务的实例故障时,应用必须优雅地处理这种情况,且不降低用户体验,或者最低限度地降低。

但由于这种情况在云环境中随机发生,因此很难在受控环境中再现并研究其对系统的影响。 这将是一件非常有用的事情。

为了解决这个问题,Netflix 的优秀人士提出了 “Chaos Monkey” 和整套相关工具,但这些工具不易部署和运维。

通过服务网格,通过代理配置可以实现相同的功能。 可以为每种服务引入两种随机扰动:

延迟一定比例的请求以观察在分布式系统上增加服务延迟的影响,确保系统作为一个整体能够处理它。

传入请求按百分比失败与随机错误代码,并确保系统可以存活。

在典型工作负载期间将这些扰动转移到不同程度时测量系统吞吐量和终端用户感知延迟,以确定哪些下游服务非常关键,哪些不是。


限速,配额,监控和追踪

服务网格代理处理所有到达服务的流量,它知道什么是正确的,哪里出了问题,它可以强制使用策略,如配额和限速。

代理能注意到每个失败和 SLA 违规。 这使它成为监控服务性能的理想场所。

因为从前端微服务到最后一个下游服务的每个调用都通过代理,所以这也是实现跟踪的理想场所。

一个好的服务网格可以自动安装诸如 Prometheus 和 Zipkin 等监控和跟踪基础设施部分,以及 Grafana 等可视化工具。



当前服务网格现状

当今在服务网格领域有两个玩家:Linkerd 和 Istio。

Linkerd 首当其冲,它是一个更成熟,经过生产验证的解决方案。 它最为人民所知的是被一家全新的在线英国银行 Monzo 用于生产环境中。

另一选择 Istio,则是新兴的挑战者。 它尚未达到生产质量,但速度非常快,并从一开始就得到 Google 云平台的支持。 它建立在 Lyft 开发的 Envoy 代理之上。

ServiceMesh微信交流群:

添加微信xiaoshu062,备注:服务网格,即可加入Service Mesh微信交流群。 查看全部

timg111.jpg

 
 
 作者:Emil Kirschner

翻译:张晔

原文:Proxy Based Service Mesh

地址:https://medium.com/%40entzik/p ... 4c198




基于代理的服务网格是一种新兴技术,通过使用专用代理在容器编排级别提供横切式的基础设施功能,如服务发现、负载平衡、断路器、度量监控、分布式跟踪等,从而简化分布式微服务系统的构建。 通过消除服务中的样板代码,可自由地使用任何技术和任何编程语言。

如果想建立一个分布式的微服务系统,通常必须寻找一组提供服务发现、负载平衡和断路器的组件或框架,然后必须专门制定服务来适配这些组件或框架。 通常这些组件或框架或多或少与特定语言或框架相关联。

例如 Netflix OSS 与 Spring Cloud Netflix 一起使用则非常容易。 只需在 Spring Boot 应用中添加一些注解,即可启动 Zuul 代理和 Eureka 服务器。 通过添加另一组不同的注解,则可以将微服务标记为 Eureka 客户端,且在注册后即可使用。 如果您需要调用下游服务则使用 Feign。 并且可以使用 Hystrix 来保护下游调用。

然而,只要离开了 Java / Spring Boot 领域,事情就会变得复杂起来。

如果需要使用 C ++ 或 Go 来编写服务,则需要自行构建与 Netflix OS S的集成。 这会产生更多的样板代码,每次使用一种新的语言到技术栈时都必须这样做一遍。


服务网格

容器和容器编排技术的兴起使得新的基础架构成为了可能,使我们能够摆脱服务发现/负载平衡/断路器框架的束缚。 这个新的基础设施就是“服务网格” —— 当说它新的时候,我的意思是在撰写本文时(2017年11月),它甚至还没有维基百科页面。

那服务网格是什么呢? 服务网格是一个基础架构层 ,主要是一个代理集合,每个逻辑服务都有一个代理 , 与 Docker Swarm 或 Kubernetes 等容器编排解决方案集成,并提供服务发现,负载平衡,断路器,故障注入,安全,监控,跟踪以及更多以非侵入性的方式提供的开箱即用功能。

由于服务网格在容器级别运行,它并不关心使用什么技术或编程语言来编写微服务。 你可以将微服务使用 Java,C ++,Rust,Go,NodeJS 来编写简单 HTTP 服务器,这些都已不再重要。

可以将服务网格有效地视为分布式容器化应用基础架构级的面向切面编程。 服务网格中的代理就像 AOP 中的一个切面。 它们包裹了一个容器化的微服务,就像 AspectJ 切面可以包裹和测试 Java 方法一样,通过分离横切关注点来简化系统。



乾坤内境

以非侵入方式免费获得所有这些是很酷的,但它是如何工作的? 让我们逐一展开:


服务发现和负载均衡

服务网格将 hook 到编排层 ,Docker Swarm 或 Kubernetes,并在每次启动和停止容器时收到通知。

当启动第一个带有 “service1” 实例的容器时,服务网格将创建一个代理并应用 iptables 配置,该配置将捕获所有到 “service1” 的流量并对其进行管理。 随着更多的 “service1” 实例出现,服务网格将被通知,并将新实例添加到代理的配置中。

当流量流入时,代理将提供:
  • 通过配置软件定义网络来解析主机名 “service1” 到自身的服务发现;
  • 通过将传入请求平均分配给可用服务实例来实现负载平衡;



这两个功能有效地取代了 Netflix OSS 技术栈中的 Eureka 和 Ribbon。


断路器

断路器是一种快速失败机制。 如果底层服务实例变慢并且在配置的时间内没有对调用响应,则断路器将使请求失败,并向客户端返回适当的错误码。 客户端然后可以重试并最终到达更具响应力的实例。 这提供了更好的用户体验。

通常情况下,响应慢的实例将被标记为非活动状态,并在接收任何流量之前一段时间后才能恢复。

同样在服务网格中,位于服务的所有实例前的代理充当了断路器。 这有效地取代了 Netflix OSS 技术栈中的 Hystrix 断路器。


故障注入

分布式云原生应用必须设计为容错的。 应用在云中运行的硬件可能随时出现故障,可以取出机器进行定期维护,任何服务的任何实例可能随时无响应。 当这样的事件下游服务的实例故障时,应用必须优雅地处理这种情况,且不降低用户体验,或者最低限度地降低。

但由于这种情况在云环境中随机发生,因此很难在受控环境中再现并研究其对系统的影响。 这将是一件非常有用的事情。

为了解决这个问题,Netflix 的优秀人士提出了 “Chaos Monkey” 和整套相关工具,但这些工具不易部署和运维。

通过服务网格,通过代理配置可以实现相同的功能。 可以为每种服务引入两种随机扰动:

延迟一定比例的请求以观察在分布式系统上增加服务延迟的影响,确保系统作为一个整体能够处理它。

传入请求按百分比失败与随机错误代码,并确保系统可以存活。

在典型工作负载期间将这些扰动转移到不同程度时测量系统吞吐量和终端用户感知延迟,以确定哪些下游服务非常关键,哪些不是。


限速,配额,监控和追踪

服务网格代理处理所有到达服务的流量,它知道什么是正确的,哪里出了问题,它可以强制使用策略,如配额和限速。

代理能注意到每个失败和 SLA 违规。 这使它成为监控服务性能的理想场所。

因为从前端微服务到最后一个下游服务的每个调用都通过代理,所以这也是实现跟踪的理想场所。

一个好的服务网格可以自动安装诸如 Prometheus 和 Zipkin 等监控和跟踪基础设施部分,以及 Grafana 等可视化工具。



当前服务网格现状

当今在服务网格领域有两个玩家:Linkerd 和 Istio。

Linkerd 首当其冲,它是一个更成熟,经过生产验证的解决方案。 它最为人民所知的是被一家全新的在线英国银行 Monzo 用于生产环境中。

另一选择 Istio,则是新兴的挑战者。 它尚未达到生产质量,但速度非常快,并从一开始就得到 Google 云平台的支持。 它建立在 Lyft 开发的 Envoy 代理之上。

ServiceMesh微信交流群:

添加微信xiaoshu062,备注:服务网格,即可加入Service Mesh微信交流群。

实用指南 | 基于Kubernetes, GRPC 和 Linkerd 构建可扩展微服务

Linkerd小数 发表了文章 • 1 个评论 • 684 次浏览 • 2018-03-06 09:59 • 来自相关话题

作者:Rik Nauta
翻译:周巍
原文:Building scalable micro-services with Kubernetes, GRPC & Linkerd
地址:https://medium.com/%40riknauta ... 79599







这是一份关于如何在 K8S(注1)上实现 Docker(注2)微服务自动伸缩的实用指南,其中服务间通过 GRPC(注3)通信,通过 Linkerd(注4)实现负载均衡和服务发现,直到谷歌支持开箱即用的功能。

Warning:这是一篇高技术含量的博文。它不适合所有人但希望对一些人有用,因此如果你不理解标题,建议看这里(注5)或者给 Wikipedia(注6)捐点钱~

Update:关于这个问题 Google 答复了我,似乎可以用 Ingress 控制器代替 LB 来解决。我正在研究是否可以通过那种方法解决,如果可以,我将再写一片博文。




1、介绍

在这篇文章中,我将简要介绍下我们最近如何修改我们的数据处理 Pipeline,来加入一个新的自然语言处理(Natural Language Processing,NLP)微服务。Kubernetes、Docker 和 GRPC 本已经开箱即用支持我们的这种场景,但还是遇到了一些烦人的扩展伸缩问题。我们花了很长的时间来找到一个“production ready”的临时解决方案。为了让其他人避免类似问题,本文将介绍我们是如何做到的。同时,如果你有任何建议,请作评论(或者将你的 CV 发给我们)。


本文首先解释我们的设计方案,然后将会介绍我们当前的实现,最后描述一些未来改进的想法。


2、背景


1为什么选择Docker微服务?

如果你完全不了解 Docker 或者微服务,你应该快速阅读这篇文章(注7)。我们将巨无霸“MapReduce”修改成微服务 pipeline 有三大好处:


1. 可以用任何语言来实现 NLP 模型。将它抽象为 Docker 容器并对外提供 API,则不再需要关心实现的细节,只需要符合 API 约定,这就引入了 GRPC,稍后详细描述。

2. 可以轻松地对模型进行修改、升级和 A/B 测试。我们只需要用新版本替换 Docker 容器,甚至可以实时操作,这在流式数据处理和在线机器学习模型中非常方便。

3. 更好的伸缩性。这一优点并不总是,但至少在本例中能够体现。在我们的巨无霸中,我们不得不将100个模型加载到内存中,尽管这样能够解决问题,但它会导致很多难以加载/卸载的代码,这些代码并是我们核心目的的一部分。相反,针对不同的语言,使用100个不同的 NLP 微服务按需进行扩展要更加高效。

理论上来说,用 RPC 调用来“阻止(clog down)”高效的 MapReduce 任务并不是个好的方法,但实际中使用 Apache Beam 效果很好,它使得我们能够用 Beam 作为数据编排器从而能够执行 ETL 操作,而不是简单的 MapReduce 实现。


2为什么选择K8S?

为什么要选择 kubernetes ?因为它真的很棒!我仍然记得尝试 Docker Swarm 甚至 Amazon 的容器编排器的黑暗时光,这并不有趣。但 Kubernetes 却提供了我们部署和伸缩那些微服务所需的所有功能(甚至更多)。

我们并没有搭建自己的 Kubernetes 集群,而是使用 Google Container Engine(GCE) (注8)。当然,如果你觉得管理自己的 Kubernetes 集群更好的话,你可以使用 AWS 或者其他类似平台。但对我们来说,还有更重要的事情做,所以就选择了 GCE。

不幸的是,尽管 GCE 中已经集成了 K8S,我们还是发现不得不绞尽脑汁地找到好的办法来实现微服务的负载均衡,稍后详细解释。


3为什么选择GRPC?

对于微服务来说,相对于普通的 REST/JSON API,使用像 GRPC 一样的框架将会有许多优势。首先 GRPC 是一个非常高效的二进制协议,同时,你仅仅需要指定你的“服务API”就可以生成任何你所需要的语言绑定,例如 Java, Python, Go, Rust 等,与发送 JSON 并期望每个人都遵从最新的约定相比,GRPC 更加友好且更不容易出错,因为定义和实现是分离的。

当然,GRPC 不是唯一有这些特性的框架,Apache Thrift 是另一个常见的竞争者。也许你不认为,但我觉得 GRPC 将是未来的趋势。


4为什么选择Linkerd?

正如我之前提到的那样,我们在扩展伸缩微服务时遇到了一些问题,因为 GRPC 使用的新的 HTTP2 作为通信协议,虽然 HTTP2 相对 HTTP1.1 来说更快且更加高效,但几乎所有我们见过的与 Kubernetes 一起使用的“标准”负载均衡均是4层负载均衡(包括谷歌和亚马逊的“硬件”负载均衡器),而我们需要一个7层负载均衡器来实现 HTTP2 通信的负载均衡。

简单地说:客户端连接一个4层负载均衡器,之后再连一个后端服务,客户端的请求会不断重用与负载均衡的连接,这就意味着通信根本没有实现负载均衡。而7层负载均衡器则更加智能,能将请求发送到不同的服务器。


因此我们找了一些支持7层的负载均衡器。尽管 Lyft 的 Envoy 是个很不错的方案,但我们还是选择了 Linkerd,因为它看起来经过了更多的测试,而且至少还有一些关于 Kubernetes 和 GRPC 通信的文档作为参考。


3、实现

既然你了解了那些组件,并且知道我们为什么选择它们。以下是如何将它们组合起来的一个例子:在 Kubernetes 集群中部署自动伸缩,负载均衡的 GRPC 微服务。如果有必要,我可以将它放到 GitHub repo 中,但现在的话,先看看吧。

--

apiVersion: v1

kind: ConfigMap

metadata:

  name: linkerd-config

  namespace: app

data:

  config.yaml: |-

    admin:

      port: 9990

    namers:

      - kind: io.l5d.k8s

        experimental: true

        host: 127.0.0.1

        port: 8001

    routers:

    - protocol: h2

      experimental: true

      label: grpc

      client:

        loadBalancer:

          kind: ewma

          maxEffort: 10

          decayTimeMs: 15000

      servers:

        - port: 8080

          ip: 0.0.0.0

      baseDtab: |

      # this directs http2 traffic straight to the specified service

      # this can be changed to read the service name header and redirect

      # traffic to different services based on that:

      # /srv => /#/io.l5d.k8s/<namespace>/service;

      # /h2 => /srv ;

        /h2 => /#/io.l5d.k8s/<namespace>/<port-name>/<service-name>;

```







---

apiVersion: extensions/v1beta1

kind: Deployment

metadata:

  name: app

  namespace: app

  labels:

    type: app

spec:

  replicas: 3

  template:

    metadata:

      labels:

        type: app

      name: app

      annotations:

        #this annotation makes sure the containers get scheduled on a nodepool that

        #autoscales based on container requirements. This feature might not be available

        #outside of GCE...but why would you use anything else!

        scheduler.alpha.kubernetes.io/affinity: >

          {

            "nodeAffinity": {

              "requiredDuringSchedulingIgnoredDuringExecution": {

                "nodeSelectorTerms": [

                  {

                    "matchExpressions": [

                      {

                        "key": "cloud.google.com/gke-nodepool",

                        "operator": "In",

                        "values": ["autoscaling-nodepool"]

                      }

                    ]

                  }

                ]

              }

            }

          }

    spec:

      containers:

        - name: app

          image: company/microservice:0.0.1

          imagePullPolicy: Always

          ports: 

          resources:

            requests:

              memory: "1Gi"

            limits:

              memory: "1Gi"

          ports:

          - name: grpc

            containerPort: 50051

            

        - name: linkerd

          image: buoyantio/linkerd:latest

          args:

          - "/io.buoyant/linkerd/config/config.yaml"

          ports:

          - name: ext

            containerPort: 8080

          - name: admin

            containerPort: 9990

          volumeMounts:

          - name: "linkerd-config"

            mountPath: "/io.buoyant/linkerd/config"

            readOnly: true

        

        #This container is used by linkerd to resolve the service name

        #to an actual local IP

        - name: kubectl

          image: buoyantio/kubectl:1.2.3

          args:

          - "proxy"

          - "-p"

          - "8001"

      dnsPolicy: ClusterFirst

      volumes:

        - name: linkerd-config

          configMap:

            name: "linkerd-config"

  ```




---

kind: Service

apiVersion: v1

metadata:

  namespace: app

  name: app

spec:

  selector:

    type: app

  type: LoadBalancer

loadBalancerSourceRanges:

  #You can easily turn this into an internal load balancer so that any service (inside and outside of your K8S network)

  #can reach it. This again won't work outisde Google's super smart router which will optimize traffic to take the shortest route.

  #So even if you give an internal service the public IP of this loadbalancer the traffic will be optimized to use the internal route.

  #In contrast...on AWS you're f#ck'd, they just route you outside your private network and then back which means your public IP isn't accepted

  #and you have to fiddle with resolving private IP's manually...ugh

  - "0.0.0.0/0" 

  ports:

  - name: ext

    port: 80

    targetPort: 8080

  - name: grpc

    port: 50051

    targetPort: grpc

```




# The admin shouldn't be reachable outside of Kubernetes. Just use `kubectl proxy` or `kubectl port-forward` to access it securely!

---

kind: Service

apiVersion: v1

metadata:

  namespace: app

  name: admin

spec:

  selector:

    type: app

  ports:

    - name: admin

      port: 9990

```




---

apiVersion: autoscaling/v1

kind: HorizontalPodAutoscaler

metadata:

  name: app

  namespace: app

spec:

  scaleTargetRef:

    apiVersion: extensions/v1beta1

    kind: Deployment

    name: app

  minReplicas: 1

  maxReplicas: 100

  targetCPUUtilizationPercentage: 30

  #Custom metrics will soon be supported!

```




4、结论

首先,我不是100%肯定,但它完全可以正常工作。最初的一些测试结果显示流量确实路由到了所有 pod,这对我来说有些神奇。当然,我只看了 Linkerd 的文档十分钟,还有一大堆我们没有涉及的功能,所以我相信还有提升的空间。

我的一个想法是不将 Linkerd 作为的 side-carts 部署,而是部署为 DaemonSets,这意味着每个节点仅需要运行一个实例。为了实现这一点,我们需要从 HTTP2 请求的 header 中获取服务名,并相应地路由请求。然而,根据我们当前的命名/命名空间设置,这很难做到,因此我们先进行测试。

另一个想法是让 Linkerd 根据需要向 K8S 发送伸缩命令,而不是利用 Horizontal Pod Autoscaler,因为它只支持测量 CPU 负载。

最后,这不是最终的解决方案。Kubernetes 和 GRPC 正在快速发展,我相信 GRPC 微服务的部署、伸缩和负载均衡将会很快实现开箱即用,到时候我将第一个切换。




1、https://kubernetes.io/

2、https://www.docker.com/

3、https://grpc.io/

4、https://linkerd.io/

5、https://www.youtube.com/watch?v=xb8u2s7cxzg

6、https://wikimediafoundation.org/wiki/Ways_to_Give

7、http://www.simplicityitself.io ... w.html)

8、http://%2522https//cloud.googl ... gine/

ServiceMesh微信交流群:

添加微信xiaoshu062,备注:服务网格,即可加入Service Mesh微信交流群。
  查看全部
作者:Rik Nauta
翻译:周巍
原文:Building scalable micro-services with Kubernetes, GRPC & Linkerd
地址:https://medium.com/%40riknauta ... 79599


微信图片_20180305170110.jpg


这是一份关于如何在 K8S(注1)上实现 Docker(注2)微服务自动伸缩的实用指南,其中服务间通过 GRPC(注3)通信,通过 Linkerd(注4)实现负载均衡和服务发现,直到谷歌支持开箱即用的功能。

Warning:这是一篇高技术含量的博文。它不适合所有人但希望对一些人有用,因此如果你不理解标题,建议看这里(注5)或者给 Wikipedia(注6)捐点钱~

Update:关于这个问题 Google 答复了我,似乎可以用 Ingress 控制器代替 LB 来解决。我正在研究是否可以通过那种方法解决,如果可以,我将再写一片博文。




1、介绍

在这篇文章中,我将简要介绍下我们最近如何修改我们的数据处理 Pipeline,来加入一个新的自然语言处理(Natural Language Processing,NLP)微服务。Kubernetes、Docker 和 GRPC 本已经开箱即用支持我们的这种场景,但还是遇到了一些烦人的扩展伸缩问题。我们花了很长的时间来找到一个“production ready”的临时解决方案。为了让其他人避免类似问题,本文将介绍我们是如何做到的。同时,如果你有任何建议,请作评论(或者将你的 CV 发给我们)。


本文首先解释我们的设计方案,然后将会介绍我们当前的实现,最后描述一些未来改进的想法。


2、背景


1为什么选择Docker微服务?

如果你完全不了解 Docker 或者微服务,你应该快速阅读这篇文章(注7)。我们将巨无霸“MapReduce”修改成微服务 pipeline 有三大好处:


1. 可以用任何语言来实现 NLP 模型。将它抽象为 Docker 容器并对外提供 API,则不再需要关心实现的细节,只需要符合 API 约定,这就引入了 GRPC,稍后详细描述。

2. 可以轻松地对模型进行修改、升级和 A/B 测试。我们只需要用新版本替换 Docker 容器,甚至可以实时操作,这在流式数据处理和在线机器学习模型中非常方便。

3. 更好的伸缩性。这一优点并不总是,但至少在本例中能够体现。在我们的巨无霸中,我们不得不将100个模型加载到内存中,尽管这样能够解决问题,但它会导致很多难以加载/卸载的代码,这些代码并是我们核心目的的一部分。相反,针对不同的语言,使用100个不同的 NLP 微服务按需进行扩展要更加高效。

理论上来说,用 RPC 调用来“阻止(clog down)”高效的 MapReduce 任务并不是个好的方法,但实际中使用 Apache Beam 效果很好,它使得我们能够用 Beam 作为数据编排器从而能够执行 ETL 操作,而不是简单的 MapReduce 实现。


2为什么选择K8S?

为什么要选择 kubernetes ?因为它真的很棒!我仍然记得尝试 Docker Swarm 甚至 Amazon 的容器编排器的黑暗时光,这并不有趣。但 Kubernetes 却提供了我们部署和伸缩那些微服务所需的所有功能(甚至更多)。

我们并没有搭建自己的 Kubernetes 集群,而是使用 Google Container Engine(GCE) (注8)。当然,如果你觉得管理自己的 Kubernetes 集群更好的话,你可以使用 AWS 或者其他类似平台。但对我们来说,还有更重要的事情做,所以就选择了 GCE。

不幸的是,尽管 GCE 中已经集成了 K8S,我们还是发现不得不绞尽脑汁地找到好的办法来实现微服务的负载均衡,稍后详细解释。


3为什么选择GRPC?

对于微服务来说,相对于普通的 REST/JSON API,使用像 GRPC 一样的框架将会有许多优势。首先 GRPC 是一个非常高效的二进制协议,同时,你仅仅需要指定你的“服务API”就可以生成任何你所需要的语言绑定,例如 Java, Python, Go, Rust 等,与发送 JSON 并期望每个人都遵从最新的约定相比,GRPC 更加友好且更不容易出错,因为定义和实现是分离的。

当然,GRPC 不是唯一有这些特性的框架,Apache Thrift 是另一个常见的竞争者。也许你不认为,但我觉得 GRPC 将是未来的趋势。


4为什么选择Linkerd?

正如我之前提到的那样,我们在扩展伸缩微服务时遇到了一些问题,因为 GRPC 使用的新的 HTTP2 作为通信协议,虽然 HTTP2 相对 HTTP1.1 来说更快且更加高效,但几乎所有我们见过的与 Kubernetes 一起使用的“标准”负载均衡均是4层负载均衡(包括谷歌和亚马逊的“硬件”负载均衡器),而我们需要一个7层负载均衡器来实现 HTTP2 通信的负载均衡。

简单地说:客户端连接一个4层负载均衡器,之后再连一个后端服务,客户端的请求会不断重用与负载均衡的连接,这就意味着通信根本没有实现负载均衡。而7层负载均衡器则更加智能,能将请求发送到不同的服务器。


因此我们找了一些支持7层的负载均衡器。尽管 Lyft 的 Envoy 是个很不错的方案,但我们还是选择了 Linkerd,因为它看起来经过了更多的测试,而且至少还有一些关于 Kubernetes 和 GRPC 通信的文档作为参考。


3、实现

既然你了解了那些组件,并且知道我们为什么选择它们。以下是如何将它们组合起来的一个例子:在 Kubernetes 集群中部署自动伸缩,负载均衡的 GRPC 微服务。如果有必要,我可以将它放到 GitHub repo 中,但现在的话,先看看吧。

--

apiVersion: v1

kind: ConfigMap

metadata:

  name: linkerd-config

  namespace: app

data:

  config.yaml: |-

    admin:

      port: 9990

    namers:

      - kind: io.l5d.k8s

        experimental: true

        host: 127.0.0.1

        port: 8001

    routers:

    - protocol: h2

      experimental: true

      label: grpc

      client:

        loadBalancer:

          kind: ewma

          maxEffort: 10

          decayTimeMs: 15000

      servers:

        - port: 8080

          ip: 0.0.0.0

      baseDtab: |

      # this directs http2 traffic straight to the specified service

      # this can be changed to read the service name header and redirect

      # traffic to different services based on that:

      # /srv => /#/io.l5d.k8s/<namespace>/service;

      # /h2 => /srv ;

        /h2 => /#/io.l5d.k8s/<namespace>/<port-name>/<service-name>;

```







---

apiVersion: extensions/v1beta1

kind: Deployment

metadata:

  name: app

  namespace: app

  labels:

    type: app

spec:

  replicas: 3

  template:

    metadata:

      labels:

        type: app

      name: app

      annotations:

        #this annotation makes sure the containers get scheduled on a nodepool that

        #autoscales based on container requirements. This feature might not be available

        #outside of GCE...but why would you use anything else!

        scheduler.alpha.kubernetes.io/affinity: >

          {

            "nodeAffinity": {

              "requiredDuringSchedulingIgnoredDuringExecution": {

                "nodeSelectorTerms": [

                  {

                    "matchExpressions": [

                      {

                        "key": "cloud.google.com/gke-nodepool",

                        "operator": "In",

                        "values": ["autoscaling-nodepool"]

                      }

                    ]

                  }

                ]

              }

            }

          }

    spec:

      containers:

        - name: app

          image: company/microservice:0.0.1

          imagePullPolicy: Always

          ports: 

          resources:

            requests:

              memory: "1Gi"

            limits:

              memory: "1Gi"

          ports:

          - name: grpc

            containerPort: 50051

            

        - name: linkerd

          image: buoyantio/linkerd:latest

          args:

          - "/io.buoyant/linkerd/config/config.yaml"

          ports:

          - name: ext

            containerPort: 8080

          - name: admin

            containerPort: 9990

          volumeMounts:

          - name: "linkerd-config"

            mountPath: "/io.buoyant/linkerd/config"

            readOnly: true

        

        #This container is used by linkerd to resolve the service name

        #to an actual local IP

        - name: kubectl

          image: buoyantio/kubectl:1.2.3

          args:

          - "proxy"

          - "-p"

          - "8001"

      dnsPolicy: ClusterFirst

      volumes:

        - name: linkerd-config

          configMap:

            name: "linkerd-config"

  ```




---

kind: Service

apiVersion: v1

metadata:

  namespace: app

  name: app

spec:

  selector:

    type: app

  type: LoadBalancer

loadBalancerSourceRanges:

  #You can easily turn this into an internal load balancer so that any service (inside and outside of your K8S network)

  #can reach it. This again won't work outisde Google's super smart router which will optimize traffic to take the shortest route.

  #So even if you give an internal service the public IP of this loadbalancer the traffic will be optimized to use the internal route.

  #In contrast...on AWS you're f#ck'd, they just route you outside your private network and then back which means your public IP isn't accepted

  #and you have to fiddle with resolving private IP's manually...ugh

  - "0.0.0.0/0" 

  ports:

  - name: ext

    port: 80

    targetPort: 8080

  - name: grpc

    port: 50051

    targetPort: grpc

```




# The admin shouldn't be reachable outside of Kubernetes. Just use `kubectl proxy` or `kubectl port-forward` to access it securely!

---

kind: Service

apiVersion: v1

metadata:

  namespace: app

  name: admin

spec:

  selector:

    type: app

  ports:

    - name: admin

      port: 9990

```




---

apiVersion: autoscaling/v1

kind: HorizontalPodAutoscaler

metadata:

  name: app

  namespace: app

spec:

  scaleTargetRef:

    apiVersion: extensions/v1beta1

    kind: Deployment

    name: app

  minReplicas: 1

  maxReplicas: 100

  targetCPUUtilizationPercentage: 30

  #Custom metrics will soon be supported!

```




4、结论

首先,我不是100%肯定,但它完全可以正常工作。最初的一些测试结果显示流量确实路由到了所有 pod,这对我来说有些神奇。当然,我只看了 Linkerd 的文档十分钟,还有一大堆我们没有涉及的功能,所以我相信还有提升的空间。

我的一个想法是不将 Linkerd 作为的 side-carts 部署,而是部署为 DaemonSets,这意味着每个节点仅需要运行一个实例。为了实现这一点,我们需要从 HTTP2 请求的 header 中获取服务名,并相应地路由请求。然而,根据我们当前的命名/命名空间设置,这很难做到,因此我们先进行测试。

另一个想法是让 Linkerd 根据需要向 K8S 发送伸缩命令,而不是利用 Horizontal Pod Autoscaler,因为它只支持测量 CPU 负载。

最后,这不是最终的解决方案。Kubernetes 和 GRPC 正在快速发展,我相信 GRPC 微服务的部署、伸缩和负载均衡将会很快实现开箱即用,到时候我将第一个切换。




1、https://kubernetes.io/

2、https://www.docker.com/

3、https://grpc.io/

4、https://linkerd.io/

5、https://www.youtube.com/watch?v=xb8u2s7cxzg

6、https://wikimediafoundation.org/wiki/Ways_to_Give

7、http://www.simplicityitself.io ... w.html)

8、http://%2522https//cloud.googl ... gine/

ServiceMesh微信交流群:

添加微信xiaoshu062,备注:服务网格,即可加入Service Mesh微信交流群。
 

万字长文 | 如何构建安全的微服务应用,先要解决这两个问题

ServiceMesh小数 发表了文章 • 0 个评论 • 438 次浏览 • 2018-03-02 10:19 • 来自相关话题

   
作者简介:
      赵化冰是一名程序员及开源软件爱好者,目前在NFV&SDN编排开源社区ONAP担任MSB项目PTL,致力于高性能,高可用性微服务架构在编排领域的应用。
      博客链接:http://zhaohuabing.com/  
 
目录 
一、前言
二、单体应用的实现方式
三、微服务认证和鉴权面临的问题
四、微服务认证和鉴权的技术方案
1.用户身份认证
2.用户状态保持
3.实现单点登录
4.用户权限控制
API Gateway处进行统一的权限控制
由各个微服务单独进行权限控制
5.第三方应用接入
API Token
OAuth
6.微服务之间的认证​
五、参考
  
一、前言 
 
微服务架构的引入为软件应用带来了诸多好处:包括小开发团队,缩短开发周期,语言选择灵活性,增强服务伸缩能力等。与此同时,也引入了分布式系统的诸多复杂问题。其中一个挑战就是如何在微服务架构中实现一个灵活,安全,高效的认证和鉴权方案。本文将尝试就此问题进行一次比较完整的探讨。
 
 
 
二、单体应用的实现方式
 
在单体架构下,整个应用是一个进程,在应用中,一般会用一个安全模块来实现用户认证和鉴权。 用户登录时,应用的安全模块对用户身份进行验证,验证用户身份合法后,为该用户生成一个会话(Session),并为该Session关联一个唯一的编号(Session Id)。Session是应用中的一小块内存结构,其中保存了登录用户的信息,如User name, Role, Permission等。服务器把该Session的Session Id返回给客户端,客户端将Session Id以cookie或者URL重写的方式记录下来,并在后续请求中发送给应用,这样应用在接收到客户端访问请求时可以使用Session Id验证用户身份,不用每次请求时都输入用户名和密码进行身份验证。

备注:为了避免Session Id被第三者截取和盗用,客户端和应用之前应使用TLS加密通信,session也会设置有过期时间。

 





                          单体应用用户登录认证序列图
 
客户端访问应用时,Session Id随着HTTP请求发送到应用,客户端请求一般会通过一个拦截器处理所有收到的客户端请求。拦截器首先判断Session Id是否存在,如果该Session Id存在,就知道该用户已经登录。然后再通过查询用户权限判断用户能否执行该此请求,以实现操作鉴权。
 





data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWNgYGBgAAAABQABh6FO1AAAAABJRU5ErkJggg==单体应用用户操作鉴权序列图    
 
 

三、微服务认证和鉴权面临的问题 
 
在微服务架构下,一个应用被拆分为多个微服务进程,每个微服务实现原来单体应用中一个模块的业务功能。应用拆分后,对每个微服务的访问请求都需要进行认证和鉴权。如果参考单体应用的实现方式会遇到下述问题:
认证和鉴权逻辑需要在每个微服务中进行处理,需要在各个微服务中重复实现这部分公共逻辑。虽然我们可以使用代码库复用部分代码,但这又会导致所有微服务对特定代码库及其版本存在依赖,影响微服务语言/框架选择的灵活性。微服务应遵循单一职责原理,一个微服务只处理单一的业务逻辑。认证和鉴权的公共逻辑不应该放到微服务实现中。为了充分利用微服务架构的好处,实现微服务的水平扩展(Scalability)和弹性(Resiliency),微服务最好是无状态的。因此不建议使用session这种有状态的方案。微服务架构下的认证和鉴权涉及到场景更为复杂,涉及到用户访问微服务应用,第三方应用访问微服务应用,应用内多个微服务之间相互访问等多种场景,每种场景下的认证和鉴权方案都需要考虑到,以保证应用程序的安全性。 data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWNgYGBgAAAABQABh6FO1AAAAABJRU5ErkJggg==
 微服务认证和鉴权涉及到的三种场景  
  
四、微服务认证和鉴权的技术方案

  1.用户身份认证
 
一个完整的微服务应用是由多个相互独立的微服务进程组成的,对每个微服务的访问都需要进行用户认证。如果将用户认证的工作放到每个微服务中,应用的认证逻辑将会非常复杂。因此需要考虑一个SSO(单点登录)的方案,即用户只需要登录一次,就可以访问所有微服务提供的服务。 由于在微服务架构中以API Gateway作为对外提供服务的入口,因此可以考虑在API Gateway处提供统一的用户认证。
 
 2.用户状态保持
 
HTTP是一个无状态的协议,对服务器来说,用户的每次HTTP请求是相互独立的。互联网是一个巨大的分布式系统,HTTP协议作为互联网上的一个重要协议,要考虑到大量应用访问的效率问题。无状态意味着服务端可以把客户端的请求根据需要发送到集群中的任何一个节点,HTTP的无状态设计对负载均衡有明显的好处,由于没有状态,用户请求可以被分发到任意一个服务器,应用也可以在靠近用户的网络边缘部署缓存服务器。对于不需要身份认证的服务,例如浏览新闻网页等,这是没有任何问题的。但很多服务如网络购物,企业管理系统等都需要对用户的身份进行认证,因此需要在HTTP协议基础上采用一种方式保存用户的登录状态,避免用户每发起一次请求都需要进行验证。
 
传统方式是在服务器端采用Cookie来保存用户状态,由于在服务器是有状态的,对服务器的水平扩展有影响。在微服务架构下建议采用Token来记录用户登录状态。
 
Token和Seesion主要的不同点是存储的地方不同。Session是集中存储在服务器中的;而Token是用户自己持有的,一般以cookie的形式存储在浏览器中。Token中保存了用户的身份信息,每次请求都会发送给服务器,服务器因此可以判断访问者的身份,并判断其对请求的资源有没有访问权限。
 
Token用于表明用户身份,因此需要对其内容进行加密,避免被请求方或者第三者篡改。JWT(Json Web Token)是一个定义Token格式的开放标准(RFC 7519),定义了Token的内容,加密方式,并提供了各种语言的lib。
 
JWT Token的结构非常简单,包括三部分:
Header头部包含类型,为固定值JWT。然后是JWT使用的Hash算法。{"alg": "HS256","typ": "JWT"}Payload包含发布者,过期时间,用户名等标准信息,也可以添加用户角色,用户自定义的信息。{"sub": "1234567890","name": "John Doe","admin": true}SignatureToken颁发方的签名,用于客户端验证Token颁发方的身份,也用于服务器防止Token被篡改。 签名算法HMACSHA256(base64UrlEncode(header) + "." +base64UrlEncode(payload),secret)
 
这三部分使用Base64编码后组合在一起,成为最终返回给客户端的Token串,每部分之间采用”.”分隔。下图是上面例子最终形成的Token
data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWNgYGBgAAAABQABh6FO1AAAAABJRU5ErkJggg==
采用Token进行用户认证,服务器端不再保存用户状态,客户端每次请求时都需要将Token发送到服务器端进行身份验证。Token发送的方式rfc6750进行了规定,采用一个 Authorization: Bearer HHTP Header进行发送。Authorization: Bearer mF_9.B5f-4.1JqM
 
采用Token方式进行用户认证的基本流程如下图所示:
用户输入用户名,密码等验证信息,向服务器发起登录请求服务器端验证用户登录信息,生成JWT token服务器端将Token返回给客户端,客户端保存在本地(一般以Cookie的方式保存)客户端向服务器端发送访问请求,请求中携带之前颁发的Token服务器端验证Token,确认用户的身份和对资源的访问权限,并进行相应的处理(拒绝或者允许访问) data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWNgYGBgAAAABQABh6FO1AAAAABJRU5ErkJggg==



采用Token进行用户认证的流程图 
 
3、实现单点登录
 
单点登录的理念很简单,即用户只需要登录应用一次,就可以访问应用中所有的微服务。API Gateway提供了客户端访问微服务应用的入口,Token实现了无状态的用户认证。结合这两种技术,可以为微服务应用实现一个单点登录方案。
 
用户的认证流程和采用Token方式认证的基本流程类似,不同之处是加入了API Gateway作为外部请求的入口。
 
用户登录
客户端发送登录请求到API GatewayAPI Gateway将登录请求转发到Security ServiceSecurity Service验证用户身份,并颁发Token
用户请求
客户端请求发送到API GatewayAPI Gateway调用的Security Service对请求中的Token进行验证,检查用户的身份如果请求中没有Token,Token过期或者Token验证非法,则拒绝用户请求。Security Service检查用户是否具有该操作权如果用户具有该操作权限,则把请求发送到后端的Business Service,否则拒绝用户请求 data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWNgYGBgAAAABQABh6FO1AAAAABJRU5ErkJggg==



采用API Gateway和Token实现微服务应用的单点登录   
 
 
4、用户权限控制 
用户权限控制有两种做法,在API Gateway处统一处理,或者在各个微服务中单独处理。 
 
API Gateway处进行统一的权限控制
 
客户端发送的HTTP请求中包含有请求的Resource及HTTP Method。如果系统遵循REST规范,以URI资源方式对访问对象进行建模,则API Gateway可以从请求中直接截取到访问的资源及需要进行的操作,然后调用Security Service进行权限判断,根据判断结果决定用户是否有权限对该资源进行操作,并转发到后端的Business Service。这种实现方式API Gateway处统一处理鉴权逻辑,各个微服务不需要考虑用户鉴权,只需要处理业务逻辑,简化了各微服务的实现。
由各个微服务单独进行权限控制
 
如果微服务未严格遵循REST规范对访问对象进行建模,或者应用需要进行定制化的权限控制,则需要在微服务中单独对用户权限进行判断和处理。这种情况下微服务的权限控制更为灵活,但各个微服务需要单独维护用户的授权数据,实现更复杂一些。

 
 5、第三方应用接入
 
对于第三方应用接入的访问控制,有两种实现方式:
API Token
 
第三方使用一个应用颁发的API Token对应用的数据进行访问。该Token由用户在应用中生成,并提供给第三方应用使用。在这种情况下,一般只允许第三方应用访问该Token所属用户自身的数据,而不能访问其他用户的敏感私有数据。
 
例如Github就提供了Personal API Token功能,用户可以在Github的开发者设置界面中创建Token,然后使用该Token来访问Github的API。在创建Token时,可以设置该Token可以访问用户的哪些数据,如查看Repo信息,删除Repo,查看用户信息,更新用户信息等。
 
使用API Token来访问Github APIcurl -u zhaohuabing:fbdf8e8862252ed0f3ba9dba4e328c01ac93aeec https://api.github.com/user
 
使用API Token而不是直接使用用户名/密码来访问API的好处是降低了用户密码暴露的风险,并且可以随时收回Token的权限而不用修改密码。
 
由于API Token只能访问指定用户的数据,因此适合于用户自己开发一些脚本或小程序对应用中自己的数据进行操作。
 
OAuth
 
某些第三方应用需要访问不同用户的数据,或者对多个用户的数据进行整合处理,则可以考虑采用OAuth。采用OAuth,当第三方应用访问服务时,应用会提示用户授权第三方应用相应的访问权限,根据用户的授权操作结果生成用于访问的Token,以对第三方应用的操作请求进行访问控制。
 
同样以Github为例,一些第三方应用如Travis CI,GitBook等就是通过OAuth和Github进行集成的。 OAuth针对不同场景有不同的认证流程,一个典型的认证流程如下图所示:
用户向OAuth客户端程序发起一个请求,OAuth客户端程序在处理该请求时发现需要访问用户在资源服务器中的数据。客户端程序将用户请求重定向到认证服务器,该请求中包含一个callback的URL。认证服务器返回授权页面,要求用户对OAuth客户端的资源请求进行授权。用户对该操作进行授权后,认证服务器将请求重定向到客户端程序的callback url,将授权码返回给客户端程序。客户端程序将授权码发送给认证服务器,请求token。认证服务器验证授权码后将token颁发给客户端程序。客户端程序采用颁发的token访问资源,完成用户请求。

备注:
OAuth中按照功能区分了资源服务器和认证服务器这两个角色,在实现时这两个角色常常是同一个应用。将该流程图中的各个角色对应到Github的例子中,资源服务器和认证服务器都是Github,客户端程序是Travis CI或者GitBook,用户则是使用Travis CI或者GitBook的直接用户。有人可能会疑惑在该流程中为何要使用一个授权码(Authorization Code)来申请Token,而不是由认证服务器直接返回Token给客户端。OAuth这样设计的原因是在重定向到客户端Callback URL的过程中会经过用户代理(浏览器),如果直接传递Token存在被窃取的风险。采用授权码的方式,申请Token时客户端直接和认证服务器进行交互,并且认证服务期在处理客户端的Token申请请求时还会对客户端进行身份认证,避免其他人伪造客户端身份来使用认证码申请Token。 下面是一个客户端程序采用Authorization Code来申请Token的示例,client_id和client_secret被用来验证客户端的身份。
POST /oauth/token HTTP/1.1
Host: authorization-server.com

grant_type=authorization_code
&code=xxxxxxxxxxx
&redirect_uri=https://example-app.com/redirect
&client_id=xxxxxxxxxx
&client_secret=xxxxxxxxxx

 
OAuth认证流程
 
另外在谈及OAuth时,我们需要注意微服务应用作为OAuth客户端和OAuth服务器的两种不同场景:
 
在实现微服务自身的用户认证时,也可以采用OAuth将微服务的用户认证委托给一个第三方的认证服务提供商,例如很多应用都将用户登录和微信或者QQ的OAuth服务进行了集成。
 
第三方应用接入和微服务自身用户认证采用OAuth的目的是不同的,前者是为了将微服务中用户的私有数据访问权限授权给第三方应用,微服务在OAuth架构中是认证和资源服务器的角色;而后者的目的是集成并利用知名认证提供服务商提供的OAuth认证服务,简化繁琐的注册操作,微服务在OAuth架构中是客户端的角色。
 
因此在我们需要区分这两种不同的场景,以免造成误解。
 
 
6、微服务之间的认证
 
除了来自用户和第三方的北向流量外,微服务之间还有大量的东西向流量,这些流量可能在同一个局域网中,也可能跨越不同的数据中心,这些服务间的流量存在被第三方的嗅探和攻击的危险,因此也需要进行安全控制。
 
通过双向SSL可以实现服务之间的相互身份认证,并通过TLS加密服务间的数据传输。需要为每个服务生成一个证书,服务之间通过彼此的证书进行身份验证。在微服务运行环境中,可能存在大量的微服务实例,并且微服务实例经常会动态变化,例如随着水平扩展增加服务实例。在这种情况下,为每个服务创建并分发证书变得非常困难。我们可以通过创建一个私有的证书中心(Internal PKI/CA)来为各个微服务提供证书管理如颁发、撤销、更新等。
 
 
  
五、参考
How We Solved Authentication and Authorization in Our Microservice ArchitectureHow to build your own public key infrastructureOAuth 2.0 Authorization Code RequestPKI/CA工作原理及架构深入聊聊微服务架构的身份认证问题
 
推荐阅读
实例 | 当Istio遇见Jaeger,如何解决端到端分布式追踪问题?
微服务架构之思维三部曲:What、Why、How
倍道而进:Conduit 0.3 正式从 experimental 升级到 alpha,实现生产指日可待

 
ServiceMesh中文社区:
ServiceMesh中文社区(servicemesh.cn)已上线,Istio、Conduit官方文档翻译版已在社区发布,欢迎大家登录浏览。社区翻译小组志愿者招募中,有兴趣的私信小数即可~
 
ServiceMesh微信交流群:
添加微信xiaoshu062,备注:服务网格,即可加入Service Mesh微信交流群。
  查看全部
   
作者简介:
      赵化冰是一名程序员及开源软件爱好者,目前在NFV&SDN编排开源社区ONAP担任MSB项目PTL,致力于高性能,高可用性微服务架构在编排领域的应用。
      博客链接:http://zhaohuabing.com/  
 
目录 
一、前言
二、单体应用的实现方式
三、微服务认证和鉴权面临的问题
四、微服务认证和鉴权的技术方案
1.用户身份认证
2.用户状态保持
3.实现单点登录
4.用户权限控制
  • API Gateway处进行统一的权限控制

  • 由各个微服务单独进行权限控制

5.第三方应用接入
  • API Token

  • OAuth

6.微服务之间的认证
五、参考
  
一、前言 
 
微服务架构的引入为软件应用带来了诸多好处:包括小开发团队,缩短开发周期,语言选择灵活性,增强服务伸缩能力等。与此同时,也引入了分布式系统的诸多复杂问题。其中一个挑战就是如何在微服务架构中实现一个灵活,安全,高效的认证和鉴权方案。本文将尝试就此问题进行一次比较完整的探讨。
 
 
 
二、单体应用的实现方式
 
在单体架构下,整个应用是一个进程,在应用中,一般会用一个安全模块来实现用户认证和鉴权。 用户登录时,应用的安全模块对用户身份进行验证,验证用户身份合法后,为该用户生成一个会话(Session),并为该Session关联一个唯一的编号(Session Id)。Session是应用中的一小块内存结构,其中保存了登录用户的信息,如User name, Role, Permission等。服务器把该Session的Session Id返回给客户端,客户端将Session Id以cookie或者URL重写的方式记录下来,并在后续请求中发送给应用,这样应用在接收到客户端访问请求时可以使用Session Id验证用户身份,不用每次请求时都输入用户名和密码进行身份验证


备注:为了避免Session Id被第三者截取和盗用,客户端和应用之前应使用TLS加密通信,session也会设置有过期时间。


 
1_(3).png


                          单体应用用户登录认证序列图
 
客户端访问应用时,Session Id随着HTTP请求发送到应用,客户端请求一般会通过一个拦截器处理所有收到的客户端请求。拦截器首先判断Session Id是否存在,如果该Session Id存在,就知道该用户已经登录。然后再通过查询用户权限判断用户能否执行该此请求,以实现操作鉴权。
 
2_(3).png


data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWNgYGBgAAAABQABh6FO1AAAAABJRU5ErkJggg==单体应用用户操作鉴权序列图    
 
 

三、微服务认证和鉴权面临的问题 
 
在微服务架构下,一个应用被拆分为多个微服务进程,每个微服务实现原来单体应用中一个模块的业务功能。应用拆分后,对每个微服务的访问请求都需要进行认证和鉴权。如果参考单体应用的实现方式会遇到下述问题:
  • 认证和鉴权逻辑需要在每个微服务中进行处理,需要在各个微服务中重复实现这部分公共逻辑。虽然我们可以使用代码库复用部分代码,但这又会导致所有微服务对特定代码库及其版本存在依赖,影响微服务语言/框架选择的灵活性。
  • 微服务应遵循单一职责原理,一个微服务只处理单一的业务逻辑。认证和鉴权的公共逻辑不应该放到微服务实现中。
  • 为了充分利用微服务架构的好处,实现微服务的水平扩展(Scalability)和弹性(Resiliency),微服务最好是无状态的。因此不建议使用session这种有状态的方案。
  • 微服务架构下的认证和鉴权涉及到场景更为复杂,涉及到用户访问微服务应用,第三方应用访问微服务应用,应用内多个微服务之间相互访问等多种场景,每种场景下的认证和鉴权方案都需要考虑到,以保证应用程序的安全性。 data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWNgYGBgAAAABQABh6FO1AAAAABJRU5ErkJggg==

 微服务认证和鉴权涉及到的三种场景  
  
四、微服务认证和鉴权的技术方案

  1.用户身份认证
 
一个完整的微服务应用是由多个相互独立的微服务进程组成的,对每个微服务的访问都需要进行用户认证。如果将用户认证的工作放到每个微服务中,应用的认证逻辑将会非常复杂。因此需要考虑一个SSO(单点登录)的方案,即用户只需要登录一次,就可以访问所有微服务提供的服务。 由于在微服务架构中以API Gateway作为对外提供服务的入口,因此可以考虑在API Gateway处提供统一的用户认证。
 
 2.用户状态保持
 
HTTP是一个无状态的协议,对服务器来说,用户的每次HTTP请求是相互独立的。互联网是一个巨大的分布式系统,HTTP协议作为互联网上的一个重要协议,要考虑到大量应用访问的效率问题。无状态意味着服务端可以把客户端的请求根据需要发送到集群中的任何一个节点,HTTP的无状态设计对负载均衡有明显的好处,由于没有状态,用户请求可以被分发到任意一个服务器,应用也可以在靠近用户的网络边缘部署缓存服务器。对于不需要身份认证的服务,例如浏览新闻网页等,这是没有任何问题的。但很多服务如网络购物,企业管理系统等都需要对用户的身份进行认证,因此需要在HTTP协议基础上采用一种方式保存用户的登录状态,避免用户每发起一次请求都需要进行验证。
 
传统方式是在服务器端采用Cookie来保存用户状态,由于在服务器是有状态的,对服务器的水平扩展有影响。在微服务架构下建议采用Token来记录用户登录状态。
 
Token和Seesion主要的不同点是存储的地方不同。Session是集中存储在服务器中的;而Token是用户自己持有的,一般以cookie的形式存储在浏览器中。Token中保存了用户的身份信息,每次请求都会发送给服务器,服务器因此可以判断访问者的身份,并判断其对请求的资源有没有访问权限。
 
Token用于表明用户身份,因此需要对其内容进行加密,避免被请求方或者第三者篡改。JWT(Json Web Token)是一个定义Token格式的开放标准(RFC 7519),定义了Token的内容,加密方式,并提供了各种语言的lib。
 
JWT Token的结构非常简单,包括三部分:
  • Header头部包含类型,为固定值JWT。然后是JWT使用的Hash算法。
  • {"alg": "HS256","typ": "JWT"}
  • Payload包含发布者,过期时间,用户名等标准信息,也可以添加用户角色,用户自定义的信息。
    {"sub": "1234567890","name": "John Doe","admin": true}
  • SignatureToken颁发方的签名,用于客户端验证Token颁发方的身份,也用于服务器防止Token被篡改。 签名算法
    HMACSHA256(base64UrlEncode(header) + "." +base64UrlEncode(payload),secret)

 
这三部分使用Base64编码后组合在一起,成为最终返回给客户端的Token串,每部分之间采用”.”分隔。下图是上面例子最终形成的Token
data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWNgYGBgAAAABQABh6FO1AAAAABJRU5ErkJggg==
采用Token进行用户认证,服务器端不再保存用户状态,客户端每次请求时都需要将Token发送到服务器端进行身份验证。Token发送的方式rfc6750进行了规定,采用一个 Authorization: Bearer HHTP Header进行发送。
Authorization: Bearer mF_9.B5f-4.1JqM

 
采用Token方式进行用户认证的基本流程如下图所示:
  1. 用户输入用户名,密码等验证信息,向服务器发起登录请求
  2. 服务器端验证用户登录信息,生成JWT token
  3. 服务器端将Token返回给客户端,客户端保存在本地(一般以Cookie的方式保存)
  4. 客户端向服务器端发送访问请求,请求中携带之前颁发的Token
  5. 服务器端验证Token,确认用户的身份和对资源的访问权限,并进行相应的处理(拒绝或者允许访问) data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWNgYGBgAAAABQABh6FO1AAAAABJRU5ErkJggg==
    5_(2).png

采用Token进行用户认证的流程图 
 
3、实现单点登录
 
单点登录的理念很简单,即用户只需要登录应用一次,就可以访问应用中所有的微服务。API Gateway提供了客户端访问微服务应用的入口,Token实现了无状态的用户认证。结合这两种技术,可以为微服务应用实现一个单点登录方案。
 
用户的认证流程和采用Token方式认证的基本流程类似,不同之处是加入了API Gateway作为外部请求的入口。
 
用户登录
  1. 客户端发送登录请求到API Gateway
  2. API Gateway将登录请求转发到Security Service
  3. Security Service验证用户身份,并颁发Token

用户请求
  1. 客户端请求发送到API Gateway
  2. API Gateway调用的Security Service对请求中的Token进行验证,检查用户的身份
  3. 如果请求中没有Token,Token过期或者Token验证非法,则拒绝用户请求。
  4. Security Service检查用户是否具有该操作权
  5. 如果用户具有该操作权限,则把请求发送到后端的Business Service,否则拒绝用户请求 data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWNgYGBgAAAABQABh6FO1AAAAABJRU5ErkJggg==
    api-gateway-sso.png

采用API Gateway和Token实现微服务应用的单点登录   
 
 
4、用户权限控制 
用户权限控制有两种做法,在API Gateway处统一处理,或者在各个微服务中单独处理。 
 
  • API Gateway处进行统一的权限控制

 
客户端发送的HTTP请求中包含有请求的Resource及HTTP Method。如果系统遵循REST规范,以URI资源方式对访问对象进行建模,则API Gateway可以从请求中直接截取到访问的资源及需要进行的操作,然后调用Security Service进行权限判断,根据判断结果决定用户是否有权限对该资源进行操作,并转发到后端的Business Service。这种实现方式API Gateway处统一处理鉴权逻辑,各个微服务不需要考虑用户鉴权,只需要处理业务逻辑,简化了各微服务的实现。
  • 由各个微服务单独进行权限控制

 
如果微服务未严格遵循REST规范对访问对象进行建模,或者应用需要进行定制化的权限控制,则需要在微服务中单独对用户权限进行判断和处理。这种情况下微服务的权限控制更为灵活,但各个微服务需要单独维护用户的授权数据,实现更复杂一些。

 
 5、第三方应用接入
 
对于第三方应用接入的访问控制,有两种实现方式:
  • API Token

 
第三方使用一个应用颁发的API Token对应用的数据进行访问。该Token由用户在应用中生成,并提供给第三方应用使用。在这种情况下,一般只允许第三方应用访问该Token所属用户自身的数据,而不能访问其他用户的敏感私有数据。
 
例如Github就提供了Personal API Token功能,用户可以在Github的开发者设置界面中创建Token,然后使用该Token来访问Github的API。在创建Token时,可以设置该Token可以访问用户的哪些数据,如查看Repo信息,删除Repo,查看用户信息,更新用户信息等。
 
使用API Token来访问Github API
curl -u zhaohuabing:fbdf8e8862252ed0f3ba9dba4e328c01ac93aeec https://api.github.com/user

 
使用API Token而不是直接使用用户名/密码来访问API的好处是降低了用户密码暴露的风险,并且可以随时收回Token的权限而不用修改密码。
 
由于API Token只能访问指定用户的数据,因此适合于用户自己开发一些脚本或小程序对应用中自己的数据进行操作。
 
  • OAuth

 
某些第三方应用需要访问不同用户的数据,或者对多个用户的数据进行整合处理,则可以考虑采用OAuth。采用OAuth,当第三方应用访问服务时,应用会提示用户授权第三方应用相应的访问权限,根据用户的授权操作结果生成用于访问的Token,以对第三方应用的操作请求进行访问控制。
 
同样以Github为例,一些第三方应用如Travis CI,GitBook等就是通过OAuth和Github进行集成的。 OAuth针对不同场景有不同的认证流程,一个典型的认证流程如下图所示:
  • 用户向OAuth客户端程序发起一个请求,OAuth客户端程序在处理该请求时发现需要访问用户在资源服务器中的数据。
  • 客户端程序将用户请求重定向到认证服务器,该请求中包含一个callback的URL。
  • 认证服务器返回授权页面,要求用户对OAuth客户端的资源请求进行授权。
  • 用户对该操作进行授权后,认证服务器将请求重定向到客户端程序的callback url,将授权码返回给客户端程序。
  • 客户端程序将授权码发送给认证服务器,请求token。
  • 认证服务器验证授权码后将token颁发给客户端程序。
  • 客户端程序采用颁发的token访问资源,完成用户请求。


备注:

  1. OAuth中按照功能区分了资源服务器和认证服务器这两个角色,在实现时这两个角色常常是同一个应用。将该流程图中的各个角色对应到Github的例子中,资源服务器和认证服务器都是Github,客户端程序是Travis CI或者GitBook,用户则是使用Travis CI或者GitBook的直接用户。
  2. 有人可能会疑惑在该流程中为何要使用一个授权码(Authorization Code)来申请Token,而不是由认证服务器直接返回Token给客户端。OAuth这样设计的原因是在重定向到客户端Callback URL的过程中会经过用户代理(浏览器),如果直接传递Token存在被窃取的风险。采用授权码的方式,申请Token时客户端直接和认证服务器进行交互,并且认证服务期在处理客户端的Token申请请求时还会对客户端进行身份认证,避免其他人伪造客户端身份来使用认证码申请Token。 下面是一个客户端程序采用Authorization Code来申请Token的示例,client_id和client_secret被用来验证客户端的身份。

POST /oauth/token HTTP/1.1
Host: authorization-server.com

grant_type=authorization_code
&code=xxxxxxxxxxx
&redirect_uri=https://example-app.com/redirect
&client_id=xxxxxxxxxx
&client_secret=xxxxxxxxxx


 
OAuth认证流程
 
另外在谈及OAuth时,我们需要注意微服务应用作为OAuth客户端和OAuth服务器的两种不同场景:
 
在实现微服务自身的用户认证时,也可以采用OAuth将微服务的用户认证委托给一个第三方的认证服务提供商,例如很多应用都将用户登录和微信或者QQ的OAuth服务进行了集成。
 
第三方应用接入和微服务自身用户认证采用OAuth的目的是不同的,前者是为了将微服务中用户的私有数据访问权限授权给第三方应用,微服务在OAuth架构中是认证和资源服务器的角色;而后者的目的是集成并利用知名认证提供服务商提供的OAuth认证服务,简化繁琐的注册操作,微服务在OAuth架构中是客户端的角色。
 
因此在我们需要区分这两种不同的场景,以免造成误解。
 
 
6、微服务之间的认证
 
除了来自用户和第三方的北向流量外,微服务之间还有大量的东西向流量,这些流量可能在同一个局域网中,也可能跨越不同的数据中心,这些服务间的流量存在被第三方的嗅探和攻击的危险,因此也需要进行安全控制。
 
通过双向SSL可以实现服务之间的相互身份认证,并通过TLS加密服务间的数据传输。需要为每个服务生成一个证书,服务之间通过彼此的证书进行身份验证。在微服务运行环境中,可能存在大量的微服务实例,并且微服务实例经常会动态变化,例如随着水平扩展增加服务实例。在这种情况下,为每个服务创建并分发证书变得非常困难。我们可以通过创建一个私有的证书中心(Internal PKI/CA)来为各个微服务提供证书管理如颁发、撤销、更新等。
 
 
  
五、参考
  • How We Solved Authentication and Authorization in Our Microservice Architecture
  • How to build your own public key infrastructure
  • OAuth 2.0 Authorization Code Request
  • PKI/CA工作原理及架构
  • 深入聊聊微服务架构的身份认证问题

 
推荐阅读
实例 | 当Istio遇见Jaeger,如何解决端到端分布式追踪问题?
微服务架构之思维三部曲:What、Why、How
倍道而进:Conduit 0.3 正式从 experimental 升级到 alpha,实现生产指日可待

 
ServiceMesh中文社区:
ServiceMesh中文社区(servicemesh.cn)已上线,Istio、Conduit官方文档翻译版已在社区发布,欢迎大家登录浏览。社区翻译小组志愿者招募中,有兴趣的私信小数即可~
 
ServiceMesh微信交流群:
添加微信xiaoshu062,备注:服务网格,即可加入Service Mesh微信交流群。
 

实例 | 当Istio遇见Jaeger,如何解决端到端分布式追踪问题?

Istio小数 发表了文章 • 0 个评论 • 505 次浏览 • 2018-03-01 10:05 • 来自相关话题

作者:Steven Cheng

译者:王晓轩

原文:When Istio Meets Jaeger — An Example of End-to-end Distributed Tracing









译者话:

       本文从微服务架构为何引入开始,介绍了程序设计在使用微服务架构后存在的一些问题,以及用 service mesh 的方式如何去解决它们。

       作者从 Kuberentes 集群的安装开始,到配置 Istio 和 Jaeger,图文并茂的展示了部署结果,文章的最后部分以源码和讲解结合的方式,说明了 Istio 的大致工作原理。深入浅出,既有理论价值又有实际经验可以借鉴。


众所周知,Kubernetes 很厉害!因为它能帮助很多工程师团队去实现 SOA(面向服务的架构体系)的梦想。在过去很长一段时间里,我们一直围绕 monolith mindset 的概念来构建我们的应用程序,也就是说,我们会在一个很牛X的计算机上运行一个应用的所有组件。像帐户管理、结算、报告生成等这些工作,都是在一个机器上用共享资源的方式运行。这种模式一直很OK,直到 SOA 的出现。它通过将应用程序拆分成一个个相对小的组件,让它们之间使用 REST 或 gRPC 进行通信。我们这么做,是希望应用程序比以前的管理方式更加容易,但后来发现,迎接我们的是一堆新的挑战(所谓愿望是丰满的,现实是骨感的)。跨服务之间的访问如何通信?如何去 observe 两个 microservices 之间的通信(如日志或 tracing)?本文演示如何在 Kubernetes 集群内部设置 OpenTracing,以便在服务之间进行 end-to-end 的 tracing,并在服务内部使用正确的工具进行 tracing。



创建kubernetes集群

首先,我们需要有一个可用的 Kubernetes 集群。我在 AWS 上使用 kops(注1),因为它提供了一系列 K8S 集群自动化操作命令,如 upgrade,scaling up/down 和多个 instance group。除了方便的集群操作之外,kops 团队还随着 Kubernetes 版本升级而升级,以支持 Kubernetes 的最新版本。我觉得这东西很酷,很有用!

按照这个步骤(注2)可以安装和使用 kops。




创建集群
kops create cluster \ 
--name steven.buffer-k8s.com \ 
--cloud aws \ 
--master-size t2.medium \
 --master-zones=us-east-1b \ 
--node-size m5.large \ 
--zones=us-east-1a,us-east-1b,us-east-1c,us-east-1d,us-east-1e,us-east-1f \ 
--node-count=2 \ 
--kubernetes-version=1.8.6 \ 
--vpc=vpc-1234567a \ 
--network-cidr=10.0.0.0/16 \ 
--networking=flannel \ 
--authorization=RBAC \ 
--ssh-public-key="~/.ssh/kube_aws_rsa.pub" \ 
--yes
 
这个命令会告诉 AWS 在 us-east-1上创建一个 VPC 1234456a,会有 1个 master 节点和 2个 worker(minion)节点,它的 CIDR (无类别域间路由,Classless Inter-Domain Routing)是10.0.0.0/16。大约10分钟后,你的集群就可以使用了。当然在此过程中,你也可以用 watch kubectl get nodes 去查看整个创建的过程。

一旦 Kubernetes 集群安装完成,你就可以在上面去安装 Istio (注3)了。它是管理一个集群内部服务之间流量的服务网格。由于它的这种特性,使得 Istio 能够很轻松的实现在两个服务之间进行 trace。



安装Istio

从 GitHub repo(注4)下载 Istio。

在你下载的 Istio 目录中可以找到 istio.yaml 文件,运行: 

kubectl apply -f install/kubernetes/istio.yaml

现在你的 Istio 应该已经运行在 Kubernetes 集群里了。而且它应该同时创建了一个 Nignx 的 Ingress Controller,这个东西是用来接收外面对集群内资源的访问的。我们一会儿会介绍如何设置 IP。



安装Jaeger

Jaeger 和 Istio 一起协同工作,可以实现跨服务的 tracing。你可以用这个命令安装 Jaege。

kubectl create -n istio-system -fhttps://raw.githubusercontent. ... e.yml


完成之后,你可以通过 Jaeger 的 UI 访问它 








Instrument Code

Jaeger 和 Istio 安装成功以后,你就可以看到跨服务的 traces 了。这是因为 Istio 注入了 Envoy sidecars 来处理服务间通信,而被部署的应用程序只与指定的 sidecar 进行通信。 从我的 GitHub (注5)你可以找到一个简单的应用程序例子。


main.go

package main 
import ( 
"fmt" 
"log"
 "net/http" 
"runtime" 
"time" 
 
"github.com/opentracing-contrib/go-stdlib/nethttp" opentracing "github.com/opentracing/opentracing-go" jaeger "github.com/uber/jaeger-client-go" "github.com/uber/jaeger-client-go/zipkin" )
 
 func indexHandler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "hello world, I'm running on %s with an %s CPU ", runtime.GOOS, runtime.GOARCH) } 
 
func getTimeHandler(w http.ResponseWriter, r *http.Request) { log.Print("Received getTime request") t := time.Now() ts := t.Format("Mon Jan _2 15:04:05 2006") fmt.Fprintf(w, "The time is %s", ts) } func main() { zipkinPropagator := zipkin.NewZipkinB3HTTPHeaderPropagator() injector := jaeger.TracerOptions.Injector(opentracing.HTTPHeaders, zipkinPropagator) extractor := jaeger.TracerOptions.Extractor(opentracing.HTTPHeaders, zipkinPropagator) // Zipkin shares span ID between client and server spans; it must be enabled via the following option. zipkinSharedRPCSpan := jaeger.TracerOptions.ZipkinSharedRPCSpan(true) sender, _ := jaeger.NewUDPTransport("jaeger-agent.istio-system:5775", 0) tracer, closer := jaeger.NewTracer( "myhelloworld", jaeger.NewConstSampler(true), jaeger.NewRemoteReporter( sender, jaeger.ReporterOptions.BufferFlushInterval(1*time.Second)), injector, extractor, zipkinSharedRPCSpan, ) defer closer.Close() http.HandleFunc("/", indexHandler) http.HandleFunc("/gettime", getTimeHandler) http.ListenAndServe( ":8080", nethttp.Middleware(tracer, http.DefaultServeMux))


从第28-30行开始,我们创建了一个 Zipkin propagator,告诉 Jaeger 从 OpenZipkin 的 request header 中捕捉上下文(context)。你可能会问,这些 header 是怎么被放到 request 开始部分的?还记得吗,当我说 Istio 用 sidecar 处理服务间的通信,并且应用程序只与它交互。对!你可能已经猜到了。为了让 Istio 跟踪服务之间的 request,当有 request 进入集群时,Istio 的 Ingress Controller 将注入一组 header。然后,它通过 Envoy sidecars 进行传播,并且每个都会将相关的 associated span 上报给 Jaeger。它会让 spana 对应到每一个 trace。我们的应用程序代码利用这些 header来收集内部服务之间的 spans。




下面是一个被 Istio 的 Ingress Controller 注入到 OpenZipkin 中 header的列表

x-request-id
x-b3-traceid 
x-b3-spanid 
x-b3-parentspanid 
x-b3-sampled 
x-b3-flags 
x-ot-span-context

可以用下面这个 yaml 文件去部署一个简单的应用程序


apiVersion: extensions/v1beta1 
kind: Deployment 
metadata:  
labels:    
app: myhelloworld  
name: myhelloworld
 spec:  
replicas: 1  
template:    
metadata:      
labels:        
app: myhelloworld    
spec:      
containers:     
 - image: stevenc81/jaeger-tracing-example:0.1        
imagePullPolicy: Always        
name: myhelloworld        
ports:       
 - containerPort: 8080      
restartPolicy: Always 
--- 
apiVersion: v1 
kind: Service 
metadata:  
name: myhelloworld  
labels:    
app: myhelloworld 
spec:  
type: NodePort 
ports:  
- port: 80    
targetPort: 8080   
 name: http  
selector:    
app: myhelloworld 
--- 
apiVersion: extensions/v1beta1 
kind: Ingress 
metadata:  
name: myhelloworld  
annotations:    
kubernetes.io/ingress.class: "istio" 
spec:  
rules:  
- http:      
paths:     
 - path: /        
backend:          
serviceName: myhelloworld          
servicePort: 80      
- path: /gettime        
backend:          
serviceName: myhelloworld         
servicePort: 80



部署

kubectl apply -f <(istioctl kube-inject -f myhelloword.yaml)

请注意,可以从 Istio 的 bin 目录下找到命令istioctl

现在是收获的时候了,当我们向 Istio Ingress Controller 发送请求时,它将在服务以及应用程序之间进行 trace。从截图中我们可以看到从不同地方报告的3个spans
Ingress Controller
 
Envoy sidecar for application 
 
Application code 








展开 trace(看到3个spans)就可以看到 end-to-end 的 tracing








结束语

SOA 带来了一些待解决问题,特别是在如何 observe 服务之间的通信上。

Istio+Jager 的集成解决方案可以从 servcie 到 service 的这个层面解决这个问题。

使用 OpenZipkin prapagator 配合 Jaeger,可以在 end-to-end 上 tracing。







注:

1、 https://github.com/kubernetes/kops

2、https://github.com/kubernetes/ ... ws.md

3、https://istio.io/

4、 https://github.com/istio/istio/releases/tag/0.4.0

5、https://github.com/stevenc81/j ... ample











推荐阅读倍道而进:Conduit 0.3 正式从 experimental 升级到 alpha,实现生产指日可待?




收藏篇 | 20篇精选干货,Service Mesh内容一应俱全





专题 | A Service Mesh for Kubernetes第4期:轻松预发微服务




实测 | 转型微服务,这4大工具谁是API网关性能最优?










ServiceMesh中文社区:


ServiceMesh中文社区(servicemesh.cn)已上线,Istio、Conduit官方文档翻译版已在社区发布,欢迎大家登录浏览。点击阅读原文即可浏览!社区翻译小组志愿者招募中,有兴趣的私信小数即可~




ServiceMesh微信交流群:

添加微信xiaoshu062,备注:服务网格,即可加入Service Mesh微信交流群。 查看全部
作者:Steven Cheng

译者:王晓轩

原文:When Istio Meets Jaeger — An Example of End-to-end Distributed Tracing


v2-23e62a9f48d307dcbbbe3aa09934ea63_hd.jpg




译者话:

       本文从微服务架构为何引入开始,介绍了程序设计在使用微服务架构后存在的一些问题,以及用 service mesh 的方式如何去解决它们。

       作者从 Kuberentes 集群的安装开始,到配置 Istio 和 Jaeger,图文并茂的展示了部署结果,文章的最后部分以源码和讲解结合的方式,说明了 Istio 的大致工作原理。深入浅出,既有理论价值又有实际经验可以借鉴。


众所周知,Kubernetes 很厉害!因为它能帮助很多工程师团队去实现 SOA(面向服务的架构体系)的梦想。在过去很长一段时间里,我们一直围绕 monolith mindset 的概念来构建我们的应用程序,也就是说,我们会在一个很牛X的计算机上运行一个应用的所有组件。像帐户管理、结算、报告生成等这些工作,都是在一个机器上用共享资源的方式运行。这种模式一直很OK,直到 SOA 的出现。它通过将应用程序拆分成一个个相对小的组件,让它们之间使用 REST 或 gRPC 进行通信。我们这么做,是希望应用程序比以前的管理方式更加容易,但后来发现,迎接我们的是一堆新的挑战(所谓愿望是丰满的,现实是骨感的)。跨服务之间的访问如何通信?如何去 observe 两个 microservices 之间的通信(如日志或 tracing)?本文演示如何在 Kubernetes 集群内部设置 OpenTracing,以便在服务之间进行 end-to-end 的 tracing,并在服务内部使用正确的工具进行 tracing。



创建kubernetes集群

首先,我们需要有一个可用的 Kubernetes 集群。我在 AWS 上使用 kops(注1),因为它提供了一系列 K8S 集群自动化操作命令,如 upgrade,scaling up/down 和多个 instance group。除了方便的集群操作之外,kops 团队还随着 Kubernetes 版本升级而升级,以支持 Kubernetes 的最新版本。我觉得这东西很酷,很有用!

按照这个步骤(注2)可以安装和使用 kops。




创建集群
kops create cluster \ 
--name steven.buffer-k8s.com \ 
--cloud aws \ 
--master-size t2.medium \
 --master-zones=us-east-1b \ 
--node-size m5.large \ 
--zones=us-east-1a,us-east-1b,us-east-1c,us-east-1d,us-east-1e,us-east-1f \ 
--node-count=2 \ 
--kubernetes-version=1.8.6 \ 
--vpc=vpc-1234567a \ 
--network-cidr=10.0.0.0/16 \ 
--networking=flannel \ 
--authorization=RBAC \ 
--ssh-public-key="~/.ssh/kube_aws_rsa.pub" \ 
--yes
 
这个命令会告诉 AWS 在 us-east-1上创建一个 VPC 1234456a,会有 1个 master 节点和 2个 worker(minion)节点,它的 CIDR (无类别域间路由,Classless Inter-Domain Routing)是10.0.0.0/16。大约10分钟后,你的集群就可以使用了。当然在此过程中,你也可以用 watch kubectl get nodes 去查看整个创建的过程。

一旦 Kubernetes 集群安装完成,你就可以在上面去安装 Istio (注3)了。它是管理一个集群内部服务之间流量的服务网格。由于它的这种特性,使得 Istio 能够很轻松的实现在两个服务之间进行 trace。



安装Istio

从 GitHub repo(注4)下载 Istio。

在你下载的 Istio 目录中可以找到 istio.yaml 文件,运行: 

kubectl apply -f install/kubernetes/istio.yaml

现在你的 Istio 应该已经运行在 Kubernetes 集群里了。而且它应该同时创建了一个 Nignx 的 Ingress Controller,这个东西是用来接收外面对集群内资源的访问的。我们一会儿会介绍如何设置 IP。



安装Jaeger

Jaeger 和 Istio 一起协同工作,可以实现跨服务的 tracing。你可以用这个命令安装 Jaege。

kubectl create -n istio-system -fhttps://raw.githubusercontent. ... e.yml


完成之后,你可以通过 Jaeger 的 UI 访问它 

微信图片_20180301095317.jpg




Instrument Code

Jaeger 和 Istio 安装成功以后,你就可以看到跨服务的 traces 了。这是因为 Istio 注入了 Envoy sidecars 来处理服务间通信,而被部署的应用程序只与指定的 sidecar 进行通信。 从我的 GitHub (注5)你可以找到一个简单的应用程序例子。


main.go

package main 
import ( 
"fmt" 
"log"
 "net/http" 
"runtime" 
"time" 
 
"github.com/opentracing-contrib/go-stdlib/nethttp" opentracing "github.com/opentracing/opentracing-go" jaeger "github.com/uber/jaeger-client-go" "github.com/uber/jaeger-client-go/zipkin" )
 
 func indexHandler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "hello world, I'm running on %s with an %s CPU ", runtime.GOOS, runtime.GOARCH) } 
 
func getTimeHandler(w http.ResponseWriter, r *http.Request) { log.Print("Received getTime request") t := time.Now() ts := t.Format("Mon Jan _2 15:04:05 2006") fmt.Fprintf(w, "The time is %s", ts) } func main() { zipkinPropagator := zipkin.NewZipkinB3HTTPHeaderPropagator() injector := jaeger.TracerOptions.Injector(opentracing.HTTPHeaders, zipkinPropagator) extractor := jaeger.TracerOptions.Extractor(opentracing.HTTPHeaders, zipkinPropagator) // Zipkin shares span ID between client and server spans; it must be enabled via the following option. zipkinSharedRPCSpan := jaeger.TracerOptions.ZipkinSharedRPCSpan(true) sender, _ := jaeger.NewUDPTransport("jaeger-agent.istio-system:5775", 0) tracer, closer := jaeger.NewTracer( "myhelloworld", jaeger.NewConstSampler(true), jaeger.NewRemoteReporter( sender, jaeger.ReporterOptions.BufferFlushInterval(1*time.Second)), injector, extractor, zipkinSharedRPCSpan, ) defer closer.Close() http.HandleFunc("/", indexHandler) http.HandleFunc("/gettime", getTimeHandler) http.ListenAndServe( ":8080", nethttp.Middleware(tracer, http.DefaultServeMux))


从第28-30行开始,我们创建了一个 Zipkin propagator,告诉 Jaeger 从 OpenZipkin 的 request header 中捕捉上下文(context)。你可能会问,这些 header 是怎么被放到 request 开始部分的?还记得吗,当我说 Istio 用 sidecar 处理服务间的通信,并且应用程序只与它交互。对!你可能已经猜到了。为了让 Istio 跟踪服务之间的 request,当有 request 进入集群时,Istio 的 Ingress Controller 将注入一组 header。然后,它通过 Envoy sidecars 进行传播,并且每个都会将相关的 associated span 上报给 Jaeger。它会让 spana 对应到每一个 trace。我们的应用程序代码利用这些 header来收集内部服务之间的 spans。




下面是一个被 Istio 的 Ingress Controller 注入到 OpenZipkin 中 header的列表

x-request-id
x-b3-traceid 
x-b3-spanid 
x-b3-parentspanid 
x-b3-sampled 
x-b3-flags 
x-ot-span-context

可以用下面这个 yaml 文件去部署一个简单的应用程序


apiVersion: extensions/v1beta1 
kind: Deployment 
metadata:  
labels:    
app: myhelloworld  
name: myhelloworld
 spec:  
replicas: 1  
template:    
metadata:      
labels:        
app: myhelloworld    
spec:      
containers:     
 - image: stevenc81/jaeger-tracing-example:0.1        
imagePullPolicy: Always        
name: myhelloworld        
ports:       
 - containerPort: 8080      
restartPolicy: Always 
--- 
apiVersion: v1 
kind: Service 
metadata:  
name: myhelloworld  
labels:    
app: myhelloworld 
spec:  
type: NodePort 
ports:  
- port: 80    
targetPort: 8080   
 name: http  
selector:    
app: myhelloworld 
--- 
apiVersion: extensions/v1beta1 
kind: Ingress 
metadata:  
name: myhelloworld  
annotations:    
kubernetes.io/ingress.class: "istio" 
spec:  
rules:  
- http:      
paths:     
 - path: /        
backend:          
serviceName: myhelloworld          
servicePort: 80      
- path: /gettime        
backend:          
serviceName: myhelloworld         
servicePort: 80



部署

kubectl apply -f <(istioctl kube-inject -f myhelloword.yaml)

请注意,可以从 Istio 的 bin 目录下找到命令istioctl

现在是收获的时候了,当我们向 Istio Ingress Controller 发送请求时,它将在服务以及应用程序之间进行 trace。从截图中我们可以看到从不同地方报告的3个spans
  • Ingress Controller

 
  • Envoy sidecar for application 

 
  • Application code 



微信图片_20180301095354.jpg



展开 trace(看到3个spans)就可以看到 end-to-end 的 tracing

微信图片_20180301095412.jpg




结束语

SOA 带来了一些待解决问题,特别是在如何 observe 服务之间的通信上。

Istio+Jager 的集成解决方案可以从 servcie 到 service 的这个层面解决这个问题。

使用 OpenZipkin prapagator 配合 Jaeger,可以在 end-to-end 上 tracing。







注:

1、 https://github.com/kubernetes/kops

2、https://github.com/kubernetes/ ... ws.md

3、https://istio.io/

4、 https://github.com/istio/istio/releases/tag/0.4.0

5、https://github.com/stevenc81/j ... ample











推荐阅读倍道而进:Conduit 0.3 正式从 experimental 升级到 alpha,实现生产指日可待?




收藏篇 | 20篇精选干货,Service Mesh内容一应俱全





专题 | A Service Mesh for Kubernetes第4期:轻松预发微服务




实测 | 转型微服务,这4大工具谁是API网关性能最优?










ServiceMesh中文社区:


ServiceMesh中文社区(servicemesh.cn)已上线,Istio、Conduit官方文档翻译版已在社区发布,欢迎大家登录浏览。点击阅读原文即可浏览!社区翻译小组志愿者招募中,有兴趣的私信小数即可~




ServiceMesh微信交流群:

添加微信xiaoshu062,备注:服务网格,即可加入Service Mesh微信交流群。

微服务架构之思维三部曲:What、Why、How

ServiceMesh小数 发表了文章 • 0 个评论 • 571 次浏览 • 2018-02-27 10:02 • 来自相关话题

 
 
What:什么是微服务? 
 
某百科对微服务架构的定义和阐述:
 
微服务可以在“自己的程序”中运行,并通过“轻量级设备与 HTTP 型 API 进行沟通”。关键在于该服务可以在自己的程序中运行。通过这一点我们就可以将服务公开与微服务架构(在现有系统中分布一个API)区分开来。在服务公开中,许多服务都可以被内部独立进程所限制。如果其中任何一个服务需要增加某种功能,那么就必须缩小进程范围。在微服务架构中,只需要在特定的某种服务中增加所需功能,而不影响整体进程。
 
定义总是晦涩些,如果将微服务拆开理解就简单许多:
 
微:它基于单一责任的“微小”功能模块,这些微小模块从前端 WEB UI,到控制层、逻辑层、数据库访问以及数据库都可以是完全独立的一整套。——独立部署、互相隔离
 
服务:业务被拆分成多个“微小”服务模块,这些模块之间通过使用轻量的通讯协议和简单的数据结构沟通(通常可采用 http+json),因此,每个微小模块需要消费外部其它微小模块暴露的服务,同时还需对外提供服务。——我为人人,人人为我  
Why:为什么需要微服务
 
在讨论为什么的问题之前,我们先回顾一下服务化架构的演进。
 
data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWNgYGBgAAAABQABh6FO1AAAAABJRU5ErkJggg==





图1  服务化架构演进图
 
从图1中我们可知,随着互联网的发展,网站应用的规模不断扩大,微服务之前的架构面临着多方面的挑战:
代码重复率高,模块过度依赖。共享困难,公共类库维护成本高。需求变更困难,新业务快速交付难。可扩展性差,功能模块按需扩展难。运维成本高,测试、部署成本高。
 
简单总结各个演进架构(包括微服务)的优缺点,如下表格所示:
 





其实,在软件开发里,不同的架构并没有哪个更好的说法。对于架构的选型,只有合适与不合适之说。比如,简单的小型应用开发,就可直接使用单体架构设计,直接打包,方便部署,容易测试,响应迅速。所以,我们应该结合对技术和业务的理解,选择更符合我们的目标架构。
 
 
 
How:怎么用微服务
 
从上文我们知道微服务能给我们带来众多好处,尤其对于较大规模的应用开发在业务大规模爬升时,微服务的架构的优势更加凸显:1、开发效率更高。2、沟通成本更低。3、响应速度更快。4、迭代周期更短。
 
那如何应用微服务呢?需要做哪些准备工作?下面从五个方面来谈:
 
1、单体架构拆分
下面这张老外的抽象“拆分图”,从三个维度概括了一个系统的扩展过程:
 
 

x轴,水平复制,即在负载均衡服务器后增加多个WEB服务器,实现分布式部署;z轴扩展,是对数据库的扩展,即分库分表(分库是将关系紧密的表放在一台数据库服务器上,分表是因为一张表的数据太多,需要将一张表的数据通过hash放在不同的数据库服务器上);y轴扩展,是功能分解,将不同职能的模块分成不同的服务。从y轴这个方向扩展,能将巨型应用分解为一组不同的服务。不同服务使用不同的数据,与外部交互通过消息或 API,每个服务设计需要把握“微”的度,不宜在基础功能上做过多堆叠,否则每个微服务组件可能又变成大的单体应用。
2、服务治理
服务治理依赖底层的技术支持,需要做好很多必要的技术知识储备。
 
搭建微服务总线和通讯机制
这个问题涉及到几个方面,如服务注册、服务发现、服务调用。阿里开源的 Dubbo 框架就是一种微服务框架,它借助 Zookeeper 等多种注册中心实现对 Provider 服务的注册,并且提供服务发现功能。Dubbo 支持 Hessian、WebService、Thrift 等方式的 RPC 远程服务调用,此外当当的 Dubbox(由 Dubbo 扩展新功能而成,即 DubboeXtensions)还支持 RESTAPI 的服务调用方式。事实上更地道的微服务架构会采用基于异步通信的调用。在异步通信中,各服务间彼此依赖,但不会因相互等待结果而导致响应速度缓慢。因此,如果一项服务发生故障,其不会影响到其它服务,瓶颈与单点故障问题也将不复存在。
 
负载均衡
Dubbo 提供的 ConfigServer 的原理,就可知道如何保证微服务系统的负载均衡和整体的可靠性问题了。Dubbo 的配置中心和每个 Server/Client 之间会作一个实时的心跳检测,收集并更新每个Server提供的服务的信息和每个 Client 的信息。每个 Server 启动时,主动与 ConfigServer 建立连接,并将自己的 IP,提供的服务名称,端口等信息直接发送给ConfigServer,ConfigServer 会更新服务列表。Client 在使用服务的时候根据服务名称去ConfigServer 中获取服务提供者信息,后面就可以直接调用服务了。当有多个服务提供者的时候,Client根据一定的规则来进行负载均衡,如轮询、随机、按权重等。一旦 Client 使用的服务它对应的服务提供者有变化,ConfigServer 就会把最新的服务提供者列表推送给 Client,Client 重新建立连接。
 
3、自动化测试
微服务一个明显的表象就是随着业务规模的扩大,服务将会增多、增强。传统的测试模式就会遇到瓶颈,为了保证高效的迭代,尽量做到更多的环节实现自动化。
 
4、自动运维
微服务拆分之后,每个服务都可以独立打包、发布、部署、启停、扩容和升级,核心服务独立集群部署,进而言之应该是随时随地可以升级。尤其当互联网发展到今天,业务要保持对市场变化的一个高效响应,自动化运维就是提升交付速度的一个重要环节。
 
5、监控
包括硬件环境、服务状态、系统健康度、接口调用情况、异常的实时告警以及潜在问题的事先预警等等。监控在实施微服务过程中会重要到什么程度呢?一句话:没准备好监控,就不要搞微服务。
 
  
微服务不是银弹?  软件领域没有银弹,微服务带来了很多收益,同时它也引入了很多问题,总结以下几点供将准备搞微服务架构的同学们思考。
 
时延问题,服务之间远程通信增加的性能损耗。事务一致性,有逻辑关联的多个数据库操作被分布到多个独立的服务中,在分布式环境下引起的事务一致性问题。[size=14]问题定位,分布式环境下,问题定位和日志检索。[/size]测试运维难度增大,跨服务的测试将更复杂,运维工作更具挑战。  查看全部


1518159112.png

 
 
What:什么是微服务? 
 
某百科对微服务架构的定义和阐述:
 
微服务可以在“自己的程序”中运行,并通过“轻量级设备与 HTTP 型 API 进行沟通”。关键在于该服务可以在自己的程序中运行。通过这一点我们就可以将服务公开与微服务架构(在现有系统中分布一个API)区分开来。在服务公开中,许多服务都可以被内部独立进程所限制。如果其中任何一个服务需要增加某种功能,那么就必须缩小进程范围。在微服务架构中,只需要在特定的某种服务中增加所需功能,而不影响整体进程。
 
定义总是晦涩些,如果将微服务拆开理解就简单许多:
 
  • 微:它基于单一责任的“微小”功能模块,这些微小模块从前端 WEB UI,到控制层、逻辑层、数据库访问以及数据库都可以是完全独立的一整套。——独立部署、互相隔离

 
  • 服务:业务被拆分成多个“微小”服务模块,这些模块之间通过使用轻量的通讯协议和简单的数据结构沟通(通常可采用 http+json),因此,每个微小模块需要消费外部其它微小模块暴露的服务,同时还需对外提供服务。——我为人人,人人为我  

Why:为什么需要微服务
 
在讨论为什么的问题之前,我们先回顾一下服务化架构的演进。
 
data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWNgYGBgAAAABQABh6FO1AAAAABJRU5ErkJggg==
微信图片_20180227101557.jpg


图1  服务化架构演进图
 
从图1中我们可知,随着互联网的发展,网站应用的规模不断扩大,微服务之前的架构面临着多方面的挑战:
  • 代码重复率高,模块过度依赖。
  • 共享困难,公共类库维护成本高。
  • 需求变更困难,新业务快速交付难。
  • 可扩展性差,功能模块按需扩展难。
  • 运维成本高,测试、部署成本高。

 
简单总结各个演进架构(包括微服务)的优缺点,如下表格所示:
 
微信图片_20180227101621.jpg


其实,在软件开发里,不同的架构并没有哪个更好的说法。对于架构的选型,只有合适与不合适之说。比如,简单的小型应用开发,就可直接使用单体架构设计,直接打包,方便部署,容易测试,响应迅速。所以,我们应该结合对技术和业务的理解,选择更符合我们的目标架构。
 
 
 
How:怎么用微服务
 
从上文我们知道微服务能给我们带来众多好处,尤其对于较大规模的应用开发在业务大规模爬升时,微服务的架构的优势更加凸显:1、开发效率更高。2、沟通成本更低。3、响应速度更快。4、迭代周期更短。
 
那如何应用微服务呢?需要做哪些准备工作?下面从五个方面来谈:
 
1、单体架构拆分
下面这张老外的抽象“拆分图”,从三个维度概括了一个系统的扩展过程:
 
 

  • x轴,水平复制,即在负载均衡服务器后增加多个WEB服务器,实现分布式部署;
  • z轴扩展,是对数据库的扩展,即分库分表(分库是将关系紧密的表放在一台数据库服务器上,分表是因为一张表的数据太多,需要将一张表的数据通过hash放在不同的数据库服务器上);
  • y轴扩展,是功能分解,将不同职能的模块分成不同的服务。从y轴这个方向扩展,能将巨型应用分解为一组不同的服务。不同服务使用不同的数据,与外部交互通过消息或 API,每个服务设计需要把握“微”的度,不宜在基础功能上做过多堆叠,否则每个微服务组件可能又变成大的单体应用。

2、服务治理
服务治理依赖底层的技术支持,需要做好很多必要的技术知识储备。
 
  • 搭建微服务总线和通讯机制

这个问题涉及到几个方面,如服务注册、服务发现、服务调用。阿里开源的 Dubbo 框架就是一种微服务框架,它借助 Zookeeper 等多种注册中心实现对 Provider 服务的注册,并且提供服务发现功能。Dubbo 支持 Hessian、WebService、Thrift 等方式的 RPC 远程服务调用,此外当当的 Dubbox(由 Dubbo 扩展新功能而成,即 DubboeXtensions)还支持 RESTAPI 的服务调用方式。事实上更地道的微服务架构会采用基于异步通信的调用。在异步通信中,各服务间彼此依赖,但不会因相互等待结果而导致响应速度缓慢。因此,如果一项服务发生故障,其不会影响到其它服务,瓶颈与单点故障问题也将不复存在。
 
  • 负载均衡

Dubbo 提供的 ConfigServer 的原理,就可知道如何保证微服务系统的负载均衡和整体的可靠性问题了。Dubbo 的配置中心和每个 Server/Client 之间会作一个实时的心跳检测,收集并更新每个Server提供的服务的信息和每个 Client 的信息。每个 Server 启动时,主动与 ConfigServer 建立连接,并将自己的 IP,提供的服务名称,端口等信息直接发送给ConfigServer,ConfigServer 会更新服务列表。Client 在使用服务的时候根据服务名称去ConfigServer 中获取服务提供者信息,后面就可以直接调用服务了。当有多个服务提供者的时候,Client根据一定的规则来进行负载均衡,如轮询、随机、按权重等。一旦 Client 使用的服务它对应的服务提供者有变化,ConfigServer 就会把最新的服务提供者列表推送给 Client,Client 重新建立连接。
 
3、自动化测试
微服务一个明显的表象就是随着业务规模的扩大,服务将会增多、增强。传统的测试模式就会遇到瓶颈,为了保证高效的迭代,尽量做到更多的环节实现自动化。
 
4、自动运维
微服务拆分之后,每个服务都可以独立打包、发布、部署、启停、扩容和升级,核心服务独立集群部署,进而言之应该是随时随地可以升级。尤其当互联网发展到今天,业务要保持对市场变化的一个高效响应,自动化运维就是提升交付速度的一个重要环节。
 
5、监控
包括硬件环境、服务状态、系统健康度、接口调用情况、异常的实时告警以及潜在问题的事先预警等等。监控在实施微服务过程中会重要到什么程度呢?一句话:没准备好监控,就不要搞微服务。
 
  
微服务不是银弹?  软件领域没有银弹,微服务带来了很多收益,同时它也引入了很多问题,总结以下几点供将准备搞微服务架构的同学们思考。
 
  • 时延问题,服务之间远程通信增加的性能损耗。
  • 事务一致性,有逻辑关联的多个数据库操作被分布到多个独立的服务中,在分布式环境下引起的事务一致性问题。
  • [size=14]问题定位,分布式环境下,问题定位和日志检索。[/size]
  • 测试运维难度增大,跨服务的测试将更复杂,运维工作更具挑战。 

倍道而进:Conduit 0.3 正式从 experimental 升级到 alpha,实现生产指日可待?

Conduit小数 发表了文章 • 0 个评论 • 358 次浏览 • 2018-02-24 10:10 • 来自相关话题

作者:WILLIAM MORGAN

翻译:崔秀龙

转自:伪架构师(公众号ID:fake-architect)

原文:Announcing Conduit 0.3 and the Conduit Roadmap









2月21号,我们荣幸的发布了 Conduit 的 0.3 版本。在这一版本中,Conduit 从experimental升级到alpha,这代表我们已经做好准备,来迎接用户的严肃测试和审查。详情可以参看 Release Notes(注 1) 。

Conduit 0.3 主要在 Conduit 的监控系统方向进行了加强,这一部分功能自动的对服务级的成功率、延迟分布以及请求量进行测量和聚合。Conduit 无需配置,能够支持 Kubernetes 1.8 和 1.9 的绝大多数应用,能够承受几百服务、几千实例、每实例几百 RPS 这样规模的负载。同样在无配置的情况下,为绝大多数的 HTTP/1.x 和 gRPC 提供了主要指标。可以将这些指标直接导出到 Prometheus(注 2) 中去。

Conduit 0.3 提供了具有负载感知能力的请求级的负载均衡,这一功能让 Conduit 能够将请求发送到具备最少排队请求的服务实例上。相对于 Kubernetes 缺省的 L4 负载均衡来说,这一方式应该能够提高应用、尤其是大负载应用的效率。

最重要的是在这一版本中,我们对 Conduit 的开发和计划进行了开放。我们发布了备受关注的路线图(注 3),开始在 Github 进行 Issue 和里程碑进展的跟踪(注 4)。我们还启动了新的邮件列表,包括 conduit-user(注 5)、conduit-dev(注 6)、以及 conduit-announce(注 7),我们会使用上述渠道对 Conduit 的开发进行计划和协调。


我们希望这些变化能够让大家更容易加入到项目之中。如果想要加入,请订阅上面提供的邮件列表,熟悉一下 Conduit README(注 8),并查看 Github 上有求助标签的 Issue(注 9)。


最后,Conduit 还只是在 Alpha 阶段,我们希望能够尽快进步。我们致力于让 Conduit 尽快进入生产就绪状态。当然这一切都取决于用户。希望用户能够在自己的 Kubernetes 应用中尝试一下 Conduit(注 10),并作出反馈,从而帮助我们更快进步。


完整的更改列表

CLI
 
CLI 命令不再依赖于 kubectlconduit dashboard 现在运行在临时端口上,消除端口8001冲突conduit inject 现在跳过带有 hostNetwork = true 的 podCLI 命令现在有更友好的错误消息,并且支持 --verbose 标志进行调试



Web UI
 
所有显示的指标现在都是即时快照,而不是在10分钟内汇总侧栏现在可以折叠UX 改进和错误修复
 
conduit 代理(数据平面)
 
代理为 HTTP 执行负载感知(P2C +最小负载)L7平衡代理现在可以路由到外部 DNS 名称当代理无法路由时,代理可以正确的对负载进行放弃操作



遥测系统
 
许多优化和改进来支持提高负载均衡能力删除单一路径和 Pod 级别指标,从而提高伸缩性和稳定性;这些指标将会在 Conduit 0.4中重新引入(#405)
 

构建方面的改进
 
Conduit docker 镜像现在小很多。Dockerfiles 已经发生变化,以充分利用缓存,大幅缩短构建时间



已知的问题
 
某些到外部域的 DNS 查找失败(#62,#155,#392)使用 WebSockets,HTTP 隧道/代理或者诸如 MySQL 和 SMTP 等协议的应用程序需要额外的配置(#339)




注:
https://github.com/runconduit/conduit/releases/tag/v0.3.0https://conduit.io/prometheushttps://conduit.io/roadmap/https://github.com/runconduit/conduit/milestoneshttps://groups.google.com/forum/#!forum/conduit-usershttps://groups.google.com/forum/#!forum/conduit-devhttps://groups.google.com/forum/#!forum/conduit-announcehttps://github.com/runconduit/conduit/blob/master/README.mdhttps://github.com/runconduit/conduit/issuesq=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22https://conduit.io/



ServiceMesh微信交流群:

添加微信xiaoshu062,备注:服务网格,即可加入Service Mesh微信交流群。 查看全部
作者:WILLIAM MORGAN

翻译:崔秀龙

转自:伪架构师(公众号ID:fake-architect)

原文:Announcing Conduit 0.3 and the Conduit Roadmap



version_conduit_030-680x341.png



2月21号,我们荣幸的发布了 Conduit 的 0.3 版本。在这一版本中,Conduit 从experimental升级到alpha,这代表我们已经做好准备,来迎接用户的严肃测试和审查。详情可以参看 Release Notes(注 1) 。

Conduit 0.3 主要在 Conduit 的监控系统方向进行了加强,这一部分功能自动的对服务级的成功率、延迟分布以及请求量进行测量和聚合。Conduit 无需配置,能够支持 Kubernetes 1.8 和 1.9 的绝大多数应用,能够承受几百服务、几千实例、每实例几百 RPS 这样规模的负载。同样在无配置的情况下,为绝大多数的 HTTP/1.x 和 gRPC 提供了主要指标。可以将这些指标直接导出到 Prometheus(注 2) 中去。

Conduit 0.3 提供了具有负载感知能力的请求级的负载均衡,这一功能让 Conduit 能够将请求发送到具备最少排队请求的服务实例上。相对于 Kubernetes 缺省的 L4 负载均衡来说,这一方式应该能够提高应用、尤其是大负载应用的效率。

最重要的是在这一版本中,我们对 Conduit 的开发和计划进行了开放。我们发布了备受关注的路线图(注 3),开始在 Github 进行 Issue 和里程碑进展的跟踪(注 4)。我们还启动了新的邮件列表,包括 conduit-user(注 5)、conduit-dev(注 6)、以及 conduit-announce(注 7),我们会使用上述渠道对 Conduit 的开发进行计划和协调。


我们希望这些变化能够让大家更容易加入到项目之中。如果想要加入,请订阅上面提供的邮件列表,熟悉一下 Conduit README(注 8),并查看 Github 上有求助标签的 Issue(注 9)。


最后,Conduit 还只是在 Alpha 阶段,我们希望能够尽快进步。我们致力于让 Conduit 尽快进入生产就绪状态。当然这一切都取决于用户。希望用户能够在自己的 Kubernetes 应用中尝试一下 Conduit(注 10),并作出反馈,从而帮助我们更快进步。


完整的更改列表

CLI
 
  • CLI 命令不再依赖于 kubectl
  • conduit dashboard 现在运行在临时端口上,消除端口8001冲突
  • conduit inject 现在跳过带有 hostNetwork = true 的 pod
  • CLI 命令现在有更友好的错误消息,并且支持 --verbose 标志进行调试




Web UI
 
  • 所有显示的指标现在都是即时快照,而不是在10分钟内汇总
  • 侧栏现在可以折叠
  • UX 改进和错误修复

 
conduit 代理(数据平面)
 
  • 代理为 HTTP 执行负载感知(P2C +最小负载)L7平衡
  • 代理现在可以路由到外部 DNS 名称
  • 当代理无法路由时,代理可以正确的对负载进行放弃操作




遥测系统
 
  • 许多优化和改进来支持提高负载均衡能力
  • 删除单一路径和 Pod 级别指标,从而提高伸缩性和稳定性;这些指标将会在 Conduit 0.4中重新引入(#405)

 

构建方面的改进
 
  • Conduit docker 镜像现在小很多。
  • Dockerfiles 已经发生变化,以充分利用缓存,大幅缩短构建时间




已知的问题
 
  • 某些到外部域的 DNS 查找失败(#62,#155,#392)
  • 使用 WebSockets,HTTP 隧道/代理或者诸如 MySQL 和 SMTP 等协议的应用程序需要额外的配置(#339)





注:
  1. https://github.com/runconduit/conduit/releases/tag/v0.3.0
  2. https://conduit.io/prometheus
  3. https://conduit.io/roadmap/
  4. https://github.com/runconduit/conduit/milestones
  5. https://groups.google.com/forum/#!forum/conduit-users
  6. https://groups.google.com/forum/#!forum/conduit-dev
  7. https://groups.google.com/forum/#!forum/conduit-announce
  8. https://github.com/runconduit/conduit/blob/master/README.md
  9. https://github.com/runconduit/conduit/issuesq=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22
  10. https://conduit.io/




ServiceMesh微信交流群:

添加微信xiaoshu062,备注:服务网格,即可加入Service Mesh微信交流群。