跳到主要内容

· 阅读需 54 分钟
南哥

介绍

CNCF最初的平台定义白皮书描述了什么是云计算的内部平台,以及它们承诺为企业提供的价值。但是,为了实现这些价值观,组织必须反思并有意识地追求对他们有影响的结果和实践,请记住,每个组织都依赖于为自己的组织设计的内部平台——即使该平台只是有关如何使用第三方服务的文档。这种成熟度模型为这种反思和识别任何组织中的改进机会提供了一个框架。

什么是平台工程?

在DevOps承诺的跨职能合作的启发下,平台和平台工程已经作为这种合作的明确形式出现在企业中。平台策划并呈现通用功能、框架和体验。在本工作组和相关出版物的背景下,重点是促进和加速内部用户(如产品和应用团队)工作的平台。

平台工程是规划和向开发人员和用户提供此类计算平台的实践,涵盖平台的所有部分及其功能——人员、流程、策略和技术;以及推动他们实现的预期业务成果。

请先阅读 CNCF 平台定义白皮书,了解完整的背景信息。

如何使用此模型

随着平台工程在过去几年中的地位越来越高,一些模式已经变得明显。通过将这些模式和观察结果组织成一个渐进式成熟度模型,我们的目标是让平台团队适应他们可能面临的挑战和瞄准的机会。每个方面都由该方面每个级别的不同团队和组织的连续特征来描述。我们希望读者在模型中找到自己,并在相邻的层面上发现机会。

值得注意的是,每增加一个成熟度水平,对资金和人员时间的要求就越高。因此,达到最高水平本身不应该是一个目标。每个级别都描述了在该阶段应该出现的品质。读者必须考虑,鉴于所需的投资,他们的组织和当前环境是否会从这些品质中受益。

请记住,每个方面都应该独立评估和发展。然而,与任何社会技术系统一样,这些方面是复杂且相互关联的。因此,你可能会发现,要在一个方面有所改进,你就必须在另一个方面达到最低水平。

同样重要的是要认识到,平台的实现因组织而异。请务必评估团队整体云原生转型的当前状态。可用于此评估的非凡资源是云原生成熟度模型。

最后,该模型鼓励组织通过有意识的规划来完善其平台工程学科及其生成的平台。这种规划和纪律本身就是成熟平台开发和持续演进的必要条件。

目标受众

每个读者都会带来独特的背景,并将从这个模型中学到独特的知识。以下是我们想到的一些角色,以及他们参与此模型的可能动机:

  • 首席技术官、副总裁和技术总监:希望规划数字化转型和提高开发人员生产力的道路的领导者
  • 工程经理:寻求使工程师能够以更少的开销和更高的效率提供价值的团体和个人
  • 企业架构师:在现代技术领域中寻求以价值和解决方案为导向的技术问题视角的个人
  • 平台工程师和平台产品经理:寻求为平台构建者和平台用户构建最佳体验的团队和人员
  • 产品供应商和项目维护人员:希望设计工具和传递消息的组织和工程师,使用户能够利用平台和功能取得成功
  • 应用程序和产品开发人员:希望更详细地了解他们对内部平台的期望的平台用户

模型表

投资

如何为平台功能分配人员和资金?

对平台和平台工程的投资是分配预算和人员以构建和维护共同能力的过程。通常,计划被描述为自下而上有机构建,或通过自上而下的计划来推动。无论哪种情况,都是持续投入努力的能力推动了高影响力的工作。这方面反映了投资的规模和广度如何影响平台的成功。

1级 自愿或临时

可能存在单个功能,以便为常见或关键功能提供共同基础。这些能力的建立和维护是出于必要,而不是计划和有意资助的。

这些功能由临时或自愿分配的人员构建和维护;没有故意向他们分配中央资金或人员。它们取决于用户当前的战术要求。

  • 特性

    • 团队的寿命很短,没有分配也没有时间提供长期规划和支持
    • 员工抱怨倦怠和对他们在核心角色之外所做的大量工作感到沮丧
    • 在处理新需求(例如紧急安全补丁)时,可能会引入流程改进或自动化,但不支持以可重用或可持续的方式构建解决方案
  • 示例场景:

    • 有一位特定的员工被视为测试环境专家。虽然这位员工的本意是好的,但他们在投资有限的情况下试图实现更好的测试环境,这导致了风险的增加,因为他们的解决方案没有得到维护,也没有对如何对损坏的测试环境进行分类的共识。
    • 当管理层没有对创收功能施加压力时,我们鼓励工程师投资于能力改进。 这转化为一些冲刺的最后几天,他们优先考虑自动化和改进 CI/CD 管道的部分内容。 这些改进突然出现的情况并不少见,因为可能有几个月的过度冲刺,没有时间进行这些副业。

2级 运营 — 专业团队

预算和人员分配用于持久的人员和资源支持。 指定人员的任务是提供一组常用的功能来加快软件交付速度。 这些团队通常专注于满足反应性技术要求。 它们可能被称为 DevOps、工程支持、开发人员体验(DevEx 或 DevX)、共享工具、卓越中心,甚至平台。 它们得到集中资助并被视为成本中心; 它们对直接价值流和应用程序团队的影响没有被衡量。 很难描绘出这个级别的平台团队对组织及其价值流的影响,这使得维持和继续资助此类团队变得困难。

  • 特性

    • 团队预算可能包括与其工作相关的基础设施成本,这通常是预算对话中的一个关键点。
    • 积压工作 (backlog) 项包含多种技术,导致频繁且大型的上下文切换。
    • 这个团队通常是第一个填补尚未解决的空白的团队,即使不在团队声明的范围内。此团队拥有没有所有者的资源的所有权。
    • 被指派的人员很少有时间或经验进行客户研究来验证他们的设计或实施
  • 示例场景:

    应用程序开发人员提出了一个问题,即其应用程序的构建时间过长。集中式团队的任务是将构建时间缩短 50%。他们通过将 CI 运行器的大小和数量增加一倍来解决这个问题,因为它们与软件的距离不够近,无法单独改进应用程序构建。这给他们的集中式团队带来了预算问题,因为生产力的提高无法直接衡量这种增加的基础设施成本。

3级 可扩展 — 即产品

对内部平台及其功能的投资类似于对企业对外产品和价值流的投资:基于它们预期为客户提供的价值。产品管理和用户体验被明确考虑和投资。退款系统可用于反映平台对其客户自身直接价值流和产品的影响。企业通过使用数据驱动的绩效指标和反馈循环,将资金和人员分配给适当的计划。平台团队最终可以优化业务本身,并有助于提高盈利能力。

  • 特性

    • 平台团队员工角色传统上在内部服务或技术团队中找不到,例如产品管理和用户体验。
    • 团队在组织内部发布路线图,该路线图指示交付的价值和高级功能目标。
    • 在设计、交付和部署后阶段,对功能的实施质量和用户体验进行了测试。
    • 功能删除是对话的关键部分,目标是拥有一个得到良好支持、使用良好的功能套件,而不是可能无法维护的庞大资产
  • 示例场景: 从平台使用指标中获得的数据为决策提供信息,将资金和人员分配给最具影响力的计划。

第 4 级,优化 — 启用的生态系统

平台团队想方设法提高组织范围的效率和有效性,而不仅仅是基本功能。核心平台维护人员有意努力优化新产品的上市时间、降低整个企业的成本、实现新服务的高效治理和合规性、快速轻松地扩展工作负载以及其他跨领域要求。这些核心维护人员专注于使能力专家能够将他们的需求和产品无缝集成到平台的现有和新部分。此外,该组织将来自安全、性能、质量等专业领域的人员和资源集中在与提供的平台框架互动上,以引入高级功能,使产品团队能够加速实现公司目标,而无需依赖集中的团队积压工作。

  • 特性:

    • 使专家能够扩展平台功能并引入新功能成为当务之急。
    • 该组织可以集中专家,允许他们的知识和支持通过平台功能传播。
  • 示示例场景:

    • 营销部门与平台建设者合作,引入一致的用户跟踪,以便将营销工作归因于产品结果。
    • 自动化计划将每个实例配置数据库的人工时间缩短了 30 分钟,每年可节省 1000 万美元。

采用

采用不仅描述了组织使用平台功能的方式和程度,还描述了他们这样做的动机。在早期阶段,许多目标用户可能根本没有意识到他们正在使用一个平台,而是将他们的工具视为来自各种内部来源的功能的临时集合。这可能会发展成为一组一致管理并呈现给用户的功能,即一个或多个平台。随着功能变得更加精细和可发现,平台使用的驱动力通常会远离更多的外部动机,如授权或激励。这导致用户自行选择平台功能,理想情况下甚至将自己的努力投入到更广泛的平台生态系统中。

指示平台采用的常见增长模式的图表。这展示了主要由平台建设者推动的缓慢起步。一旦平台为用户提供了足够的价值,增长就会更多地受到用户的拉动,从而导致更陡峭的采用曲线。

1 级,临时 — 不稳定

共享平台和功能的采用是零星且不一致的。在选择和整合所需的支持服务和技术方面,没有组织范围的战略或指导。各个团队可能会利用平台实践来改进自己的流程,但整个组织没有协调的努力或标准化。这种采用程度的特点是缺乏连贯的方法,并且认为外部工具比内部提供的工具更有效。

  • 特性:

    • 一次性工具、服务和功能由组织中的各个团队和部门管理和使用。
    • 提供商管理(又称“云”)服务的采用和使用不一致,并且没有标准的做法和策略,因为内部配置很难找到或使用。
    • 应用和服务团队通过谣言和偶然的对话随意发现工具和功能,而不是通过更集中的流程。
    • 组件和功能的协调和重用仅由最终用户(应用程序团队)驱动(如果有的话)。
    • 每个产品团队都维护自己的一组脚本或工具来部署其应用程序。
  • 示例方案:

    • 银行服务需要数据库。开发人员从另一个团队的朋友那里得知,他们可以请求 AWS 账户并设置 RDS 数据库。他们从另一个团队中找到了一个 Terraform 脚本来预配该数据库。为了进行监控,他们临时使用 CloudWatch;在运行 Terraform 脚本之前,他们手动将密钥从 AWS 控制台复制到 Hashicorp Vault 实例。

第 2 级,可操作 — 外在推动

该组织认识到共享平台和功能的价值,并努力鼓励和培养它们。内部指令激励甚至要求在某些用例中使用共享平台服务。一些产品团队比其他产品团队更多地使用平台功能;功能涵盖组织中的典型用例,但不包括不寻常的用例;并且很难将这些异常值添加到通用平台。

用户对功能的发现及其使用方式不一致;除非平台团队指示,否则产品团队中的用户可能不会发现受支持的功能。

  • 特性:

    • 一定程度的外部推动力导致使用平台功能,例如:个人评论等激励措施/要求用于生产发布或获得资金等任务
    • 平台功能的利用是分散的——用户可能利用一种功能,但可能不知道或有兴趣采用其他可用的功能。
    • 用户学习如何使用平台功能的积极性较低,并且严重依赖通过办公时间或服务台等论坛与提供商的协作。
    • 鼓励平台用户加入非正式的实践社区,分享问题和解决方案,但出席人数可能会受到限制。
  • 示例场景:

    • 工程组织决定使用标准部署工具,并指示所有团队使用它。新流程(发行说明的沟通等)是围绕该标准构建的。指示团队停止使用其他类型的部署脚本,而是使用通用工具。对于一些团队来说,这很困难,他们的需求没有被新流程满足,但又不理解或不允许扩展它。

第 3 级,可扩展 — 内在拉力

