網路資源可以連線你的基礎設施資源,並將它們連到網際網路。雲端網路服務讓你能夠建立隔離的網路環境、控制流量走向,以及保護你的資源安全。

虛擬網路

虛擬網路(也稱為虛擬私有雲或VPC)在雲端提供隔離的網路環境。它們讓你能夠自訂IP位址範圍、子網路和路由表。

虛擬網路的關鍵元件包括:

子網路
將你的虛擬網路細分成不同IP位址範圍的區塊。子網路可以是公開的(可連線網際網路)或私有的(僅供內部使用)。

路由表
定義流量如何在你的虛擬網路內部和外部網路之間傳遞。

網路ACL和安全群組
控制進出虛擬網路中資源的流量。

虛擬網路服務的例子包括:

  • Amazon VPC
  • Azure Virtual Network
  • Google Cloud VPC
  • Linode VPC

虛擬網路為你的雲端資源提供隔離和安全保障,讓你能夠建立具有不同安全等級的多層架構。

負載平衡器

負載平衡器將進來的流量分散到多個運算執行個體,以提高用性和擴充套件性。它們還可以執行健康檢查,自動將不健康的執行個體移出輪轉。

負載平衡器的型別包括:

應用程式負載平衡器
運作在應用層(HTTP/HTTPS)並能根據內容(如URL路徑)路由流量。

網路負載平衡器
運作在傳輸層(TCP/UDP)並提供高效能,每秒可處理數百萬個請求。

全球負載平衡器
在多個區域間分散流量,適用於全球性應用程式。

例子包括:

  • Amazon Elastic Load Balancing (ELB)
  • Azure Load Balancer
  • Google Cloud Load Balancing
  • Linode NodeBalancers

負載平衡器對於在雲端建立高用性和可擴充套件應用程式至關重要。

內容傳遞網路

內容傳遞網路(CDN)在全球各地的邊緣位置快取內容,以減少延遲並提高使用者經驗。它們特別適合傳遞靜態內容,例如圖片、影片和JavaScript檔案。

例子包括:

  • Amazon CloudFront
  • Azure Content Delivery Network
  • Google Cloud CDN
  • Cloudflare

CDN可以大幅提升網頁應用程式的效能,因為它們從離使用者較近的位置提供內容。

DNS服務

網域名稱系統(DNS)服務將網域名稱轉換為IP位址。雲端供應商提供的受管理DNS服務具有高用性和可擴充套件性。

例子包括:

  • Amazon Route 53
  • Azure DNS
  • Google Cloud DNS
  • Linode DNS Manager

DNS服務通常包括健康檢查、流量路由策略和網域註冊等功能。

網路安全

網路安全服務幫助保護你的雲端資源免受未授權存取和攻擊。這些服務包括:

防火牆
根據規則控制進出流量。

DDoS保護
減輕分散式阻斷服務攻擊的影響。

Web應用程式防火牆
保護網頁應用程式免受常見漏洞攻擊。

私人連線
安全地將雲端資源連線到內部網路。

例子包括:

  • Amazon VPC Security Groups和Network ACLs
  • Azure Network Security Groups
  • Google Cloud Firewalls
  • 虛擬私人網路和Direct Connect服務

網路安全是雲端基礎設施的關鍵方面,特別是對於處理敏感資料或需要符合法規要求的應用程式。

基礎設施平台為建立和執行現代應用程式提供了基礎。它們提供各種運算、儲存和網路資源,以及管理這些資源的服務。 瞭解不同型別的基礎設施資源及其特性,有助於在設計和實施基礎設施時做出明智的決定。每種資源型別都有其優勢、限制和適用場景。 在接下來的章節中,我會探討如何將這些資源定義為程式碼並進行管理、如何安全地測試和交付基礎設施變更,以及如何建立有彈性與易於維護的基礎設施系統。

雲端基礎設施堆積積疊:現代架構的核心元件

在現代技術架構中,基礎設施堆積積疊(Infrastructure Stack)已成為建構可靠系統的關鍵元素。當我們討論基礎設施即程式碼(Infrastructure as Code)時,堆積積疊概念是不可或缺的核心理念。

基礎設施堆積積疊的定義與重要性

基礎設施堆積積疊是一組相關資源的集合,這些資源被定義並透過自動化工具一起管理。這些資源可能包括虛擬機器、網路設定、資料函式庫、負載平衡器等各種雲端或本地基礎設施元件。

堆積積疊的核心價值在於它將相關資源組織成一個邏輯單元,使團隊能夠:

  1. 以一致與可重複的方式佈署完整環境
  2. 追蹤基礎設施的變更歷史
  3. 實作基礎設施的版本控制
  4. 簡化複雜系統的管理

主流基礎設施管理工具

目前市場上有多種成熟的工具可用於定義和管理基礎設施堆積積疊:

Terraform

HashiCorp的Terraform是一個開放原始碼工具,使用宣告式語法定義基礎設施。它支援多雲環境,並以其強大的狀態管理和模組化設計而聞名。

resource "aws_instance" "web_server" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
  
  tags = {
    Name = "WebServer"
    Environment = "Production"
  }
}

