文件與入門指南
本文件將引導您設定和使用 ONDEMANDENV,提供必要的詳細資訊以使平台運作並整合您的服務。
安裝與設定
請依照以下步驟在您的環境中設定 ONDEMANDENV 平台。
1. 環境準備
AWS 環境:
- AWS Organization: 設定 AWS Organization。
-
兩個 AWS 帳戶: 在您的組織內,指定或建立:
- 一個中央帳戶:這是核心 ONDEMANDENV 平台引擎將執行的地方。
- 一個工作區帳戶 (workspace0):部署的初始目標,包括強制性的 contractsLib enver。
- 託管區域: 在中央帳戶的 Route 53 中建立一個公用託管區域。選擇一個合適的網域名稱,例如:<your-chosen-name>.root.ondemandenv.link。請記下此名稱,稍後將會用到。
- 區域: 決定主要的 AWS 區域(例如 us-east-1)。所有初始設定資源都應位於此區域。
-
AWS CDK 啟動: 在您選擇的區域中,同時在中央帳戶和 workspace0 帳戶中啟動 CDK。執行:
# 在中央帳戶內容中 aws configure set region YOUR_REGION cdk bootstrap aws://CENTRAL_ACCOUNT_ID/YOUR_REGION # 在 workspace0 帳戶內容中 aws configure set region YOUR_REGION cdk bootstrap aws://WORKSPACE0_ACCOUNT_ID/YOUR_REGION
- 跨帳戶信任: 設定 workspace0 帳戶以信任中央帳戶。在 workspace0 中建立一個 IAM 角色(例如 OndemandenvDeployerRole),賦予其 AdministratorAccess(或稍後基於最低權限的更嚴格原則)權限,以便中央帳戶可以擔任該角色。信任原則應明確允許 ONDEMANDENV 平台將在中央帳戶中使用的角色 ARN(這將由平台範本定義)。
- GitHub 應用程式私鑰密碼: 在中央帳戶的 AWS Secrets Manager 中建立一個密碼。為此密碼選擇一個特定的名稱(例如 ondemandenv/github-app-private-key)。您將在下一步中將 GitHub 應用程式的私鑰儲存在此處。記下此密碼名稱 (ghAppPrivateKeySecretName)。ONDEMANDENV 平台範本將需要此名稱。
GitHub 環境:
- GitHub 組織: 確保您已設定 GitHub 組織。
-
私有 GitHub 應用程式: 建立一個由您的組織擁有的新的私有 GitHub 應用程式。
- 下載產生的私鑰(.pem 檔案)。
- 重要: 將此私鑰檔案的內容安全地儲存為新版本,存入您在中央帳戶中建立的 AWS Secrets Manager 密碼 (ghAppPrivateKeySecretName) 中。
- 為應用程式設定必要的權限(請參閱 ONDEMANDENV 文件以取得詳細資訊,通常包括對程式碼、中繼資料的讀取權限,以及對問題、提取請求、工作流程、檢查、狀態、部署的寫入權限)。
- 目前將 Webhook URL 留空;您將在部署平台後更新此 URL。
- 將此 GitHub 應用程式安裝到您打算用於 `contractsLib` 的特定儲存庫。
-
`contractsLib` 儲存庫: 在您的 GitHub 組織內建立一個儲存庫來定義您的服務合約。此儲存庫將包含您的 ONDEMANDENV 建置和 enver 定義。
- 您可以使用 `ondemandenv/odmd-contracts-sandbox` 作為範例結構。
- 確保您的儲存庫包含必要的相依性(例如 `@ondemandenv/odmd-contracts-base`)和建置指令碼(例如在 `package.json` 中)以編譯您的 TypeScript 定義。
- 您需要使用 npm pack 來封裝已編譯的 `contractsLib` 定義。這會產生一個 .tgz 檔案。
2. 平台部署
-
向 ONDEMANDENV 服務提交資訊:
您需要向 ONDEMANDENV 團隊(或指定的聯絡人)提供以下資訊,以進行平台的初始設定並產生 CloudFormation 範本。這通常涉及一個上線流程。
- 中央帳戶 ID
- 工作區帳戶 ID (workspace0)
- 主要 AWS 區域
- Route 53 託管區域名稱(例如 <your-chosen-name>.root.ondemandenv.link)
- GitHub 應用程式 ID
- GitHub 應用程式安裝 ID(將應用程式安裝到 `contractsLib` 儲存庫後)
- GitHub 組織名稱
- `contractsLib` 儲存庫名稱
- `contractsLib` 定義的 .tgz 檔案(例如 `my-org-contractslib-1.0.0.tgz`)——這需要透過安全的方式共用。
- `contractsLib` 的建置定義名稱(例如 MyOrgContractsLibSbx - `contractsLib` 程式碼中 `OdmdBuildContracts` 實例的名稱)
- `contractsLib` 的 enver 定義名稱(例如 contractsLibSbx - `contractsLib` 程式碼中 `OdmdEnverContracts` 實例的名稱)
- GitHub 應用程式私鑰密碼名稱 (ghAppPrivateKeySecretName)
- (選用)初始管理員使用者電子郵件地址(用於存取平台 UI/API)
-
部署 CloudFormation 堆疊:
使用從 ONDEMANDENV 團隊收到的 CloudFormation 範本和參數,在您的中央帳戶中部署堆疊。
- 這將佈建核心平台引擎、API、Webhook 處理常式以及相關的 IAM 角色。
- 部署完成後,將輸出平台 API 端點和 Webhook URL。
-
設定 GitHub 應用程式 Webhook:
- 從 CloudFormation 堆疊輸出中取得 Webhook URL。
- 前往 GitHub 應用程式設定頁面,並使用此 URL 更新 Webhook URL。同時設定 Webhook 密碼(由平台提供或在設定時指定)。
- 訂閱事件(例如推送、提取請求)。
-
`contractsLib` Enver 的初始部署:
平台通常會在首次推送到 `contractsLib` 儲存庫時(或透過手動觸發),自動嘗試將 `contractsLib` enver 部署到 workspace0 帳戶。這包括:
- 從 `contractsLib` 儲存庫簽出程式碼。
- 使用 `npm ci` 和 `npm run build`(或在 `package.json` 中定義的建置指令碼)建置程式碼。
- 使用 CDK 將在 `contractsLib` 中定義的基礎架構(例如 S3 儲存貯體、CodePipeline)部署到 workspace0 帳戶。
此步驟成功後,ONDEMANDENV 平台的基礎即已建立。

