แนวทางปฏิบัติที่ดีที่สุดเมื่อใช้ Terraform [ปิด]


112

ฉันอยู่ระหว่างการเปลี่ยนโครงสร้างพื้นฐานของเราให้กลายเป็นพื้นดิน แนวทางปฏิบัติที่ดีที่สุดในการจัดการไฟล์ Terraform และสถานะคืออะไร? ฉันรู้ว่าโครงสร้างพื้นฐานเป็นรหัสและฉันจะส่งไฟล์. tf ของฉันไปยัง git แต่ฉันจะผูกมัด tfstate ด้วยหรือไม่ ควรอยู่ที่ไหนสักแห่งเช่น S3 หรือไม่? ในที่สุดฉันก็ต้องการให้ CI จัดการทั้งหมดนี้ แต่มันยืดออกไปไกลและต้องการให้ฉันคิดหาชิ้นส่วนที่เคลื่อนไหวสำหรับไฟล์

ฉันแค่ต้องการดูว่าผู้คนที่นั่นใช้ประโยชน์จากสิ่งประเภทนี้ในการผลิตได้อย่างไร

คำตอบ:


85

ฉันยังอยู่ในสถานะของการย้ายโครงสร้างพื้นฐาน AWS ที่มีอยู่ไปยัง Terraform ดังนั้นฉันจะพยายามอัปเดตคำตอบเมื่อฉันพัฒนา

ฉันพึ่งพาตัวอย่าง Terraform อย่างเป็นทางการและการทดลองและข้อผิดพลาดหลายครั้งเพื่อดึงประเด็นที่ฉันไม่แน่ใจออกมา

.tfstate ไฟล์

สามารถใช้การกำหนดค่า Terraform เพื่อจัดเตรียมกล่องจำนวนมากบนโครงสร้างพื้นฐานที่แตกต่างกันซึ่งแต่ละกล่องอาจมีสถานะที่แตกต่างกัน เนื่องจากสามารถดำเนินการโดยคนหลายคนสถานะนี้ควรอยู่ในตำแหน่งที่รวมศูนย์ (เช่น S3) แต่ไม่ใช่คอมไพล์

นี้สามารถยืนยันได้มองหาที่ .gitignoreterraform

การควบคุมของนักพัฒนา

เป้าหมายของเราคือให้การควบคุมโครงสร้างพื้นฐานแก่นักพัฒนามากขึ้นในขณะที่รักษาการตรวจสอบทั้งหมด (บันทึกคอมไพล์) และความสามารถในการตรวจสอบการเปลี่ยนแปลง (คำขอดึง) ด้วยเหตุนี้เวิร์กโฟลว์โครงสร้างพื้นฐานใหม่ที่ฉันตั้งเป้าไว้คือ:

  1. รากฐานพื้นฐานของ AMI ทั่วไปที่มีโมดูลที่ใช้ซ้ำได้เช่นหุ่นเชิด
  2. โครงสร้างพื้นฐานหลักที่ DevOps จัดเตรียมโดยใช้ Terraform
  3. นักพัฒนาเปลี่ยนแปลงการกำหนดค่า Terraform ใน Git ตามต้องการ (จำนวนอินสแตนซ์ VPC ใหม่การเพิ่มภูมิภาค / โซนความพร้อมใช้งาน ฯลฯ )
  4. ผลักดันการกำหนดค่า Git และคำขอดึงที่ส่งให้สมาชิกของทีม DevOps ตรวจสอบความถูกต้อง
  5. หากได้รับอนุมัติให้เรียก webhook ไปที่ CI เพื่อสร้างและปรับใช้ (ไม่แน่ใจว่าจะแบ่งพาร์ติชันหลายสภาพแวดล้อมอย่างไรในขณะนี้)

แก้ไข 1 - อัปเดตสถานะปัจจุบัน

ตั้งแต่เริ่มคำตอบนี้ฉันได้เขียนรหัส TF จำนวนมากและรู้สึกสบายใจมากขึ้นในสถานการณ์ของเรา เราพบข้อบกพร่องและข้อ จำกัด ระหว่างทาง แต่ฉันยอมรับว่านี่เป็นลักษณะของการใช้ซอฟต์แวร์ใหม่ที่เปลี่ยนแปลงอย่างรวดเร็ว

เค้าโครง

เรามีโครงสร้างพื้นฐาน AWS ที่ซับซ้อนพร้อมด้วย VPC หลายตัวแต่ละตัวมีเครือข่ายย่อยหลายเครือข่าย กุญแจสำคัญในการจัดการสิ่งนี้อย่างง่ายดายคือการกำหนดอนุกรมวิธานที่ยืดหยุ่นซึ่งครอบคลุมภูมิภาคสภาพแวดล้อมบริการและเจ้าของซึ่งเราสามารถใช้เพื่อจัดระเบียบรหัสโครงสร้างพื้นฐานของเรา (ทั้งพื้นดินและหุ่น)

โมดูล

ขั้นตอนต่อไปคือการสร้างที่เก็บ git เดียวเพื่อจัดเก็บโมดูล Terraform ของเรา โครงสร้าง dir ระดับบนสุดของเราสำหรับโมดูลมีลักษณะดังนี้:

tree -L 1 .

ผลลัพธ์:

├── README.md
├── aws-asg
├── aws-ec2
├── aws-elb
├── aws-rds
├── aws-sg
├── aws-vpc
└── templates

แต่ละคนตั้งค่าเริ่มต้นที่ดี แต่แสดงให้เห็นว่าเป็นตัวแปรที่ "กาว" ของเราสามารถเขียนทับได้

กาว

เรามีที่เก็บข้อมูลที่สองglueซึ่งใช้ประโยชน์จากโมดูลที่กล่าวถึงข้างต้น วางไว้ตามเอกสารอนุกรมวิธานของเรา:

.
├── README.md
├── clientA
   ├── eu-west-1
      └── dev
   └── us-east-1
       └── dev
├── clientB
   ├── eu-west-1
      ├── dev
      ├── ec2-keys.tf
      ├── prod
      └── terraform.tfstate
   ├── iam.tf
   ├── terraform.tfstate
   └── terraform.tfstate.backup
