Khóc cười chuyện học Azure Cloud DevOps Nanodegree

Đây là mẩu chuyện bi hài trong quá trình hoàn thành Nanodegree Azure Cloud DevOps. Dù hơi vật vã nhưng tôi đã thu được vài trải nghiệm hay ho, có thể giúp bạn tránh được các vấn đề không mong muốn khi học chương trình này.

Upload image

Bạn tôi bảo tôi đổi bút danh thành “Hơi Dại” sau câu chuyện này, mà tôi nghĩ cũng đáng như thế thật. Ban đầu khi tôi tham gia khoá học Azure Cloud DevOps trong chương trình Nanodegree của Udacity, tôi chỉ dự định viết lại một bài giới thiệu tổng quan để mọi người tham khảo. Nhưng rồi tôi lại không trải qua khoá học một cách “êm đềm” như đã tưởng. Nên những điều chia sẻ trong câu chuyện này sẽ chỉ là trải nghiệm của tôi.

Câu chuyện xuất phát từ một thử thách của sếp dành cho các anh em trong team: chọn học một khoá trong chương trình Nanodegree và hoàn thành trong một tháng. Chương trình gồm các khoá học đa dạng về Azure, AWS, Data… Mỗi khóa thường yêu cầu học viên dành khoảng 10h mỗi tuần và kéo dài trong 3 đến 5 tháng. Cả team được ưu tiên dành thời gian cho việc học các khoá này, nên phải hoàn thành sớm hơn là chuyện đương nhiên (sếp bảo thế).

