- Trong 6 năm qua, Gitpod đã sử dụng Kubernetes để xây dựng một “nền tảng môi trường phát triển từ xa”, hỗ trợ 1,5 triệu người dùng và cung cấp hàng nghìn môi trường phát triển mỗi ngày
- Tuy nhiên, họ nhận ra Kubernetes không phù hợp để xây dựng môi trường phát triển
- Đây không phải là câu chuyện về việc có nên dùng Kubernetes cho production workload hay không, cũng không phải chủ đề về cách tạo trải nghiệm lập trình viên để triển khai ứng dụng lên K8s
→ Đây là câu chuyện về cách xây dựng môi trường phát triển trên đám mây (hoặc cách không nên làm điều đó)
[Vì sao môi trường phát triển là một trường hợp đặc biệt]
- Có nhiều trạng thái và mức độ tương tác rất cao
- Không thể di chuyển giữa các node
- Một lượng lớn mã nguồn, build cache, Docker container, dữ liệu test... thường xuyên thay đổi và chi phí di chuyển rất cao
- Khác với dịch vụ production, ở đây diễn ra tương tác 1:1 giữa lập trình viên và môi trường
- Lập trình viên gắn chặt với mã nguồn và các thay đổi của mình
- Họ không thích bị mất thay đổi trong mã nguồn hoặc bị hệ thống chặn lại
- Môi trường phát triển đặc biệt nhạy cảm với lỗi
- Có mô hình sử dụng tài nguyên khó dự đoán
- Phần lớn thời gian không cần nhiều băng thông CPU, nhưng trong vài trăm ms có thể cần nhiều core cùng lúc
- Chậm hơn mức đó sẽ dẫn đến độ trễ và tình trạng không phản hồi không thể chấp nhận
- Cần quyền hạn và tính năng ở mức rộng
- Không giống production workload, môi trường phát triển cần quyền root và khả năng tải/cài đặt package
- Những gì bị coi là rủi ro bảo mật trong production workload lại là hành vi được mong đợi trong môi trường phát triển (quyền root, tính năng mạng mở rộng, mount thêm filesystem...)
- Chính các đặc tính này khiến nó khác với workload ứng dụng thông thường và ảnh hưởng lớn tới quyết định hạ tầng
[Hệ thống hiện tại: Kubernetes]
- Ở giai đoạn đầu của Gitpod, Kubernetes có vẻ là lựa chọn hạ tầng lý tưởng
- Khả năng mở rộng, điều phối container và hệ sinh thái phong phú rất phù hợp với tầm nhìn về môi trường phát triển trên đám mây
- Nhưng khi quy mô và lượng người dùng tăng lên, họ gặp khó khăn về bảo mật và quản lý trạng thái
- Kubernetes được thiết kế để chạy các application workload được kiểm soát tốt, chứ không phải cho các môi trường phát triển khó kiểm soát
- Quản lý Kubernetes ở quy mô lớn là việc phức tạp
- Các dịch vụ managed như GKE, EKS có giảm bớt một phần vấn đề nhưng lại có những ràng buộc và giới hạn riêng
- Nhiều đội ngũ muốn vận hành CDE có xu hướng đánh giá thấp độ phức tạp của Kubernetes
- Điều này từng dẫn tới gánh nặng hỗ trợ đáng kể với sản phẩm Gitpod self-managed trước đây
Khó khăn trong quản lý tài nguyên
- Phân bổ CPU và bộ nhớ là bài toán khó nhất
- Việc chia sẻ môi trường trên cùng một node có vẻ hấp dẫn, nhưng trên thực tế hiệu ứng noisy neighbor xảy ra rất rõ
- Vấn đề CPU
- Môi trường phát triển có lúc gần như không cần CPU, nhưng cũng có lúc cần rất nhiều trong thời gian ngắn
- Họ đã thử các giải pháp dựa trên CFS, controller tùy chỉnh... nhưng rất khó dự đoán
- Ngay cả khi dùng giới hạn CPU tĩnh thì vẫn xuất hiện tình trạng nhiều process cạnh tranh nhau
- Quản lý bộ nhớ
- Cấp phát bộ nhớ cố định thì đơn giản nhưng hạn chế
- Overbooking có thể dẫn tới việc process bị kill
- Khi swap được đưa vào, nhu cầu overbooking phần nào được giảm bớt
Tối ưu hiệu năng lưu trữ
- IOPS và độ trễ ảnh hưởng trực tiếp tới trải nghiệm môi trường phát triển
- Họ đã thử nhiều cấu hình khác nhau để tìm điểm cân bằng giữa tốc độ, độ ổn định, chi phí và hiệu năng
- SSD RAID 0
- Block storage như EBS, persistent disk
- PVC
- Backup/restore là tác vụ tốn kém
Tối ưu autoscaling và thời gian khởi động
- Mục tiêu ưu tiên hàng đầu là giảm tối thiểu thời gian khởi động
- Họ từng nghĩ rằng chạy nhiều workspace trên một node sẽ cải thiện thời gian khởi động nhờ cache dùng chung, nhưng thực tế không như vậy
- Kubernetes áp một ngưỡng tối thiểu lên thời gian khởi động
- Sự tiến hóa của cách scale-out
- Họ đã thử nghiệm scale-out bằng ghost workspace, ballast pod...
- Việc đưa autoscaler plugin vào đã cải thiện chiến lược mở rộng đáng kể
- Autoscaling theo tỷ lệ để xử lý tải đỉnh
- Khởi động sẵn các pod trống để phản ứng nhanh với nhu cầu tăng đột biến
- Nhiều nỗ lực tối ưu image pull
- Pull trước bằng DaemonSet, tối đa hóa tái sử dụng layer, image được bake sẵn, Stargazer và lazy pulling, Registry-facade + IPFS
Độ phức tạp của networking
- Kiểm soát truy cập vào môi trường phát triển
- Các môi trường phải được cô lập hoàn toàn với nhau
- Network policy có ích, nhưng khi số lượng service tăng lên thì phát sinh vấn đề về độ tin cậy
- Chia sẻ băng thông mạng
- Một số CNI hỗ trợ network shaping, nhưng đó lại là thêm một thứ cần kiểm soát
Bảo mật và cô lập: cân bằng giữa linh hoạt và bảo vệ
- Thách thức lớn nhất là vừa trao cho người dùng sự linh hoạt, vừa cung cấp một môi trường an toàn
- Việc cấp quyền root cho người dùng có nhiều lỗ hổng
- User namespace là giải pháp chi tiết hơn
- Chuyển đổi UID của filesystem, mount
procđã được che giấu, hỗ trợ FUSE, cung cấp tính năng mạng, bật Docker
- Chuyển đổi UID của filesystem, mount
- Khó khăn khi triển khai user namespace
- Ảnh hưởng hiệu năng, vấn đề tương thích, độ phức tạp, và việc theo kịp các phiên bản Kubernetes
[Thử nghiệm Micro VM]
- Khi cảm nhận được giới hạn của Kubernetes, họ bắt đầu khám phá các công nghệ micro VM (uVM) như Firecracker, Cloud Hypervisor, QEMU như một điểm trung gian
- Họ kỳ vọng có thể cải thiện cô lập tài nguyên, tăng cường bảo mật, vẫn tương thích với các workload khác (như Kubernetes...) đồng thời giữ được lợi ích của container hóa
- Ưu điểm của micro VM
- Chúng mang lại nhiều lợi ích hấp dẫn, rất phù hợp với mục tiêu của môi trường phát triển trên đám mây
- Cải thiện cô lập tài nguyên: khả năng overbooking kém hơn, nhưng cô lập tài nguyên tốt hơn container. Không còn tranh chấp tài nguyên kernel dùng chung, nên hiệu năng của từng môi trường phát triển dễ dự đoán hơn
- Memory snapshot và resume nhanh: tính năng
userfaultfdcủa Firecracker hỗ trợ memory snapshot. Điều này cho phép khôi phục gần như tức thì toàn bộ máy, bao gồm cả các process đang chạy. Với lập trình viên, môi trường khởi động nhanh hơn rất nhiều và có thể tiếp tục ngay tại điểm đã dừng - Cải thiện ranh giới bảo mật: uVM có thể đóng vai trò như một biên bảo mật mạnh, giúp cơ chế user namespace phức tạp từng triển khai trên Kubernetes không còn cần thiết. Điều này cũng giúp tương thích hoàn toàn với phạm vi workload rộng hơn, bao gồm container hóa lồng nhau (chạy Docker hay Kubernetes bên trong môi trường phát triển)
- Khó khăn của micro VM
- Tuy nhiên, các thử nghiệm micro VM cũng làm lộ ra một số thách thức lớn
- Overhead: dù là VM nhẹ, uVM vẫn tạo ra overhead lớn hơn container. Điều này ảnh hưởng cả hiệu năng lẫn mức sử dụng tài nguyên, vốn đều là yếu tố quan trọng với nền tảng môi trường phát triển trên đám mây
- Chuyển đổi image: để dùng OCI image trên uVM, cần giải pháp tùy chỉnh để chuyển chúng sang filesystem mà uVM có thể sử dụng. Điều này làm pipeline quản lý image phức tạp hơn và có thể ảnh hưởng tới thời gian khởi động
- Các hạn chế theo từng công nghệ
- Firecracker: không hỗ trợ GPU (ngày càng quan trọng với một số workflow phát triển), không hỗ trợ
virtiofs(hạn chế lựa chọn chia sẻ filesystem hiệu quả) - Cloud Hypervisor: không hỗ trợ
userfaultfd, khiến quy trình snapshot và restore chậm hơn (làm giảm ưu điểm lớn của uVM)
- Firecracker: không hỗ trợ GPU (ngày càng quan trọng với một số workflow phát triển), không hỗ trợ
- Bài toán di chuyển dữ liệu: uVM khiến họ phải xử lý các memory snapshot dung lượng lớn, làm việc di chuyển dữ liệu khó hơn. Điều này ảnh hưởng cả scheduling lẫn thời gian khởi động, vốn là yếu tố cốt lõi của trải nghiệm người dùng trên nền tảng môi trường phát triển đám mây
- Các cân nhắc về lưu trữ: thử nghiệm gắn EBS volume vào micro VM mở ra khả năng mới nhưng cũng đặt ra câu hỏi mới
- Lưu trữ bền vững: nếu giữ nội dung workspace trong volume gắn kèm, họ không cần lặp lại việc lấy dữ liệu từ S3, từ đó có thể cải thiện thời gian khởi động và giảm sử dụng mạng
- Cân nhắc hiệu năng: chia sẻ volume thông lượng cao giữa nhiều workspace được kỳ vọng cải thiện hiệu năng I/O, nhưng cũng làm dấy lên lo ngại về việc triển khai quota hiệu quả, quản lý độ trễ và đảm bảo khả năng mở rộng
- Bài học từ thử nghiệm micro VM
- Dù micro VM cuối cùng không trở thành giải pháp hạ tầng chính, các thử nghiệm này mang lại nhiều góc nhìn quý giá
- Họ đặc biệt thích trải nghiệm backup toàn bộ workspace và tạm dừng/khôi phục trạng thái runtime cho môi trường phát triển
- Đây là lần đầu tiên họ cân nhắc rời khỏi Kubernetes. Sau các nỗ lực tích hợp KVM và uVM vào pod, họ bắt đầu khám phá các lựa chọn ngoài Kubernetes
- Nó cũng giúp họ một lần nữa nhận ra lưu trữ là yếu tố then chốt để đồng thời đạt được ba mục tiêu: hiệu năng khởi động ổn định, workspace ổn định (tránh mất dữ liệu) và tận dụng máy tối ưu
Kubernetes là một nền tảng rất thách thức cho môi trường phát triển
- Như đã nói ở trên, môi trường phát triển cần một hệ thống tôn trọng tính trạng thái đặc thù của nó
- Hệ thống đó phải trao cho lập trình viên đủ quyền để làm việc hiệu quả, đồng thời vẫn đảm bảo ranh giới an toàn
- Và tất cả điều này phải đạt được với overhead vận hành thấp mà không đánh đổi bảo mật
- Ngày nay, có thể làm được toàn bộ điều này bằng Kubernetes, nhưng với chi phí rất lớn
- Họ đã học được theo cách khó khăn về sự khác nhau giữa application workload và system workload
- Kubernetes là một công nghệ tuyệt vời
- Nó có một hệ sinh thái thực sự phong phú, được hậu thuẫn bởi cộng đồng đầy nhiệt huyết
- Nếu bạn đang chạy application workload, Kubernetes vẫn là lựa chọn tốt
- Nhưng với system workload như môi trường phát triển, Kubernetes tạo ra những thách thức rất lớn về bảo mật và overhead vận hành
- Micro VM và ngân sách tài nguyên rõ ràng có ích, nhưng chi phí lại trở thành yếu tố chi phối hơn
- Vì vậy, sau nhiều năm cố gắng thiết kế ngược và ép môi trường phát triển vào nền tảng Kubernetes, họ quyết định lùi lại một bước để suy nghĩ về kiến trúc phát triển của tương lai nên trông như thế nào
- Tháng 1/2024, họ bắt đầu xây dựng điều đó, và tới tháng 10 thì ra mắt Gitpod Flex
- Hơn 6 năm những bài học cực kỳ khó khăn về cách chạy môi trường phát triển an toàn ở quy mô Internet đã được đưa vào nền tảng kiến trúc này
Tương lai của môi trường phát triển
- Với Gitpod Flex, họ kế thừa những khía cạnh nền tảng của Kubernetes — tức việc áp dụng linh hoạt control theory và API khai báo — đồng thời đơn giản hóa kiến trúc và cải thiện nền tảng bảo mật
- Họ dùng một control plane lấy cảm hứng mạnh từ Kubernetes để điều phối môi trường phát triển
- Họ đưa vào các lớp trừu tượng cần thiết dành riêng cho môi trường phát triển và loại bỏ phần lớn độ phức tạp hạ tầng không cần thiết
- Tất cả điều này được thực hiện với bảo mật zero-trust là ưu tiên hàng đầu
- Kiến trúc mới này cũng cho phép tích hợp dev container một cách liền mạch
- Đồng thời mở ra khả năng chạy môi trường phát triển ngay trên desktop
- Vì không còn phải gánh sức nặng của nền tảng Kubernetes nữa, Gitpod Flex giờ có thể được triển khai self-hosted trong chưa tới 3 phút và có thể triển khai trên bao nhiêu region tùy ý
- Điều này mang lại khả năng kiểm soát chi tiết hơn cho tuân thủ và linh hoạt hơn khi mô hình hóa ranh giới tổ chức cũng như domain
(Ban đầu đây là một bài khác, nhưng có vẻ nên gộp lại nên tôi chuyển cùng.)
Gitpod Flex
- Nền tảng tự động hóa đầu tiên cho môi trường phát triển zero-trust
- Được thiết kế để chạy trên laptop, cloud và on-premise, đồng thời giữ mã nguồn, dữ liệu và tài sản trí tuệ bên trong mạng riêng
- Cung cấp các building block để tự động hóa vòng đời phát triển phần mềm, bắt đầu từ môi trường phát triển
- Tự động hóa (Automations)
- Các tác vụ và dịch vụ có thể lập trình, được định nghĩa qua repository hoặc API
- Giúp lập trình viên tự giải quyết vấn đề, đồng thời cho phép đội ngũ năng suất lập trình viên tập trung hóa việc cải thiện môi trường phát triển
- Không chỉ dừng ở việc chạy script đơn giản
- Có thể dùng để provisioning và seeding database, tùy biến workflow của lập trình viên, chạy cluster tạm thời, thiết lập workflow tác nhân dựa trên LLM, áp dụng tập trung bảo mật và tuân thủ ở phạm vi toàn cầu/khu vực...
- Môi trường zero-trust (Zero-trust environments)
- Mọi tác nhân và dịch vụ đều được đối xử theo nguyên tắc “never trust, always verify”
- Chặn hoàn toàn tác nhân độc hại, giảm mạnh bề mặt tấn công, giảm rủi ro malware hoặc rò rỉ mã nguồn
- Bao gồm đánh giá liên tục và xác minh tường minh, mã hóa cấp doanh nghiệp đã được kiểm chứng, kiểm soát truy cập chi tiết, toàn quyền kiểm soát networking và nhật ký audit đầy đủ
- Điều quan trọng nhất là giữ mã nguồn, dữ liệu và tài sản trí tuệ trong mạng riêng
- Gitpod Desktop
- Có thể chuẩn hóa và tự động hóa môi trường phát triển cục bộ
- Bắt đầu hỗ trợ từ Apple Silicon
- Mang lại độ trễ gần như bằng 0, là lựa chọn thay thế nhanh hơn, nhẹ hơn và đơn giản hơn cho Docker Desktop dùng cho phát triển, tối ưu chi phí nhờ tận dụng tài nguyên tính toán cục bộ, đồng thời hỗ trợ khôi phục thảm họa trước gián đoạn cloud hoặc endpoint
- Hỗ trợ Development Container
- Tích hợp hoàn toàn đặc tả Dev Container
- Có thể dùng cấu hình Dev Container hiện có mà không cần thay đổi
- Tương thích với VS Code và các công cụ hỗ trợ khác
- Có thể làm việc nhất quán cả ở local lẫn cloud
- Việc áp dụng tiêu chuẩn Dev Container giúp định nghĩa, chia sẻ và quản lý môi trường phát triển dễ dàng hơn
Sẽ là nền móng cho 10 năm tới của tự động hóa phát triển phần mềm
- Chúng ta đã nghĩ quá hẹp về môi trường phát triển
- Môi trường phát triển không chỉ là IDE, dependency hay công cụ, mà là không gian nền tảng nơi phần mềm được tạo ra
- Đó là nơi diễn ra việc tạo prototype mã, được định hình bởi con người và máy móc, kiểm thử, refactor, biên dịch, đóng gói, ký và triển khai
- Nó mang lại khả năng tiếp cận vô song tới bối cảnh phát triển, workflow và insight, từ đó đem đến những năng lực khác biệt so với các nền tảng phát triển khác
- Tầm nhìn của sản phẩm
- Continuous Integration (CI) sẽ hòa vào môi trường phát triển
- Đóng vai trò là system of record cho phát triển phần mềm
- Trở thành nền tảng cho thế hệ công cụ lập trình viên tiếp theo
- Không chỉ đơn thuần cải thiện thực hành lập trình, mà còn xây dựng con đường nhanh nhất và an toàn nhất để doanh nghiệp từ startup tới Fortune 50 có thể mở rộng và thành công trong 10 năm tới
3 bình luận
Các doanh nghiệp trong nước lấy cớ bảo mật để ép dùng desktop ảo với cấu hình RAM 8GB. Thật chua chát.
Ngay cả việc tìm người giỏi Kubernetes cũng đã khó, nên tôi nghĩ sẽ còn khó hơn nữa để tìm được người có thể hiểu và thử những thứ được đưa ra ở đây như một phương án thay thế.
Ý kiến trên Hacker News
Lập trình viên nên sở hữu thiết bị phát triển mà mình sử dụng. Nếu cần một môi trường nhất quán, lập trình viên nên sở hữu thiết bị của mình và được cung cấp image VM ổn định. Hầu hết các nỗ lực chuyển môi trường phát triển sang host từ xa đều thất bại. Cung cấp phần cứng phù hợp cho lập trình viên có chi phí hiệu quả hơn so với tài nguyên từ xa. Cần hỗ trợ chạy stack cục bộ, và container giúp duy trì tính nhất quán. Cần có công cụ tạo dữ liệu trong môi trường cục bộ, và việc này có thể tự động hóa. Dù có nhược điểm về quản lý dữ liệu, ở đa số công ty, năng lực thực thi của đội ngũ quan trọng hơn mã nguồn.
Việc dùng Kubernetes cho workload production là một vấn đề riêng; ở đây đang nói về cách xây dựng môi trường phát triển trên đám mây. Đây là một bài viết thú vị về các đánh đổi kỹ thuật phức tạp của Kubernetes.
Bài viết mô tả các vấn đề của Kubernetes và những cách đã thử để giải quyết, nhưng lại thiếu giải thích về phương án thay thế cuối cùng được chọn. Có nhắc đến giải pháp mới là Gitpod Flex, nhưng thông tin về nó không nhiều.
Kubernetes phù hợp với workload stateless, nhưng với workload stateful thì LXC phù hợp hơn. LXC có thể được cluster tương tự K8S và cho phép lộ các công cụ ra data plane. Nó cung cấp instance hệ thống tương tự VM, đồng thời có hiệu năng giống container Docker. Nó dùng cú pháp khai báo và có thể được dùng làm lớp nền tảng cho một cụm Kubernetes.
Việc chọn Kubernetes khi xây dựng giải pháp CI cho thấy họ chưa thực sự hiểu rõ vấn đề. Vì mục đích bảo mật, nên dùng các công cụ như Firecracker.
Kubernetes không phù hợp cho môi trường phát triển. Môi trường phát triển luôn ở trong trạng thái thay đổi liên tục. Tôi không hiểu nhu cầu của môi trường phát triển trên đám mây. Mục đích của ứng dụng được container hóa là để tránh phải đồng bộ môi trường phát triển giữa các nhóm.
Bài báo về Kubernetes chỉ nhắc đến tổ hợp workflow độ trễ thấp và độ trễ cao như trường hợp sử dụng duy nhất. Rất khó để biện minh cho việc cân nhắc Kubernetes đối với bài toán của Gitpod.
Tôi từng làm một dự án tương tự Gitpod, và không hiểu việc dùng micro VM để thay thế Kubernetes. Kubernetes có thể điều phối container bên ngoài và có thể được dùng để chạy micro VM. Vấn đề lớn nhất là các vấn đề liên quan đến storage.
Xây dựng môi trường phát triển trên Kubernetes là lãng phí. Nếu sản phẩm được self-host trên hạ tầng của khách hàng, việc debug và hỗ trợ sẽ khó khăn. Việc để kỹ sư nhìn thấy trực tiếp các vấn đề về mạng, bộ nhớ, compute và storage sẽ hiệu quả hơn. Với các đội ngũ lớn, Kubernetes là một bước nâng cấp.