一通百通,一文实现灵活的K8S基础架构!

本文转自Rancher Labs

作者简介

VIGNESH T.V.,Timecampus CEO、CTO及创始人。

Kubernetes是当前最为流行的开源容器编排平台,成为众多企业构建基础架构的首选。在本文中,我们将探讨针对你的用例构建基础设施的最佳方式,以及你可能要根据各种限制条件做出的各种决定.
 

架构设计

你的架构应该在很大程度上围绕你的用例来设计,因此在设计过程中你需要非常仔细以确保该基础架构能够支撑你的用例,在必要的时候也可以寻求外部专业团队的帮助。在架构设计的开始保证方向正确十分重要,但是这并不意味着不会发生错误,而且随着每天都有新的技术或研究横空出世,你可以看到变革已经成为常态,并且你的架构设计思维有可能过时。 

这就是为什么我强烈建议你采用Architect for Chang的原则,让你的架构成为一个模块化的架构以便在未来有需要的时候你可以灵活地在内部进行改变。 

让我们看看在考虑client-server模型的情况下如何实现系统架构的目标。 

切入点:DNS

在任何典型的基础架构中(无论是否是云原生架构),一个消息请求必须先由DNS服务器解析,并返回服务器的IP地址。设置你的DNS应该基于你所需要的可用性。如果你需要更高的可用性,你可能想要将你的服务器分布到多个区域或者云提供程序上,具体的实现要基于你想要达到的可用性等级。 
 
内容分发网络(CDN)
 
在某些情况下,你可能需要尽可能地以最小的延迟为用户提供服务,同时减少服务器的负载。这就是内容分发网络(CDN)发挥重要作用的地方。
Client是否经常从服务器上请求一组静态资产?你是否希望提高向用户交付内容的速度,同时减少服务器的负载?在这种情况下,采用边缘的CDN为一组静态资产提供服务,实际上可能有助于降低用户的延迟和服务器的负载。 

你所有的内容都是动态的吗?你是否可以在一定程度上为用户提供延迟的内容,以减少复杂性?或者你的应用程序接收很低的流量吗?在这种情况下,使用CDN可能没有太大的意义,你可以将所有的流量直接发送到全局负载均衡器。但要注意的是,拥有CDN也确实有分配流量的优势,这在你的服务器受到DDOS***时是很有帮助的。
 
CDN提供程序包括Cloudfare CDN、Fastly、Akamai CDN、Stackpath,此外你的云提供商也有可能会提供CDN服务,比如谷歌云平台的Cloud CDN、AWS的CloudFront、微软Azure的Azure CDN等。
在这里插入图片描述

Load Balancer

如果有一个请求不能被你的CDN服务,这个请求下一步会传送到你的负载均衡器上。而这些可以是区域性的IP,也可以是全局性的Anycast IP。在某些情况下,你也可以使用负载均衡器来管理内部流量。

除了路由和代理流量到合适的后端服务,负载均衡还能够承担SSL终止、与CDN集成,甚至管理网络流量的某些方面等职责。

虽然存在硬件负载均衡器,但软件负载均衡器提供了强大的灵活性、减少了成本开支以及弹性伸缩性。

与CDN类似,你的云提供程序应该也能够为你提供一个负载均衡器(如GCP的GLB、AWS的ELB、Azure的ALB等),但更有趣的是你可以直接从Kubernetes中调配这些负载均衡器。例如,在GKE中创建一个Ingress也会在后端为你创建一个GLB来接收流量,其他功能如CDN、SSL重定向等也可以通过配置你的ingress来设置,访问以下链接查看详情:

https://cloud.google.com/kubernetes-engine/docs/how-to/ingress-features

虽然一开始总是从小开始,但是负载均衡器可以让你逐步扩展至具有以下规模的架构:
在这里插入图片描述

网络及安全架构

 
下一件需要关注的事情是网络。如果你想要提高安全性,你可能需要一个私有集群。在那里,你可以调节入站和出站流量,在NATs后面屏蔽IP地址,在多个VPC上隔离多个子网的网络等。
 
如何设置网络通常取决于你所追求的灵活性程度以及如何实现它。设置正确的网络就是要尽可能地减少面,同时还能保持正常的运转。
 
通过设置正确的网络来保护你的基础设施通常还涉及到使用正确规则和限制条件设置的防火墙,以便限制来自各后端服务的流量的进出,包括入站和出站。
 