Sau khi tìm hiểu và cân nhắc, tôi chọn học khoá Azure Cloud DevOps. Một phần vì tôi đã quen với các Azure service nên dự là có thể “đua” bài được. Phần khác vì tôi không thường làm việc với Azure DevOps lắm, (mấy việc này tôi hay đẩy cho anh bạn Nekogami nên cũng định nhân cơ hội này “lấy lại căn bản” luôn.

Khoá học Azure Cloud DevOps có 3 phần:

  • Phần một: Infrastructure as Code với Terraform và Azure service
  • Phần hai: CI/CD và cách cài đặt deployment pipeline với Azure DevOps
  • Phần ba: Các công cụ đảm bảo chất lượng và cách tích hợp chúng vào deployment pipeline

Mỗi phần sẽ có một project để thực hành các kiến thức đã học.

Phần một: Kể cũng nhàn

Về phần đầu tiên, tôi khá quen thuộc với nội dung học do đã từng viết Terraform để deploy Azure service vài lần trước đây. Bên cạnh đó, bài học còn nói về Azure policy và các practice khác để thực hiện việc bảo mật trên môi trường Azure. Project của phần này gồm tạo một policy yêu cầu các resource phải gắn tag khi được tạo, sử dụng packer để tạo image, và viết một tập tin Terraform để deploy VM availability set.

Tôi hoàn thành và nộp bài project đầu tiên khá nhanh, và được “trả về” cũng… nhanh không kém. Có một số điểm mà bài của tôi còn thiếu so với checklist (tôi không để ý là có checklist). Checklist này đưa ra nhiều yêu cầu cụ thể hơn so với đề bài. Sau khi sửa theo thì tôi “qua cửa”.

Phần hai: Trong cái khó ló cái hơi khôn

Phần thứ hai học về Agile Development và cách cài đặt CI/CD bằng Azure Pipelines. Trước khi bước vào project 2, tôi quyết tâm làm thật kỹ bài tập Azure Pipeline để nắm vững kiến thức. Nhìn hướng dẫn từng bước kèm hình minh hoạ vô cùng rõ ràng và chi tiết của bài tập, tôi đã không nghĩ rằng thực tế mình lại mất thời gian hơn nhiều.

Sau khi chỉnh sửa python flask source code được cung cấp để deploy lên Azure WebApp, đến đoạn tạo account Azure DevOps và setup pipeline. Mỗi bước đều có hình minh hoạ nên bài tập trông có vẻ thật đơn giản. Pipeline được tạo cũng từ template sẵn có của Azure DevOps (Python to Linux Web App on Azure) nên hầu như không phải chỉnh sửa gì nhiều.

Và đây là kết quả khi thực thi pipeline của tôi:

Upload image

OK thôi… làm gì có chuyện bấm phát ăn ngay. Tôi tìm hiểu nhẹ lỗi mình gặp phải là gì, hoá ra đó là do Azure DevOps vừa thay đổi policy, không mặc định cấp Microsoft-hosted parallel job miễn phí như lúc trước, mà người dùng cần điền và nộp form yêu cầu. Quá trình này cần 2-3 ngày để hoàn tất.

Nhưng chờ đợi 2-3 ngày với tôi là quá lâu.

Câu chuyện bắt đầu…

Bên cạnh việc nộp form, tôi đã ngay lập tức chuyển sang phương án thứ hai để thực thi pipeline, đó là sử dụng Self-hosted agent. Nói cách khác, thay vì chạy pipeline trên môi trường Microsoft dựng sẵn thì tôi sẽ cài agent để nhận lệnh và thực thi pipeline trên máy mình. Tôi biết việc này sẽ khoai hơn xài đồ có sẵn của Microsoft, nhưng thử thách một tí mới vui (hoặc mới dại).

Cài agent tool lên máy mình là một việc đơn giản. Chỉ việc tải bộ cài (Windows) hoặc chạy các câu lệnh cài đặt (Linux/MacOS) là có thể run ngay một agent.

Upload image

Tuy việc điều chỉnh pipeline sẵn có để sử dụng Self-hosted agent thay vì Microsoft agent cần phải tìm hiểu một chút nhưng nói chung, tôi cũng thành công trong việc gửi task từ Azure DevOps xuống agent trên máy tôi. Và khi tôi đang hí hửng vì hoàn thành nhiệm vụ cài đặt này thì:

Upload image

Lại lỗi. Nhưng không sao. Agent kết nối được với Azure DevOps là tôi đã thành công được một nửa rồi. Để giải quyết lỗi này, tôi đã phải tra Google loạn cả lên và tìm thấy hint trong… tài liệu của Microsoft về tổ chức folder để cài tool cho agent.

Upload image

Tổ chức folder như vậy thì dễ rồi, nhưng đặt nội dung gì vào thư mục x64/ thì… không thấy tài liệu đề cập rõ ràng. Tuy nhiên với tổ chức thư mục như vậy, tôi đoán rằng nội dung cần có python.exe. Nghĩ vậy nên tôi dùng máy Windows, tải bộ cài Python phiên bản đang cần, và thiết lập cài đặt vào thư mục x64.

Upload image

À ha! Pipeline không báo lỗi nữa. Tôi đã thành công.

Upload image

Sau đó, tôi zip thư mục Python và chuyển qua máy Mac thì agent trên Mac vẫn chạy ổn. Vậy là tôi đã học thêm được cách cài đặt (Python) tool cho Self-hosted agent.

Cần phải nói thêm là ngay sau khi tôi thành công trong việc cài Self-hosted agent thì Microsoft cũng đã cấp Microsoft-hosted parallel job cho account DevOps của tôi. Việc thực thi pipeline trên Microsoft-hosted agent lại không cần phải tốn công sức gì cả. Nên tôi khuyên các bạn sắp học khoá này hãy chuẩn bị sẵn account DevOps và submit form luôn để không bị gián đoạn khi làm project.

May mắn thay, project số 2 là sử dụng Azure Pipeline để setup CD cho python flask app, nên xem như tôi cũng vừa làm xong project của phần này. Một điều thú vị nữa là project này yêu cầu quay phim lại quá trình làm và thuyết minh, sau đó upload video này lên Youtube để nộp bài.

Phần ba: Suýt nữa mất tiền ngu

Phần cuối cùng trong khoá học nói về các công cụ dùng để đảm bảo chất lượng như Postman, Selenium và Jmeter. Project số 3 yêu cầu setup pipeline để chạy các công cụ này tự động, và đưa ra các report cho Regression Test, Data Validation Test, UI Test, Stress Test, và Endurance Test.

Tôi đó giờ không giỏi xài tool cho lắm nên bài tập này cũng làm tôi hơi chật vật. Nhưng phần chính của câu chuyện này lại không phải về việc tôi hoàn thành bài như thế nào, mà là một incident tôi đã vô tình gây ra.

Số là phần pipeline có yêu cầu viết terraform để deploy resource lên Azure. Tôi dùng public github để làm repository. Phải, tôi đã dùng PUBLIC github (vì ở bài tập trước có yêu cầu nộp link github để chấm bài nên tôi cứ nghĩ bài này cũng vậy).

Để cấp quyền cho terraform tạo resource, tôi đã tạo một service principal, và cấp quyền Contributor trên SUBSCRIPTION cho service principal đó. Nhưng tôi cũng biết cẩn thận khi sử dụng public github chứ, nên tôi đã ignore tập tin tftvars (chứa service principal) ra khỏi project lúc commit. Ấy thế mà…

Câu chuyện bắt đầu…

Lúc làm pipeline, thay vì dùng các phương pháp bảo mật để truyền variable, tôi lại để nguyên service principal vào tập tin pipeline.yaml, và cứ thế… commit lên github. Lúc đó, tôi vẫn hoàn toàn không để ý rằng bộ key và secret đủ-quyền-để-tạo-mọi-resource trên account của mình đang nằm public để ai cũng có thể xem.

12h30 trưa hôm sau, tôi tình cờ xem danh mục VM trong account và phát hiện ra rằng có hơn 30 VM đang chạy trên tất cả các region! Tôi bàng hoàng thật sự. Tưởng tượng đến số tiền mà đống VM này phát sinh là tôi phát hoảng (lúc này tôi vẫn chưa tính cụ thể là bao nhiêu), nhưng vẫn phải giữ bình tĩnh để giải quyết vấn đề.

Upload image

Đầu tiên, tôi chụp lại màn hình hiện trạng đang xảy ra, bao gồm các resource được tạo, activity log của các resource này. Qua đó, tôi phát hiện được các resource này được tạo bằng service principal của tôi vào khoảng từ 9h - 10h sáng. Xem thêm activity log của resource group, tôi còn thấy các template deploy spam liên tục, nên chắc chắn là tôi bị hack acc rồi.

Upload image

Sau khi đã thu thập đủ thông tin, tôi tiến hành xoá secret của service principal (để đừng bị spam nữa), và xoá tất cả resource “bị tạo”. Vừa xoá, tôi vừa nghĩ xem tại sao service principal lại bị lộ (tới lúc này tôi vẫn chưa biết luôn), và rồi tôi mới nhớ ra file yaml trên Azure DevOps của mình.

Sau khi xoá xong resource, tôi tính toán sơ sơ thiệt hại. VM mà tôi bị spam là NV6 và D8_v3 (mỗi region chứa 2 VM này là vừa đủ limit 20 CPU được tạo trên account của tôi), tính toán sơ sơ thì số tiền VM đã chạy trong 4h đồng hồ là khoảng $100, chưa tính các phát sinh về network (vì tôi quên check).

Phải đến sáng hôm sau Azure mới cập nhật chính xác cost phát sinh hôm nay, nên hiện tại tôi vẫn chưa biết cụ thể là bao nhiêu. Nhưng tôi cảm thấy hối hận và… tiếc tiền vô cùng.

Phải chi tôi vẫn còn giữ policy tạo tag từ project 1, hoặc ít nhất tôi đã cài đặt các policy khác để giới hạn việc sử dụng resource.

Phải chi tôi dùng các phương pháp bảo mật để bảo vệ service principal thay vì dán nó thẳng vào tập tin sẽ commit lên github.

Phải chi tôi cấp quyền cho service principal đúng nguyên tắc Least Privilege… thì sự việc này đã không diễn ra.

$100 cho một bài học mà tôi vốn đã biết, nhưng chưa thật sự cảm nhận được bao giờ.

Phải đến tận tối hôm đó, tôi mới lấy hết can đảm để báo cáo cho sếp về việc vừa diễn ra (vì tôi làm bài bằng account của sếp mà). Sếp tôi không hài lòng về việc tôi báo cáo sự việc trễ, nhưng đồng thời cũng bảo tôi gửi support ticket cho Azure, vì với các trường hợp này, Azure sẽ kiểm tra, và cấp credit để bù vào khoản phí phát sinh do bị hack.

Tôi vốn không nghĩ Azure cấp credit dễ dàng như thế, nhưng nghe vậy tôi cũng an tâm được phần nào. Account của (sếp) tôi chỉ tạo được ticket với Severity là C, nên tôi đinh ninh rằng cũng phải lâu lắm mới được trả lời. Nhưng chỉ hôm sau là tôi nhận được tin rep ngay: tôi chỉ cần gửi lại thông tin về chi phí phát sinh bằng cách chụp hình Cost Management, Azure sẽ kiểm tra và hoàn phí cho tôi dưới dạng credit. Sau đó tầm 3-4 ngày thì Azure đã xác nhận với tôi về việc này.

Upload image

Tôi pass bài tập thứ 3 và cả khoá học nói chung sau đó một ngày.

Kết lại

Nhìn lại có lẽ giá trị lớn nhất mà khoá học này mang lại cho tôi không phải những điều tôi đã học được thêm, mà là quá trình tôi đã trải qua.

Tôi có vui không? Có, tôi vui vì mình đã không dừng bước khi gặp khó khăn trong câu chuyện Azure DevOps agent.

Tôi có hối tiếc không? Có, trong câu chuyện service principal, nhưng không phải tôi tiếc vì mình đã gây ra incident. Đối với tôi, đó là một bài học giúp thay đổi nhận thức của bản thân. Nhưng tôi tiếc rằng nếu báo với sếp sớm hơn, tôi đã không phải trải qua quãng thời gian cảm thấy thật tồi tệ. Lần kế tiếp (haha) tôi sẽ cố gắng làm điều này.

Tôi có hài lòng không? Có, tôi mừng vì mình đã thay đổi bản thân qua các bài học. Đó thật sự là phần thưởng lớn ở cuối cuộc hành trình. Ban đầu tôi đã không nghĩ rằng mình lại có một câu chuyện dài để kể.

Thật ra tôi cũng không muốn kể lại câu chuyện này, nhưng tôi hy vọng có thể truyền tới bạn cảm hứng để tham gia một khoá học online (một hành trình đáng nhớ), một chút những bài học “đắt giá” (đừng phạm sai lầm như tôi), và những điều mới mẻ mà nếu không bắt đầu thì sẽ không bao giờ nhận ra.

Atekco - Home for Authentic Technical Consultants