Infrastructure as Code là gì? Và tại sao mình không còn quản lý hạ tầng bằng tay
Infrastructure as Code không chỉ là Terraform hay một file .tf. Trong bài viết đầu tiên của series này, mình chia sẻ vì sao IaC ra đời, những vấn đề của việc quản lý hạ tầng thủ công và cách tư duy "Infrastructure as Code" thay đổi cách mình xây dựng hệ thống.

Infrastructure as Code là gì? Và tại sao mình không còn quản lý hạ tầng bằng tay
Có một điều khá thú vị là...
Trong nhiều năm làm Software Engineering, mình nhận ra chúng ta dành rất nhiều thời gian để xây dựng một quy trình phát triển phần mềm thật chặt chẽ.
Khi muốn thêm một tính năng mới, chúng ta sẽ:
- Tạo một branch.
- Viết code.
- Commit.
- Push lên Git.
- Tạo Pull Request.
- Được review.
- Merge.
- CI/CD sẽ tự động build và deploy.
Mọi thay đổi đều có lịch sử.
Mọi thay đổi đều có người review.
Nếu có sự cố xảy ra, chúng ta có thể biết chính xác ai thay đổi, thay đổi điều gì và thay đổi vào thời điểm nào.
Đó gần như đã trở thành một tiêu chuẩn trong phát triển phần mềm hiện đại.
Nhưng có một câu hỏi mà mình chưa từng nghĩ đến trong những năm đầu đi làm.
Nếu Application được quản lý như Source Code, vậy tại sao Infrastructure thì không?
Một ngày đẹp trời...
Hãy tưởng tượng bạn vừa nhận được một task.
"Tạo thêm một môi trường Staging giống Production."
Nghe khá đơn giản.
Bạn mở AWS Console.
Hoặc Azure Portal.
Hoặc Google Cloud Console.
Hoặc Vercel Dashboard.
Hoặc Firebase Console.
Bạn bắt đầu tạo từng thành phần.
- Một Virtual Machine.
- Một PostgreSQL Database.
- Một Storage Bucket.
- Một VPC.
- Một vài Security Rules.
- Một vài DNS Records.
- Một vài Environment Variables.
Khoảng một tiếng sau.
Mọi thứ đều chạy.
Bạn kiểm tra.
Ứng dụng hoạt động bình thường.
Task hoàn thành.
Hai tuần sau.
Một bug chỉ xuất hiện trên Production.
Team dành gần nửa ngày để điều tra.
Cuối cùng nguyên nhân không nằm ở source code.
Cũng không nằm ở database.
Mà là vì Production đang có một cấu hình khác với Staging.
Có thể chỉ là:
- Một Firewall Rule.
- Một Environment Variable.
- Một IAM Permission.
- Một Database Flag.
Điều đáng nói là...
Không ai biết sự khác biệt đó xuất hiện từ khi nào.
Không có commit.
Không có Pull Request.
Không có lịch sử review.
Không có changelog.
Chỉ có một câu nói quen thuộc.
"Hình như hôm trước mình có vào dashboard sửa một chút..."
Mình tin rằng nếu bạn đã từng làm việc với Cloud, đây không phải là một câu chuyện quá xa lạ.
Thực tế, mình cũng đã từng gặp những tình huống tương tự.
Không phải vì ai đó làm sai.
Mà bởi vì dashboard vốn không được thiết kế để trở thành nơi quản lý lịch sử thay đổi của hạ tầng.
Dashboard không phải là vấn đề
Đến đây, mình muốn làm rõ một điều.
Bài viết này không nhằm phủ nhận giá trị của dashboard.
Ngược lại.
Mình vẫn sử dụng dashboard hằng ngày.
Mình dùng nó để:
- Quan sát hệ thống.
- Theo dõi Monitoring.
- Debug Logs.
- Xem Metrics.
- Kiểm tra trạng thái tài nguyên.
- Điều tra Production Incident.
Dashboard cực kỳ mạnh ở việc quan sát (Observe).
Nhưng nó không phải công cụ tốt nhất để quản lý (Manage).
Hai khái niệm này nghe có vẻ giống nhau, nhưng trong thực tế lại hoàn toàn khác.
Ví dụ.
Bạn có thể nhìn thấy một PostgreSQL Database trên dashboard.
Bạn có thể biết:
- Database đang ở region nào.
- Dung lượng bao nhiêu.
- CPU đang sử dụng bao nhiêu.
- Có bao nhiêu kết nối.
Nhưng dashboard không thể trả lời những câu hỏi như:
- Tại sao database này lại được cấu hình như vậy?
- Ai là người thay đổi cấu hình này?
- Cấu hình cũ là gì?
- Khi nào Backup được bật?
- Có Pull Request nào cho thay đổi này không?
- Nếu muốn tạo thêm một môi trường giống hệt, phải làm như thế nào?
Đó mới là bài toán thực sự.
Và càng nhiều project, càng nhiều môi trường, càng nhiều thành viên trong team, bài toán này càng trở nên khó giải quyết.
Điều thú vị là chúng ta đã có lời giải từ rất lâu
Nếu nhìn lại cách chúng ta phát triển phần mềm ngày nay, sẽ thấy mọi thứ gần như đều xoay quanh một ý tưởng.
Source Code là nguồn sự thật duy nhất (Single Source of Truth).
Không ai tự ý sửa code trực tiếp trên Production.
Không ai SSH vào Production để chỉnh vài dòng Java hay Node.js rồi lưu lại.
Thay vào đó.
Mọi thay đổi đều phải bắt đầu từ Source Code.
Rồi thông qua Git.
Thông qua Pull Request.
Thông qua Review.
Thông qua CI/CD.
Vậy tại sao Infrastructure lại khác?
Tại sao cùng một hệ thống, Application được quản lý như một sản phẩm phần mềm, còn Infrastructure lại được quản lý bằng những thao tác thủ công trên dashboard?
Đó chính là câu hỏi đã dẫn mình đến với Infrastructure as Code.
Và cũng là chủ đề của toàn bộ series này.
Infrastructure as Code thực sự là gì?
Nếu đây là lần đầu bạn tìm hiểu về Infrastructure as Code, rất có thể bạn sẽ bắt gặp một định nghĩa tương tự như sau.
Infrastructure as Code là việc quản lý và provisioning hạ tầng thông qua các file cấu hình thay vì thao tác thủ công trên giao diện quản trị.
Định nghĩa này hoàn toàn đúng.
Nhưng theo mình, nó vẫn chưa trả lời được câu hỏi quan trọng nhất.
Tại sao việc chuyển từ "click" sang "code" lại tạo ra một sự khác biệt lớn đến vậy?
Sau vài năm làm việc với Terraform và Terragrunt, mình nhận ra rằng Infrastructure as Code chưa bao giờ chỉ là chuyện viết code để tạo Server hay Database.
Đó chỉ là kết quả.
Giá trị thực sự nằm ở việc thay đổi cách chúng ta quản lý Infrastructure.
Từ "ClickOps" sang "GitOps"
Mình khá thích một thuật ngữ mà cộng đồng DevOps hay sử dụng.
ClickOps
Đây là cách gọi vui cho việc quản lý hạ tầng bằng cách đăng nhập vào dashboard rồi thao tác bằng chuột.
Ví dụ.
Muốn tăng CPU cho một Virtual Machine.
- Đăng nhập Cloud Provider.
- Chọn Virtual Machine.
- Chỉnh CPU.
- Save.
Muốn tạo thêm một Storage Bucket.
- Đăng nhập.
- Chọn Bucket.
- Create.
Muốn thêm một Environment Variable.
- Mở Dashboard.
- Add Variable.
- Save.
Nghe có vẻ rất nhanh.
Và thực tế đúng là nhanh.
Ít nhất là trong vài lần đầu.
Nhưng hãy thử tưởng tượng sau một năm.
Có hàng chục project.
Có Development.
Có Staging.
Có UAT.
Có Production.
Có nhiều người cùng thao tác trên một hệ thống.
Lúc đó một câu hỏi bắt đầu xuất hiện.
"Làm sao mình biết toàn bộ Infrastructure hiện tại được tạo ra như thế nào?"
Nếu câu trả lời là:
"Mở dashboard lên xem."
Thì đó thường là dấu hiệu cho thấy hệ thống đang rất khó bảo trì.
Infrastructure as Code thay đổi hoàn toàn cách tiếp cận này.
Thay vì coi dashboard là nơi tạo Infrastructure.
Dashboard chỉ còn là nơi để quan sát.
Còn toàn bộ quá trình tạo mới, cập nhật hay xóa tài nguyên đều được bắt đầu từ Source Code.
Nói cách khác.
Infrastructure cũng đi qua đúng quy trình mà Application đang đi.
Developer
│
▼
Infrastructure Code
│
▼
Git Repository
│
▼
Pull Request
│
▼
Code Review
│
▼
CI/CD
│
▼
Cloud InfrastructureĐó là lý do nhiều người nói rằng:
Infrastructure as Code không phải là một công cụ. Nó là một cách làm việc.
Mình hoàn toàn đồng ý với quan điểm đó.
Infrastructure cũng nên có "Single Source of Truth"
Trong Software Engineering có một khái niệm rất quen thuộc.
Single Source of Truth
Nói đơn giản.
Chỉ nên có một nơi duy nhất phản ánh trạng thái chính xác của hệ thống.
Với Application.
Đó là Source Code.
Nếu Production đang chạy khác với Source Code.
Chúng ta sẽ coi đó là một vấn đề.
Infrastructure cũng nên như vậy.
Thứ phản ánh trạng thái của hệ thống không nên là:
- Dashboard.
- Wiki.
- Một file Excel.
- Một tài liệu hướng dẫn.
- Hay trí nhớ của một Senior Engineer.
Mà nên là những file cấu hình được lưu trong Git.
Ví dụ.
Nếu ai đó hỏi.
"Production hiện đang có bao nhiêu Redis?"
Bạn không cần đăng nhập Cloud Provider.
Bạn chỉ cần mở repository.
Nếu ai đó hỏi.
"Database Backup được bật từ khi nào?"
Bạn không cần hỏi người khác.
Chỉ cần xem Git History.
Nếu cần tạo thêm một môi trường mới.
Bạn cũng không cần đọc một tài liệu dài hàng chục trang.
Chỉ cần chạy lại Infrastructure Code.
Đó mới là ý nghĩa của việc biến Infrastructure thành Source Code.
Điều mình thích nhất ở Infrastructure as Code
Nếu phải chọn một giá trị lớn nhất của IaC.
Có lẽ mình sẽ không chọn Automation.
Cũng không phải Reusable.
Hay Multi Cloud.
Thứ mình đánh giá cao nhất là khả năng tạo ra sự nhất quán (Consistency).
Một môi trường Development.
Một môi trường Staging.
Một môi trường Production.
Đều được tạo ra từ cùng một bộ Infrastructure Code.
Điều này giúp giảm rất nhiều những lỗi kiểu:
- "Máy em chạy."
- "Staging không bị."
- "Production khác Development."
Tất nhiên.
Thực tế vẫn sẽ có những khác biệt giữa các môi trường.
Ví dụ:
- Kích thước Database.
- Số lượng Replica.
- CPU.
- Memory.
Nhưng kiến trúc và cách hệ thống được định nghĩa vẫn nên giống nhau.
Đó là điều Infrastructure as Code mang lại.
Không phải bằng tài liệu.
Không phải bằng checklist.
Mà bằng chính source code.
Nhưng... IaC có phải chỉ là Terraform?
Đây là một hiểu lầm mà mình từng có khi mới bắt đầu tìm hiểu.
Mình từng nghĩ.
Infrastructure as Code = Terraform.
Thực ra không phải.
Infrastructure as Code là một tư duy.
Terraform chỉ là một công cụ giúp hiện thực hóa tư duy đó.
Cũng giống như:
- Git không phải là Version Control.
- Git chỉ là một công cụ để thực hiện Version Control.
Hay:
- Docker không phải Containerization.
- Docker chỉ là một implementation của Container Technology.
Infrastructure as Code cũng vậy.
Có rất nhiều công cụ khác nhau để triển khai IaC.
Terraform chỉ là một trong số đó.
Trong phần tiếp theo, chúng ta sẽ cùng nhìn qua bức tranh tổng thể của hệ sinh thái Infrastructure as Code và tìm hiểu vì sao mình lại lựa chọn Terraform cùng Terragrunt cho toàn bộ series này.
Infrastructure as Code không phải là Terraform
Nếu đây là lần đầu bạn tìm hiểu về Infrastructure as Code, rất có thể bạn cũng giống mình trước đây.
Mình từng nghĩ.
Infrastructure as Code chính là Terraform.
Thực ra điều này không đúng.
Terraform rất nổi tiếng.
Thậm chí ở nhiều công ty, nhắc đến IaC là mọi người sẽ nghĩ ngay đến Terraform.
Nhưng Terraform chỉ là một công cụ.
Infrastructure as Code mới là tư duy.
Đây là hai khái niệm hoàn toàn khác nhau.
Đừng nhầm giữa tư duy và công cụ
Hãy lấy một ví dụ quen thuộc.
Nếu ai đó hỏi bạn.
"Version Control là gì?"
Chắc chắn câu trả lời sẽ không phải là:
"Version Control là Git."
Git chỉ là một công cụ để hiện thực hóa Version Control.
Nếu một ngày Git biến mất.
Khái niệm Version Control vẫn tồn tại.
Infrastructure as Code cũng giống như vậy.
Terraform.
OpenTofu.
Pulumi.
CloudFormation.
Đó đều là những công cụ khác nhau để triển khai cùng một tư duy.
Điều quan trọng nhất không phải là bạn sử dụng công cụ nào.
Điều quan trọng là Infrastructure của bạn có đang được quản lý như Source Code hay không.
Nếu câu trả lời là có.
Bạn đang làm Infrastructure as Code.
Vậy tại sao mình lại chọn Terraform?
Có khá nhiều công cụ để triển khai Infrastructure as Code.
Mỗi công cụ đều có những ưu điểm riêng.
Tuy nhiên, trong toàn bộ series này mình sẽ sử dụng Terraform và Terragrunt.
Lý do rất đơn giản.
Đó là hai công cụ mình đang sử dụng hằng ngày để quản lý hạ tầng cho các dự án thực tế.
Từ những side project cá nhân.
Cho đến các hệ thống production.
Bao gồm cả chính blog mà bạn đang đọc.
Trong series này, chúng ta sẽ không chỉ học cách viết Terraform.
Mình cũng sẽ chia sẻ:
- Vì sao mình thiết kế module theo cách đó.
- Vì sao mình sử dụng Terragrunt.
- Cách mình tổ chức repository.
- Những lỗi mình từng gặp.
- Những quyết định mình đã thay đổi sau khi đưa Terraform vào production.
Nói cách khác.
Đây không phải là series giới thiệu Terraform.
Đây là series chia sẻ cách mình áp dụng Infrastructure as Code vào những dự án thực tế.
Terraform chỉ là công cụ được sử dụng xuyên suốt để minh họa.
Một điều mình nhận ra sau nhiều năm
Khi mới bắt đầu, mình dành khá nhiều thời gian để tìm hiểu:
- Terraform syntax.
- Resource.
- Variable.
- Module.
- Provider.
Nhưng càng làm nhiều, mình càng nhận ra.
Điều tạo nên sự khác biệt không phải là việc thuộc bao nhiêu resource.
Mà là cách chúng ta tư duy về Infrastructure.
Một hệ thống tốt không được xây dựng nhờ việc click dashboard nhanh hơn.
Nó được xây dựng nhờ khả năng mô tả toàn bộ hạ tầng bằng code, để bất kỳ ai trong team cũng có thể hiểu, review và tái tạo nó.
Đó cũng là mục tiêu lớn nhất của Infrastructure as Code.
Và là lý do mình muốn bắt đầu series này bằng chính tư duy đó, trước khi đi vào Terraform.
Tiếp theo chúng ta sẽ học gì?
Ở bài viết này, chúng ta đã nói rất nhiều về "Tại sao".
Tại sao Infrastructure as Code ra đời?
Tại sao việc quản lý Infrastructure bằng code lại quan trọng?
Và tại sao Terraform không phải là Infrastructure as Code?
Nhưng vẫn còn một câu hỏi quan trọng hơn.
Terraform thực sự hoạt động như thế nào?
Terraform không chạy từng dòng lệnh giống như Bash Script.
Nó cũng không đơn giản là "đọc file rồi tạo resource".
Nó có một cách "suy nghĩ" hoàn toàn khác.
Theo mình, đó là phần thú vị nhất của Terraform.
Và cũng là chủ đề của bài viết tiếp theo.