在很多情况下,可以通过设置堡垒主机并通过隧道进行集群中的所有操作来保护这些私有集群,因为你需要向公共网络公开的就是堡垒(又称Jump host),通常是在与集群相同的网络中设置。
 
一些云提供商在实现零信任安全的方法上也提供了定制化的解决方案。例如,GCP为其用户提供身份意识代理(IAP),可用于代替典型的
实现。

 
所有都处理好之后,下一步是根据你的用例在集群本身内设置网络。
这牵涉到以下任务:
 
设置集群内的服务发现(可由CoreDNS处理)

如果需要的话,设置一个服务网格(如LinkerD、Istio、Consul等)

设置Ingress controller和API网关(例如:Nginx、Ambassador、Kong、Gloo等)

设置使用CNI的网络插件,方便集群内的联网

设置网络策略,调节服务间的通信,并根据需要使用各种服务类型暴露服务

使用GRPC、Thrift或HTTP等协议和工具,设置不同服务之间的服务间通信

设置A/B测试,如果你使用像Istio或Linkerd这样的服务网格,实现起来可以更容易

如果你想看一些示例实现,我建议你看看这个repo(https://github.com/terraform-google-modules/cloud-foundation-fabric),它可以帮助用户在GCP中设置所有这些不同的网络模型,包括通过***的hub和spoke、用于内部的DNS和Google Private Access、支持GKE的共享VPC等等,所有这些都使用Terraform。
而云计算中网络的有趣之处在于,它不局限于你所在地区的云服务商,而是可以根据需要跨越多个地区的多个服务商。这就是Kubefed或Crossplane这样的项目可以提供帮助的地方。

如果你想探索更多关于设置VPC、子网和整体网络时的一些最佳实践,我建议你访问下方网页,同样的概念也适用于你加入的任何云提供商:

https://cloud.google.com/solutions/best-practices-vpc-design

Kubernetes

 
如果你使用的是GKE、EKS、AKS这样的托管集群,Kubernetes是自动管理的,从而降低了用户操作的复杂程度。
 
如果你自己管理Kubernetes,你需要处理很多事情,比如,备份和加密etcd存储,在集群中的各个节点之间建立网络,定期为你的节点打上最新版本的操作系统补丁,管理集群升级以与上游的Kubernetes版本保持一致。基于此,只有当你拥有一个专门的团队来维护这些事情的时候,才建议这样做。 

Site Reliability Engineering (SRE)

当你维护一个复杂的基础设施时,拥有合适的可观察性堆栈是非常重要的,这样你就可以在用户注意到错误之前就检测到错误以及预测可能的变化,进而识别异常,并有余力深入钻研问题到底在哪里。
 
现在,这就需要你有代理,将指标暴露为特定的工具或应用来收集分析(可以遵循pull或push机制)。而如果你使用的是带有sidecars的服务网格,它们往往会自带指标,而不需要自定义配置。
 
在任意场景下,都可以使用Prometheus这样的工具作为时序数据库,为你收集所有的指标,以及借助类似于OpenTelemetry的工具,使用内置的exporter从应用程序和各种工具中公开指标。借助Alertmanager之类的工具可以向多个渠道发送通知和告警, Grafana将提供可视化仪表板,给用户提供整个基础设施的完整可见性。
 
综上,这就是Prometheus的可观察性的解决方案:
在这里插入图片描述
来源:https://prometheus.io/docs/introduction/overview/

拥有这样复杂的系统,还需要使用日志聚合系统,这样所有的日志就可以流到一个地方,便于调试。大部分企业倾向于使用ELK或EFK堆栈,Logstash或FluentD根据你的限制条件为你做日志聚合和过滤。但日志领域也有新的玩家,比如Loki和Promtail。
 
下图说明了类似FluentD的日志聚合系统如何简化你的架构:
在这里插入图片描述
来源:https://www.fluentd.org/architecture

但是,如果要追踪跨越多个微服务和工具的请求呢?这是分布式跟踪开始发挥作用的地方,特别是考虑到微服务的复杂性。像Zipkin和Jaeger这样的工具一直是这个领域的先驱,最近进入这个领域的新兴工具是Tempo。
 
虽然日志聚合会给出各种来源的信息,但它不一定能给出请求的上下文,这才是做跟踪真正有帮助的地方。但是请记住,在你的堆栈中添加跟踪会给你的请求增加很大的开销,因为上下文必须和请求一起在服务之间传播。
 
下图是一个典型的分布式跟踪架构:
在这里插入图片描述
来源:https://www.jaegertracing.io/docs/1.21/architecture/

但是,网站的可靠性并不仅仅止于监控、可视化和告警。你必须准备好处理系统任何部分的任何故障,并定期进行备份和故障切换,这样至少可以将数据损失的程度降到最低。你可以借助类似Velero的工具实现。
 
Velero通过利用你使用的相同Kubernetes架构,帮助你维护集群中各种组件的定期备份,包括你的工作负载、存储等。Velero的架构如下:
在这里插入图片描述
正如你所观察到的,有一个备份controller,它定期对对象进行备份,根据你设置的计划将它们推送到特定的目的地,其频率是基于你设置的计划。这可以用于故障转移和迁移,因为几乎所有的对象都有备份。
 

存 储

有许多不同的存储程序和文件系统可用,这在云提供程序之间可能存在很大的不同。这就需要像容器存储接口(CSI)这样的标准,该标准可以帮助大部分volume的外置插件,从而使其易于维护和发展而不会成为核心瓶颈。
 
下图是CSI架构,通常可以支持各种volume插件:
在这里插入图片描述
来源:https://kubernetes.io/blog/2018/08/02/dynamically-expand-volume-with-csi-and-kubernetes/

 
分布式存储带来的集群、扩展等各种问题怎么办?这时Ceph这样的文件系统已经证明了自己的能力,不过考虑到Ceph并不是以Kubernetes为中心构建的,部署和管理起来存在一些难度,此时可以考虑Rook这样的项目。
 
虽然Rook没有和Ceph耦合,也支持其他文件系统,比如EdgeFS、NFS等,但Rook与Ceph CSI就像是天作之合。Rook与Ceph的架构如下:
在这里插入图片描述
来源:https://rook.io/docs/rook/v1.5/ceph-storage.html

如你所见,Rook承担了Kubernetes集群中的Ceph安装、配置和管理的功能。根据用户的喜好,自动分配下面的存储。这一切的发生,都不会让应用暴露在任何复杂的情况下。
 

镜像仓库

 
镜像仓库为你提供了一个用户界面,你可以在这里管理各种用户账户、推送/拉取镜像、管理配额、通过webhook获得事件通知、进行漏洞扫描、签署推送的镜像,还可以处理镜像或在多个镜像仓库中复制镜像等操作。
 
如果你使用的是云提供商,他们很有可能已经提供了镜像仓库作为一项服务(例如GCR、ECR、ACR等),这就消除了很多复杂性。如果你的云提供商没有提供,你也可以选择第三方的镜像仓库,比如Docker Hub、Quay等。
 
但如果你想托管自己的镜像仓库呢?
 
如果你想在企业内部部署镜像仓库,想对其本身有更多的控制权,或者想降低漏洞扫描等操作的相关成本,那么可能需要进行托管。
 
如果是这种情况,那么选择像Harbor这样的私有镜像仓库会对你有所帮助。Harbor架构如下:
在这里插入图片描述
来源:https://goharbor.io/docs/1.10/install-config/harbor-ha-helm/
 
Harbor是一个符合OCI的镜像仓库,由各种开源组件组成,包括Docker镜像仓库V2、Harbor UI、Clair和Notary。
 

CI/CD架构

 
Kubernetes可以在任何规模下托管所有的工作负载,但这也需要一个标准的方式来部署应用程序,并采用精简的CI/CD工作流程。下图为典型的CI/CD流水线:
在这里插入图片描述
一些第三方服务如Travis CI、Circle CI、Gitlab CI或Github Actions都包含了自己的CI运行器。你只需定义你要构建的流水线中的步骤。这通常包括:构建镜像,扫描镜像以查找可能的漏洞,运行测试并将其推送到镜像仓库,在某些情况下还需要提供一个预览环境以进行审批。
 
现在,虽然如果你管理自己的CI运行器,步骤通常保持不变,但你需要将它们配置为在集群内部或外部设置,并具有适当的权限,以便将资产推送到镜像仓库。
 

总 结

 
我们已经介绍了基于Kubernetes的云原生基础设施的架构。正如我们上面所看到的,各种工具解决了基础设施的不同问题。它们就像乐高积木一样,每一个都专注于当前的一个特定问题,为你抽象掉了很多复杂的东西。

这使得用户可以以渐进的方式逐渐上手Kubernetes。并且你可以根据你的用例,只使用整个堆栈中你需要的工具。

猜你喜欢

转载自blog.51cto.com/12462495/2664678