Product Management
Đăng nhập
ESC

Nhập từ khóa để tìm kiếm

↑↓ Di chuyển
Enter Mở
ESC Đóng

Infrastructure as Code và Containers

Đã đọc 0/15 mục · còn khoảng 14 phút
Cách chúng tôi ghi nhận

Một mục được tính là đã đọc khi nó nằm giữa màn hình đủ lâu so với độ dài của nó (bảng và sơ đồ tính một nửa), bạn vẫn đang cuộn hoặc bấm phím, và bạn đã thấy tới cuối mục. Lướt nhanh hoặc để tab mở không được tính. Chúng tôi chỉ lưu thời gian đọc từng mục — không lưu gì khác.

Mở đầu — vì sao bài này quan trọng

Hãy tưởng tượng bạn vừa được giao nhiệm vụ dựng một hệ thống web cho công ty. Bạn mở giao diện quản trị của nhà cung cấp cloud, bấm chuột tạo một máy chủ, cài đặt hệ điều hành, cấu hình firewall, gõ hàng chục lệnh cài phần mềm, rồi mở port. Sau ba tiếng đồng hồ, mọi thứ chạy tốt. Nhưng ba tháng sau, sếp bảo: "Dựng cho anh một môi trường y hệt để test." Và bạn chợt nhận ra — bạn không nhớ mình đã bấm những gì, gõ những lệnh nào, chỉnh cấu hình ra sao.

Đây chính là "cơn ác mộng" mà mọi kỹ sư vận hành đều từng trải qua: hạ tầng được tạo ra bằng tay, không ghi chép, không thể tái lập, và mỗi lần cần dựng lại là một lần đánh cược với may rủi. Bài học hôm nay giới thiệu hai trụ cột đã thay đổi hoàn toàn cách chúng ta xây dựng và vận hành hệ thống hiện đại: Infrastructure as Code (IaC) — quản lý hạ tầng bằng mã nguồn, và Containers — đóng gói ứng dụng thành các đơn vị chạy được ở bất cứ đâu.

Hai khái niệm này là nền tảng khái niệm mà bạn sẽ đào sâu suốt phần sau của khóa học (Terraform, Docker, Kubernetes...). Ở bài này, chúng ta chưa đi vào cú pháp cụ thể của công cụ nào — mục tiêu là để bạn hiểu tư duy và lý do tồn tại của chúng. Khi bạn nắm được cái "vì sao", thì cái "làm thế nào" ở các bài sau sẽ trở nên rõ ràng và dễ tiếp thu hơn rất nhiều.

Khái niệm cốt lõi

Infrastructure as Code là gì?

Infrastructure as Code (IaC), tạm dịch là "Hạ tầng dưới dạng mã", là phương pháp quản lý và cung cấp hạ tầng máy tính (máy chủ, mạng, cân bằng tải, cơ sở dữ liệu, quyền truy cập...) thông qua các tệp mã nguồn thay vì thao tác thủ công bằng tay.

Thay vì click chuột trên giao diện hoặc gõ lệnh trực tiếp trên máy chủ, bạn viết một tệp mô tả trạng thái mong muốn của hạ tầng. Ví dụ, thay vì bấm nút tạo một máy chủ ảo, bạn viết một đoạn mô tả kiểu như: "Tôi muốn có một máy chủ 2 CPU, 4GB RAM, chạy Ubuntu 22.04, ở khu vực Singapore, mở port 80 và 443." Công cụ IaC (như Terraform hay Ansible) sẽ đọc tệp này và tự động dựng ra đúng hạ tầng bạn mô tả.

Điểm mấu chốt cần hiểu: IaC chuyển hạ tầng từ thứ bạn làm (một chuỗi hành động thủ công) thành thứ bạn khai báo (một tài liệu mô tả kết quả). Đây gọi là tư duy declarative (khai báo) — bạn nói "tôi muốn kết quả trông thế này", còn công cụ lo phần làm thế nào để đạt được nó.

Vì sao IaC quan trọng — các lợi ích cốt lõi

