2015-10-15 20 views
42

Tôi đang trong quá trình trao đổi qua cơ sở hạ tầng của chúng tôi thành địa chỉ. Thực tiễn tốt nhất để thực sự quản lý các tệp terraform và trạng thái là gì? Tôi nhận ra đó là cơ sở hạ tầng như mã, và tôi sẽ cam kết các tệp .tf của tôi thành git, nhưng tôi có cam kết tfstate không? Có nên cư trú ở đâu đó giống S3 không? Tôi muốn cuối cùng cho CI để quản lý tất cả điều này, nhưng đó là xa kéo dài và đòi hỏi tôi để tìm ra những mảnh di chuyển cho các tập tin.Thực tiễn tốt nhất khi sử dụng Terraform

Tôi thực sự chỉ muốn xem cách mọi người ra có thực sự sử dụng các loại công cụ sản xuất

Trả lời

43

Tôi cũng trong tình trạng di cư cơ sở hạ tầng hiện có để AWS Terraform để biên nhằm mục đích cập nhật các câu trả lời như tôi phát triển, xây dựng.

tôi đã dựa rất nhiều vào Terraform chính thức examples và nhiều thử và sai để xác thịt ra lĩnh vực mà tôi đã không chắc chắn trong.

file .tfstate

Terraform cấu hình có thể được sử dụng để cung cấp nhiều hộp trên cơ sở hạ tầng khác nhau, mỗi cái có thể có một trạng thái khác nhau. Vì nó cũng có thể được chạy bởi nhiều người nên trạng thái này ở một vị trí tập trung (như S3) nhưng không phải là git.

Điều này có thể được xác nhận xem tại Terraform .gitignore.

kiểm soát phát triển

Mục đích của chúng tôi là cung cấp thêm quyền kiểm soát của các cơ sở hạ tầng để phát triển trong khi duy trì một kiểm toán đầy đủ (git log) và khả năng thay đổi kiểm tra sự tỉnh táo (yêu cầu kéo). Với ý nghĩ đó, quy trình làm việc cơ sở hạ tầng mới mà tôi hướng tới là:

  1. Nền tảng cơ bản của AMI chung bao gồm các mô-đun có thể tái sử dụng, ví dụ: con rối.
  2. Cơ sở hạ tầng lõi được cung cấp bởi DevOps sử dụng Terraform.
  3. Nhà phát triển thay đổi cấu hình Terra trong Git khi cần (số phiên bản; VPC mới; bổ sung vùng/vùng khả dụng, v.v.).
  4. Cấu hình Git được đẩy và yêu cầu kéo được gửi đến để đảm bảo sự an toàn của một thành viên của nhóm DevOps.
  5. Nếu được chấp thuận, gọi webhook để CI để xây dựng và triển khai (không chắc chắn làm thế nào để phân vùng nhiều môi trường vào thời điểm này)

Sửa 1 - Cập nhật về tình trạng hiện thời

Kể từ khi bắt đầu câu trả lời này tôi có viết rất nhiều mã TF và cảm thấy thoải mái hơn trong tình trạng của chúng ta. Chúng tôi đã gặp lỗi và hạn chế trên đường đi nhưng tôi chấp nhận đây là đặc điểm của việc sử dụng phần mềm thay đổi nhanh chóng.

Layout

Chúng tôi có một cơ sở hạ tầng AWS phức tạp với nhau nhiều của VPC với nhiều mạng con. Chìa khóa để dễ dàng quản lý điều này là xác định phân loại linh hoạt bao gồm khu vực, môi trường, dịch vụ và chủ sở hữu mà chúng tôi có thể sử dụng để tổ chức mã cơ sở hạ tầng của chúng tôi (cả terraform và con rối).

Modules

Bước tiếp theo là tạo ra một kho git duy nhất để lưu trữ các module terraform của chúng tôi. Cơ cấu trình độ dir đầu của chúng tôi cho các module trông như thế này:

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

Mỗi người đặt một số giá trị mặc định lành mạnh nhưng cho thấy chúng như biến có thể được ghi đè bởi "keo" của chúng tôi.

Keo

