本文翻译自原文:Using Go in Devops,原作者:Natalie Pistunovich
原文出处:https://blog.gopheracademy.com/advent-2018/go-devops/
这篇文章旨在为使用Go语言提供了一个新的角度。不要期望找到代码片段或是学到新东西,而是开启一个新的视角,并和你正在寻找新的解决方案的系统运维/DevOps 工程师们分享。
在不久前,系统运维还是一个常见的工作,负责软件升级,网络配置和胶水脚本编写。然后是DevOps到来 — 这是开发与运维界限模糊的一个角色。现在,随着系统变得更为复杂,服务部署更为分散(微服务) – 可观察性成为一种你追踪系统健康状况的重要指标。
定义可观察性
人们早就开始并仍在进行对此的讨论。我很高兴能够参与一个发展如此迅速的技术分支,并跟随它学到了很多东西。有些人可能不太赞同以下的定义,也许未来我也会对这个定义有不同的看法。
监控是指反复去检查系统及其输出,以确保它们处于健康状态。它是可操作的集成测试,并更偏向于通过告警和日志等工具,去发现其中的问题。
在控制理论中,可观察性是能从系统外部输出推测的,对系统内部状态的一种衡量。可观察性和可控性是系统的数学奇偶(原文:The observability and controllability of a system are mathematical duals.)。
但可观察性是先理解软件与系统内部的状态,提出问题,并且通过观察系统输出来提供答案。任何问题 – 不限于可操作的告警或问题。随着关注点从监控转向可观察性,相较于 已知-未知 ,我们也更多地去讨论 未知-未知 。
现在许多用于运维/提供可观察性的工具是用Go写的。
代码如何完成这个转变
这一切始于在代码中添加日志输出,这绝对是所有调试工具的源头。
我们也可以写一个Bash脚本做这件事。
但是有时会发现你会写一个简单的脚本去处理这个问题,但是脚本会一直保留。随着系统变得越来越复杂,脚本也会随之增多堆叠。最终形成一个脚本集群。在编写时采用编程语言相比于使用脚本语言来说可能是更好的解决方案,使用一个程序去替代一堆脚本。
就像你无法想象餐厅厨师使用常规刀具,在复杂的架构中维护多个服务,使之具有高可用性及低时延,需要一个易于维护的适当的解决方案。Go提供了许多合适的工具,我们将在下面详细介绍。
工具
此处列出的所有工具都是开源的:
用Go编写的运维工具
Kubernetes
Borg于2003年在Google时创建,作为集群管理器,旨在有效地管理成千上万的工作,并使计算更为高效。它是由C++编写的。
2014年,Kubernetes作为操作系统发布:一个由大型公司用于生产环境的分布式容器协调器。
Kubernetes是一个用于自动化容易化应用程序的部署、扩展和管理的系统。它将构成应用程序的容器分组为易于管理和发现的逻辑单元。Kubernetes可以在不增加运维人员的情况下进行无限制的资源扩展。它在内部部署、混合云或是公共云上都可使用。
Prometheus
亦由Borg在2003年开发,是一个免费提供的内部监控系统,由C++编写。
2012年Prometheus正式开源:作为时序数据库,用于收集指标以及生成告警。
时间序列由一个指标名称和一个键值对组成,提供了强大的查询功能以及高效的存储。内置告警功能,支持10种语言,并可以从Docker和StatsD等来源导入数据。
Etcd
Chubby与2006年创建,是一个分布式锁管理工具。一个有趣的事实:为了保证99.99的SLO,团队经常需要每季度执行一次长达13分钟的计划中断。
2013年,Etcd面世:一个强大的分布式键值对存储,可供读取与写入数据,这提供了一种在集群中存储数据的可靠方法。
Etcd是Kubernetes的核心组件,它用于关键的分布式任务系统,因为他可以很好地处理网络分区导致的领导选举,以及机器故障。一个简单的用例是将Etcd中数据库连接信息存储为键值对,并监控这些值,允许你的应用在配置变更时重新读取。现在这也是一个CNCF(Cloud Native Computing Foundation)项目!
Docker
2006年,谷歌退出了cgroups,可以隔离进程并且限制其资源。2008年推出了lxc,增加了具有内核模块的额外功能。这允许了命名空间以及限制某个进程可见。
2013年Docker发布:它可以完成上述所有工作,并且使用管道和工具来构建产生于容器的快照,并控制了端口映射。
Docker实现了容器化-操作系统级的虚拟化。它是限制市面上最为流行的容器,也是Kubernetes的核心组件。
用Go编写的Ops工具
Helm
Helm是Kubernetes的包管理工具。是查找,共享,使用Kubernetes中软件的最佳方式。Helm Charts可以定义、安装和升级复杂的Kubernetes应用程序,包括版本控制、共享以及发布配置文件,避免迷失在复制-粘贴当中。
Grafana
Grafana是一个时间序列分析和监控的可视化平台。官方支持的数据来源有:Prometheus, InfluxDB和Elasticsearch等等。对应每个数据源都有一个为其特性和功能定制的查询编辑器。每个数据源绑定到一个面板,由诸多面板构成一个仪表盘。可以控制其中的时间段,注释时间,以便让时间序列数据和其他时间相关联。
The Open Tracing Project
分布式追踪所有事件?这个项目是用于分析和监控那些部署在分布式体系架构(比如微服务)上的应用程序,分布式追踪通过查明故障发生的位置来帮助调试复杂的系统,并通过发现性能不佳的原因来进行优化。
OpenTracing API项目致力于创建更为标准化的API和工具,它包含了API规范,已规范的框架/库以及项目文档。它允许开发人员在其代码中使用未锁定在某个特定产品的API。
Jaeger
与OpenTracing兼容,Jaeger是一种端到端的分布式追踪工具,用于监控和排查复杂分布式系统中的事务,通常用于有网络或是可观察性基础的系统。
Jaeger是一个用于分布式事务监控、上下文传播、性能分析、根因分析和服务依赖分析的工具。
Istio
一个可配置的基础设施层,用于微服务架构。Istio使得微服务实例之间的通信变得灵活、可靠、快速及安全。它通过在每个应用部署一个sidecar(一个代理)来添加到应用程序中,这意味着你不需要修改代码!
它有一个自动发现、追踪、监控、记录、增加可观察性的平台,通过访问控制和身份验证、访问策略控制和流量控制等手段实现安全。
CNCF
Cloud Native Computing Foundation(CNCF)是上述许多项目的所在。它是一个开源软件基金会,致力于云计算的普及和可持续性。该基金会构建了一个可持续发展的流程,并围绕一系列高质量的开源项目建立了一个社区,这些项目都将容器作为了其微服务架构的一部分。
云计算使用开源软件将应用程序部署为微服务,将每个部分打包到自己的容器中,并动态安排容器以优化资源的使用率。
Go为SRE(Site Reliability Engineering)带来的好处
简单,可靠,快速
使用Go – 无论你在构建什么,都专注于构建它,而不是运行它所需要的工具。
简单
可读性
还记得之前我们讨论到需要一个可靠的软件来取代bash脚本组吗?这样的话即使多个运营团队共享代码库,该软件也易于阅读并且保持高度一致性。gofmt内置的linter很容易就可以实现这种可读性。
内置测试、分析和基准测试
遵循Go的最佳实践,你可能会进行TDD(测试驱动开发)。如果你想要断言,可以用,但没必要。测试,分析(CPU和内存)都是内置的,不需要学习使用子语言,新的命令或是新的工具,并且有一些很好的工具用于结果可视化。
一个二进制解决问题
Go是静态链接的,这意味着不需要外部库,复制依赖项或是担心引入。所有代码以及依赖都在二进制文件当中。并且作为一个纯粹的同质环境,它不依赖于语言的版本。
交叉编译
将所有东西都放到二进制文件让事情变得简单了,而能够交叉编译则更好:为了支持在不同的操作系统上运行二进制文件,只需要设置两个环境变量,$GOOS,$GOARCH。不需要虚拟环境,包管理工具或者依赖管理工具。这是CLI提供的一个很棒的功能,有许多开源项目正在使用它:etcdctl,kubectl和docker。
这是部分支持的平台清单
$GOOS | $GOARCH | OS |
---|---|---|
darwin | 386 | 32 bit MacOSX |
darwin | amd64 | 64 bit MacOSX |
linux | 386 | 32 bit Linux |
linux | amd64 | 64 bit Linux |
linux | arm | RISC Linux |
windows | 386 | 32 bit Windows |
windows | amd64 | 64 bit Windows |
组合,而不是继承
避免继承带来的混乱。
标准库
许多标准库中的包都是运维工具的构建部分。比如使用HTTP/HTTP2等不同协议来处理Web服务或是文件处理:路径、打开、进程、时间、Json、正则等等。不需要保持追踪这些库,或是在它们弃用时切换。因为他们都在标准库内,由官方开发人员进行维护、记录和使用。虽然标准库并不是很大,但是对于运维/SRE人员来说非常有用。
可靠性
有指针,没有指针运算
保证安全!
错误处理
明确将错误作为值来处理,而不是将其作为异常抛出,使执行更加流畅。
开源
Go有一个令人惊叹的社区,多年来使用该语言的公司以及谷歌、微软和苹果等行业巨头的支持(你知道SpaceX正在使用Go吗?)。所以到现在为止,它仍然存在。
数据类型
Go是强类型&类型安全的,这意味着无法对int进行string操作,因为编译器会阻止这个操作。基于数组类型抽象的内存好处是让某些操作明显变快了
快速
快速编译和执行
如果有未使用的导入,编译器将无法运行。编译时间短,二进制很小。由于代码被编译为机器代码 – 将被快速执行。想想通过sed或者bash运行数百万个循环,Go将会有多快?
垃圾收集
像大部分编程语言一样,Go的垃圾回收机制也是一个有争议的话题。简而言之,它有一套默认的逻辑,可以修改它们来获取更好的性能。
引入-定义依赖项
所有依赖项都在二进制文件中,这样可以节省在二进制文件旁携带依赖项的任何额外的步骤。
快速表演
许多基准的测试已经完成。这里有一个相当全面的列表。
总结
Go是用于构建快速可靠的Web服务的绝佳语言。很多时候它也非常适合去构建能够确保这些服务正常运行的工具。选择适合的工具当然是重中之重,所以我们应使用批判性思维去看待并考虑将Go用于Web开发之外,更多的将它用于DevOps。