标签 IaC 下的文章

云上运维,那就是和云上资源和产品打交道,无疑会涉及到一系列的资源部署。比如简单地使用一台云服务器,就需要运维人员依次创建 VPC、VSwitch、安全组和云服务器实例,如果想创建一个集群,那还要进一步创建负载均衡、数据库和多个云服务器实例。

随着业务规模的不断扩大,IT系统和环境日益复杂,人工一个一个创建资源的方式显然不可取,许多人正在转向自动化资源部署和配置的工具。

本文将基于基础设施即代码 IaC 理念,分享如何借助自动化编排工具实现自动化部署,使得运上运维工作更为高效。

手动/半手动云上运维的五大痛点

对于云上资源的部署,如果你的云上运维还处于手动或是半手动运维阶段,那么大部分工作是通过控制台选择特定资源规格参数进行创建,还有一部分是使用 CLI(如 aliyun-cli)或者 SDK 直接调用接口来创建资源。但随着企业的云上业务规模不断扩大,不论是哪种方式,或多或少都会遇到下述五个问题:

  • 部署效率低。手动创建对于创建少量种类的资源来说倒是种很直观的方式,但一旦涉及到大量不同资源时,尤其是资源之间还有依赖关系,这时候会发现需要在不同的产品控制台之间来回切换,还要时刻关注创建进度,才能再去创建下一个依赖它的资源,整个过程所耗费的时间和精力可想而知,相信不少人有深有体会。
  • 可复制性差。当手动创建好了一系列的资源后,如果需要针对不同的环境(如预发、测试和生产)或不同的地域(如北京和上海)创建完全相同的资源,则又需要花费很多时间一步步地进行操作,无法直接复制、做到一键部署。
  • 一致性差。手动创建还有一个非常大的问题,那就是非常容易出现配置错误,很难保证两套环境中各个资源配置是完全相同的。
  • 管理困难。资源的创建只是开始,可能还需要针对这批资源做扩缩容、更新特定资源的规格等操作。但手动运维的方式就导致没有统一管理这批资源的入口,仍需要分别到各产品控制台上操作。随着资源数越来越多,资源管理就愈发难以维护。
  • 难以 DevOps。每次开发、测试或部署软件应用程序时都可能需要手动部署基础设施,既无法对基础设施进行版本控制,也无法对其变动进行评审,更无法做到敏捷部署。

其实,我们都知道这些问题的背后是因为资源的部署还未做到自动化。但这些问题也不断促使着我们思考应该通过什么样的方式来解决这些痛点,才能让整个资源部署过程自动化。

引入基础设施即代码 IaC 理念,实现云上资源自动化部署

在真正做到自动化部署之前,不妨回头看看所需要创建的云服务资源(如 VPC、VSwitch、ECS 实例等),它们相对于Web服务等应用程序来说都是云上的基础设施,如果把这些基础设施想象成一段“代码”,在“代码”中定义产品、规格、数量等信息,那么是不是就可以通过这段“代码”来管理整个基础设施了呢?

这就是 基础设施即代码 Infrastructure as Code (IaC)的理念,将基础设施配置视为软件编程。Kief Morris 在《Infarftruce as Code》一书中对基础设施即代码是这么定义的:

“基础设施即代码是一种使用新的技术来构建和管理动态基础设施的方式。它把基础设施、工具和服务以及对基础设施的管理本身作为一个软件系统,采纳软件工程实践以结构化的安全的方式来管理对系统的变更。”

引入 IaC 的理念,运维人员可以将基础设施的部署和管理过程变得敏捷:

  • 在模板(宽泛意义上的代码)中定义基础设施,即各类云资源及其规格、数量等属性、云资源之间的依赖;
  • 使用版本控制(如 Git)管理模板,并提交评审;
  • 通过评审后由自动化部署工具使用模板来创建/更新基础设施;

