Tìm hiểu về tự động hóa triển khai cho Applications trên Kubernetes (Phần 1)

toannm

Bài này là phần đầu tiên của loạt bài viết cùng chủ đề. Đọc phần thứ hai tại đây.

Chỉ khi là CLI chính thức, thì Kubectl chắc chắn là cách hỗ trợ phổ biến nhất cho Kubernetes clusters. Chạy kubectl apply là cách thuận tiện để có thể hoạt động trên state mong muốn trong các files cục bộ và đồng bộ hóa với cluster.

Tương tự, kubectl apply nhanh cũng dễ dàng chạy như một phần của CI / CD pipeline. Nó hoạt động hiệu quả cho rất nhiều trường hợp thường gặp và có lẽ là điều mà khá nhiều teams hiện đang làm.

PSdivercoral.jpg

Mặc dù hoạt động tốt cho hầu hết mọi trường hợp, nhưng vẫn có một vài edge cases khác cần biết, đó sẽ là chủ đề chính của bài viết này. Đối với teams sử dụng triển khai liên tục, nghĩa là tất cả thành viên trong team cần phải hiểu các edge cases để biết được khi nào cần thực hiện thủ công trước hoặc sau khi chạy tự động hóa.

Kubectl áp dụng Edge Cases

Kubectl apply thực hiện các công việc hậu kỳ, có thể đơn giản hóa bằng cách kiểm tra tài nguyên có tồn tại không và nếu chưa thì nó sẽ tạo ra tài nguyên. Nhưng nếu đã tồn tại, nó sẽ gửi bản vá để cập nhật state mong muốn của tài nguyên.

Nó sẽ làm như vậy trên cơ sở mỗi tài nguyên. Thứ tự của các tài nguyên dựa trên thứ tự các files trong filesystem, thứ tự của các tài nguyên trong một `kind: List` hoặc thứ tự của documents trong multi document YAML. Và đây là vấn đề tiên quyết mọi thành viên trong team cần nắm.

Nếu cấu hình bất kỳ tài nguyên nào thất bại thì nguyên nhân là do kubectl. Tất cả thay đổi đối với tài nguyên trước khi tài nguyên bị lỗi đã được áp dụng, chứ không phải là tất cả thay đổi sau khi tài nguyên bị lỗi - rời khỏi state mong muốn bằng state không mong muốn (lối chơi chữ).

Các phụ thuộc tài nguyên

Các tài nguyên như namespace hoặc Custom Resource Definition (CRD) phải được tạo trước khi tài nguyên khác được đặt vào namespace đó hoặc object tùy chỉnh của loại CRD có thể tạo. Việc tạo Namespace thường nhanh và hiếm khi gây ra sự cố, nhưng phải đảm bảo tạo namespace trước bằng cách sắp xếp các tài nguyên phù hợp.

Mặt khác, ngay cả khi CRDs được sắp xếp chính xác, thì vẫn có xu hướng gây ra edge case này thường xuyên hơn, vì API server mất thời gian để thiết lập các CRD’s REST endpoints. Vì vậy, nếu CRD và một trong các objects tùy chỉnh của nó được gửi quá nhanh sau đó, kubectl sẽ thường xuyên bị lỗi.

Sự xác thực chưa đầy đủ

Bất cứ điều gì xảy ra từ các lỗi xác thực đơn giản đến các thay đổi bất biến, như thay đổi labelSelector, đều có thể khiến việc áp dụng cấu hình bị lỗi và gây ra vấn đề với state áp dụng từng phần.

Để xác thực cấu hình trước khi gửi, kubectl có --dry-run flag. Tuy nhiên, dry run này chạy hoàn toàn ở client side. Vì vậy, tuy có thể xác nhận cấu hình dựa trên lược đồ, ít nhất là đối với các loại tài nguyên tích hợp, nhưng vẫn không thể ngăn lỗi từ các thay đổi đối với các trường bất biến.

Từ Kubernetes 1.13, server side dry chạy beta, sẵn chạy bằng cách sử dụng --server-dry-run kubectl flag , trải qua tất cả các bước của server side ngoại trừ việc thực sự thay đổi state mong muốn. Điều này có nghĩa là nó cũng sẽ bao gồm xác thực lược đồ cho CRDs, webhooks cho admission controllers và có thể phát hiện các lỗi thay đổi bất biến trước đó.