Version controlled (kiểm soát phiên bản): Vì hạ tầng bây giờ là các tệp văn bản, bạn có thể lưu chúng vào Git giống hệt như mã ứng dụng. Mọi thay đổi đều được ghi lại: ai sửa, sửa cái gì, khi nào, vì sao. Nếu một thay đổi làm hỏng hệ thống, bạn chỉ cần "quay ngược" (rollback) về phiên bản trước. Không còn cảnh "hình như hôm qua có ai đó vào sửa firewall mà không nói".

Reproducibility (khả năng tái lập): Cùng một tệp mã sẽ luôn tạo ra cùng một hạ tầng. Bạn có thể dựng môi trường development, staging và production giống hệt nhau chỉ bằng cách chạy cùng một đoạn mã với vài tham số khác nhau. Điều này xóa bỏ hoàn toàn vấn đề kinh điển "trên máy tôi chạy được mà".

Tốc độ và tính nhất quán: Dựng một hạ tầng bằng tay có thể mất vài giờ; với IaC, chỉ mất vài phút và không có sai sót do con người gõ nhầm. Nếu cần 50 máy chủ giống nhau, bạn viết một lần rồi nhân bản.

Tài liệu sống (living documentation): Chính đoạn mã IaC là tài liệu mô tả hạ tầng của bạn. Không còn cảnh tài liệu Word lỗi thời trong khi hệ thống thực tế đã thay đổi — vì mã chính là hệ thống.

Containers là gì?

Nếu IaC giải quyết bài toán "làm sao dựng hạ tầng nhất quán", thì Containers giải quyết bài toán "làm sao đóng gói và chạy ứng dụng nhất quán trên mọi hạ tầng đó".

Một container là một đơn vị đóng gói nhẹ, chứa toàn bộ những gì ứng dụng cần để chạy: mã nguồn, thư viện phụ thuộc (dependencies), runtime, và cấu hình. Nhờ vậy, ứng dụng chạy giống hệt nhau dù ở trên máy tính của lập trình viên, trên máy chủ staging, hay trên production ở cloud.

Để dễ hình dung, hãy nghĩ đến container vận chuyển hàng hóa ngoài đời thật. Trước khi có container tiêu chuẩn, hàng hóa được xếp lộn xộn lên tàu, mỗi loại một kiểu, bốc xếp cực nhọc và chậm. Khi thế giới thống nhất một kích thước container chuẩn, mọi thứ thay đổi: một chiếc container có thể được cẩu từ tàu sang xe tải sang tàu hỏa mà không cần mở ra, vì "vỏ ngoài" luôn giống nhau. Container phần mềm cũng vậy — nó tạo ra một "vỏ tiêu chuẩn" để ứng dụng có thể di chuyển giữa các môi trường mà không bị "vỡ".

Container khác máy ảo (VM) như thế nào?

Đây là điểm hay gây nhầm lẫn. Máy ảo (Virtual Machine) mô phỏng cả một máy tính hoàn chỉnh, bao gồm một hệ điều hành riêng đầy đủ. Vì thế mỗi VM thường nặng vài GB và khởi động mất vài phút.

Container thì nhẹ hơn nhiều vì nó chia sẻ nhân (kernel) của hệ điều hành máy chủ, chỉ đóng gói riêng phần ứng dụng và thư viện của nó. Một container thường chỉ nặng vài chục đến vài trăm MB và khởi động trong vài giây, đôi khi vài phần trăm giây.

Hệ quả thực tế: trên một máy chủ vật lý, bạn có thể chạy có lẽ 10 VM, nhưng lại có thể chạy hàng trăm container. Đó là lý do container giúp tận dụng tài nguyên hiệu quả hơn rất nhiều và trở thành nền tảng của kiến trúc microservices hiện đại.

IaC và Containers phối hợp ra sao?

Hai khái niệm này bổ trợ cho nhau một cách đẹp đẽ. IaC dựng ra sân khấu — máy chủ, mạng, cụm máy để chạy container. Containers là diễn viên — các ứng dụng được đóng gói để triển khai lên sân khấu đó. Một quy trình DevOps trưởng thành thường dùng IaC để tạo ra một cụm hạ tầng, rồi triển khai các container ứng dụng lên cụm đó — tất cả đều được mô tả bằng mã và lưu trong Git.

Tình huống thực tế