基础设施的部署和管理变得便捷后,上述提到的手动运维/半手动运维的痛点问题就可以得到很好的解决:

  • 提升部署效率。使用自动化部署工具进行部署,相对于人工部署的效率将大大提升。
  • 标准化和一致性。将基础设施的内容通过模板的形式保存,对基础设施的变更由对模板的变更来实现,实现了基础设施管理的标准化。此外,使用相同的模板在不同地域部署,也能够保证资源的一致性。
  • 易于管理。对基础设施的管理不再分散于各个产品控制台,而统一到单个模板,使得管理成本大大降低。
  • 敏捷化工作流程。通过基础设施管理流程的规范化和标准化,资源部署的整个过程就变得敏捷。
  • 审计和回滚。对模板进行版本管理,使得对基础设施变动的审计和回退到某个特定版本成为了可能。

四个常见的 IaC 自动化配置与编排工具

当前,有很多 IaC 自动化部署工具,有第三方资源编排工具,也有云服务商提供的云原生的资源编排工具,这里介绍四个自动化配置与编排工具:

  1. 阿里云资源编排服务 ROS(Resource Orchestration Service),这是云原生编排工具,通过编写 JSON/YAML 格式的模板,在模板中定义所需的ECS实例、数据库实例等云服务资源以及资源依赖关系等,然后再根据模板在 ROS 中创建资源栈,ROS 服务端将根据模板自动完成所有资源的创建和配置,实现自动化部署及运维。而资源栈则管理着模板中定义的所有资源,并可通过新模板来更新资源栈,包括资源的新增、更新或删除等操作。
  2. AWS CloudFormation,也是云原生的编排工具,运维人员也是通过 JSON/YAML 格式的模板定义云服务资源,通过资源栈管理这些资源。
  3. HashiCorp Terraform,这是一个开源的自动化编排工具。以配置文件为驱动,可以在文件中定义所要管理的组件,即基础设施资源,以此生成一个可执行的计划,通过执行这个计划来完成所定义组件的创建,增量式的变更和持续的管理。如果不可执行,会提示报错。Terraform 不仅可以管理 IaaS 层的资源,如计算实例、网络实例和存储实例等,也可以管理更上层的服务,如DNS 域名和解析记录、SaaS 应用的功能等。
  4. Pulumi,与 Terraform 一样也是开源项目,但它与 Terraform 的重要区别在于:可以用熟悉的编程语言来编写声明式配置,而不需要额外学习云服务商特定的模板语言来写配置。

对于自动化配置与编排工具的选择,笔者的建议是:

  1. 如果你的业务部署在单一云平台,就选择云平台提供的资源编排工具,在阿里云平台就用 ROS、在 AWS 平台就用 CloudFormation,原因很简单:云平台提供的工具是云原生,是免费的托管服务,在服务端就可以执行自动化部署;同时,它还实现了云原生的访问控制、编排资源与实际资源差异检测等功能,用起来比较省心。
  2. 如果你的业务是部署在多个云平台,建议使用第三方的 Terraform 和 Pulumi,因为它不仅可以进行多云资源的部署和管理,还能管理除云以外的其他资源,如 Kubernetes。

如何利用编排工具进行自动化部署和管理?

对于运维人员来说,使用 IaC 理念的自动化部署工具的门槛其实不高,使用步骤也非常简单,主要来说就是编写模板和使用模板。这里谈谈编写模板和使用模板有哪些注意事项,如何才能更好地利用工具、更好地提升运维效率。

1、编写模板的三个注意事项

确认好自动化部署工具,就可以根据不同工具的模板语言来编写对应的模板文件。如果你选择云服务商提供的云原生的编排工具, 编写模板这里,有三点注意事项想重点提醒一下:

  1. 注意资源的依赖关系。不恰当的依赖或少了依赖都会导致资源创建出错。
  2. 注意使用通用属性作为参数。比如实例规格等就是比较通用的属性,建议使用同一份模板,指定不同的参数来达到部署不同规格实例的目的。
  3. 使用有价值的属性作为输出。比如实例 ID、连接地址等内容就是有价值的属性,它们都是在资源创建完成后才能获取到,把这些属性作为整个模板的输出,可以方便后续的查看和管理。

