自動化VPC和網路設定
下面的Playbook建立一個基本的VPC環境,包括子網、網際網路閘道和路由表:
---
- name: 建立VPC環境
hosts: localhost
connection: local
gather_facts: False
vars:
region: ap-northeast-1
vpc_name: "my-vpc"
vpc_cidr: "10.0.0.0/16"
public_subnet_cidr: "10.0.1.0/24"
private_subnet_cidr: "10.0.2.0/24"
az: "ap-northeast-1a"
tasks:
- name: 建立VPC
ec2_vpc_net:
name
## AWS 雲端服務入門與核心服務概述
### Amazon S3 儲存服務
Amazon S3 (Simple Storage Service) 提供高度耐用與可用性強的儲存服務,能夠存放從網頁應用程式到媒體檔案等各種內容。透過 S3,你可以將整個儲存基礎設施轉移到雲端,利用其可擴充套件性和按用量計費的定價模式來應對不斷增長的儲存需求。
S3 的主要優勢在於它的彈性使用方式:你可以直接從 S3 分發內容,或將 S3 作為來源儲存函式庫送內容到 Amazon CloudFront 邊緣位置,加速全球內容交付。
### 彈性負載平衡 (ELB)
彈性負載平衡 (Elastic Load Balancing) 能自動將傳入的應用程式流量分配到多個 Amazon EC2 執行個體上。這項服務讓你的應用程式達到更高的容錯能力,同時無縫提供分配應用程式流量所需的負載平衡容量。
ELB 的關鍵特性包括:
- 自動擴充套件請求處理能力,以滿足應用程式流量需求
- 與 Auto Scaling 整合,確保後端容量能夠應對不同流量水平,無需手動干預
- 提高應用程式的可用性和容錯能力
### Route 53 DNS 服務
Amazon Route 53 是一個高用性與可擴充套件的網域名稱系統 (DNS) 網路服務。它為開發人員和企業提供一種極其可靠與經濟實惠的方式,將終端使用者引導至網際網路應用程式,透過將網域名稱 (如 www.example.com) 轉換為電腦連線所需的數字 IP 地址 (如 192.0.2.1)。
Route 53 的主要功能:
- 有效地將使用者請求連線到在 AWS 上執行的基礎設施,如 EC2 執行個體、彈性負載平衡器或 S3 儲存桶
- 也可用於將使用者引導到 AWS 外部的基礎設施
- 使用全球 DNS 伺服器網路,以低延遲回應 DNS 查詢
- 可透過 AWS 管理主控台或 API 輕鬆管理公共 DNS 記錄
- 與其他 AWS 服務整合,如 IAM 服務,可控制組織內誰能修改 DNS 記錄
### AWS 全球基礎設施
傳統基礎設施難以為全球分散的使用者群提供出色效能,大多數公司為節省成本和時間,只專注於一個地理區域。而雲端運算改變了這一點 - 你可以輕鬆地在世界各地的任何或所有 AWS 區域佈署應用程式。
這意味著你可以最低成本為客戶提供更低延遲和更佳體驗。AWS 的全球基礎設施讓企業能夠快速拓展全球業務,不受地理位置限制。
### 設定 AWS 帳戶
如果你還沒有 Amazon Web Services 帳戶,請依照以下步驟設定:
1. 存取 http://aws.amazon.com 並點選「登入主控台」按鈕
2. 選擇「我是新使用者」選項,填寫電子郵件地址,然後點選「使用我們的安全伺服器登入」按鈕
3. 輸入你的姓名、再次輸入電子郵件地址,設定密碼,然後點選「建立帳戶」按鈕
4. 選擇「個人帳戶」(或如果要為公司建立 AWS 帳戶,則選擇「公司帳戶」),填寫聯絡資訊表格,輸入安全檢查字元,確認接受 AWS 客戶協定,然後點選「安全提交」按鈕
5. 輸入信用卡號碼和帳單地址資訊,點選「繼續」按鈕
6. 驗證身份:輸入有效的電話或行動電話號碼,點選「立即致電」按鈕,接聽電話並輸入顯示的 PIN 碼
7. 選擇支援方案,點選「繼續」按鈕
完成設定後,你將收到確認帳戶設定的電子郵件。值得注意的是,初始帳戶註冊提供一年的免費使用層級。
#### 關於費用注意事項
設定 AWS 帳戶時,你已提供信用卡資訊來支付所使用的資源。建議瞭解每項服務的定價方案,以避免意外的費用支出。AWS 提供線上計算器來估算每月的 AWS 帳單。
### AWS 管理主控台
AWS 管理主控台是一個直覺與功能強大的網頁介面,讓你能夠管理所有 AWS 資源。透過這個單一平台,你可以執行各種任務,從佈署新應用程式到監控應用程式的健康狀態。
主控台主要功能:
- 管理從 EC2 執行個體到 DynamoDB 資料表等所有 AWS 資源
- 管理 AWS 帳戶的各個方面,包括檢視每月按服務分類別的支出
- 管理安全憑證或設定新的 IAM 使用者
- 可自訂導航欄以快速存取常用服務
每項服務都有自己的主控台,你可以從 AWS 管理主控台存取。
### 建立第一個 EC2 執行個體
EC2 (Elastic Compute Cloud) 是最廣泛使用的 AWS 服務。EC2 徹底改變了伺服器佈建的方式,只需在 AWS 管理主控台上點選幾下,就能在幾分鐘內獲得虛擬伺服器。
#### 建立金鑰對
首先,需要建立一個金鑰對。AWS 使用公鑰密碼學來保護執行個體的登入資訊。Linux 執行個體沒有密碼,你需要使用金鑰對安全地登入。啟動執行個體時,需指定金鑰對的名稱,然後在登入時提供私鑰。
需要注意的是,金鑰對是區域特定的。例如,如果計劃在亞太地區 (雪梨) 啟動執行個體,必須為該區域的執行個體建立金鑰對。
AWS 雲端服務的核心價值
AWS 的核心優勢在於其服務整合性與彈性。以 S3 為例,它不僅是一個儲存服務,更是一個可以與 CloudFront、EC2 和其他服務無縫整合的平台。當建立一個完整的雲端應用程式時,這種整合能力讓架構設計變得更加靈活。
在實際佈署中,玄貓發現 ELB 與 Auto Scaling 的組合是處理流量波動的絕佳解決方案。這種自動化擴充套件機制讓系統能夠在高峰期自動增加資源,並在低峰期釋放資源,從而最佳化成本。這是傳統基礎設施難以實作的靈活性。
Route 53 的全球分散式架構則是國際業務的關鍵支柱。透過將 DNS 查詢路由到最近的伺服器,它能夠顯著降低延遲,提升使用者經驗。這對於需要全球佈署的應用程式來說是無價的優勢。
在設定 AWS 帳戶時,玄貓建議特別注意免費層級的使用限制。許多新手誤以為「免費」意味著無限制使用,但實際上每項服務都有明確的使用上限。超過這些限制後,費用可能會迅速累積。這是雲端服務的一個重要管理導向 - 資源使用的可見性與控制。
AWS 管理主控台的直覺設計大降低了雲端服務的使用門檻。不過,對於需要自動化的大型佈署,玄貓推薦學習使用 AWS CLI 或 CloudFormation,這些工具能夠實作基礎設施即程式碼 (IaC),提高佈署效率和一致性。
EC2 作為 AWS 的核心計算服務,其彈性和多樣性是其最大特點。從微型例項到高效能計算例項,EC2 提供了適合各種工作負載的選項。在選擇例項類別時,應根據應用程式的具體需求進行評估,而不僅是考慮成本因素。
雲端服務的真正價值在於它將基礎設施轉變為程式化資源,使技術團隊能夠將更多精力放在創新和業務價值上,而非基礎設施管理的繁瑣工作上。
## 雲端佈署的第一步:AWS關鍵設定
在雲端運算的世界中,AWS(Amazon Web Services)是一個領先的平台,提供了豐富的服務幫助企業和開發者建立、佈署和管理應用程式。作為一名經常在不同雲端環境中工作的技術工作者,我認為掌握AWS的基礎設定是進入雲端世界的關鍵。本文將帶你完成AWS環境設定的三個基本步驟:建立金鑰對、設定安全群組以及啟動EC2執行個體。
### 金鑰對:你的雲端伺服器鑰匙
在AWS中,金鑰對就像是你進入雲端伺服器的數位鑰匙。它由公鑰和私鑰組成,AWS儲存公鑰,而你需要安全地保管私鑰。這種設計確保只有擁有對應私鑰的人才能連線到你的EC2執行個體。
#### 如何建立金鑰對
1. 登入AWS管理主控台,開啟EC2儀錶板(https://console.aws.amazon.com/ec2)
2. 從導航欄中選擇你要建立金鑰對的區域
3. 在導航窗格中點選「金鑰對」
4. 點選「建立金鑰對」
5. 在「金鑰對名稱」欄位中輸入一個容易記憶的名稱,建議使用「你的名稱-key-pair-區網域名稱」的格式,例如「blackcat-key-pair-apsydney」
6. 點選「建立」按鈕,瀏覽器將自動下載私鑰檔案(.pem檔案)
> **重要提醒**:這是你唯一可以儲存私鑰檔案的機會。當你啟動執行個體時需要提供金鑰對的名稱,而每次連線到執行個體時則需要對應的私鑰。請將私鑰檔案存放在安全的地方!
#### 設定私鑰檔案許可權
如果你使用Mac或Linux系統,需要設定私鑰檔案的許可權,確保只有你能讀取:
```bash
$ chmod 400 blackcat-key-pair-apsydney.pem
在Windows系統上使用PuTTY連線Linux執行個體
如果你使用Windows系統,可以使用PuTTY連線到Linux執行個體。你需要先將.pem檔案轉換為PuTTY可用的.ppk格式:
- 從PuTTY官網下載並安裝PuTTY(建議安裝完整套件)
- 啟動PuTTYgen(從開始選單點選「所有程式 > PuTTY > PuTTYgen」)
- 在「要產生的金鑰類別」下,選擇「SSH-2 RSA」
- 點選「載入」並選擇你之前建立的.pem私鑰檔案(需要顯示所有類別的檔案)
- 在確認對話方塊中點選「確定」
- 點選「儲存私鑰」(PuTTYgen會顯示關於不使用密碼儲存金鑰的警告,點選「是」)
- 為金鑰指定與金鑰對相同的名稱,PuTTY會自動增加.ppk副檔名
金鑰對是一種非對稱加密技術的應用。公鑰用於加密資料,而私鑰則用於解密。當你連線到EC2執行個體時,AWS使用你提供的公鑰來加密一個挑戰,只有擁有對應私鑰的人才能解密這個挑戰並成功連線。這比使用密碼更安全,因為私鑰不會透過網路傳輸,與長度通常為2048位或更長,幾乎不可能被暴力破解。
chmod 400命令設定檔案許可權為只有擁有者可讀取,這是一種安全最佳實踐,防止其他使用者讀取你的私鑰。在Windows中,PuTTY不能直接使用.pem格式的私鑰,所以需要使用PuTTYgen將其轉換為.ppk格式。
安全群組:你的雲端防火牆
安全群組是AWS中的虛擬防火牆,控制著進出執行個體的網路流量。在啟動執行個體前,我們需要建立一個安全群組來定義允許哪些流量進入和離開我們的執行個體。
建立安全群組的步驟
- 開啟Amazon EC2儀錶板(https://console.aws.amazon.com/ec2)
- 從導航欄選擇你要建立安全群組的區域(安全群組是區域特定的)
- 在導航窗格中點選「安全群組」
- 點選「建立安全群組」
- 輸入安全群組名稱和描述,建議使用「SG_」加區網域名稱,例如「SG_apsydney」
- 在「入站」標籤中,增加以下規則:
- 選擇「HTTP」,來源設定為「任何地方」(0.0.0.0/0)
- 選擇「HTTPS」,來源設定為「任何地方」(0.0.0.0/0)
- 選擇「SSH」,來源設定為「自訂IP」,並指定你的電腦或網路的公共IP位址(CIDR表示法)
關於SSH規則的來源IP設定,可以使用以下方法:
- 如果你的IP是固定的,例如203.0.100.2,則使用203.0.100.2/32
- 如果你的公司從一個IP範圍分配地址,則指定整個範圍,例如203.0.100.0/24
- 你可以使用AWS提供的服務(http://checkip.amazonaws.com)查詢你的公共IP位址
- 為了方便,你也可以在來源框中選擇「我的IP」,系統會自動填入你當前的IP位址
警告:出於安全考量,不建議允許所有IP位址(0.0.0.0/0)透過SSH存取你的執行個體,除非是短期測試用途。
安全群組是一種狀態性防火牆,意味著它會記住允許的入站流量並自動允許相應的出站回應流量,無需額外的出站規則。這與傳統防火牆不同,後者通常需要同時設定入站和出站規則。
CIDR(無類別域間路由)表示法是一種用於指定IP位址範圍的標準方法。格式為「IP位址/字首長度」,字首長度表示網路部分的位數。例如,/32表示單一IP位址,/24表示一個包含256個IP位址的範圍。
為什麼不建議開放0.0.0.0/0的SSH存取?因為這會讓全世界任何人都能嘗試SSH連線到你的執行個體,增加被暴力攻擊的風險。限制SSH僅允許你的IP位址或IP範圍是一種重要的安全實踐。
啟動你的第一個EC2執行個體
現在我們已經準備好了金鑰對和安全群組,可以啟動第一個EC2執行個體了。EC2(Elastic Compute Cloud)是AWS的核心服務之一,提供可擴充套件的運算能力。
啟動執行個體的步驟
- 開啟Amazon EC2儀錶板(https://console.aws.amazon.com/ec2)
- 從主控台儀錶板點選「啟動執行個體」
- 在「選擇Amazon機器映像(AMI)」頁面,選擇標記為「免費方案合格」的64位元Amazon Linux AMI
- 在「選擇執行個體類別」頁面,系統預設選擇t2.micro或t1.micro(取決於AMI虛擬化類別)。點選「檢視與啟動」讓精靈完成其他設定
- 在「檢視執行個體啟動」頁面,需要選擇我們之前建立的安全群組:
- 點選「編輯安全群組」
- 在「設定安全群組」頁面,確保選中「選擇現有安全群組」選項
- 從列表中選擇你之前建立的安全群組,然後點選「檢視並啟動」
- 在「檢視執行個體啟動」頁面,點選「啟動」
- 在「選擇現有金鑰對或建立新金鑰對」對話方塊中,選擇「選擇現有金鑰對」,然後選擇你之前建立的金鑰對。勾選確認核取方塊,然後點選「啟動執行個體」
- 確認頁面會通知你執行個體正在啟動。點選「檢視執行個體」回傳主控台
- 在「執行個體」畫面,你可以檢視執行個體的狀態。執行個體啟動需要一小段時間。初始狀態為「待處理」,啟動後狀態變為「執行中」,並獲得一個公共DNS名稱
要了解更多關於Amazon EC2執行個體類別的資訊,可以參考AWS官方檔案
EC2的啟動過程涉及多個AWS內部系統的協調工作。當你點選「啟動執行個體」時,AWS會在選定的可用區分配物理硬體資源、設定網路介面、附加儲存卷、設定安全群組並啟動作業系統。
AMI(Amazon Machine Image)是一種預設設定的範本,包含作業系統和可能的應用軟體。選擇AMI就像選擇電腦的作業系統一樣,不同的是AMI可能已經預裝了特定的軟體套件和設定。
t2.micro和t1.micro是AWS提供的入門級執行個體類別,適合低流量網站、開發環境或小型應用。它們是「可爆發」執行個體類別,意味著它們在閒置時積累CPU積分,然後在需要時消耗這些積分以獲得更高的CPU效能。這種設計特別適合間歇性工作負載。
連線到你的EC2執行個體
現在你已經成功啟動了EC2執行個體,下一步是連線到它。如果你使用Windows作業系統,需要使用PuTTY連線到Linux EC2執行個體。
使用PuTTY連線到Linux執行個體
啟動PuTTY(從開始選單點選「所有程式 > PuTTY > PuTTY」)
在「分類別」窗格中,選擇「工作階段」並填寫以下欄位:
- 在「主機名(或IP位址)」框中,輸入
ec2-user@public_ip
(將public_ip替換為你的執行個體的公共IP位址) - 確保「連線類別」設定為SSH
- 連線埠應為22(SSH的預設連線埠)
- 在「主機名(或IP位址)」框中,輸入
在「分類別」窗格中,展開「連線 > SSH > 認證」,然後點選「瀏覽」按鈕找到並選擇你之前生成的.ppk檔案
點選「開啟」按鈕連線到你的執行個體
當PuTTY安全警告出現時,點選「是」將伺服器的主機金鑰加入到PuTTY的登入檔中
當提示登入時,輸入「ec2-user」(對於Amazon Linux AMI)
連線到EC2執行個體時,使用者名稱取決於你選擇的AMI。對於Amazon Linux AMI,預設使用者名稱是「ec2-user」;對於Ubuntu AMI,是「ubuntu」;對於CentOS AMI,是「centos」或「ec2-user」;對於RHEL AMI,是「ec2-user」或「root」。
SSH(Secure Shell)是一種加密的網路協定,用於在不安全的網路上安全地操作網路服務。它使用非對稱加密技術(即我們之前建立的金鑰對)來驗證遠端電腦並允許遠端電腦驗證使用者。
PuTTY安全警告是一種防範「中間人攻擊」的機制。
SSH 連線到 AWS EC2 執行個體的完整
PuTTY 連線設定與安全性
在 Windows 系統中使用 PuTTY 連線到 EC2 執行個體需要正確設定 SSH 連線引數。首先,在連線類別選項中選擇 SSH,並確保連線埠設定為 22(SSH 標準連線埠)。接著需要設定 SSH 金鑰認證:
- 展開 Connection 分類別,再展開 SSH,然後選擇 Auth
- 點選 Browse 按鈕,選擇您先前生成的 .ppk 格式金鑰檔案
- 點選 Open 啟動 PuTTY 連線
初次連線時,PuTTY 會顯示安全警告對話方塊,詢問您是否信任要連線的主機。這是正常的安全機制,確認後點選 Yes,就能成功連線到您的 EC2 執行個體。
在處理 SSH 連線時,玄貓建議將常用的連線設定儲存為 PuTTY 工作階段,這樣下次連線時就不必重複輸入這些引數,大幅提升工作效率。
Mac 與 Linux 系統的 SSH 連線方法
Mac 與 Linux 使用者在連線 EC2 時更為簡便,因為這些系統通常已內建 SSH 客戶端。可以在終端機中輸入 ssh
命令檢查是否已安裝。如果系統沒有內建 SSH 客戶端,可以使用 OpenSSH 專案提供的免費工具套件,詳情請參考 OpenSSH 官網。
使用以下命令連線到 EC2 執行個體:
$ ssh -i /path/key_pair.pem ec2-user@public_ip
在使用 SSH 連線時,需要注意不同 Linux 發行版的預設使用者名稱:
- Amazon Linux: 預設使用者為
ec2-user
- RHEL5: 使用者通常為
root
,但有時也是ec2-user
- Ubuntu: 使用者為
ubuntu
- SUSE Linux: 使用者為
root
如果使用其他 AMI,請向 AMI 提供者確認正確的使用者名稱。
終止 EC2 執行個體的正確方式
在完成入門教學後,為了避免不必要的費用,應該正確終止不再需要的 EC2 執行個體。終止執行個體實際上是刪除該執行個體,終止後將無法再連線到該執行個體。這與停止執行個體不同,停止執行個體只是關閉,您不會被收取小時使用費或資料傳輸費,而與可以隨時重新啟動。
終止執行個體的步驟:
- 在 EC2 管理主控台的執行個體頁面找到您的執行個體(如果找不到,請確認您選擇了正確的區域)
- 右鍵點選該執行個體,選擇「執行個體狀態」,然後點選「終止」
- 在確認提示中點選「是,終止」
玄貓提醒:終止執行個體是不可逆的操作,確保您已備份所有重要資料,再執行終止操作。
Ansible 自動化工具入門
Ansible 的核心理念與架構優勢
Ansible 是一個極其簡單但功能強大的 IT 自動化引擎,它能自動化設定管理、應用佈署和許多其他 IT 需求。與其他自動化工具不同,Ansible 透過檢視所有系統如何相互關聯的綜合架構來建模 IT 基礎設施,而不是一次只管理一個系統。
Ansible 的核心優勢在於:
- 無需在被管理節點安裝代理程式
- 不需要額外的自定義安全基礎設施
- 使用簡單易懂的語言(YAML 格式的 Ansible playbook)
- 透過 SSH 協定安全地管理遠端節點
Ansible 的工作原理是連線到目標節點並推播小型程式(稱為「Ansible 模組」),這些模組描述了系統期望狀態的資源模型。Ansible 透過 SSH 執行這些模組,完成後會將它們移除。模組庫存在於任何機器上,不需要伺服器、守護程式或資料函式庫 YAML(YAML Ain’t Markup Language)是一種對人友好的資料序列化標準,適用於所有程式語言。如果想了解更多關於 YAML 的訊息,可以存取 YAML 官網。
相較於 Chef 和 Puppet,Ansible 採用無代理架構。您只需在用於管理基礎設施的機器上安裝 Ansible,被管理的節點不需要安裝和執行背景守護程式來連線控制機器並提取設定,從而減少了網路開銷。
安裝 Ansible 的完整步驟
Ansible 是用 Python 編寫的,我們將使用 pip(Python 套件管理工具)來安裝最新版本的 Ansible。Ansible 發布的新版本會立即推播到 pip 儲存函式庫 在 CentOS/RHEL 系統上安裝 Ansible:
- 首先安裝 EPEL 儲存函式庫PEL(Extra Packages for Enterprise Linux)是為 Red Hat Enterprise Linux 或 CentOS 提供的套件儲存函式庫 Fedora 專案社群維護,提供 Fedora 中的附加套件。
$ sudo yum -y update
$ sudo yum -y install wget
$ wget http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
$ sudo rpm -Uvh epel-release-6*.rpm
- 安裝「開發工具」群組。「開發工具」是一個 yum 群組,它是預定義的軟體包,可以一次性安裝,無需單獨安裝每個應用程式。開發工具允許從原始碼建構和編譯軟體,還包括用於構建 RPM 的工具以及原始碼管理工具如 Git、SVN 和 CVS。
$ sudo yum groupinstall -y 'development tools'
- 安裝 python-pip 和 python-devel
$ sudo yum -y install python-pip python-devel
- 升級 setuptools
$ sudo pip install setuptools --upgrade
- 透過 pip 安裝 Ansible
$ sudo pip install ansible
安裝完成後,可以執行以下命令檢視 Ansible 的版本號:
$ ansible --version
ansible 2.1.1.0
要升級 Ansible 到 pip 儲存函式庫最新版本:
$ sudo pip install ansible --upgrade
設定 SSH 金鑰認證
Ansible 透過 SSH 與遠端機器通訊。預設情況下,Ansible 1.3 及更高版本會盡可能使用原生 OpenSSH 進行遠端通訊。建議使用 SSH 金鑰進行 SSH 認證,這樣 Ansible 就不必要求密碼來與遠端主機通訊。
啟用 SSH 金鑰認證的步驟:
- 使用 ssh-keygen 建立公鑰和私鑰
$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/yan/.ssh/id_rsa):[按 ENTER 鍵]
Enter passphrase (empty for no passphrase):[按 ENTER 鍵]
Enter same passphrase again:[按 ENTER 鍵]
Your identification has been saved in /home/yan/.ssh/id_rsa.
Your public key has been saved in /home/yan/.ssh/id_rsa.pub.
The key fingerprint is:
- 使用 ssh-copy-id 將公鑰複製到遠端主機(本例中使用 localhost 作為「遠端主機」)
$ ssh-copy-id -i ~/.ssh/id_rsa.pub localhost
yan@localhost's password:[輸入密碼]
Now try logging into the machine, with "ssh 'localhost'", and check in:
.ssh/authorized_keys
設定好 SSH 金鑰認證後,Ansible 就能無需密碼地與遠端主機通訊,大簡化了自動化流程。
SSH 金鑰認證的工作原理
SSH 金鑰認證使用非對稱加密機制,包含一對金鑰:私鑰(儲存在本地)和公鑰(分發到遠端伺服器)。當你嘗試連線到遠端伺服器時,伺服器會傳送一個隨機挑戰,只有擁有對應私鑰的使用者才能正確回應這個挑戰,從而完成認證。
ssh-keygen
命令生成這對金鑰,而 ssh-copy-id
則將公鑰增加到遠端伺服器的授權金鑰檔案中。這種方法比密碼認證更安全、更方便,特別適合自動化工具如 Ansible,因為它允許無人值守的自動操作。
Ansible 與 AWS 的協同優勢
結合 Ansible 和 AWS 可以實作強大的雲端基礎設施自動化。Ansible 提供了豐富的 AWS 模組,可以自動化建立、設定和管理 EC2 執行個體、S3 儲存桶、RDS 資料函式庫AWS 資源。
在實際工作中,玄貓發現這種組合特別適合以下場景:
- 大規模基礎設施佈署:快速設定數十甚至數百台具有相同設定的伺服器
- 災難還原:透過自動化指令碼快速重建基礎設施
- 持續整合/持續佈署:將程式碼變更自動佈署到測試和生產環境
- 基礎設施即程式碼:將基礎設施設定儲存為程式碼,實作版本控制和可重複佈署
透過 Ansible 管理 AWS 資源不僅提高了效率,還降低了人為錯誤的可能性,確保了環境的一致性和可靠性。
自動化實踐的關鍵考量
在實施 Ansible 自動化方案時,玄貓建議注意以下幾點:
- 安全性考量:確保 SSH 金鑰妥善保管,考慮使用金鑰輪換策略
- 版本控制:將所有 Ansible playbook 存放於版本控制系統中(如 Git)
- 模組化設計:將常用任務封裝為可重用的角色(roles)
- 測試策略:在應用到生產環境前,在測試環境驗證自動化指令碼
- 檔案化:為所有重要的 playbook 和自動化流程提供清晰的檔案
Ansible 的學習曲線相對平緩,但掌握其所有功能需要時間和實踐。從簡單的任務開始,逐步構建更複雜的自動化流程,將幫助您更有效地利用這個強大工具。
雲端自動化是現代 IT 基礎設施管理的核心能力。透過結合 AWS 的強大雲端服務和 Ansible 的簡單自動化能力,IT 團隊可以實作前所未有的效率和可靠性。隨著雲端技術的不斷發展,自動化工具的重要性將只增不減,成為每個 IT 專業人員必備的技能。
Ansible入門:開發高效自動化基礎設施
在現代DevOps環境中,基礎設施自動化不再是選項而是必需品。我在多年的雲端架構設計中發現,Ansible憑藉其無客戶端架構和簡潔的YAML語法,成為許多團隊的首選自動化工具。它不需要在受管理的節點上安裝代理程式,僅依賴SSH連線,大幅降低了匯入門檻與維護負擔。
本文將帶領你從Ansible的基礎概念開始,逐步建立起自動化管理基礎設施的能力。無論你是DevOps工程師、系統管理員,還是希望提高工作效率的開發人員,這篇都能幫助你快速上手這個強大的自動化工具。
Ansible環境準備與SSH無密碼登入設定
Ansible的基礎建立在SSH連線之上,因此設定SSH無密碼登入是使用Ansible的第一步。以下是如何設定SSH金鑰並實作無密碼登入:
- 如果你還沒有SSH金鑰,首先需要生成一組:
ssh-keygen -t rsa -b 4096
這個命令會在你的 ~/.ssh/
目錄下生成 id_rsa
(私鑰)和 id_rsa.pub
(公鑰)檔案。
- 接下來,將你的公鑰複製到目標主機:
ssh-copy-id username@remote_host
這組命令的核心功能是建立SSH信任關係。ssh-keygen
會產生非對稱加密金鑰對,其中私鑰留在本機,公鑰則被分享給遠端伺服器。-t rsa
指定使用RSA演算法,而-b 4096
設定金鑰長度為4096位元,提供較高安全性。
ssh-copy-id
命令則會自動將你的公鑰附加到遠端主機的~/.ssh/authorized_keys
檔案中。當這個設定完成後,遠端主機就會接受你的私鑰所簽署的連線請求,無需再輸入密碼。
- 測試無密碼登入是否成功:
ssh localhost
exit
如果你能夠無需輸入密碼就登入成功,表示SSH金鑰設定正確。這個基礎設定將讓Ansible能夠順利地連線並管理你的所有目標主機。
Ansible函式庫案:定義你的基礎設施拓撲
在Ansible中,函式庫案(Inventory)是定義你要管理哪些主機的核心設定。預設情況下,Ansible使用/etc/ansible/hosts
作為函式庫案,但你也可以透過-i
選項指定自訂的函式庫案路徑。
函式庫案的基本結構
函式庫案採用INI格式,結構簡單直觀:
one.example.com
[webservers]
web1.example.com
web2.example.com
two.example.com
[dbservers]
db1.example.com
db2.example.com
two.example.com
這個函式庫案展示了Ansible最基本的主機分組方式。方括號內的名稱(如[webservers]
)定義了主機組,而下方則列出該組包含的主機。注意觀察two.example.com
同時出現在webservers
和dbservers
兩個組中 - 這展示了一個重要特性:單一主機可以同時屬於多個組,讓你能夠根據不同維度(功能、地理位置、環境等)來組織你的基礎設施。
使用模式比對批次增加主機
當你需要增加大量類別似命名的主機時,可以使用模式比對功能:
[webservers]
web[01:50].example.com
[databases]
db-[a:f].example.com
這種寫法能夠大幅簡化大規模基礎設施的定義。第一個例子會展開為web01到web50共50台伺服器,而第二個例子則會比對db-a到db-f共6台資料函式庫器。
建立群組的群組
你還可以進一步組織你的基礎設施,建立群組的群組:
[sydney]
host1
host2
[singapore]
host3
host4
[asiapacific:children]
sydney
singapore
這種分層結構特別適合按地理位置或環境(如開發、測試、生產)來組織主機。使用:children
語法,我們定義了一個名為asiapacific
的上層群組,它包含了sydney
和singapore
兩個子群組的所有主機。
Ansible中的變數管理
Ansible提供了豐富的變數管理功能,讓你能夠靈活地設定不同主機的特性。
主機變數
你可以直接在函式庫案中為特定主機指定變數:
[webservers]
web1.example.com ansible_user=ec2-user
web2.example.com ansible_user=ubuntu
更好的做法是將主機變數存放在單獨的檔案中。假設你的函式庫案路徑為/home/yan/ansible4aws/hosts
,你可以在以下路徑建立YAML格式的主機變數檔案:
/home/yan/ansible4aws/host_vars/web1.example.com
檔案內容範例:
---
ansible_user: ec2-user
ansible_port: 5300
ansible_ssh_private_key_file: /home/yan/.ssh/keypair1.pem
這種變數管理方式遵循"基礎設施即程式碼"的最佳實踐。將變數與函式庫離存放有幾個關鍵優勢:
- 提高可讀性:主函式庫案保持簡潔
- 更好的版本控制:變更容易追蹤
- 安全性提升:敏感設定(如SSH金鑰路徑)可以更好地管理
- 更容易維護:當主機數量增加時,分散式的變數檔案更易於管理
常用的連線變數
Ansible提供了許多控制遠端連線行為的變數,以下是一些最常用的:
ansible_host
: 連線的主機名稱,如果與別名不同ansible_port
: SSH連線埠,預設為22ansible_user
: SSH使用者名ansible_ssh_private_key_file
: SSH私鑰檔案路徑ansible_ssh_common_args
: 附加到SSH命令的引數,適合設定ProxyCommand
許可權提升相關變數
在許多自動化任務中,你可能需要提升許可權執行命令:
ansible_become
: 啟用許可權提升(相當於sudo或su)ansible_become_method
: 設定許可權提升方法ansible_become_user
: 設定提升許可權後使用的使用者ansible_become_pass
: 許可權提升所需的密碼
遠端主機環境變數
有時你需要指定遠端主機的特定環境引數:
ansible_shell_type
: 目標系統的shell類別ansible_python_interpreter
: 目標主機上Python的路徑,特別適用於有多個Python版本的系統ansible_*_interpreter
: 類別似於python直譯器設定,可用於ruby、perl等
群組變數
你也可以將變數應用於整個群組:
[sydney]
node1
node2
[sydney:vars]
ntp_server=ntp.sydney.example.com
proxy_server=proxy.sydney.example.com
同樣地,更好的做法是使用單獨的檔案存放群組變數:
/home/yan/ansible4aws/group_vars/sydney
檔案內容範例:
---
ntp_server: ntp.sydney.example.com
proxy_server: proxy.sydney.example.com
群組變數也可以應用到群組的群組:
[asiapacific:vars]
db_server=db1.asiapacific.example.com
開始使用Ansible命令
現在我們已經瞭解了基本概念,讓我們開始執行一些基本的Ansible命令。首先,建立一個簡單的函式庫案:
mkdir -p /home/yan/ansible4aws && cd /home/yan/ansible4aws
vi hosts
檔案內容:
[local]
localhost
# 你可以增加更多主機
# [mygroup]
# 192.168.1.10
# 192.168.1.11
執行你的第一個Ansible命令
ping所有節點,檢查連線狀態:
ansible -i hosts all -m ping
這條命令是Ansible最基本的健康檢查。-i hosts
指定了函式庫案的路徑,all
表示針對所有主機執行,-m ping
則指定使用ping模組。Ansible的ping不同於ICMP ping,它實際上是透過SSH連線到目標主機,驗證Python環境,然後回傳成功訊息。這能確認整個Ansible執行鏈路是否正常工作。
執行一個簡單的命令:
ansible -i hosts all -a "/bin/echo hello"
這條命令使用-a
引數直接執行shell命令,而不是使用特定模組。在這個例子中,我們讓所有主機執行/bin/echo hello
命令。這種方式適合執行簡單的一次性命令,但對於複雜任務,應該使用專用模組或Playbook。
這些例子展示瞭如何使用ansible
命令執行臨時任務(ad-hoc tasks)。臨時任務適用於你不一定需要寫完整Playbook的快速操作,例如重啟某些服務或檢查系統狀態。
Ansible Playbook:自動化的核心
雖然ad-hoc命令很有用,但Ansible的真正威力來自於Playbook。Playbook是Ansible的設定、佈署和協調語言,使用YAML格式編寫,讓你能夠描述自動化任務,並接近自然語言的方式表達。
每個Playbook由一個或多個"play"組成,每個play將一組主機對映到定義好的角色,這些角色由Ansible任務(tasks)表示。每個任務都是對Ansible模組的呼叫。
Playbook的基本結構
一個Ansible Playbook的基本結構如下:
---
- name: 安裝並啟動Apache伺服器
hosts: webservers
become: yes
tasks:
- name: 安裝Apache
yum:
name: httpd
state: present
- name: 啟動Apache服務
service:
name: httpd
state: started
enabled: yes
這個Playbook展示了Ansible自動化的基本結構:
name
:描述性名稱,幫助識別play的目的hosts
:指定執行任務的目標主機組become: yes
:啟用許可權提升(類別似sudo)tasks
:定義要執行的具體任務列表
每個任務都有自己的名稱和使用的模組(如yum、service)。模組接受不同的引數,例如要安裝的套件名稱或服務狀態。這種結構讓Playbook極易閱讀和維護,即使對不熟悉的人也是如此。
從命令列執行模組與Playbook執行模組的對比
你可以從命令列直接執行模組:
ansible webservers -m service -a "name=httpd state=started"
ansible webservers -m ping
ansible webservers -m command -a "/sbin/reboot -t now"
或在Playbook中執行同樣的模組:
- name: 重啟伺服器
command: /sbin/reboot -t now
雖然兩種方式都能完成任務,但Playbook提供了更多優勢:
- 可重複執行的自動化流程
- 版本控制和檔案化
- 更複雜的控制流程(條件、迴圈等)
- 更好的錯誤處理和報告
Ansible模組函式庫
Ansible提供了數百個內建模組,以下是一些常用類別:
- 套件管理:yum、apt - 用於安裝、更新或移除軟體套件
- 遠端執行:command、shell - 在遠端主機上執行命令
- **服務
Ansible 模組的核心特性與工作原理
在深入研究 Ansible Playbook 之前,我們需要先了解 Ansible 模組的一個關鍵特性:冪等性(Idempotent)。這個特性讓 Ansible 成為維運自動化的理想工具。
冪等性意味著無論執行多少次相同的操作,系統都只會朝著目標狀態變化,而不會重複執行已經完成的變更。舉例來說,如果你編寫了一個安裝 Apache 伺服器的任務,第一次執行時 Ansible 會安裝它,但再次執行時,如果 Apache 已經存在與狀態符合要求,Ansible 就不會做任何變更。
這種特性使得 Ansible 指令碼可以安全地重複執行,不必擔心會造成系統狀態紊亂或重複操作帶來的問題。在大規模佈署和持續整合環境中,這個特性尤為重要。
YAML 語法:Ansible Playbook 的根本
Ansible Playbook 使用 YAML 格式撰寫,這是一種人類易讀的資料序列化標準。瞭解 YAML 的基本語法對於編寫高效的 Playbook 至關重要。
每個 YAML 檔案通常以 ---
開頭,這表示檔案的開始。Playbook 中最常見的結構是列表,每個列表項通常是一個字典(key-value 對的集合)。
以下是一個基本的 YAML 語法範例:
---
- hosts: webservers
tasks:
- name: ensure apache is installed
yum: name=httpd state=present
- hosts: databases
tasks:
- name: ensure mysql server is installed
yum: name=mysql-server state=present
在這個例子中,我們定義了兩個 play,分別針對 webservers 和 databases 主機群組。每個 play 包含一個任務,用於確保特定的服務已安裝。
YAML 使用縮排來表示結構關係,這使得檔案格式清晰易讀,但也意味著必須嚴格遵守縮排規則。在實際工作中,我發現很多 Ansible 初學者的錯誤都源於縮排不正確。
Playbook 結構深度解析
Playbook 是 Ansible 的核心元素,一個完整的 Playbook 通常由多個 play 組成,每個 play 定義了在特定主機上執行的一組任務。讓我們深入理解 Playbook 的三個主要部分:
hosts 區塊:定義目標與連線方式
hosts 區塊指定了 play 將在哪些主機上執行,以及如何連線這些主機:
- hosts: webservers
remote_user: root
Ansible 提供了多種方式來指定目標主機:
- 使用
all
或*
來選擇所有主機 - 使用主機名、IP 地址或萬用字元(如
192.168.1.*
) - 使用群組名稱(如
webservers
) - 使用群組合(如
webservers:dbservers
表示兩個群組的主機) - 使用排除模式(如
webservers:!sydney
表示 webservers 群組中不在 sydney 群組的主機) - 使用交集(如
webservers:&staging
表示同時在兩個群組中的主機) - 使用正規表示式(如
~(web|db).*\.example\.com
)
hosts 區塊中還可以設定多種引數:
become
:啟用許可權提升(值為 true/yes)become_user
:指定許可權提升後使用的使用者become_method
:指定許可權提升的方法(如 sudo、su 等)connection
:指定連線方式(ssh、paramiko 或 local)gather_facts
:控制是否收集目標主機的系統訊息
variables 區塊:設定與靈活性
variables 區塊允許你定義適用於整個 play 的變數,這些變數可以在後續任務中使用:
- hosts: webservers
vars:
http_port: 80
region: ap-southeast-2
tasks:
- name: create key pair
local_action:
module: ec2_key
region: "{{ region }}"
變數使用 {{ variable_name }}
語法參照。當我在複雜專案中工作時,我發現將變數集中定義在 play 的頂部,可以大提高設定的可讀性和可維護性。
除了直接定義變數,你還可以:
- 從外部 YAML 檔案載入變數:
- hosts: webservers
vars_files:
- /vars/external_vars.yml
- 讓 Ansible 提示輸入變數:
vars_prompt:
- name: 'vpc_subnet_id'
prompt: 'Enter the VPC subnet ID: '
- 透過命令列傳遞變數:
$ ansible-playbook -i hosts site.yml --extra-vars "hosts=dbservers user=ec2-user"
tasks 區塊:執行實際操作
tasks 區塊包含一系列任務,Ansible 會按順序執行這些任務:
tasks:
- name: make sure apache is running
service: name=httpd state=running
每個任務應該有一個描述性的名稱,這有助於在執行過程中瞭解當前進度。任務的核心是模組呼叫,大多數模組使用 key=value
格式指定引數。
command 和 shell 模組是例外,它們直接受命令字元串:
tasks:
- name: disable selinux
command: /sbin/setenforce 0
如果任務行太長,可以將其分成多行,後續行需要適當縮排:
tasks:
- name: Copy somefile to remote host
copy: src=/home/somefile dest=/etc/somefile
owner=root group=root mode=0644
處理器(Handlers):條件觸發的任務
Handlers 是一種特殊的任務,只有在被 notify 指令觸發時才會執行:
tasks:
- name: Configure ntp file
template: src=ntp.conf.j2 dest=/etc/ntp.conf
notify: restart ntp
handlers:
- name: restart ntp
service: name=ntpd state=restarted
在上面的例子中,只有當 ntp.conf 檔案被修改時,ntpd 服務才會重啟。這種機制非常適合需要在設定變更後重啟服務的場景。
值得注意的是,即使多個任務都觸發了同一個 handler,該 handler 也只會在所有任務完成後執行一次。這避免了不必要的重複操作。
實戰:建立並執行第一個 Playbook
理論學習後,讓我們透過實際操作來鞏固知識。我將帶你建立一個簡單的 Playbook,用於安裝和管理 Apache 伺服器。
步驟 1:建立函式庫案
首先,建立一個函式庫案 hosts
,定義我們的目標主機:
[local]
localhost
這個簡單的函式庫案只包含一個名為 local
的群組,其中包含 localhost
。
步驟 2:編寫第一個 Playbook
接下來,建立一個名為 site.yml
的 Playbook 檔案:
---
- hosts: localhost
tasks:
- name: ensure apache is at the latest version
yum: name=httpd state=latest
- name: ensure apache is running
service: name=httpd state=started
這個 Playbook 包含兩個任務:
- 安裝最新版本的 Apache(httpd)
- 確保 Apache 服務正在執行
步驟 3:執行 Playbook
使用以下命令執行 Playbook:
$ ansible-playbook -i hosts site.yml
Ansible 將按順序執行定義的任務,並顯示每個任務的執行結果。如果一切順利,Apache 伺服器將被安裝並啟動。
你可以使用以下命令驗證 Apache 是否正在執行:
# ps ax | grep httpd
應該會看到多個 httpd 程式,表明 Apache 已成功啟動。
步驟 4:修改 Playbook 解除安裝 Apache
Ansible 的強大之處在於可以輕鬆修改系統狀態。讓我們修改 Playbook 來解除安裝 Apache:
---
- hosts: localhost
tasks:
- name: ensure apache is absent
yum: name=httpd state=absent
再次執行 Playbook:
$ ansible-playbook -i hosts site.yml
這次 Ansible 將解除安裝 Apache,展示瞭如何使用相同的工具來安裝和移除軟體。
角色與包含陳述式:組織複雜 Playbook
隨著自動化需求的增長,Playbook 可能變得非常龐大和複雜。Ansible 提供了角色(Roles)和包含陳述式(Include Statements)來組織和重用程式碼。
包含陳述式
包含陳述式允許你將設定分割成多個小檔案,然後在主 Playbook 中參照它們:
- hosts: webservers
tasks:
- include: tasks/webserver.yml
這種方式可以將相關任務組織在一起,使主 Playbook 保持簡潔。
角色
角色是 Ansible 中組織 Playbook 的更強大方式。一個角色可以包含變數、處理器、任務和其他資源,形成一個可重用的單元。
基本的角色結構如下:
roles/
common/
tasks/
main.yml
handlers/
main.yml
files/
templates/
vars/
main.yml
defaults/
main.yml
meta/
main.yml
在 Playbook 中使用角色:
---
- hosts: webservers
roles:
- common
- webservers
使用角色可以大簡化複雜 Playbook 的管理,並促程式碼重用。在我管理的大型基礎設施專案中,角色已經成為標準做法,它們讓團隊成員可以專注於特定領域的自動化,同時保持整體一致性。
Ansible 模組選擇的最佳實踐
在實際使用 Ansible 的過程中,選擇合適的模組是提高效率和可靠性的關鍵。根據我的經驗,以下是一些選擇模組的最佳實踐:
優先使用專用模組:例如,使用
yum
/apt
/dnf
模組安裝軟體,而不是使用command
模組執行安裝命令。專用模組通常實作了冪等性,更容易處理各種邊緣情況。瞭解模組的回傳值:不同模組回傳的資料結構不同,瞭解這些回傳值有助於編寫更複雜的條件邏輯。
考慮模組的冪等性:某些模組(如
command
)預設不是冪等的,需要額外設定(如creates
引數)來實作冪等性。查閱最新檔案:Ansible 模組不斷發展,新版本可能引入新引數或更改行為,定期查閱官方檔案是個好習慣。
Ansible 的魅力在於它能將複雜的系統管理任務簡化為清晰、可重複的程式碼。透過掌握 Ansible 的基本概念和實踐技巧,你可以大幅提高基礎設施管理的效率和可靠性。
從我多年使用 Ansible 的經驗來看,最初投入時間學習這些概念絕對值得,它將為你節省大量重複性工作的時間,並降低人為錯誤的風險。開始時可能感覺複雜,但一旦掌握了基本工作流程,你會發現它是一個極其強大而靈活的工具。
無論是管理幾台伺服器還是成百上千的節點,Ansible 都能以同樣簡單的方式處理,這也是為什麼它已成為現代 DevOps 工具鏈中不可或缺的一部分。
Ansible任務檔案與角色:組織自動化佈署的最佳實踐
在自動化佈署的世界裡,程式碼組織與結構設計是成功的關鍵。多年來,我在處理複雜的基礎設施佈署時發現,良好的結構設計不僅能提升維護性,更能大幅增加團隊協作效率。Ansible提供了兩種核心機制來組織自動化任務:任務檔案(Task Files)與角色(Roles)。這兩種機制各有優勢,今天就讓我們探討。
任務檔案:簡單直接的任務組織方式
任務檔案(Task Files)是Ansible中最基本的任務組織單元,它允許我們將相關任務集中在單一檔案中,便於重複使用。一個典型的任務檔案結構相當簡單:
# 儲存為 tasks/task1.yml
- name: task one
command: /bin/commandone
- name: task two
command: /bin/commandtwo
在主要的playbook中,我們可以透過include指令來參照這些任務檔案:
tasks:
- include: tasks/task1.yml
這種方式在小型專案或單一功能模組中非常有效,但隨著專案規模擴大,我們需要更結構化的組織方式。
角色:Ansible的高階組織單元
角色(Roles)是Ansible中更強大的組織機制,它遵循特定的目錄結構,自動載入任務、處理程式、變數等內容。在大型專案中,角色能讓程式碼更易於維護和分享。
角色的標準目錄結構
roles/
common/
files/
templates/
tasks/
handlers/
vars/
meta/
webservers/
files/
templates/
tasks/
handlers/
vars/
meta/
這種結構化的組織方式讓每個角色專注於特定功能,例如「common」角色處理所有伺服器共用的設定,而「webservers」角色則專注於網頁伺服器的設定。
在Playbook中使用角色
在playbook中使用角色非常直觀:
---
- hosts: webservers
roles:
- common
- webservers
這個簡單的宣告會自動觸發以下行為:
- 如果存在
roles/x/tasks/main.yml
,其中的任務會被增加到playbook中 - 如果存在
roles/x/handlers/main.yml
,其中的處理程式會被增加到playbook中 - 如果存在
roles/x/vars/main.yml
,其中的變數會被增加到playbook中 - 如果存在
roles/x/meta/main.yml
,其中列出的角色依賴會被增加到角色列表中 - 任何複製任務都可以直接參照
roles/x/files/
中的檔案,無需指定相對或絕對路徑 - 任何指令碼任務都可以直接參照
roles/x/files/
中的指令碼,無需指定路徑 - 任何範本任務都可以直接參照
roles/x/templates/
中的檔案,無需指定路徑 - 任何include任務都可以直接參照
roles/x/tasks/
中的檔案,無需指定路徑
這種結構化的組織方式大幅簡化了複雜自動化任務的管理,讓程式碼更加模組化,也更容易在團隊間分享和重用。
AWS VPC基礎:虛擬網路的核心概念
在深入討論如何使用Ansible自動化VPC佈署前,讓我們先了解AWS VPC的核心概念。Amazon Virtual Private Cloud (VPC)允許我們在AWS雲端中定義自己的虛擬網路,這個虛擬網路與傳統資料中心的網路非常相似,但同時享有AWS可擴充套件基礎設施的優勢。
預設VPC的特性
當你在沒有指定自定義VPC的情況下啟動EC2執行個體時,AWS會將執行個體啟動到預設VPC中。預設VPC具有以下特點:
- 每個可用區(Availability Zone)中都有一個預設子網
- 連線到預設VPC的網際網路閘道(Internet Gateway)
- 主路由表包含將所有流量導向網際網路閘道的規則
- 與預設VPC關聯的預設安全群組
- 與VPC關聯的預設網路存取控制清單(ACL)
- 與預設VPC關聯的預設DHCP選項集
預設VPC的CIDR區塊總是172.31.0.0/16,提供多達65,536個私有IP位址。預設子網具有/20子網路遮罩,每個子網提供多達4,096個地址。某些地址保留給Amazon使用。
自定義VPC入門
自定義VPC允許我們根據需求設計網路架構,這是構建安全、高效雲端基礎設施的關鍵。建立VPC時,我們需要指定VPC的IP位址範圍,採用CIDR(無類別域間路由)表示法,例如10.0.0.0/16。
VPC必須使用私有地址空間,例如:
- 10.0.0.0/8 (10.0.0.0 - 10.255.255.255)
- 172.16.0.0/12 (172.16.0.0 - 172.31.255.255)
- 192.168.0.0/16 (192.168.0.0 - 192.168.255.255)
VPC可以跨越多個可用區,建立VPC後,我們可以在每個可用區中增加一個或多個子網。建立子網時,需要指定子網的CIDR區塊,它是VPC CIDR區塊的子集。每個子網必須完全位於單個可用區內,不能跨區域。
可用區是設計用於彼此隔離的獨立位置,在不同可用區啟動執行個體可以保護應用程式免受單一位置故障的影響。這種設計是AWS提供高用性的核心策略之一。
基礎設施即程式碼:使用Ansible管理AWS VPC
使用Ansible管理AWS VPC的最大優勢在於將基礎設施轉化為程式碼。這意味著我們透過編寫程式碼來定義基礎設施,而不是手動點選控制檯。將版本控制系統(如Git)應用於基礎設施程式碼,可實作基礎設施的版本控制,輕鬆重建整個基礎設施或回退到先前版本。
這種方法使開發、測試和生產環境保持一致性,大幅降低了"在我機器上可以執行"的問題發生率。在我帶領的多個團隊中,採用這種方法後,環境差異導致的問題減少了近80%。
多層架構VPC設計
在本文中,我們將設計一個適用於多層Web應用程式的VPC架構,包括:
- 公共子網中的Web伺服器,可直接收來自網際網路的流量
- 私有子網中的資料函式庫器,不能直接從網際網路存取
公共子網中的執行個體可以直接向網際網路傳送和接收流量。而私有子網中的執行個體無法直接存取網際網路,需要透過佈署在公共子網中的NAT(網路地址轉換)執行個體來存取網際網路。
這種架構提供了更高的安全性,因為資料函式庫要資源被隔離在私有子網中,不直接暴露於網際網路。
網路地址轉換(NAT)例項
NAT執行個體允許私有子網中的執行個體發起對網際網路的連線,同時阻止網際網路上的主機發起與這些執行個體的連線。這是實作出站網際網路連線同時維護安全性的重要機制。
AWS提供了代管NAT閘道服務,具有更好的可用性和更高的頻寬。雖然在生產環境中強烈推薦使用AWS代管NAT服務,但在學習階段,我們可以先使用自行設定的NAT執行個體來瞭解其工作原理。
Ansible自動化VPC佈署實戰
現在,讓我們將理論付諸實踐,使用Ansible自動化佈署一個多層架構的VPC。這個例項將展示如何使用基礎設施即程式碼方法管理雲端資源。
定義VPC與子網
首先,我們建立一個Ansible playbook來定義VPC及其子網:
---
- name: Provision AWS VPC
hosts: localhost
connection: local
gather_facts: false
vars:
vpc_name: "Web-App-VPC"
vpc_cidr: "10.0.0.0/16"
region: "us-west-2"
public_subnet_1_cidr: "10.0.1.0/24"
public_subnet_2_cidr: "10.0.2.0/24"
private_subnet_1_cidr: "10.0.3.0/24"
private_subnet_2_cidr: "10.0.4.0/24"
tasks:
- name: Create VPC
ec2_vpc_net:
name: "{{ vpc_name }}"
cidr_block: "{{ vpc_cidr }}"
region: "{{ region }}"
tags:
Name: "{{ vpc_name }}"
Environment: "Production"
register: vpc
- name: Create public subnet 1
ec2_vpc_subnet:
vpc_id: "{{ vpc.vpc.id }}"
cidr: "{{ public_subnet_1_cidr }}"
az: "{{ region }}a"
region: "{{ region }}"
tags:
Name: "Public Subnet 1"
Environment: "Production"
register: public_subnet_1
- name: Create public subnet 2
ec2_vpc_subnet:
vpc_id: "{{ vpc.vpc.id }}"
cidr: "{{ public_subnet_2_cidr }}"
az: "{{ region }}b"
region: "{{ region }}"
tags:
Name: "Public Subnet 2"
Environment: "Production"
register: public_subnet_2
- name: Create private subnet 1
ec2_vpc_subnet:
vpc_id: "{{ vpc.vpc.id }}"
cidr: "{{ private_subnet_1_cidr }}"
az: "{{ region }}a"
region: "{{ region }}"
tags:
Name: "Private Subnet 1"
Environment: "Production"
register: private_subnet_1
- name: Create private subnet 2
ec2_vpc_subnet:
vpc_id: "{{ vpc.vpc.id }}"
cidr: "{{ private_subnet_2_cidr }}"
az: "{{ region }}b"
region: "{{ region }}"
tags:
Name: "Private Subnet 2"
Environment: "Production"
register: private_subnet_2
這個playbook執行以下操作:
- 定義了VPC及子網的CIDR區塊和其他屬性
- 建立具有指定CIDR區塊的VPC,並為其增加標籤
- 在兩個不同的可用區(a和b)中建立兩個公共子網
- 在相同的兩個可用區中建立兩個私有子網
- 使用
register
指令將每個任務的結果儲存到變數中,以便後續任務使用
這種方法使我們的VPC設定完全程式碼化,可以輕鬆重新建立或修改。
設定網際網路連線
接下來,我們需要為VPC設定網際網路連線,使公共子網能夠存取網際網路:
- name: Create Internet Gateway
ec2_vpc_igw:
vpc_id: "{{ vpc.vpc.id }}"
region: "{{ region }}"
tags:
Name: "{{ vpc_name }}-IGW"
Environment: "Production"
register: igw
- name: Create public route table
ec2_vpc_route_table:
vpc_id: "{{ vpc.vpc.id }}"
region: "{{ region }}"
tags:
Name: "Public Route Table"
Environment: "Production"
subnets:
- "{{ public_subnet_1.subnet.id }}"
- "{{ public_subnet_2.subnet.id }}"
routes:
- dest: "0.0.0.0/0"
gateway_id: "{{ igw.gateway_id }}"
register: public_route_table
這段設定執行以下操作:
- 建立網際網路閘道(Internet Gateway)並將其附加到VPC
- 建立公共路由表,關聯到兩個公共子網
- 增加路
AWS VPC 網路架構設計與自動化設定
在雲端架構設計中,虛擬私有雲(VPC)是構建安全、可擴充套件系統的根本。透過精心設計的 VPC,我們能夠建立隔離的網路環境,並依據應用程式需求進行分層設計。本文將探討 VPC 的核心元件、設計考量,以及如何使用 Ansible 自動化佈署整個網路基礎設施。
VPC 架構核心元件解析
在典型的多層 VPC 設計中,我們通常會看到下列核心元件的組合:
![VPC 架構示意圖]
核心網路元件說明
- 虛擬私有雲 (VPC) - 使用 CIDR 10.0.0.0/16 設定,提供 65,536 個 IP 位址的私有網路空間
- 公有子網路 - 使用 CIDR 10.0.0.0/24 設定,提供 256 個可直接連線網際網路的 IP 位址
- 私有子網路 - 使用 CIDR 10.0.1.0/24 設定,提供 256 個內部使用的 IP 位址
- 網際網路閘道 (Internet Gateway) - 連線 VPC 到網際網路和其他 AWS 服務,如 S3
- NAT 例項 - 允許私有子網路中的例項向外傳送請求,但阻止外部連線進入
在這種架構中,公有子網路中的例項同時擁有私有 IP(如 10.0.0.5)和公有彈性 IP(如 198.51.100.1),而私有子網路中的例項僅有私有 IP(如 10.0.1.5)。私有子網路中的後端伺服器透過 NAT 例項間接連線網際網路,確保安全性的同時仍能取得必要的更新。
VPC 規模設計考量
VPC 的規模設計是基礎架構規劃中的關鍵決策點。AWS 允許的 VPC CIDR 區塊範圍在 /28 到 /16 網路遮罩之間,這意味著 VPC 可包含從 16 到 65,536 個 IP 位址。
在實際規劃時,我發現許多團隊往往低估了 IP 位址需求。值得注意的是,一旦建立 VPC 後,其大小就無法更改。如果 VPC 規模不足以滿足需求,唯一的解決方案是終止 VPC 中的所有例項,刪除 VPC,然後建立一個新的、更大的 VPC。
因此,在規劃階段,我建議採用以下策略:
- 評估長期業務增長需求
- 考慮未來可能需要的子網路數量
- 為每個子網路預留足夠的 IP 空間
- 為特殊用途(如 虛擬私人網路、DirectConnect)預留子網路空間
建立 VPC 基礎架構的步驟
接下來,我將介紹如何手動建立 VPC 架構,以便更好地理解各元件之間的關係,為後續的自動化做準備。
建立 VPC
首先,我們需要建立基本的 VPC:
- 登入 AWS 管理控制檯,進入 VPC 服務
- 點選「建立 VPC」
- 輸入 VPC 名稱標籤和 CIDR 區塊(例如 10.0.0.0/16)
- 選擇「租用類別:預設」
這裡需要特別說明的是租用屬性(Tenancy)。VPC 的租用屬性決定了在該 VPC 中啟動的 EC2 例項的硬體分配方式:
- 預設租用:例項分享物理硬體
- 專用租用:例項在專用硬體上執行,實作物理層級的隔離
專用租用(Dedicated Instance)在硬體層級提供物理隔離,對於有嚴格合規要求的應用非常有用,但成本較高。一旦設定,VPC 的租用屬性就無法更改,因此需要謹慎選擇。
建立網際網路閘道並連線到 VPC
網際網路閘道是 VPC 連線外部網路的必要元件:
- 在 VPC 控制檯中,選擇「網際網路閘道」
- 點選「建立網際網路閘道」
- 輸入閘道名稱標籤
- 建立後,選擇該閘道並點選「連線到 VPC」
- 選擇之前建立的 VPC 並確認連線
網際網路閘道是有狀態的裝置,提供 NAT 轉換功能,允許公有子網路中的例項與網際網路通訊。每個 VPC 只能連線一個網際網路閘道。
建立子網路
子網路是 VPC 網路空間的細分,用於組織和隔離資源:
- 在 VPC 控制檯中,選擇「子網路」
- 點選「建立子網路」
- 為公有子網路設定名稱標籤和 CIDR 區塊(如 10.0.0.0/24)
- 選擇 VPC 和可用區
- 重複上述步驟,建立私有子網路(如 10.0.1.0/24)
子網路的大小應該根據預期的工作負載和未來增長規劃來確定。每個子網路都與特定的可用區關聯,這對於設計高用性架構非常重要。
路由表設定與管理
路由表是 VPC 中控制網路流量的核心元素。瞭解路由表的工作原理對於正確設定 VPC 網路至關重要:
- VPC 有一個隱式路由器
- 每個新建的 VPC 自動附帶一個主路由表
- 可以為 VPC 建立額外的自定義路由表
- 每個子網路必須關聯一個路由表
- 如果未明確關聯,子網路預設使用主路由表
- 每條路由指定一個目標 CIDR 和一個目標裝置
主路由表
當建立 VPC 時,系統會自動生成一個主路由表。初始狀態下,主路由表只包含一個本地路由,允許 VPC 內部通訊。這個本地路由無法修改,與會自動覆寫 VPC 內的所有例項。
主路由表通常用於私有子網路。對於我們的架構,主路由表需要包含一個條目,允許私有子網路中的例項透過 NAT 例項與網際網路通訊。
自定義路由表
為公有子網路建立自定義路由表:
- 在 VPC 控制檯中,選擇「路由表」
- 點選「建立路由表」
- 輸入路由表名稱並選擇 VPC
- 編輯路由表,增加目的地為 0.0.0.0/0,目標為網際網路閘道的路由
- 將公有子網路與此路由表關聯
這個設定允許公有子網路中的資源直接與網際網路通訊,是佈署導向公眾服務(如 Web 伺服器)的必要設定。
使用 Ansible 自動化 VPC 佈署
手動設定 VPC 在測試環境中可能可行,但在生產環境中,我們需要可重複、可版本控制的自動化方法。這裡,Ansible 的 ec2_vpc
模組提供了強大的自動化能力。
ec2_vpc 模組引數說明
Ansible 的 ec2_vpc 模組提供了豐富的引數,允許我們精細控制 VPC 的建立和設定:
- aws_access_key - AWS 存取金鑰
- aws_secret_key - AWS 秘密鑰
- cidr_block - VPC 的 CIDR 區塊,例如 10.0.0.0/16(必需)
- dns_hostnames - 是否啟用 DNS 主機名支援
- dns_support - 是否啟用 DNS 解析
- instance_tenancy - 例項租用選項(default 或 dedicated)
- internet_gateway - 是否應該附加網際網路閘道到 VPC
- resource_tags - 資源標籤字典
Ansible 的 ec2_vpc 模組是基礎設施即程式碼(IaC)的絕佳範例。它允許我們將 VPC 設定轉換為程式碼,實作版本控制、自動化佈署和一致性設定。引數設計非常全面,涵蓋了從基本的 CIDR 設定到 DNS 支援和租用類別等細節。
特別值得注意的是 resource_tags 引數,它允許我們為 VPC 資源增加標籤。在大型雲環境中,標籤策略對於資源管理、成本分配和安全控制至關重要。我通常建議至少包含 Name、Environment、Project 和 Owner 等標籤。
VPC 自動化佈署實戰
以下是一個完整的 Ansible playbook 範例,用於自動化佈署具有公有和私有子網路的 VPC:
---
- name: Provision VPC Infrastructure
hosts: localhost
connection: local
gather_facts: false
vars:
vpc_name: "Production-VPC"
vpc_cidr: "10.0.0.0/16"
public_subnet_cidr: "10.0.0.0/24"
private_subnet_cidr: "10.0.1.0/24"
region: "ap-northeast-1"
az: "ap-northeast-1a"
tasks:
- name: Create VPC
ec2_vpc:
state: present
cidr_block: "{{ vpc_cidr }}"
resource_tags: { "Name": "{{ vpc_name }}" }
region: "{{ region }}"
internet_gateway: yes
dns_support: yes
dns_hostnames: yes
register: vpc
- name: Create public subnet
ec2_vpc_subnet:
state: present
vpc_id: "{{ vpc.vpc_id }}"
cidr: "{{ public_subnet_cidr }}"
az: "{{ az }}"
resource_tags: { "Name": "Public Subnet" }
region: "{{ region }}"
register: public_subnet
- name: Create private subnet
ec2_vpc_subnet:
state: present
vpc_id: "{{ vpc.vpc_id }}"
cidr: "{{ private_subnet_cidr }}"
az: "{{ az }}"
resource_tags: { "Name": "Private Subnet" }
region: "{{ region }}"
register: private_subnet
- name: Create Internet Gateway route table
ec2_vpc_route_table:
vpc_id: "{{ vpc.vpc_id }}"
region: "{{ region }}"
tags:
Name: "Public Route Table"
subnets:
- "{{ public_subnet.subnet.id }}"
routes:
- dest: 0.0.0.0/0
gateway_id: "{{ vpc.igw_id }}"
register: public_route_table
- name: Create NAT instance
ec2:
key_name: my_key
instance_type: t2.micro
image: ami-12345678 # 應替換為您區域中的 NAT AMI
region: "{{ region }}"
vpc_subnet_id: "{{ public_subnet.subnet.id }}"
assign_public_ip: yes
group: ["nat_security_group"] # 應事先建立
instance_tags:
Name: "NAT Instance"
source_dest_check: no # 關鍵設定,允許 NAT 功能
register: nat_instance
- name: Create NAT route table
ec2_vpc_route_table:
vpc_id: "{{ vpc.vpc_id }}"
region: "{{ region }}"
tags:
Name: "Private Route Table"
subnets:
- "{{ private_subnet.subnet.id }}"
routes:
- dest: 0.0.0.0/0
instance_id: "{{ nat_instance.instances[0].id }}"
register: private_route_table
這個 Ansible playbook 實作了完整的 VPC 佈署自動化。讓我解釋其中的關鍵部分:
變數定義:首先定義了所有需要的變數,包括 VPC 名稱、CIDR 區塊、子網路設定和區域訊息。這使得 playbook 可以輕鬆地應用於不同環境。
VPC 建立:使用
ec2_vpc
模組建立 VPC,並啟用網際網路閘道、DNS 支援和 DNS 主機名。子網路建立:使用 `ec2_
Ansible 實戰:自動化 AWS VPC 與安全架構建置
在雲端架構設計中,虛擬私有雲(VPC)是構建安全可靠網路環境的基礎。透過 Ansible 這類別自動化工具,我們可以將繁瑣的 VPC 設定轉化為簡潔的程式碼,實作基礎設施即程式碼(Infrastructure as Code)的理念。本文將探討如何使用 Ansible 自動化設定 AWS VPC 及其安全元件。
AWS VPC 自動化設定的關鍵引數
在使用 Ansible 的 ec2_vpc
模組建立 VPC 時,有幾個關鍵引數需要特別理解:
route_tables
:定義路由表設定,格式為字典陣列,包含子網路列表和路由規則。例如:route_tables: - subnets: [172.22.2.0/24] routes: [{ dest: 0.0.0.0/0, gw: igw }]
其中
subnets
指定關聯的子網路,routes
定義路由規則。特殊關鍵字igw
表示流量應透過連線到 VPC 的網際網路閘道。目前由於 boto 的限制,此模組無法修改「主要」路由表,因此必須明確定義關聯的子網路。subnets
:定義要增加的子網路,格式為字典陣列:subnets: - cidr: 10.0.0.0/24 az: ap-southeast-2a resource_tags: { "Name": "public_subnet" }
這裡的
az
指定子網路的可用區域,雖非必需但建議設定。所有不在此列表中的 VPC 子網路將被移除。state
:指定 VPC 的狀態,必填引數,可選值為present
(建立)或absent
(終止)。
公私網路架構的 VPC 自動化建置
以下範例展示如何使用 Ansible 建立具有公有和私有子網路的 VPC 架構:
---
- hosts: localhost
connection: local
gather_facts: no
vars:
region: ap-southeast-2
# 命名字首
prefix: staging
# 可用區域
az: ap-southeast-2a
tasks:
- name: 建立 VPC
ec2_vpc:
region: "{{ region }}"
cidr_block: 10.0.0.0/16
resource_tags: '{"Name":"{{ prefix }}_vpc"}'
subnets:
- cidr: 10.0.0.0/24
az: "{{ az }}"
resource_tags: '{"Name":"{{ prefix }}_subnet_public"}'
- cidr: 10.0.1.0/24
az: "{{ az }}"
resource_tags: '{"Name":"{{ prefix }}_subnet_private"}'
internet_gateway: yes
route_tables:
- subnets:
- 10.0.0.0/24
routes:
- dest: 0.0.0.0/0
gw: igw
register: vpc
- name: 將 VPC ID 寫入 {{ prefix }}_vpc_info 檔案
shell: echo "{{ prefix }}"_vpc":" "{{ vpc.vpc_id }}" > "{{ prefix }}"_vpc_info
- name: 將子網路 ID 寫入 {{ prefix }}_vpc_info 檔案
shell: echo "{{ item.resource_tags.Name }}"":" "{{ item.id }}" >> "{{ prefix }}"_vpc_info
with_items: vpc.subnets
這個 Ansible Playbook 執行以下操作:
- 建立一個 CIDR 為 10.0.0.0/16 的 VPC,並標記為
staging_vpc
- 在 VPC 中建立兩個子網路:
- 公有子網路 (10.0.0.0/24),擁有通往往網際網路的路由
- 私有子網路 (10.0.1.0/24),沒有直接通往往網際網路的路由
- 建立網際網路閘道並連線到 VPC
- 為公有子網路建立路由表,增加通往往網際網路的預設路由
- 將 VPC 和子網路的 ID 儲存到檔案中,以便後續使用
執行此 Playbook 後,你可以在 AWS VPC 控制檯看到新建立的 VPC 及其子網路。值得注意的是,儲存的 staging_vpc_info
檔案可作為其他 Playbook 的變數檔案使用,這是一種實用的狀態管理方式。
VPC 刪除自動化
當需要刪除已建立的 VPC 時,可以使用以下 Playbook:
---
- hosts: localhost
connection: local
gather_facts: no
vars:
region: ap-southeast-2
vars_files:
- staging_vpc_info
tasks:
- name: 刪除 VPC
ec2_vpc:
region: "{{ region }}"
state: absent
# 從 staging_vpc_info 檔案取得 vpc_id
vpc_id: "{{ staging_vpc }}"
wait: yes
這個 Playbook 從前一個指令碼生成的 staging_vpc_info
檔案中讀取 VPC ID,然後使用 state: absent
引數刪除該 VPC。引數 wait: yes
確保 Ansible 等待 VPC 完全刪除後才繼續。
需要特別注意的是,刪除 VPC 時,AWS 會自動刪除其所有元件,如子網路、安全群組、網路 ACL、路由表等。然而,如果 VPC 中有執行中的執行個體,你必須先終止這些執行個體,才能刪除 VPC。
VPC 安全群組設定
安全群組是 AWS 中控制網路流量的虛擬防火牆。在 VPC 環境中,安全群組具有以下特性:
- 每個 VPC 最多可建立 100 個安全群組,每個安全群組最多可增加 50 條規則
- 只能指定允許規則,不能指定拒絕規則
- 可為入站和出站流量指定獨立規則
- 預設情況下,所有入站流量被拒絕,直到增加入站規則
- 預設情況下,所有出站流量被允許,直到增加出站規則
- 安全群組具有狀態感知特性,允許的入站流量的回應可以自由流出,反之亦然
- 與同一安全群組關聯的執行個體預設無法互相通訊,除非增加允許規則
- 執行個體啟動後,可以變更其關聯的安全群組
針對我們的 VPC 架構,可以設計以下安全群組:
- Web 伺服器安全群組:允許來自網際網路的 HTTP/HTTPS 流量、來自特定 IP 的 SSH 連線,以及到資料函式庫器的 MySQL 連線
- 資料函式庫群組:允許來自 Web 伺服器群組的 MySQL 連線,允許出站 HTTP/HTTPS 連線到網際網路
- NAT 執行個體安全群組:允許來自私有子網路的 HTTP/HTTPS 流量、來自特定 IP 的 SSH 連線,以及到網際網路的出站連線
在 Ansible 中,我們使用 ec2_group
模組來管理安全群組。與在 EC2 Classic 環境中不同,在 VPC 中建立安全群組時需要指定 vpc_id
引數。
以下是一個建立基本安全群組框架的 Playbook 範例:
---
- hosts: localhost
connection: local
gather_facts: no
vars:
region: ap-southeast-2
vars_files:
- staging_vpc_info
tasks:
- name: 建立 Web 伺服器安全群組
ec2_group:
name: "staging_webservers"
description: "Security group for web servers"
vpc_id: "{{ staging_vpc }}"
region: "{{ region }}"
rules: []
rules_egress: []
register: web_sg
- name: 建立資料函式庫群組
ec2_group:
name: "staging_db"
description: "Security group for database servers"
vpc_id: "{{ staging_vpc }}"
region: "{{ region }}"
rules: []
rules_egress: []
register: db_sg
- name: 建立 NAT 執行個體安全群組
ec2_group:
name: "staging_nat"
description: "Security group for NAT instances"
vpc_id: "{{ staging_vpc }}"
region: "{{ region }}"
rules: []
rules_egress: []
register: nat_sg
這個 Playbook 首先建立了三個安全群組的框架,但暫時沒有增加任何規則。這種方法允許我們先建立安全群組的基本結構,然後在後續步驟中增加具體的安全規則,有助於解決安全群組之間的相互依賴問題。
當你需要刪除安全群組時,可以先執行這個 Playbook 清空所有規則,然後再刪除安全群組本身,這樣可以避免因依賴關係而導致的刪除失敗。
安全群組規則設定策略
在實際設定中,我們需要為安全群組增加具體的規則。以下是一個更完整的安全群組設定範例:
---
- hosts: localhost
connection: local
gather_facts: no
vars:
region: ap-southeast-2
# 你的辦公室或家庭 IP
my_ip: 203.0.113.0/24
vars_files:
- staging_vpc_info
tasks:
- name: 建立 Web 伺服器安全群組
ec2_group:
name: "staging_webservers"
description: "Security group for web servers"
vpc_id: "{{ staging_vpc }}"
region: "{{ region }}"
rules:
- proto: tcp
from_port: 80
to_port: 80
cidr_ip: 0.0.0.0/0
- proto: tcp
from_port: 443
to_port: 443
cidr_ip: 0.0.0.0/0
- proto: tcp
from_port: 22
to_port: 22
cidr_ip: "{{ my_ip }}"
rules_egress:
- proto: tcp
from_port: 3306
to_port: 3306
group_id: "{{ db_sg.group_id }}"
- proto: tcp
from_port: 80
to_port: 80
cidr_ip: 0.0.0.0/0
- proto: tcp
from_port: 443
to_port: 443
cidr_ip: 0.0.0.0/0
register: web_sg
- name: 建立資料函式庫群組
ec2_group:
name: "staging_db"
description: "Security group for database servers"
vpc_id: "{{ staging_vpc }}"
region: "{{ region }}"
rules:
- proto: tcp
from_port: 3306
to_port: 3306
group_id: "{{ web_sg.group_id }}"
rules_egress:
- proto: tcp
from_port: 80
to_port: 80
cidr_ip: 0.0.0.0/0
- proto: tcp
from_port: 443
to_port: 443
cidr_ip: 0.0.0.0/0
register: db_sg
這個更完整的 Playbook 為安全群組增加了具體規則:
Web 伺服器安全群組:
- 允許來自任何地方的 HTTP (80) 和 HTTPS (443) 連線
- 只允許來自特定 IP 範圍的 SSH 連線
- 允許到資料函式庫器的 MySQL (3306) 連線
- 允許到網際網路的 HTTP/HTTPS 出站流量
資料函式庫群組:
- 僅允許來自 Web 伺服器安全群組的 MySQL 連線
- 允許到網際網路的 HTTP/HTTPS 出站流量
注意這裡使用了 group_id
引數來參照其他安全群組,這是 VPC 安全群組的一個強大功能,允許我們根據安全群組而不僅是 IP 範圍來定義規則。
實用技巧與最佳實踐
在使用 Ansible 自動化 AWS VPC 設定時,有一些實用技巧值得注意:
- 變數管理
Ansible自動化設定AWS安全群組與EC2例項
在雲端環境中,安全群組(Security Group)是控制流量進出EC2例項的虛擬防火牆,是AWS網路安全的核心元素。透過Ansible實作安全群組的自動化設定,不僅能提高佈署效率,還能確保安全設定的一致性。本文將深入介紹如何利用Ansible在AWS VPC環境中建立並設定安全群組,以及如何在特定子網中啟動EC2例項。
建立空白安全群組
首先,讓我們建立三個不包含任何規則的空白安全群組。這是設定安全架構的起點,之後我們會為每個群組增加相應的規則。
---
- hosts: localhost
connection: local
gather_facts: no
vars_files:
- staging_vpc_info
vars:
#your region
region: ap-southeast-2
#prefix for naming
prefix: staging
vpc_id: "{{ staging_vpc }}"
tasks:
- name: create empty security group for webservers
ec2_group:
region: "{{ region }}"
vpc_id: "{{ vpc_id }}"
name: "{{ prefix }}_sg_web"
description: security group for webservers
- name: create empty security group for databases
ec2_group:
region: "{{ region }}"
vpc_id: "{{ vpc_id }}"
name: "{{ prefix }}_sg_database"
description: security group for databases
- name: create empty security group for nat
ec2_group:
region: "{{ region }}"
vpc_id: "{{ vpc_id }}"
name: "{{ prefix }}_sg_nat"
description: security group for nat
這個Playbook建立了三個空白的安全群組,分別用於Web伺服器、資料函式庫器和NAT伺服器。讓我們分析一下關鍵元素:
hosts: localhost
- 指定在本地執行Ansible,而非遠端伺服器connection: local
- 使用本地連線,不需SSHgather_facts: no
- 跳過收集主機資訊階段,加快執行速度vars_files: - staging_vpc_info
- 從外部檔案匯入VPC相關變數ec2_group
模組 - Ansible提供的AWS安全群組管理模組,用於建立、修改和刪除安全群組
每個安全群組都有特定用途,命名時使用字首(prefix)便於識別環境(如staging、production),這是雲端環境管理的最佳實踐。
執行這個Playbook後,你可以在AWS VPC管理控制檯的安全群組部分看到這三個新建的安全群組,但它們還沒有任何入站或出站規則。
設定安全群組規則
接下來,我們需要為這些安全群組增加適當的規則,以控制流量。以下Playbook將為前面建立的安全群組設定規則:
---
- hosts: localhost
connection: local
gather_facts: no
vars_files:
- staging_vpc_info
vars:
#your region
region: ap-southeast-2
#your ip address
allowed_ip: 123.xxx.xxx.xxx/32
#prefix for naming
prefix: staging
vpc_id: "{{ staging_vpc }}"
private_subnet: 10.0.1.0/24
tasks:
- name: modify sg_web rules
ec2_group:
region: "{{ region }}"
vpc_id: "{{ vpc_id }}"
#your security group name
name: "{{ prefix }}_sg_web"
description: security group for webservers
rules:
# allow ssh access from your ip address
- proto: tcp
from_port: 22
to_port: 22
cidr_ip: "{{ allowed_ip }}"
# allow http access from anywhere
- proto: tcp
from_port: 80
to_port: 80
cidr_ip: 0.0.0.0/0
# allow https access from anywhere
- proto: tcp
from_port: 443
to_port: 443
cidr_ip: 0.0.0.0/0
rules_egress:
- proto: tcp
from_port: 3306
to_port: 3306
group_name: "{{ prefix }}_sg_database"
- name: modify sg_database rules
ec2_group:
region: "{{ region }}"
vpc_id: "{{ vpc_id }}"
name: "{{ prefix }}_sg_database"
description: security group for databases
rules:
- proto: tcp
from_port: 3306
to_port: 3306
group_name: "{{ prefix }}_sg_web"
rules_egress:
- proto: tcp
from_port: 80
to_port: 80
cidr_ip: 0.0.0.0/0
- proto: tcp
from_port: 443
to_port: 443
cidr_ip: 0.0.0.0/0
- name: modify sg_nat rules
ec2_group:
region: "{{ region }}"
vpc_id: "{{ vpc_id }}"
name: "{{ prefix }}_sg_nat"
description: security group for nat
rules:
# allow ssh access from your ip address
- proto: tcp
from_port: 22
to_port: 22
cidr_ip: "{{ allowed_ip }}"
# allow http access from private subnet
- proto: tcp
from_port: 80
to_port: 80
cidr_ip: "{{ private_subnet }}"
# allow https access from private subnet
- proto: tcp
from_port: 443
to_port: 443
cidr_ip: "{{ private_subnet }}"
rules_egress:
- proto: tcp
from_port: 80
to_port: 80
cidr_ip: 0.0.0.0/0
- proto: tcp
from_port: 443
to_port: 443
cidr_ip: 0.0.0.0/0
這個Playbook設定了三個安全群組的詳細規則,讓我們逐一分析其安全性考量和網路設計邏輯:
Web伺服器安全群組(
sg_web
):- 入站規則:
- 允許從特定IP(
allowed_ip
)透過SSH(22埠)連線,增強安全性 - 允許從任何地方(0.0.0.0/0)存取HTTP(80埠)和HTTPS(443埠)服務
- 允許從特定IP(
- 出站規則:
- 只允許連線到資料函式庫群組(3306埠),遵循最小許可權原則
- 入站規則:
資料函式庫群組(
sg_database
):- 入站規則:
- 僅允許來自Web伺服器安全群組的MySQL連線(3306埠)
- 出站規則:
- 允許HTTP/HTTPS流量出站,便於資料函式庫器進行更新
- 入站規則:
NAT伺服器安全群組(
sg_nat
):- 入站規則:
- 允許從特定IP進行SSH管理連線
- 只允許私有子網(10.0.1.0/24)的HTTP/HTTPS請求
- 出站規則:
- 允許HTTP/HTTPS流量出站,實作私有子網到網際網路的通訊
- 入站規則:
這種設計展現了深思熟慮的網路隔離策略:Web伺服器暴露給網際網路但有限制的出站流量;資料函式庫受來自Web伺服器的連線;NAT伺服器則作為私有子網的出口點。這遵循了AWS安全最佳實踐中的深度防禦原則。
安全群組依賴關係與刪除
在AWS中,安全群組之間可能存在依賴關係,這會影響刪除操作。例如,如果嘗試刪除sg_web
安全群組,由於sg_database
的入站規則參照了它,操作會失敗。
要解決這個問題,我們需要先清空安全群組規則,再進行刪除:
- 首先執行
sg_empty.yml
清空所有規則 - 然後使用以下Playbook刪除安全群組:
---
- hosts: localhost
connection: local
gather_facts: no
vars_files:
- staging_vpc_info
vars:
#your region
region: ap-southeast-2
#prefix for naming
prefix: staging
vpc_id: "{{ staging_vpc }}"
tasks:
- name: delete {{ prefix }}_sg_web
ec2_group:
region: "{{ region }}"
vpc_id: "{{ vpc_id }}"
name: "{{ prefix }}_sg_web"
description: security group for webservers
state: absent
- name: delete {{ prefix }}_sg_database
ec2_group:
region: "{{ region }}"
vpc_id: "{{ vpc_id }}"
name: "{{ prefix }}_sg_database"
description: security group for databases
state: absent
- name: delete {{ prefix }}_sg_nat
ec2_group:
region: "{{ region }}"
vpc_id: "{{ vpc_id }}"
name: "{{ prefix }}_sg_nat"
description: security group for nat
state: absent
這個刪除Playbook的關鍵在於state: absent
引數,它告訴Ansible移除指定的安全群組。然而,直接執行此Playbook可能會因依賴關係而失敗。這揭示了AWS資源管理中的重要概念:資源間的參照關係必須妥善處理。
在實際操作中,我發現處理這類別依賴關係的最佳方式是遵循以下順序:
- 先清空所有安全群組規則(執行sg_empty.yml)
- 再刪除安全群組(執行sg_delete.yml)
這類別似於資料函式庫外部索引鍵約束處理,必須先移除參照關係,才能刪除被參照的物件。
在VPC中啟動EC2例項
現在我們已經設定了VPC和安全群組,接下來可以在特定子網中啟動EC2例項。首先,讓我們在公有子網中啟動Web伺服器:
---
- hosts: localhost
connection: local
gather_facts: no
vars_files:
- staging_vpc_info
vars:
region: ap-southeast-2
key: yan-key-pair-apsydney
instance_type: t2.micro
image: ami-d9fe9be3
prefix: staging
tasks:
- name: web instance provisioning
ec2:
region: "{{ region }}"
key_name: "{{ key }}"
instance_type: "{{ instance_type }}"
image: "{{ image }}"
wait: yes
group: "{{ prefix }}_sg_web"
instance_tags:
Name: "{{ prefix }}_web"
class: web
environment: staging
id: web_launch_01
vpc_subnet_id: "{{ staging_subnet_public }}"
register: ec2
- name: associate new EIP for the instance
ec2_eip:
region: "{{ region }}"
instance_id: "{{ item.id }}"
with_items: ec2.instances
這個Playbook在我們的VPC公有子網中啟動了一個Web伺服器例項,並為其分配了彈性IP。關鍵設定包括:
vpc_subnet_id: "{{ staging_subnet_public }}"
- 指定在公有子網中啟動例項group: "{{ prefix }}_sg_web"
- 應用之前建立的Web伺服器安全群組instance_tags
- 增加標籤以便於識別和管理register: ec2
- 將EC2啟動結果儲存在變數中,以便後續使用ec2_eip
任務 - 為例項分配彈性IP,確保其可從網際網路存取
接下來,我們在私有子網中啟動資料函式庫器:
---
- hosts: localhost
connection: local
gather_facts: no
vars_files:
- staging_vpc_info
vars:
region: ap-southeast-2
key: yan-key-pair-apsydney
instance_type: t2.micro
image: ami-d9fe9be3
prefix: staging
tasks:
- name: database instance provisioning
ec2:
region: "{{ region }}"
key_name: "{{ key }}"
instance_type: "{{ instance_type }}"
image: "{{ image }}"
wait: yes
group: "{{ prefix }}_sg_database"
instance_tags:
Name: "{{ prefix }}_database"
class: database
environment: staging
id: db_launch_01
vpc_subnet_id: "{{ staging_subnet_private }}"
assign_public_ip: no
資料函式庫器Playbook的關鍵點:
vpc_subnet_id: "{{ staging_subnet_private }}"
- 在私有子網中啟動例項assign_public_ip: no
- 明確指定不分配公共IPgroup: "{{ prefix }}_sg_database"
- 應用資料函式庫
AWS VPC中的NAT例項佈署與設定
在AWS雲端環境中,虛擬私有雲(VPC)的網路架構設計至關重要。當我們建立包含私有子網的VPC時,這些私有子網內的EC2例項無法直接存取網際網路,此時就需要佈署NAT(網路地址轉換)例項作為中間橋樑。在這篇文章中,玄貓將帶領大家深入瞭解NAT例項的佈署流程和多可用區架構的實作方法。
NAT例項AMI的選擇與準備
要佈署NAT例項,首先需要選擇適合的AMI。AWS提供了專門的NAT AMI,這些AMI已經預先設定好了NAT功能所需的設定。
取得NAT AMI ID的步驟如下:
- 登入AWS管理控制檯,進入EC2服務
- 在控制檯中,點選「啟動例項」按鈕
- 在「選擇Amazon機器映像(AMI)」頁面,選擇「社群AMI」分類別
- 搜尋「amzn-ami-vpc-nat」,結果列表中每個AMI的名稱會包含版本訊息,例如2013.09
- 記下適合的AMI ID
需要注意的是,這種NAT AMI使用的是半虛擬化(paravirtual)技術,因此無法與t2.micro等硬體虛擬化例項類別一起使用。我們將使用t1.micro例項類別來佈署NAT服務。
使用Ansible佈署NAT例項
以下是一個完整的Ansible playbook,用於在VPC的公有子網中啟動NAT例項,並為其關聯彈性IP位址:
---
- hosts: localhost
connection: local
gather_facts: no
vars_files:
- staging_vpc_info
vars:
region: ap-southeast-2
key: yan-key-pair-apsydney
instance_type: t1.micro
image: ami-3bae3201
prefix: staging
tasks:
- name: NAT instance provisioning
ec2:
region: "{{ region }}"
key_name: "{{ key }}"
instance_type: "{{ instance_type }}"
image: "{{ image }}"
wait: yes
group: "{{ prefix }}_sg_nat"
instance_tags:
Name: "{{ prefix }}_nat"
class: nat
environment: staging
id: nat_launch_01
vpc_subnet_id: "{{ staging_subnet_public }}"
source_dest_check: no
wait: yes
register: ec2
- name: associate new EIP for the instance
tags: eip
ec2_eip:
region: "{{ region }}"
instance_id: "{{ item.id }}"
with_items: ec2.instances
when: item.id is defined
這段Ansible playbook完成了以下關鍵任務:
- NAT例項佈署:在指定的公有子網中啟動一個NAT例項
- 標籤管理:為例項增加名稱、類別、環境等標籤,便於資源管理
- 停用源/目標檢查:設定
source_dest_check: no
是NAT例項的關鍵設定 - 彈性IP分配:為NAT例項分配彈性IP,使其能夠維持穩定的公網IP位址
值得特別注意的是源/目標檢查設定。預設情況下,EC2例項會執行源/目標檢查,這意味著例項必須是其傳送或接收的任何流量的源或目標。然而,NAT例項必須能夠傳送和接收源或目標不是自己的流量,因此必須在NAT例項上停用源/目標檢查。
執行這個playbook後,一個名為staging_nat的例項將在staging_subnet_public子網中建立,並關聯一個彈性IP位址。
設定路由表實作私有子網網際網路存取
僅佈署NAT例項還不夠,我們需要更新主路由表,以允許私有子網中的例項透過NAT例項連線到網際網路:
- 在VPC控制檯導航窗格中選擇「路由表」
- 選擇你的staging_vpc VPC的主路由表,並選擇「路由」選項卡
- 點選「編輯」
- 在「目的地」欄位中輸入0.0.0.0/0 CIDR區塊,並從「目標」列表中選擇staging_nat例項ID
- 點選「儲存」
完成這一設定後,私有子網中的例項就能夠透過NAT例項存取網際網路,同時保持私有子網的安全性,因為外部無法直接存取私有子網中的資源。
多可用區佈署架構
為了提高系統的可用性和容錯能力,我們可以將Amazon VPC跨越多個可用區(AZ)中的多個子網。這種多可用區架構能夠增加系統的冗餘性,使單個元件的故障不會導致整個系統當機。
多可用區VPC架構設計
在我們的多可用區設計中,將在同一區域的另一個可用區內增加一個公有子網和一個私有子網,形成跨可用區的冗餘架構。這種設計特別適合需要高用性的應用系統。
首先,我們需要刪除之前建立的staging_vpc VPC。可以使用vpc_delete.yml playbook或直接從AWS VPC控制檯刪除VPC。注意:刪除VPC前必須先終止VPC中的所有EC2例項。
使用Ansible佈署多可用區VPC
以下是一個完整的Ansible playbook,用於建立具有多可用區子網的VPC:
---
- hosts: localhost
connection: local
gather_facts: no
vars:
region: ap-southeast-2
# prefix for naming
prefix: staging
# availability zones
az0: ap-southeast-2a
az1: ap-southeast-2b
tasks:
- name: create vpc with multi-az subnets
ec2_vpc:
region: "{{ region }}"
cidr_block: 10.0.0.0/16
resource_tags: '{"Name":"{{ prefix }}_vpc"}'
subnets:
- cidr: 10.0.0.0/24
az: "{{ az0 }}"
resource_tags: '{"Name":"{{ prefix }}_subnet_public_0"}'
- cidr: 10.0.1.0/24
az: "{{ az0 }}"
resource_tags: '{"Name":"{{ prefix }}_subnet_private_0"}'
- cidr: 10.0.2.0/24
az: "{{ az1 }}"
resource_tags: '{"Name":"{{ prefix }}_subnet_public_1"}'
- cidr: 10.0.3.0/24
az: "{{ az1 }}"
resource_tags: '{"Name":"{{ prefix }}_subnet_private_1"}'
internet_gateway: yes
route_tables:
- subnets:
- 10.0.0.0/24
- 10.0.2.0/24
routes:
- dest: 0.0.0.0/0
gw: igw
register: vpc
- name: write vpc id to {{ prefix }}_vpc_info file
shell: echo "{{ prefix }}"_vpc":" "{{ vpc.vpc_id }}"
> "{{ prefix }}"_vpc_info
- name: write subnets id to {{ prefix }}_vpc_info file
shell: echo "{{ item.resource_tags.Name }}"":" "{{ item.id }}"
>> "{{ prefix }}"_vpc_info
with_items: vpc.subnets
這個playbook實作了以下核心功能:
- VPC基礎設定:建立CIDR為10.0.0.0/16的VPC
- 多可用區子網設定:
- 在ap-southeast-2a可用區建立公有子網(10.0.0.0/24)和私有子網(10.0.1.0/24)
- 在ap-southeast-2b可用區建立公有子網(10.0.2.0/24)和私有子網(10.0.3.0/24)
- 路由設定:為公有子網設定通往往網際網路的路由
- 設定訊息儲存:將VPC和子網的ID訊息儲存到設定檔案中,供後續操作使用
執行這個playbook後,一個新的VPC將被建立,包含四個子網:兩個在ap-southeast-2a可用區(staging_subnet_private_0和staging_subnet_public_0),兩個在ap-southeast-2b可用區(staging_subnet_private_1和staging_subnet_public_1)。
接下來,執行sg_empty.yml playbook,然後執行sg_modify.yml playbook,重新建立VPC的安全組。
實作多可用區的高用性架構
要實作真正的高用性,你可以:
- Web應用層:在兩個(或更多)可用區的公有子網(staging_subnet_public_0和staging_subnet_public_1)中佈署Web應用叢集,並使用Amazon彈性負載平衡(ELB)分配負載
- *資料函式庫:使用Amazon RDS(關係型資料函式庫),佈署在兩個(或更多)可用區的私有子網(staging_subnet_private_0和staging_subnet_private_1)中
這種架構能夠確保即使一個可用區完全故障,系統仍然可以繼續執行,提供不間斷的服務。
VPC中的Ansible佈署策略
在VPC環境中使用Ansible管理私有子網中的伺服器設定時,面臨一個挑戰:私有子網中的例項無法直接從網際網路接收入站流量。為解決這個問題,我們有兩種選擇:
跳板機(Jump Box)方案
在VPC的公有子網中安裝Ansible,並允許從Ansible機器透過SSH連線到私有子網中要管理的主機。這台Ansible機器還可以用作跳板機,允許從網際網路透過SSH存取私有子網中的主機(先SSH到Ansible機器,然後使用Ansible機器SSH到私有子網中的主機)。
虛擬私人網路連線方案
在Ansible機器(透過網際網路)和私有子網之間建立虛擬私人網路(虛擬私有網路)連線。我們可以在公有子網中啟動一個Open虛擬私人網路伺服器(在AWS市場中可用)例項,允許Ansible機器使用Open虛擬私人網路客戶端登入並透過SSH連線到私有子網中的主機。
佈署跳板機例項
我們可以使用當前的Ansible機器在公有子網中啟動一個跳板機例項,並在該例項上安裝Ansible。首先,需要為這個例項建立一個新的安全組:
---
- hosts: localhost
connection: local
gather_facts: no
vars_files:
- staging_vpc_info
vars:
#your region
region: ap-southeast-2
#your ip address
allowed_ip: 123.xxx.xxx.xxx/32
#prefix for naming
prefix: staging
vpc_id: "{{ staging_vpc }}"
tasks:
- name: create security group for jump box instance
ec2_group:
region: "{{ region }}"
vpc_id: "{{ vpc_id }}"
#your security group name
name: "{{ prefix }}_sg_jumpbox"
description: security group for jump box
rules:
# allow ssh access from your ip address
- proto: tcp
from_port: 22
to_port: 22
cidr_ip: "{{ allowed_ip }}"
rules_egress:
- proto: all
cidr_ip: 0.0.0.0/0
這個安全組設定:
- 只允許從特定IP位址(allowed_ip)透過SSH(連線埠22)存取跳板機
- 允許跳板機向任何目的地傳送任何類別的出站流量
這是一個最小許可權原則的實踐,只開放必要的入站存取,提高安全性。
接下來,使用以下playbook在公有子網A中啟動跳板機例項:
---
- hosts: localhost
connection: local
gather_facts: no
vars_files:
- staging_vpc_info
vars:
region: ap-southeast-2
key: yan-key-pair-apsydney
instance_type: t2.micro
image: ami-d9fe9be3
prefix: staging
vpc_subnet_id: "{{ staging_subnet_public_0 }}"
tasks:
- name: jump box instance provisioning
ec2:
region: "{{ region }}"
key_name: "{{ key }}"
instance_type: "{{ instance_type }}"
image: "{{ image }}"
wait: yes
group: "{{ prefix }}_sg_jumpbox"
instance_tags:
Name: "{{ prefix }}_jumpbox"
class: jump