介紹
基礎設施即代碼(IaC)是通過在代碼中定義資源狀態及其關係來自動化基礎設施的部署和修改的一種實踐。執行該代碼然後在雲中創建或修改實際資源。IaC允許工程師使用像Terraform(由HashiCorp開發)這樣的IaC工具來配置基礎設施。
使用IaC,對基礎設施的更改可以通過與應用程序代碼相同的代碼審查流程進行。您可以將代碼存儲在版本控制中(如Git)以保留基礎設施狀態的歷史,並且可以使用更高級別的工具進一步自動化部署流程,例如自助內部開發者平台(IDP)。
Terraform 是一個流行的跨平台基礎設施即代碼(IaC)工具,由於其對許多平台的廣泛支持,包括 GitHub、Cloudflare 和 DigitalOcean 等,因此廣受歡迎。大多數 Terraform 配置都是使用一種叫做 HashiCorp Configuration Language(HCL)的聲明性語言編寫的。
Cloud Development Kit for Terraform(CDKTF)是建立在 Terraform 之上的一個工具,它允許您使用熟悉的編程語言(如 TypeScript、Python 或 Go)而不是 HCL 來定義基礎設施。該工具可以為不熟悉 HCL 的開發人員提供較簡單的學習曲線,同時允許開發人員使用原生的編程功能,如循環、變量和函數。
在本教程中,您將首先安裝 cdktf 命令行界面(CLI)工具。然後,您將使用 TypeScript 編寫 CDKTF 項目並定義該項目的兩個由負載均衡器負載平衡的 NGINX 服務器。然後,您將使用 cdktf 部署基礎設施。在本教程的末尾,您將擁有一個 CDKTF 項目,您可以通過該項目擴展您的基礎設施。
注意:本教程已使用 CDKTF 0.11.2
和 Terraform 1.2.2
进行测试。
先决条件
要完成本教程,您需要:
- A good understanding of Infrastructure-as-Code (IaC). You can learn about IaC in Infrastructure as Code Explained.
- A DigitalOcean account. If you do not have one, sign up for a new account.
- A DigitalOcean Personal Access Token, which you can create via the DigitalOcean console. Instructions on how to do that can be found at How to Generate a Personal Access Token.
- A password-less SSH key added to your DigitalOcean account. You can add that by following How To Use SSH Keys with DigitalOcean Droplets. When you add the key to your account, remember the name you give it, as you will need it in this tutorial. For CDKTF to accept the name of your key, it must start with a letter or underscore and may contain only letters, digits, underscores, and dashes.
- 在您的本地机器上安装 Terraform,您可以通过《如何在 DigitalOcean 上使用 Terraform》中的“步骤 1 – 安装 Terraform”进行设置。
- 在您的本地机器上安装 Node.js。您可以在《如何安装 Node.js 并创建本地开发环境》系列中找到说明。
- 熟练使用 JavaScript 进行编程。要提高您的技能,请查看《如何在 JavaScript 中编码》系列。
- 熟悉 TypeScript 的基本特性。如果您对 TypeScript 不熟悉,那么《如何在 TypeScript 中编码》教程系列是帮助您快速入门的好资源。
- A code editor or integrated development environment (IDE) that supports TypeScript. If you are not currently using one, try Visual Studio Code. You can also read up on How To Work With TypeScript in Visual Studio Code.
步驟1 — 安裝 cdktf
CLI
首先,您將安裝 cdktf
命令行工具。
cdktf
CLI 可以作為一個 NPM 套件使用。如果您在 npmjs.com 上搜尋 cdktf
,您會找到兩個名稱類似的套件:cdktf
和 cdktf-cli
。
概念上,CDKTF 是在 Terraform 之上的抽象層。它由兩部分組成:
-
一個包含一組語言本地構造(例如函數和類)的庫,用於定義基礎設施。這部分被封裝在
cdktf
npm 包中。例如,您可以在以下示例 CDKTF 項目中看到來自cdktf
包的App
和TerraformStack
類的使用: -
一個適配器,解析 CDKTF 項目中的構造,並將它們縮減為一組 JSON 文檔,然後以與 HCL 相同的方式將它們引入 Terraform。該適配器封裝為一個名為
cdktf
的 CLI 工具,由cdktf-cli
套件提供。
要安裝 cdktf
CLI 工具,您需要 cdktf-cli
套件。您可以使用 npm
、yarn
或您選擇的套件管理器全局安裝此套件。
要使用 npm
安裝 cdktf-cli
,請運行以下命令:
注意:在本文發布後,cdktf-cli
套件可能有更新版本。您可以嘗試使用以下命令以最新版本遵循教程:npm install --global cdktf-cli@latest
,但請注意,某些輸出可能略有不同。
或者,您可以在 macOS 或 Linux 上使用 Homebrew 安裝 cdktf
CLI,如下:cdktf
公式:
要驗證安裝是否成功,請執行不帶參數的 cdktf
命令:
您將看到類似以下的輸出:
OutputPlease pass a command to cdktf, here are all available ones:
cdktf
Commands:
cdktf init Create a new cdktf project from a template.
cdktf get Generate CDK Constructs for Terraform providers and modules.
cdktf convert Converts a single file of HCL configuration to CDK for Terraform.
cdktf deploy [stacks...] Deploy the given stacks
cdktf destroy [stacks..] Destroy the given stacks
cdktf diff [stack] Perform a diff (terraform plan) for the given stack
cdktf list List stacks in app.
cdktf login Retrieves an API token to connect to Terraform Cloud.
cdktf synth Synthesizes Terraform code for the given app in a directory.
cdktf watch [stacks..] [experimental] Watch for file changes and automatically trigger a deploy
cdktf output [stacks..] Prints the output of stacks
cdktf debug Get debug information about the current project and environment
cdktf completion generate completion script
Options:
--version 顯示版本號
--disable-logging 不寫入日誌文件。支援使用環境變量CDKTF_DISABLE_LOGGING。
--disable-plugin-cache-env 不自動設置TF_PLUGIN_CACHE_DIR。
--log-level 應該寫入哪個日誌級別。
-h, --help Show help
Options can be specified via environment variables with the "CDKTF_" prefix (e.g. "CDKTF_OUTPUT")
該輸出顯示了可用命令。在本教程的其餘部分,您將學習使用cdktf init
、cdktf get
、cdktf deploy
和cdktf destroy
。
現在您已經安裝了cdktf
CLI,您可以通過編寫一些TypeScript代碼來定義基礎架構。
步驟2 — 建立新的CDKTF專案
在此步驟中,您將使用剛剛安裝的cdktf
CLI來創建一個樣板CDKTF專案,在後續步驟中將繼續構建。
運行以下命令來創建一個將容納CDKTF專案的目錄:
然後,進入新創建的目錄:
使用cdktf init
命令來創建您將構建的CDKTF專案脊柱結構:
CDKTF 允許開發人員使用 TypeScript、Python、Java、C# 或 Go 定義基礎設施。 使用 --template=typescript
選項告訴 cdktf
使用 TypeScript 模板來搭建這個 CDKTF 項目。
Terraform(因此也包括 CDKTF)通過在稱為 Terraform 狀態 文件中記錄其管理的資源的定義和狀態來跟踪這些資源。 使用 --local
選項告訴 CDKTF 在運行 cdktf
的機器上本地保存這些狀態文件(每個文件遵循命名結構 terraform.<stack>.tfstate
)。
執行命令後,CLI 可能會詢問您是否同意將崩潰報告發送給 CDKTF 團隊以幫助改進產品:
Output? Do you want to send crash reports to the CDKTF team? See https://www.terraform.io/cdktf/create-and-deploy/configuration-file for
more information (Y/n)
如果您同意,請輸入 Y
,如果不同意,請輸入 N
,然後按 ENTER
。
cdktf
然後會創建項目搭建結構並安裝套件。 當項目搭建完成時,您將看到類似以下的輸出:
Output Your cdktf typescript project is ready!
cat help Print this message
Compile:
npm run get Import/update Terraform providers and modules (you should check-in this directory)
npm run compile Compile typescript code to javascript (or "npm run watch")
npm run watch Watch for changes and compile typescript in the background
npm run build Compile typescript
Synthesize:
cdktf synth [stack] Synthesize Terraform resources from stacks to cdktf.out/ (ready for 'terraform apply')
Diff:
cdktf diff [stack] Perform a diff (terraform plan) for the given stack
Deploy:
cdktf deploy [stack] Deploy the given stack
Destroy:
cdktf destroy [stack] Destroy the stack
Test:
npm run test Runs unit tests (edit __tests__/main-test.ts to add your own tests)
npm run test:watch Watches the tests and reruns them on change
Upgrades:
npm run upgrade Upgrade cdktf modules to latest version
npm run upgrade:next Upgrade cdktf modules to latest "@next" version (last commit)
您還將看到一些新文件添加到 infra
目錄中。 最重要的文件是 cdktf.json
和 main.ts
。
cdktf.json
是 CDKTF 項目的 配置文件。 如果打開文件,它將顯示如下內容:
屬性 app
定義了將運行以合成 TypeScript 代碼為 Terraform 兼容 JSON 的命令。 此屬性指示 main.ts
是 CDKTF 項目的入口點。
如果你打开main.ts
文件,你会看到类似以下内容:
在 CDKTF 的语言中,一组相关的基础设施资源可以分组到一个stack中。例如,组成 API 应用程序的资源,如 Droplets、负载均衡器和 DNS 记录,可以被分组到一个名为APIStack
的单个堆栈中。每个堆栈都保留其自己的状态,并且可以独立于其他堆栈部署、修改或销毁。堆栈的常见用途是为生产环境和开发环境各有一个堆栈。
一个应用程序是多个堆栈的容器。例如,一个应用程序可以将各种微服务的堆栈分组。
在main.ts
中生成的 CDKTF 项目脚手架包含一个名为MyStack
的单个堆栈类,目前没有定义任何资源。一个名为infra
的MyStack
实例被创建,并包含在一个名为app
的应用程序中。在后续步骤中,你将在MyStack
构造函数中定义基础设施资源。
创建项目后,下一步是配置 CDKTF 项目使用providers。
步骤 3 — 安装 DigitalOcean Provider
在這個步驟中,您將在 CDKTF 專案中安裝 DigitalOcean Provider。
提供者是提供指示給 Terraform(在幕後由cdktf
使用)如何在雲提供者、SaaS 提供者和其他公開應用程式編程界面(API)的平台上創建、更新和刪除資源的庫。提供者將調用這些上游 API 的邏輯封裝到 Terraform 可以調用的標準函數中。
例如,如果您要在沒有 Terraform 的情況下創建一個新的 DigitalOcean Droplet,您將不得不向/v2/droplets
端點的DigitalOcean API發送一個POST
請求。有了 Terraform,您可以安裝DigitalOcean 提供者並定義一個digitalocean_droplet
資源,類似於以下示例片段:
然後,您可以使用cdktf
CLI 工具將此 TypeScript 代碼轉換為 Terraform 兼容的 JSON,並將其傳遞給提供者,該提供者將代表您進行相應的 API 呼叫來創建 Droplet。
現在您已經了解了提供者是什麼,您可以為您的 CDKTF 專案設置 DigitalOcean 提供者。
打開 cdktf.json
檔案並將字串 digitalocean/digitalocean
加入到 terraformProviders
陣列中:
digitalocean/digitalocean
是 Terraform 注冊表上 DigitalOcean 提供者的識別符。
保存並關閉該文件。
接下來,運行 cdktf get
以下載並安裝提供者。
cdktf get
會下載提供者、提取模式、生成相應的 TypeScript 類,並將其添加為 TypeScript 模組,存放在 .gen/providers/
下。此自動代碼生成功能使您能夠使用任何 Terraform 提供者和 HCL 模組與 CDKTF 一起使用,也是 CDKTF 能夠在支持其的編輯器中提供代碼完成的方式。
一旦 cdktf get
完成運行,您將看到類似以下的輸出:
OutputGenerated typescript constructs in the output directory: .gen
您還將看到一個名為 .gen
的新目錄,其中包含提供者的生成代碼。
在這一步驟中,您將 DigitalOcean 提供者安裝到了項目中。在下一步中,您將配置 DigitalOcean 提供者,以使用 DigitalOcean API 驗證提供者所需的憑據。
步驟 4 — 配置 DigitalOcean 提供者
在這一步中,您將使用您的 DigitalOcean 個人訪問令牌配置 DigitalOcean 提供者,該提供者允許提供者代表您調用 DigitalOcean API。
不同的提供者需要並支持與上游 API 進行身份驗證的不同憑證。對於 DigitalOcean 提供者,您需要提供您的 DigitalOcean 個人訪問令牌。您可以通過將其設置為 DIGITALOCEAN_TOKEN
或 DIGITALOCEAN_ACCESS_TOKEN
環境變量來將令牌指定給提供者。
在終端中運行以下命令以為該終端會話設置環境變量。
注意:通過調用 export
,您僅為該終端會話設置環境變量。如果您關閉並重新打開終端,或者在不同的終端中運行 cdktf
命令,則需要再次運行 export
命令才能使環境變量生效。
接下來,您將在 MyStack
類中指定提供者,這將允許您在堆棧中定義提供者提供的資源。將 main.ts
文件更新為以下內容:
提供者的模塊位於 ./.gen/providers/digitalocean
,這是在運行 cdktf get
時自動生成的。
您在這一步中配置了帶有憑證的 digitalocean/digitalocean
提供者。接下來,您將開始定義構成本教程目標的基礎設施。
步驟5 — 在 Droplets 上定義 Web 應用程式
在此步驟中,您將定義兩個NGINX伺服器,每個伺服器提供不同的檔案,部署在兩個相同的Ubuntu 20.04 Droplets上。
您將從定義兩個Droplets開始。修改main.ts
,並進行以下突顯的更改:
您使用JavaScript原生迴圈(Array.prototype.map()
)來避免在程式碼中重複。
就像您透過控制台創建Droplet一樣,需要指定幾個參數:
image
– Droplet將運行的Linux發行版和版本。region
– Droplet將運行的資料中心。size
– 保留給Droplet的CPU和記憶體資源量。name
– 用於參考Droplet的唯一名稱。
image
、region
和 size
的值必须是 DigitalOcean 支援的。您可以在 DigitalOcean API Slugs 頁面找到所有支援的 Linux 發行版映像、Droplet 大小和地區的有效值(稱為 slugs)。您可以在 digitalocean_droplet
文檔頁面上找到所需和可選屬性的完整列表。
添加 SSH 金鑰
作為前提條件的一部分,您將一個無密碼的 SSH 公鑰上傳到您的 DigitalOcean 帳戶並記錄了它的名稱。現在,您將使用該名稱來檢索 SSH 金鑰的 ID 並將其傳遞到您 Droplet 的定義中。
由於 SSH 金鑰是手動添加到您的 DigitalOcean 帳戶中的,它不是由您目前的 Terraform 配置管理的資源。如果您嘗試定義一個新的 digitalocean_ssh_key
資源,它將創建一個新的 SSH 金鑰而不是使用現有的。
然而,您將定義一個新的digitalocean_ssh_key
資料來源。在 Terraform 中,資料來源 用於檢索當前 Terraform 配置未管理的基礎設施的信息。換句話說,它們提供了對預先存在的外部基礎設施狀態的只讀查看。一旦定義了資料來源,您就可以在 Terraform 配置的其他地方使用該資料。
仍然在 main.ts
中,在 MyStack
的構造函數內,定義一個新的 DataDigitaloceanSshKey
資料來源,並傳入您為 SSH 金鑰分配的名稱(這裡名稱為 do_cdktf
):
然後,更新 Droplet 的定義以包括 SSH 金鑰:
在進行配置時,您可以使用私有 SSH 金鑰而不是密碼訪問 Droplet。
指定用戶數據腳本以安裝 NGINX
您現在已經定義了兩個運行 Ubuntu 的相同 Droplet,配置了 SSH 訪問。下一個任務是在每個 Droplet 上安裝 NGINX。
當創建一個 Droplet 時,一個名為 CloudInit 的工具將引導啟動伺服器。CloudInit 可以接受一個名為 user data 的檔案,該檔案可以修改伺服器的啟動方式。用戶數據可以是任何伺服器可以解釋的 cloud-config
檔案或腳本,比如 Bash 腳本。
在接下來的步驟中,您將創建一個 Bash 腳本,並將其指定為 Droplet 的 user data。該腳本將在引導過程中安裝 NGINX。此外,該腳本還將替換 /var/www/html/index.html
檔案的內容(NGINX 默認提供的檔案)為 Droplet 的主機名和 IP 地址,這將導致兩個 NGINX 伺服器提供不同的檔案。在下一步中,您將把這兩個 NGINX 伺服器放在一個負載平衡器後面;通過提供不同的檔案,可以明顯地看出負載平衡器是否正確分發請求。
仍然在 main.ts
中,將一個新的 userData
屬性添加到 Droplet 的配置對象中:
警告: 確保在 shebang(#!
)之前沒有新的行;否則,可能無法執行該腳本。
當滴水器首次配置時,將運行腳本作為root
用戶。它將使用Ubuntu的套件管理器,APT,來安裝nginx
套件。然後,它將使用DigitalOcean的Metadata Service來檢索有關自身的信息,並將主機名和IP地址寫入index.html
,該文件由NGINX提供服務。
在這一步中,您定義了兩個運行Ubuntu的滴水器,配置了每個滴水器的SSH訪問權限,並使用用戶數據功能安裝了NGINX。在下一步中,您將定義一個負載均衡器,它將位於這些NGINX服務器的前面,並將其配置為以循環方式進行負載平衡。
第6步 — 定義負載均衡器
在這一步中,您將通過定義DigitalOcean 負載均衡器來定義一個digitalocean_loadbalancer
資源的實例。
仍然在main.ts
中,在MyStack
構造函數的末尾添加以下負載均衡器的定義:
forwardingRule
參數告訴負載平衡器監聽端口 80
上的 HTTP 請求,並將它們轉發到每個 Droplet 的端口 80
。
dropletIds
指定負載平衡器將傳遞請求的 Droplets。它接受一個數字,但 droplet.id
的值是一個字符串。因此,您使用了 Fn.tonumber
Terraform 函數 將字符串 Droplet ID 值轉換為數字。
注意: 您在這裡使用了 Fn.tonumber
Terraform 函數,而不是 JavaScript 原生的 parseInt
,因為直到 Droplet 被配置之前,droplet.id
的值是未知的。Terraform 函數設計用於在 Terraform 應用配置之前處理未知的運行時值。
保存並關閉文件。
您現在已經定義了兩個 Droplets 和一個坐在它們前面的負載平衡器。您的 main.ts
應該看起來類似於這樣:
在下一步中,您將使用 cdktf
CLI 工具來實現整個 CDKTF 項目。
步驟 7 — 配置您的基礎設施
在這一步,您將使用cdktf
CLI工具來配置您在上一步中定義的Droplets和負載平衡器。
確保您位於infra/
目錄中並且已為您的終端會話設置了DIGITALOCEAN_ACCESS_TOKEN
環境變量,然後運行cdktf deploy
命令:
您應該看到類似以下的輸出:
Outputinfra Initializing the backend...
infra Initializing provider plugins...
infra - Reusing previous version of digitalocean/digitalocean from the dependency lock file
infra - Using previously-installed digitalocean/digitalocean v2.19.0
infra Terraform has been successfully initialized!
infra Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
infra # digitalocean_droplet.bar (bar) will be created
+ resource "digitalocean_droplet" "bar" {
+ backups = false
+ created_at = (known after apply)
+ disk = (known after apply)
+ graceful_shutdown = false
+ id = (known after apply)
+ image = "ubuntu-20-04-x64"
+ ipv4_address = (known after apply)
+ ipv4_address_private = (known after apply)
+ ipv6 = false
+ ipv6_address = (known after apply)
+ locked = (known after apply)
+ memory = (known after apply)
+ monitoring = false
+ name = "bar"
+ price_hourly = (known after apply)
+ price_monthly = (known after apply)
+ private_networking = (known after apply)
+ region = "lon1"
+ resize_disk = true
+ size = "s-1vcpu-1gb"
+ ssh_keys = [
+ "34377800",
]
+ status = (known after apply)
+ urn = (known after apply)
+ user_data = "f9b1d9796d069fe504ce0d89439b6b664b14b1a1"
+ vcpus = (known after apply)
+ volume_ids = (known after apply)
+ vpc_uuid = (known after apply)
}
# digitalocean_droplet.foo(foo)將被創建
+ resource "digitalocean_droplet" "foo" {
+ backups = false
+ created_at = (known after apply)
+ disk = (known after apply)
+ graceful_shutdown = false
+ id = (known after apply)
+ image = "ubuntu-20-04-x64"
+ ipv4_address = (known after apply)
+ ipv4_address_private = (known after apply)
+ ipv6 = false
+ ipv6_address = (known after apply)
+ locked = (known after apply)
+ memory = (known after apply)
+ monitoring = false
+ name = "foo"
+ price_hourly = (known after apply)
+ price_monthly = (known after apply)
+ private_networking = (known after apply)
+ region = "lon1"
+ resize_disk = true
+ size = "s-1vcpu-1gb"
+ ssh_keys = [
+ "34377800",
]
+ status = (known after apply)
+ urn = (known after apply)
+ user_data = "f9b1d9796d069fe504ce0d89439b6b664b14b1a1"
+ vcpus = (known after apply)
+ volume_ids = (known after apply)
+ vpc_uuid = (known after apply)
}
# digitalocean_loadbalancer.lb(lb)將被創建
+ resource "digitalocean_loadbalancer" "lb" {
+ algorithm = "round_robin"
+ disable_lets_encrypt_dns_records = false
+ droplet_ids = (known after apply)
+ enable_backend_keepalive = false
+ enable_proxy_protocol = false
+ id = (known after apply)
+ ip = (known after apply)
+ name = "default"
+ redirect_http_to_https = false
+ region = "lon1"
+ size_unit = (known after apply)
+ status = (known after apply)
+ urn = (known after apply)
+ vpc_uuid = (known after apply)
+ forwarding_rule {
+ certificate_id = (known after apply)
+ certificate_name = (known after apply)
+ entry_port = 80
+ entry_protocol = "http"
+ target_port = 80
+ target_protocol = "http"
+ tls_passthrough = false
}
+ healthcheck {
+ check_interval_seconds = (known after apply)
+ healthy_threshold = (known after apply)
+ path = (known after apply)
+ port = (known after apply)
+ protocol = (known after apply)
+ response_timeout_seconds = (known after apply)
+ unhealthy_threshold = (known after apply)
}
+ sticky_sessions {
+ cookie_name = (known after apply)
+ cookie_ttl_seconds = (known after apply)
+ type = (known after apply)
}
}
Plan: 3 to add, 0 to change, 0 to destroy.
─────────────────────────────────────────────────────────────────────────────
Saved the plan to: plan
To perform exactly these actions, run the following command to apply:
terraform apply "plan"
Please review the diff output above for infra
❯ Approve Applies the changes outlined in the plan.
Dismiss
Stop
注意:CDKTF仍在開發中,輸出可能與上面顯示的不同。
此顯示列出了cdktf
計劃要創建、更新和刪除的所有資源和屬性。一些值,例如Droplet的ID,在資源配置後才知道。對於這些值,您將在輸出中看到(known after apply)
作為屬性值。
請查看資源列表,以確保其符合您的期望。然後,使用箭頭鍵選擇批准選項並按ENTER
。
您將看到類似以下的輸出:
Outputinfra digitalocean_droplet.foo (foo): Creating...
digitalocean_droplet.bar (bar): Creating...
infra digitalocean_droplet.bar (bar): Still creating... [10s elapsed]
infra digitalocean_droplet.foo (foo): Still creating... [10s elapsed]
1 Stack deploying 0 Stacks done 0 Stacks waiting
此輸出告訴您cdktf
正在與DigitalOcean API通信以創建Droplet。cdktf
首先創建Droplets,因為負載平衡器取決於Droplet的ID,該ID在Droplets被配置之前是未知的。
Droplet的創建通常需要不到一分鐘。一旦Droplets被配置,cdktf
就會繼續創建負載平衡器。
Outputinfra digitalocean_droplet.bar (bar): Creation complete after 54s [id=298041598]
infra digitalocean_droplet.foo (foo): Creation complete after 55s [id=298041600]
infra digitalocean_loadbalancer.lb (lb): Creating...
infra digitalocean_loadbalancer.lb (lb): Still creating... [10s elapsed]
負載平衡器可能需要較長的時間。創建負載平衡器後,您將看到一個摘要,顯示堆疊已成功部署。
Outputinfra digitalocean_loadbalancer.lb (lb): Still creating... [1m30s elapsed]
infra digitalocean_loadbalancer.lb (lb): Creation complete after 1m32s [id=4f9ae2b7-b649-4fb4-beed-96b95bb72dd1]
infra
Apply complete! Resources: 3 added, 0 changed, 0 destroyed.
No outputs found.
您現在可以訪問DigitalOcean 控制台,在那裡您可以看到一個名為default
的負載平衡器和兩個名為foo
和bar
的健康 Droplet,每個 Droplet 都作為負載平衡器的目標。
您可以通過訪問每個 Droplet 的 IP 地址來測試 NGINX 是否正在運行並正確提供內容。您應該會看到類似以下的文本:
Droplet: bar, IP Address: droplet_ip
如果您沒有看到該文本字符串或服務器沒有響應,請檢查您指定的用戶數據是否正確,以及是否沒有任何字符(包括換行符)在 shebang(#!
)之前。您也可以使用您的 SSH 私鑰 SSH 連接到 Droplet,並查看 CloudInit 在/var/log/cloud-init-output.log
生成的輸出日誌:
一旦您確認 Droplets 已經啟動並提供內容,您可以開始測試負載平衡器。您可以通過發送一些請求來完成此操作。
從您的終端運行以下命令,向負載平衡器發送十個請求:
您應該會看到類似以下的輸出,但顯示的 IP 地址將不同:
OutputDroplet: foo, IP Address: droplet_foo_ip
Droplet: bar, IP Address: droplet_bar_ip
Droplet: foo, IP Address: droplet_foo_ip
Droplet: bar, IP Address: droplet_bar_ip
Droplet: bar, IP Address: droplet_bar_ip
Droplet: foo, IP Address: droplet_foo_ip
Droplet: bar, IP Address: droplet_bar_ip
Droplet: foo, IP Address: droplet_foo_ip
Droplet: bar, IP Address: droplet_bar_ip
Droplet: foo, IP Address: droplet_foo_ip
它顯示了將請求轉發到每個 Droplet 五次,表明負載平衡器正在工作。
注意:負載平衡器不一定始終完全平衡兩個 Droplet 之間;您可能會發現四個請求發送到一個 Droplet,而六個請求發送到另一個 Droplet。這種行為是正常的。
在這一步中,您使用了 cdktf
來配置您的資源,然後您使用 DigitalOcean 控制台來查找您的 Droplets 和負載平衡器的 IP 地址。然後,您對每個 Droplet 和負載平衡器發送請求以確認它們運作。
在下一個步驟中,您將獲取 Droplets 和負載平衡器的 IP 地址,而無需登錄到 DigitalOcean 控制台。
步驟 8 — 輸出資訊
在上一步中,您必須登錄到 DigitalOcean 控制台以獲取您的 Droplet 和負載平衡器的 IP 地址。在這一步中,您將稍微修改您的程式碼,以便這些資訊被列印在 cdktf deploy
命令的輸出中,節省您前往控制台的步驟。
Terraform 在狀態檔中記錄其受管理資源的配置和狀態。對於您的 infra
堆疊,狀態檔可以在 infra/terraform.infra.tfstate
中找到。您將能夠在此狀態檔中找到 Droplets 和負載平衡器的 IP 地址。
但是,篩選大型檔案可能會不方便。CDKTF 提供了 TerraformOutput
構造,您可以使用它來輸出變數並使其在堆疊之外可用。任何輸出都會在執行 cdktf deploy
後被列印在 stdout
中。執行 cdktf output
也可以隨時列印輸出。
注意:儘管在本教程中您僅使用輸出將信息打印到控制台,但其真正的威力來自使用其他堆棧的輸出作為輸入的功能,這種功能被稱為交叉堆棧引用。
更新main.ts
文件以包括負載均衡器和Droplets的IP地址的輸出:
保存並關閉文件。
運行cdktf deploy
以實現更改:
在輸出中,您應該看到類似以下的內容:
Output─────────────────────────────────────────────────────────────────────────────
Changes to Outputs:
+ droplet0IP = "droplet_foo_ip"
+ droplet1IP = "droplet_bar_ip"
+ loadBalancerIP = "load_balancer_ip"
You can apply this plan to save these new output values to the Terraform
state, without changing any real infrastructure.
─────────────────────────────────────────────────────────────────────────────
此輸出告訴您不會進行基礎設施更改,僅會輸出堆棧的內容。
使用箭頭鍵選擇批准,然後按ENTER
。在終端輸出末尾,您應該看到類似以下的內容:
Outputinfra
droplet0IP = droplet_foo_ip
droplet1IP = droplet_bar_ip
loadBalancerIP = load_balancer_ip
現在,每次運行cdktf deploy
或cdktf output
,Droplets和負載均衡器的IP地址將被打印在終端輸出中,無需從DigitalOcean控制台訪問該信息。
您現在已經配置了兩個Droplets和一個負載均衡器,並確認它們正在運行。您可以將您開發的CDKTF項目用作定義更複雜基礎設施的基礎(您可以在do-community / digitalocean-cdktf-typescript
中找到參考實現)。
本教程中配置的资源将产生费用。如果您不打算使用创建的基础架构,应该将其销毁。在下一步,您将通过销毁本教程中创建的资源来清理项目。
步骤9 — 销毁您的基础架构
在这一步中,您将删除本教程中创建的所有资源。
仍然在infra/
目录中,运行cdktf destroy
:
您应该会看到类似以下的输出:
Outputinfra Initializing the backend...
infra Initializing provider plugins...
infra - Reusing previous version of digitalocean/digitalocean from the dependency lock file
infra - Using previously-installed digitalocean/digitalocean v2.19.0
infra Terraform has been successfully initialized!
infra digitalocean_droplet.bar (bar): Refreshing state... [id=298041598]
digitalocean_droplet.foo (foo): Refreshing state... [id=298041600]
infra digitalocean_loadbalancer.lb (lb): Refreshing state... [id=4f9ae2b7-b649-4fb4-beed-96b95bb72dd1]
infra Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
- destroy
Terraform will perform the following actions:
infra # digitalocean_droplet.bar (bar) will be destroyed
- resource "digitalocean_droplet" "bar" {
- backups = false -> null
- created_at = "2022-05-02T10:04:16Z" -> null
- disk = 25 -> null
- graceful_shutdown = false -> null
- id = "298041598" -> null
- image = "ubuntu-20-04-x64" -> null
- ipv4_address = "droplet_bar_public_ip" -> null
- ipv4_address_private = "droplet_bar_private_ip" -> null
- ipv6 = false -> null
- locked = false -> null
- memory = 1024 -> null
- monitoring = false -> null
- name = "bar" -> null
- price_hourly = 0.00744 -> null
- price_monthly = 5 -> null
- private_networking = true -> null
- region = "lon1" -> null
- resize_disk = true -> null
- size = "s-1vcpu-1gb" -> null
- ssh_keys = [
- "34377800",
] -> null
- status = "active" -> null
- tags = [] -> null
- urn = "do:droplet:298041598" -> null
- user_data = "f9b1d9796d069fe504ce0d89439b6b664b14b1a1" -> null
- vcpus = 1 -> null
- volume_ids = [] -> null
- vpc_uuid = "bed80b32-dc82-11e8-83ec-3cfdfea9f3f0" -> null
}
# digitalocean_droplet.foo (foo) 将被销毁
- resource "digitalocean_droplet" "foo" {
- backups = false -> null
- created_at = "2022-05-02T10:04:16Z" -> null
- disk = 25 -> null
- graceful_shutdown = false -> null
- id = "298041600" -> null
- image = "ubuntu-20-04-x64" -> null
- ipv4_address = "droplet_foo_public_ip" -> null
- ipv4_address_private = "droplet_foo_private_ip" -> null
- ipv6 = false -> null
- locked = false -> null
- memory = 1024 -> null
- monitoring = false -> null
- name = "foo" -> null
- price_hourly = 0.00744 -> null
- price_monthly = 5 -> null
- private_networking = true -> null
- region = "lon1" -> null
- resize_disk = true -> null
- size = "s-1vcpu-1gb" -> null
- ssh_keys = [
- "34377800",
] -> null
- status = "active" -> null
- tags = [] -> null
- urn = "do:droplet:298041600" -> null
- user_data = "f9b1d9796d069fe504ce0d89439b6b664b14b1a1" -> null
- vcpus = 1 -> null
- volume_ids = [] -> null
- vpc_uuid = "bed80b32-dc82-11e8-83ec-3cfdfea9f3f0" -> null
}
# digitalocean_loadbalancer.lb (lb) 将被销毁
- resource "digitalocean_loadbalancer" "lb" {
- algorithm = "round_robin" -> null
- disable_lets_encrypt_dns_records = false -> null
- droplet_ids = [
- 298041598,
- 298041600,
] -> null
- enable_backend_keepalive = false -> null
- enable_proxy_protocol = false -> null
- id = "4f9ae2b7-b649-4fb4-beed-96b95bb72dd1" -> null
- ip = "load_balancer_ip" -> null
- name = "default" -> null
- redirect_http_to_https = false -> null
- region = "lon1" -> null
- size_unit = 1 -> null
- status = "active" -> null
- urn = "do:loadbalancer:4f9ae2b7-b649-4fb4-beed-96b95bb72dd1" -> null
- vpc_uuid = "bed80b32-dc82-11e8-83ec-3cfdfea9f3f0" -> null
- forwarding_rule {
- entry_port = 80 -> null
- entry_protocol = "http" -> nul
infra l
- target_port = 80 -> null
- target_protocol = "http" -> null
- tls_passthrough = false -> null
}
- healthcheck {
- check_interval_seconds = 10 -> null
- healthy_threshold = 5 -> null
- path = "/" -> null
- port = 80 -> null
- protocol = "http" -> null
- response_timeout_seconds = 5 -> null
- unhealthy_threshold = 3 -> null
}
- sticky_sessions {
- cookie_ttl_seconds = 0 -> null
- type = "none" -> null
}
}
Plan: 0 to add, 0 to change, 3 to destroy.
─────────────────────────────────────────────────────────────────────────────
Saved the plan to: plan
To perform exactly these actions, run the following command to apply:
terraform apply "plan"
Please review the diff output above for infra
❯ Approve Applies the changes outlined in the plan.
Dismiss
Stop
这一次,与每个资源旁边显示+
不同,它显示-
,表示CDKTF计划销毁该资源。审查建议的更改,然后使用箭头键选择批准并按ENTER
键。现在,DigitalOcean提供商将与DigitalOcean API通信以销毁资源。
Outputinfra digitalocean_loadbalancer.lb (lb): Destroying... [id=4f9ae2b7-b649-4fb4-beed-96b95bb72dd1]
infra digitalocean_loadbalancer.lb (lb): Destruction complete after 1s
infra digitalocean_droplet.bar (bar): Destroying... [id=298041598]
digitalocean_droplet.foo (foo): Destroying... [id=298041600]
首先删除了负载均衡器,因为它没有依赖项(其他资源没有在其输入中引用负载均衡器)。因为负载均衡器引用了Droplets,所以它们只能在负载均衡器被销毁后销毁。
资源被销毁后,您将在输出中看到以下行打印出来:
OutputDestroy complete! Resources: 3 destroyed.
結論
在這個教程中,您使用了 CDKTF 來配置和銷毀一個由兩個運行 NGINX 服務器的 DigitalOcean Droplets 組成的負載平衡的網頁,並且這些服務器位於一個負載均衡器後面。您還在終端上輸出了有關資源的信息。
CDKTF 是在 Terraform 之上的一個抽象層。對 Terraform 的良好理解有助於理解 CDKTF。如果您想了解更多關於 Terraform 的信息,您可以閱讀《如何使用 Terraform 管理基礎設施》系列文章,該系列深入介紹了 Terraform。
您還可以查閱官方的 CDK for Terraform 文檔 和 教程 以了解更多關於 CDKTF 的信息。