- Kubernetes đã dẫn dắt cuộc cách mạng điều phối container trong 10 năm qua
- Nhiều giới hạn và nhu cầu cải tiến đã được quan sát thấy ở cấu hình YAML, sự phụ thuộc vào etcd, quản lý gói bằng Helm hiện nay
- Áp dụng HCL, kho lưu trữ dạng plugin, trình quản lý gói mới (KubePkg), đặt IPv6 làm mặc định, v.v. đang được thảo luận như các yếu tố thay đổi của Kubernetes 2.0
- Cấu trúc mở hiện tại vẫn quan trọng, nhưng giá trị mặc định và định hướng chính thức có ảnh hưởng mang tính quyết định đến đổi mới của hệ sinh thái
- Đã xác nhận rằng Kubernetes cần trở nên phù hợp hơn với nhiều người dùng và tổ chức hơn thông qua cải tiến mang tính đột phá liên tục
10 năm của Kubernetes: thành công và giới hạn
Khởi đầu và tăng trưởng
- Trong giai đoạn 2012~2013, những tin đồn về Borg, hệ thống container Linux nội bộ của Google, bắt đầu lan rộng trong cộng đồng sysadmin
- Năm 2014, Kubernetes được công bố, và ban đầu ngay cả cái tên cũng khó phát âm
- Microsoft, RedHat, IBM, Docker cùng nhiều công ty lớn nhanh chóng tham gia, giúp Kubernetes bắt đầu trở thành tiêu chuẩn của hệ sinh thái
- Năm 2015, việc phát hành v1.0 và sự ra đời của CNCF đã mở ra một hệ sinh thái mở một cách thực sự
Những điểm đổi mới chính
Quản lý container ở quy mô lớn
- Kubernetes mang lại khả năng mở rộng cho phát triển và triển khai phần mềm dựa trên container
- Nó cho phép triển khai cùng một môi trường ở quy mô lớn, từ môi trường phát triển đơn giản đến hàng nghìn máy chủ
- Các tổ chức có thể lấy đó làm động lực để chuyển từ kiến trúc monolithic sang microservice phân tán
Bảo trì chi phí thấp và tự phục hồi
- Việc quản lý máy chủ đã chuyển biến nhanh chóng từ thời đại "Simpsons" (mỗi máy chủ có biệt danh riêng, vận hành thủ công) sang thời đại "UUID" (thay thế hoàn toàn, tự động hóa, phi trạng thái)
- Khái niệm vòng đời máy, thời hạn hỗ trợ của OS gần như biến mất; khi hỏng hóc, hệ thống sẽ tự tái cấu hình bằng cách “tạo lại node”
- Nhiều kỹ năng Linux giờ đây không còn là điều kiện bắt buộc, mà trở thành dạng “có thì tốt”
Xử lý batch và quản lý Job
- Xử lý batch từng phụ thuộc vào các “máy chuyên cron” trong quá khứ nay được thay thế bằng các tác vụ tự động hóa dựa trên hàng đợi và cơ chế retry
- Việc tự động khởi động lại khi tác vụ thất bại cùng cách xử lý linh hoạt đã giúp tăng mạnh hiệu quả vận hành và mức độ hài lòng của nhà phát triển
Service discovery và load balancing
- Thay vì hardcode địa chỉ IP, hệ thống áp dụng cơ chế đặt tên dịch vụ dựa trên DNS nội bộ
- Kết nối giữa các dịch vụ được đơn giản hóa bằng API, IP cố định, hostname, và cả dịch vụ bên ngoài cũng có thể được xử lý như dịch vụ nội bộ
Kubernetes 2.0: các đề xuất cải tiến cốt lõi
Từ YAML sang HCL, thay đổi ngôn ngữ cấu hình
Giới hạn của YAML
- YAML dễ nhìn và có vẻ tốt hơn JSON hay XML, nhưng vẫn tồn tại những vấn đề nghiêm trọng như dễ gây lỗi, không hỗ trợ kiểu dữ liệu, khó debug
- Ví dụ) vấn đề Na Uy ("NO" bị diễn giải là false), lỗi thụt lề, nhầm lẫn giữa chuỗi và số cùng nhiều yếu tố dễ gây sự cố khác
Giải pháp thay thế: dùng HCL
- HCL (HashiCorp Configuration Language) là định dạng chuẩn của Terraform, cung cấp các tính năng mạnh như kiểu dữ liệu chặt chẽ, xác thực, hàm, rẽ nhánh điều kiện
- Đã có khá nhiều cụm Kubernetes sử dụng HCL cùng với Terraform
- HCL sở hữu nhiều khả năng mạnh hơn YAML như an toàn kiểu dữ liệu, giảm trùng lặp, cấu hình động, xử lý lặp, logic điều kiện, hỗ trợ comment tốt, tính module và kiểm tra tính hợp lệ
- Vấn đề giấy phép mã nguồn mở (MPL 2.0 → khả năng tương thích với Apache 2.0) vẫn còn, nhưng giá trị mà nó mang lại cho việc nâng cao chất lượng là đủ lớn
Ví dụ: HCL vs YAML
- Nhờ các ưu điểm của HCL như kiểu dữ liệu, biến, hàm, câu điều kiện, vòng lặp, có thể ngăn ngừa lỗi cấu hình từ sớm, cải thiện khả năng bảo trì và đảm bảo tính nhất quán ngay cả trong môi trường phức tạp
Hỗ trợ tùy chọn thay thế etcd
- etcd rất mạnh mẽ, nhưng với các cụm nhỏ hoặc môi trường cấu hình thấp thì lại tiêu tốn tài nguyên quá mức
- Có nhu cầu mở rộng tính linh hoạt của kho lưu trữ mặc định thông qua việc chính thức hỗ trợ backend dạng plugin như Kine
- Ví dụ) k8s-dqlite: cung cấp một tầng dữ liệu nhẹ và linh hoạt dựa trên SQLite phân tán + Raft
Vượt qua Helm: trình quản lý gói native
Giới hạn của Helm
- Helm là trường hợp một giải pháp hack tạm thời trở thành tiêu chuẩn, và tồn tại nhiều vấn đề như độ phức tạp của template, khó debug, xung đột phụ thuộc/phiên bản, thiếu xác thực
- Trong thực tế có rất nhiều khó khăn như chart trùng lặp, lệch phiên bản, khó cài đặt giữa các namespace, thiếu tìm kiếm chart/metadata, không tuân thủ semantic versioning, quản lý CRD không an toàn
Đề xuất hệ thống gói mới: KubePkg
- Quản lý toàn diện ở dạng tài nguyên Kubernetes từ gói/phụ thuộc/semantic versioning/bảo mật/vòng đời/metadata
- Được trang bị đầy đủ lifecycle hook tinh vi, chiến lược trạng thái và backup/restore, cấu hình khai báo, quy trình ký có thể xác minh, bản ghi audit, kiểm soát chính sách theo tổ chức
- Mục tiêu là kế thừa ưu điểm của trình quản lý gói Linux để mang lại độ tin cậy và tính nhất quán mạnh mẽ cho quản lý hạ tầng thực tế
Các yêu cầu chính
- Cấu trúc tài nguyên native hoàn chỉnh của Kubernetes
- Hỗ trợ tích hợp cho ứng dụng có trạng thái
- Tăng cường quy trình ký/xác thực/quét bảo mật
- Cấu hình khai báo có cấu trúc + xác thực schema
- Kiểm soát toàn bộ vòng đời và hỗ trợ Upgrade/Hook đơn giản
- Phân giải phụ thuộc/phiên bản theo phong cách Linux
- Lịch sử thay đổi và truy vết kiểm toán
- Khả năng áp dụng chính sách theo tổ chức
- Mang lại UX quản lý gói Linux quen thuộc
Chuyển sang mặc định IPv6
- Hiện tại IPv6 và dualstack đã được hỗ trợ, nhưng mặc định vẫn là IPv4
- Điều này có lợi thế trong việc giải quyết giao tiếp giữa các cụm, vấn đề NAT, tình trạng thiếu IP, đồng thời giúp cấu trúc mạng đơn giản hơn và có IPSec tích hợp
- Trong các môi trường cần nhiều IP ở quy mô lớn (ví dụ: dải /20, 40 node, 30 pod trên mỗi node), giới hạn của IPv4 sẽ nhanh chóng bị chạm tới
- Các lợi ích thực tế như đơn giản hóa vận hành trong môi trường IPv6 công cộng, thu hút người dùng cloud và giảm gánh nặng quản lý vùng địa chỉ riêng là rất rõ ràng
Kết luận: sự cần thiết của thay đổi và sức mạnh của giá trị mặc định
- Có ý kiến cho rằng “đây là nền tảng mở nên cộng đồng sẽ tự lo”, nhưng giá trị mặc định mới là thứ dẫn dắt cách hành xử của cả ngành
- Kubernetes 2.0 là thời điểm cần có niềm tin chính thức, thiết kế xuất sắc và các giá trị mặc định mạnh mẽ
- Đây là giai đoạn quan trọng để có một bước nhảy mới mẻ tương xứng với vị thế là tiêu chuẩn của ngành và xu hướng chủ đạo trong vận hành trung tâm dữ liệu toàn cầu
- Trong nhiều lĩnh vực công nghệ như mobile hay web, những thay đổi táo bạo đã nhiều lần thúc đẩy đổi mới cho toàn bộ hệ sinh thái
- Giờ cũng là lúc Kubernetes suy nghĩ về chặng tiếp theo thông qua một cột mốc 2.0 mang tính biểu tượng
2 bình luận
Có lẽ từ nay về sau vẫn sẽ chỉ có số ít kỹ sư có thể xây dựng và vận hành vanilla k8s được ghép lại từ các mã nguồn mở.
Cũng giống như trước đây đã có cực kỳ ít kỹ sư có thể vận hành hệ sinh thái Hadoop thuần thay vì mua cụm Hadoop được đóng gói trong nền tảng Cloudera.
Ý kiến trên Hacker News
Vấn đề lớn nhất của Kubernetes, theo tôi, là nó không phải kiểu hệ thống “cứ thế là chạy tốt”. Trên thực tế, chỉ có số ít kỹ sư có thể vận hành dịch vụ trơn tru trong môi trường production, và việc tự dựng rồi duy trì một cụm Kubernetes trên VM còn khó hơn nhiều. Đó cũng là lý do các startup serverless đang nổi lên gần đây: ngày càng lan rộng nhận thức rằng Kubernetes (1) tốn rất nhiều thời gian, (2) rất dễ phát sinh lỗi, và (3) có xác suất thất bại cao trong môi trường production. Với Kubernetes 2.0, tôi nghĩ nên đi theo hướng bất kỳ ai cũng có thể dễ dàng tự host nền tảng triển khai và dùng nó một cách tự tin, đồng thời vẫn giữ một lõi orchestrator nhỏ gọn nhưng mạnh mẽ. Tôi đang trực tiếp phát triển một orchestrator và nền tảng triển khai tên là Rivet, tự nhận là nền tảng serverless mã nguồn mở Rivet, nhưng bản thân tôi cũng thường xuyên tự hỏi: “Kubernetes 2.0 sẽ trông như thế nào?”. Ngày càng có nhiều trường hợp mọi người áp dụng Rivet cho những kịch bản vượt ngoài kỳ vọng ban đầu. Điểm mạnh lớn nhất của Rivet là có thể dễ dàng phát triển các tính năng ở cấp độ Kubernetes controller, nhờ đó có thể dùng cho nhiều kịch bản như game server, triển khai theo từng tenant, điều phối workload nâng cao, multi-tenancy, tính phí theo tenant, thiết kế operator mạnh mẽ, v.v.
Tôi khá dị ứng với góc nhìn này. Có lẽ vì tôi cũng có tuổi rồi và hơi hoài nghi một chút, nhưng đây là mô-típ tôi thấy lặp đi lặp lại. Công nghệ X quá nặng, nên có người nói “tôi chỉ muốn chạy đơn giản trên laptop mà không cần mớ này” rồi tạo ra công nghệ Y. Sau đó Y cũng trở nên phổ biến, và khi người ta cần mở rộng để chạy ở những nơi không còn là laptop nữa, nó lại được bổ sung đủ thứ tính năng và trở nên nặng nề. Rồi sẽ lại có người nói “giờ Y cũng quá nặng rồi” và lặp lại y nguyên câu chuyện. Nó giống như 'Bánh xe thời gian', cứ lặp mãi không có điểm bắt đầu hay kết thúc.
Thực tế thì k3s (k8s hạng nhẹ) thật sự rất dễ bảo trì. Chỉ cần auto-update cho k3s và có eviction rule hợp lý thì gần như không cần đụng vào nữa; nếu storage như Ceph quá khó thì cũng có thể chọn các lựa chọn “gần như không cần quản trị” như Lemon hoặc Longhorn. Có hàng nghìn Helm chart nên ngay cả database phức tạp cũng có thể triển khai trong 1 phút. Triển khai service cũng rất dễ nếu chỉ dùng các Helm template phổ biến. Helm không hoàn hảo, nhưng nếu cấu hình đúng ý thì còn được hưởng những thứ như autocomplete cho values. Rào cản gia nhập có cao hơn serverless một chút, nhưng bỏ ra cỡ một tuần để học mà tiết kiệm được hàng chục triệu won trong production thì hoàn toàn xứng đáng.
Bài toán mà Kubernetes giải quyết là: “Triển khai cái này như thế nào?”. Nhìn vào Docs của Rivet thì chỉ thấy single container, Docker Compose và triển khai thủ công (lệnh Docker). Tôi nghi ngờ liệu có thể triển khai hạ tầng serverless ở quy mô thực tế bằng cách đó không. Câu hỏi đầu tiên của tôi là: “Đến mức này rồi, sao không chạy Rivet trên Kubernetes (container, kube-virt, v.v.) luôn?”. Tôi không hiểu Docker Compose có thể vững chắc hay mở rộng tốt hơn Kubernetes ở điểm nào. Nếu không phải vậy mà lại bán như một dịch vụ cloud, thì điều đó cũng không khớp với ý tưởng Kubernetes 2.0. Nếu tôi là người tự host Rivet thì có lẽ tôi sẽ sửa tài liệu để có thể chạy nó trên Kubernetes.
Nếu đang dùng “k8s-as-a-service”, tức giao việc bảo trì cụm cho nhà cung cấp cloud, thì tôi khá tò mò điều gì lại khiến mọi thứ có cảm giác phức tạp đến vậy. Phạm vi cấu hình thì rộng thật, nhưng để đưa một service thực tế vào production thì chỉ cần biết một số ít cấu hình là đủ. Chỉ cần mức cấu hình phức tạp hơn Docker Compose một chút là đã có thể triển khai lên k8s rồi. Tuy nhiên, với phần lớn ứng dụng, ngay cả phần “hơn một chút” đó cũng có thể là không cần thiết. Thực ra đây chính là nhu cầu đại chúng mà Docker Compose từng hướng tới, và khá tiếc là nó không nhận được sự quan tâm bền bỉ hơn.
Kinh nghiệm của tôi trong vận hành hạ tầng là sẽ không bao giờ có thứ gì “cứ thế là chạy tốt”. Ngay cả Heroku cũng gặp vấn đề khi scale. Nếu muốn có một nền tảng triển khai mà ai cũng có thể dễ dàng tiếp cận, thì thực tế hơn là hiểu Kubernetes như primitive nền tảng đứng dưới một PaaS nào đó. Rivet khá thú vị, độc đáo và còn cho thấy một vài ý tưởng từ hệ sinh thái BEAM. Cá nhân tôi quan tâm đến độ vững chắc và local-first hơn là triển khai ở quy mô lớn.
“Low maintenance” à... Tôi dùng EKS (managed k8s) khá nhiều, và đúng là tôi không cần tự lo về tình trạng của cluster (tất nhiên đó là chưa tính những cách sáng tạo nào đó để tự tay phá nát node). Kubernetes đúng là rất giỏi tỏ ra như thể “gần như không cần bảo trì”, nhưng thực tế thì nó là một khối bảo trì thuần túy. Chỉ cần đưa ra yaml là có thể lập tức triển khai phần mềm ra thế giới, điều đó thật sự rất ấn tượng. Nhưng cái giá phải trả chính là độ phức tạp của việc bảo trì. Thiết lập cluster, khởi tạo ArgoCD, đăng ký các cluster khác trong mô hình hub-and-spoke... tất cả chỉ là một màn xiếc mở màn. Sau đó còn phải cài các operator dùng được từ tooling trong CNCF Landscape, rồi các công cụ ancillary (về mặt lý thuyết không phải tier-1 nhưng thực tế lại bắt buộc), tổng cộng khoảng ít nhất 30 thứ đang chạy. Chỉ riêng cấu hình
values.yamlthôi cũng không phải chuyện một hai tiếng, mà phần lớn là công việc với ArgoCD và template. Từ Secrets Manager -> External Secrets -> ArgoCD ApplicationSet -> mộtvalues.yamlkhác, nhiều khi chỉ để truyền một giá trị boolean mà cũng tốn cả đống thời gian. Chu kỳ cập nhật cluster/operator lại nhanh, nên đây là nguồn cơn bảo trì thường trực. Khi autoscale bằng Karpenter thì thay node và giữ zero-downtime lại biến thành một màn xiếc khác nữa (ứng dụng có state trên k8s thì “niềm vui” tăng gấp đôi). Tóm lại: “Low maintenance” thực sự là một cách nói mỉa mai.“Low maintenance” rốt cuộc chỉ là khái niệm mang tính tương đối so với các lựa chọn thay thế. Theo kinh nghiệm của tôi, khi dùng k8s thì gánh nặng bảo trì để đạt cùng chất lượng dịch vụ ở các mặt như scale, failover, rollback, disaster recovery, DevOps, spin up cluster độc lập... thấp hơn rất nhiều. Tùy tình huống có thể khác, nhưng với tôi là như vậy.
Tôi đã dùng k3s trên hetzner suốt 2 năm qua và có 100% uptime. Gánh nặng bảo trì thấp đến mức có lần tôi còn làm mất SSH key của master node, nhưng việc reprovision toàn bộ cluster, kể cả cập nhật tài liệu, cũng chỉ mất 90 phút. Nếu thật sự khẩn cấp thì có lẽ 15 phút là đủ. Tôi đang vận hành một cluster k8s với giá 20 euro/tháng gồm 3 node ARM, 1 master, một ít storage và DNS tự động tích hợp với Cloudflare.
Nhưng thứ bạn thực sự đang quản lý không phải bản thân Kubernetes, mà là các hệ thống phụ trợ như CI/CD, quản lý secret, tự động hóa vận hành database. Trước đây người ta sẽ làm những việc đó bằng cronjob, ansible, systemd, bash script... thay vì yaml.
Nghe như tự tay dựng lấy một rạp xiếc vậy. Đừng cài nhiều thứ đến thế. Mỗi lần thêm một món là lại cộng thêm technical debt và chi phí bảo trì, kể cả khi đó là công cụ miễn phí. Nếu autoscale mang lại nhiều nợ và chi phí vận hành hơn số tiền tiết kiệm được thì tốt nhất cứ tắt nó đi.
Nếu phải tự lắp ghép và vận hành một tập dịch vụ tương tự theo kiểu riêng lẻ thì gánh nặng bảo trì còn lớn hơn nhiều. Nhưng Kubernetes cũng dễ quản lý đến mức có thể để đó sau khi đã dập xong lửa. Dĩ nhiên điều kiện là bạn phải biết mình đang làm gì để không sa vào cám dỗ cài mấy “công cụ trông ngầu”.
K8S đâu có bắt buộc phải dùng yaml. Có thể đó là cách idiomatic, nhưng không phải bắt buộc.
kubectl applyngay từ đầu đã hỗ trợ cả json, còn endpoint thì là json và grpc. Cũng có thể sinh config từ nhiều ngôn ngữ khác nhau như jsonnet. Thứ hai, tôi không hiểu vì sao dependency và dependency ordering lại trở thành vấn đề trong Helm chart. Idiom chính của Kubernetes nằm ở loop: nếu dependency chưa có thì ứng dụng coi đó là recoverable error và cứ retry cho đến khi có thể chạy được. Hoặc nó crash, rồi ReplicaSet controller sẽ tự khởi động lại. Nếu chart không có dependency thì cũng chẳng có xung đột dependency nào. Nếu thực sự là ứng dụng có phụ thuộc chặt chẽ thì hợp lý nhất là gói luôn app/service phụ thuộc đó vào trong Helm chart.(Trích ý kiến chính) > Việc ReplicaSet controller khởi động lại ứng dụng khi crash là chưa đủ. Ví dụ nếu Keycloak mất 1 phút để khởi động, thì service phụ thuộc vào nó sẽ crash ngay vì chưa có Keycloak, rồi retry cho đến khi bị throttle, thành ra sau khi Keycloak đã lên rồi vẫn phải chờ vô ích 5–10 phút nữa. Nếu quan hệ phụ thuộc đã rõ ràng thì tốt hơn nên dùng init container để kiểm tra service phụ thuộc trước khi chuyển sang main container. Tôi nghĩ sẽ rất hay nếu Kubernetes có cơ chế khai báo start dependency một cách tường minh. Crash rồi retry vài lần đến mức bị throttle không phải là đáp án. Dependency đơn giản là một thực tế không thể tránh.
Tôi cho rằng lỗi dependency phải là thứ có thể phục hồi được. Trước đây tôi từng gặp sự cố vì hệ thống fail-closed chỉ vì một dependency mà thực tế chẳng dùng đến. Dependency giữa các server hầu như đều là soft dependency. Nếu downstream dependency không hoạt động thì cứ trả về 500, rồi load balancer sẽ tránh các server unhealthy là được.
Người ta cứ nói “supposed to”, nhưng điều đó chỉ thật sự phù hợp khi xây dựng một software stack in-house. Cũng có rất nhiều phần mềm cũ, làm sẵn, vốn chỉ hỗ trợ Docker rồi sau này mới được đem lên chạy trên Kubernetes. Khi nhà phát triển tạo công cụ theo đúng triết lý của riêng mình, người dùng rốt cuộc vẫn sẽ dùng nó theo cách họ muốn, và kết quả có thể thành một mớ hỗn độn. Cuối cùng vẫn phải cho người dùng nhiều tính năng và lựa chọn, còn thị trường thì sẽ sử dụng theo cách họ muốn.
Việc phản bác bằng luận điểm “ngoài yaml ra còn dùng được json” thực ra chẳng đụng đến trọng tâm. Đó không phải điều mà mọi người thật sự quan tâm. Tôi thấy đó là một kiểu bắt bẻ vô ích.
Tôi phản đối mạnh ý kiến thay yaml bằng HCL. HCL rất khó nhìn và khó đọc với nhà phát triển. Tôi cũng có nhiều phàn nàn về usability như có hỗ trợ import hay không, độ khó khi debug, v.v. Tôi không hiểu vì sao lại không đặt một ngôn ngữ định nghĩa interface như protobuf vào trung tâm rồi cho người dùng tự chuyển đổi ra hình thức họ thích.
HCL là tệ nhất. Chỉ với yaml của k8s tôi chưa bao giờ thấy thiếu. Nếu cấu hình đang quá phức tạp thì có lẽ vấn đề gần với thiết kế ứng dụng hơn là do config map.
Thực ra HCL, JSON hay YAML thì phía client chỉ cần serialize/deserialize là xong. Tức là đây không phải vấn đề của bản thân Kubernetes, mà chỉ là một lớp chuyển đổi bên ngoài.
Giao diện định nghĩa của Kubernetes vốn đã dựa trên protobuf rồi (trừ CRD).
Phàn nàn lớn nhất của tôi về HCL là cú pháp
forloop. Thật sự tệ khủng khiếp.Cái kiểu nói “HCL khó với developer, khó lint và khó debug” nghe giống như không muốn học cái mới hơn. Có vẻ như người ta đang nhầm lẫn giữa việc học HCL với độ phức tạp của chính domain.
Tôi đang phát triển dự án nebulous theo kiểu “Kubernetes 2.0” (vẫn còn ở giai đoạn pre-alpha). Mục tiêu là: phân tán toàn cầu / hạng nhẹ, có thể chạy single binary trên laptop nhưng cũng scale được tới hàng nghìn node trên cloud, có Tailnet network / BitTorrent storage / multi-tenancy / live migration, v.v. Phần lớn yêu cầu đến từ vận hành ML (đặc biệt là tình trạng thiếu GPU), và nếu sau này ML trở thành chuyện bình thường thì có lẽ đây sẽ là mặc định.
Live migration nghe rất thú vị. Hiện tại chúng tôi đang dùng chiến lược giá dựa trên autoscaling giữa nhiều cluster và nhiều cloud, còn live migration là một cấp độ thách thức hoàn toàn khác.
Cái này không phải Kubernetes, mà là một hệ thống riêng chuyên biệt cho vận hành GPU.
“Phân tán toàn cầu” có khi lại là một non-requirement. Nếu lấy Tailnet làm mạng mặc định thì đây lại là tính năng tôi muốn bỏ ngay đầu tiên. Việc Kubernetes mặc định giả định single NIC là một di sản khó chịu, quá thiên về cloud (nên tôi rất mừng khi có nhiều CNI và gần đây là các dự án như Multus; tham khảo: blog của Red Hat). Tôi cũng tò mò thiết kế multi-tenant này thực chất khác gì so với k8s. Nếu dùng BitTorrent cho storage, mà còn chia sẻ cả public container image nữa, thì phí egress traffic sẽ rất khủng.
Nhìn trên GitHub tôi thấy có
Chart.yaml, thậm chí các template nhưprovider_aws.yamlcũng là kiểu pattern code mà tôi thật sự ước là đừng làm vậy.Tôi vẫn thấy Kubernetes hiện giờ cực kỳ phức tạp. Chỉ là vì nó đã quá phổ biến nên người ta ít cảm thấy thế hơn thôi. Ở Kubernetes 2.0, tôi muốn trải nghiệm người dùng, đặc biệt là các tác vụ vận hành thường gặp (triển khai app, expose service, đổi service account/image, v.v.) được đơn giản hóa hơn nữa. Nhưng vì bây giờ mọi thứ đều xoay quanh LLM nên có vẻ khó mà có nhiều phát triển tiếp nối.
Kubernetes có quá nhiều lớp trừu tượng. Pod là một khái niệm lõi rất hay, nhưng rồi deployment, rep set, namespace... cứ chồng thêm lên khiến tôi ước gì nó đơn giản được như Docker Swarm. Terraform cũng chỉ có một lớp duy nhất và dễ học hơn nhiều. Tôi đang thật sự cảm nhận được đường cong học tập của K8s dốc đến mức nào.
Đây là kiểu vấn đề khiến tôi nghĩ rằng “việc phân loại type trong chương trình máy tính thực chất là sản phẩm của nhận thức con người”. Operator/controller bị trừu tượng hóa quá mức, kiểu như COM/CORBA ngày xưa (vừa là ưu điểm vừa là nhược điểm). Với những triển khai đơn giản, một kiểu k8s-lite hạn chế hơn có khi lại phù hợp hơn. Ngược lại, trong môi trường phức tạp thì đôi khi ngay cả các trừu tượng hiện có của k8s vẫn còn chưa đủ. Tôi nghi ngờ liệu một hệ thống duy nhất (dù là Kubernetes 2.0 hay gì khác) có thể bao trùm toàn bộ các vấn đề thực tế theo cách mà lập trình viên/kiến trúc sư con người vẫn có thể xử lý nổi hay không.
Tôi muốn một hệ thống có “sane default”, tức là dù không chọn gì đặc biệt thì trạng thái mặc định vẫn đủ ổn cho network / storage / load balancer, v.v. Tôi đều không thích cả yaml lẫn HCL. Cần một cách cấu hình tốt hơn, và chỉ đổi ngôn ngữ thôi thì không giải quyết được vấn đề. Tôi nghĩ IPv6 là bắt buộc. Docker, container và Kubernetes lẽ ra đều phải là IPv6-only ở bên trong, còn IPv4 nên chỉ là trường hợp ngoại lệ do ingress controller xử lý.
Giữa “sane defaults” và “chuyển đổi khách hàng sang dịch vụ managed” tồn tại một xung đột bản chất. Càng theo dõi k8s lâu, tôi càng thấy triết lý “batteries not included” ở các phần như storage/network ngày càng đậm, và AWS/GCP thì bán các dịch vụ tích hợp đắt đỏ xoay quanh chính chỗ trống đó. Trên thực tế, k8s ngày nay đôi khi không còn giống một dự án mã nguồn mở thuần túy, mà giống một công cụ thúc đẩy bán hàng nhằm lấp khoảng trống cloud hơn.
(Kinh nghiệm cá nhân) Terraform/HCL tốt hơn YAML ở chỗ nó không phụ thuộc vào các ký tự vô hình nên dễ đọc hơn.
Chính vì “sane defaults” mà tôi thích k3s hơn rất nhiều.
Tôi thấy đây là một wishlist hơi khiêm tốn cho một bản phát hành 2.0. Xung quanh tôi ai cũng bất mãn với độ phức tạp của k8s trong production. Điểm mấu chốt thật sự là làm sao có được backward compatibility mà vẫn giữ được sự đơn giản. Thông thường chính backward compatibility làm độ phức tạp bùng nổ (vì hệ thống mới phải gánh cả tính năng cũ lẫn mới).
Tôi có cảm giác mình đã sống trong “thế giới Kubernetes 2.0” rồi, khi quản lý cluster và ứng dụng bằng Terraform.
tf applylà có thể dựng cluster, node, tích hợp cloud (S3, v.v.) và cả service trong cluster cùng lúccloudflaredtrong cluster + cấu hình tunnel qua Cloudflare API)Với tư cách người xuất thân từ frontend, tôi lại thấy Kubernetes khá trực quan. Trước đây tôi nhận dữ liệu đầu vào rồi dựng UI theo kiểu reactive, còn bây giờ cảm giác như đang viết code để đồng bộ resource và config với control plane vậy.