简介

Pulumi 是一个基础设施即代码(IaC,Infrastructure as Code)平台,支持使用如 Go、Java、Python、JavaScript、C# 等常见编程语言及相关工具,以实现云基础设施的构建、部署和管理。

使用及基本结构

基本概念

Pulumi basic

  • Project:包含 Pulumi.yaml 配置文件的目录。可以通过 pulumi new 使用各个语言的模板创建新的 project。

  • Stack:每个 Pulumi 程序都部署到一个 Stack。Stack 是 Pulumi 程序的一个相互隔离、可独立配置的实例,Stack 通常用于表示不同的开发阶段(如 dev、staging、production)或功能分支(如 feature-x-dev)。一个 Project 下可以有多个 Stack,当使用 pulumi new 创建 project 时,默认会创建一个 dev Stack。

  • Program:Project 中包含的资源编排代码以及运行程序的元数据信息。在 project 目录中执行pulumi up命令,pulumi 会创建一个隔离、可配置的 stack 实例,Stack 类似在测试和线上应用程序使用的不同部署环境。

示例

  1. 安装 pulumi 插件
brew install pulumi/tap/pulumi
  1. 初始化 project,第一次使用会要求登陆 Pulumi Cloud(状态等元数据默认存储在 Pulumi Cloud)
mkdir pulumi-example && cd pulumi-example
pulumi new go

执行完成后,pulumi 会创建一个 pulumi-example project,同时默认创建一个名为 dev的 stack。

  1. 获取 volcengine pulumi SDK 依赖
