附註:
- 此教學課程需要存取 Oracle Cloud。若要註冊免費帳戶,請參閱開始使用 Oracle Cloud Infrastructure Free Tier 。
- 它使用 Oracle Cloud Infrastructure 憑證、租用戶及區間的範例值。完成實驗室時,請以雲端環境特有的值取代這些值。
在 OCI 中啟用 Amazon S3 相容後端的 Terraform 狀態檔鎖定
簡介
在雲端運算的動態世界中,基礎架構即程式碼 (IaC) 已成為尋求有效管理基礎架構組織的重要方法。IaC 的主要優勢在於它能夠促進一致性、自動化、版本控制和協作,使其成為雲端原生 IT 策略不可或缺的元素。
Terraform 作為著名的 IaC 工具,它會將基礎架構物件及其相依性的描述儲存在名為 terraform.tfstate
的組態檔中。在多個團隊成員管理雲端基礎架構的協作環境中,將 terraform.tfstate
儲存在本機會變得充滿挑戰。為解決此問題,Terraform 提供一個稱為「遠端後端」的功能,可在共用位置啟用狀態檔的儲存。部分後端在執行 plan
或 apply
作業時支援 tfstate 鎖定,以確保資料完整性並避免發生衝突。
本教學課程將著重於如何設定 S3 相容後端和 ScyllaDB 的 DynamoDB 相容 API 以啟用狀態檔鎖定。
目標
-
使用 Docker Compose 將 ScyllaDB 部署至執行處理。
-
設定 Terraform S3 相容後端以支援
tfstate
檔案鎖定。
必要條件
方法 1:自動部署
按一下下方的部署至 Oracle Cloud ,輸入必要的詳細資訊,然後按一下套用。
方法 2:手動部署
工作 1:設定 ScyllaDB 並啟用 DynamoDB 相容的 API
我們將建立以 ARM 為基礎的執行處理、安裝 Docker,以及設定和執行 ScyllaDB。
作業 1.1:佈建新的執行處理
-
瀏覽至 OCI 主控台中的執行處理頁面,然後按一下建立執行處理。
-
請考慮下列建議,輸入必要的組態參數。
-
影像:
Oracle Linux 8
-
資源配置:
VM.Standard.A1.Flex (1 OCPU, 6 GB RAM)
-
主要 VNIC :
Public Subnet & Assign Public IPv4 Address
(將用於 SSH 連線)
記下執行處理的公用和專用 IP 位址。
-
Task 1.2:安裝 Docker
-
透過 SSH 連線至執行處理。
$ ssh opc@<public-ip-address-of-the-instance>
-
安裝 Docker Engine、containerd 以及 Docker Compose。
sudo yum install -y yum-utils sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin sudo systemctl start docker.service sudo systemctl enable docker.service sudo usermod -aG docker opc
-
重新連線 SSH 階段作業並驗證 Docker 的成功安裝。
docker run hello-world # Unable to find image 'hello-world:latest' locally # latest: Pulling from library/hello-world # 70f5ac315c5a: Pull complete # Digest: sha256:3155e04f30ad5e4629fac67d6789f8809d74fea22d4e9a82f757d28cee79e0c5 # Status: Downloaded newer image for hello-world:latest # Hello from Docker! # This message shows that your installation appears to be working correctly.
作業 1.3:產生客戶秘密金鑰
必須提供客戶秘密金鑰,才能使用 S3 相容 API 存取 OCI 物件儲存。
-
瀏覽至 OCI 主控台中的使用者設定檔頁面,然後選取客戶秘密金鑰。
-
產生新金鑰、複製秘密金鑰值,然後按一下關閉。
-
複製存取金鑰值 (此清單中的第二欄與客戶秘密金鑰)。
工作 1.4:設定並啟動 ScyllaDB
-
建立部署目錄
s3-lock
。mkdir s3-lock cd s3-lock
-
使用下列指令建立
.env
。AWS_ACCESS_KEY_ID='<ACCESS_KEY>' AWS_SECRET_ACCESS_KEY='<SECRET_KEY>' TF_STATE_TABLE='s3-locking-demo'
注意:Docker 將使用
.env
檔案來設定 ScyllaDB。 -
使用下列指令在
scylladb
目錄中建立scylladb.Dockerfile
檔案。FROM scylladb/scylla:latest RUN echo "alternator_enforce_authorization: true" >> /etc/scylla/scylla.yaml ENTRYPOINT ["/docker-entrypoint.py"]
-
使用下列指令在
s3-lock
目錄中建立docker-compose.yaml
檔案。version: "3.3" services: scylladb: build: dockerfile: scylladb.Dockerfile context: ./scylladb image: "local-scylla:latest" container_name: "scylladb" restart: always command: ["--alternator-port=8000", "--alternator-write-isolation=always"] ports: - "8000:8000" - "9042:9042" scylladb-load-user: image: "scylladb/scylla:latest" container_name: "scylladb-load-user" depends_on: - scylladb entrypoint: /bin/bash -c "sleep 60 && echo loading cassandra keyspace && cqlsh scylladb -u cassandra -p cassandra \ -e \"INSERT INTO system_auth.roles (role,can_login,is_superuser,member_of,salted_hash) \ VALUES ('${AWS_ACCESS_KEY_ID}',True,False,null,'${AWS_SECRET_ACCESS_KEY}');\"" scylladb-create-table: image: "amazon/aws-cli" container_name: "create_table" depends_on: - scylladb env_file: .env entrypoint: /bin/sh -c "sleep 70 && aws dynamodb create-table --table-name ${TF_STATE_TABLE} \ --attribute-definitions AttributeName=LockID,AttributeType=S \ --key-schema AttributeName=LockID,KeyType=HASH --billing-mode=PAY_PER_REQUEST \ --region 'None' --endpoint-url=http://scylladb:8000"
-
複查目錄結構。
$ tree -a . . ├── docker-compose.yaml ├── .env └── scylladb └── scylladb.Dockerfile 1 directory, 3 files
-
啟動 ScyllaDB 服務。
docker compose up -d
-
允許連接埠
8000
的內送連線。sudo firewall-cmd --add-port 8000/tcp --permanent
-
驗證 ScyllaDB 的連線。
-
安裝
python3-pip
和boto3
套裝軟體。sudo yum install -y python3-pip python3 -m pip install --user boto3
-
使用下列指令建立
script.py
檔案。import boto3 endpoint_url = 'http://localhost:8000' aws_access_key_id = '<ACCESS_KEY>' aws_secret_access_key = '<SECRET_KEY>' table_name = "s3-locking-demo" client = boto3.client('dynamodb', endpoint_url=endpoint_url, region_name="None", aws_access_key_id=aws_access_key_id, aws_secret_access_key=aws_secret_access_key) response = client.describe_table(TableName=table_name) print(response["Table"]["TableName"], response["Table"]["TableStatus"])
-
使用下列命令來執行命令檔。
python3 script.py
如果命令檔執行傳回
s3-locking-demo ACTIVE
,則會如預期般運作。 -
作業 2:設定 OCI API 閘道以保護與 ScyllaDB DynamoDB 相容 API 的連線
在這項任務中,我們將設定 OCI API 閘道利用使用者與 ScyllaDB 之間的 TLS 加密。
作業 2.1:建立新的 API 閘道
-
瀏覽至 OCI 主控台中的 API 閘道頁面,然後按一下建立閘道。
-
名稱:
s3-locking
-
類型:
public
-
網路:與 ScyllaDB 執行處理相同的 VCN 和子網路
-
憑證:
Default (*.oci.oci-customer.com)
-
-
寫下與新建 API 閘道關聯的主機名稱。當您按一下新建立的 API 閘道資源時,主機名稱會顯示在閘道資訊頁籤中。
例如:
fj4etyuvz3s57jdsadsadsadsa.apigateway.eu-frankfurt-1.oci.customer-oci.com
作業 2.2:建立新的 API 閘道部署
-
建立新部署。
-
按一下新建立的 API 閘道,然後在左側功能表中,按一下資源下的部署。
-
按一下建立建置,然後使用下列資訊建立新的建置。
-
基本資訊
-
名稱:
default
-
路徑前置碼:
/
-
-
認證:沒有認證
-
路由
-
路徑:
/{requested_path*}
-
方法:
ANY
-
後端類型:
HTTP
-
URL :
http://<private_ip_address_of_the_instance>:8000/${request.path[requested_path]}
-
-
-
前往路由要求原則、標頭轉換,然後按一下新增。
-
動作:
Set
-
行為:
Overwrite
-
標頭名稱:
Host
-
值:
<API Gateway hostname>
(例如:fj4etyuvz3s57jdsadsadsadsa.apigateway.eu-frankfurt-1.oci.customer-oci.com
)
-
-
複查新部署的詳細資訊,然後按一下建立。
-
-
設定子網路安全清單,以允許對連接埠
8000
進行傳入和傳出連線。-
使用下列步驟取得配置給使用中子網路的 CIDR 區塊。
-
使用下列步驟識別與執行處理所使用子網路關聯的安全清單。
-
按一下已經與子網路關聯的預設安全清單,然後新增下列規則。
-
傳入
-
來源 CIDR :
0.0.0.0/0
-
協定:
TCP
-
目標連接埠範圍:
443
-
說明:
Ingress Access to the API Gateway
-
-
傳入
-
來源 CIDR :
<subnet CIDR>
-
協定:
TCP
-
目標連接埠範圍:
8000
-
說明:
Ingress connection to the ScyllaDB
-
-
傳出
-
目的地 CIDR :
<subnet CIDR>
-
協定:
TCP
-
目標連接埠範圍:
8000
-
說明:
Egress connection from the API Gateway backend to ScyllaDB
-
-
-
工作 2.3:透過 API 閘道驗證 ScyllaDB 的連線
-
更新
script.py
檔案中的endpoint_url
以使用 API 閘道主機名稱。例如:endpoint_url = "https://fj4etyuvz3s57jdsadsadsadsa.apigateway.eu-frankfurt-1.oci.customer-oci.com"
-
執行命令檔以測試公用端點的連線。
python3 script.py s3-locking-demo ACTIVE
工作 3:使用 S3 相容 API 時測試 terraform.tfstate
檔案鎖定
我們會在想要執行 terraform 程式碼的執行處理上執行下列步驟。
-
複製以下各行並建立
main.tf
檔案。resource "null_resource" "hello_world" { provisioner "local-exec" { command = "echo Hello World" } provisioner "local-exec" { command = "echo 'sleeping for 30 seconds';sleep 30;echo 'done';" } triggers = { run_always = "${timestamp()}" } }
-
設定 S3 後端。
terraform { backend "s3" { bucket = "<bucket-name>" # e.g.: bucket = "sample-bucket" region = "<oci-region>" # e.g.: region = "eu-frankfurt-1" skip_region_validation = true skip_credentials_validation = true skip_metadata_api_check = true # skip_requesting_account_id = true # skip_s3_checksum = true force_path_style = true # use_path_style = true # insecure = true # For best practice on how to set credentials access: https://developer.hashicorp.com/terraform/language/settings/backends/s3#access_key access_key = "<ACCESS_KEY>" secret_key = "<SECRET_KEY>" # endpoints = { # # To determine <objectostrage_namespace> access: https://docs.oracle.com/en-us/iaas/Content/Object/Tasks/understandingnamespaces.htm # s3 = "https://<objectstorage_namespace>.compat.objectstorage.<oci-region>.oraclecloud.com" # # e.g.: s3 = https://axaxnpcrorw5.compat.objectstorage.eu-frankfurt-1.oraclecloud.com # # ScyllaDB TLS endpoint, configured using the API Gateway: # dynamodb = "https://<API_Gateway_hostname>" # # e.g.: dynamodb = "https://fj4etyuvz3s57jdsadsadsadsa.apigateway.eu-frankfurt-1.oci.customer-oci.com" # } # ScyllaDB TLS endpoint, configured using the API Gateway: dynamodb_endpoint = "https://<API_Gateway_hostname>" # e.g.: dynamodb_endpoint = "https://fj4etyuvz3s57jdsadsadsadsa.apigateway.eu-frankfurt-1.oci.customer-oci.com" key = "demo.tfstate" # the name of the tfstate file dynamodb_table = "s3-locking-demo" # the name of the table in the ScyllaDB } }
-
使用
terraform init
指令初始化工作目錄。$ terraform init Initializing the backend... Successfully configured the backend "s3"! Terraform will automatically use this backend unless the backend configuration changes. Initializing provider plugins... - Finding latest version of hashicorp/null... - Installing hashicorp/null v3.2.2... - Installed hashicorp/null v3.2.2 (signed by HashiCorp) Terraform has created a lock file .terraform.lock.hcl to record the provider selections it made above. Include this file in your version control repository so that Terraform can guarantee to make the same selections by default when you run "terraform init" in the future. Terraform has been successfully initialized!
-
執行
terraform apply
。$ terraform apply 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: # null_resource.hello_world will be created + resource "null_resource" "hello_world" { + id = (known after apply) + triggers = { + "run_always" = (known after apply) } } Plan: 1 to add, 0 to change, 0 to destroy. Do you want to perform these actions? Terraform will perform the actions described above. Only 'yes' will be accepted to approve. Enter a value: yes null_resource.hello_world: Creating... null_resource.hello_world: Provisioning with 'local-exec'... null_resource.hello_world (local-exec): Executing: ["/bin/sh" "-c" "echo Hello World"] null_resource.hello_world (local-exec): Hello World null_resource.hello_world: Provisioning with 'local-exec'... null_resource.hello_world (local-exec): Executing: ["/bin/sh" "-c" "echo 'sleeping for 30 seconds';sleep 30;echo 'done';"] null_resource.hello_world (local-exec): sleeping for 30 seconds null_resource.hello_world: Still creating... [10s elapsed] null_resource.hello_world: Still creating... [20s elapsed] null_resource.hello_world: Still creating... [30s elapsed] null_resource.hello_world (local-exec): done null_resource.hello_world: Creation complete after 30s [id=5722520729023050684] Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
-
測試
terraform.tfstate
檔案鎖定。如果您在執行工作 3.4 時嘗試執行terraform plan
或terraform apply
,您的要求將會被拒絕。$ terraform apply ╷ │ Error: Error acquiring the state lock │ │ Error message: operation error DynamoDB: PutItem, https response error StatusCode: 400, RequestID: , │ ConditionalCheckFailedException: Failed condition. │ Lock Info: │ ID: 69309f13-d9fc-8c6b-9fbe-73639b340539 │ Path: sample-bucket/demo.tfstate │ Operation: OperationTypeApply │ Who: use │ Version: 1.6.4 │ Created: 2023-12-14 11:31:30.291168816 +0000 UTC │ Info: │ │ │ Terraform acquires a state lock to protect the state from being written │ by multiple users at the same time. Please resolve the issue above and try │ again. For most commands, you can disable locking with the "-lock=false" │ flag, but this is not recommended.
-
使用 DynamoDB API 管理 ScyllaDB 表格中的項目。如果您需要列出 DynamoDB 表格中的項目或手動移除項目,您可以在
script.py
檔案的結尾新增下列行。scan_response = client.scan( TableName=table_name, ) print(scan_response) entry_to_delete = input("what is the LockID value you would like to delete? ") delete_response = client.delete_item( Key={ 'LockID': { 'S': f'{entry_to_delete}', }, }, TableName=table_name ) print(delete_response)
注意: this 命令檔提供更多功能。
相關連結
認可
- 作者 - Andrei Ilas (主要雲端架構師)
其他學習資源
瀏覽 docs.oracle.com/learn 的其他實驗室,或前往 Oracle Learning YouTube 頻道存取更多免費學習內容。此外,請造訪 education.oracle.com/learning-explorer 以成為 Oracle Learning Explorer。
如需產品文件,請造訪 Oracle Help Center 。
Enable Terraform State File Locking with Amazon S3 Compatible Backend in OCI
F90992-01
January 2024
Copyright © 2024, Oracle and/or its affiliates.