這段Terraform程式碼定義了一個AWS EC2執行個體資源。aws_instance是資源型別,而web_server是這個資源在Terraform設定中的識別名稱。程式碼指定了AMI映像ID和執行個體型別,並增加了標籤以便於識別和管理。Terraform會使用這個定義與AWS API通訊,確保雲端環境中存在符合這些規格的執行個體。

Ansible

Ansible專注於組態管理和應用程式佈署,但也可用於基礎設施協調。它使用YAML格式的劇本(Playbook),不需要在目標系統上安裝代理。

- name: 設定網頁伺服器
  hosts: webservers
  become: yes
  
  tasks:
    - name: 安裝Nginx
      apt:
        name: nginx
        state: present
        
    - name: 啟動Nginx服務
      service:
        name: nginx
        state: started
        enabled: yes

這個Ansible劇本針對名為"webservers"的主機組執行任務。become: yes表示以提升的許可權(通常是root)執行這些任務。劇本包含兩個主要任務:首先使用apt模組安裝Nginx套件,然後使用service模組確保Nginx服務啟動並設定為開機自動啟動。Ansible會連線到目標伺服器並執行必要的命令來實作這些狀態。

CloudFormation

AWS CloudFormation是Amazon的原生基礎設施即程式碼服務,使用JSON或YAML格式的範本定義AWS資源。

Resources:
  WebServerInstance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: ami-0c55b159cbfafe1f0
      InstanceType: t2.micro
      SecurityGroups:
        - !Ref WebServerSecurityGroup
      UserData:
        Fn::Base64: !Sub |
          #!/bin/bash
          yum update -y
          yum install -y httpd
          systemctl start httpd
          systemctl enable httpd

這段CloudFormation範本定義了一個EC2執行個體資源。它指定了映像ID和執行個體型別,並參照了一個名為WebServerSecurityGroup的安全群組(該群組應在範本的其他部分定義)。UserData部分包含一個Base64編碼的啟動指令碼,該指令碼會在執行個體啟動時執行,用於安裝和啟動Apache HTTP伺服器。!Sub是一個內建函式,允許在指令碼中使用變數替換。

Pulumi

Pulumi允許開發人員使用熟悉的程式語言(如Python、JavaScript、TypeScript、Go)來定義基礎設施,而不是使用領域特定語言。

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

const webServer = new aws.ec2.Instance("webServer", {
    ami: "ami-0c55b159cbfafe1f0",
    instanceType: "t2.micro",
    tags: {
        Name: "WebServer",
        Environment: "Production",
    },
});

export const publicIp = webServer.publicIp;

這段Pulumi程式碼使用TypeScript定義了一個AWS EC2執行個體。與Terraform類別似,它指定了AMI ID、執行個體型別和標籤。不同之處在於Pulumi允許使用完整的程式語言功能,如變數、條件邏輯、迴圈等。程式碼最後匯出了執行個體的公共IP位址,使其可以被其他Pulumi堆積積疊或外部工具使用。

雲端運算模型與IaaS

提到基礎設施管理,不得不談雲端運算模型。美國家標準與技術研究院(NIST)對雲端運算提供了權威定義,將其分為多種服務模型,其中基礎設施即服務(IaaS)是最基本的一層。

根據NIST的定義,IaaS提供給消費者的能力是設定處理、儲存、網路和其他基本計算資源,消費者可以在這些資源上佈署和執行任意軟體,包括作業系統和應用程式。消費者不管理或控制底層雲端基礎設施,但對作業系統、儲存和已佈署的應用程式有控制權,並可能對選定的網路元件(如主機防火牆)有限的控制權。

IaaS的主要特點包括:

  1. 資源虛擬化 - 將實體硬體抽象為可程式化的資源
  2. 彈性擴充 - 能夠根據需求快速增加或減少資源
  3. 按使用付費 - 只為實際使用的資源付費
  4. 自助服務 - 使用者可以自行設定和管理資源

基礎設施堆積積疊的最佳實踐

在設計和管理基礎設施堆積積疊時,有幾個關鍵的最佳實踐值得遵循:

模組化設計

將基礎設施分解為可重用的模組,每個模組負責特定功能。這種方法提高了程式碼的可維護性和可重用性。

# Terraform模組範例
module "vpc" {
  source = "./modules/vpc"
  cidr_block = "10.0.0.0/16"
}

module "web_tier" {
  source = "./modules/web_tier"
  vpc_id = module.vpc.vpc_id
  subnet_ids = module.vpc.public_subnet_ids
}

這段Terraform程式碼展示了模組化設計的應用。它定義了兩個模組:一個用於建立VPC(虛擬私有雲),另一個用於建立Web層。第二個模組依賴於第一個模組的輸出(vpc_id和public_subnet_ids),展示了模組間的依賴關係。這種模組化方法使基礎設施程式碼更易於維護和重用,同時也使架構更加清晰。

環境分離

為不同環境(開發、測試、生產)維護獨立的基礎設施堆積積疊,但使用相同的程式碼基礎。

# 使用不同的設定檔案管理環境
terraform apply -var-file=dev.tfvars    # 開發環境
terraform apply -var-file=staging.tfvars # 測試環境
terraform apply -var-file=prod.tfvars    # 生產環境