2、自动解析依赖关系,自动化部署基础设施

编写完模板后,就可以通过对应的自动化部署工具将模板转化为真正的资源。上述提到的编排工具都能解析资源的依赖关系,并能先后创建这些资源。同时,对于互不依赖的资源也能够并行创建。

  • 对于阿里云 ROS 和 AWS CloudFormation 来说,可使用模板来创建一个资源栈。一个资源栈即一组云上资源,也就是在模板中定义的基础设施。后续当需要增/删/改一些资源时,也是通过使用模板来更新资源栈来达到目的。
  • 对于 Terraform 来说,可使用配置文件生成一个可执行的计划,通过执行这个计划来完成所定义资源/组件的创建,增量式的变更和持续的管理。
  • 对于 Pulumi 来说,则是直接执行代码来进行部署。

这样的部署方式既能使得资源能按照合理的顺序创建出来,又能够提升部署效率,在遇到异常情况时也会进行一定程度的重试,真正让整个自动化部署过程变得稳定和高效。

以基础设施代码化为基础,进一步高效运维

当运维工作完成整个基础设施模板化后,DevOps 就变得更加容易。我们可以使用版本管理工具(如 Git)管理描述当前基础设施的模板,使用阿里云云效/AWS CodePipline/Jenkins 创建一个从代码提交触发到人工卡点再到资源栈部署的流水线,这样整个基础设施的管理就会变得更加敏捷和自动化。

图1: 基础设施变更的流程图

  1. 在每次变更模板后,将本地仓库的分支内容推送到远程仓库,并发起评审;
  2. 若评审不通过,则修改模板后重新发起评审;若评审通过,则自动触发流水线;
  3. 流水线触发人工卡点,通知上级管理员检查此次变更。若不同意,则终止;若同意,则进入下一个步骤;
  4. 若是首次提交模板,则创建资源栈(即创建基础设施);反之,则更新资源栈(即更新基础设施)。

基础设施变更及预览

IT 基础设施并非一成不变,随着业务的变化,我们可能面临扩缩容场景,也可能面临整个架构的变化。好在基于 IaC 的理念,我们只需要描述基础设施最新配置,而不用担心如何进行变更。但即使如此,我们需要在变更前知道究竟会发生哪些变化。阿里云ROS 和 AWS CloudFormation 的更改集功能,Terraform 的执行计划均能让我们提前了解到变更内容。

例如,由于业务变化,在基于图1的架构基础上,在阿里云平台上新增一台 ECS 实例,并使用 SLB 实例为两台 ECS 实例做负载均衡。在编写好新的模板后,就可以使用更改集功能来感知变化,下图是 阿里云ROS 的一个变更示例:

在确认无误后,便可以执行变更。随后,自动化编排工具便会对整个基础设施进行更新,根据模板发生的变化来决定新增、更改或删除哪些资源。

基础设施偏差检测和纠正

尽管使用了自动化编排工具部署资源,仍可能有部分人员会通过非标准化的方式(比如通过控制台或 API)修改了基础设施中部分资源的属性,使得资源实际情况和模板中定义的资源产生了差异。好的自动化编排工具不仅具备检测基础设施实际属性和模板中定义的属性之间差异的能力;还能基于差异结果纠正模板或实际资源,使得模板和基础设施保持一致。

当前,通过 阿里云 ROS 和 AWS CloudFormation 的偏差检测能力,就可以轻松地发现实际资源和模板中定义的资源之间的差异,并可通过偏差纠正功能使模板内容和实际资源保持一致。

总结

在 IT 基础设施全面上云的趋势下,云上手工运维的方式已难以为继,出现了部署效率低、可复制性差、一致性差、管理困难、难以 DevOps 等痛点。阿里云 ROS/AWS CloudFormation/Terraform/Pulumi 等自动化编排工具都是基于基础设施即代码(IaC)的理念,可以通过模板来定义基础设施,同时标准化和自动化整个部署过程,配合更改集、偏差检测等能力,再结合流水线,真正实现了 IT 基础设施管理的 DevOps。建议运维人员可以重点关注和巧用工具,将帮助你更好的提升运维效率,解放生产力。