产品和服务团队的用户之所以选择使用平台及其功能,是因为它们在减少产品团队的认知负担方面提供了明确的价值,同时提供了更高质量的支持服务。文档和符合人体工程学的界面使产品团队用户能够快速配置和使用平台功能。用户选择内部平台实施,而不是自己开发功能或雇用提供商等替代方案。

  • 特性:

    • 平台采用是自我维持的——核心采用的主要驱动力不是强制用户使用平台产品的外部动力或激励——而是这些平台产品本身的价值吸引了用户。
    • 在使用和欣赏一个或某些平台功能后,用户会寻找其他功能,并发现不同功能的体验是相似的。人们期望单个功能不是孤立的,而是更大的平台功能集中的一个功能。
    • 平台团队通过收集用户反馈、分享路线图和维护开放论坛与用户对话来鼓励平台的自然采用。
    • 应用程序和产品团队对平台功能的重视程度足以为此付费,例如,通过计费系统。
    • 用户可以通过开放论坛和共享路线图分享反馈并了解即将推出的功能。
    • 自助服务门户、黄金路径模板和其他文档支持快速使用。
  • 示例场景:

    • 应用程序团队以前曾成功请求新数据库。他们的过程很容易理解,几乎不需要等待时间。此外,还包括备份和监控等关键功能,使团队能够毫无问题地将其使用一直推进到生产。这种经验意味着,当团队以后需要队列时,他们的第一反应是检查内部平台选项。虽然他们最初打算使用特定的队列技术,但最终,他们选择使用内部提供的队列技术,因为他们知道该解决方案对他们的组织的集成程度如何。

第 4 级 优化——参与式

来自产品团队的用户通过加入生态系统并回馈生态系统来进一步投资平台功能。一些贡献改进和修复了现有功能;其他人则引入了新功能和特性,以解决新的用例。定义了流程和服务,使用户能够识别需求并协调多个产品和平台团队之间的贡献。新功能通过一致的界面和门户发布,并提供完整的文档和标准版本控制。

  • 特性:

    • 应用/服务团队中的用户有权为平台功能提供修复、功能和反馈。
    • 战略性地利用外部项目和标准来降低维护成本、加速新功能交付,并最有效地利用组织员工人数。
    • 新功能和增强功能通过问题板和拉取请求异步协调。文档和清单使贡献者能够自我驱动开发。
    • 开发者倡导者和内部大使建立并支持内部用户社区,将平台所有权扩展到应用和服务团队贡献者。
    • 领导层和个人贡献者都认为使用平台功能是在组织中工作的最佳方式。
    • 平台工程师参与产品团队规划,以了解需求并建议相关的现有功能。
  • 示例场景:

    • 团队需要替代备份计划。在将其作为一般产品提出后,由于重用最少,它被视为低优先级。建议团队选择将其解决方案集成到平台框架中,并将其提供给组织。它最初是一个 alpha 产品,但一旦满足所有操作要求,就可以提升为核心平台功能。

接口

用户如何与平台功能交互和使用平台功能?

平台提供的接口会影响用户与这些平台产品进行交互以预配、管理和观察功能的方式。界面可以包括工单系统、项目模板和图形门户,以及可自动化的 API 和命令行 (CLI) 工具。

界面的主要特征包括它在关键用户旅程(如初始请求、维护或事件分类)中的可发现性和用户友好性。此处的成熟度越高,反映出接口的集成度更高、一致性更高、自动化程度更高、更受支持。

级别 1,临时 — 自定义流程

存在一组不同的进程来提供不同的功能和服务,但不考虑接口的一致性。定制的流程可以满足个人或团队的迫切需求,即使提供商使用一些自动化实施脚本,也依赖于人工干预。

有关如何请求这些解决方案的知识在人与人之间共享。请求服务的过程缺乏标准化和一致性。预配和使用平台服务可能需要功能提供商的深入支持。

由于缺乏核心要求和标准,当公司尚未确定和记录期望时,这一水平是合适的。它对于处于早期阶段的公司或平台工作的团队特别有效。在这些环境中,团队可以自由地根据自己的需求发展流程和功能,使他们能够更快地交付,并且只有在以后需要时才为标准化付出代价。

  • 特性:

    • 用户交互不是讨论的关键主题,并且很少(如果有的话)在设计和交付新功能期间测试交互。
    • 功能主要通过手动请求提供,但提供商可以选择自动执行预配用户请求所需的部分或全部活动。
    • 表面上“简单”的请求由于找到要遵循的正确流程而变得复杂
    • 有时,一个流程似乎得到了批准,但当不同的部门或团队参与进来时,用户会遇到问题
  • 示例场景:

    • 应用程序团队希望对其新更改进行性能测试。为此,他们需要一个包含足够测试数据的隔离环境,以获得准确的性能读数。上一次他们提出这个请求时,一位前队友能够访问一个环境,但他们已经离开了,没有人知道如何重新创建它。最后,他们与基础架构团队的工程师建立了联系,该工程师能够在几天内为他们提供一个环境。
    • 处于产品开发探索阶段的团队使用定制流程来配置新的云服务,而无需验证其解决方案,从而保证进一步投资。

第 2 级,可操作 — 标准工具

存在用于配置和观察平台和功能的一致标准接口,并满足广泛的需求。用户能够确定哪些功能可用,并能够请求他们需要的功能。

以文档和模板的形式提供“铺砌的道路”或“黄金路径”。这些资源定义了如何使用合规且经过测试的模式来预配和管理典型功能。虽然一些用户能够自己使用这些解决方案,但这些解决方案通常仍然需要深厚的领域专业知识,因此维护人员的支持仍然至关重要。

  • 特性:

    • 技术解决方案是特定于其问题领域的内置工具,并不总是用户熟悉的工具。
    • 在共同的道路上进行投资;然而,偏离这条道路很快就会发现很少的自定义选项,因为重点是构建一个选项。
    • 在标准化的情况下,非正式的内部小组能够形成和聚集在一起,分享良好做法并克服共同的问题。
    • 当团队采用模板、自定义模板,然后无法合并来自集中式团队的更改时,功能实现可能会出现偏差。
  • 示例场景:

    • 集中式团队策划了一个 Terraform 模块、Kubernetes 控制器和 CRD 库,用于预配不同类型的基础设施。
    • 共享位置包含有关整个组织解决方案的综合文档。

级别 3,可扩展 — 自助服务解决方案

解决方案的提供方式为用户提供了自主权,并且几乎不需要维护人员的支持。该组织鼓励并启用解决方案来提供一致的接口,以实现用户体验从一种功能到另一种功能的可发现性和可移植性。虽然是自助服务,但解决方案确实需要团队意识和实施。为了改善这种体验,可能会有一种引导式和简化的内部语言,使用户能够更快地采用和集成平台功能。这将生成以用户为中心、可自助服务且一致的功能集合。

  • 特性:

    • 解决方案以“一键式”实施的形式提供,使团队能够从功能中受益,而无需了解它们是如何配置的。
    • 虽然解决方案易于创建,但在管理解决方案的第 2 天和之后,可能没有那么多的可用性。
    • 可用的解决方案仍然很窄,使具有独特需求的用户不确定如何进行。
  • 示例场景:

    • 提供了一个 API,该 API 抽象了数据库的创建和维护,并为用户提供了利用该平台功能所需的任何信息,例如连接字符串、机密数据的位置以及包含可观测性数据的仪表板。

第 4 级,优化 — 托管服务

平台功能透明地集成到团队已经用于完成工作的工具和流程中。某些功能是自动预配的,例如已部署服务的可观测性或身份管理。当用户到达所提供服务的边缘时,就有机会超越自动化解决方案并根据他们的需求进行定制,而无需离开内部产品,因为平台功能被视为构建块。这些构建块用于构建透明和自动的合成,以满足更高级别的用例,同时在必要时实现更深入的自定义。

  • 特性:

    • 很明显,哪些功能对组织来说是差异化的,哪些不是,允许内部团队仅在无法利用行业标准的情况下投资定制解决方案。
    • 虽然功能以一致的方式显示,但没有一种方法可以使用功能。有些最适合作为脚本中使用的 CLI 工具,而另一些则受益于集成到用户在其编辑器和 IDE 中编写代码的位置。
    • 通过关注软件开发和发布的流程,扩展了单个功能的价值,从而关注如何将功能组合到更高级别的产品中。
    • 虽然功能通常以包的形式提供,但超级用户能够分解这些更高级别的产品,以便在他们需要的时间和地点进行优化。
  • 示例场景:

    • 可观测性代理被注入到每个工作负载中,并将 OIDC 代理放置在所有应用程序的前面。
    • 默认情况下,每个新项目都会在任务运行程序(管道)和运行时环境(K8s 命名空间)中接收一个空间,但是项目可以选择其他选项,例如serverless runtime.
    • 从 Service Now 门户的目录中,用户选择“预配数据库”。Automation 预置 RDS 数据库,并发送 URL 和位置以获取用户的凭据。

运营

平台及其功能是如何规划、优先排序、开发和维护的?

平台的运营意味着在其整个生命周期内运行和支持其功能及其特性,包括接受新请求、初始版本、升级和扩展、持续维护和运营、用户支持,甚至弃用和终止。组织及其平台团队选择平台和功能来创建和维护,并可以优先考虑最有价值和最有影响力的计划。

值得注意的是,提供功能的大部分工作都是在初始发布后完成的,包括提供无缝升级、新功能和改进功能、运营支持以及最终用户支持和培训。因此,一个有影响力的、有价值的平台将提前规划和管理他们的平台,以实现长期可持续的运营和可靠性。

1 级,临时 — 根据要求

平台和功能是根据临时产品团队的请求和要求被动地开发、发布和更新的。产品团队本身甚至可能需要规划和构建他们所需的功能。

构建新功能的团队,无论是专门的集中式团队还是满足自身需求的应用程序团队,都只承担非正式的责任来支持其他人使用它。他们不需要积极维护它,也很少有流程来审查产品的质量。在这个级别中,实现通常会被忽略,直到发现安全漏洞、错误阻止使用或新需求到来,此时可以快速实施另一个反应性计划。

  • 特性:

    • 这些功能旨在满足各个应用程序团队的迫切需求。
    • 重点是核心能力的初始交付;没有制定持续维护和可持续性的计划。
    • 功能实现通常已过时,正在等待更新。
    • 对于功能的最新高影响更改(例如发现漏洞),会引入突然的工作高峰。
    • 更改可能导致计划内和计划外停机。
    • 每次升级都是以定制的方式完成的,需要时间和研究来设计每次升级的流程。
  • 示例场景:

    • Log4Shell 安全漏洞被宣布,该组织成立了一个专业团队来调查组织可能易受攻击的地方并启动补丁。一旦团队确定了影响,他们就必须与许多不同的团队携手合作,因为每个团队都以不同的方式管理他们的服务器和升级过程。即使这项工作被认为是完成的,置信度也相当低,不会发现更多的实例。

可操作 — 集中跟踪

平台和功能是集中记录和可发现的,规划和管理功能生命周期的流程至少是轻定义的。记录了每个服务和功能的责任和所有权。生命周期管理流程因功能而异,具体取决于其所有者及其优先级。集中式团队维护或能够按需生成积压工作功能清单,以提供当前功能的维护状态。这使组织能够跟踪功能提供和符合升级要求的进度。

  • 特性:

    • 应用程序团队根据需要创建新功能,以满足迫切的需求。
    • 中心团队提供整个组织中可用共享服务的登记册。
    • 松散的标准(例如需要可自动化的 API 和使用文档)适用于功能。
    • 基础架构即代码用于更轻松地跟踪已部署的服务。
    • 通过服务清单启用对 PCI DSS 或 HIPPA 等合规性法规的审核。
    • 根据燃尽图跟踪迁移和升级工作,使组织能够跟踪合规性和完成时间。
    • 跟踪并不表示支持级别;通常,此阶段的升级仍然是手动和定制的。
  • 示例场景:

    • PostgreSQL 11 将于今年年底停产。组织知道哪些数据库需要升级,并计划完成每个团队积压工作的工作。