└── clientC
    ├── eu-west-1
       ├── aws.tf
       ├── dev
       ├── iam-roles.tf
       ├── ec2-keys.tf
       ├── prod
       ├── stg
       └── terraform.tfstate
    └── iam.tf

ภายในระดับไคลเอนต์เรามี.tfไฟล์เฉพาะของบัญชี AWS ที่จัดเตรียมทรัพยากรทั่วโลก (เช่นบทบาท IAM) ต่อไปคือระดับภูมิภาคที่มีคีย์สาธารณะ EC2 SSH สุดท้ายในสภาพแวดล้อมของเรา ( dev, stg, prodฯลฯ ) จะ VPC การตั้งค่าการสร้างอินสแตนซ์และ peering การเชื่อมต่อของเรา ฯลฯ จะถูกเก็บไว้

หมายเหตุด้านข้าง:อย่างที่คุณเห็นฉันกำลังต่อต้านคำแนะนำของตัวเองข้างต้นterraform.tfstateในการคอมไพล์ นี่เป็นมาตรการชั่วคราวจนกว่าฉันจะย้ายไปใช้ S3 แต่เหมาะกับฉันเพราะตอนนี้ฉันเป็นนักพัฒนาเพียงคนเดียว

ขั้นตอนถัดไป

นี่ยังคงเป็นกระบวนการแบบแมนนวลและยังไม่ได้อยู่ใน Jenkins แต่เรากำลังย้ายโครงสร้างพื้นฐานที่ค่อนข้างใหญ่ซับซ้อนและจนถึงตอนนี้ก็ดี อย่างที่บอกข้อบกพร่องน้อย แต่ไปได้ดี!

แก้ไข 2 - การเปลี่ยนแปลง

เป็นเวลาเกือบหนึ่งปีแล้วที่ฉันเขียนคำตอบเริ่มต้นนี้และสถานะของ Terraform และตัวฉันเองก็เปลี่ยนไปอย่างมาก ตอนนี้ฉันในตำแหน่งใหม่โดยใช้ terraform การจัดการคลัสเตอร์ Azure และ terraform v0.10.7อยู่ในขณะนี้

สถานะ

มีคนบอกฉันหลายครั้งว่าไม่ควรเข้า Git - และถูกต้อง เราใช้สิ่งนี้เป็นมาตรการชั่วคราวกับทีมงานสองคนที่อาศัยการสื่อสารและระเบียบวินัยของนักพัฒนา ด้วยทีมงานที่มีขนาดใหญ่ขึ้นเราจึงใช้ประโยชน์จากสถานะระยะไกลใน S3 ได้อย่างเต็มที่ด้วยการล็อกโดย DynamoDB ตามหลักการแล้วสิ่งนี้จะถูกย้ายไปที่กงสุลตอนนี้เป็น v1.0 เพื่อตัดผู้ให้บริการคลาวด์ข้าม

โมดูล

ก่อนหน้านี้เราได้สร้างและใช้โมดูลภายใน ยังคงเป็นเช่นนั้น แต่ด้วยการถือกำเนิดและการเติบโตของรีจิสทรี Terraformเราจึงพยายามใช้สิ่งเหล่านี้เป็นฐานอย่างน้อยที่สุด

โครงสร้างไฟล์

ตำแหน่งใหม่มีอนุกรมวิธานง่ายมากมีเพียงสองสภาพแวดล้อม infx - และdev prodแต่ละตัวมีตัวแปรและเอาต์พุตของตัวเองโดยนำโมดูลของเราที่สร้างไว้ด้านบนกลับมาใช้ใหม่ remote_stateผู้ให้บริการยังช่วยในการเอาท์พุทใช้ทรัพยากรร่วมกันสร้างขึ้นระหว่างสภาพแวดล้อม สถานการณ์ของเราคือโดเมนย่อยในกลุ่มทรัพยากร Azure ที่แตกต่างกันไปจนถึง TLD ที่มีการจัดการทั่วโลก

├── main.tf
├── dev
   ├── main.tf
   ├── output.tf
   └── variables.tf
└── prod
    ├── main.tf
    ├── output.tf
    └── variables.tf

การวางแผน

อีกครั้งด้วยความท้าทายพิเศษของทีมแบบกระจายตอนนี้เราบันทึกผลลัพธ์ของterraform planคำสั่งไว้เสมอ เราสามารถตรวจสอบและรู้ว่าจะดำเนินการอะไรโดยไม่ต้องเสี่ยงกับการเปลี่ยนแปลงบางอย่างระหว่างขั้นตอนplanและapplyขั้นตอน (แม้ว่าการล็อกจะช่วยในเรื่องนี้ก็ตาม) อย่าลืมลบไฟล์แผนนี้เนื่องจากอาจมีตัวแปร "ความลับ" ที่เป็นข้อความธรรมดา

โดยรวมแล้วเรามีความสุขมากกับ Terraform และยังคงเรียนรู้และปรับปรุงคุณสมบัติใหม่ที่เพิ่มเข้ามา


คุณมีโชค / ปัญหาใด ๆ ตั้งแต่คำตอบนี้หรือไม่? ดูเหมือนคุณจะทำในสิ่งที่ฉันตั้งใจจะทำมาก แต่คุณอาจจะอยู่ไกลกว่าฉัน
Marc Young

3
ฉันสงสัยว่าทำไมคุณถึงคิดว่าไม่ควรเก็บไฟล์ tfstate ไว้ใน git? เป็นเพียงเพราะสถานะเก่าไม่คุ้มค่าที่จะประหยัดหรือมีปัญหาอื่น ๆ หรือไม่?
agbodike