作者介绍:

王斌鑫,从事阿里云弹性计算资源编排工具的研发工作,热爱开源和写作。阿里云凌云时刻出品人、PyCon China出品人。

用 Node.js 或其他编程语言为你提供启动基础设施所需的一切服务。

当你在 IT 和技术的世界里遨游时,你会反复遇到一些术语。其中有些术语很难量化,随着时间的推移,可能会有不同的含义。“DevOps” 就是一个例子,这个词似乎(在我看来)会根据使用它的人而改变;最初的 DevOps 先驱者可能甚至不认识我们今天所说的 DevOps。

如果你是一个软件开发者,“ 基础架构即代码 Infrastructure as Code ”(IaC)可能是其中一个术语。IaC 是使用与你编写面向用户的功能相同的软件开发实践来声明应用程序运行的基础设施。这通常意味着使用 GitMercurial 等工具进行版本控制,使用 Puppet、Chef 或 Ansible 进行配置管理。在基础设施供应层,最常见的技术是 CloudFormation(专用于 AWS),或开源替代品 Terraform,用来创建供你的应用程序运行的混合云资源。

在配置管理领域有很好产品可供选择,可以将 IaC 写成配置文件或首选的编程语言,但这种选择在基础设施供应领域并不常见。

Pulumi 提供了一个使用标准编程语言来定义基础设施的方式。它支持一系列语言,包括 JavaScriptTypeScriptGoPythonC#)。就像 Terraform 一样,Pulumi 对许多熟悉的云提供商有一流的支持,比如 AWSAzureGoogle Cloud其他提供商

在本文中,我将向你展示如何使用 Pulumi 以 Node.js 编写基础设施。

先决条件

首先,确保你已经做好了使用 Pulumi 的准备。Pulumi 支持所有主流的操作系统,所以你安装其先决条件的方法取决于你使用的操作系统。

首先,安装你喜欢的编程语言的解释器。我将使用 TypeScript,所以我需要安装 node 二进制。请查阅 Node 的安装说明,了解你的操作系统的信息。你可以在 MacLinux 上使用 Homebrew 来安装:

brew install node

在 Linux 上,你可以使用你常用的软件包管理器,如 aptdnf

$ sudo dnf install nodejs

无论哪种情况,结果都应该是 node 二进制文件在你的 $PATH 中可用。要确认它是可访问的,运行:

node --version

接下来,安装 Pulumi 命令行界面(CLI)。你可以在 Pulumi 的文档中找到针对不同操作系统的安装说明。在 Mac 或 Linux 上使用 brew

brew install pulumi

另外,你也可以使用安装脚本。首先下载并审查它,然后执行它:

$ curl -fsSL --output pulumi_installer.sh https://get.pulumi.com/
$ more  pulumi_installer.sh
$ sh ./pulumi_installer.sh

同样,我们所希望的结果是在你的路径上有 pulumi 二进制。检查版本以确保你已经准备好了:

pulumi version
v2.5.0

配置 Pulumi

在你开始配置任何基础设施之前,给 Pulumi 一个存储其状态的地方。

Pulumi 将其状态存储在后端。默认的后端是 Pulumi 的软件即服务(它有一个针对个人用户的免费计划),但在这个例子中,我使用替代的文件后端。文件后端将在你的本地文件系统上创建一个文件来存储状态:

pulumi login --local

如果你打算和别人分享这个项目,文件后台可能不是一个好的起点。Pulumi 还可以将其状态存储在 AWS S3 等云对象存储中。要使用它,请创建一个 S3 bucket 并登录:

pulumi login --cloud-url s3://my-pulumi-state-bucket

现在你已经登录到了状态后端,你可以创建一个项目和一个堆栈了!