级别 3,可扩展 — 集中启用

平台和功能不仅集中注册,而且集中编排。平台团队负责了解组织的广泛需求,并相应地确定平台和基础架构团队的工作优先级。负责某项功能的人员不仅要在技术上维护它,还要提供标准的用户体验,以便将该功能与组织内的其他相关服务集成,确保安全可靠的使用,甚至提供可观察性。

存在用于创建和发展新功能的标准流程,使组织中的任何人都可以贡献满足预期的解决方案。平台功能和特性的持续交付流程支持定期推出和回滚。计划和协调大型更改,就像它们用于面向客户的产品更改一样。

  • 特性:

    • 应用程序团队在创建服务之前,首先向平台团队请求服务。
    • 新服务必须遵循标准做法,例如标准接口、文档和治理。
    • 升级过程已记录在案,并且跨版本和服务是一致的。
    • 果功能提供商不管理升级,他们会为用户提供工具和支持,以将影响降至最低。
  • 示例场景:

    • 组织将升级到 RHEL 9。在此过程中,每个应用程序团队都需要验证其软件是否继续工作。为了启用此测试阶段,集中式计算团队正在为每个团队设置具有正确软件和操作系统版本的测试环境。

第 4 级,优化 — 托管服务

每个功能的生命周期都以标准化、自动化的方式进行管理。功能、特性和更新持续提供,对用户没有影响。平台提供商发起的任何重大更改都包括针对现有用户的迁移计划,这些计划具有明确的职责和时间表。

平台能力提供商首当其冲地承担着维护责任,但有一个明确的合同——“责任共担模型”——描述了用户的责任,使双方能够大部分自主运行。

  • 特性:

    • 共享所有权模型清楚地定义了谁负责平台及其功能以及对用户的期望。
    • Teams 编写升级执行和任何回滚策略的脚本,以保持较低的风险和影响。
  • 示例场景:

    • 虚拟机的用户不需要管理与版本升级相关的任何操作。他们唯一的要求是在他们的交付管道中有一个包含代表性烟雾测试的阶段。然后,他们被要求将其应用程序声明为具有较低的风险承受能力,以便等待完全强化的升级或更高的容忍度成为早期采用者。然后,虚拟机功能管理升级的自动发布,包括冒烟测试或金丝雀发布失败后的回滚。

度量

收集和整合反馈和学习的过程是什么?

通过对用户的显性和隐性反馈做出反应,组织可以提高用户满意度并确保平台的长期可持续性。组织必须在创新和满足用户需求之间取得平衡,以保持平台相关性。随着技术和用户偏好的变化,敏捷且对这些变化做出响应的平台将脱颖而出。定期检讨和完善反馈机制,可以进一步优化平台开发,提高用户参与度。

1 级,临时 — 临时

使用情况和满意度指标以自定义方式收集,如果有,则适用于每个平台和功能。不同能力的结果和成功衡量标准不一致,因此无法收集相应的见解。用户对平台使用情况的反馈和工具可能不会被收集,或者如果收集,将是非正式的。决策是根据轶事要求和不完整的数据做出的。

  • 特性:

    • 没有关于如何衡量平台成功的经验或意见
    • 使用熟悉的工具收集具有有限意图和深思熟虑的常见指标
    • 依赖少量数据
    • 难以确保用户参与 — 用户认为他们的反馈没有被考虑
    • 如果使用调查,则问题在运行之间会发生变化,从而否定跟踪进度的能力
  • 示例场景:

    • 平台技术主管希望通过在下一个季度计划中添加关键主题来改善与用户的协作。他们决定对用户希望看到的内容进行调查。反应是压倒性的,这令人兴奋,但也导致难以组织和回应所有的想法。虽然有些想法会影响季度计划,但用户并不认为他们的想法被接受,也不太愿意回复下一次调查。
    • 该团队希望自动捕获更多数据,因此他们寻找轻松收集的机会,例如 CI 中的测试失败。然而,并非每个团队都使用相同的 CI 自动化,因此数据仅适用于 Java 应用程序,即使一些团队已经开始使用 Scala 编写他们的服务。

级别 2,可操作 — 一致的收集

此级别的组织有一个有意的目标,即验证平台产品是否满足其内部用户市场的需求。重视可操作的、结构化的用户反馈收集。可以指派专门的团队或个人来收集反馈,以确保采用更一致的方法。反馈渠道(如调查或用户论坛)是标准化的,反馈是分类和优先排序的。除了用户反馈之外,人们还期望对用户体验进行检测,以随着时间的推移生成使用情况数据。

在将反馈转化为可操作的任务方面仍然存在挑战。虽然用户数据存储库不断增长,但组织可能需要帮助来有效地理解这些反馈并将其集成到平台路线图中。可能很难确保用户看到由他们的反馈驱动的切实变化。

  • 特性:

    • 数据收集是大多数主要规划会议或功能实施的一部分。
    • 在验证成功的确切衡量标准上可能没有达成一致。
    • 可以衡量平台功能是否成功,例如通过衡量用户采用率或节省的用户时间。
  • 示例场景:

    • 平台团队将 20% 的时间分配给用户定义的功能,他们根据调查和其他访谈技术确定这些功能。他们的研究结果被收集到一个工具中,该工具可以进行额外的投票和评论,以进一步完善优先事项。在实施过程中,会与请求用户联系,就早期设计和实施进行协作。一旦实施,就会有公告,确保请求用户了解新功能并支持采用它们。
    • 该团队专注于软件交付功能,希望自动捕获更多数据,包括周期时间,他们通过构建工具自动执行从提交到生产的整个过程。有一种理解是,周期时间可以包括其他活动,如公关审查,但目前不包括在内。

第 3 级,可扩展 — 见解

虽然已经存在强大的标准反馈机制,但在这个阶段,数据是以精心设计的方式收集的,以产生具体的战略见解和行动。确定预期的结果和结果,然后选择标准指标以指示实现这些结果的进展情况。行业框架和标准可用于从行业对某些行为的影响的研究中受益。

使用专门的团队或工具来收集和审查反馈,并总结可操作的见解。平台产品与其用户之间建立了共生关系。反馈被视为指导平台运营和路线图的战略资产。可以建立定期的反馈审查会议,跨职能团队聚集在一起,根据用户见解进行讨论和制定战略。

  • 特性:

    • 在提供任何新的平台功能之前,团队会讨论如何评估其工作的结果。
    • 该组织在表明平台计划成功的措施上有着广泛的一致性。
    • 产品经理或专门的团队成员推动持续且一致的反馈收集和分析过程。
    • 组织已经建立了要观察的指标和目标,并有目标表明成功。
  • 示例场景:

    • 该组织一直在跟踪构建时间和交付周期。然而,现在他们意识到,虽然很容易收集,但仅凭这些并不能全面了解软件交付。考虑到这一点,该团队实施了服务可靠性和稳定性的测量。

第 4 级,优化 — 定量和定性

反馈和衡量已深深融入组织文化。整个组织,从高层管理人员到整个组织的工程师,都认识到数据收集和反馈对产品演变的价值。数据正在民主化,包括平台用户和业务领导者在内的各种利益相关者积极参与确定平台改进的假设,在设计过程中提供反馈,然后在交付后衡量影响。在规划平台计划时,会考虑所有这些衡量标准。

不仅利用了标准框架,而且人们认识到,从多个角度进行测量可以创建更全面的图景。在了解定性措施如何随着定量措施的改进而变化方面进行了投资。重点是确定领先的措施,这些措施可以预测支持用户需求的功能,减轻他们的挑战,并保持领先于行业趋势和业务需求。

  • 特性:

    • 平台团队不断寻求方法来改进他们关注的指标和收集数据的方式。
    • 该组织熟悉并敏感于古德哈特定律:“当一项措施成为目标时,它就不再是一个好的措施。
    • 对收集的指标和遥测数据进行持续评估,以获得真正的见解和价值。
    • 指标数据管理得到了很好的支持,例如用于管理数据湖和获取见解的标准平台功能。
    • 鼓励跨部门协作,以避免数据孤岛并实现有效的反馈周期。
  • 示例场景:

    • 随着时间的推移,该组织收集的数据表明构建时间增加了 15% 以上。这会触发负面的开发人员体验,一旦触发,即使构建时间减少到原始时间以下,开发人员也会在更长时间内感到沮丧。这种洞察力促使构建团队设定并遵守服务级别目标 (SLO),从而在煽动用户的负面循环之前及早识别和改进。

· 阅读需 6 分钟
南哥

Kubernetes 核心维护者应该权衡提议的新功能的好处与它们带来的额外复杂性,Kubernetes 联合创始人在今年的 KubeCon 上建议。

芝加哥——顶级的 Kubernetes 工程师们一致认为:K8s 对于最终用户甚至核心维护者来说都太复杂了。是时候将复杂性纳入预算了。

在本周的 Kubecon+CloudNativeCon 大会上,Kubernetes 联合创始人兼 Google 杰出软件工程师 Tim Hockin 在周四的主题演讲中回顾了 Kubernetes 的前九年(半)以及开源软件的未来。Kubernetes 可能已经开始主要为高度可扩展的 Web 应用程序提供支持,但现在它正日益成为更复杂工作(例如机器学习推理)的首选平台,这意味着将 K8s 扩展到更多用例的压力正在显着增加。

为了帮助他的演讲,Hockin 询问了云原生社区的其他人,他们认为 Kubernetes 面临的最紧迫的挑战是什么。正如您现在可能已经猜到的那样,一个反复出现的主题是努力解决部署和维护容器编排引擎有时令人生畏的复杂性。

有人甚至说这是K8s的“最大的生存威胁”。

“有些东西必须给予,”霍金说。在一定时间内,我们可以将有限的复杂性吸收到项目中,“他说。越复杂,核心维护者在未来轻松进行更改的敏捷性就越低。

同时,软件越复杂,用户对它的抵制就越大。

围绕 Kubernetes 的软件是社区驱动的:到目前为止,已经有超过 74,000 名贡献者加入了该项目。第一代用户对 K8s 产生了兴趣,许多人努力让它变得更好。

但随着新用户的不断加入,他们将不可避免地对 Kubernetes 的工作方式产生兴趣。因此,维护者有责任让它更易于使用,Hockin指出。

“我们添加的东西越复杂,我们消耗的预算就越多。当预算用完时,坏事就会发生,“他说。创新停止了,用户转向了其他解决方案。

因此,Kubernetes 项目经理需要将复杂性视为可以利用的有限资源:某种“复杂性预算”。

霍金承认,他不知道如何衡量一个软件的复杂性,更不用说最终用户在处理复杂软件时的耐心了。

然而,他指出,工程师通常知道他们何时在预算上超支。因此,在考虑添加新功能时,他们必须问一个问题:我们是否有足够的复杂性预算来负担?这是我们应该花有限的预算吗?

工程师工作的一部分是权衡任何决策的利弊,新功能可能带来的额外复杂性应该是要评估的一个因素。

对代码库的一些增强可能会在软件的某些方面带来 5% 的性能改进,但如果它为维护者带来了更多的内部复杂性,那么它是否值得。如果一个 API 被改变以满足一个利基用例,是否值得让所有其他用户承担这种改变的负担?

