โดยปกติ ผลของการทำงานของ terraform จะถูกจะถูกเขียนลงไฟล์ที่เรียกว่า terraform state จะถูกเก็บไว้ในไฟล์ที่ชื่อว่า terraform.tfstate ในไฟล์นั้นมีรายละเอียดต่าง ๆ อย่างครบถ้วนของ resource ที่ถูกระบุไว้ใน terraform configuration file ดังนั้นมีการสร้าง resource จำเป็นต้องใช้ข้อมูลที่เป็น sensitive information เช่นพวก password, private key ข้อมูลเหล่านี้ก็จะถูกเก็บไว้ใน tarraform state ไปด้วย ใครก็ตามที่เข้าถึงไฟล์นี้ได้ หรือจัดเก็บไว้แบบที่ไม่ระมัดระวัง ข้อมูลที่เป็น sensitive information อาจจะเกิดการรั่วไหลไปได้ ดังนั้น การบริหารจัดการ terraform state จึงมีการแนะนำให้ไปจัดกเก็บไว้ในส่วนที่เรียกว่า backend ซึ่งจะเป็นที่ที่จะบอกว่า เมื่อ terraform ทำงานเสร็จเรียบร้อย จะจัดเก็บ terraform state ไว้ด้วยวิธีการอะไร ซึ่งโดยปกติ terraform จะเรียกใช้งาน backend ที่ชื่อว่า local ซึ่งก็จะเป็นการจัดเก็บในรูปแบบของไฟล์ไว้ที่ working directory
Backend เก็บที่ไหนได้บ้าง
- local
- azurerm - Azure Blob Storage
- consul - Consul KV store
- cos - Tencent Cloud Object Storage
- gcs - Google Cloud Storage
- http - simple REST client
- kubernetes - Kubernetes secret
- oss - Alibaba Cloud OSS
- pg - Postgres database
- s3 - Amazon S3
ทดลองเก็บไว้ที่ postgres
ลองหยิบ postgres database มาศึกษาดูแนวคิดในการใช้ backend เพื่อเก็บ terraform state ซึ่งหาข้อมูลได้จาก postgres backend
- สร้าง postgres database server ในกรณีนี้จะใช้ container technology เป็นไว้ที่ server ชื่อว่า tfstate.d8k.dev และกำหนดให้ postgres database ทำงานที่ port TCP/5433
$ mkdir tfstate $ cd tfstate $ cat > docker-compose.yaml <<- EOF services: db: image: postgres restart: always ports: - 5433:5432 environment: POSTGRES_USER: tf POSTGRES_PASSWORD: mypsddeotf POSTGRES_DB: tf_backend EOF $ docker-compose up -d Creating network "tfstate_default" with the default driver Creating tfstate_db_1 ... done
- สร้าง terraform configuration file เพื่อทำการทดสอบ โดยเลือกให้ใช้ provider ที่ชื่อว่า kreuzwerker/docker โดยจะให้สร้าง container 1 ตัวชื่อว่า myapp
ส่วนสำคัญที่จะกำหนดให้ Terraform ไปเรียกใช้ backend ที่เป็น postgres จะอยู่ภายใน terraform block ตรงที่ระบุว่าเป็น backend เป็น pg และระบุรายละเอียดของ backend ผ่านตัวแปรที่ชื่อว่า conn_str
หมายเหตุ: เครื่องที่ใช้ในการทดสอบ ต้องติดตั้ง terraform และมี Docker ทำงานอยู่เรียบร้อยแล้วterraform { backend "pg" { conn_str = "postgres://tf:mypsddeotf@tfstate.d8k.dev:5433/tf_backend?sslmode=disable" } }
$ mkdir tf-docker $ cd tf-docker $ cat > main.tf <<EOF terraform { backend "pg" { conn_str = "postgres://tf:mypsddeotf@tfstate.d8k.dev:5433/tf_backend?sslmode=disable" } required_providers { docker = { source = "kreuzwerker/docker" } } } provider "docker" { host = "unix:///var/run/docker.sock" } resource "docker_image" "nginx" { name = "nginx" } resource "docker_container" "myapp" { name = "myapp" image = docker_image.nginx.image_id } $ terraform init Initializing the backend... Successfully configured the backend "pg"! Terraform will automatically use this backend unless the backend configuration changes. Initializing provider plugins... - Finding kreuzwerker/docker versions matching "3.0.2"... - Installing kreuzwerker/docker v3.0.2... - Installed kreuzwerker/docker v3.0.2 (self-signed, key ID BD080C4571C6104C) [... truncated output ...] EOF ## - ยืนยันว่ายังไม่มี container ที่ชื่อว่า myapp $ docker container ls -a | grep myapp $ terraform apply --auto-approve 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: # docker_container.myapp will be created + resource "docker_container" "myapp" { [... truncated output ...] $ docker container ls | grep myapp 28a46551b1a3 2a4fbb36e966 "/docker-entrypoint.…" 43 seconds ago Up 43 seconds 80/tcp myapp ## - ไม่พบไฟล์ terraform state $ ls -la terraform.tfstate ls: terraform.tfstate: No such file or directory ## - คำสั่งแสดงข้อมูล terraform state พบว่ามี resource อยู่ 2 ตัวตามที่ระบุไว้ใน main.tf $ terraform state list docker_container.myapp docker_image.nginx
- ทดลอง สร้าง working directory ที่ 2 โดยใช้ main.tf ตัวเดิม และให้แสดงค่า terraform state จะพบว่า ใน working directory ที่ 2 ก็จะมีข้อมูล terraform state อยู่เช่นเดียวกัน
$ mkdir test $ cp main.tf ./test $ terraform init Initializing the backend... Initializing provider plugins... - Reusing previous version of kreuzwerker/docker from the dependency lock file - Using previously-installed kreuzwerker/docker v3.0.2 Terraform has been successfully initialized! [... truncated output ...] $ terraform state list docker_container.myapp docker_image.nginx