Tuy nhiên, việc xác định cấu hình mới có bao gồm thay đổi bất biến hay không chỉ là bước đầu tiên.

Thay đổi đối với các trường bất biến

Bước tiếp theo là đảm bảo tài nguyên này bị xóa và được tạo lại. Điều này có thể xảy ra với --force flag, sẽ quay lại xóa và tạo lại tài nguyên này, sau khi vá nó không thành công.

Xóa và tạo lại thường sẽ khiến các applications trở nên không khả dụng, do đó, sử dụng --force không phải là lựa chọn khả thi.

Teams có thể thử xây dựng pipeline đối xứng Terraform plan/apply-like workflow bằng cách sử dụng kubectl, với server-side dry run là plan và kubectl apply là terraform apply.

Teams quy tắc có thể xem xét cẩn thận các thay đổi được lên kế hoạch để hiểu rằng liệu một thay đổi có thể gây ra downtime hay không bằng cách sử dụng bước đánh giá và phê duyệt thủ công. Khi có được logic đúng trong pipeline hoặc có khả năng sử dụng bash có thể trở nên khá phức tạp và gây phiền phức để duy trì lâu dài.

Lược bớt các tài nguyên trước đó

Cuối cùng nhưng không kém phần quan trọng là vấn đề lược bớt tài nguyên. Giả sử có một triển khai và một configmap được tham chiếu bởi triển khai đó. Nếu bây giờ muốn xóa configmap thì có thể xóa cục bộ và xóa tham chiếu đến configmap khỏi thông số triển khai. Chạy kubectl apply cho cấu hình mới này, kubectl sẽ cập nhật triển khai để nó không tham chiếu configmap nữa, nhưng nó sẽ không xóa configmap khỏi cluster.

Áp dụng --prune flag để xử lý trường hợp này. Nhưng hãy cẩn thận, bởi vì nó được đánh dấu rõ ràng là alpha và có thể sẽ không thực hiện những thứ được mong đợi.

Trong ví dụ trên, kubectl không có cách nào để biết được cấu hình trước đó gồm một configmap và cấu hình hiện tại đã không còn nữa. Nó chỉ có thể truy vấn các loại tài nguyên, được xác định trong whitelist , theo abel và namespace, sau đó lọc tất cả tài nguyên trong kết quả của truy vấn đó. Có thể ghi đè lên whitelist với tham số --prune-whitelist .

Ít nhất để có được các tham số label và namespace có thể hơi phức tạp để diễn giải. Cả label và namespace đều là các tham số cụ thể của prune. Chúng cũng ảnh hưởng đến chính 'apply'. Có nghĩa là tài nguyên từ cấu hình không có label sẽ không được cập nhật. Trong khi đó, tham số namespace nếu không được liên kết với bất cứ thành phần nào được xác định trong manifest, sẽ ghi đè lên giá trị từ manifest.

Vì vậy, cẩn thận kiểm soát những gì --prune có thể xóa là rất quan trọng và trong trạng thái hiện tại của nó, việc thực hiện theo cách tự động là không thể tin cậy.

Tổng kết

Trong khi kubectl có mặt ở khắp nơi và hoạt động trong một số trường hợp, thì có một số edge cases nhất định phải nắm.

Một pipeline triển khai liên tục thường xuyên bị hỏng giữa chừng và đòi hỏi sự chú ý thủ công sẽ mất phần lớn giá trị của nó. Đối với các teams nhỏ, có kinh nghiệm, đây có thể là cách tiếp cận khả thi để mọi người nắm được các edge cases và xử lý theo cách thủ công khi cần thiết. Nhưng việc xây dựng tự động triển khai mạnh mẽ xung quanh kubectl đòi hỏi wrapping logic cực kỳ phức tạp. Một câu hỏi hợp lý tại thời điểm này là liệu có không một công cụ được xây dựng có mục đích cho công việc này?

Trong phần thứ hai của loạt bài này sẽ tìm hiểu cách xây dựng tự động triển khai application mạnh mẽ bằng Terraform và Kustomize sử dụng Terraform provider mới cho Kustomize. Provider ban đầu được xây dựng cho open source Gitops framework Kubestack nhưng nó sẽ được sử dụng độc lập cho trường hợp sử dụng triển khai application.
 
Sửa lần cuối:
Top