這個命令列範例展示瞭如何使用Terraform的變數檔案來管理不同環境的設定。透過為每個環境(開發、測試、生產)建立單獨的變數檔案(如dev.tfvars、staging.tfvars、prod.tfvars),可以在保持基礎設施程式碼一致的同時,為不同環境設定不同的引數值(如執行個體大小、副本數量等)。這種方法確保了環境之間的一致性,同時允許根據環境需求進行必要的調整。

版本控制

將基礎設施程式碼儲存在版本控制系統中,就像對待應用程式碼一樣。

# Git工作流程範例
git checkout -b feature/add-redis-cache
# 修改基礎設施程式碼以增加Redis快取
git add .
git commit -m "Add Redis cache to improve performance"
git push origin feature/add-redis-cache
# 建立合併請求進行程式碼審查

這個Git命令序列展示了將基礎設施程式碼納入版本控制的工作流程。開發者建立一個功能分支來增加Redis快取功能,提交更改並推播到遠端倉函式庫,然後建立合併請求以進行程式碼審查。這種方法將軟體開發的最佳實踐應用於基礎設施管理,確保變更可追蹤、可審查與可回復。

自動化測試

為基礎設施程式碼編寫測試,確保它按預期工作。

# 使用Terratest進行基礎設施測試
go test -v ./test/
// Terratest範例
package test

import (
    "testing"
    "github.com/gruntwork-io/terratest/modules/terraform"
    "github.com/stretchr/testify/assert"
)

func TestWebServerDeployment(t *testing.T) {
    terraformOptions := &terraform.Options{
        TerraformDir: "../examples/web-server",
        Vars: map[string]interface{}{
            "region": "us-west-2",
        },
    }
    
    defer terraform.Destroy(t, terraformOptions)
    terraform.InitAndApply(t, terraformOptions)
    
    publicIp := terraform.Output(t, terraformOptions, "public_ip")
    assert.NotEmpty(t, publicIp, "Public IP should not be empty")
}

這段Go程式碼使用Terratest框架測試Terraform基礎設施佈署。測試函式TestWebServerDeployment設定Terraform選項,包括指定Terraform目錄和變數。它使用terraform.InitAndApply佈署基礎設施,然後使用terraform.Output取得輸出值(公共IP位址),並使用assert.NotEmpty確保該值不為空。defer terraform.Destroy確保測試完成後清理資源。這種自動化測試方法可以驗證基礎設施佈署是否按預期工作,並在CI/CD管道中提前捕捉問題。

基礎設施堆積積疊與雲端原生架構

隨著雲端原生架構的興起,基礎設施堆積積疊的概念也在不斷演進。現代基礎設施堆積積疊越來越多地包含容器協調平台(如Kubernetes)、無伺服器計算資源和各種託管服務。

這種演進要求基礎設施管理工具能夠處理更複雜的依賴關係和更多樣化的資源型別。因此,我們看到了像Crossplane這樣的新工具的出現,它們試圖統一不同型別資源的管理方式。

基礎設施堆積積疊是現代技術架構的根本,它使團隊能夠以程式碼的形式定義、版本控制和自動化佈署基礎設施。透過選擇適合的工具和遵循最佳實踐,組織可以實作基礎設施管理的自動化、一致性和可靠性。

隨著雲端技術的不斷發展,基礎設施堆積積疊的概念也將繼續演進,但其核心價值—將基礎設施視為可程式化的資源—將保持不變。掌握這些概念和工具,是現代技術專業人員的必備技能。

雲端基礎設施平台與資源管理

在現代軟體開發環境中,基礎設施即程式碼(Infrastructure as Code, IaC)已成為管理雲端資源的關鍵方法。本文將探討雲端基礎設施平台的核心概念、資源型別以及如何透過程式碼定義和管理這些資源。

雲端基礎設施平台:動態資源管理的基礎

雲端基礎設施平台是整個技術堆積積疊的基礎層,它提供了動態資源管理的能力,讓我們能夠透過API按需求佈建和變更資源。這正是「雲端」的本質定義—一個能夠以程式化方式管理的動態基礎設施。

從歷史角度看,我們經歷了從「鐵器時代」(實體硬體)到「雲端時代」的轉變:

  1. 虛擬化技術解耦了系統與硬體的直接關係
  2. 雲端技術則為這些虛擬化資源增加了API管理能力

雲端平台型別

目前市場上存在多種型別的基礎設施平台:

  • 公有雲IaaS服務:AWS、Azure、Google Cloud、Digital Ocean等
  • 私有雲IaaS產品:CloudStack、OpenStack、VMware vCloud
  • 裸機雲工具:Cobbler、FAI、Foreman

多雲策略

許多組織最終會採用多雲策略,常見的模式包括:

  • 混合雲:同時使用私有基礎設施和公有雲端服務,通常是因為遺留系統難以遷移或特定法規要求
  • 雲中立:建構能在多個公有雲平台上執行的系統,以避免繫結單一供應商
  • 多雲:在多個公有雲平台上執行不同的應用程式,以利用各平台的優勢

基礎設施資源型別

雲端平台提供三種基本資源:運算、儲存和網路。這些基本資源可以組合成更複雜的複合資源,如資料函式庫服務、負載平衡器等。

運算資源