Chúng tôi có một kho lưu trữ thứ hai với glue của chúng tôi mà làm cho việc sử dụng các module nêu trên. Nó được đặt ra phù hợp với tài liệu phân loại của chúng tôi:

. ├── 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

Bên trong mức khách hàng chúng tôi có AWS chiếm cụ .tf tập tin mà cung cấp nguồn lực toàn cầu (như vai trò IAM); tiếp theo là cấp vùng với khóa công khai SSH EC2; Cuối cùng trong môi trường của chúng tôi (dev, stg, prod vv) là các thiết lập VPC, tạo cá thể và kết nối ngang hàng, v.v. của chúng tôi được lưu trữ.

Lưu ý bên: Như bạn có thể thấy tôi sẽ đi ngược lại lời khuyên của riêng tôi ở trên giữ terraform.tfstate trong git. Đây là một biện pháp tạm thời cho đến khi tôi chuyển sang S3 nhưng phù hợp với tôi vì tôi hiện là nhà phát triển duy nhất.

Tiếp bước

này vẫn còn là một quá trình thủ công và không có trong Jenkins nhưng chúng tôi đang porting một khá lớn, cơ sở hạ tầng phức tạp và cho đến nay rất tốt. Giống như tôi đã nói, rất ít lỗi nhưng hoạt động tốt!

Chỉnh sửa 2 - Thay đổi

Đã gần một năm kể từ khi tôi viết câu trả lời ban đầu này và tình trạng của cả hai Terraform và bản thân mình đã thay đổi đáng kể. Bây giờ tôi đang ở một vị trí mới bằng cách sử dụng Terraform để quản lý một cụm Azure và Terraform bây giờ là v0.10.7.

Nhà nước

dân đã nhiều lần nói với tôi nhà nước nên không đi trong Git - và họ là chính xác. Chúng tôi đã sử dụng điều này như một biện pháp tạm thời với một nhóm gồm hai người dựa vào truyền thông và kỷ luật của nhà phát triển. Với một đội ngũ phân phối lớn hơn, chúng tôi hiện đang tận dụng triệt để trạng thái từ xa trong S3 với locking do DynamoDB cung cấp. Lý tưởng nhất điều này sẽ được di chuyển đến lãnh sự bây giờ nó là v1.0 để cắt các nhà cung cấp đám mây chéo.

Modules

Trước đây chúng tôi tạo ra và sử dụng các module bên trong. Đây vẫn là trường hợp nhưng với sự ra đời và tăng trưởng của Terraform registry chúng tôi cố gắng sử dụng chúng như ít nhất một cơ sở.

cấu trúc file

Vị trí mới có một phân loại đơn giản hơn nhiều với chỉ hai môi trường infx - devprod. Mỗi biến có các biến và đầu ra của riêng chúng, tái sử dụng các mô đun của chúng ta được tạo ở trên. Nhà cung cấp remote_state cũng giúp chia sẻ kết quả đầu ra của các tài nguyên được tạo giữa các môi trường. Kịch bản của chúng tôi là tên miền phụ trong các nhóm tài nguyên Azure khác nhau cho một TLD được quản lý toàn cầu.

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

Kế hoạch

Một lần nữa với những thách thức thêm của một nhóm phân phối, bây giờ chúng ta luôn luôn lưu lượng của chúng ta về lệnh terraform plan. Chúng tôi có thể kiểm tra và biết những gì sẽ được chạy mà không có rủi ro của một số thay đổi giữa các giai đoạn planapply (mặc dù khóa giúp với điều này). Hãy nhớ xóa tệp gói này vì nó có khả năng chứa các biến "bí mật" văn bản thuần túy.

Nhìn chung, chúng tôi rất hài lòng với Terraform và tiếp tục tìm hiểu và cải tiến với các tính năng mới được thêm vào.

+0

Quý vị có bất kỳ may mắn/vấn đề kể từ khi câu trả lời này? Của bạn có vẻ rất giống với những gì tôi đang nhắm tới, nhưng bạn có thể còn hơn cả tôi nữa. –

+0

đẹp! Tôi vẫn không thể thực hiện trên mặt của tôi, chúng tôi đang thanh toán bù trừ một số công cụ khác nhưng thật tuyệt vời khi biết một số điều cần làm/tránh. –

