現代軟體開發流程中,容器化技術已成為標準實務。提升容器建置效率對於開發速度和生產環境穩定性至關重要。本文將探討如何有效利用 BuildKit 的快取機制,包含基礎映像的選擇策略、透過 ONBUILD 指令強化合規性、COPY 指令的最佳化技巧以及管理建置依賴的最佳方法。此外,文章也將說明快取匯出與匯入的時機,讓 CI/CD 流程更加順暢。最後,文章也將探討定期重建容器的必要性與具體步驟,確保容器映像的安全性與更新頻率,並說明如何整合版本控制系統與 CI/CD 流程,以自動化執行重建與測試流程。
容器建置最佳化與重建策略
在現代軟體開發中,容器化技術已經成為不可或缺的一部分。最佳化容器建置過程不僅可以提高開發效率,還能確保生產環境的穩定性。本文將探討如何最佳化容器建置快取以及定期重建容器的最佳實踐。
12.4 最佳化容器建置快取
BuildKit 容器映像建置具有先進的快取功能。瞭解如何利用這些功能可以顯著提高建置速度。
基礎映像的選擇
首先需要考慮的是基礎映像。發行版套件和 Python 直譯器通常不會經常變更。即使是嚴格的合規政策也不需要在安全補丁發布後的一天內立即更新。
因此,每天建立一個包含最新發行版套件和所需 Python 版本的映像是有意義的。基礎映像可以標記日期,例如 internal-registry.example.com/base-python-image:3.9-2022-03-10。
利用 ONBUILD 指令
可以使用 ONBUILD 指令來強制執行合規政策,例如拒絕建置日期超過 60 天的映像。
FROM internal-registry.example.com/base-python-image:3.9-2022-03-10
由於這個映像不會變更,快取不會因為新映像上傳到這個標籤而失效。
COPY 指令的最佳化
在 Dockerfile 中,COPY 指令後的步驟需要謹慎安排,以最大化快取的效果。
# 不佳的範例
COPY requirements.txt setup.cfg ... /app/sources/
RUN python -m venv /app/runtime/
RUN /app/runtime/bin/pip install -r /app/sources/requirements.txt
RUN pip install build
RUN cd /app/sources/ && python -m build
RUN /app/runtime/bin/pip install --no-dependencies /app/sources/dist/*.whl
# 最佳化的範例
RUN python -m venv /app/runtime/
COPY requirements.txt /app/sources/
RUN /app/runtime/bin/pip install -r /app/sources/requirements.txt
COPY setup.cfg ... /app/sources/
RUN cd /app/sources/ && python -m build
RUN /app/runtime/bin/pip install --no-dependencies /app/sources/dist/*.whl
建置依賴的最佳化
對於需要安裝建置依賴的情況,可以先進行一次模擬建置,以 priming 安裝建置依賴。
COPY setup.cfg pyproject.toml /app/sources/
RUN cd /app/sources/ && (python -m build --no-isolation || true)
RUN rm -rf /app/sources/dist
COPY setup.cfg ... /app/sources/
RUN cd /app/sources/ && python -m build --no-isolation
RUN /app/runtime/bin/pip install --no-dependencies /app/sources/dist/*.whl
快取匯出與匯入
在使用持續整合(CI)建置映像時,建議匯出和匯入快取到持久儲存中。這樣可以避免因 CI 工作節點短暫而導致快取遺失。
12.5 重建容器
可重現且快取友好的容器建置方式意味著依賴不會在每次建置時升級。這雖然對預測性有好處,但依賴最終還是需要升級。
定期升級依賴
大多數開源專案會慢慢棄用舊功能。定期升級依賴可以減少升級難度。
建議每 1-2 周重新建置一次容器,步驟如下:
- 重新產生
requirements.txt,將依賴版本固定到最新版本。 - 更新
FROM標頭,使用最新的日期(或前一天)。
由於 Dockerfile 和 requirements.txt 都在版本控制之下,這個過程可以像其他合併請求一樣處理。可以自動或半自動產生這些變更。
驗證與測試
無論如何產生變更,都需要經過正常的開發週期,包括在分支上獲得綠色的持續整合結果。也可能需要手動或自動執行針對特定環境的測試。
Amazon Web Services(AWS)與Python的整合應用
Amazon Web Services(AWS)是一個極為流行的雲端運算平台,提供多種服務,包括運算資源、儲存資源等。AWS允許使用者根據使用量付費,並且對於某些服務提供免費層級。然而,使用者需要注意監控自己的使用情況,以避免不必要的費用。
使用Python與AWS互動
AWS的一個核心原則是所有與其服務的互動都應當能夠透過API實作。網頁控制檯只是API的前端之一,這使得基礎設施的組態可以透過程式設計實作,也就是所謂的「基礎設施即程式碼」。AWS團隊在PyPI上維護了一個名為boto3的套件,這是用於自動化AWS操作的最有效方法之一。
組態boto3
在使用boto3時,可以透過設定AWS_DEFAULT_REGION環境變數來指定AWS區域,這樣在呼叫boto3的設定函式時就可以省略區網域名稱的引數。
import os
import boto3
# 設定AWS區域
os.environ['AWS_DEFAULT_REGION'] = 'us-west-2'
# 使用boto3建立S3客戶端
s3 = boto3.client('s3')
內容解密:
- 匯入必要的模組:首先匯入
os和boto3模組。os用於設定環境變數,而boto3是用於與AWS服務互動的Python套件。 - 設定AWS區域:透過
os.environ設定AWS_DEFAULT_REGION環境變數為us-west-2,這樣就指定了AWS的區域。 - 建立S3客戶端:使用
boto3.client('s3')建立了一個S3服務的客戶端,用於與S3儲存服務進行互動。
使用Jupyter與boto3結合進行AWS操作
將boto3與Jupyter結合使用,可以建立一個強大的AWS操作控制檯。透過Jupyter使用boto3 API進行的操作都是可記錄和可重複執行的,這比透過網頁控制檯進行操作更具優勢。
# 使用boto3列出S3中的桶
response = s3.list_buckets()
# 輸出桶的名稱
for bucket in response['Buckets']:
print(bucket['Name'])
內容解密:
- 列出S3桶:使用
s3.list_buckets()方法列出使用者所有的S3桶。 - 遍歷並輸出桶名稱:遍歷傳回結果中的
Buckets列表,並列印每個桶的名稱。
安全性與成本控制
在使用AWS時,需要注意成本控制和安全性。使用者應該監控自己的使用情況,關閉未使用的服務,以避免不必要的費用。同時,應當利用AWS提供的工具和最佳實踐來提高安全性。
自動化與安全性在AWS中的實踐
在AWS環境中進行自動化操作時,安全性的考量是至關重要的。AWS提供了一套完整的身份和存取管理(IAM)系統,用於管理使用者、角色和許可權。正確組態和使用IAM對於確保AWS資源的安全至關重要。
組態存取金鑰
AWS的存取金鑰由存取金鑰ID和存取金鑰密碼組成。使用者可以自行管理自己的存取金鑰,但必須遵守組織的安全政策。通常,建議為每個使用者和自動化任務建立獨立的IAM使用者,以便於金鑰管理和稽核日誌的準確性。
金鑰輪換
為了提高安全性,存取金鑰應該定期輪換。輪換過程包括生成新的金鑰、替換舊金鑰、停用舊金鑰,並在確認無誤後刪除舊金鑰。這種做法可以最小化金鑰洩露的風險。
import boto3
# 生成新的存取金鑰
response = client.create_access_key(UserName='username')
new_access_key_id = response['AccessKey']['AccessKeyId']
new_secret_access_key = response['AccessKey']['SecretAccessKey']
# 使用新的存取金鑰替換舊的
# ...
#### 內容解密:
1. `create_access_key` 方法用於為指定使用者生成新的存取金鑰。
2. `UserName` 引數指定了要為哪個使用者生成新的存取金鑰。
3. 傳回的 `AccessKeyId` 和 `SecretAccessKey` 分別是新的存取金鑰ID和存取金鑰密碼。
### 建立短期令牌
AWS支援使用短期令牌(STS)來提高安全性和靈活性。短期令牌可以透過假設角色或使用SAML斷言來獲得。
```python
import boto3
# 假設角色以取得短期令牌
response = client.assume_role(
RoleArn='arn:aws:iam::123456789012:role/demo',
RoleSessionName='session-name'
)
credentials = response['Credentials']
session = boto3.Session(
aws_access_key_id=credentials['AccessKeyId'],
aws_secret_access_key=credentials['SecretAccessKey'],
aws_session_token=credentials['SessionToken'],
)
#### 內容解密:
1. `assume_role` 方法用於假設指定的角色,以取得短期令牌。
2. `RoleArn` 引數指定了要假設的角色的ARN。
3. `RoleSessionName` 引數為此次會話指定名稱。
4. 取得的 `Credentials` 包含了短期令牌所需的資訊,用於建立新的boto3會話。
### Elastic Computing Cloud (EC2)
EC2是AWS提供的彈性計算服務,用於執行虛擬機器。EC2例項執行在特定的區域和可用區內,並且需要適當的安全組組態來控制網路存取。
#### 區域和可用區
EC2例項執行在特定的AWS區域和可用區。區域是AWS服務的地理位置,而可用區是區域內的獨立位置。
```python
import boto3
# 連線到指定的EC2區域
ec2 = boto3.client('ec2', region_name='us-west-2')
#### 內容解密:
1. `boto3.client('ec2', region_name='us-west-2')` 用於建立連線到us-west-2區域的EC2客戶端。
2. `region_name` 引數指定了要連線的AWS區域。
### Amazon Machine Images (AMIs)
要啟動EC2例項,需要選擇適當的Amazon Machine Image (AMI)。AMI包含了作業系統和初始組態。
```python
# 使用describe_images查詢AMI
response = client.describe_images(
Filters=[
{'Name': 'name', 'Values': ['amzn2-ami-hvm-*-x86_64-gp2']},
]
)
#### 內容解密:
1. `describe_images` 方法用於查詢符合指定過濾條件的AMI。
2. `Filters` 引數用於指定過濾條件,例如根據名稱過濾。
使用 boto3 管理 AWS EC2 例項
介紹
AWS EC2 是 Amazon Web Services 提供的一種虛擬伺服器服務,允許使用者在雲端執行應用程式。boto3 是 AWS 的 Python SDK,提供了豐富的 API 來管理 AWS 資源,包括 EC2。本篇文章將介紹如何使用 boto3 來管理 EC2 例項,包括建立、組態和連線例項。
搜尋和選擇適當的 AMI
在建立 EC2 例項之前,需要選擇一個適當的 Amazon Machine Image (AMI)。AMI 是一種預先組態好的虛擬機器映像檔,包含了作業系統和應用程式。
description = client.describe_images(Filters=[{
'Name': 'product-code',
'Values': ['aw0evgkw8e5c1q413zgy5pjce']
}])
print(description)
內容解密:
- 使用
describe_images方法來查詢符合特定條件的 AMI。 Filters引數用於篩選 AMI,例如根據產品程式碼。product-code是一種篩選條件,用於查詢與特定產品程式碼相關的 AMI。
組態 SSH 金鑰
為了安全地連線到 EC2 例項,需要組態 SSH 金鑰。boto3 允許建立和管理 SSH 金鑰對。
key = boto3.client("ec2").create_key_pair(KeyName="high-security")
fname = os.path.expanduser("~/.ssh/high-security")
with open(fname, "w") as fpout:
os.chmod(fname, 0o600)
fpout.write(key["KeyMaterial"])
內容解密:
- 使用
create_key_pair方法建立一個新的 SSH 金鑰對。 KeyName引數指定金鑰對的名稱。- 將私鑰寫入檔案,並設定適當的許可權。
啟動 EC2 例項
使用 run_instances 方法可以啟動新的 EC2 例項。
client = boto3.client("ec2")
client.run_instances(
ImageId=IMAGE_ID,
MinCount=1,
MaxCount=1,
InstanceType='t2.micro',
KeyName=ssh_key_name,
SecurityGroupIds=[SECURITY_GROUP]
)
內容解密:
ImageId指定要使用的 AMI ID。MinCount和MaxCount指定要啟動的例項數量,通常設為 1。InstanceType指定例項的型別,例如t2.micro。KeyName指定要使用的 SSH 金鑰對名稱。SecurityGroupIds指定要套用的安全群組 ID。
安全地連線到 EC2 例項
為了避免 Trust On First Use (TOFU) 的問題,需要在連線前驗證例項的公鑰。
client = boto3.client('ec2')
output = client.get_console_output(InstanceId=sys.argv[1])
result = output['Output']
rsa = next(line for line in result.splitlines() if line.startswith('ssh-rsa'))
內容解密:
- 使用
get_console_output方法取得例項的控制檯輸出。 - 從輸出中提取公鑰,通常以
ssh-rsa開頭。
建立自定義映像檔
建立自定義映像檔可以加速例項啟動,並確保所有例項的一致性。
建立步驟:
- 啟動一個基礎 EC2 例項。
- 組態例項,包括安裝軟體和設定。
- 建立例項的映像檔。
使用 AWS 服務建立和管理基礎架構
13.2 自動化建立 Amazon Machine Image (AMI)
自動化建立 AMI 是雲端基礎架構管理中的重要環節。透過使用 SaltStack 和 AWS 的 boto3 函式庫,可以實作自動化建立和管理 AMI。
建立 AMI 的步驟
- 啟動基礎 EC2 例項:使用 boto3 的
run_instances方法啟動一個基礎的 EC2 例項。 - 組態 SaltStack:將 SaltStack 的程式碼和組態檔案複製到 EC2 例項中。
- 執行 SaltStack:透過 SSH 連線到 EC2 例項,並執行 SaltStack 的
salt-call命令來組態例項。 - 建立 AMI:使用 boto3 的
create_image方法將當前 EC2 例項的磁碟內容儲存為一個 AMI。
import boto3
# 建立 EC2 客戶端
ec2 = boto3.client('ec2')
# 啟動基礎 EC2 例項
response = ec2.run_instances(
ImageId='ami-abcd1234',
InstanceType='t2.micro',
MinCount=1,
MaxCount=1
)
# 取得例項 ID
instance_id = response['Instances'][0]['InstanceId']
# 複製 SaltStack 程式碼和組態檔案到 EC2 例項
# ...
# 透過 SSH 連線到 EC2 例項並執行 SaltStack
# ...
# 建立 AMI
response = ec2.create_image(
InstanceId=instance_id,
Name='my-ami'
)
使用 SaltStack 組態 EC2 例項
SaltStack 是一個強大的自動化工具,可以用來組態和管理 EC2 例項。以下是一個簡單的例子,展示如何使用 SaltStack 組態 EC2 例項。
$ pex -o salt-call -c salt-call salt-ssh
$ scp -r salt-call salt-files $USER@$IP:/
$ ssh $USER@$IP /salt-call --local --file-root /salt-files
使用 boto3 建立 AMI
使用 boto3 的 create_image 方法可以將當前 EC2 例項的磁碟內容儲存為一個 AMI。
>>> client.create_image(....)
13.3 簡單儲存服務 (S3)
簡單儲存服務 (S3) 是 AWS 提供的一個物件儲存服務,可以用來儲存和檢索物件。
管理 S3 Bucket
S3 Bucket 是 S3 中用來儲存物件的容器。以下是一些管理 S3 Bucket 的基本操作。
建立 S3 Bucket
response = client("s3").create_bucket(
ACL='private',
Bucket='my.unique.name.example.com',
)
列出 S3 Bucket 中的物件
response = client("s3").list_objects(
Bucket=bucket,
MaxKeys=10,
Marker=marker,
Prefix=prefix,
)
上傳物件到 S3 Bucket
response = boto3.client("s3").put_object(
Bucket=BUCKET,
Key=some_key,
Body=b'some content',
)
從 S3 Bucket 下載物件
response = boto3.client("s3").get_object(
Bucket=BUCKET,
Key=OBJECT_KEY,
)
value = response["Body"].read()
使用預簽名 URL 分享 S3 物件
S3 允許生成預簽名 URL,可以用來分享 S3 物件。
url = s3.generate_presigned_url(
ClientMethod='get_object',
Params={
'Bucket': my_bucket,
'Key': 'meeting-recording.avi'
}
)
這個 URL 可以被分享給其他人,用來下載 S3 物件。