3
@agbodike - เมื่อทำงานในฐานะนักพัฒนาคนเดียวหรือเป็นส่วนหนึ่งของ tfstate ทีมขนาดเล็กมากสามารถเก็บไว้ใน git ได้ตราบเท่าที่มีความมุ่งมั่นอย่างสม่ำเสมอและผลักดันเพื่อหลีกเลี่ยงความขัดแย้ง ขั้นตอนต่อไปของฉันคือการตั้งค่าตามเอกสารสถานะระยะไกลใน S3 (ซึ่งกล่าวว่า: "ทำให้การทำงานกับ Terraform ในทีมมีความซับซ้อนเนื่องจากเป็นแหล่งที่มาของความขัดแย้งในการผสานบ่อยครั้งสถานะระยะไกลช่วยบรรเทาปัญหาเหล่านี้") . เช่นเดียวกับสิ่งต่างๆส่วนใหญ่แม้ว่าการสื่อสารในทีมที่ดีจะช่วยบรรเทาปัญหาส่วนใหญ่ / ทั้งหมดโดยไม่คำนึงถึงกลยุทธ์ที่จะรักษาสถานะ :-)
Ewan

1
@ the0ther - ฉันกลัวว่าที่เก็บข้อมูลหลักของฉันจะเป็นกรรมสิทธิ์ แต่ฉันกำลังทำงานกับที่เก็บข้อมูลส่วนตัวที่ฉันจะเปิดเผยต่อสาธารณะในอนาคตอันใกล้นี้
Ewan

2
โชคดีใน Git repo @Ewan หรือไม่? ฉันชอบที่จะเห็นว่าคุณกำลังทำอะไรอยู่
David

85

เราใช้ Terraform อย่างหนักและการตั้งค่าที่เราแนะนำมีดังต่อไปนี้:

เค้าโครงไฟล์

เราขอแนะนำอย่างยิ่งให้จัดเก็บโค้ด Terraform สำหรับแต่ละสภาพแวดล้อมของคุณ (เช่น stage, prod, qa) ในชุดเทมเพลตแยกกัน (และ.tfstateไฟล์แยกกัน) นี่เป็นสิ่งสำคัญเพื่อให้สภาพแวดล้อมที่แยกจากกันของคุณถูกแยกออกจากกันในขณะที่ทำการเปลี่ยนแปลง มิฉะนั้นในขณะที่กำลังส่งรหัสบางอย่างในการจัดเตรียมการจัดเตรียมบางอย่างก็ง่ายเกินไป ดูTerraform, VPC และเหตุผลที่คุณต้องการไฟล์ tfstate ต่อ envเพื่อการสนทนาที่มีสีสันว่าทำไม

ดังนั้นเค้าโครงไฟล์ทั่วไปของเราจึงมีลักษณะดังนี้:

stage
   main.tf
   vars.tf
   outputs.tf
prod
   main.tf
   vars.tf
   outputs.tf
global
   main.tf
   vars.tf
   outputs.tf

รหัส Terraform ทั้งหมดสำหรับขั้นตอน VPC จะเข้าไปในstageโฟลเดอร์รหัสทั้งหมดสำหรับ prod VPC จะเข้าไปในprodโฟลเดอร์และรหัสทั้งหมดที่อยู่นอก VPC (เช่นผู้ใช้ IAM หัวข้อ SNS ถัง S3) จะเข้าไปในglobalโฟลเดอร์ .

โปรดทราบว่าโดยปกติแล้วเราจะแบ่งโค้ด Terraform ออกเป็น 3 ไฟล์:

  • vars.tf: ตัวแปรอินพุต
  • outputs.tf: ตัวแปรเอาต์พุต
  • main.tf: ทรัพยากรที่แท้จริง

โมดูล

โดยทั่วไปเรากำหนดโครงสร้างพื้นฐานของเราในสองโฟลเดอร์:

  1. infrastructure-modules: โฟลเดอร์นี้มีโมดูลขนาดเล็กที่ใช้ซ้ำได้ ให้คิดว่าแต่ละโมดูลเป็นพิมพ์เขียวสำหรับวิธีสร้างโครงสร้างพื้นฐานชิ้นเดียวเช่น VPC หรือฐานข้อมูล
  2. infrastructure-live: โฟลเดอร์นี้มีโครงสร้างพื้นฐานที่ใช้งานจริงซึ่งสร้างขึ้นโดยการรวมโมดูลเข้าinfrastructure-modulesด้วยกัน คิดว่ารหัสในโฟลเดอร์นี้เป็นบ้านจริงที่คุณสร้างจากพิมพ์เขียวของคุณ

โมดูล terraformเป็นเพียงชุดใด ๆ ของแม่ terraform ในโฟลเดอร์ ยกตัวอย่างเช่นเราอาจจะมีโฟลเดอร์ที่เรียกว่าvpcในinfrastructure-modulesกำหนดว่าทุกตารางเส้นทางเครือข่ายย่อยเกตเวย์ ACLs ฯลฯ สำหรับ VPC เดียว:

infrastructure-modules
   vpc
     main.tf
     vars.tf
     outputs.tf

จากนั้นเราสามารถใช้โมดูลนั้นในinfrastructure-live/stageและinfrastructure-live/prodเพื่อสร้างสเตจและผลิต VPCs ตัวอย่างเช่นนี่คือสิ่งที่infrastructure-live/stage/main.tfอาจมีลักษณะดังนี้:

module "stage_vpc" {
  source = "git::git@github.com:gruntwork-io/module-vpc.git//modules/vpc-app?ref=v0.0.4"

  vpc_name         = "stage"
  aws_region       = "us-east-1"
  num_nat_gateways = 3
  cidr_block       = "10.2.0.0/18"
}

ในการใช้โมดูลคุณใช้moduleทรัพยากรและชี้sourceฟิลด์ไปที่เส้นทางภายในฮาร์ดไดรฟ์ของคุณ (เช่นsource = "../infrastructure-modules/vpc") หรือตามตัวอย่างข้างต้นคือ Git URL (ดูที่มาของโมดูล ) ข้อดีของ Git URL คือเราสามารถระบุ git sha1 หรือ tag ( ref=v0.0.4) ที่เฉพาะเจาะจงได้ ตอนนี้เราไม่เพียง แต่กำหนดโครงสร้างพื้นฐานของเราเป็นโมดูลขนาดเล็กจำนวนมากเท่านั้น แต่เราสามารถสร้างเวอร์ชันของโมดูลเหล่านั้นและอัปเดตหรือย้อนกลับอย่างระมัดระวังได้ตามต้องการ