運算資源負責執行程式碼,常見形式包括:

  • 虛擬機器(VM):平台在實體主機伺服器上執行虛擬機器例項
  • 實體伺服器:也稱為裸機,平台按需動態佈建實體伺服器
  • 伺服器叢集:平台作為一個群組佈建和管理的伺服器池
  • 容器:大多數雲平台提供容器即服務(CaaS)來佈署和執行容器例項
  • 應用程式託管叢集:用於佈署和管理多個應用程式的伺服器池
  • FaaS無伺服器程式碼執行環境:按需執行程式碼,完成後終止,如AWS Lambda

儲存資源

即使應用程式不直接使用儲存,許多服務也需要儲存資源。典型的儲存資源包括:

  • 區塊儲存(虛擬磁碟):可附加到單一伺服器或容器例項,如AWS EBS
  • 物件儲存:可從多個位置存取檔案,如Amazon S3
  • 網路檔案系統:可掛載到多個運算例項的分享儲存卷
  • 結構化資料儲存:如資料函式庫即服務(DBaaS)
  • 機密管理:用於安全儲存密碼、金鑰等敏感資訊

網路資源

軟體定義網路(SDN)使得網路設定更加靈活與安全。透過程式碼定義網路,可以實作零信任安全模型,為每個服務和應用程式提供最低層級的安全保障。

常見的網路資源包括:

  • 網路地址區塊:用於分組資源以控制流量路由
  • 名稱(如DNS專案):對映到低層級網路地址
  • 路由:設定地址區塊間允許的流量
  • 閘道:引導流量進出區塊
  • 負載平衡規則:將連線轉發到資源池
  • 代理:接受連線並使用規則轉換或路由它們
  • API閘道:處理API非核心方面的HTTP/S代理
  • 虛擬私人網路(虛擬私有網路):連線不同位置的地址區塊
  • 直接連線:雲網路與其他位置之間的專用連線
  • 網路存取規則(防火牆規則):限制或允許網路位置之間的流量
  • 非同步訊息:程式間傳送和接收訊息的佇列
  • 快取:分散資料以改善延遲
  • 服務網格:動態管理分散式系統連線的去中心化服務網路

程式碼定義一切:IaC的核心實踐

將基礎設施定義為程式碼是IaC的核心實踐之一,它帶來了可重用性、一致性和透明度等優勢。

為何要使用程式碼定義基礎設施?

雖然透過網頁介面或命令列工具佈建基礎設施看似更簡單,但使用程式碼定義系統能夠:

  • 提高重用性:相同的程式碼可用於建立多個相似的環境
  • 確保一致性:每次佈署都遵循相同的規範
  • 增強透明度:所有變更都有記錄與可追蹤
  • 加速變更:自動化流程減少手動操作時間
  • 提升品質:透過速度改善品質,這是高績效的秘訣

可定義為程式碼的元素

可以定義為程式碼的基礎設施元素包括:

  • 基礎設施堆積積疊:從雲平台佈建的元素集合
  • 伺服器設定元素:如套件、檔案、使用者帳戶和服務
  • 伺服器角色:應用於單一伺服器例項的伺服器元素集合
  • 伺服器映像定義:用於建立多個伺服器例項的映像
  • 應用程式套件:定義如何建立可佈署的應用程式成品
  • 交付服務設定:包括管道和佈署
  • 操作服務設定:如監控檢查
  • 驗證規則:包括自動化測試和合規則

選擇具有外部化設定的工具

IaC工具應該將基礎設施定義儲存在外部文字檔案中,而非封閉在工具內部。這種外部化設定模式帶來多項優勢:

  • 可以使用任何工具讀取、編輯和分析規範
  • 可以使用標準版本控制系統管理程式碼
  • 可以實施持續整合和持續交付
  • 可以建立自定義交付管道

在版本控制系統中管理程式碼

將基礎設施程式碼放入版本控制系統可獲得:

  • 可追溯性:變更歷史、執行者和上下文
  • 回復能力:當變更出現問題時還原到之前狀態
  • 關聯性:在排除問題時關聯不同元素
  • 可見性:團隊成員可看到所有變更
  • 可操作性:每次變更可自動觸發行動

需要注意的是,不應將未加密的機密資訊(如密碼和金鑰)放入原始碼控制中,即使是私有儲存函式庫。

基礎設施程式碼語言型別

基礎設施程式碼主要有兩種語言正規化:宣告式和命令式。

宣告式基礎設施語言

宣告式程式碼定義系統的期望狀態,而不指定如何實作。例如:

virtual_machine:
  name: my_application_server
  source_image: 'base_linux'
  cpu: 2
  ram: 2GB
  network: private_network_segment
  provision:
    provisioner: servermaker
    role: tomcat_server

宣告式程式碼的優勢在於:

  • 分離「想要什麼」和「如何建立」
  • 程式碼更清晰直接
  • 工具會處理檢查現有狀態並計算需要的變更

宣告式程式碼必須是冪等的(idempotent),意味著可以重複執行而不會產生不良副作用。

命令式(程式化)基礎設施語言

命令式程式碼指定如何實作目標的指令集。當需要根據情況產生不同結果時,命令式語言更為適合。例如,動態發現資料中心數量並在每個中建立VLAN:

this_country = getArgument("country")
data_centers = CloudApi.find_data_centers(country: this_country)
full_ip_range = 10.2.0.0/16
vlan_number = 0
for $DATA_CENTER in data_centers {
  vlan = CloudApi.vlan.apply(
    name: "public_vlan_${DATA_CENTER.name}"
    data_center: $DATA_CENTER.id
    ip_range: Networking.subrange(
      full_ip_range,
      data_centers.howmany,
      data_centers.howmany++
    )
  )
}

領域特定語言(DSL)與通用語言

許多基礎設施工具使用領域特定語言(DSL),這些語言專為建模特定領域(如基礎設施)而設計。DSL使程式碼更易於編寫和理解,因為它直接對映所定義的事物。

相比之下,使用通用程式設計語言(如JavaScript、Python、Ruby或TypeScript)的最大優勢是工具生態系統,包括IDE支援、語法突顯、程式碼重構和測試支援。

實施原則

為了輕鬆安全地更新和演進基礎設施系統,需要保持程式碼函式庫的清晰:易於理解、測試、維護和改進。

分離宣告式和命令式程式碼

混合宣告式和命令式程式碼是一種設計氣味,表明應該將程式碼分為不同關注點。

將基礎設施程式碼視為真正的程式碼

許多基礎設施程式碼函式庫從設定案和實用指令碼演變成難以管理的混亂狀態。要保持基礎設施程式碼函式庫的可維護性,需要將其視為一等公民:

  • 設計和管理基礎設施程式碼,使其易於理解和維護
  • 遵循程式碼品質實踐,如程式碼審查、結對程式設計和自動化測試
  • 團隊應意識到技術債務並努力將其最小化

基礎設施即程式碼是現代雲端環境中管理資源的關鍵方法。透過瞭解不同型別的基礎設施平台、資源型別以及如何使用程式碼定義和管理這些資源,我們可以建立更靈活、可靠與安全的系統。無論是選擇宣告式還是命令式語言,關鍵在於分離關注點,保持程式碼的清晰和可維護性,並將基礎設施程式碼視為與應用程式碼同等重要的資產。

建構基礎設施堆積積疊與環境的藝術

基礎設施即程式碼的核心實踐

在現代雲端架構中,將基礎設施定義為程式碼已成為不可或缺的實踐。這種方法不僅提供了自動化的優勢,更為團隊帶來了前所未有的靈活性與可靠性。基礎設施程式碼成為系統的真實記錄,為各種角色提供價值:

  • 新加入的團隊成員可以透過瀏覽程式碼來瞭解系統架構
  • 團隊成員能夠閲讀程式碼和檢視提交記錄,瞭解他人的工作內容
  • 技術審核人員可以利用程式碼評估需要改進的地方
  • 稽核人員能夠檢視程式碼和版本歷史,獲得系統的精確影像

雖然基礎設施程式碼是寶貴的檔案來源,但它通常需要搭配高階檔案以提供上下文和策略。許多團隊選擇將這些檔案也以程式碼方式管理,例如使用標記語言編寫架構決策記錄(ADRs)並將其儲存在版本控制系統中。更進一步,我們可以從程式碼自動生成架構圖表和引數參考等有用資料,並透過變更管理管道在每次程式碼變更時更新檔案。

基礎設施堆積積疊的本質

基礎設施堆積積疊(Infrastructure Stack)是一組基礎設施資源的集合,這些資源被定義、佈建和更新為一個單元。這個概念將第3章和第4章的內容結合起來,描述瞭如何使用程式碼管理基礎設施平台提供的資源。

什麼是基礎設施堆積積疊?

基礎設施堆積積疊是一組基礎設施資源的集合,這些資源被定義、佈建和更新為一個單元。你編寫原始碼來定義堆積積疊的元素,這些元素是基礎設施平台提供的資源和服務。例如,你的堆積積疊可能包括虛擬機器、磁碟區和子網路。

當你執行堆積積疊管理工具時,它會讀取你的堆積積疊原始碼,並使用雲端平台的API來組裝程式碼中定義的元素,從而佈建堆積積疊的例項。

堆積積疊管理工具的例子

  • HashiCorp Terraform
  • AWS CloudFormation
  • Azure Resource Manager
  • Google Cloud Deployment Manager
  • OpenStack Heat
  • Pulumi
  • Bosh

某些伺服器設定工具也有擴充套件功能可以處理基礎設施堆積積疊,例如Ansible Cloud Modules、Chef Provisioning(現已終止支援)、Puppet Cloud Management和Salt Cloud。

「堆積積疊」作為術語

大多數堆積積疊管理工具並不自稱為堆積積疊管理工具。每個工具都有自己的術語來描述它所管理的基礎設施單元。在這篇文章中,我描述的模式和實踐應該與任何這些工具相關。我選擇使用「堆積積疊」這個詞。

業界對於這個概念的稱呼尚未達成共識。每個人心中都有完全不同的詞彙。因此,在達成共識之前,我將繼續使用「堆積積疊」這個詞。

堆積積疊程式碼

每個堆積積疊都由原始碼定義,這些程式碼宣告瞭它應該包含哪些基礎設施元素。Terraform程式碼(.tf檔案)和CloudFormation範本都是基礎設施堆積積疊程式碼的例子。堆積積疊專案包含定義堆積積疊基礎設施的原始碼。

以下是一個使用虛構工具Stackmaker的堆積積疊原始碼專案的資料夾結構:

stack-project/
├── src/
 ├── dns.infra
 ├── load_balancers.infra
 ├── networking.infra
 └── webserver.infra
└── test/

堆積積疊例項

你可以使用單個堆積積疊專案來佈建多個堆積積疊例項。當你為專案執行堆積積疊工具時,它使用平台API來確保堆積積疊例項存在,並使其與專案程式碼比對。如果堆積積疊例項不存在,工具會建立它。如果堆積積疊例項存在但與程式碼不完全比對,則工具會修改例項使其比對。

我經常將這個過程描述為將程式碼「應用」到例項上。

如果你更改程式碼並重新執行工具,它會更改堆積積疊例項以比對你的更改。如果你在不對程式碼進行任何更改的情況下再次執行工具,那麼它應該保持堆積積疊例項的原樣。

在堆積積疊中設定伺服器

對於不完全根據容器或無伺服器應用程式架構的系統,基礎設施程式碼通常包含大量用於佈建和設定伺服器的程式碼。即使是根據容器的系統也需要建立主機伺服器來執行容器。

最早的主流基礎設施即程式碼工具,如CFEngine、Puppet和Chef,都是用來設定伺服器的。

你應該將建立伺服器的程式碼與建立堆積積疊的程式碼解耦。這樣做可以使程式碼更容易理解,透過解耦簡化變更,並支援伺服器程式碼的重用和測試。

堆積積疊程式碼通常指定要建立哪些伺服器,並透過呼叫伺服器設定工具來傳遞有關它們將執行的環境的訊息。以下是一個呼叫虛構servermaker工具來設定伺服器的堆積積疊定義範例:

virtual_machine:
  name: appserver-waterworks-${environment}
  source_image: shopspinner-base-appserver
  memory: 4GB
  provision:
    tool: servermaker
    parameters:
      maker_server: maker.shopspinner.xyz
      role: appserver
      environment: ${environment}

這個堆積積疊定義了一個應用程式伺服器例項,從名為shopspinner-appserver的伺服器映像建立,具有4GB的RAM。定義包括一個觸發執行Servermaker的佈建過程的子句。程式碼還為Servermaker工具傳遞了幾個引數。這些引數包括設定伺服器(maker_server)的地址,該伺服器託管設定檔案;以及一個角色appserver,Servermaker使用它來決定要應用於這個特定伺服器的設定。它還傳遞環境名稱,設定可以使用它來自定義伺服器。

基礎設施語言型別:低階基礎設施語言

大多數流行的堆積積疊管理工具語言都是低階基礎設施語言。也就是説,該語言直接暴露了你正在使用的基礎設施平台提供的基礎設施資源。

作為基礎設施程式設計師,你的工作是編寫將這些資源連線在一起形成有用東西的程式碼,例如:

address_block:
  name: application_network_tier
  address_range: 10.1.0.0/24"
  vlans:
    - appserver_vlan_A
      address_range: 10.1.0.0/16
virtual_machine:
  name: shopspinner_appserver_A
  vlan: application_network_tier.appserver_vlan_A
gateway:
  name: public_internet_gateway
  address_block: application_network_tier
inbound_route:
  gateway: public_internet_gateway
  public_ip: 192.168.99.99
  incoming_port: 443
  destination:
    virtual_machine: shopspinner_appserver_A
    port: 8443

這個簡化的偽程式碼範例定義了一個虛擬機器、一個地址區塊和VLAN,以及一個網際網路閘道。然後它將它們連線在一起,並定義了一個入站連線,將進入https://192.168.99.99的連線路由到虛擬機器上的8443連線埠。

平台本身可能提供更高層次的抽象;例如,提供應用程式託管叢集。平台提供的叢集元素可能會自動佈建伺服器例項和網路由。但低階基礎設施程式碼直接對映到平台API暴露的資源和選項。

高階基礎設施語言

高階基礎設施語言定義的實體不直接對映到底層平台提供的資源。例如,上述範例的高階程式碼版本可能會宣告應用程式伺服器的基本內容,如下所示:

application_server:
  public_ip: 192.168.99.99

在這個例子中,應用程式碼要麼佈建前一個例子中的網路和伺服器資源,要麼發現有資源來使用。這段程式碼呼叫的工具或函式庫決定了網路連線埠和VLAN的值,以及如何構建虛擬伺服器。

許多應用程式託管解決方案,如PaaS平台或封裝叢集,提供了這種級別的抽象。你為你的應用程式編寫佈署描述符,平台分配基礎設施資源來佈署它。

在其他情況下,你可以透過編寫函式庫或模組來構建自己的抽象層。

結構化堆積積疊的模式與反模式

基礎設施設計的一個挑戰是決定如何調整和結構化堆積積疊。你可以建立一個單一的堆積積疊程式碼專案來管理整個系統。但隨著系統的增長,這變得難以處理。在這一節中,我將描述結構化基礎設施堆積積疊的模式和反模式。

以下模式都描述了將系統的各個部分組到一個或多個堆積積疊中的方法。你可以將它們視為一個連續體:

  • 單體堆積積疊將整個系統放入一個堆積積疊中。
  • 應用程式群組堆積積疊將系統的多個相關部分組到堆積積疊中。
  • 服務堆積積疊將單個應用程式的所有基礎設施放入單個堆積積疊中。
  • 微堆積積疊將給定應用程式或服務的基礎設施分解為多個堆積積疊。