Shell
...
require (
    github.com/pulumi/pulumi-volcengine/sdk v0.0.73
...
  1. 获取 volcengine pulumi 插件

默认情况下,pulumi CLI 会自动从 https://get.pulumi.com/releases/plugins/pulumi-resource-xxx-vx.x.x-darwin-amd64.tar.gz 下载相关 provider 二进制插件,目前 volcengine 还未发布到 pulumi cloud,因此需要手动复制二进制插件至 $GOPATH/bin 目录下。

  1. 修改 main.go 代码
Go
package main

import (
    "github.com/pulumi/pulumi-volcengine/sdk/go/volcengine/vpc"
    "github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
    pulumi.Run(func(ctx *pulumi.Context) error {
       vpcInstance, err := vpc.NewVpc(ctx, "demo-vpc", &vpc.VpcArgs{
          CidrBlock: pulumi.String("172.16.0.0/16"),
          DnsServers: pulumi.StringArray{
             pulumi.String("8.8.8.8"),
             pulumi.String("114.114.114.114"),
          },
          VpcName: pulumi.String("pulumi-demo-1"),
       })
       if err != nil {
          return err
       }

       _, err = vpc.NewSubnet(ctx, "demo-subnet", &vpc.SubnetArgs{
          CidrBlock:  pulumi.String("172.16.1.0/24"),
          SubnetName: pulumi.String("subnet-pulumi-test-1"),
          VpcId:      vpcInstance.VpcId,
          ZoneId:     pulumi.String("cn-beijing-a"),
       })
       if err != nil {
          return err
       }

       return nil
    })
}
  1. 设置环境变量,执行 pulumi up
export VOLCENGINE_ENDPOINT=open.volcengineapi.com
export VOLCENGINE_REGION=cn-beijing
export VOLCENGINE_ACCESS_KEY=your-access-key
export VOLCENGINE_SECRET_KEY=your-secret-key
pulumi up

工作原理

组件设计

Pulumi 使用 DSM(Desired State Model)管理基础设施。一个 Pulumi 程序由 Language Host 执行,并计算出 Stack 下基础设施的期望状态;Deployment Engine将 Stack 当前状态与期望状态对比,确定要创建、更新或删除哪些资源;同时 Engine 使用一组 Resource Providers(如 AWS、Azure Provider 等)来管理各个资源,根据已管理资源的信息以及正在执行中的操作,来更新当前管理基础设施的最终状态信息。

Language Hosts

负责触发执行 Pulumi 应用程序(资源编排代码),并且设置一个可以向Deployment Engine注册资源的运行环境。Language Host主要由两部分组成:

  1. Language Executor:是一个名为pulumi-language-<language-name>的二进制文件,负责为用户编写的资源编排程序启动运行时,该二进制文件与 Pulumi CLI 一同分发,通过ls ~/.pulumi/bin/pulumi-language-*可以查看目前已下载的运行时。
  2. Language Runtime:负责准备要执行的程序,并且在程序执行中检查资源注册信息,当一个资源被注册时(比如 JS new Resource() 或 Python Resource(...) 调用),Language Runtime 会将注册请求发送至 Deployment Engine。Language Runtime 作为常规包分发,在资源编排程序中以依赖的形式存在,如 Golang 运行时的github.com/pulumi/pulumi/sdk/v3 v3.60.1依赖,Node 运行时 @pulumi/pulumi 依赖,Python 运行时包含在 PyPI 上可用的 pulumi 包中。

Depolyment Engine

负责计算将当前基础设施的状态流转为用户编写的应用程序定义的目标状态所需要执行的一组操作。当 Engine 模块从 Language Host 收到一次资源注册的请求后,会先查询当前状态,确实该资源是否已经创建过,如果还未创建,Engine 使用 Resource Provider 触发资源创建;如果资源已经存在,Engine 将比较新旧资源状态,如果状态有更新,Engine 会根据字段定义,确定通过 Update 还是 Replace 的方式流转资源状态至目标状态。当 Language Host 完成编排代码执行后会通知 Engine,Engine 会检查是否已有资源没有收到来自 Language Host 的注册请求,如有则会删除这部分资源。

Deployment Engine 目前集成在 pulumi CLI 中。

Resource Providers

Resource Provider 由两部分组成:

  1. Resource Plugin:Deployment Engine 用来管理资源的二进制文件,内部包装了 Terraform Provider,用于实现资源增删改查操作。这些插件存储在插件缓存中(位于 ~/.pulumi/plugins 中),可以使用 pulumi plugin 命令管理。

  1. SDK:Provider 提供的每种资源的 binding,提供了多语言 SDK,定义了资源属性,支持通过各种语言通过 pulumi 实现资源编排。

执行原理

Pulumi CLI 实现包含两个核心接口:

• Stack:通过组合可插拔 Backend 实现 Stack 下的资源管理。

• Backend:Stack 后端实现,定义了 Pulumi 云服务功能的抽象接口。通过 Backend 的多种实现,支持 Engine 与不同实现的状态管理层对接,目前 Pulumi 支持 cloud(Pulumi 云服务) 和 local(支持本地文件,AWS、Azure、GCP 对象存储) 两种实现。

以上述示例代码为例,介绍 pulumi up 执行后,pulumi 内部的核心执行流程(原图用飞书画的有水印将就下了):

  • Pulumi CLI:Pulumi 命令,即 pulumi up 中 pulumi 二进制包中执行的内容。
  • State Storage:状态存储,Pulumi 支持选择将状态信息存储在 cloud(Pulumi 云服务) 或 local(本地文件、AWS、Azure、GCP 对象存储)。
  • Language Hosts:上述 Language Hosts 组件中的 Executor 部分,Runtime 位于 User Program 中。
  • User Program:用户编写的资源编排应用,集成了 Pulumi SDK ,包含云提供商的资源信息定义,以及 Language Hosts 中的 Runtime 部分,后者负责管理用户程序中编写的资源读取、注册等操作。
  • Resource Monitor:Pulumi CLI 执行过程中创建的一个 Goroutine,启动了一个 gRpc Server,供 User Program 中的 Language Runtime 调用。
  • Resource Provider:云提供商插件,基于 pulumi-tf-bridge 构建,以二进制包形式提供给用户使用,启动时会初始化一个 gRpc Server,供 Pulumi CLI 中的 Engine 部分以及 Resource Monitor 调用。
  • Cloud:云厂商,负责提供最终的资源。

相关链接