Tình huống 1: Startup fintech ở TP.HCM và cơn ác mộng "server tuyết"

Một startup fintech tại Quận 1, TP.HCM (gọi là công ty Momo-like giả định, quy mô 30 người) vận hành hệ thống thanh toán trên 8 máy chủ được dựng thủ công qua hai năm. Mỗi máy chủ được các kỹ sư khác nhau chỉnh sửa dần theo thời gian — người thêm gói này, người sửa cấu hình kia. Kết quả: không máy nào giống máy nào. Dân trong nghề gọi đây là hiện tượng snowflake server (máy chủ "bông tuyết" — mỗi cái độc nhất, không thể tái tạo).

Một đêm, ổ đĩa của máy chủ thanh toán chính bị hỏng. Đội kỹ thuật mất 11 tiếng để dựng lại một máy tương đương, vì không ai biết chính xác cấu hình gốc là gì — họ phải mò mẫm so sánh với các máy khác. Trong 11 tiếng đó, hệ thống thanh toán gián đoạn, gây thiệt hại doanh thu và uy tín.

Sau sự cố, công ty áp dụng IaC: toàn bộ cấu hình 8 máy chủ được viết lại thành mã Terraform và Ansible, lưu vào Git. Ba tháng sau khi một máy khác gặp sự cố tương tự, họ dựng lại toàn bộ trong 9 phút.

Bài học rút ra: Hạ tầng dựng bằng tay là một khoản nợ kỹ thuật vô hình — nó chỉ "phát nổ" đúng vào lúc bạn cần nó nhất. IaC biến quy trình khôi phục từ "khảo cổ học" thành "chạy một lệnh".

Tình huống 2: "Trên máy em chạy được mà!" — nỗi đau của đội phát triển

Một công ty phần mềm gia công (outsourcing) ở Đà Nẵng có đội 12 lập trình viên làm một ứng dụng Node.js cho khách Nhật. Mỗi bạn cài Node phiên bản khác nhau trên laptop của mình — người dùng Node 16, người Node 18, có bạn còn cài qua Homebrew, có bạn cài trực tiếp. Ứng dụng chạy ngon trên máy các bạn, nhưng khi đưa lên máy chủ test của khách (chạy Node 14) thì lỗi tràn lan.

Mỗi lần như vậy, đội mất trung bình nửa ngày chỉ để tìm ra nguyên nhân là "lệch phiên bản môi trường", chứ không phải lỗi logic thật sự. Trong một sprint hai tuần, họ ước tính đã đốt gần 20 giờ công chỉ cho loại lỗi vô nghĩa này.

Giải pháp: họ đóng gói ứng dụng thành container. Từ đó, mọi lập trình viên, máy chủ test và production đều chạy cùng một container với đúng một phiên bản Node và đúng các thư viện. Lỗi "lệch môi trường" gần như biến mất hoàn toàn.

Bài học rút ra: Container không chỉ là công nghệ triển khai — nó xóa bỏ tận gốc câu nói kinh điển "trên máy em chạy được mà" bằng cách đảm bảo môi trường chạy luôn giống nhau ở mọi nơi.

Tình huống 3: Sàn thương mại điện tử và ngày sale 12/12

Một sàn thương mại điện tử tầm trung ở Đông Nam Á cần mở rộng hệ thống gấp 5 lần cho ngày sale 12/12, rồi thu nhỏ lại sau đó để tiết kiệm chi phí. Nếu dựng máy chủ bằng tay, việc mở rộng và thu hẹp sẽ là ác mộng hậu cần.

Nhờ kết hợp IaC (mô tả cụm hạ tầng bằng mã) và Containers (ứng dụng đóng gói sẵn, khởi động trong vài giây), đội vận hành chỉ cần đổi một con số trong tệp cấu hình — từ "10 phiên bản ứng dụng" thành "50 phiên bản" — và chạy một lệnh. Hệ thống tự mở rộng trước giờ G và tự thu hẹp sau khi hết sale. Chi phí cloud tháng đó chỉ tăng đúng phần dùng thêm trong vài ngày cao điểm.