+1

Tôi tò mò là tại sao bạn nghĩ rằng các tập tin tfstate không nên được lưu trữ trong git? Có phải đơn giản là vì trạng thái cũ không đáng để tiết kiệm hay có vấn đề gì khác? – agbodike

9

Với remote config, điều này đã trở thành đơn giản hơn nhiều:

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 

Xem docs để biết chi tiết.

+0

Nguồn từ xa có cần phải được cấu hình lại mỗi khi bạn muốn làm việc trên một thành phần/môi trường/mô-đun khác không? – jmreicha

50

Chúng tôi sử dụng Terraform nặng nề và thiết lập đề nghị của chúng tôi là như sau:

bố trí tập tin

Chúng tôi khuyên bạn nên lưu trữ mã Terraform cho mỗi môi trường của bạn (ví dụ như sân khấu, sản, qa) rời đồng bộ riêng biệt của các mẫu (và do đó, tách riêng các tệp .tfstate). Điều này quan trọng để các môi trường riêng biệt của bạn thực sự bị cô lập với nhau trong khi thực hiện các thay đổi. Nếu không, trong khi rối tung xung quanh với một số mã trong dàn dựng, nó quá dễ dàng để thổi lên một cái gì đó trong sản quá. Xem Terraform, VPC, and why you want a tfstate file per env để có cuộc thảo luận đầy màu sắc về lý do.

Do đó, bố trí tập tin thông thường của chúng tôi trông như thế này:

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

Tất cả các mã Terraform cho giai đoạn VPC đi vào thư mục stage, tất cả các mã cho các sản VPC đi vào thư mục prod, và tất cả mã tồn tại bên ngoài VPC (ví dụ: người dùng IAM, chủ đề SNS, nhóm S3) đi vào thư mục global.

Lưu ý rằng, theo quy ước, chúng tôi thường phá vỡ mã Terraform của chúng tôi xuống thành 3 file:

  • vars.tf: biến Input.
  • outputs.tf: Biến đầu ra.
  • main.tf: Tài nguyên thực tế.

Modules

Thông thường, chúng ta định nghĩa cơ sở hạ tầng của chúng tôi trong hai thư mục:

  1. infrastructure-modules: Thư mục này chứa nhỏ, tái sử dụng, mô-đun phiên bản. Hãy nghĩ về từng mô-đun như là một kế hoạch chi tiết về cách tạo một phần cơ sở hạ tầng đơn lẻ, chẳng hạn như VPC hoặc cơ sở dữ liệu.
  2. infrastructure-live: Thư mục này chứa cơ sở hạ tầng trực tiếp, đang chạy, mà nó tạo ra bằng cách kết hợp các mô-đun trong infrastructure-modules. Hãy nghĩ về mã trong thư mục này như những ngôi nhà thực tế bạn đã xây dựng từ các bản thiết kế của mình.

A Terraform module chỉ là bất kỳ tập hợp các mẫu Terraform nào trong một thư mục. Ví dụ, chúng ta có thể có một thư mục có tên vpc trong infrastructure-modules định nghĩa tất cả các bảng định tuyến, mạng con, cổng, ACL, vv cho một VPC duy nhất:

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

Sau đó chúng tôi có thể sử dụng mô-đun trong infrastructure-live/stageinfrastructure-live/prod tạo giai đoạn và sản phẩm VPCs. Ví dụ, đây là những gì infrastructure-live/stage/main.tf có thể trông giống như:

module "stage_vpc" { 
    source = "git::[email protected]: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" 
} 

Để sử dụng một mô-đun, bạn sử dụng tài nguyên module và chỉ lĩnh vực source của nó hoặc là một con đường địa phương trên ổ cứng của bạn (ví dụ source = "../infrastructure-modules/vpc") hoặc, như trong ví dụ trên, một URL Git (xem module sources). Lợi thế của URL Git là chúng tôi có thể chỉ định git sha1 hoặc thẻ cụ thể (ref=v0.0.4). Bây giờ, chúng tôi không chỉ xác định cơ sở hạ tầng của mình như một loạt các mô-đun nhỏ, mà chúng tôi có thể phiên bản các mô-đun đó và cập nhật hoặc khôi phục cẩn thận khi cần thiết.