“提高标准需要我们所有人愿意说不,愿意对我们真正想要的东西说不,那些不是坏主意的事情,那些本身看起来显而易见和容易的事情。老实说,公司付钱给我们的东西可能真的想要,“他说。

通过对某些提案说“不”,可以在复杂性预算中留出一些空间,以处理未来更相关的项目。

“我们必须对今天的事情说'不',这样我们明天就可以做有趣的事情,”霍金说。

Kubernetes 还有很多工作要做,但这并不意味着所有工作都需要立即完成。Hockin 说,我们都习惯于总是认为越多越好,但 Kubernetes 现在可能会遇到少等于多的情况。

正如有人向 Hockin 建议的那样:为了保持活力,Kubernetes 应该保持未完成。

· 阅读需 6 分钟
南哥

大家好,我是南哥。

Go1.21 在8月8日晚上 11 点 30 多的时候,终于发布出来了,这个版本比较重要,加入了很多新特性,下面我带大家尝鲜。

1.21.0 简介

最新的 Go 1.21版本,在 Go 1.20 六个月后发布。它的大部分更改都在工具链、运行时和库的实现中。与往常一样,该版本保持了Go 1的兼容性承诺。

Go 1.21 对版本的编号进行了一个小的更改。过去,我们使用 Go 1.N 来指代整个 Go 语言版本和发行版系列以及该系列中的第一个版本。从 Go 1.21 开始,第一个版本现在是 Go 1.N.0。今天,我们将发布 Go 1.21 语言及其初始实现 Go 1.21.0 版本。

go 现在支持向后和向前语言兼容性,大家放心升级。

语言改变

Go 1.21 为该语言添加了三个新的内置函数。

  • 新函数 min 并 max 计算固定数量的给定参数的最小(或最大 max )值
  • 新函数 clear 从 map 中删除所有元素或将 slice 的所有元素归零

对泛型函数的类型推断进行了几项改进。规范中对类型推断的描述已得到扩展和澄清

在 Go 的未来版本中,我们计划解决 Go 编程中最常见的问题之一:循环变量捕获。Go 1.21 附带了此功能的预览,您可以使用环境变量在代码中启用该功能。

标准库添加

  • 用于结构化日志记录的新日志/日志包 log/slog

  • 新的 slice 包,用于对任何元素类型的切片进行常见操作

  • 新的 map 包 ,用于对任何键或元素类型的映射进行常见操作

  • 新的 cmp 包,带有用于比较有序值的新实用程

性能改进

  • 启用 PGO 提升编译性能
  • 调整垃圾回收
  • 优化对 amd64 和 arm64 对于 trace 的CPU 消耗

支持 WASI

Go 1.21 为 WebAssembly System Interface (WASI) 添加了一个实验性端口,预览版 1 ( GOOS=wasip1 , GOARCH=wasm )。

代码

clear

Go 1.21增加了一个clear预定义函数用来做切片和map的clear操作,其原型如下:


// The clear built-in function clears maps and slices.
// For maps, clear deletes all entries, resulting in an empty map.
// For slices, clear sets all elements up to the length of the slice
// to the zero value of the respective element type. If the argument
// type is a type parameter, the type parameter's type set must
// contain only map or slice types, and clear performs the operation
// implied by the type argument.
func clear[T ~[]Type | ~map[Type]Type1](t T)

clear是针对map和slice的操作函数,它的语义是什么呢?我们通过一个例子来看一下:

package main

import "fmt"

func main() {
var sl = []int{1, 2, 3, 4, 5, 6}
fmt.Printf("before clear, sl=%v, len(sl)=%d, cap(sl)=%d\n", sl, len(sl), cap(sl))
clear(sl)
fmt.Printf("after clear, sl=%v, len(sl)=%d, cap(sl)=%d\n", sl, len(sl), cap(sl))

var m = map[string]int{
"tony": 13,
"tom": 14,
"amy": 15,
}
fmt.Printf("before clear, m=%v, len(m)=%d\n", m, len(m))
clear(m)
fmt.Printf("after clear, m=%v, len(m)=%d\n", m, len(m))
}

slog

包 slog 提供结构化日志记录,其中日志记录包括消息、严重性级别和表示为键值对的各种其他属性。

它定义了一个类型,Logger,它提供了几种方法(如 Logger.Info 和Logger.Error)来报告感兴趣的事件。

每个记录器(Logger)都与一个处理程序(Handler)相关联。记录器输出方法从方法参数创建 Record,并将其传递给处理程序,处理程序决定如何处理它。有一个默认记录器,可通过调用相应记录器方法的顶级函数(如信息和错误)访问。

日志记录(Logger)由时间、级别、消息和一组键值对组成,其中键是字符串,值可以是任何类型的。实际使用:

slog.Info("hello", "count", 3)
//2023/08/09 10:36:18 INFO hello count=3

cmp

包 cmp 提供与比较有序值相关的类型和函数,原型如下:

// Compare returns
//
// -1 if x is less than y,
// 0 if x equals y,
// +1 if x is greater than y.
//
// For floating-point types, a NaN is considered less than any non-NaN,
// a NaN is considered equal to a NaN, and -0.0 is equal to 0.0.
func Compare[T Ordered](x, y T) int {
xNaN := isNaN(x)
yNaN := isNaN(y)
if xNaN && yNaN {
return 0
}
if xNaN || x < y {
return -1
}
if yNaN || x > y {
return +1
}
return 0
}

实际使用如下:


result := cmp.Compare(2, 3)
slog.Info("2 cmp 3", "result", result)
//2023/08/09 10:39:04 INFO 2 cmp 3 result=-1

min

    minResult := min(2, 4, 5, 5, 56)
slog.Info("min 2,3,4,5,56", "result", minResult)
//2023/08/09 10:42:37 INFO min 2,3,4,5,56 result=2
标签:

· 阅读需 3 分钟
南哥

好学校还是好专业

宁做鸡头不做凤尾,选择自己喜欢的专业

选专业听父母朋友的还是自己的

父母决定不了你的人生,你不小了,可以做你想做的事了!

机械还是计算机

选计算机

提前接触行业

如果你对计算机感兴趣,欢迎加VX :mkjnnm

选择计算机专业

首先,我要为你表示祝贺和赞扬,因为你已经为自己的未来做出了一个重要的选择。计算机科学是一个极富挑战性和创新性的领域,它为你提供了无限的可能性。祝你在计算机科学领域取得辉煌的成就!加油!

特性:

  • 潜力无限:计算机科学作为一个不断发展的领域,会为你提供许多机会,包括软件开发、人工智能、数据科学和更多。
  • 改变世界:通过计算机科学,你将有能力开发出能够改变世界的技术和应用。
  • 高薪就业:计算机科学专业的毕业生通常有很高的就业率和收入水平。

大学:

  • 基础知识:务必打好基础,不仅要关注编程,还要了解计算机系统、数据结构和算法等基础知识。
  • 实践经验:理论知识很重要,但实践经验同样关键。尝试参与项目、编写代码,并逐步建立自己的作品集。
  • 持续学习:计算机科学是一个快速发展的领域,因此要保持学习的热情,关注最新的技术和趋势。
  • 拓展网络:结交同行,参加研讨会和活动,与教授和行业专家建立联系,以拓展你的人际网络。
  • 培养软技能:除了技术技能,沟通、团队合作和解决问题的能力也是非常重要的。这些软技能将帮助你在职业生涯中取得成功。

· 阅读需 8 分钟
南哥

Terraform是一种部署技术,适用于希望以代码(IaC)的形式提供和管理其基础设施的任何人。基础设施主要指云基础设施,尽管从技术上讲,任何可以通过应用程序编程接口(API)控制的东西都可以视为基础设施。基础设施即代码是通过机器可读的定义文件来管理和提供基础设施的过程。我们使用IaC来自动化过去需要手动完成的过程。

当我们谈论提供服务时,我们指的是部署基础设施的行为,与配置管理不同,后者主要处理应用程序的交付,特别是在虚拟机(VMs)上。像Ansible、Puppet、SaltStack和Chef这样的配置管理(CM)工具非常受欢迎,并且已经存在了很多年。Terraform并没有完全取代这些工具,因为基础设施提供和配置管理本质上是不同的问题。话虽如此,Terraform确实执行了许多过去由CM工具负责的功能,许多公司发现在采用Terraform后不再需要CM工具。

Terraform的基本原理是,它允许你编写人类可读的配置代码来定义你的IaC。通过配置代码,你可以在公有云、私有云和混合云的供应商中部署可重复、短暂且一致的环境

在本章中,我们首先讨论Terraform的显著特性。我们讨论了Terraform相对于其他IaC技术的优势和劣势,以及什么使Terraform成为明显的赢家。最后,我们通过部署一个单独的服务器到AWS并加入一些Terraform的更多动态特性,来看看Terraform的典型“Hello World!”。

最近关于Terraform的炒作很多,但这些炒作是否有理由呢?Terraform并不是唯一的IaC技术——有很多其他工具也能做同样的事情。那么Terraform,一种在高利润的软件部署市场空间中的技术,如何能与亚马逊、微软和谷歌等公司竞争呢?有六个关键特性使得Terraform独特,并赋予它竞争优势。

  • 提供工具 — 部署基础设施,而不仅仅是应用程序。
  • 易于使用 — 适合所有非天才人士。
  • 免费和开源 — 谁不喜欢免费的?
  • 声明式 — 说你想要什么,而不是怎么做。
  • 云服务无关 — 使用同一工具部署到任何云服务。
  • 富有表现力和可扩展性 — 你并不受语言的限制。

Terraform是一种基础设施提供工具,而不是配置管理(CM)工具。提供工具部署和管理基础设施,而像Ansible、Puppet、SaltStack和Chef这样的CM工具则在现有服务器上部署软件。一些CM工具也可以执行一定程度的基础设施提供,但不如Terraform,因为这并不是它们原本设计要做的任务。

CM和提供工具之间的区别是一种哲学问题。CM工具倾向于支持可变基础设施,而Terraform和其他提供工具则倾向于支持不可变基础设施。

可变基础设施意味着你在现有服务器上进行软件更新。相比之下,不可变基础设施并不关心现有的服务器——它将基础设施视为一种可丢弃的商品。这两种范例之间的区别可以概括为可重用与一次性的思维方式。

即使对于非程序员来说,Terraform的基础也是快速且容易学习的。到第4章的结束时,你将拥有成为中级Terraform用户所需的技能,当你思考这一点时,这是相当震惊的。当然,达到精通是另一回事,但这对大多数技能都是如此。

Terraform如此易用的主要原因是,代码是用一种特定领域的配置语言编写的,称为HashiCorp配置语言(HCL)。这是HashiCorp发明的一种语言,作为更冗长的配置语言(如JSON和XML)的替代品。HCL试图在人类可读性和机器可读性之间取得平衡,受到了该领域早期尝试(如libucl和Nginx配置)的影响。HCL与JSON完全兼容,这意味着HCL可以1:1地转换为JSON,反之亦然。这使得与Terraform之外的系统进行互操作或动态生成配置代码变得容易。

驱动Terraform的引擎叫做Terraform core,这是一个根据Mozilla公共许可证v2.0提供的免费和开源软件。该许可证规定任何人都可以使用、分发或修改软件,无论是用于私人还是商业目的。免费是非常好的,因为你永远不必担心在使用Terraform时产生额外的费用。另外,你可以完全了解产品及其运作方式。