Bài học rút ra: Sự kết hợp IaC + Containers biến "khả năng co giãn" (elasticity) từ một dự án hạ tầng khổng lồ thành một thao tác đổi tham số. Đây là nền tảng cho mọi hệ thống hiện đại cần chịu tải biến động.

Hướng dẫn từng bước

Dưới đây là lộ trình tư duy để bắt đầu áp dụng IaC và Containers cho một dự án. Ở giai đoạn này, tập trung vào quy trình và cách nghĩ, chưa cần thuộc lòng cú pháp công cụ.

  • Xác định trạng thái mong muốn của hạ tầng. Trước khi viết bất kỳ dòng mã nào, hãy liệt kê rõ: bạn cần bao nhiêu máy chủ, cấu hình ra sao, mạng và firewall thế nào, ứng dụng cần gì để chạy. Viết ra giấy trước.
  • Chọn công cụ IaC phù hợp. Với việc cung cấp hạ tầng cloud (tạo máy chủ, mạng), Terraform là lựa chọn phổ biến. Với việc cấu hình bên trong máy chủ (cài phần mềm), Ansible thường được dùng. Bạn sẽ học chi tiết ở các bài sau — giờ chỉ cần biết chúng tồn tại để làm gì.
  • Đóng gói ứng dụng thành container. Viết một tệp mô tả (Dockerfile) liệt kê: ứng dụng dựa trên nền tảng gì, cần cài thư viện nào, chạy lệnh gì để khởi động. Kết quả là một "image" — bản đóng gói ứng dụng có thể chạy ở mọi nơi.
  • Đưa mọi thứ vào Git. Cả tệp IaC lẫn Dockerfile đều phải nằm trong hệ thống quản lý phiên bản. Đây là bước biến hạ tầng của bạn thành thứ có thể theo dõi, review và rollback.
  • Thử tái lập. Bài kiểm tra thật sự: xóa toàn bộ môi trường test rồi dựng lại chỉ từ mã. Nếu bạn dựng lại được y hệt mà không cần thao tác tay nào, bạn đã làm đúng.
  • Lặp lại và cải tiến. Mỗi thay đổi hạ tầng từ nay trở đi đều phải đi qua mã, không sửa tay lên hệ thống đang chạy. Đây là kỷ luật quan trọng nhất.

Lỗi thường gặp & mẹo

Lỗi 1 — Sửa tay lên hệ thống đang chạy ("drift"). Đây là sai lầm phổ biến nhất. Bạn viết mã IaC đàng hoàng, nhưng khi có sự cố gấp, bạn SSH vào máy chủ sửa nhanh bằng tay. Giờ trạng thái thực tế đã "trôi" (drift) khác với mã. Lần sau chạy IaC, nó có thể ghi đè bản sửa tay của bạn, gây sự cố mới. Mẹo: luôn sửa qua mã, kể cả khi gấp. Nếu buộc phải sửa tay, phải cập nhật lại mã ngay sau đó.

Lỗi 2 — Nhét bí mật (secrets) vào mã rồi đẩy lên Git. Rất nhiều người vô tình commit mật khẩu, API key, chứng chỉ vào tệp IaC hay Dockerfile công khai. Mẹo: không bao giờ để secrets trong mã. Dùng biến môi trường hoặc công cụ quản lý bí mật (bạn sẽ học ở bài về Vault, KMS sau này).

Lỗi 3 — Container quá "béo". Người mới thường đóng gói cả một hệ điều hành đầy đủ vào container, khiến image nặng hàng GB, chậm và dễ dính lỗ hổng bảo mật. Mẹo: dùng base image tối giản (như phiên bản alpine hoặc slim), chỉ cài đúng thứ cần thiết.

Lỗi 4 — Coi container như VM. Nhiều người xem container như một máy chủ nhỏ để lưu trữ dữ liệu lâu dài. Sai. Container nên là stateless (không giữ trạng thái) và có thể bị xóa/tạo lại bất cứ lúc nào. Dữ liệu quan trọng phải lưu ở nơi khác (volume, database). Mẹo: hãy nghĩ về container như "gia súc chứ không phải thú cưng" (cattle, not pets) — thay thế được, không nâng niu.