反模式:單體堆積積疊

單體堆積積疊是一個包含太多元素的基礎設施堆積積疊,使其難以維護。

動機

人們構建單體堆積積疊是因為向系統增加新元素的最簡單方法是將其增加到現有專案中。每個新堆積積疊都會增加更多的移動部件,這些部件可能需要被協調、整合和測試。

單一堆積積疊更簡單管理。對於適度大小的基礎設施元素集合,單體堆積積疊可能有意義。但更常見的是,單體堆積積疊會有機地失控增長。

適用性

當你的系統小而簡單時,單體堆積積疊可能是適當的。當你的系統增長,佈建和更新需要更長時間時,它就不適合了。

後果

更改大型堆積積疊比更改較小的堆積積疊風險更大。可能出錯的事情更多——它有更大的爆炸半徑。失敗變更的影響可能更廣泛,因為堆積積疊內有更多的服務和應用程式。較大的堆積積疊佈建和變更也更慢,這使它們更難管理。

由於更改單體堆積積疊的速度和風險,人們傾向於不那麼頻繁地進行更改,並花更長時間來做。這種額外的摩擦可能導致更高水平的技術債務。

爆炸半徑

直接爆炸半徑是應用你的變更命令所包含的程式碼範圍。例如,當你執行terraform apply時,直接爆炸半徑包括你專案中的所有程式碼。間接爆炸半徑包括系統中依賴於你直接爆炸半徑中資源的其他元素,這些元素可能會因為破壞這些資源而受到影響。

實作

你透過建立一個基礎設施堆積積疊專案然後不斷增加程式碼來構建單體堆積積疊,而不是將其拆分為多個堆積積疊。

相關模式

單體堆積積疊的對立面是微堆積積疊,它旨在保持堆積積疊小,使其更容易維護和改進。單體堆積積疊可能是一個失控的應用程式群組堆積積疊。

我的堆積積疊是單體嗎?

你的基礎設施堆積積疊是否為單體是一個判斷問題。單體堆積積疊的症狀包括:

  • 很難理解堆積積疊的各個部分如何組合在一起(它們可能太混亂而無法理解,或者它們可能不太適合在一起)。
  • 新人需要一段時間來學習堆積積疊的程式碼函式庫。
  • 除錯堆積積疊問題很困難。
  • 對堆積積疊的更改經常導致問題。
  • 你花太多時間維護系統和流程,其目的是管理堆積積疊的複雜性。

堆積積疊是否變得單體的一個關鍵指標是任何時候有多少人在處理對它的更改。同時有多人處理堆積積疊的情況越常見,你花在協調更改上的時間就越多。多個團隊對同一堆積積疊進行更改甚至更糟。如果在佈署對給定堆積積疊的更改時經常出現失敗和衝突,那麼它可能太大了。

功能分支是應對這種情況的策略,但它可能會增加交付的摩擦和開銷。習慣性地使用功能分支來處理堆積積疊表明堆積積疊已經變成單體。

CI是一種更可持續的方式,使多人在單一堆積積疊上工作更安全。然而,隨著堆積積疊越來越單體化,CI構建需要更長時間執行,並且變得更難維持良好的構建紀律。如果你團隊的CI很草率,這是你的堆積積疊是單體的另一個跡象。

這些問題與單一團隊在基礎設施堆積積疊上工作有關。多個團隊在分享堆積積疊上工作是一個明確的跡象,表明應該考慮將其拆分為更易於管理的部分。

模式:應用程式群組堆積積疊

應用程式群組堆積積疊包括多個相關應用程式或服務的基礎設施。所有這些應用程式的基礎設施都作為一個群組進行佈建和管理。

例如,ShopSpinner的產品應用程式堆積積疊包括用於瀏覽產品、搜尋產品和管理購物籃的獨立服務。所有這些的伺服器和其他基礎設施都組合在單個堆積積疊例項中。

動機

將多個相關服務的基礎設施定義在一起可以使管理應用程式作為單一單元更容易。

適用性

當單一團隊擁有所有應用程式部分的基礎設施和佈署時,這種模式可以很好地工作。應用程式群組堆積積疊可以將堆積積疊的邊界與團隊的責任對齊。

多服務堆積積疊有時作為從單體堆積積疊到服務堆積積疊的增量步驟很有用。

後果

將多個應用程式的基礎設施分組在一起也結合了變更的時間、風險和步調。團隊需要管理對整個堆積積疊的每次變更的風險,即使只有一部分正在變更。如果堆積積疊的某些部分比其他部分更頻繁地變更,這種模式效率低下。

佈建、變更和測試堆積積疊的時間根據整個堆積積疊。因此,如果一次只更改堆積積疊的一部分是常見的,將它們分組會增加不必要的開銷和風險。

實作

要建立應用程式群組堆積積疊,你需要定義一個基礎設施專案,為一組服務構建所有基礎設施。你可以用一個命令佈建和銷毀應用程式的所有部分。

相關模式

這種模式有成長為單體堆積積疊的風險。在另一個方向上,將應用程式群組堆積積疊中的每個服務分解為單獨的堆積積疊會建立服務堆積積疊。