在你开始创建 Pulumi 项目之前,请先了解以下 Pulumi 术语,你将在本教程中看到这些术语。

项目

项目 project 是一个包含 Pulumi.yaml 文件的目录。这个文件包含了 Pulumi 需要知道的元数据,以便进行它的工作。在 Pulumi.yaml 文件中可以找到的示例字段有:

  • 运行时(例如,Python、Node、Go、.Net)
  • 项目说明(如“我的第一个 Pulumi 项目”)
  • 项目名称

项目是一个松散的概念,可以满足你的需求。一般来说,一个项目包含了一系列的资源,这些资源是你想要提供和控制的东西。你可以选择拥有资源很少的小型 Pulumi 项目,也可以选择包含所有你需要的资源的大型项目。随着你对 Pulumi 越来越熟悉,你想如何布局你的项目会变得更加清晰。

堆栈

Pulumi 堆栈 stack 允许你根据可配置的值来区分你的 Pulumi 项目。一个常见的用途是将一个项目部署到不同的环境,如开发或生产环境,或不同的地区,如欧洲、中东和非洲以及美国。

在入门时,你不大需要一个复杂的堆栈设置,所以本演练使用默认的堆栈名称 dev

在 IaC 中使用 TypeScript

你可以使用方便的 pulumi new 命令来 初建 bootstrap 一个 Pulumi 项目。new 命令有一大堆标志和选项,可以帮助你入门 Pulumi,所以请继续创建你的第一个项目:

$ pulumi new typescript
This command will walk you through creating a new Pulumi project.

Enter a value or leave blank to accept the (default), and press <ENTER>.
Press ^C at any time to quit.

project name: (pulumi) my-first-project
project description: (A minimal TypeScript Pulumi program) My very first Pulumi program
Created project 'my-first-project'

Please enter your desired stack name.
To create a stack in an organization, use the format <org-name>/<stack-name> (e.g. `acmecorp/dev`).
stack name: (dev) dev
Created stack 'dev'

Installing dependencies...


> node scripts/postinstall

added 82 packages from 126 contributors and audited 82 packages in 2.84s

13 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities

Finished installing dependencies

Your new project is ready to go! ✨

To perform an initial deployment, run 'pulumi up'

这里发生了很多事情,我将其展开来说:

第一部分是为你的 Pulumi 项目确定一个模板。我选择了通用的 typescript 选项,但是有很多选项可供选择

这个 new 命令从你的模板库中抓取模板,并将这个文件复制到本地,包括运行时的依赖关系(在本例中是 package.json)。

new 命令通过在这个目录下运行 npm install 来安装这些依赖关系。然后 npm install 下载并安装运行 Pulumi 程序所需的一切,在这种情况下就是:@pulumi/pulumi NPM 包。

你已经准备好创建你的第一个资源了!

创建你的第一个云资源

资源是一个由你的基础设施供应软件生命周期进行管理的东西。资源一般是一个 云提供商对象 cloud provider object ,比如 S3 桶。Pulumi 的提供商处理 Pulumi 资源,提供商是具体的云提供商。Pulumi 有大约 40 个提供商可供你使用,但对于你的第一个资源,使用一个最简单的: 随机提供商 random provider

随机提供者顾名思义:它幂等地创建一个随机资源(例如,可以是一个字符串),并将其存储在 Pulumi 状态中。

使用 npm 将其添加到你的 Pulumi 项目中作为依赖关系:

npm install @pulumi/random

npm 包管理器下载并安装随机提供者包,并为你安装。现在你已经准备好编写你的 Pulumi 程序了。

当你之前生成你的项目时,Pulumi 的初建过程创建了一个 index.ts TypeScript 文件。在你喜欢的集成开发环境(IDE)中打开它,并添加你的第一个资源:

import * as pulumi from "@pulumi/pulumi";
import * as random from "@pulumi/random";

const password = new random.RandomString(`password`, {
    length: 10
})