Mẹo tổng quát: Bắt đầu nhỏ. Đừng cố IaC-hóa toàn bộ hạ tầng khổng lồ ngay ngày đầu. Chọn một dịch vụ nhỏ, đóng gói nó thành container, viết IaC cho phần hạ tầng của nó, rồi mở rộng dần.

Bài tập thực hành

Bài tập 1 — Phân tích hạ tầng thủ công (không cần máy tính): Hãy chọn một hệ thống bạn biết (dự án cá nhân, hệ thống ở công ty, hoặc một ví dụ giả định). Liệt kê ra giấy tất cả các bước cần làm để dựng nó từ đầu bằng tay. Sau đó đánh dấu những bước nào dễ bị quên hoặc dễ gõ sai. Đây chính là những chỗ IaC sẽ cứu bạn.

Bài tập 2 — Vẽ sơ đồ "sân khấu và diễn viên": Vẽ một sơ đồ đơn giản mô tả một ứng dụng web điển hình. Khoanh vùng phần nào là hạ tầng (sẽ do IaC quản lý: máy chủ, mạng, database) và phần nào là ứng dụng (sẽ đóng gói thành container). Việc phân biệt rạch ròi hai lớp này là kỹ năng tư duy nền tảng.

Bài tập 3 — So sánh chi phí thời gian: Với hệ thống ở Bài tập 1, hãy ước lượng: dựng lại bằng tay mất bao lâu? Nếu có IaC thì mất bao lâu? Viết ra con số cụ thể. Bài tập này giúp bạn nói chuyện được với sếp bằng ngôn ngữ chi phí — kỹ năng cực kỳ giá trị của một DevOps engineer.

Bài tập 4 — Nhận diện "drift": Đọc lại phần lỗi thường gặp, rồi tự viết ra một kịch bản trong đó việc sửa tay lên hệ thống gây ra sự cố. Mô tả nó sẽ xảy ra thế nào và cách phòng tránh. Hiểu sâu về drift sẽ giúp bạn tránh sai lầm phổ biến nhất của nghề.

Tóm tắt

Trong bài này, chúng ta đã tìm hiểu hai trụ cột nền tảng của DevOps hiện đại. Infrastructure as Code (IaC) là phương pháp quản lý hạ tầng bằng các tệp mã nguồn thay vì thao tác thủ công, mang lại ba lợi ích cốt lõi: khả năng kiểm soát phiên bản qua Git, khả năng tái lập chính xác giữa các môi trường, và tốc độ cùng tính nhất quán vượt trội. Tư duy quan trọng nhất của IaC là chuyển từ làm thủ công sang khai báo trạng thái mong muốn.

Containers là các đơn vị đóng gói nhẹ, chứa toàn bộ những gì ứng dụng cần để chạy giống hệt nhau ở mọi môi trường. Khác với máy ảo, container chia sẻ nhân hệ điều hành nên nhẹ hơn, khởi động nhanh hơn và tận dụng tài nguyên hiệu quả hơn rất nhiều — đây là nền tảng cho microservices và các hệ thống co giãn theo tải.

Qua ba tình huống thực tế — từ startup fintech TP.HCM với "snowflake server", đội phát triển ở Đà Nẵng với nỗi đau lệch môi trường, đến sàn thương mại điện tử co giãn cho ngày sale — bạn đã thấy IaC và Containers không phải lý thuyết suông mà giải quyết những vấn đề rất cụ thể, tốn kém tiền bạc và thời gian thật.

Điều quan trọng cần ghi nhớ: IaC dựng sân khấu, Containers là diễn viên, và cả hai đều sống trong Git dưới dạng mã. Ở các bài tiếp theo, chúng ta sẽ đào sâu vào từng công cụ cụ thể — Terraform, Docker, Kubernetes — nhưng nền tảng tư duy bạn vừa xây dựng ở đây sẽ theo bạn suốt cả hành trình. Hãy nhớ kỷ luật vàng của nghề: mọi thay đổi đều đi qua mã, không sửa tay lên hệ thống đang chạy.

Học xong bài này rồi? Tạo tài khoản miễn phí để lưu lại — lần sau vào là biết ngay đang dở ở đâu, và học hết khóa thì có chứng chỉ. Lưu tiến độ của tôi