圖 1:ONDEMANDENV 概念性設定架構。中央帳戶託管平台引擎,而工作區帳戶(例如 workspace0)託管 `contractsLib` enver 及其後的服務 enver。
核心工作流程與指南
平台設定完成後,開發人員將遵循以下一般工作流程來定義、部署和管理服務。
1. 在 `contractsLib` 中定義
所有服務及其環境 (Envers) 首先在 `contractsLib` 儲存庫中以宣告方式定義。這可確保集中控制和一致性。
a. 定義建置組態 (`OdmdBuild`)
對於每種類型的服務(例如 Node.js Lambda、Spring Boot Fargate 服務、靜態網站),建立一個 `OdmdBuild` 實例。這定義了如何建置和封裝服務。
// 範例:my-org-contractslib/lib/builds/my-service-builds.ts
import { OdmdBuild } from '@ondemandenv/odmd-contracts-base';
import { MyOrgAppEnver } from '../envers/my-org-app-enver'; // 匯入 Enver 類型
export const MyNodeJsLambdaBuild = new OdmdBuild(this, 'MyNodeJsLambdaBuild', {
githubRepoAlias: 'my-nodejs-lambda-service-repo', // 服務程式碼所在的儲存庫
buildType: 'lambda_nodejs', // 或 'cdk', 'container_image' 等
sourcePath: 'src', // 根據 buildType 的來源路徑
// 特定於 buildType 的其他參數
});
githubRepoAlias 指向在 ONDEMANDENV 平台設定中對應的儲存庫(例如 GitHub 應用程式安裝)。
b. 定義 Enver 定義 (擴充 `OdmdEnver`)
對於每個服務,建立一個擴充 `OdmdEnverCdk`(用於基於 CDK 的部署)或 `OdmdEnverGeneric` 的類別。這可讓您模型化特定的環境實例(例如開發、預備、生產)。
// 範例:my-org-contractslib/lib/envers/my-org-app-enver.ts
import { OdmdEnverCdk, Product, Consumer } from '@ondemandenv/odmd-contracts-base';
import { Construct } from 'constructs';
// 定義此 Enver 類型將發佈和使用的產品/消費者的介面
export interface MyOrgAppEnverProps {
// 此 Enver 將發佈的產品範例
readonly outputsProduct?: Product;
// 此 Enver 將使用的產品範例
readonly userDatabaseConsumer?: Consumer;
}
export class MyOrgAppEnver extends OdmdEnverCdk implements MyOrgAppEnverProps {
readonly outputsProduct?: Product;
readonly userDatabaseConsumer?: Consumer;
constructor(scope: Construct, id: string, props: OdmdEnverCdkProps & MyOrgAppEnverProps) {
super(scope, id, props);
this.outputsProduct = props.outputsProduct;
this.userDatabaseConsumer = props.userDatabaseConsumer;
}
}
c. 實例化特定的 Enver 實例
使用建置和 Enver 類型來實例化特定的環境實例(例如 `myServiceDev`、`myServiceProd`)。定義產品(此 Enver 將發佈的輸出)和消費者(此 Enver 所需的相依性)。
// 範例:my-org-contractslib/lib/envers/service-instances.ts
import { MyNodeJsLambdaBuild } from '../builds/my-service-builds';
import { MyOrgAppEnver } from './my-org-app-enver';
import { Product } from '@ondemandenv/odmd-contracts-base';
// 匯入其他 Enver 實例以定義相依性
// import { sharedDatabaseProd } from './shared-services';
export const myServiceDev = new MyOrgAppEnver(this, 'MyServiceDev', {
build: MyNodeJsLambdaBuild, // 連結到相關的建置定義
targetAccountAlias: 'dev-account', // 在平台設定中定義的帳戶別名
targetRegion: 'us-east-1', // 選用,預設為平台的主要區域
outputsProduct: new Product(this, 'Outputs'), // 此 Enver 將發佈輸出
// userDatabaseConsumer: new Consumer(this, 'UserDb', sharedDatabaseProd.outputsProduct), // 使用來自另一個 Enver 的產品
// enverSpecificConfig: { key: 'devValue' } // 特定於環境的組態
});
export const myServiceProd = new MyOrgAppEnver(this, 'MyServiceProd', {
build: MyNodeJsLambdaBuild,
targetAccountAlias: 'prod-account',
immutable: true, // 生產環境通常標記為不可變
outputsProduct: new Product(this, 'Outputs'),
// userDatabaseConsumer: new Consumer(this, 'UserDb', sharedDatabaseProd.outputsProduct),
// enverSpecificConfig: { key: 'prodValue' }
});
提交並推送對 `contractsLib` 的變更後,平台將自動處理這些定義。
2. 實作服務
在 `OdmdBuild` 定義中指定的儲存庫(例如 `my-nodejs-lambda-service-repo`)中,實作服務的商業邏輯。根據部署類型(CDK、Lambda、容器),建立相關檔案(例如 `cdk-stack.ts`、`lambda-handler.js`、`Dockerfile`)。
對於基於 CDK 的服務 (`buildType: 'cdk'`)
CDK 堆疊可以透過 `OdmdEnverCdk`(或其子類別)的 `getSharedValue('consumerName')` 存取已使用的值,並透過 `getEnverSpecificConfig()` 存取特定於環境的組態。
// 範例:my-nodejs-lambda-service-repo/lib/my-service-stack.ts
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import { OdmdEnverCdk, OdmdShareOut } from '@ondemandenv/odmd-contracts-base'; // 從基礎程式庫匯入
import * as lambda from 'aws-cdk-lib/aws-lambda';
// ... 其他 CDK 匯入
// 在 MyOrgAppEnver 中定義的 enverSpecificConfig 介面
interface MyServiceConfig {
key: string;
// 其他組態屬性
}
export class MyServiceStack extends OdmdEnverCdk { // 擴充 OdmdEnverCdk
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// 取得已使用的值 (在 contractsLib 中定義)
// const userDbDetailsJson = OdmdEnverCdk.getSharedValue('UserDb');
// const userDbDetails = JSON.parse(userDbDetailsJson || '{}');
// 取得特定於環境的組態 (在 contractsLib 中定義)
const config = OdmdEnverCdk.getEnverSpecificConfig();
const myFunction = new lambda.Function(this, 'MyLambdaFunction', {
runtime: lambda.Runtime.NODEJS_18_X,
handler: 'index.handler',
code: lambda.Code.fromAsset('src'), // 符合在 MyNodeJsLambdaBuild 中定義的 sourcePath
environment: {
// DB_HOST: userDbDetails.host,
CONFIG_KEY: config?.key || 'defaultValue',
},
});
// 發佈此堆疊的輸出 (符合 contractsLib 中的 Outputs 產品)
new OdmdShareOut(this, 'Outputs', {
value: cdk.Stack.of(this).toJsonString({
lambdaFunctionName: myFunction.functionName,
// 其他輸出
}),
});
}
}
在 `package.json` 中包含服務程式碼所需的相依性(例如 `@ondemandenv/odmd-contracts-base`)。
3. 部署與迭代
將變更提交並推送到服務儲存庫(例如 `my-nodejs-lambda-service-repo`)。
- 平台會偵測到推送事件,並觸發在 `contractsLib` 中定義的相關 Enver(例如 `myServiceDev`)的建置和部署。
- 可以透過 ONDEMANDENV 平台 UI 或 API 監控建置日誌和部署狀態。
- 已部署服務的端點或資源詳細資料通常可以透過平台 UI 或使用 `Product` 來取得。
重複此週期以開發和更新您的服務。
4. 複製 Enver (動態環境)
ONDEMANDENV 支援現有 Enver 的隨選複製,非常適合隔離測試、功能開發或臨時沙箱。
若要建立複製,請提交到服務儲存庫的目標分支(例如 `feature/new-feature`),並在提交訊息本文中包含特殊指令。
git commit -m "功能:實作新的驗證流程
odmd: create@myServiceDev"
- odmd: create@BASE_ENVER_ID:建立 `BASE_ENVER_ID`(例如 `myServiceDev`)的複製,並使用目前分支的程式碼進行部署。
- 複製的 Enver 將繼承基礎 Enver 的組態(相依性、目標帳戶等),但會使用目前分支的程式碼進行部署。
- 資源名稱將為複製唯一產生,以避免衝突。
- 可以透過平台 UI 或 API 存取複製 Enver 的詳細資料。
或者,您也可以在 `contractsLib` 中靜態定義 `ClonedEnver` 實例。
5. 刪除複製
當不再需要動態建立的複製 Enver 時,您可以將其刪除以釋放資源。
提交到與複製 Enver 相關聯的分支,並在提交訊息本文中包含特殊指令。
git commit --allow-empty -m "刪除功能分支複製
odmd: delete"
- odmd: delete:銷毀與目前分支相關聯的複製 Enver。
- 平台將清除與複製 Enver 相關聯的所有已佈建資源。
使用平台服務 (產品與消費者)
Enver 可以透過發佈 `Product` 並使用其他 Enver 發佈的 `Product` 作為 `Consumer` 來進行互動。這實現了基於合約的相依性管理。
- 發佈產品: 在您的 CDK 堆疊中使用 `OdmdShareOut` 建構,將 Enver 的輸出作為 JSON 字串發佈。它必須符合在 `contractsLib` 中定義的 `Product` ID。
- 使用產品: 在 `contractsLib` 中定義一個 `Consumer`,以另一個 Enver 的 `Product` 為目標。在您的 CDK 堆疊中,使用 `OdmdEnverCdk.getSharedValue('ConsumerName')` 作為 JSON 字串取得產品的值,然後進行解析和使用。
平台將協調這些跨 Enver 和跨帳戶相依性的安全解析。
部署模型
ONDEMANDENV 支援彈性的部署模型。
- 多帳戶: Enver 可以根據 `contractsLib` 中定義的 `targetAccountAlias` 部署到不同的 AWS 帳戶。平台管理跨帳戶角色擔任和資源共用。
- 多區域: 可以透過指定 `targetRegion` 將 Enver 部署到不同的 AWS 區域。
- 建置類型:
- cdk:使用 AWS CDK 部署基礎架構和應用程式。
- lambda_nodejs / lambda_python / lambda_java 等:直接部署指定執期的 AWS Lambda 函數(平台可能會產生必要的包裝函式或 CDK 程式碼)。
- container_image:建置容器映像並將其部署到 ECS 或 EKS 等服務。
- static_site:將靜態網站內容部署到 S3/CloudFront。
- 不可變性: Enver 可以標記為 `immutable: true`,以防止意外修改。變更需要建立新的 Enver 版本或複製。
安全考量
ONDEMANDENV 的設計考量到安全性。
- 最低權限 IAM 角色: 平台元件和已部署的 Enver 使用遵循最低權限原則設計的 IAM 角色。
- 基於合約的安全性: `contractsLib` 中產品和消費者之間的連線構成了管理跨帳戶存取權限的信任基礎。平台會根據這些合約自動設定必要的 IAM 原則和資源共用(例如 AWS RAM)。
- 密碼管理: 敏感資料(例如 GitHub 應用程式私鑰)會安全地儲存在 AWS Secrets Manager 中。
- 網路隔離: Enver 可以利用標準的 AWS 網路建構(VPC、安全群組等)進行隔離。共享網路模式允許安全地連線到集中管理的網路資源。
- 稽核與記錄: 平台動作和 Enver 部署會透過 AWS CloudTrail 和 CloudWatch Logs 進行記錄,提供稽核功能。
CI/CD 整合
ONDEMANDENV 補充並增強了現有的 CI/CD 實務。
- 以 GitOps 為中心: 核心工作流程圍繞 Git 操作(推送、提交訊息)展開,自然符合 GitOps 原則。
- Webhook 整合: GitHub (或其他 VCS) Webhook 會根據對 `contractsLib` 和服務儲存庫的變更觸發平台動作。
- 平台 API: ONDEMANDENV API 可用於從外部 CI/CD 管線(例如 Jenkins、GitLab CI、GitHub Actions)以程式設計方式觸發建置、部署和複製操作。
- 環境進程: 在 `contractsLib` 中定義不同的 Enver(開發、預備、生產)並結合指定來源提交雜湊的功能,可在 CI/CD 管線中實現受控的環境進程。
基礎程式庫 (`@ondemandenv/odmd-contracts-base`)
@ondemandenv/odmd-contracts-base 程式庫提供與 ONDEMANDENV 平台互動所需的核心建構和公用程式。
主要建構:
- OdmdBuild:定義如何建置服務成品。
- OdmdEnverCdk:使用 AWS CDK 部署的環境基礎類別。提供對特定於環境的組態和共用值的存取。
- OdmdEnverGeneric:用於非 CDK 部署情境的通用環境基礎類別。
- OdmdBuildContracts / OdmdEnverContracts:用於定義和部署 `contractsLib` 本身的特殊類型。
- Product:定義 Enver 發佈的輸出或資源。
- Consumer:定義對另一個 Enver 的 Product 的相依性。
- OdmdShareOut:用於從 CDK 堆疊內發佈 Product 的值。
公用程式:
- OdmdEnverCdk.getSharedValue(consumerName):在 CDK 堆疊中取得已使用的 Product 值。
- OdmdEnverCdk.getEnverSpecificConfig():在 CDK 堆疊中取得特定於 Enver 的組態。
有關這些建構的詳細 API 文件和使用範例,請參閱程式庫的原始碼和相關的類型定義。
探索程式碼
為了更深入地了解 ONDEMANDENV 的功能,建議探索以下儲存庫:
-
`odmd-contracts-base`
核心 TypeScript 程式庫。包含 `OdmdBuild`、`OdmdEnverCdk`、`Product`、`Consumer` 等基本建構。這是建置您自己的 `contractsLib` 和服務 CDK 程式碼的基礎。
-
`odmd-contracts-sandbox`
範例 `contractsLib` 儲存庫。展示了各種建置類型、Enver 定義、產品/消費者使用方式以及資料夾結構的最佳實務。是開始建置您自己的 `contractsLib` 的絕佳起點。
-
`odmd-example-services` (若有,或個別服務範例)
可使用 ONDEMANDENV 部署的各種類型範例服務(例如 Node.js Lambda、Python Fargate 服務)。這些範例展示了它們如何與 `odmd-contracts-sandbox` 中定義的合約互動。
-
平台引擎儲存庫 (若可存取)
包含 ONDEMANDENV 平台本身核心邏輯的私有儲存庫(通常無法存取)。包括 Webhook 處理常式、API、部署協調和狀態管理。
平台內部機制 (進階概觀)
ONDEMANDENV 平台由數個主要元件組成:
- 合約儲存 (`contractsLib`): 所有環境和服務定義的信任來源。它作為在專用 AWS 帳戶(例如 `workspace0`)中執行的特殊 Enver 進行管理。其主要輸出是包含已處理合約定義的 S3 儲存貯體。
- Webhook 處理常式: 監聽來自 GitHub (或其他 VCS 供應商) 的 Webhook 事件 (例如推送、提交訊息指令) 的 API Gateway 和 Lambda 函數。它們會解析這些事件並觸發相應的平台動作。
- API 端點: 用於與平台互動的 RESTful API。用於觸發建置、查詢 Enver 狀態、管理複製等。
- 協調引擎 (Step Functions / Lambda): 管理複雜工作流程 (例如建置、部署、複製建立、刪除) 的 AWS Step Functions 狀態機器和 Lambda 函數。這些工作流程包括簽出程式碼、解析相依性 (Products/Consumers)、合成和部署 CDK,以及更新狀態。
- 狀態資料庫 (DynamoDB): 追蹤 Enver、建置、部署及其關係狀態的 DynamoDB 資料表。
- 身分識別管理: 管理 API 和 UI 存取的使用者身分識別和驗證 (例如 Amazon Cognito)。
- CDK 工具組整合: 平台與 AWS CDK 工具組深度整合,以在指定的目標帳戶和區域中合成和部署 CDK 堆疊。利用跨帳戶部署角色。
- 通知服務 (SNS/SES): (選用) 就重要事件 (例如部署完成或錯誤) 通知使用者。
當平台收到指令 (例如 `odmd: create@baseEnver`) 時,會發生以下一般順序:
- Webhook 處理常式驗證指令並觸發協調引擎。
- 協調引擎從合約儲存讀取基礎 Enver 定義。
- 從指定的分支簽出服務程式碼。
- 在目標帳戶和區域中,使用基礎 Enver の組態和分支的程式碼合成新 Enver (複製) 的 CDK 堆疊。
- 部署合成的範本,確保資源名稱是唯一的。
- 更新狀態資料庫,並透過平台 UI 提供詳細資料。
此架構能夠以可擴展、具彈性且安全的方式,隨選建立和管理高擬真度的環境。