เราได้สร้างชุดโครงสร้างพื้นฐานที่ใช้ซ้ำได้ทดสอบและจัดทำเป็นเอกสารจำนวนมากสำหรับการสร้าง VPCs คลัสเตอร์ Docker ฐานข้อมูลและอื่น ๆ และภายใต้ประทุนนั้นส่วนใหญ่เป็นเพียงโมดูล Terraform เวอร์ชัน

สถานะ

เมื่อคุณใช้ Terraform เพื่อสร้างทรัพยากร (เช่นอินสแตนซ์ EC2, ฐานข้อมูล, VPCs) จะบันทึกข้อมูลเกี่ยวกับสิ่งที่สร้างขึ้นใน.tfstateไฟล์ ในการเปลี่ยนแปลงทรัพยากรเหล่านั้นทุกคนในทีมของคุณจำเป็นต้องเข้าถึง.tfstateไฟล์เดียวกันนี้แต่คุณไม่ควรตรวจสอบใน Git (ดูคำอธิบายที่นี่สำหรับคำอธิบาย )

แต่ขอแนะนำให้จัดเก็บ.tfstateไฟล์ใน S3 โดยเปิดใช้งานTerraform Remote Stateซึ่งจะผลัก / ดึงไฟล์ล่าสุดโดยอัตโนมัติทุกครั้งที่คุณเรียกใช้ Terraform ตรวจสอบให้แน่ใจว่าได้เปิดใช้งานการกำหนดเวอร์ชันในที่เก็บข้อมูล S3 ของคุณเพื่อให้คุณสามารถย้อนกลับไปใช้.tfstateไฟล์รุ่นเก่าได้ในกรณีที่เวอร์ชันล่าสุดเสียหาย อย่างไรก็ตามหมายเหตุสำคัญ: terraform ไม่ได้ให้ล็อค ดังนั้นหากสมาชิกในทีมสองคนทำงานterraform applyพร้อมกันใน.tfstateไฟล์เดียวกันพวกเขาอาจเขียนทับการเปลี่ยนแปลงของกันและกัน

เพื่อแก้ปัญหานี้เราได้สร้างเครื่องมือโอเพนซอร์สที่เรียกว่าTerragruntซึ่งเป็นกระดาษห่อหุ้มแบบบางสำหรับ Terraform ที่ใช้ Amazon DynamoDB ในการล็อก (ซึ่งควรจะฟรีสำหรับทีมส่วนใหญ่) ตรวจสอบเพิ่มการล็อกสถานะระยะไกลอัตโนมัติและการกำหนดค่าไปยัง Terraform ด้วย Terragruntสำหรับข้อมูลเพิ่มเติม

อ่านเพิ่มเติม

เราเพิ่งเริ่มบล็อกโพสต์ชุดหนึ่งชื่อคำแนะนำที่ครอบคลุมสำหรับ Terraformซึ่งอธิบายรายละเอียดเกี่ยวกับแนวทางปฏิบัติที่ดีที่สุดทั้งหมดที่เราได้เรียนรู้สำหรับการใช้ Terraform ในโลกแห่งความเป็นจริง

อัปเดต: คำแนะนำที่ครอบคลุมสำหรับซีรี่ส์บล็อกโพสต์ Terraform ได้รับความนิยมมากจนเราขยายเป็นหนังสือชื่อTerraform: Up & Running !


ฉันคิดว่านี่เป็นคำตอบที่ถูกต้อง ใช้โมดูลกำหนดเวอร์ชันและแยกสภาพแวดล้อม
wrangler

ขั้นตอนการกำหนดค่าระยะไกลจำเป็นต้องรันซ้ำทุกครั้งที่คุณต้องการทำงานกับส่วนประกอบพื้นผิว / สภาพแวดล้อม / โมดูล / อะไรก็ตามถ้าไม่ใช้ terragrunt หรือเครื่องห่ออื่น ๆ
jmreicha

@jmreicha: คุณต้องเรียกใช้remote configหากคุณเพิ่งตรวจสอบการกำหนดค่า Terraform ของคุณหรือหากคุณต้องการเปลี่ยนการกำหนดค่าระยะไกลก่อนหน้านี้ Terraform 0.9 จะนำเสนอแนวคิดbackendsซึ่งจะช่วยลดความซับซ้อนของสิ่งนี้ได้มาก ดูPR นี้สำหรับรายละเอียดเพิ่มเติม
Yevgeniy Brikman

เพื่อให้ฉันเข้าใจ - ฉันกำลังทำงานใน 'เวที' สภาพแวดล้อม แต่จากนั้นก็เริ่มทำงานกับ 'prod' ฉันจะต้องรันremote configคำสั่งอีกครั้งเพื่อชี้ไปที่สถานะแยง สมมติว่าสถานะที่แตกต่างกันต่อสภาพแวดล้อม นั่นถูกต้องใช่ไหม? ฉันหวังว่าจะได้ v0.9
jmreicha

หากคุณกำลังจะปรับใช้ชุด.tfไฟล์เดียวกันกับสองสภาพแวดล้อมที่แตกต่างกันใช่คุณจะต้องเรียกใช้remote configทุกครั้งที่เปลี่ยน เห็นได้ชัดว่านี่เป็นข้อผิดพลาดได้ง่ายดังนั้นฉันไม่แนะนำให้ใช้เทคนิคนี้จริงๆ ลองดูรูปแบบไฟล์ Terraform ที่แนะนำในบล็อกโพสต์นี้พร้อมวิธีใช้โมดูล Terraform ในบล็อกโพสต์นี้
Yevgeniy Brikman

9

ก่อนหน้านี้remote configอนุญาตสิ่งนี้ แต่ตอนนี้ถูกแทนที่ด้วย " แบ็กเอนด์ " ดังนั้นรีโมต Terraform จึงไม่สามารถใช้งานได้อีกต่อไป

terraform remote config -backend-config="bucket=<s3_bucket_to_store_tfstate>" -backend-config="key=terraform.tfstate" -backend=s3
terraform remote pull
terraform apply
terraform remote push

ดูรายละเอียดในเอกสาร