模式:服務堆積積疊

服務堆積積疊在單獨的基礎設施堆積積疊中管理每個可佈署應用程式元件的基礎設施。

動機

服務堆積積疊將基礎設施的邊界與執行在其上的軟體對齊。這種對齊將變更的爆炸半徑限制在一個服務內,這簡化了安排變更的過程。服務團隊可以擁有與其軟體相關的基礎設施。

適用性

服務堆積積疊可以與微服務應用程式架構很好地配合。它們還幫助具有自主團隊的組織確保每個團隊擁有其基礎設施。

後果

如果你有多個應用程式,每個都有一個基礎設施堆積積疊,可能會有不必要的程式碼重複。例如,每個堆積積疊可能包括指定如何佈建應用程式伺服器的程式碼。重複可能會鼓勵不一致,例如使用不同的作業系統版本或不同的網路設定。你可以透過使用模組來分享程式碼來緩解這一點。

實作

每個應用程式或服務都有一個單獨的基礎設施程式碼專案。建立新應用程式時,團隊可能會從另一個應用程式的基礎設施中複製程式碼。或者團隊可以使用參考專案,其中包含建立新堆積積疊的樣板程式碼。

在某些情況下,每個堆積積疊可能是完整的,不與其他應用程式堆積積疊分享任何基礎設施。在其他情況下,團隊可能會建立具有支援多個應用程式堆積積疊的基礎設施的堆積積疊。

相關模式

服務堆積積疊模式介於應用程式群組堆積積疊(在單一堆積積疊中有多個應用程式)和微堆積積疊(將單一應用程式的基礎設施分解為多個堆積積疊)之間。

模式:微堆積積疊

微堆積積疊模式將單一服務的基礎設施分割為多個堆積積疊。

例如,你可能為網路、伺服器和資料函式庫各有一個單獨的堆積積疊專案。

動機

服務基礎設施的不同部分可能以不同的速率變化。或者它們可能具有使它們更容易單獨管理的不同特性。例如,管理伺服器例項的某些方法涉及頻繁地銷毀和重建它們。然而,某些服務在資料函式庫或磁碟卷中使用持久資料。在單獨的堆積積疊中管理伺服器和資料意味著它們可以有不同的生命週期,伺服器堆積積疊比資料堆積積疊重建得更頻繁。

後果

雖然較小的堆積積疊本身更簡單,但有更多的移動部件增加了複雜性。

實作

增加新的微堆積積疊涉及建立新的堆積積疊專案。你需要在堆積積疊之間劃定正確的邊界,以保持它們適當大小並易於管理。相關模式包括解決這個問題的方法。你可能還需要整合不同的堆積積疊。

相關模式

微堆積積疊是與單體堆積積疊相對的光譜的另一端,單體堆積積疊中單一堆積積疊包含系統的所有基礎設施。

使用堆積積疊建立環境

在基礎設施即程式碼的世界中,環境是一個關鍵概念。環境是一個完整的系統例項,用於特定目的,如開發、測試或生產。每個環境都由一個或多個堆積積疊例項組成。

環境與堆積積疊的關係

環境通常包含多個堆積積疊例項。例如,一個生產環境可能包括網路堆積積疊、資料函式庫堆積積疊和多個應用程式服務堆積積疊。這些堆積積疊共同工作,形成一個完整的系統。

堆積積疊程式碼專案可以用來建立多個環境。例如,同一個網路堆積積疊程式碼可以用來在測試環境和生產環境中建立網路基礎設施。這種重用確保了環境之間的一致性,同時允許根據環境的需求進行特定設定。

環境管理的最佳實踐

  1. 環境引數化:設計堆積積疊程式碼時,使用引數來處理環境之間的差異,如資源大小、網路設定等。

  2. 環境隔離:確保不同環境之間的資源完全隔離,防止測試活動影響生產系統。

  3. 一致的佈署流程:使用相同的自動化流程將變更佈署到所有環境,減少"在我的機器上可以執行"的問題。

  4. 環境特定設定:允許某些設定因環境而異,例如,生產環境可能需要更高的安全性設定或更大的資源分配。

基礎設施堆積積疊是自動化基礎設施的基本構建塊。本文詳細介紹了將系統定義為程式碼的核心實踐,包括為什麼應該將事物定義為程式碼,以及系統的哪些部分可以定義為程式碼。

文章探討了不同的基礎設施語言正規化,這可能看起來是一個抽象的主題。但在正確的方式使用正確的語言是建立有效基礎設施的關鍵挑戰,這是行業尚未解決的挑戰。因此,在系統的不同部分使用哪種型別的語言,以及這些決定的後果,是一個將在整個基礎設施管理中反覆出現的主題。

本文中的模式是思考如何將基礎設施組織成堆積積疊的起點。從單體堆積積疊到微堆積積疊,每種方法都有其優勢和挑戰。選擇正確的模式取決於你的團隊結構、系統複雜性和變更頻率等因素。

隨著我們進入基礎設施堆積積疊的世界,下一步是瞭解如何使用這些堆積積疊構建完整的環境,以及如何管理這些環境之間的關係和設定差異。這將是我們繼續探索基礎設施即程式碼旅程的下一個重要主題。