介绍
服务网格是一个基础设施层,允许您管理应用程序微服务之间的通信。 随着越来越多的开发人员使用微服务,服务网格已经发展到通过在分布式设置中整合常见的管理和管理任务来使这项工作更容易、更有效。
采用微服务方法来构建应用程序架构涉及将您的应用程序分解为一组松散耦合的服务。 这种方法提供了某些好处:团队可以使用更广泛的工具和语言快速迭代设计和扩展。 另一方面,微服务对操作复杂性、数据一致性和安全性提出了新的挑战。
服务网格旨在通过提供对服务之间通信方式的精细控制来应对其中的一些挑战。 具体来说,它们为开发人员提供了一种管理方式:
- 服务发现
- 路由和流量配置
- 加密和认证/授权
- 指标和监控
尽管可以使用 Kubernetes 等容器编排器在本地完成这些任务,但与 Istio 等服务网格解决方案相比,这种方法涉及更多的前期决策和管理] 和 Linkerd 开箱即用。 从这个意义上说,服务网格可以简化和简化在微服务架构中使用通用组件的过程。 在某些情况下,它们甚至可以扩展这些组件的功能。
为什么是服务网格?
服务网格旨在解决分布式应用程序架构固有的一些挑战。
这些架构源于三层应用程序模型,该模型将应用程序分为 Web 层、应用程序层和数据库层。 在规模上,这种模式已证明对经历快速增长的组织具有挑战性。 单体应用程序代码库可能会变得笨拙 “大泥球”,给开发和部署带来挑战。
为了解决这个问题,Google、Netflix 和 Twitter 等组织开发了内部“胖客户端”库来标准化跨服务的运行时操作。 这些库提供负载平衡、断路、路由和遥测——服务网格功能的前身。 但是,它们还对开发人员可以使用的语言施加了限制,并且在更新或更改服务时要求跨服务进行更改。
微服务设计避免了其中一些问题。 您拥有的不是一个大型的集中式应用程序代码库,而是一组代表应用程序功能的离散托管服务。 微服务方法的好处包括:
- 由于团队可以独立开发和部署不同的应用程序功能,因此开发和部署更加敏捷。
- CI/CD 的更好选择,因为可以独立测试和重新部署单个微服务。
- 更多语言和工具选项。 开发人员可以使用最好的工具来完成手头的任务,而不是局限于给定的语言或工具集。
- 易于缩放。
- 正常运行时间、用户体验和稳定性方面的改进。
与此同时,微服务也带来了挑战:
- 分布式系统需要不同的方式来考虑延迟、路由、异步工作流和故障。
- 微服务设置不一定能满足与单体设置相同的数据一致性要求。
- 更高级别的分发需要更复杂的操作设计,尤其是在服务到服务的通信方面。
- 服务的分布增加了安全漏洞的表面积。
服务网格旨在通过对服务通信方式提供协调和精细的控制来解决这些问题。 在接下来的部分中,我们将了解服务网格如何通过服务发现、路由和内部负载平衡、流量配置、加密、身份验证和授权以及指标和监控来促进服务到服务的通信。 我们将使用 Istio 的 Bookinfo 示例应用程序 (四个微服务共同显示特定书籍的信息)作为具体示例来说明服务网格的工作原理。
服务发现
在分布式框架中,有必要知道如何连接到服务以及它们是否可用。 服务实例位置在网络上动态分配,并且随着容器通过自动缩放、升级和故障而创建和销毁,有关它们的信息也在不断变化。
历史上,有一些工具可以在微服务框架中进行服务发现。 etcd 等键值存储与 Registrator 等其他工具配对,以提供服务发现解决方案。 Consul 等工具通过将键值存储与允许用户直接使用其 DNS 服务器或节点的 DNS 接口相结合来对此进行迭代。
采用类似的方法,Kubernetes 默认提供基于 DNS 的服务发现。 有了它,您可以查找服务和服务端口,并使用常见的 DNS 命名约定进行反向 IP 查找。 通常,Kubernetes 服务的 A 记录与以下模式匹配:service.namespace.svc.cluster.local
。 让我们看看它在 Bookinfo 应用程序的上下文中是如何工作的。 例如,如果您想从 Bookinfo 应用程序获取有关 details
服务的信息,您可以查看 Kubernetes 仪表板中的相关条目:
这将为您提供有关服务名称、命名空间和 ClusterIP
的相关信息,即使单个容器被销毁和重新创建,您也可以使用这些信息连接您的服务。
像 Istio 这样的服务网格也提供服务发现功能。 为了进行服务发现,Istio 依赖于 Kubernetes API、Istio 自己的控制平面(由流量管理组件 Pilot 管理)与其数据平面(由 Envoy 边车代理管理)之间的通信。 Pilot 解释来自 Kubernetes API 服务器的数据以注册 Pod 位置的更改。 然后,它将这些数据转换为规范的 Istio 表示并将其转发到 sidecar 代理。
这意味着 Istio 中的服务发现与平台无关,我们可以通过使用 Istio 的 Grafana 附加组件 在 Istio 的服务仪表板中再次查看 details
服务来看到这一点:
我们的应用程序在 Kubernetes 集群上运行,因此我们可以再次看到有关 details
服务的相关 DNS 信息,以及其他性能数据。
在分布式架构中,拥有关于服务的最新、准确且易于定位的信息非常重要。 Kubernetes 和 Istio 等服务网格都提供了使用 DNS 约定获取此信息的方法。
路由和流量配置
在分布式框架中管理流量意味着控制流量如何到达您的集群以及如何将其定向到您的服务。 您在配置外部和内部流量时拥有的控制力和特异性越强,您就可以对设置进行越多的操作。 例如,在您使用金丝雀部署、将应用程序迁移到新版本或通过故障注入对特定服务进行压力测试的情况下,能够决定您的服务获得多少流量以及流量来自何处将是关键你的目标的成功。
Kubernetes 提供了不同的工具、对象和服务,允许开发人员控制到集群的外部流量:kubectl proxy、NodePort、Load Balancers 和 入口控制器和资源。 kubectl proxy
和 NodePort
都允许您快速将服务公开给外部流量:kubectl proxy
创建一个代理服务器,允许通过 HTTP 路径访问静态内容,而 NodePort
在每个节点上公开一个随机分配的端口。 尽管这提供了快速访问,但缺点包括在 kubectl proxy
的情况下必须以经过身份验证的用户身份运行 kubectl
,在 NodePort
。 尽管负载均衡器通过附加到特定服务来优化灵活性,但每个服务都需要自己的负载均衡器,这可能会很昂贵。
入口资源和入口控制器一起提供了比这些其他选项更大程度的灵活性和可配置性。 使用带有入口资源的入口控制器允许您将外部流量路由到服务并配置内部路由和负载平衡。 要使用入口资源,您需要配置服务、入口控制器和 LoadBalancer
以及入口资源本身,这将指定到服务的所需路由。 目前,Kubernetes 支持自己的 Nginx Controller,但您也可以选择其他选项,由 Nginx、Kong 等管理。
Istio 使用 Istio Gateways 和 VirtualServices 迭代 Kubernetes 控制器/资源模式。 与 Ingress Controller 一样,Gateway 定义了应如何处理传入流量,指定要使用的公开端口和协议。 它与 VirtualService 结合使用,VirtualService 定义了网格内服务的路由。 这两种资源都将信息传递给 Pilot,然后 Pilot 将该信息转发给 Envoy 代理。 尽管它们类似于入口控制器和资源,但网关和虚拟服务提供了不同级别的流量控制:网关和虚拟服务不是结合 开放系统互连 (OSI) 层和协议 ,而是允许您区分 OSI设置中的图层。 例如,通过使用 VirtualServices,使用应用层规范的团队可以将关注点与使用不同层规范的安全运营团队分离。 VirtualServices 可以将离散应用程序功能或不同信任域内的工作分开,并可用于金丝雀测试、逐步推出、A/B 测试等。
要可视化服务之间的关系,您可以使用 Istio 的 Servicegraph 插件 ,它使用实时流量数据生成服务之间关系的动态表示。 Bookinfo 应用程序可能看起来像这样,没有应用任何自定义路由:
同样,您可以使用 Weave Scope 之类的可视化工具来查看给定时间您的服务之间的关系。 没有高级路由的 Bookinfo 应用程序可能如下所示:
在分布式框架中配置应用程序流量时,有许多不同的解决方案——从 Kubernetes 原生选项到 Istio 等服务网格——它们提供了各种选项来确定外部流量将如何到达您的应用程序资源以及这些资源将如何与某个资源进行通信其他。
加密和认证/授权
分布式框架为安全漏洞提供了机会。 微服务架构中的服务不像在单体设置中那样通过本地内部调用进行通信,而是通过网络传递信息,包括特权信息。 总体而言,这为攻击创造了更大的表面积。
保护 Kubernetes 集群涉及一系列程序; 我们将专注于身份验证、授权和加密。 Kubernetes 为其中的每一个提供了本机方法:
- Authentication:Kubernetes 中的 API 请求与用户或服务帐户绑定,需要进行身份验证。 有几种不同的方法来管理必要的凭据:静态令牌、引导令牌、X509 客户端证书和外部工具,如 OpenID Connect。
- Authorization:Kubernetes 有不同的授权模块,允许您根据角色、属性和其他专门功能等确定访问权限。 由于默认情况下对 API 服务器的所有请求都被拒绝,因此 API 请求的每个部分都必须由授权策略定义。
- Encryption:这可以指以下任何一种:最终用户和服务之间的连接、秘密数据、Kubernetes 控制平面中的端点,以及工作集群组件和主组件之间的通信。 Kubernetes 对这些都有不同的解决方案: 入口控制器和资源,可以与 cert-manager 等附加组件一起使用来管理 TLS 证书。 加密静态秘密数据,用于加密 etcd 中的秘密资源。 TLS 引导以引导 kubelet 的客户端证书以及工作节点和 kube-apisever 之间的安全通信。 您也可以使用 Weave Net 之类的覆盖网络来执行此操作。
在 Kubernetes 中配置单独的安全策略和协议需要管理投资。 像 Istio 这样的服务网格可以整合其中的一些活动。
Istio 旨在自动化一些保护服务的工作。 它的控制平面包括几个处理安全性的组件:
- Citadel:管理密钥和证书。
- Pilot:监督身份验证和命名策略,并与 Envoy 代理共享此信息。
- Mixer:管理授权和审计。
例如,当您创建服务时,Citadel 会从 kube-apiserver
接收该信息,并为此服务创建 SPIFFE 证书和密钥。 然后它将这些信息传输到 Pod 和 Envoy 边车,以促进服务之间的通信。
您还可以通过在 Istio 安装期间 启用双向 TLS 来实现一些安全功能。 其中包括用于跨集群和集群间通信的强大服务身份、安全的服务到服务和用户到服务的通信,以及可以自动创建、分发和轮换密钥和证书的密钥管理系统。
通过迭代 Kubernetes 如何处理身份验证、授权和加密,像 Istio 这样的服务网格能够整合和扩展一些推荐的最佳实践,以运行安全的 Kubernetes 集群。
指标和监控
分布式环境改变了对指标和监控的要求。 监控工具需要具有适应性,考虑到服务和网络地址的频繁变化,并且要全面,考虑到服务之间传递的信息的数量和类型。
Kubernetes 默认包含一些内部监控工具。 这些资源属于其 资源度量管道,可确保集群按预期运行。 cAdvisor 组件从各个容器和节点收集网络使用情况、内存和 CPU 统计信息,并将这些信息传递给 kubelet; kubelet 反过来通过 REST API 公开该信息。 Metrics Server 从 API 获取此信息,然后将其传递给 kube-aggregator 进行格式化。
您可以使用完整的指标解决方案扩展这些内部工具和监控功能。 使用像 Prometheus 这样的服务作为指标聚合器,您可以直接在 Kubernetes 资源指标管道之上构建。 Prometheus 通过其位于节点上的代理直接与 cAdvisor 集成。 它的主要聚合服务从节点收集和存储数据,并通过仪表板和 API 将其公开。 如果您选择将主要聚合服务与后端存储、日志记录和可视化工具(如 InfluxDB、Grafana、ElasticSearch)集成,则还可以使用其他存储和可视化选项、Logstash、Kibana 等。
在像 Istio 这样的服务网格中,完整指标管道的结构是网格设计的一部分。 在 Pod 级别运行的 Envoy sidecar 将指标传达给管理策略和遥测的 Mixer。 此外,Prometheus 和 Grafana 服务默认启用(但如果您使用 Helm 安装 Istio,则需要在安装期间 指定 granafa.enabled=true)。 与完整指标管道的情况一样,您还可以 配置其他服务和部署 以进行日志记录和查看选项。
借助这些指标和可视化工具,您可以在一个中心位置访问有关服务和工作负载的当前信息。 例如,BookInfo 应用程序的全局视图在 Istio Grafana 仪表板中可能如下所示:
通过复制 Kubernetes 完整指标管道的结构并简化对其一些常见组件的访问,像 Istio 这样的服务网格在使用集群时简化了数据收集和可视化的过程。
结论
微服务架构旨在使应用程序开发和部署快速可靠。 然而,服务间通信的增加已经改变了某些管理任务的最佳实践。 本文讨论了其中一些任务,如何在 Kubernetes 原生上下文中处理它们,以及如何使用服务网格(在本例中为 Istio)来管理它们。
有关此处涵盖的一些 Kubernetes 主题的更多信息,请参阅以下资源:
- 如何在 DigitalOcean Kubernetes 上使用 Cert-Manager 设置 Nginx 入口。
- 如何在 Kubernetes 上设置 Elasticsearch、Fluentd 和 Kibana (EFK) 日志堆栈。
- Kubernetes DNS服务简介。
此外,Kubernetes 和 Istio 文档中心是查找有关此处讨论的主题的详细信息的好地方。