Trọng tâm của tự động hóa dần dần: Do-nothing scripting (2019)
(blog.danslimmon.com)- Trong đội ngũ vận hành vẫn còn những quy trình thủ công (toil) khó có thể loại bỏ hoàn toàn, như thay đổi hạ tầng hay cấp phát tài khoản, và khi công ty lớn dần thì số bước cùng ngoại lệ cũng tăng lên
- Mỗi bước đều có vẻ có thể tự động hóa, nhưng nếu chỉ script hóa một phần thì số công cụ đơn mục đích sẽ tăng lên, còn người dùng vẫn phải làm theo tài liệu quy trình dài
- Do-nothing script không tự động thực thi công việc thực tế, mà bọc từng bước của quy trình thành các hàm rồi hướng dẫn người dùng từng bước một
- Người dùng ít có khả năng mất dấu vị trí hiện tại hoặc bỏ sót bước, và về sau lập trình viên cũng dễ thay phần câu hướng dẫn của một bước cụ thể bằng mã tự động hóa thực sự
- Dù khối lượng công việc thủ công trước mắt không giảm, cách này làm hạ chi phí khởi đầu của tự động hóa, để có thể dần dần loại bỏ toil theo thời gian
Khi quy trình thủ công trở thành cực hình
- Mọi đội ngũ vận hành đều vẫn có những quy trình thủ công chưa thể tự động hóa, và rất khó để toil biến mất hoàn toàn
- Ở các công ty đang phát triển, những quy trình như thay đổi hạ tầng hay cấp phát tài khoản người dùng rất dễ trở thành trung tâm của toil lớn
- Một quy trình cấp phát tài khoản người dùng có thể gồm nhiều bước như sau
- Tạo cặp khóa SSH của người dùng
- Commit khóa công khai vào Git và push lên master
- Chờ job build hoàn tất
- Kiểm tra địa chỉ email của người dùng trong thư mục nhân viên
- Gửi khóa riêng cho người dùng qua 1Password
- Trong môi trường thực tế, quy trình có thể kéo dài đến 20 bước, hoặc trong lúc thực hiện phải liên tục theo dõi các nhánh rẽ và trường hợp đặc biệt
- Những công việc như vậy đòi hỏi rất nhiều tập trung, nhưng gần với việc đánh thêm một dấu kiểm trong danh sách hơn là giải quyết vấn đề thú vị, nên trở thành một công việc nặng nề
Khoảng trống mà tự động hóa một phần để lại
- Công việc nặng nề như vậy trông có vẻ là mục tiêu lý tưởng để tự động hóa
- Rất dễ nghĩ ra cách tự động hóa từng bước
- Máy tính có thể thực hiện chỉ dẫn nhanh hơn và chính xác hơn con người
- Khả năng xảy ra practical drift cũng thấp hơn
- Vấn đề là việc tự động hóa kiểu này thường tạo cảm giác như hoặc tất cả, hoặc không gì cả
- Bạn có thể viết script chỉ xử lý bước 2 hay bước 5, nhưng sự phiền toái của toàn bộ quy trình sẽ không giảm đi bao nhiêu
- Khi số script đơn mục đích tăng lên, mỗi công cụ lại có quy ước và hành vi kỳ vọng khác nhau, và người dùng vẫn phải theo tài liệu gồm nhiều bước
Cách Do-nothing script hoạt động
- Gần như mọi công việc nặng nề đều có thể được chuyển thành Do-nothing script
- Cốt lõi là đưa chỉ dẫn của công việc đó vào mã, rồi đóng gói từng bước thành một hàm
- Luồng của script ví dụ như sau
CreateSSHKeypairStepin ra lệnhssh-keygenvà chờ người dùng nhấn EnterGitCommitStepsao chép khóa công khai vào kho Git rồi hướng dẫn chạygit commit,git pushWaitForBuildStephướng dẫn chờ hoàn tất tại URL của job buildRetrieveUserEmailSteptìm địa chỉ email trong thư mục và nhận đầu vào để lưu vàocontext["email"]SendPrivateKeyStephướng dẫn tạo tài liệu khóa riêng trong 1Password và chia sẻ với người dùng có email đó
- Script này không thực sự thực hiện bất kỳ bước nào của quy trình, mà chỉ hướng dẫn người dùng từng bước rồi chờ hoàn tất thủ công
Con đường dẫn tới tự động hóa
- Thoạt nhìn, Do-nothing script có thể giống như đang biến tài liệu thành thứ còn khó đọc hơn, nhưng trên thực tế nó giúp giữ luồng công việc an toàn hơn
- Người dùng ít có khả năng mất dấu tiến độ hoặc bỏ qua bước
- Dễ duy trì tập trung và hoàn thành công việc nặng nề đến cùng
- Mỗi bước được tách thành hàm riêng nên có thể thay phần văn bản của một bước cụ thể bằng mã hành động thực sự
- Theo thời gian sẽ hình thành thư viện các bước có thể tái sử dụng, giúp việc tự động hóa sau này hiệu quả hơn
- Bản thân Do-nothing script không làm giảm khối lượng công việc thủ công của cả nhóm
- Tác dụng của nó nằm ở việc tạo ra trạng thái dễ bắt đầu tự động hóa hơn, và từ đó cả nhóm có thể dần loại bỏ toil theo thời gian
1 bình luận
Ý kiến trên Hacker News
Tôi rất thích cách tiếp cận này
Nhìn tổng thể, đây là một cách khác để định nghĩa giao diện quanh một quy trình. Quy trình đó có thể là thủ công hoặc được tự động hóa, nhưng giao diện vẫn có thể được giữ nguyên. Vì vậy nó khá mạnh mẽ khi tự động hóa từng bước
Cứ áp dụng giống hệt như với các hệ thống khác
Trước đây tôi từng điền Google Sheets thủ công rồi tự động hóa bằng script, và cũng từng để hệ thống tự động nhặt và xử lý khi tạo ticket Jira. Có thể bắt đầu nhanh hơn, chỉ tự động hóa phần phiền nhất, và cũng không nhất thiết phải tự động hóa toàn bộ
Một hiệu ứng phụ của script không làm gì là nó có khả năng được dùng thực tế cao hơn tài liệu, nên có thể được cập nhật thường xuyên hơn
Bản thân danh sách các script tự động hóa những tác vụ phổ biến thì tôi đồng ý. Nhưng ngay khi các script đó bắt đầu được gọi từ dịch vụ vận hành, nó sẽ tạo ra một khoản nợ kỹ thuật khổng lồ cho người xui xẻo phải gỡ mớ spaghetti đó
Xa hơn nữa, vì quy trình lấy con người làm trung tâm đã mã hóa cả hệ thống, nên những thay đổi có lợi cho hệ thống phần mềm, chẳng hạn như tách hệ thống thành các component, sẽ trở nên bất khả thi. Cuối cùng, mở rộng dần sẽ trở thành việc nhồi thêm nhiều thứ vào quy trình, và điều đó biến thành một vòng tự tăng sinh tiếp tục chắp vá vào script monolith
Trong khi thực hiện bước 3 và 4, hãy để quy trình được lặp đi lặp lại, được càng nhiều người dùng càng tốt, rồi điều chỉnh quy trình theo những cách dùng sai thấy được ngoài thực tế
4) tự động hóa quy trình
Ai cũng đồng ý với 1 và 2, đa số cuối cùng cũng sẽ theo 4, nhưng nếu làm 3 thì sẽ có nhiều người hơn yêu cầu và hiểu 4
Tuy nhiên, giới hạn của cách tiếp cận này là nếu có thể tự động hóa phần đầu hoặc phần cuối của quy trình thì ổn, nhưng nếu có hai điểm tự động hóa tách rời như những hòn đảo ở giữa, thì nó cũng chẳng tốt hơn một công cụ dòng lệnh có prompt
Chỉ cần mô tả việc cần làm, cung cấp boilerplate hoặc ví dụ, và file thực thi có tham số hóa
Dùng Notebooks như một hệ thống tài liệu trên thực tế nghe có vẻ tuyệt. Chỉ là nó quá nặng để đặt thành một lớp bên trên SaaS đám mây như Confluence, và với hình thức hiện tại thì cũng có quá nhiều khả năng phát sinh các vấn đề như leo thang đặc quyền
Cách tiếp cận này biến trang hướng dẫn Confluence thành một walkthrough bán tương tác. Đây là phía có ý thức
Phía còn lại là tự động hóa kiểm thử. Ban đầu nó khởi đầu bằng một đống XPath bị overfit và các bước không được tài liệu hóa. Mỗi khi ứng dụng thay đổi, bạn lại phải phát hiện lại các bước đó. Đây là phía vô thức
Hy vọng là có thể lên tới đỉnh, chạy thật nhanh, mà vẫn biết mình đã đi tới đó như thế nào và vì sao lại như vậy
Chỉ cần hỏi xác nhận người dùng kiểu
Execute command (y/N)?là đượcTôi rất ghét việc copy rồi paste từ terminal này sang terminal khác. Việc đó cũng ngốn rất nhiều sự tập trung
Chỉ cần hỏi người dùng về những thao tác thủ công chưa phải là lệnh:
Look up the e-mail address for foo. Paste it here:hoặcPut that shit in 1Password: Are you done (y/N)?Một cách tiếp cận thú vị
Nhưng tác vụ được đưa làm ví dụ chỉ cho thấy cách cấp phát khóa SSH của công ty đó kém an toàn đến mức nào. Trên thực tế, người dùng nên tự tạo khóa riêng, rồi chỉ chuyển khóa công khai cho quản trị viên hệ thống để họ cấp quyền truy cập. Ở bất kỳ thời điểm nào, quản trị viên hệ thống cũng không được có bản sao khóa riêng, dù chỉ là tạm thời. Vì vậy bản thân bước 1Password lẽ ra không cần tồn tại
Nhân tiện, tôi là tác giả của github-keygen, một công cụ tự động hóa việc tạo khóa SSH chuyên dùng cho truy cập GitHub và cấu hình SSH trong ngữ cảnh đó
https://github.com/dolmen/github-keygen
người dùng phải tự tạo khóa riêng và chỉ chuyển khóa công khai cho quản trị viên hệ thốnglúc nào cũng khó chịu khi triển khaiChúng tôi đã chuyển từ SSH sang xác thực dựa trên chứng chỉ, và không còn chuyển khóa công khai đi khắp nơi nữa. Toàn bộ quy trình thật sự đã đơn giản hơn
Khoảng một năm sau khi bài viết này được đăng lần đầu, cuối cùng tôi cũng thử cách này
Do lỗi trong toolchain của chúng tôi, runbook cho hotfix phức tạp hơn quy trình phát hành thông thường khoảng gấp đôi
Tuy không được đánh giá cao đến mức đó, nhưng trước đây thứ chỉ được dùng khoảng 10 tuần một lần cho sự cố sev 1 hoặc các epic ở giai đoạn hoàn tất thì nay được dùng trung bình mỗi tuần một lần, có tuần tới 3 lần. Khi không còn phải biến mọi thứ thành feature toggle nữa, chúng tôi có thể đào sâu vào nợ kỹ thuật hơn nhiều
Nếu là một công ty nhỏ và dễ sao chép dữ liệu production sang môi trường tiền production, có thể bạn sẽ không thấy kết quả như vậy. Nhưng chúng tôi có hơn 150 endpoint phải giao tiếp, tôi nghĩ trung bình khoảng 3 endpoint cho mỗi dịch vụ. Có rất nhiều dataset, và một số trong đó được thu thập theo kiểu giống Kafka trước khi Kafka tồn tại
Chỉ có một người cố gắng sao chép dữ liệu production, và người đó cũng thiếu thời gian lẫn năng lượng nên mỗi năm chỉ làm được một hoặc hai lần. Tốc độ đó chậm hơn rất nhiều so với tốc độ thay đổi của khách hàng và tính năng. Cuối cùng chúng tôi phải mày mò quy trình triển khai blue-green và jmeter để xem mình đã tiệm cận đến đâu, cũng như đo thành công/thất bại trước khi lên live như thế nào
Rốt cuộc thứ cản mọi người lại là quy trình build lặt vặt và dễ lỗi, và chỉ sau khi tôi bán tự động hóa nó thì vấn đề mới được tháo gỡ
Về sau, khi mức sử dụng tăng lên, chúng tôi tìm tất cả URL trong các bước thủ công và đưa vào bảng tra cứu trong công cụ, đồng thời hiển thị chúng trong quy trình kiểm chứng thông thường để phê duyệt phát hành. Nhờ đó coordinator làm việc nhanh hơn một chút và bớt căng thẳng hơn. Quy trình đó phiền đến mức ba đội phải luân phiên đảm nhiệm để chia sẻ gánh nặng
Nói “giảm năng lượng kích hoạt của việc tự động hóa tác vụ” rốt cuộc có nghĩa là script không làm gì cả sau này sẽ có các bước thực sự tự động hóa điều gì đó phải không?
Nếu xem nó như một placeholder cho tự động hóa trong tương lai, thì đây có vẻ là điểm cân bằng hợp lý giữa tự động hóa và hiệu quả. Bạn có thể thử bước đầu mà không đầu tư quá nhiều, và để lại những trái thấp dễ hái cho lúc nỗ lực đó trở nên rõ ràng là đáng giá hơn
Vì từng bước của quy trình giờ đã được đóng gói thành hàm, nên có thể thay phần văn bản của một bước cụ thể bằng code tự động thực hiện hành động thật
class Foo(object): def run(self, context): ...Đối tượng chỉ có một phương thức thực thi thực ra đã được tích hợp sẵn trong Python rồi. Đó chính là hàm
def foo(context): ...Với cách dùng hàm, nếu cần hàm mới thì bạn sẽ thêm nó ở cấp global. Một hai hàm thì hoàn toàn ổn, nhưng khi nhiều hơn, cùng một cấp sẽ đầy các hàm xếp cạnh nhau và quan hệ phụ thuộc giữa chúng không còn rõ ràng nữa
Một trong số đó nói về các ví dụ đơn giản hóa code bị abstraction hóa một cách không cần thiết
Tuyệt, nhưng không thể dừng giữa chừng
Sẽ tốt hơn nếu hiển thị trước tất cả các bước và đánh dấu từng mục khi tiến hành. Đôi khi chuẩn bị từ góc nhìn rộng hơn thực sự là điều nên làm
Cũng có thể ghi bản tóm tắt vào file dưới dạng log
Có quá nhiều thứ có thể cải thiện, nên có lẽ giải pháp đơn giản nhất lại là tốt nhất
Tuy nhiên, script shell không làm gì cả dễ bắt đầu đến mức khó mà không làm cho xong. Có thể dùng công sức đó để tự động hóa luôn một bước thì tốt hơn. Bạn rất dễ sa vào vũng lầy thú vị nhưng không mấy hiệu quả như nên dùng thư viện TUI nào, cấu trúc ra sao
Mỗi bước là một rule có tên
*.done, và khi hoàn thành thì tạo file.done. Bạn có thể dừng bất cứ lúc nào, sửa script để khắc phục gì đó rồi tiếp tục bằngmakeNhưng viết Makefile đó thật sự rất đau khổ. Có giải pháp nào tốt hơn không?
./do-the-thing.sh 2025, tạo thư mục 2025 và lưu trạng thái xem đã làm đến đâuKhi phê duyệt bước đầu tiên, có thể
touchfile2025/first-step. Nếu script chết hoặc bị dừng rồi chạy lại, nó kiểm tra file đó và bỏ qua bước đầu tiênKhi có gì đó thay đổi khiến tự động hóa không chạy được, sẽ rất tốt nếu có thể thoát ra mà không mất trạng thái, sửa script rồi chạy lại
Thường thì tôi để script chỉ thông báo một bước thủ công tiếp theo rồi thoát. Như vậy có thể dùng terminal cho việc khác. Có thể dễ dàng chạy lại script từ lịch sử lệnh
Cũng có các thảo luận trước đó. Rất nhiều bình luận
https://news.ycombinator.com/item?id=29083367 - 3 năm trước, 230 bình luận
https://news.ycombinator.com/item?id=20495739 - 6 năm trước, 124 bình luận
Tôi không thể nói quá lên được là mình thích cách tiếp cận này đến mức nào
Tôi đã áp dụng thành công cho nhiều dự án. Ví dụ tôi thích nhất là một robot phẫu thuật trị giá 30 triệu đô la từng thất bại trong kiểm thử phòng thí nghiệm vì “yếu tố con người”
Tôi làm trong một lĩnh vực khác là hành nghề luật, nhưng muốn suy nghĩ xem có thể áp dụng cách tiếp cận này vào công ty của chúng tôi như thế nào
Tôi thích cách tiếp cận này. Ngay cả với các hệ thống dựa trên ngôn ngữ lập trình có độ phức tạp từ một mức nào đó trở lên, tôi cũng thích làm những thứ tương tự. Trong lập trình hàm, có vẻ người ta gọi thứ này là lỗ trống (holes)
Lỗi
not implementedcủa interface cũng theo logic tương tự, nhưng tôi cho rằng việc viết ra những thứ nhỏ nhặt, tuy không có ý nghĩa nhưng tạo ra đầu ra hợp lệ cho từng mảnh trong nhiều mảnh phụ thuộc lẫn nhau, có giá trị đáng kể. Khi đó quá trình tạo ra các mảnh đó sẽ nhanh hơn, và khả năng kiểm thử rồi xây dựng từng thứ một sẽ lớn hơn nhiều. Nhu cầu phải viết nhiều phần cùng lúc trước khi bắt đầu kiểm thử cũng giảm điTrong ngữ cảnh script như trường hợp sử dụng được nói tới trong bài, đôi khi tính hợp lệ ở cấp độ kiểu dữ liệu như vậy khó trở nên quan trọng. Vì từ góc nhìn lập trình hàm, khá nhiều hiệu ứng của dòng lệnh có lẽ là tác dụng phụ. Nhưng vì nó diễn ra tuần tự nên ảnh hưởng nhỏ hơn nhiều, và nhờ các prompt chờ, ta có thể bảo toàn thứ tự công việc với một chút chi phí, đồng thời vẫn giữ các bước thủ công vốn dù không có script thì cũng phải làm
Giàn giáo tuy không hoàn chỉnh, nhưng về căn bản là hữu ích
Về lý thuyết thì tốt, nhưng thực tế có vẻ sẽ khó
Nếu đội vận hành đang lặp đi lặp lại cùng một công việc và thấy rằng một script không làm gì thực sự không làm gì cả, thì ngay khi họ nghĩ mình đã thuộc các bước, hoặc cảm thấy làm thủ công nhanh hơn hay thú vị hơn, họ sẽ nhanh chóng ngừng dùng nó
Tôi đã viết nhiều tài liệu và tự động hóa cho đội vận hành, nhưng việc khiến mọi người dùng chúng và tiếp tục dùng chúng luôn là một vấn đề. Ngay cả thay đổi tài liệu cũng cần được thông báo. Khi mọi người đã biết làm một việc gì đó, họ sẽ nhanh chóng không đọc tài liệu nữa
Trong một thế giới hoàn hảo, cách tiếp cận này rất hợp lý, và với công việc cá nhân thì có lẽ tôi cũng có thể dùng. Nhưng thực tế hiếm khi hoàn hảo. Nếu là tôi, tôi có lẽ chỉ dùng cách này khi 90% đã được tự động hóa và chỉ còn 1 bước chưa giải quyết được. Ngay cả khi đó, một số người trong đội vận hành vẫn có thể bỏ qua bước thủ công đó và mặc định rằng toàn bộ là một phép màu đã tự động hóa