แหล่งที่มาระยะไกลจำเป็นต้องได้รับการกำหนดค่าใหม่ทุกครั้งที่คุณต้องการทำงานกับส่วนประกอบพื้นผิว / สภาพแวดล้อม / โมดูล / อะไรก็ตาม?
jmreicha

6

ครอบคลุมในเชิงลึกมากขึ้นโดย @Yevgeny Brikman แต่ตอบคำถามของ OP โดยเฉพาะ:

แนวทางปฏิบัติที่ดีที่สุดในการจัดการไฟล์ Terraform และสถานะคืออะไร?

ใช้ git สำหรับไฟล์ TF แต่อย่าตรวจสอบไฟล์สถานะใน (เช่น tfstate) แทนที่จะใช้Terragruntสำหรับการซิงค์ / ล็อกไฟล์สถานะไปยัง S3

แต่ฉันยอมรับ tfstate ด้วยหรือไม่?

ไม่

ควรอยู่ที่ไหนสักแห่งเช่น S3 หรือไม่?

ใช่


2

ฉันรู้ว่ามีคำตอบมากมายที่นี่ แต่แนวทางของฉันค่อนข้างแตกต่างกัน

   Modules
   Environment management 
   Separation of duties

โมดูล

  1. สร้างโมดูลสำหรับการรวบรวมทรัพยากรแบบลอจิคัล ตัวอย่าง: หากเป้าหมายของคุณคือการปรับใช้ API ซึ่งต้องใช้ DB, HA VMs, การปรับขนาดอัตโนมัติ, DNS, PubSub และที่เก็บอ็อบเจ็กต์ทรัพยากรทั้งหมดเหล่านี้ควรได้รับการเทมเพลตในโมดูลเดียว
  2. หลีกเลี่ยงการสร้างโมดูลที่ใช้ทรัพยากรเดียว สิ่งนี้ทำได้และทำได้แล้วและโมดูลจำนวนมากในรีจิสทรีก็ทำเช่นนี้ได้ แต่เป็นการปฏิบัติที่ช่วยในการเข้าถึงทรัพยากรมากกว่าการจัดโครงสร้างพื้นฐาน ตัวอย่าง: โมดูลสำหรับ AWS EC2 ช่วยให้ผู้ใช้เข้าถึง EC2 โดยทำให้การกำหนดค่าที่ซับซ้อนง่ายขึ้นในการเรียกใช้ แต่โมดูลดังตัวอย่างใน 1 ช่วยผู้ใช้เมื่อจัดเตรียมแอปพลิเคชันส่วนประกอบหรือโครงสร้างพื้นฐานที่ขับเคลื่อนด้วยบริการ
    1. หลีกเลี่ยงการประกาศทรัพยากรในพื้นที่ทำงานของคุณ ข้อมูลเพิ่มเติมเกี่ยวกับการรักษารหัสของคุณให้เป็นระเบียบและเป็นระเบียบ เนื่องจากโมดูลมีการกำหนดเวอร์ชันได้ง่ายคุณจึงสามารถควบคุมรุ่นต่างๆได้มากขึ้น

การจัดการสิ่งแวดล้อม

IaC ทำให้กระบวนการ SDLC เกี่ยวข้องกับการจัดการโครงสร้างพื้นฐานและไม่ใช่เรื่องปกติที่จะคาดหวังว่าจะมีโครงสร้างพื้นฐานการพัฒนารวมถึงสภาพแวดล้อมแอปพลิเคชันการพัฒนา

  1. อย่าใช้โฟลเดอร์เพื่อจัดการสภาพแวดล้อม IaC ของคุณ สิ่งนี้นำไปสู่การล่องลอยเนื่องจากไม่มีเทมเพลตทั่วไปสำหรับโครงสร้างพื้นฐานของคุณ
  2. ใช้พื้นที่ทำงานและตัวแปรเดียวเพื่อควบคุมข้อกำหนดสภาพแวดล้อม ตัวอย่าง: เขียนโมดูลของคุณเพื่อที่เมื่อคุณเปลี่ยนตัวแปรสภาพแวดล้อม (var.stage เป็นที่นิยม) แผนจะปรับเปลี่ยนให้เหมาะสมกับความต้องการของคุณ โดยทั่วไปสภาพแวดล้อมควรแตกต่างกันให้น้อยที่สุดโดยปริมาณการเปิดรับแสงและความจุมักจะเป็นการกำหนดค่าตัวแปร นักพัฒนาอาจปรับใช้ 1 VM พร้อม 1 คอร์และ 1GB RAM ในโทโพโลยีส่วนตัว แต่การผลิตอาจเป็น 3 VM ที่มี 2 คอร์และ 4GB RAM พร้อมโทโพโลยีสาธารณะเพิ่มเติม แน่นอนคุณสามารถมีรูปแบบที่หลากหลายมากขึ้น: dev อาจเรียกใช้กระบวนการฐานข้อมูลบนเซิร์ฟเวอร์เดียวกันกับแอปพลิเคชันเพื่อประหยัดต้นทุน แต่การใช้งานจริงอาจมีอินสแตนซ์ DB เฉพาะ ทั้งหมดนี้สามารถจัดการได้โดยการเปลี่ยนตัวแปรเดียวคำสั่งประกอบและการแก้ไข

การแบ่งแยกหน้าที่

หากคุณอยู่ในองค์กรขนาดเล็กหรือใช้โครงสร้างพื้นฐานส่วนบุคคลสิ่งนี้ไม่ได้ใช้ แต่จะช่วยให้คุณจัดการการดำเนินงานของคุณได้

  1. แบ่งโครงสร้างพื้นฐานของคุณตามหน้าที่ความรับผิดชอบหรือทีม ตัวอย่าง: การควบคุมไอทีส่วนกลางที่อยู่ภายใต้บริการที่ใช้ร่วมกัน (เครือข่ายเสมือน, เครือข่ายย่อย, ที่อยู่ IP สาธารณะ, กลุ่มบันทึก, ทรัพยากรการกำกับดูแล, ฐานข้อมูลที่เช่าหลายรายการ, คีย์ที่ใช้ร่วมกัน ฯลฯ ) ในขณะที่ทีม API ควบคุมเฉพาะทรัพยากรที่จำเป็นสำหรับบริการของตน (VMs, LBs PubSub ฯลฯ ) และใช้บริการ Central ITs ผ่านแหล่งข้อมูลและการค้นหาสถานะระยะไกล
    1. ควบคุมการเข้าถึงทีม ตัวอย่าง: IT ส่วนกลางอาจมีสิทธิ์ระดับผู้ดูแลระบบ แต่ทีม API มีสิทธิ์เข้าถึงเฉพาะชุด API ระบบคลาวด์สาธารณะที่ จำกัด