如果你对 TypeScript 或 JavaScript 非常熟悉,这看起来会非常熟悉,因为它是用你熟悉的编程语言编写的。如果你使用的是 Pulumi 支持的其他语言之一,也是一样的。这里是之前的那个随机资源,但这次是用 Python 写的:

import pulumi_random as random

password = random.RandomString("password", length=10)

一个 Pulumi 项目目前只支持单一一种语言,但每个项目都可以引用其他语言编写的项目,这对于多语言团队的成员来说是一个很有用的技巧。

你已经编写了第一个 Pulumi 资源。现在你需要部署它。

离开编辑器,回到命令行。在你的项目目录下,运行 pulumi up,然后看着神奇的事情发生:

pulumi up

Previewing update (dev):
     Type                          Name                  Plan
 +   pulumi:pulumi:Stack           my-first-project-dev  create
 +   └─ random:index:RandomString  password              create

Resources:
    + 2 to create

Do you want to perform this update? yes
Updating (dev):
     Type                          Name                  Status
 +   pulumi:pulumi:Stack           my-first-project-dev  created
 +   └─ random:index:RandomString  password              created

Resources:
    + 2 created

Duration: 2s

Permalink: file:///Users/lbriggs/.pulumi/stacks/dev.json

太好了,你有了第一个 Pulumi 资源! 虽然你可能很享受这种成就感,但不幸的是,这个随机资源并没有那么有用:它只是一个随机的字符串,你甚至看不到它是什么。先解决这部分问题。修改你之前的程序,在你创建的常量中加入 export

import * as pulumi from "@pulumi/pulumi";
import * as random from "@pulumi/random";

export const password = new random.RandomString(`password`, {
    length: 10
})

重新运行 pulumi up,看看输出:

pulumi up
Previewing update (dev):
     Type                 Name                  Plan
     pulumi:pulumi:Stack  my-first-project-dev

Outputs:
  + password: {
      + id             : "&+r?{}J$J7"
      + keepers        : output<string>
      + length         : 10
      + lower          : true
      + minLower       : 0
      + minNumeric     : 0
      + minSpecial     : 0
      + minUpper       : 0
      + number         : true
      + overrideSpecial: output<string>
      + result         : "&+r?{}J$J7"
      + special        : true
      + upper          : true
      + urn            : "urn:pulumi:dev::my-first-project::random:index/randomString:RandomString::password"
    }

Resources:
    2 unchanged

Do you want to perform this update? yes
Updating (dev):
     Type                 Name                  Status
     pulumi:pulumi:Stack  my-first-project-dev

Outputs:
  + password: {
      + id        : "&+r?{}J$J7"
      + length    : 10
      + lower     : true
      + minLower  : 0
      + minNumeric: 0
      + minSpecial: 0
      + minUpper  : 0
      + number    : true
      + result    : "&+r?{}J$J7"
      + special   : true
      + upper     : true
      + urn       : "urn:pulumi:dev::my-first-project::random:index/randomString:RandomString::password"
    }

Resources:
    2 unchanged

Duration: 1s
Permalink: file:///Users/lbriggs/.pulumi/stacks/dev.json

现在你可以在 Outputsresult 部分下看到一个随机生成的字符串。你现在可以看到你创建的资源有很多属性。

这一切都很好,但如果你想享受 IaC,你得提供一些随机字符串以外的东西。试试吧。

部署一个容器

到目前为止,你已经通过安装依赖关系和注册一个简单的随机资源来 体验了初建你的 Pulumi。现在部署一些实际的基础设施,尽管是在你的本地机器上。

首先,将 @pulumi/docker 提供者添加到你的堆栈中。使用你选择的包管理器将其添加到项目中:

npm install @pulumi/docker

你已经从 npm 下拉了 Pulumi Docker 提供商包,这意味着你现在可以在你的项目中创建 Docker 镜像。

如果你的机器上还没有安装 Docker,现在是一个极好的时机去安装它。说明将取决于你的操作系统,所以看看 Docker 的安装页面了解信息。