并没有Terraform的高级版本,但是为了在大规模下运行Terraform,有商业和企业解决方案可用:Terraform Cloud和Terraform Enterprise。我们将在第6章中详细介绍这些内容;并且在第12章,我们将开发我们自己的Terraform Enterprise的仿制版本。

Terraform通过Terraform提供程序与不同的云进行集成。提供程序是为Terraform设计的插件,用于与外部API进行接口。每个云供应商都维护自己的Terraform提供程序,使Terraform能够管理该云中的资源。提供程序是用golang编写的,并以二进制形式在Terraform注册表(https://registry.terraform.io)上分发。它们处理所有的认证、API请求、超时和错误处理等程序逻辑。注册表上有数百个已发布的提供程序,它们共同使你能够管理数千种不同的资源。你甚至可以编写自己的Terraform提供程序,我们将在第11章中讨论。

· 阅读需 8 分钟
南哥

背景

多年来,Kubernetes 已成为全世界的话题。它彻底改变了容器的编排,并已成为该领域的领导者。许多开发人员喜欢使用 Kubernetes。虽然组织更喜欢在 Kubernetes 上部署应用程序以应对规模和苛刻的资源,但与 Kubernetes 相关的部署正在流行一种新的方法 - GitOps。

是的,GitOps 提供了一种流畅的方法和一组实践来利用 Git 等简单工具来管理基础结构和应用程序部署。通过结合 Kubernetes 和 GitOps,组织可以获得灵活性、敏捷性、规模、性能、效率和更快的功能交付的巨大好处。

在这本 Kubernetes 和 GitOps 指南中,我有一个分步的初学者级教程,用于开始使用 Kubernetes 实现 GitOps。是时候将应用程序部署提升到一个新的水平了。让我们开始吧!

简单的 GitOps 工作流

GitOps 基本上的工作原理是让 Git 成为事实的来源,包括将所有内容移动到代码中以及在 Git 中存储和维护所有内容。在部署方面,请使用运算符以声明方式部署在 Git 和 Yaml 中配置的内容。由于所有开发人员主要对 Git 友好,因此 GitOps 简化了他们复杂的工作流程。

因此,当涉及到 Kubernetes 时,应用程序代码、容器映像和所有相关清单文件都将存储在 Git 中,任何更改都将通过 Git 作为单一事实来源进行。

今天,我们将在下面的教程中向您展示如何开始使用应用程序的 GitOps 方法。

先决条件

  • 在本教程中,我们将使用持续交付工具(如 Harness)来执行 GitOps。因此,创建一个免费的Harness帐户。它使用Argo CD-as-a-Service。
  • GitHub 帐户和要试验的示例存储库。我有一个示例存储库,您可以fork并使用。

教程

注册到 harness 帐户,验证电子邮件,然后重新登录以设置 GitOps Pipeline 。您将看到以下部署选项 - Kubernetes 和 Kubernetes with GitOps。选择“Kubernetes with GitOps”并继续。

您不必担心任何设置和安装。安全带可以照顾一切。它通过预配托管代理连接到 Harness。 您可以单击“配置”并等待一段时间,以便为您的代理显示绿色复选框。

成功安装代理后,请转到下一个配置,在这里,我们提供简单的详细信息,例如源,身份验证和Git详细信息。

从选项中选择 Git 并拥有源代码。添加我们的 Git 存储库链接 - https://github.com/pavanbelagatti/argocd-example-apps

注意:上面显示的是我的 GitHub 存储库链接,您应该添加您的存储库链接,即您在本教程开头 fork 的链接。

添加这些详细信息后,请确保添加“匿名”以验证您的详细信息。[顺便说一句,这是一个公共存储库,因此不需要用户名和密码进行身份验证]

确保身份验证成功。

接下来,让我们添加其他必需的 Git 详细信息,如下所示。

选择“Target revision”作为“master”,选择“Path”作为“helm-guestbook”

接下来,选择“Harness Hosted”以测试 GitOps 工作流。您也可以选择自我管理。但在本教程中,我们将选择“Harness Hosted”。

单击“Connect to Cluster”按钮并确保连接成功。

接下来,您将看到最后一步,我们将全部准备好部署应用程序。

单击“Create and Sync Application”。

这是您将输入的 GitOps 仪表板,所有 GitOps 详细信息都将在其中显示。

您将看到“Sync”状态正在运行。

在一两分钟内,我们可以看到成功消息。

您可以从“Resource View”开始检查每个选项卡

这些是下面显示的“App Details”选项卡功能。

在同一选项卡中,您可以看到同步策略,它设置为“手动”,将其更改为“自动”。

这意味着,当 GitHub 存储库发生任何更改时,GitOps 代理将自动选择这些更改,并以自动方式进行同步。

下一个选项卡显示应用程序的同步状态。

你可以看到集群实时应用拓扑图。

这是我们来自示例存储库的 values.yaml 文件。

# Default values for helm-guestbook.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.

replicaCount: 4

image:
repository: gcr.io/heptio-images/ks-guestbook-demo
tag: 0.1
pullPolicy: IfNotPresent

service:
type: ClusterIP
port: 80

ingress:
enabled: false
annotations: {}
# kubernetes.io/ingress.class: nginx
# kubernetes.io/tls-acme: "true"
path: /
hosts:
- chart-example.local
tls: []
# - secretName: chart-example-tls
# hosts:
# - chart-example.local

resources: {}
# We usually recommend not to specify default resources and to leave this as a conscious
# choice for the user. This also increases chances charts run on environments with little
# resources, such as Minikube. If you do want to specify resources, uncomment the following
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
# limits:
# cpu: 100m
# memory: 128Mi
# requests:
# cpu: 100m
# memory: 128Mi

nodeSelector: {}

tolerations: []

affinity: {}

现在,将 replicaCount: 4 从 4 更改为 5。

您应该看到 GitOps 代理将看到此差异并将应用此差异。突然,应用程序配置不同步。需要一些时间来匹配并返回到正常且成功的同步状态。

可以看到第二个部署为“自动化”,因为我们将同步策略更改为自动化。

在上面的资源视图中,您可以看到副本已匹配到 5,因为我们想要 5 个副本。

由于 GitOps 使用 Git 作为事实来源,它会记录谁提交了什么代码,以及是否有人更改了存储库中的某些内容。您可以从我们的 GitOps 仪表板中看到这一点。

这就是使用 Harness CD 通过 GitOps 方式部署应用程序的直观和简单之处。

Kubernetes GitOps 是处理复杂云原生应用程序部署的绝佳方法。由于它使用开发人员已经知道的像 Git 这样的简单工具,因此可以轻松学习和简化应用程序部署方法。使用 Kubernetes GitOps 使您的应用程序更加稳定、敏捷和高效。立即开始使用 GitOps!

· 阅读需 18 分钟
南哥

“GitOps”和“服务网格”可能不是你立即想到的东西 - 但也许它们应该是!这两种截然不同的技术各自具有巨大的独立能力,并且它们结合起来提供的远远超过它们各部分的总和。在这篇博文中,我将向您介绍在现实世界中同时使用 Flux、Flagger 和 Linkerd 以实现成功的 GitOps 需要了解的内容。

我们为什么在这里?

不过,首先,让我们谈谈在静态文本博客文章的结构中我们能做什么和不能做什么。这篇文章本身不会让你成为 GitOps 专家。GitOps 很复杂,实践没有实际的替代品。你不能通过阅读博客文章来获得这一点。

不过,我们在这里可以提供的是仔细研究使 GitOps 实际工作的好、坏和丑陋。我们将讨论概念和惯例,讨论哪些有效,哪些无效,我们将使您能够充分利用您以后投入的实践

最后,不要忘记我们有一个现成的演示存储库供您练习!您可以在 https://github.com/BuoyantIO/gitops-linkerd 中找到它 - 查看其 README.md 以获取完整说明。

GitOps 简介

如果你是 GitOps 的新手,你可能会发现所有关于“持续部署”和“单一不可变事实来源”的定义都令人困惑。出于我们的目的查看 GitOps 的一种简单方法是,这是一种管理集群配置的方法,方法是将我们想要的配置放在 git 存储库中,然后拥有使集群与存储库匹配的软件。

换句话说,您不会通过运行 kubectl apply 来更改集群:使用 Git 提交来进行更改。

这似乎是一种倒退,但这是完成生产中非常重要的两件事的绝佳方式:

  • 您始终可以确切地知道您的集群正在运行什么配置。
  • 您始终可以知道谁进行了特定更改。

这两件事为许多好东西打开了大门,因为了解集群的状态意味着您可以轻松复制它。知识就是力量。在引擎盖下,我们将使用来自WeaveWorks的Flux和Flagger来完成这项工作。

Flux

Kubernetes 集群无法与 git 存储库进行本机交互。Flux 是一种弥合差距的工具:Flux 代理在群集中运行,并监视存储库和群集中的更改。每当它注意到更改(在任一位置)时,它都会执行任何需要执行的操作以使群集看起来像存储库。

注意:Flux 只会使集群看起来像存储库。没有规定走另一个方向,因为这将是一个糟糕的主意!GitOps 的全部意义在于 git 存储库包含您想要的状态的真相,因此允许存储库修改它不会是一种反模式。

Flux 相当简单:它可以从 GitHub 或 GitLab 读取 Git 存储库,并将其指向存储库中的目录,该目录包含定义 Flux Kustomization 的 YAML 文件。库造口定义包括三个关键组件:

  • 源告诉 Flux 去哪里读取集群中应该存在的基本资源。源可以是 Git 存储库或 Helm 图表中的目录。
  • 一组可选的补丁(标准 JSONpatch 定义)告诉 Flux 如何在将基本资源应用于集群之前对其进行修改。
  • 一个可选的依赖项列表告诉 Flux 在应用此依赖项之前必须应用哪些其他 Kustomization。

这三者的组合非常强大,同时相对简单(尽管我将是第一个承认JSONpatch并不总是令人愉快的使用)。稍后,我们将深入探讨如何处理 Kustomization,以及典型的 Kustomization 可能是什么样子。

Flagger

Flagger是Flux的姊妹篇,专门处理渐进式交付。这个想法是,当您部署工作负载的新版本时,您应该慢慢地将流量增加到它以确保新版本能够正常工作,而不是立即将所有流量削减到新的(可能损坏的)版本。

Flagger最初看起来很奇怪的是,您没有明确提供“请立即进行渐进式推出”的资源。相反,您只需编辑一个部署,Flagger 就会从那里获取它:它会注意到对其管理下的对象的任何更改,并自动调整集群中的内容以设置渐进式部署。

这意味着 Flagger 需要一种方法来控制流向新版本的流量。它不会直接执行此操作:相反,它需要更改系统其他部分的配置以实际进行流量转移。Flagger对此有几种不同的选择:

  • 对于调用图顶部的工作负载,它可以直接与多个入口控制器一起使用;
  • 它可以对调用图中任何位置的流量使用 SMI 流量拆分;或
  • 它可以使用Gateway API HTTPRoutes。

(目前,Linkerd依赖于SMI TrafficSplit机制。稍后会详细介绍。

Linkerd

如果您之前没有运行过 Linkerd,它是一个服务网格:一个在平台级别提供安全性、可靠性和可观测性功能的基础结构层,而无需修改您的应用程序。事实上,它是目前唯一的 CNCF 分级服务网格,可提供出色的安全性、一流的操作简便性和任何生产服务网格中最小的开销。

与大多数其他网格一样,Linkerd 的工作原理是在每个工作负载容器旁边放置一个 sidecar 代理,并允许 sidecar 拦截进出工作负载的所有流量。这种低级访问使 Linkerd 能够对集群中网络通信的情况进行巨大的控制和可见性。

Linkerd 同时支持 SMI TrafficSplit 资源和(从 2.12 开始)网关 API HTTPRoute 资源。但是,在 2.12 和 2.13 中,Linkerd 的 HTTPRoute 支持是有限的,这意味着 Flagger 需要使用 SMI TrafficSplit 接口。

付诸实践:Flux

与许多事情一样,从基本理论到实际实践的跳跃可能很棘手。一个好的开始方法是使用上面提到的演示存储库,https://github.com/BuoyantIO/gitops-linkerd。它的 README.md 提供了有关如何运行一切的完整说明,但让我们在这里也了解亮点和陷阱。

首先,您需要有一个空集群、一个有效的 kubectl 命令和 flux CLI。查看 https://fluxcd.io/flux/installation/ 以获取完整说明,但在 Mac 和 Linux 上的简单方法是 brew install fluxcd/tap/flux 。

存储库布局和 flux bootstrap

需要了解的非常重要的一点是,在使用 Flux 时,您通常会设置所有 Kustomization,将 Flux 安装到本地机器上,然后运行 flux bootstrap 告诉 Flux 为您设置集群中的所有内容!任何时候都不需要手动设置群集。

运行 flux bootstrap 时,您告诉 Flux 要使用的 git 存储库,以及该存储库中的分支和路径,以开始在存储库中查找其配置。这就引出了两个非常重要的点:

  • Flux 需要访问你的 Git 存储库,这通常意味着它需要访问 GitHub 或 GitLab,这意味着你需要设置一个访问令牌供 Flux 使用。有关此处的完整详细信息,请查看 https://fluxcd.io/flux/installation/#bootstrap - 但问题是 Flux 需要能够写入和读取(例如,使用 GitHub 需要能够创建部署密钥)。请仔细阅读有关设置令牌的权限的信息。
  • 如果你想理解一个 Flux 设置,你需要知道给了 flux bootstrap 什么分支和路径,这样你就会知道从哪里开始阅读以了解发生了什么。

在这篇博文中,我们不会包含 gitops-linkerd 的完整 flux bootstrap 命令:我们希望专注于概念和陷阱,而不是设置 Git 权限等的所有细节。查看 gitops-linkerd 存储库中的 README.md ,了解所有引导程序详细信息。

但是,在我们的 gitops-linkerd 存储库配置中非常值得一看。其配置的起点是 main 分支上的 clusters/my-cluster 目录,你将在其中找到群集基础结构所需的所有定义以及对应用程序本身的另一个存储库的引用。如果要将其用于自己的 Flux/Flagger/Linkerd 设置,一个好的开始是保留群集基础结构,但将应用程序定义替换为您自己的定义。

  • infrastructure.yaml 告诉 Flux 要设置的集群基础架构;
  • apps.yaml 告诉 Flux 我们想要在该基础架构上运行的应用程序;和
  • flux-system 是自定义 Flux 本身的目录。在这篇博文中,我们不会进入 flux-system ,但很高兴知道它是什么。

“基础架构”和“应用程序”之间的划分是模糊的,而且在很大程度上是约定俗成的,但如果您想使用 gitops-linkerd 作为您自己的集群定义的基础,您可以先关注 apps.yaml ,而不考虑集群基础设施。

gitops-linkerd 集群基础架构

infrastructure.yaml 为群集基础结构定义了五个单独的组件。其中每个都由此 YAML 文件中的单独文档表示:

  • cert-manager
  • Linkerd
  • NGINX
  • Flagger
  • Weave GitOps

(回想一下,Flux本身是我们唯一手动安装的东西。此外,Weave GitOps 是 Flux 的仪表板;在 https://www.cncf.io/blog/2023/04/24/how-to-use-weave-gitops-as-your-flux-ui/ 查看。

重要的是, infrastructure.yaml 还定义了这些组件之间的依赖关系;这是Flux的一个特别强大的方面。我们将在这里快速浏览前两个元素: cert-manager 和 linkerd 。

cert-manager

infrastructure.yaml 中的第一个文档如下所示:

---
apiVersion: kustomize.toolkit.fluxcd.io/v1beta2
kind: Kustomization
metadata:
name: cert-manager
namespace: flux-system
spec:
interval: 1h
retryInterval: 1m
timeout: 5m
prune: true
wait: true
sourceRef:
kind: GitRepository
name: flux-system
path: ./infrastructure/cert-manager

这里有几件事需要了解:

name: cert-manager sets the name of the Kustomization. This is how we’ll refer to this component when describing dependencies.

namespace: flux-system places the Kustomization itself in the flux-system namespace; this does not mean that cert-manager will live in flux-system, though.

按照惯例, flux-system 是群集基础结构核心元素的主页,其他命名空间用于应用程序。

  • 没有 dependsOn 属性,因此此库斯托姆化不依赖于任何东西。
  • sourceRef 有点神奇:提到 flux-system GitRepository 实际上意味着“与 Kustomization 本身相同的 Git 存储库”。
  • path: ./infrastructure/cert-manager 告诉我们在源中的哪个位置查找此 Kustomization 的更多文件。
  • wait: true 表示 Flux 将等待安装的所有内容准备就绪,然后再继续其他库Kustomizations。
  • interval: 1h 表示 Flux 将每小时检查一次,以查看是否有需要处理的新更改。

如果我们查看 ./infrastructure/cert-manager ,我们会找到一些文件:

kustomization.yaml
namespace.yaml
release.yaml
repository.yaml

开始阅读的地方始终是 kustomization.yaml ,这在这里很简单:

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: cert-manager
resources:
- namespace.yaml
- repository.yaml
- release.yaml

这会告诉 Flux 应用这三个 YAML 文件。我们不会在这里深入探讨它们 - gitops-linkerd 演示更详细 - 但重要的是要知道

  • namespace.yaml 创建 cert-manager 命名空间;
  • repository.yaml 告诉 Flux 到 helm repo add 一个 Helm 存储库;和
  • release.yaml 告诉 Flux 到 helm install 一个由 repository.yaml 添加的存储库中的图表。

请注意,这实际上是一个无序列表: kustomize 会自动对所有这些文件中包含的所有资源进行排序,以确保它正在使用的资源按正确的顺序应用。

我们将在 gitops-linkerd 演示本身中深入研究这些文件,除了一个注意事项:如果您查看 repository.yaml 和 release.yaml ,您会发现它们在 cert-manager 命名空间中定义资源,而不是 flux-system 命名空间。这是您将一次又一次看到的模式:Kustomization 管理的资源应位于适合所管理组件的命名空间中。

因此,要从中获取的三个重要概念是:

  • 您不必在 Kustomization 中应用任何补丁,尽管它的名字。
  • 您可以在 Kustomization 中应用 Kubernetes 资源和更高级别的 Flux 资源。
  • Kustomization 创建和管理的资源属于组件的相应命名空间,而不是 flux-system 。

当您查看 gitops-linkerd 定义时,您会一遍又一遍地看到这些相同的概念。

The linkerd component

infrastructure.yaml 中的第二个文档定义了 linkerd 个组件:

---
apiVersion: kustomize.toolkit.fluxcd.io/v1beta2
kind: Kustomization
metadata:
name: linkerd
namespace: flux-system
spec:
dependsOn:
- name: cert-manager
interval: 1h
retryInterval: 1m
timeout: 5m
prune: true
wait: true
sourceRef:
kind: GitRepository
name: flux-system
path: ./infrastructure/linkerd

其中大部分与 cert-manager Kustomization 一致:我们有一个 name ,我们仍然在 flux-system 命名空间中,我们会在 ./infrastructure/linkerd 中找到更多文件,等等。

主要区别在于新的 dependsOn 属性,它表示 linkerd Kustomization取决于 cert-manager Kustomization。(另请注意, dependsOn 采用数组值,因此您可以列出许多依赖项。这是 Flux 最强大的功能之一:定义复杂的开始排序只是解释什么取决于什么,然后让 Flux 完成所有艰苦的工作。

快速浏览一下 ./infrastructure/linkerd 目录,我们会发现比 cert-manager 要阅读的内容要多得多:

README.md
ca.crt
ca.key
kustomization.yaml
kustomizeconfig.yaml
linkerd-certs.yaml
linkerd-control-plane.yaml
linkerd-crds.yaml
linkerd-smi.yaml
linkerd-viz.yaml
namespaces.yaml
repositories.yaml

不过,和以前一样,开始阅读的地方仍然是 kustomization.yaml 。它更复杂,因为我们正在安装四个独立的 Linkerd 组件(它的 CRD、控制平面、SMI 扩展和可视化扩展),我们需要将 Linkerd 配置为使用来自 cert-manager 的自定义机密 - 但您将能够看到它们全部布置在文件中。

同样,我们主要将深入探讨留给 gitops-linkerd 演示,但值得指出的是, cert-manager Kustomization 有一个 repository.yaml 文件, linkerd Kustomization 有 repositories.yaml ,名称是复数的。名称对 Flux 来说根本不重要,因为它必须在 kustomization.yaml 中明确列出:这意味着您可以自由选择名称来帮助后来的读者了解正在发生的事情。

infrastructure.yaml 文件中还有很多内容,但我们将把其余部分留给 gitops-linkerd 演示和您自己的阅读。让我们继续使用该应用程序。

更多

https://www.cncf.io/blog/2023/05/25/real-world-gitops-with-flux-flagger-and-linkerd/

· 阅读需 8 分钟
南哥

反向代理是什么

在计算机网络中,反向代理是一种代理服务器,它代表客户端从一个或多个服务器检索资源。然后,这些资源将返回到客户端,就好像它们源自 Web 服务器本身一样。与正向代理相反,正向代理是其关联客户端联系任何服务器的中介,反向代理是任何客户端联系其关联服务器的中介。有许多工具,例如 提琴手 , Tinyproxy 可以帮助您做到这一点,主要用于调试网络。

经过一些修改的反向代理可以帮助修改/过滤/路由请求以获取资源。如果在同一实例中运行许多服务,则可以使用 reveres 代理将适当的请求路由到适当的资源。

教程目标

这篇文章是一种教程,将解释开发反向代理所涉及的事情,该代理将拦截http调用,打印请求/响应正文并通过响应时间等帮助进行性能分析。Golang 的 net/http pkg 附带了客户端-服务器通信所需的大多数实现。您需要做的就是了解该功能并在需要时使用它,我们将使用golang这门语言来进行演示。

正文

假设您有一个可以通过 http 在某个端口访问的服务,但您不希望它被公开,或者您想添加一些自定义规则,或者您想在接口上进行一些性能分析,那么您可以使用反向代理。

在此示例中,我们将通过将来自服务器 one(在任意 9090 端口上运行)的所有 Web 请求转发到某处的另一个服务器来演示反向代理的作用,假设 http://127.0.0.1:8080

  • 反向代理 golang 服务器将在 9090 端口上运行。
  • 向服务器发出的所有请求都将透明地转发到目标Web服务器,并将响应发送到第一台服务器。
  • 在转发请求之前,将捕获请求正文。感谢ioutil pkg的ReadAll和NopCloseer函数,它有助于复制请求正文而无需修改请求缓冲区。
  • 我们还捕获了原始网络服务器为每个路径提供请求所花费的时间。

让我们有一个名为 Prox 的简单结构,它将处理反向代理的业务逻辑。

以下是一些结构体用法和带有 Go 接收器的指针方法接收器的示例。

Simple Proxy

type Prox struct {
target *url.URL
proxy *httputil.ReverseProxy
}

func NewProxy(target string) *Prox {
url, _ := url.Parse(target)
return &Prox{target: url, proxy: httputil.NewSingleHostReverseProxy(url)}
}

func (p Prox) handle(w http.ResponseWriter, r http.Request) { w.Header().Set("X-GoProxy", "GoProxy") p.proxy.Transport = &myTransport{} p.proxy.ServeHTTP(w, r) }

如您所见,没有太多代码。我们只需要发送目标网址,NewProxy 函数将返回一个 Prox 结构对象。

func (p *Prox) handle(w http.ResponseWriter, r *http.Request) {
w.Header().Set("X-GoProxy", "GoProxy")
p.proxy.Transport = &myTransport{}
p.proxy.ServeHTTP(w, r)
}

由于我们想捕获请求/响应正文或为每个请求添加一些自定义规则,因此我们必须更改传输接口。因此,我们创建了自己的传输往返函数,并将其分配给代理。我们之前创建的运输。

type myTransport struct {
}


func (t *myTransport) RoundTrip(request *http.Request) (*http.Response, error) {

buf, _ := ioutil.ReadAll(request.Body)
rdr1 := ioutil.NopCloser(bytes.NewBuffer(buf))
rdr2 := ioutil.NopCloser(bytes.NewBuffer(buf))

fmt.Println("Request body : ", rdr1)
request.Body = rdr2


response, err := http.DefaultTransport.RoundTrip(request)
if err != nil {
print("\n\ncame in error resp here", err)
return nil, err //Server is not reachable. Server not working
}

body, err := httputil.DumpResponse(response, true)
if err != nil {
print("\n\nerror in dumb response")
// copying the response body did not work
return nil, err
}

log.Println("Response Body : ", string(body))
return response, err
}

多亏了 Go 的时间包,我们可以测量函数所花费的时间,在我们的例子中是原始服务器的响应时间。我们修改了往返函数以测量每条路径所花费的时间。我们添加了代码,以便对于特定路径,我们有进行的http调用次数,所有调用所花费的时间,平均时间等。


var globalMap = make(map[string]Montioringpath)

func (t *myTransport) RoundTrip(request *http.Request) (*http.Response, error) {
start := time.Now()
response, err := http.DefaultTransport.RoundTrip(request)
if err != nil {
print("\n\ncame in error resp here", err)
return nil, err //Server is not reachable. Server not working
}
elapsed := time.Since(start)

key := request.Method + "-" + request.URL.Path //for example for POST Method with /path1 as url path key=POST-/path1

if val, ok := globalMap[key]; ok {
val.Count = val.Count + 1
val.Duration += elapsed.Nanoseconds()
val.AverageTime = val.Duration / val.Count
globalMap[key] = val
//do something here
} else {
var m Montioringpath
m.Path = request.URL.Path
m.Count = 1
m.Duration = elapsed.Nanoseconds()
m.AverageTime = m.Duration / m.Count
globalMap[key] = m
}
b, err := json.MarshalIndent(globalMap, "", " ")
if err != nil {
fmt.Println("error:", err)
}

body, err := httputil.DumpResponse(response, true)
if err != nil {
print("\n\nerror in dumb response")
// copying the response body did not work
return nil, err
}

log.Println("Response Body : ", string(body))
log.Println("Response Time:", elapsed.Nanoseconds())
}

main

Go 的标志 pkg 有助于在运行程序时接受命令行参数。我们可以通过命令行参数设置 http 端口(代理服务器将运行的位置)和重定向 url(需要路由 http 请求的位置)。

func main() {
const (
defaultPort = ":9090"
defaultPortUsage = "default server port, ':9090'"
defaultTarget = "http://127.0.0.1:8080"
defaultTargetUsage = "default redirect url, 'http://127.0.0.1:8080'"
)

// flags
port = flag.String("port", defaultPort, defaultPortUsage)
redirecturl = flag.String("url", defaultTarget, defaultTargetUsage)

flag.Parse()

fmt.Println("server will run on :", *port)
fmt.Println("redirecting to :", *redirecturl)

// proxy
proxy := NewProxy(*redirecturl)

http.HandleFunc("/proxyServer", ProxyServer)

// server redirection
http.HandleFunc("/", proxy.handle)
log.Fatal(http.ListenAndServe(":"+*port, nil))
}

如果在运行程序时未设置参数,则默认端口集为 9090,请求将路由到 http://127.0.0.1:8080

运行

如果要在 9090 上托管反向代理并将请求重定向到端口 5000 ,请运行以下命令

./ReverseProxy -port=9090 -url=http://localhost:5000

当您运行反向代理服务器时,它将打印运行反向代理的端口以及将请求重定向到的位置。

以下屏幕截图显示了通过反向代理发出登录 POST 请求之一后捕获的内容。

· 阅读需 14 分钟
南哥

什么是 Argo CD

ArgoCD 是使用 Kubernetes 持续交付的流行工具。它通过不断协调 repo 的状态与实时工作负载,自动将应用程序部署到 Kubernetes 集群中。

GitOps模型是Argo设计中不可或缺的一部分。它使 repo 成为应用程序所需状态的单一事实来源。应用所需的所有 Kubernetes 清单、Kustomize 模板、Helm charts 和配置文件都应提交到您的存储库。这些资源“声明”应用的成功部署。

Argo 将声明的状态与集群中实际运行的状态进行比较,然后应用正确的更改来解决任何差异。此过程可以配置为自动运行,防止集群偏离存储库。每当出现差异时,Argo 都会重新同步状态,例如在您手动运行 Kubectl 命令之后。

Argo带有CLI和Web UI。它支持多租户和多集群环境,与 SSO 提供程序集成,生成审计跟踪,并可以实施复杂的 rollout 策略,例如 Canary 部署和蓝/绿升级。它还提供集成的回滚功能,因此您可以快速从部署故障中恢复

从历史上看,大多数 CI/CD 实现都依赖于推送驱动行为。这需要您将集群连接到 CI/CD 平台,然后在管道中使用 Kubectl 和 Helm 等工具来应用 Kubernetes 的更改

Argo是一个基于拉动的CI / CD系统。它运行在您的 Kubernetes 集群中,并从您的存储库中提取源代码。然后,Argo 无需手动配置管道即可为您应用更改。

此模型比基于推送的工作流更安全。您不必公开集群的 API 服务器或在 CI/CD 平台中存储 Kubernetes credentials。破坏源存储库只会使攻击者能够访问您的代码,而不是你的集群。

为什么选择Argo CD?

应用程序定义、配置和环境应具有声明性和版本控制。应用程序部署和生命周期管理应该是自动化的、可审计的且易于理解的。

快速入门

前置条件

  • 安装 kubectl 命令行工具
  • 有一个 kubeconfig 文件(默认位置是 ~/.kube/config)

安装命令

kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

这将创建一个新的命名空间 argocd ,Argo CD 服务和应用程序资源将驻留在其中。

提示

安装清单包括引用 argocd 命名空间的 ClusterRoleBinding 资源。如果要将Argo CD安装到不同的命名空间中,请确保更新命名空间引用

此默认安装将具有自签名证书,如果不进行一些额外的工作,则无法访问。执行以下操作之一:

  • 按照说明配置证书(并确保客户端操作系统信任它)
  • 将客户端操作系统配置为信任自签名证书
  • 在本指南中的所有 Argo CD CLI 操作上使用 --insecure 标志

Argo的所有组件可能需要几秒钟才能在您的集群中运行。通过使用 Kubectl 列出 argocd 命名空间中的部署来监视进度。

$ kubectl get deployments -n argocd
NAME READY UP-TO-DATE AVAILABLE AGE
argocd-applicationset-controller 1/1 1 1 67s
argocd-dex-server 1/1 1 1 67s
argocd-notifications-controller 1/1 1 1 67s
argocd-redis 1/1 1 1 67s
argocd-repo-server 1/1 1 1 67s
argocd-server 1/1 1 1 67s

Kubectl 端口转发也可用于连接到 API 服务器,而无需公开服务

kubectl port-forward svc/argocd-server -n argocd 8080:443

实际示例:使用 Argo CD 部署到 Kubernetes

让我们使用 Argo 在 Kubernetes 中运行一个基本的 NGINX Web 服务器实例。我们假设您已经可以访问 Kubernetes 集群,并且您的机器上已经拥有可用的 Kubectl 和 Helm CLI。

创建应用的 GitHub 存储库

首先,前往 GitHub 并为您的应用程序创建一个新的存储库。之后,将您的存储库克隆到您的计算机,准备提交您的 Kubernetes 清单

$ git clone https://github.com/<username>/<repo>.git

复制以下 YAML 并将其另存为 deployment.yaml 在存储库中

apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
namespace: argo-demo
labels:
app.kubernetes.io/name: nginx
spec:
replicas: 3
selector:
matchLabels:
app.kubernetes.io/name: nginx
template:
metadata:
labels:
app.kubernetes.io/name: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- name: http
containerPort: 80

它定义了一个运行三个 NGINX 副本的基本 Kubernetes 部署对象

接下来,复制第二个 YAML 文件并将其保存到 service.yaml 。它会设置负载均衡器服务以在群集外部公开部署

apiVersion: v1
kind: Service
metadata:
name: nginx
namespace: argo-demo
spec:
type: LoadBalancer
selector:
app.kubernetes.io/name: nginx
ports:
- protocol: TCP
port: 80
targetPort: http

最后,添加一个将创建应用程序命名空间的清单:

apiVersion: v1
kind: Namespace
metadata:
name: argo-demo

将更改提交到存储库,然后将其推送到 GitHub:

$ git add .
$ git commit -m "Added initial Kubernetes YAML files"
$ git push

您已准备好安装 Argo 并开始部署您的应用程序。

获取 Argo 命令行界面

Argo的CLI允许您从终端与应用程序进行交互。稍后您将需要它来向 Argo 实例注册您的应用程序。

您可以从 GitHub 下载最新的 CLI 版本。为您的平台选择正确的二进制文件,然后使其可执行并将其移动到路径中的某个位置。以下步骤适用于大多数 Linux 系统 - 首先替换最新版本号而不是下面的 2.6.1:

$ wget https://github.com/argoproj/argo-cd/releases/download/v2.6.1/argocd-linux-amd64
$ chmod +x argocd-linux-amd64
$ mv argocd-linux-amd64 /usr/bin/argocd

在登录之前,您需要检索默认管理员用户的密码。这是在Argo的安装过程中自动生成的。可以通过运行以下 argocd 命令来访问它:

使用这些凭据登录到Argo

进入后,直接转到左侧边栏中的“用户信息”项,然后单击屏幕顶部的“更新密码”按钮。按照提示将您的密码更改为唯一的密码

Login to the CLI 登录到命令行界面

要登录到 Argo CLI,请运行 argocd login 并提供 API 服务器的 URL 作为参数:

$ argocd login localhost:8080

与上面遇到的浏览器警告类似,如果您尚未配置自己的TLS,系统将提示您接受Argo的内置自签名证书:

通过键入 y 并按回车键接受提示。然后,系统会要求您输入用户名和密码。CLI 应成功向您的 Argo 实例进行身份验证:

'admin:login' logged in successfully
Context 'localhost:8080' updated

使用 Argo 部署您的应用程序

一切准备就绪,可以开始将应用程序部署到 Argo!首先,运行以下 CLI 命令来注册应用:

$ argocd app create argo-demo \
--repo https://github.com/<username>/<repo>.git \
--path . \
--dest-server https://kubernetes.default.svc \
--dest-namespace argo-demo
application 'argo-demo' created

让我们解释这里发生的事情:

  • --repo 标志指定 Git 存储库的 URL。
  • --path 标志指示 Argo 在存储库的此路径中搜索 Kubernetes 清单、Helm 图表和其他可部署资产。 此处使用 . 是因为示例清单存储在存储库的根目录中。
  • --dest-server 标志指定要部署到的 Kubernetes 群集的 URL。在部署到运行 Argo 的同一群集时,可以使用 kubernetes.default.svc 。
  • --dest-namespace 设置应用将部署到的 Kubernetes 命名空间。这应与资源上设置的 metadata.namespace 字段匹配。

您的应用程序现在将在 Argo 中注册。您可以使用 argocd app list 命令检索其详细信息:

NAME              CLUSTER                         NAMESPACE   PROJECT  STATUS     HEALTH   SYNCPOLICY  CONDITIONS  REPO                                                   PATH  TARGET
argocd/argo-demo https://kubernetes.default.svc argo-demo default OutOfSync Missing <none> <none> https://github.com/ilmiont/spacelift-argo-cd-demo.git

该应用程序还显示在Argo UI中:

Your First Sync 您的首次同步

应用显示为“缺失”和“不同步”。创建应用不会自动将其同步到群集中。立即执行同步,让 Argo 应用存储库内容当前定义的目标状态:

$ argocd app sync argo-demo
...
GROUP KIND NAMESPACE NAME STATUS HEALTH HOOK MESSAGE
Namespace argo-demo argo-demo Running Synced namespace/argo-demo created
Service argo-demo nginx Synced Progressing service/nginx created
apps Deployment argo-demo nginx Synced Progressing deployment.apps/nginx created
Namespace argo-demo Synced

同步结果显示在您的终端中。应会看到命名空间、服务和部署对象都同步到群集中,如上面的命令输出所示。所有三个对象的消息都确认它们已成功创建。

重复 apps list 命令以检查应用的新状态

$ argocd app list
NAME CLUSTER NAMESPACE PROJECT STATUS HEALTH SYNCPOLICY CONDITIONS REPO PATH TARGET
argocd/argo-demo https://kubernetes.default.svc argo-demo default Synced Healthy <none> <none> https://github.com/ilmiont/spacelift-argo-cd-demo.git .

现在应用程序已同步且健康!它在Argo UI中也是绿色的:

作为最终证明,请使用 Kubectl 检查应用命名空间中的部署。这应确认 nginx 已启动并运行三个副本:

$ kubectl get deployment -n argo-demo
NAME READY UP-TO-DATE AVAILABLE AGE
nginx 3/3 3 3 7m56s

Syncing App Updates 同步应用更新

现在,让我们对应用进行更改。修改 deployment.yaml 中的 spec.replicas 字段,以便部署中现在有五个 Pod:

apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
namespace: argo-demo
labels:
app.kubernetes.io/name: nginx
spec:
replicas: 5
...

提交并推送更改

$ git add .
$ git commit -m "Run 5 replicas"
$ git push

接下来,重复 argocd app sync 命令以将更改应用于群集。或者,您可以单击用户界面中的“同步”按钮。

Argo 从存储库刷新应用的目标状态,然后执行操作来转换实时状态。部署已重新配置,现在运行五个 Pod:

$ kubectl get deployment -n argo-demo
NAME READY UP-TO-DATE AVAILABLE AGE
nginx 5/5 5 5 12m

启用自动同步

在重复同步命令之前,对五个副本的更改不适用。不过,Argo 可以自动同步存储库中的更改,无需每次都发出命令。这完全自动化了您的交付工作流程。

您可以通过单击用户界面中的“应用程序详细信息”按钮并向下滚动到“同步策略”部分来激活应用程序的自动同步。单击“启用自动同步”按钮。

还可以通过运行以下命令使用 CLI 启用自动同步:$ argocd app set argo-demo --sync-policy automated

默认情况下,自动同步每三分钟运行一次。如果需要更频繁的部署,您可以通过修改 Argo 的配置映射来更改此值。

总结

Argo CD 是 Kubernetes 的持续交付工具。它提供基于拉取的 GitOps 工作流,用于自动将源存储库与群集内部署同步。虽然本文只介绍了基础知识,但 Argo 为您提供了一个完整的工具包,用于部署应用程序、检查其运行状况以及快速回滚任何失败的更改。

ps: 友情链接 : https://spacelift.io/blog/argocd

· 阅读需 11 分钟
南哥

导言

Kubernetes 是一个容器编排系统,可自动部署、扩展和管理容器化应用程序。Kubernetes 的架构旨在为运行和管理容器化工作负载提供一个灵活且可扩展的平台。

在本文中,我们将深入探讨 Kubernetes 的架构,包括构成系统的各种组件,以及它们如何协同工作,为容器编排提供强大且可扩展的平台。

在高层次上,Kubernetes 的架构基于管理工作节点集群的主节点。主节点为 Kubernetes 集群提供控制平面,而工作节点提供用于运行容器化应用程序的计算资源。

主节点组件

Kubernetes 主节点由多个组件组成,这些组件协同工作,为集群提供控制平面。这些组件包括:

API Server

API 服务器提供了一个 RESTful 接口,用于与 Kubernetes 集群进行交互。它接收来自各种客户端(如 kubectl)的请求,并将其转换为由控制平面中的其他组件执行的操作

apiVersion: v1
kind: Pod
metadata:
name: test-pod
spec:
containers:
- name: nginx
image: nginx

etcd

etcd 是一个分布式键值存储,被 Kubernetes 用来存储集群状态信息。etcd 数据存储用于存储集群中对象的配置数据、机密和元数据。

etcdctl get /registry/pods/default/test-pod -w json

控制器管理器

控制器管理器负责管理监视和管理集群中对象的各种控制器。这些控制器包括管理 Pod 部署的复制控制器和管理网络终结点的终结点控制器。

apiVersion: v1
kind: ReplicationController
metadata:
name: nginx
spec:
replicas: 3
selector:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80

Scheduler

调度程序负责将 Pod 调度到集群中的工作节点上。调度程序根据 Pod 的资源需求以及工作节点上资源的可用性做出决策。

                                            +-----------+
| |
| etcd |
| |
+-----------+
^
|
|
|
+-----------+ +--------------+ +------------------------+
| | | | | |
| kube-apis |<---| Controller |<---| Scheduler |
| -erver | | Manager | | |
| | | | +------------------------+
+-----------+ +--------------+

从图中可以看出,API 服务器是接收来自各种客户端的请求并与控制平面中的其他组件交互的中心组件。API 服务器使用 etcd 数据存储来存储有关集群中对象的配置数据、机密和元数据。控制器管理器负责管理监视和管理集群中对象的各种控制器,调度程序负责将 Pod 调度到集群中的工作器节点上。所有这些组件协同工作,为 Kubernetes 集群提供控制平面。

工作节点组件

Kubernetes 集群中的工作节点为运行容器化应用程序提供计算资源。每个工作节点都由多个组件组成,这些组件协同工作以管理在该节点上运行的容器。这些组件包括

kubelet

kubelet 是在每个工作节点上运行的代理,负责管理该节点上的容器。它与主节点通信,并接收有关运行哪些容器并管理其生命周期的指令。kubelet 负责以下任务

  • 从镜像仓库拉取容器映像
  • 启动和停止容器
  • 监视容器的运行状况并在必要时重新启动它们
  • 将卷装载到容器
  • 日志记录容器输出

kubelet 与容器运行时密切合作,以确保容器正常运行。它还与其他 Kubernetes 组件配合使用,以管理网络连接和存储资源。

kube-proxy

kube-proxy 是在每个工作节点上运行的网络代理,负责管理与在该节点上运行的容器的网络连接。它维护网络规则并管理每个容器的网络接口。kube 代理负责以下任务:

  • 将流量路由到相应的容器
  • 为服务实现负载平衡
  • 管理网络策略

kube-proxy 与 kubelet 和其他 Kubernetes 组件密切合作,以确保保持网络连接并正确路由流量。

Container Runtime

容器运行时是在工作器节点上运行容器的软件。Kubernetes 支持多个容器运行时,包括 Docker、containerd 和 CRI-O。容器运行时负责以下任务:

  • 从仓库拉取容器映像
  • 启动和停止容器
  • 管理容器资源,例如 CPU 和内存
  • 管理容器网络

容器运行时与 kubelet 密切合作,以确保容器正常运行并有效利用资源。

示例

让我们看一些示例,说明这些工作节点组件如何协同工作以管理在 Kubernetes 集群中工作节点上运行的容器

  1. 创建具有单个容器的 Pod:

要创建具有单个容器的 pod,我们需要创建一个描述 pod 规范的 YAML 文件。下面是一个示例 YAML 文件:

apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: my-container
image: nginx
ports:
- containerPort: 80

此 YAML 文件指定一个具有单个容器的 pod,该容器运行 nginx 映像并公开端口 80。当 kubelet 收到这个 YAML 文件时,它会从注册表中提取 nginx 镜像,启动容器,并挂载必要的卷

  1. 创建服务以公开 Pod:

要公开在工作节点上运行的 Pod,我们需要创建一个将网络端口映射到 Pod 端口的服务。下面是一个示例 YAML 文件:

apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: my-app
ports:
- name: http
protocol: TCP
port: 80
targetPort: 80
type: LoadBalancer

此 YAML 文件指定一个service,该服务将服务上的端口 80 映射到容器上的端口 80,标签为 app=my-app。服务类型为 LoadBalancer,这意味着 Kubernetes 集群将创建一个外部负载均衡器来将流量路由到 Pod。当 kube-proxy 收到此 YAML 文件时,它会创建必要的网络规则并管理每个 Pod 的网络接口。kube-proxy 还实现了服务的负载均衡并管理网络策略。

  1. 扩展deployment

若要在 Kubernetes 中缩放deployment,我们需要更新部署的 YAML 文件以指定所需的副本数。下面是一个示例 YAML 文件

apiVersion: apps/v1
kind: Deployment
metadata:
name: my-deployment
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-container
image: nginx
ports:
- containerPort: 80

此 YAML 文件指定一个deployment,其中包含在工作器节点上运行的 nginx 容器的三个副本。当 kubelet 收到这个 YAML 文件时,它会创建三个相同的 pod,每个 pod 都运行 nginx 容器。然后,kube-proxy 更新其网络规则,将流量路由到三个 Pod 中的每一个。

  1. 更新deployment:

若要更新 Kubernetes 中的部署,我们需要更新部署的 YAML 文件以指定新的容器映像或其他配置更改。下面是一个示例 YAML 文件

apiVersion: apps/v1
kind: Deployment
metadata:
name: my-deployment
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-container
image: nginx:latest
ports:
- containerPort: 80

此 YAML 文件指定使用最新版本的 nginx 映像的更新部署。当 kubelet 收到此 YAML 文件时,它会更新 Pod 以使用新映像并管理容器生命周期。kube-proxy 还会更新其网络规则,以将流量路由到更新的 Pod。

总结

总之,了解 Kubernetes 架构对于任何使用 Kubernetes 的人来说都是至关重要的,从开发人员到系统管理员。该架构由两个主要组件组成:控制平面和工作节点。控制平面包括几个关键组件,这些组件为 Kubernetes 集群提供中央命令和控制。工作节点负责在集群中运行容器化应用程序和服务。

通过了解不同的组件以及它们之间的交互方式,您可以更好地解决问题、优化性能并设计满足您特定需求的 Kubernetes 集群。此外,随着 Kubernetes 的不断发展和新功能的添加,对架构有深入的了解将帮助您及时了解最新的发展和最佳实践。