นอกจากนี้ยังช่วยคลายข้อกังวลเนื่องจากคุณจะพบว่าแหล่งข้อมูลบางอย่างไม่ค่อยมีการเปลี่ยนแปลงในขณะที่แหล่งข้อมูลอื่น ๆ เปลี่ยนแปลงตลอดเวลา การแบ่งแยกช่วยขจัดความเสี่ยงและความซับซ้อน

กลยุทธ์นี้มีความคล้ายคลึงกับกลยุทธ์หลายบัญชีของ AWS อ่านข้อมูลเพิ่มเติม

CI / ซีดี

นี่เป็นหัวข้อของตัวเอง แต่ Terraform ทำงานได้ดีมากภายในท่อที่ดี ข้อผิดพลาดที่พบบ่อยที่สุดคือการถือว่า CI เป็นกระสุนเงิน ในทางเทคนิค Terraform ควรจัดเตรียมโครงสร้างพื้นฐานในระหว่างขั้นตอนของการประกอบท่อเท่านั้น สิ่งนี้จะแยกออกจากสิ่งที่เกิดขึ้นในขั้นตอน CI ซึ่งโดยทั่วไปจะตรวจสอบและทดสอบเทมเพลต

NB เขียนบนมือถือดังนั้นโปรดขออภัยในข้อผิดพลาด


0

ก่อนที่คำตอบจะชัดเจนและให้ข้อมูลฉันจะพยายามเพิ่ม 2 เซ็นต์ของฉันที่นี่

คำแนะนำทั่วไปสำหรับการจัดโครงสร้างโค้ด

  1. ง่ายและเร็วกว่าในการทำงานกับทรัพยากรจำนวนน้อย:

    • Cmds terraform planและterraformใช้ทั้งการเรียก API บนคลาวด์เพื่อตรวจสอบสถานะของทรัพยากร
    • หากคุณมีโครงสร้างพื้นฐานทั้งหมดในองค์ประกอบเดียวอาจใช้เวลาหลายนาที (แม้ว่าคุณจะมีไฟล์หลายไฟล์ในโฟลเดอร์เดียวกันก็ตาม)
  2. รัศมีการระเบิดเล็กลงโดยใช้ทรัพยากรน้อยลง:

    • การแยกทรัพยากรที่ไม่เกี่ยวข้องออกจากกันโดยการวางไว้ในองค์ประกอบแยกต่างหาก (โฟลเดอร์) ช่วยลดความเสี่ยงหากมีสิ่งผิดปกติเกิดขึ้น
  3. เริ่มโครงการของคุณโดยใช้สถานะระยะไกล:

    • แล็ปท็อปของคุณไม่มีที่สำหรับแหล่งความจริงของโครงสร้างพื้นฐาน
    • การจัดการtfstateไฟล์ในคอมไพล์เป็นฝันร้าย
    • ในภายหลังเมื่อเลเยอร์โครงสร้างพื้นฐานเริ่มเติบโตไปในทิศทางใด ๆ (จำนวนการอ้างอิงหรือทรัพยากร)
    • โมดูลตัวอย่าง: https://github.com/cloudposse/terraform-aws-tfstate-backend
    • เครื่องมืออ้างอิง: https://github.com/camptocamp/terraboard
  4. พยายามฝึกโครงสร้างและหลักการตั้งชื่อที่สอดคล้องกัน:

    • เช่นเดียวกับรหัสขั้นตอนควรเขียนโค้ดTerraformให้คนอ่านก่อนความสม่ำเสมอจะช่วยได้เมื่อมีการเปลี่ยนแปลงเกิดขึ้นหกเดือนนับจากนี้
    • เป็นไปได้ที่จะย้ายทรัพยากรในไฟล์สถานะ Terraformแต่อาจทำได้ยากกว่าหากคุณมีโครงสร้างและการตั้งชื่อที่ไม่สอดคล้องกัน
  5. ทำให้โมดูลทรัพยากรธรรมดาที่สุด

  6. อย่าฮาร์ดโค้ดค่าที่สามารถส่งผ่านเป็นตัวแปรหรือค้นพบโดยใช้แหล่งข้อมูล

  7. ใช้dataแหล่งที่มาและterraform_remote_stateโดยเฉพาะเป็นกาวระหว่างโมดูลโครงสร้างพื้นฐานภายในองค์ประกอบ