Chúng tôi đã tạo một số tài liệu có thể sử dụng lại, đã được kiểm tra và được ghi lại Infrastructure Packages để tạo VPC, cụm Docker, cơ sở dữ liệu, v.v ... và hầu hết trong số đó chỉ là các mô-đun Terraform phiên bản.

Nhà nước

Khi bạn sử dụng Terraform để tạo ra nguồn lực (ví dụ EC2, cơ sở dữ liệu, VPCs), nó ghi thông tin về những gì nó được tạo ra trong một tập tin .tfstate. Để thực hiện thay đổi đối với các tài nguyên đó, mọi người trong nhóm của bạn cần quyền truy cập vào cùng một tệp .tfstate này, nhưng bạn KHÔNG nên kiểm tra nó vào Git (xem here for an explanation why). Thay vào đó, chúng tôi khuyên bạn nên lưu trữ .tfstate tệp trong S3 bằng cách bật Terraform Remote State, thao tác này sẽ tự động đẩy/kéo các tệp mới nhất mỗi khi bạn chạy Terraform. Đảm bảo enable versioning trong thùng S3 của bạn để bạn có thể quay lại các tệp cũ hơn .tfstate trong trường hợp bạn bằng cách nào đó đã làm hỏng phiên bản mới nhất. Tuy nhiên, lưu ý quan trọng: Terraform không cung cấp khóa. Vì vậy, nếu hai thành viên trong nhóm chạy terraform apply cùng một lúc trên cùng một tệp .tfstate, họ có thể sẽ ghi đè lên các thay đổi của nhau. Để giải quyết vấn đề này, chúng tôi đã tạo ra một công cụ mã nguồn mở có tên là Terragrunt, là một trình bao bọc mỏng cho Terraform sử dụng Amazon DynamoDB để cung cấp khóa (hoàn toàn miễn phí cho hầu hết các nhóm). Hãy xem Add Automatic Remote State Locking and Configuration to Terraform with Terragrunt để biết thêm thông tin.

Đọc thêm

Chúng tôi chỉ mới bắt đầu một loạt các bài đăng trên blog gọi là A Comprehensive Guide to Terraform mô tả chi tiết tất cả các thực hành tốt nhất chúng tôi đã học được sử dụng Terraform trong thế giới thực.

Cập nhật: Hướng dẫn toàn diện cho chuỗi bài đăng trên blog Terraform đã trở nên phổ biến đến mức chúng tôi đã mở rộng cuốn sách đó thành một cuốn sách có tên là Terraform: Up & Running!

+0

Tôi nghĩ đây là câu trả lời đúng. Sử dụng các mô-đun, phiên bản chúng và giữ riêng môi trường. – DrewVS

+0

Bước cấu hình từ xa có cần phải chạy lại mỗi lần bạn muốn làm việc trên một thành phần/môi trường/mô-đun khác nhau/bất kỳ điều gì nếu không sử dụng terragrunt hoặc một số trình bao bọc khác không? – jmreicha

+0

@jmreicha: Bạn cần chạy 'cấu hình từ xa' nếu bạn chỉ cần kiểm tra cấu hình Terraform của mình hoặc nếu bạn muốn thay đổi cấu hình từ xa trước đó. Terraform 0.9 sẽ giới thiệu khái niệm 'backends', điều này sẽ đơn giản hóa rất nhiều điều này. Xem [PR này] (https://github.com/hashicorp/terraform/pull/11286) để biết thêm chi tiết. –

2

Bao sâu hơn bởi @Yevgeny Brikman nhưng trả lời câu hỏi đặc biệt của OP:

What's the best practice for actually managing the terraform files and state? 

Sử dụng git cho các tập tin TF. Nhưng đừng kiểm tra các tệp của Tiểu bang trong (ví dụ: tfstate). Thay vào đó hãy sử dụng Terragrunt để đồng bộ/khóa các tệp trạng thái vào S3.

but do I commit tfstate as well? 

số

Should that reside somewhere like S3? 

Các vấn đề liên quan