在本教程中,你将按照分步说明,使用 Pulumi 基础设施即代码(IaC)将现有网站接入 Cloudflare,以熟悉资源管理生命周期。具体而言,你将创建一个 Zone 和一个 DNS 记录来解析新添加的网站。本教程采用 IaC 原则来完成添加网站教程中列出的步骤。
确保你拥有:
- 一个 Cloudflare 账户和 API 令牌,具有在本教程中编辑资源的权限。如有需要,请在继续之前注册 Cloudflare 账户 ↗。你的令牌必须具有:
Zone-Zone-Edit权限Zone-DNS-Edit权限include-All zones from an account-<your account>Zone 资源
- 一个 Pulumi Cloud 账户。你可以注册永久免费的个人版 ↗。
- 在你的机器上安装了 Pulumi CLI。
- 配置了一种 Pulumi 支持的编程语言 ↗。(TypeScript、JavaScript、Python、Go、.NET、Java 或使用 YAML)
- 一个域名。你可以使用
example.com来完成本教程。
Pulumi 项目是专用文件夹中的一组文件,描述了你想要创建的基础设施。Pulumi 项目文件夹通过必需的 Pulumi.yaml 文件来标识。你将使用 Pulumi CLI 创建和配置新项目。
为本教程使用一个新的空目录。
mkdir addsite-cloudflare
cd addsite-cloudflarePulumi Cloud ↗ 是一种托管服务,为管理基础设施即代码提供安全且可扩展的平台。你将使用它来存储 Pulumi 后端配置。
在提示符处,按 Enter 通过浏览器登录你的 Pulumi Cloud 账户。或者,你也可以提供 Pulumi Cloud 访问令牌 ↗。
pulumi loginPulumi 程序是用支持的编程语言 ↗编写的代码,用于定义基础设施资源。
要创建程序,请选择你喜欢的语言并运行 pulumi 命令:
pulumi new javascript --name addsite-cloudflare --yes
# wait a few seconds while the project is initializedpulumi new typescript --name addsite-cloudflare --yes
# wait a few seconds while the project is initializedpulumi new python --name addsite-cloudflare --yes
# wait a few seconds while the project is initializedpulumi new go --name addsite-cloudflare --yes
# wait a few seconds while the project is initializedpulumi new java --name addsite-cloudflare --yes
# wait a few seconds while the project is initializedpulumi new csharp --name addsite-cloudflare --yes
# wait a few seconds while the project is initializedpulumi new yaml --name addsite-cloudflare --yesPulumi Stack ↗ 是 Pulumi 程序的实例。Stack 可以独立配置,可以代表不同的环境(开发、暂存、生产)或功能分支。在本教程中,你将使用 dev Stack。
要实例化你的 dev Stack,请运行:
pulumi up --yes
# wait a few seconds for the stack to be instantiated.此时你尚未定义任何资源,因此你将拥有一个空的 Stack。
在此步骤中,你将把设置存储在 Pulumi ESC Environment ↗ 中,这是一个包含配置和密钥的 YAML 文件。这些可以通过多种方式访问,包括 Pulumi 程序。所有 ESC Environment 都安全地存储在你的 Pulumi Cloud 账户中,可以通过 Pulumi CLI 完全管理。在本教程中,你将存储以下值:
# Define an ESC Environment name
E=cloudflare/my-dev-env
# Create a new Pulumi ESC Environment
pulumi config env init --env $E --yesCreating environment cloudflare/my-dev-env for stack dev...# Replace abc123 with your Cloudflare Account ID
pulumi env set $E --plaintext pulumiConfig.accountId abc123
# Replace API_TOKEN with your Cloudflare API Token
pulumi env set $E --secret pulumiConfig.cloudflare:apiToken API_TOKEN
# Replace example.com with your registered domain, or leave as is
pulumi env set $E --plaintext pulumiConfig.domain example.com你需要为所选语言安装 Cloudflare 包,以便在 Pulumi 程序中定义 Cloudflare 资源。
通过运行以下命令安装 Cloudflare 包:
npm install @pulumi/cloudflareadded 1 package ...npm install @pulumi/cloudflareadded 1 package ...echo "pulumi_cloudflare>=5.38,<6.0.0" >> requirements.txt
source venv/bin/activate
pip install -r requirements.txt...Collecting pulumi-cloudflare...go get github.com/pulumi/pulumi-cloudflare/sdk/v3/go/cloudflarego: downloading github.com/pulumi/pulumi-cloudflare ...以下是 Apache Maven 的说明。对于其他 Java 项目管理器(如 Gradle),请参阅官方 Maven repository ↗
- 打开你的
pom.xml文件。 - 在
<dependencies>部分内添加 Pulumi Cloudflare 依赖项。
<dependency>
<groupId>com.pulumi</groupId>
<artifactId>cloudflare</artifactId>
<version>5.38.0</version>
</dependency>- Run:
mvn clean install...[INFO] BUILD SUCCESS...dotnet add package Pulumi.Cloudflare...
info : Adding PackageReference for package 'Pulumi.Cloudflare' into project
...YAML 没有需要下载的依赖项。请跳过此步骤。
安装 Cloudflare 包后,你现在可以在 Pulumi 程序中定义任何支持的 Cloudflare 资源 ↗。接下来你将定义一个 Zone 和一个 DNS 记录。
域名(或网站)在 Cloudflare 中称为 Zone。在 Pulumi 中,Zone 资源 ↗表示一个 Cloudflare Zone。
将你的入口文件内容替换为以下内容:
Filename: index.js
"use strict";
const pulumi = require("@pulumi/pulumi");
const cloudflare = require("@pulumi/cloudflare");
const config = new pulumi.Config();
const accountId = config.require("accountId");
const domain = config.require("domain");
// Create a Cloudflare resource (Zone)
const zone = new cloudflare.Zone("my-zone", {
zone: domain,
accountId: accountId,
plan: "free",
jumpStart: true,
});
exports.zoneId = zone.id;
exports.nameservers = zone.nameServers;
exports.status = zone.status;Filename: index.ts
import * as pulumi from "@pulumi/pulumi";
import * as cloudflare from "@pulumi/cloudflare";
const config = new pulumi.Config();
const accountId = config.require("accountId");
const domain = config.require("domain");
// Create a Cloudflare resource (Zone)
const zone = new cloudflare.Zone("my-zone", {
zone: domain,
accountId: accountId,
plan: "free",
jumpStart: true,
});
export const zoneId = zone.id;
export const nameservers = zone.nameServers;
export const status = zone.status;Filename: __main__.py
import pulumi
import pulumi_cloudflare as cloudflare
account_id = pulumi.Config().require("accountId")
domain = pulumi.Config().require("domain")
# Create a Cloudflare resource (Zone)
zone = cloudflare.Zone("my-zone",
zone=domain,
account_id=account_id,
plan="free",
jump_start=True)
pulumi.export("zoneId", zone.id)
pulumi.export('nameservers', zone.name_servers)
pulumi.export('status', zone.status)Filename: main.go
package main
import (
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
cloudflare "github.com/pulumi/pulumi-cloudflare/sdk/v3/go/cloudflare"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
domain, _ := ctx.GetConfig("domain")
// Create a Cloudflare resource (Zone)
zone, err := cloudflare.NewZone(ctx, "my-zone", &cloudflare.ZoneArgs{
Zone: pulumi.String(domain),
Plan: pulumi.String("free"),
JumpStart: pulumi.Bool(true),
})
if err != nil {
return err
}
ctx.Export("zoneId", zone.ID())
ctx.Export("nameservers", zone.NameServers)
ctx.Export("status", zone.Status)
return nil
})
}Filename: src/main/java/myproject/App.java
package myproject;
import com.pulumi.Pulumi;
import com.pulumi.Context;
import com.pulumi.cloudflare.ZoneArgs;
import com.pulumi.cloudflare.Zone;
public class App {
public static void main(String[] args) {
Pulumi.run(ctx -> {
var config = ctx.config();
String accountId = config.require("accountId");
String domain = config.require("domain");
var zone = new Zone("my-zone", ZoneArgs.builder()
.zone(domain)
.accountId(accountId)
.plan("free")
.jumpStart(true)
.build());
ctx.export("zoneId", zone.id());
ctx.export("nameservers", zone.nameServers());
ctx.export("status", zone.status());
});
}
}Filename: Program.cs
using System.Threading.Tasks;
using System.Collections.Immutable;
using Pulumi;
using Pulumi.Cloudflare;
class Program
{
static Task<int> Main() => Deployment.RunAsync<MyStack>();
class MyStack : Stack
{
public MyStack()
{
var config = new Pulumi.Config();
var accountId = config.Require("accountId");
var domain = config.Require("domain");
var zone = new Zone("my-zone", new ZoneArgs
{
ZoneName = domain,
AccountId = accountId,
Plan = "free",
JumpStart = true
});
this.ZoneId = zone.Id;
this.Nameservers = zone.NameServers;
this.Status = zone.Status;
}
[Output]
public Output<string> ZoneId { get; set; }
public Output<ImmutableArray<string>> Nameservers { get; set; }
public Output<string> Status { get; set; }
}
}Filename: Pulumi.yaml
name: addsite-cloudflare
runtime: yaml
resources:
myZone:
type: cloudflare:Zone
properties:
zone: ${domain}
accountId: ${accountId}
plan: "free"
jumpStart: true
outputs:
zoneId: ${myZone.id}
nameservers: ${exampleZone.nameServers}
status: ${exampleZone.status}请注意,代码还从 Zone 资源输出了多个属性,例如 zoneId、nameservers 和 status,以便在后续步骤中轻松访问。
你现在将添加一个 DNS Record 资源 ↗来测试之前配置的 Zone。
在 Zone 资源定义之后,将以下代码片段添加到你的入口文件中:
Filename: index.js
const record = new cloudflare.Record("my-record", {
zoneId: zone.id,
name: domain,
content: "192.0.2.1",
type: "A",
proxied: true,
});Filename: index.ts
const record = new cloudflare.Record("my-record", {
zoneId: zone.id,
name: domain,
content: "192.0.2.1",
type: "A",
proxied: true,
});Filename: __main__.py
record = cloudflare.Record("my-record",
zone_id=zone.id,
name=domain,
content="192.0.2.1",
type="A",
proxied=True
)Filename: main.go
_, err = cloudflare.NewRecord(ctx, "my-record", &cloudflare.RecordArgs{
ZoneId: zone.ID(),
Name: pulumi.String(domain),
Content: pulumi.String("192.0.2.1"),
Type: pulumi.String("A"),
Proxied: pulumi.Bool(true),
})
if err != nil {
return err
}Filename: src/main/java/myproject/App.java
// Add imports
import com.pulumi.cloudflare.Record;
import com.pulumi.cloudflare.RecordArgs;
// Below the Zone resource, add
new Record("my-record", RecordArgs.builder()
.zoneId(zone.id())
.name(domain)
.content("192.0.2.1")
.type("A")
.proxied(true)
.build());Filename: Program.cs
new Record("my-record", new RecordArgs
{
ZoneId = zone.Id,
Name = domain,
Content = "192.0.2.1",
Type = "A",
Proxied = true
});Filename: Pulumi.yaml
myRecord:
type: cloudflare:Record
properties:
zoneId: ${myZone.id}
name: ${domain}
content: 192.0.2.1
type: A
proxied: true现在你已经定义了资源,可以使用 Pulumi CLI 部署更改,以便它们在你的 Cloudflare 账户中生效。
要部署更改,请运行:
pulumi up --yeswait for the dev stack to become ready将域名添加到 Cloudflare 后,该域名将获得两个分配的权威名称服务器。
要检索分配的 nameservers,请运行:
pulumi stack output在你的注册商处更新名称服务器以为你的域名激活 Cloudflare 服务。说明因注册商而异。你可以在常用注册商的综合列表下找到指导。
成功注册后,你的域名 status 将变为 active。
pulumi stack output你将对 Cloudflare 分配的名称服务器运行两个 nslookup 命令。
要测试你的网站,请运行:
DOMAIN=$(pulumi config get domain)
NS1=$(pulumi stack output nameservers | jq '.[0]' -r)
NS2=$(pulumi stack output nameservers | jq '.[1]' -r)
nslookup $DOMAIN $NS1
nslookup $DOMAIN $NS2对于 .NET,请使用 Nameservers 作为 Output。
确认你的响应返回了你网站的 IP 地址。
在最后一步,你将删除本教程中使用的资源和 Stack。
pulumi destroy --yespulumi stack rm dev你已逐步定义了将网站添加到 Cloudflare 所需的 Cloudflare 资源。你用所选的编程语言声明资源,由 Pulumi 处理其余事项。
要使用 Pulumi 部署无服务器应用程序,请参照部署 Worker 教程。