( บทความอ้างอิง: https://www.terraform-best-practices.com/code-structure )


ตัวอย่าง:

ง่ายและรวดเร็วกว่าในการทำงานกับทรัพยากรจำนวนน้อยดังนั้นเราจึงนำเสนอเค้าโครงโค้ดที่แนะนำด้านล่าง

หมายเหตุ: เช่นเดียวกับการอ้างอิงที่ไม่ควรปฏิบัติตามอย่างเคร่งครัดเนื่องจากแต่ละโครงการมีลักษณะเฉพาะของตนเอง

.
├── 1_tf-backend #remote AWS S3 + Dynamo Lock tfstate 
   ├── main.tf
   ├── ...
├── 2_secrets
   ├── main.tf
   ├── ...
├── 3_identities
   ├── account.tf
   ├── roles.tf
   ├── group.tf
   ├── users.tf
   ├── ...
├── 4_security
   ├── awscloudtrail.tf
   ├── awsconfig.tf
   ├── awsinspector.tf
   ├── awsguarduty.tf
   ├── awswaf.tf
   └── ...
├── 5_network
   ├── account.tf
   ├── dns_remote_zone_auth.tf
   ├── dns.tf
   ├── network.tf
   ├── network_vpc_peering_dev.tf
   ├── ...
├── 6_notifications
   ├── ...
├── 7_containers
   ├── account.tf
   ├── container_registry.tf
   ├── ...
├── config
   ├── backend.config
   └── main.config
└── readme.md

0

ฉันเชื่อว่ามีแนวทางปฏิบัติที่ดีที่สุดบางประการที่ต้องปฏิบัติตามในขณะที่ใช้พื้นระเบียงเพื่อจัดโครงสร้างพื้นฐาน

  1. อย่าเขียนรหัสเดิมอีก (การใช้ซ้ำ)
  2. แยกการกำหนดค่าสภาพแวดล้อมเพื่อให้ดูแลรักษาได้ง่าย
  3. ใช้รีโมตแบ็กเอนด์ s3 (เข้ารหัส) และไดนาโม DB เพื่อจัดการการล็อกพร้อมกัน
  4. สร้างโมดูลและใช้โมดูลนั้นในโครงสร้างพื้นฐานหลักหลาย ๆ ครั้งเหมือนกับฟังก์ชันที่ใช้ซ้ำได้ซึ่งสามารถเรียกใช้ได้หลายครั้งโดยส่งผ่านพารามิเตอร์ที่แตกต่างกัน

จัดการกับสภาพแวดล้อมที่หลากหลาย

วิธีที่แนะนำส่วนใหญ่คือการใช้ 'พื้นที่ทำงาน' ของ Terraform เพื่อจัดการกับสภาพแวดล้อมที่หลากหลาย แต่ฉันเชื่อว่าการใช้พื้นที่ทำงานอาจแตกต่างกันไปตามวิธีการทำงานในองค์กร อื่น ๆ กำลังจัดเก็บรหัส Terraform สำหรับแต่ละสภาพแวดล้อมของคุณ (เช่น stage, prod, QA) เพื่อแยกสถานะสภาพแวดล้อม อย่างไรก็ตามในกรณีนี้เราแค่คัดลอกโค้ดเดียวกันในหลาย ๆ ที่

├── main.tf
├── dev
   ├── main.tf
   ├── output.tf
   └── variables.tf
└── prod
├── main.tf
├── output.tf
└── variables.tf

ฉันทำตามแนวทางที่แตกต่างกันในการจัดการและหลีกเลี่ยงการทำซ้ำรหัสพื้นผิวเดียวกันโดยเก็บไว้ในโฟลเดอร์สภาพแวดล้อมแต่ละโฟลเดอร์เนื่องจากฉันเชื่อว่าส่วนใหญ่สภาพแวดล้อมทั้งหมดจะเหมือนกัน 90%

├── deployment
 ├── 01-network.tf
 ├── 02-ecs_cluster.tf
 ├── 03-ecs_service.tf
 ├── 04-eks_infra.tf
 ├── 05-db_infra.tf
 ├── 06-codebuild-k8s.tf
 ├── 07-aws-secret.tf
 ├── backend.tf
 ├── provider.tf
 └── variables.tf
├── env
 ├── dev
  ├── dev.backend.tfvar
  └── dev.variables.tfvar
 └── prod
 ├── prod.backend.tfvar
 └── prod.variables.tfvar
├── modules
 └── aws
 ├── compute
  ├── alb_loadbalancer
  ├── alb_target_grp
  ├── ecs_cluster
  ├── ecs_service
  └── launch_configuration
 ├── database
  ├── db_main
  ├── db_option_group
  ├── db_parameter_group
  └── db_subnet_group
 ├── developertools
 ├── network
  ├── internet_gateway
  ├── nat_gateway
  ├── route_table
  ├── security_group
  ├── subnet
  ├── vpc
 └── security
 ├── iam_role
 └── secret-manager
└── templates

การกำหนดค่าที่เกี่ยวข้องกับสภาพแวดล้อม

เก็บคอนฟิกูเรชันและพารามิเตอร์ที่เกี่ยวข้องกับสภาวะแวดล้อมแยกกันในไฟล์ตัวแปรและส่งผ่านค่านั้นเพื่อกำหนดคอนฟิกโครงสร้างพื้นฐาน เช่นด้านล่าง

  • dev.backend.tfvar

      region = "ap-southeast-2"
      bucket = "dev-samplebackendterraform"
      key = "dev/state.tfstate"
      dynamo_db_lock = "dev-terraform-state-lock"
  • dev.variable.tfvar

    environment                     =   "dev"
    vpc_name                        =   "demo"
    vpc_cidr_block                  =   "10.20.0.0/19"
    private_subnet_1a_cidr_block    =   "10.20.0.0/21"
    private_subnet_1b_cidr_block    =   "10.20.8.0/21"
    public_subnet_1a_cidr_block     =   "10.20.16.0/21"
    public_subnet_1b_cidr_block     =   "10.20.24.0/21"

การข้ามส่วนโครงสร้างพื้นฐานอย่างมีเงื่อนไข

สร้างการกำหนดค่าในไฟล์ตัวแปรเฉพาะ env และขึ้นอยู่กับตัวแปรนั้นตัดสินใจที่จะสร้างหรือข้ามส่วนนั้น ด้วยวิธีนี้ขึ้นอยู่กับความต้องการส่วนเฉพาะของโครงสร้างพื้นฐานสามารถข้ามไปได้

variable vpc_create {
   default = "true"
}

module "vpc" {
  source = "../modules/aws/network/vpc"
  enable = "${var.vpc_create}"
  vpc_cidr_block = "${var.vpc_cidr_block}"
  name = "${var.vpc_name}"
 }

 resource "aws_vpc" "vpc" {
    count                = "${var.enable == "true" ? 1 : 0}"
    cidr_block           = "${var.vpc_cidr_block}"
    enable_dns_support   = "true"
   enable_dns_hostnames = "true"
}

คำสั่งด้านล่างนี้จำเป็นสำหรับการเริ่มต้นและดำเนินการเปลี่ยนแปลงอินฟาเรดสำหรับแต่ละสภาพแวดล้อม cd ไปยังโฟลเดอร์สภาพแวดล้อมที่ต้องการ

  terraform init -var-file=dev.variables.tfvar -backend-config=dev.backend.tfvar ../../deployment/

  terraform apply -var-file=dev.variables.tfvar ../../deployment

สำหรับการอ้างอิง: https://github.com/mattyait/devops_terraform


0

ฉันไม่ชอบแนวคิดของโฟลเดอร์ย่อยเพราะจะทำให้เกิดแหล่งที่มาที่แตกต่างกันตามสภาพแวดล้อมและสิ่งนี้มีแนวโน้มที่จะล่องลอย

แนวทางที่ดีกว่าคือการมีสแต็กเดียวสำหรับทุกสภาพแวดล้อม (สมมติว่า dev, preprod และ prod) terraform workspaceในการทำงานในสภาพแวดล้อมการใช้งานเพียงครั้งเดียว

terraform workspace new dev

สิ่งนี้จะสร้างพื้นที่ทำงานใหม่ ซึ่งรวมถึงไฟล์สถานะเฉพาะและตัวแปรที่terraform.workspaceคุณสามารถใช้ในโค้ดของคุณ

resource "aws_s3_bucket" "bucket" {
  bucket = "my-tf-test-bucket-${terraform.workspace}"
}

ด้วยวิธีนี้คุณจะได้รับการเรียกถัง

  • my-tf-test-bucket-dev
  • my-tf-test-bucket-preprod
  • my-tf-test-bucket-prod

หลังจากใช้กับพื้นที่ทำงานด้านบน (ใช้terraform workspace select <WORKSPACE>เพื่อเปลี่ยนสภาพแวดล้อม) ในการทำให้รหัสมีการพิสูจน์หลายภูมิภาคให้ทำดังนี้:

data "aws_region" "current" {}

resource "aws_s3_bucket" "bucket" {
  bucket = "my-tf-test-bucket-${data.aws_region.current.name}-${terraform.workspace}"
}

ที่จะได้รับ (สำหรับ us-east-1 ภูมิภาค)

  • my-tf-test-bucket-us-east-1-dev
  • my-tf-test-bucket-us-east-1-preprod
  • my-tf-test-bucket-us-east-1-prod

0

แนวทางปฏิบัติที่ดีที่สุดของ Terraform ที่ควรปฏิบัติตาม:

  1. หลีกเลี่ยงการเข้ารหัสยาก: บางครั้งนักพัฒนาสร้างทรัพยากรด้วยตนเองโดยตรง คุณต้องทำเครื่องหมายทรัพยากรเหล่านี้และใช้การนำเข้าพื้นดินเพื่อรวมไว้ในรหัส ตัวอย่าง:

    account_number =“ 123456789012 "account_alias =" mycompany "

  2. เรียกใช้ Terraform จากคอนเทนเนอร์นักเทียบท่า: Terraform เผยแพร่คอนเทนเนอร์ Docker อย่างเป็นทางการที่ช่วยให้คุณควบคุมเวอร์ชันที่คุณสามารถเรียกใช้ได้อย่างง่ายดาย

ขอแนะนำให้รันคอนเทนเนอร์ Terraform Docker เมื่อคุณตั้งค่างานสร้างในท่อ CI / CD

TERRAFORM_IMAGE=hashicorp/terraform:0.11.7
TERRAFORM_CMD="docker run -ti --rm -w /app -v ${HOME}/.aws:/root/.aws -v ${HOME}/.ssh:/root/.ssh -v `pwd`:/app $TERRAFORM_IMAGE"

สำหรับข้อมูลเพิ่มเติมโปรดดูที่บล็อกของฉัน: https://medium.com/tech-darwinbox/how-darwinbox-manages-infrastructure-at-scale-with-terraform-371e2c5f04d3


0

ฉันต้องการมีส่วนร่วมในหัวข้อนี้

  • สิ่งนี้น่าจะเป็น AWS S3 + DynamoDB มากที่สุดเว้นแต่คุณจะใช้ Terraform Cloud
  • โครงสร้างพื้นฐานแยกต่างหาก (เครือข่าย + RBAC) ของการผลิตและแบ็กเอนด์ที่ไม่ได้ผลิต
  • วางแผนที่จะปิดใช้งานการเข้าถึงไฟล์สถานะ (การเข้าถึงเครือข่ายและ RBAC) จากภายนอกเครือข่ายที่กำหนด (เช่นกลุ่มตัวแทนการปรับใช้)
  • อย่าเก็บโครงสร้างพื้นฐานด้านหลังของ Terraform ไว้กับสภาพแวดล้อมรันไทม์ ใช้บัญชีแยกกัน
  • เปิดใช้งานการกำหนดเวอร์ชันออบเจ็กต์บนแบ็กเอนด์ Terraform ของคุณเพื่อหลีกเลี่ยงการสูญเสียการเปลี่ยนแปลงและไฟล์สถานะและเพื่อรักษาประวัติสถานะ Terraform

ในบางกรณีพิเศษจำเป็นต้องมีการเข้าถึงไฟล์สถานะ Terraform ด้วยตนเอง สิ่งต่างๆเช่นการปรับโครงสร้างใหม่การทำลายการเปลี่ยนแปลงหรือการแก้ไขข้อบกพร่องจะต้องใช้การดำเนินการของสถานะ Terraform โดยเจ้าหน้าที่ฝ่ายปฏิบัติการ ในโอกาสดังกล่าวให้วางแผนการเข้าถึงสถานะ Terraform ที่มีการควบคุมพิเศษโดยใช้ bastion host, VPN เป็นต้น

ตรวจสอบบล็อกแนวทางปฏิบัติที่ดีที่สุดที่ยาวขึ้นซึ่งครอบคลุมรายละเอียดนี้รวมถึงแนวทางสำหรับไปป์ไลน์ CI / CD


-1

หากคุณยังคงมองหาโซลูชันที่ดีกว่าให้ดูที่พื้นที่ทำงานซึ่งสามารถแทนที่การรักษาโครงสร้างโฟลเดอร์สภาพแวดล้อมที่แตกต่างกันได้โดยสามารถมีตัวแปรเฉพาะของพื้นที่ทำงานได้

ดังที่Yevgeniy Brikman กล่าวว่าควรมีโครงสร้างโมดูล


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.