再次打开你喜欢的 IDE,运行一个 Docker 容器。修改你之前的 index.ts 文件,让它看起来像这样:

import * as pulumi from "@pulumi/pulumi";
import * as random from "@pulumi/random";
import * as docker from "@pulumi/docker";

const password = new random.RandomString(`password`, {
    length: 10
})

const container = new docker.Container(`my-password`, {
    image: 'hashicorp/http-echo',
    command: [ pulumi.interpolate`-text=Your super secret password is: ${password.result}` ],
    ports: [{
        internal: 5678,
        external: 5678,
    }]
})

export const id = container.id

这将创建一个容器,创建一个 Web 服务器。Web 服务器的输出是你随机生成的字符串,在本例中是一个密码。运行这个,看看会发生什么:

pulumi up

Previewing update (dev):
     Type                       Name                  Plan
     pulumi:pulumi:Stack        my-first-project-dev
 +   └─ docker:index:Container  my-password           create

Outputs:
  + id      : output<string>
  ~ password: {
        id        : "&+r?{}J$J7"
        length    : 10
        lower     : true
        minLower  : 0
        minNumeric: 0
        minSpecial: 0
        minUpper  : 0
        number    : true
        result    : "&+r?{}J$J7"
        special   : true
        upper     : true
        urn       : "urn:pulumi:dev::my-first-project::random:index/randomString:RandomString::password"
    }

Resources:
    + 1 to create
    2 unchanged

Do you want to perform this update? yes
Updating (dev):
     Type                       Name                  Status
     pulumi:pulumi:Stack        my-first-project-dev
 +   └─ docker:index:Container  my-password           created

Outputs:
  + id      : "e73b34aeca34a64b72b61b0b9b8438637ce28853937bc359a1528ca99f49ddda"
    password: {
        id        : "&+r?{}J$J7"
        length    : 10
        lower     : true
        minLower  : 0
        minNumeric: 0
        minSpecial: 0
        minUpper  : 0
        number    : true
        result    : "&+r?{}J$J7"
        special   : true
        upper     : true
        urn       : "urn:pulumi:dev::my-first-project::random:index/randomString:RandomString::password"
    }

Resources:
    + 1 created
    2 unchanged

Duration: 2s
Permalink: file:///Users/lbriggs/.pulumi/stacks/dev.json

你会注意到在 Outputs 部分,你输出的值已经改变了,它只是一个 Docker 容器 ID。检查你的非常简单的密码生成器是否工作:

curl http://localhost:5678
Your super secret password is: &+r?{}J$J7

就是这样! 你刚刚用 TypeScript 配置了你的第一个基础架构。

关于 Pulumi 输出的快速说明

你会注意到在创建 Docker 容器的代码中,它使用了一个特殊的 pulumi.interpolate 调用。如果你熟悉 TypeScript,你可能会好奇为什么需要这样做(因为它是 Pulumi 特有的)。这有一个有趣的原因。

当 Pulumi 创建一个资源时,直到程序执行时有一些值是 Pulumi 不知道的。在 Pulumi 中,这些值被称为 Outputs。这些 Outputs 可以在上面的代码中看到,例如,在你的第一个随机资源中,你使用 export 关键字来输出随机资源的属性,你还输出了你创建的容器的容器 ID。

因为 Pulumi 直到执行时才知道这些 Outputs 的值,所以在操作字符串时,它需要特殊的助手来使用它们。如果你想了解更多关于这个特殊的编程模型,请观看这个短视频

总结

随着混合云基础架构中出现的复杂性,IaC 在很多方面都有了发展。在基础设施供应领域,Pulumi 是一个很好的选择,它可以使用你最喜欢的编程语言来供应你所需要的一切基础设施,然后你可以在你最喜欢的配置管理工具中进行标记,以采取下一步措施。


via: https://opensource.com/article/20/8/infrastructure-as-code-pulumi

作者:Lee Briggs 选题:lujun9972 译者:wxy 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出