Kubernetes có một số tùy chọn để cập nhật tài nguyên: áp dụng, chỉnh sửa, vá lỗi và thay thế. Có sự nhầm lẫn về những gì mỗi người làm và khi nào nên sử dụng chúng. Hãy tìm ra nó.
Nếu kubectl patch
, không bao gồm so sánh apply
и patch
. Bài viết này sẽ xem xét các tùy chọn khác nhau, cũng như cách sử dụng hợp lý từng tùy chọn.
Trong vòng đời của tài nguyên Kubernetes (dịch vụ, triển khai, xâm nhập, v.v.), đôi khi bạn cần thay đổi, thêm hoặc xóa một số thuộc tính của tài nguyên này. Ví dụ: thêm ghi chú, tăng hoặc giảm số lượng bản sao.
Kubernetes CLI
Nếu bạn đang làm việc với các cụm Kubernetes thông qua CLI thì bạn đã quen với apply
и edit
. Đội apply
đọc đặc tả tài nguyên từ tệp và tạo "upsert" cho cụm Kubernetes, tức là. tạo tài nguyên nếu nó không tồn tại và cập nhật nó nếu nó tồn tại. Đội edit
đọc tài nguyên thông qua API, sau đó ghi đặc tả tài nguyên vào tệp cục bộ, sau đó tệp này được mở trong trình soạn thảo văn bản. Sau khi chỉnh sửa và lưu file, kubectl
sẽ gửi lại những thay đổi được thực hiện thông qua API, API này sẽ áp dụng cẩn thận những thay đổi này cho tài nguyên.
Không phải ai cũng biết lệnh patch
и replace
. Đội patch
cho phép bạn thay đổi một phần đặc tả tài nguyên, chỉ cung cấp phần đã thay đổi trên dòng lệnh. Đội replace
hoạt động tương tự như edit
, nhưng mọi thứ cần phải được thực hiện thủ công: bạn cần tải xuống phiên bản hiện tại của đặc tả tài nguyên, ví dụ: sử dụng kubectl get -o yaml
, chỉnh sửa nó rồi sử dụng replace
để cập nhật tài nguyên theo thông số kỹ thuật đã thay đổi. Đội replace
sẽ không hoạt động nếu có bất kỳ thay đổi nào xảy ra giữa việc đọc và thay thế tài nguyên.
API Kubernetes
Có lẽ bạn đã quen với các phương pháp CoreV1().Pods().Update()
, replaceNamespacedService
hoặc patch_namespaced_deployment
, nếu bạn làm việc với các cụm thông qua PUT
и PATCH
... Trong đó update
и replace
sử dụng PUT
Và patch
, cho dù nó tầm thường đến đâu, hãy sử dụng PATCH
.
Cần lưu ý rằng kubectl
cũng hoạt động với các cụm thông qua API. Nói cách khác, kubectl
là một trình bao bọc bên trên thư viện máy khách dành cho ngôn ngữ Go, phần lớn cung cấp khả năng cung cấp các lệnh phụ ở dạng nhỏ gọn và dễ đọc hơn bên cạnh các khả năng API tiêu chuẩn. Ví dụ, như bạn có thể đã nhận thấy, phương pháp apply
đã không được đề cập ở trên trong đoạn trước. Hiện tại (tháng 2020 năm XNUMX, khoảng người phiên dịch) tất cả logic kubectl apply
, I E. tạo tài nguyên không tồn tại và cập nhật tài nguyên hiện có, hoạt động hoàn toàn ở phía mã kubectl
. Những nỗ lực đang được thực hiện apply
về phía API, nhưng nó vẫn đang trong giai đoạn thử nghiệm. Tôi sẽ viết chi tiết hơn ở bên dưới.
Bản vá theo mặc định
Sử dụng tốt nhất patch
, nếu bạn muốn cập nhật tài nguyên. Đây là cách cả hai thư viện máy khách hoạt động dựa trên API Kubernetes và kubectl
(không có gì đáng ngạc nhiên, vì nó là một trình bao bọc cho thư viện máy khách, khoảng người phiên dịch).
Làm việc có chiến lược
Tất cả các đội kubectl
apply
, edit
и patch
sử dụng phương pháp PATCH
trong các yêu cầu HTTP để cập nhật tài nguyên hiện có. Nếu bạn đi sâu vào việc thực hiện các lệnh chi tiết hơn thì tất cả chúng đều sử dụng phương pháp patch
có thể sử dụng các phương pháp khác (xem thêm về điều này bên dưới). Phương pháp vá lỗi hợp nhất chiến lược cố gắng "làm đúng" bằng cách hợp nhất đặc tả được cung cấp với đặc tả hiện có. Cụ thể hơn, nó cố gắng kết hợp cả đối tượng và mảng, có nghĩa là những thay đổi có xu hướng mang tính bổ sung. Ví dụ: chạy lệnh patch
với một biến môi trường mới trong đặc tả vùng chứa nhóm, biến môi trường đó sẽ được thêm vào các biến môi trường hiện có thay vì ghi đè chúng. Để loại bỏ việc sử dụng phương pháp này, bạn phải buộc giá trị tham số thành null trong thông số kỹ thuật được cung cấp. Đội nào trong số các đội kubectl
Tốt nhất là sử dụng để cập nhật?
Nếu bạn tạo và quản lý tài nguyên của mình bằng cách sử dụng kubectl apply
, khi cập nhật, tốt hơn hết là luôn sử dụng kubectl apply
Để kubectl
có thể quản lý cấu hình và theo dõi chính xác các thay đổi được yêu cầu từ ứng dụng này sang ứng dụng khác. Ưu điểm luôn sử dụng apply
là nó theo dõi đặc tả được áp dụng trước đó, cho phép nó biết khi nào các thuộc tính đặc tả và phần tử mảng bị loại bỏ rõ ràng. Điều này cho phép bạn sử dụng apply
để loại bỏ các thuộc tính và phần tử mảng, trong khi việc hợp nhất chiến lược thông thường sẽ không hoạt động. Đội edit
и patch
không cập nhật ghi chú rằng kubectl apply
sử dụng để theo dõi các thay đổi của nó, do đó, mọi thay đổi được theo dõi và thực hiện thông qua API Kubernetes nhưng được thực hiện thông qua các lệnh edit
и patch
, vô hình với các lệnh tiếp theo apply
Đó là, apply
không loại bỏ chúng ngay cả khi chúng không xuất hiện trong đặc tả đầu vào cho apply
(Tài liệu nói rằng edit
и patch
cập nhật các ghi chú được sử dụng apply
, nhưng trong thực tế - không).
Nếu bạn không sử dụng lệnh apply
, có thể được sử dụng như edit
Và patch
, chọn lệnh phù hợp nhất với thay đổi đang được thực hiện. Khi thêm và thay đổi thuộc tính BOM, cả hai cách tiếp cận đều gần giống nhau. Khi xóa thuộc tính đặc tả hoặc phần tử mảng edit
hoạt động giống như khởi chạy một lần apply
, bao gồm cả việc theo dõi đặc tả như thế nào trước và sau khi được chỉnh sửa, do đó bạn có thể loại bỏ rõ ràng các thuộc tính và phần tử mảng khỏi tài nguyên. Bạn cần đặt rõ ràng giá trị thuộc tính thành null trong thông số kỹ thuật cho patch
để loại bỏ nó khỏi tài nguyên. Việc loại bỏ một phần tử mảng bằng cách sử dụng bản vá hợp nhất chiến lược phức tạp hơn vì nó yêu cầu sử dụng các lệnh hợp nhất. Xem các phương pháp nâng cấp khác bên dưới để có các lựa chọn thay thế khả thi hơn.
Để triển khai các phương thức cập nhật trong thư viện máy khách hoạt động tương tự như các lệnh trên kubectl
, nên được đặt trong yêu cầu content-type
в application/strategic-merge-patch+json
. Nếu bạn muốn loại bỏ các thuộc tính trong một đặc tả, bạn cần đặt rõ ràng giá trị của chúng thành null theo cách tương tự kubectl patch
. Nếu cần loại bỏ các phần tử mảng, bạn nên đưa các lệnh hợp nhất vào đặc tả cập nhật hoặc sử dụng một cách tiếp cận khác để cập nhật.
Các cách tiếp cận khác để cập nhật
Kubernetes hỗ trợ hai phương pháp cập nhật khác: kubectl patch --type=merge
. Khi làm việc với Kubernetes API, bạn nên sử dụng phương thức request PATCH
và cài đặt content-type
в application/merge-patch+json
.
Cách tiếp cận bản vá JSON, thay vì cung cấp thông số kỹ thuật một phần của tài nguyên, sử dụng việc cung cấp các thay đổi bạn muốn thực hiện cho tài nguyên dưới dạng một mảng, trong đó mỗi phần tử của mảng thể hiện mô tả về thay đổi được thực hiện đối với tài nguyên. Cách tiếp cận này là một cách linh hoạt và mạnh mẽ hơn để thể hiện những thay đổi đang được thực hiện, nhưng phải trả giá bằng việc liệt kê những thay đổi được thực hiện ở định dạng riêng biệt, không phải Kubernetes, thay vì gửi thông số tài nguyên một phần. TRONG kubectl
bạn có thể chọn bản vá JSON bằng cách sử dụng kubectl patch --type=json
. Khi sử dụng API Kubernetes, phương pháp này hoạt động bằng phương thức yêu cầu PATCH
và cài đặt content-type
в application/json-patch+json
.
Chúng tôi cần sự tự tin - sử dụng thay thế
Trong một số trường hợp, bạn cần chắc chắn rằng không có thay đổi nào được thực hiện đối với tài nguyên trong khoảng thời gian tài nguyên được đọc và khi tài nguyên được cập nhật. Nói cách khác, bạn nên đảm bảo rằng mọi thay đổi sẽ được thực hiện nguyên tử. Trong trường hợp này, để cập nhật tài nguyên bạn nên sử dụng replace
. Ví dụ: nếu bạn có ConfigMap với bộ đếm được cập nhật bởi nhiều nguồn, bạn nên đảm bảo rằng hai nguồn không cập nhật bộ đếm cùng lúc, khiến bản cập nhật bị mất. Để chứng minh, hãy tưởng tượng một chuỗi các sự kiện bằng cách sử dụng phương pháp patch
:
- A và B lấy trạng thái hiện tại của tài nguyên từ API
- Mỗi cái cập nhật cục bộ thông số kỹ thuật bằng cách tăng bộ đếm lên một và cũng thêm "A" hoặc "B" tương ứng vào ghi chú "được cập nhật bởi"
- Và nó cập nhật tài nguyên nhanh hơn một chút
- B cập nhật tài nguyên
Kết quả là bản cập nhật A bị mất. Hoạt động cuối cùng patch
thắng, bộ đếm được tăng lên một thay vì hai và giá trị của ghi chú "được cập nhật bởi" kết thúc bằng "B" và không chứa "A". Hãy so sánh những điều trên với những gì xảy ra khi cập nhật được thực hiện bằng cách sử dụng phương pháp này replace
:
- A và B lấy trạng thái hiện tại của tài nguyên từ API
- Mỗi cái cập nhật cục bộ thông số kỹ thuật bằng cách tăng bộ đếm lên một và cũng thêm "A" hoặc "B" tương ứng vào ghi chú "được cập nhật bởi"
- Và nó cập nhật tài nguyên nhanh hơn một chút
- B cố gắng cập nhật tài nguyên nhưng bản cập nhật bị API từ chối vì phiên bản tài nguyên nằm trong thông số kỹ thuật
replace
không khớp với phiên bản hiện tại của tài nguyên trong Kubernetes vì phiên bản của tài nguyên đã được tăng lên nhờ hoạt động thay thế của A.
Trong trường hợp trên, B sẽ phải tìm nạp lại tài nguyên, thay đổi trạng thái mới và thử lại replace
. Điều này sẽ khiến bộ đếm tăng lên hai và ghi chú "được cập nhật bởi" sẽ bao gồm "AB" ở cuối.
Ví dụ trên ngụ ý rằng khi thực hiện replace
Toàn bộ tài nguyên được thay thế hoàn toàn. Đặc điểm kỹ thuật được sử dụng cho replace
, không được một phần hoặc từng phần như trong apply
, nhưng đầy đủ, bao gồm cả phần bổ sung resourceVersion
vào siêu dữ liệu đặc tả. Nếu bạn chưa kích hoạt resourceVersion
hoặc phiên bản bạn cung cấp không phải là phiên bản hiện hành, việc thay thế sẽ bị từ chối. Vì vậy cách tốt nhất để sử dụng là replace
– đọc tài nguyên, cập nhật và thay thế nó ngay lập tức. sử dụng kubectl
, nó có thể trông như thế này:
$ kubectl get deployment my-deployment -o json
| jq '.spec.template.spec.containers[0].env[1].value = "new value"'
| kubectl replace -f -
Điều đáng lưu ý là hai lệnh sau đây, được thực hiện tuần tự, sẽ thực thi thành công, vì deployment.yaml
không chứa tài sản .metadata.resourceVersion
$ kubectl create -f deployment.yaml
$ kubectl replace -f deployment.yaml
Điều này dường như mâu thuẫn với những gì đã nói ở trên, tức là "thêm resourceVersion
vào siêu dữ liệu đặc tả." Nói như vậy có sai không? Không, không phải vậy, bởi vì nếu kubectl
thông báo mà bạn không chỉ định resourceVersion
, nó sẽ đọc nó từ tài nguyên và thêm nó vào thông số kỹ thuật mà bạn đã chỉ định và chỉ sau đó mới thực thi nó replace
. Bởi vì điều này tiềm ẩn nguy hiểm nếu bạn dựa vào tính nguyên tử, nên phép thuật hoàn toàn có tác dụng kubectl
, bạn không nên dựa vào nó khi sử dụng thư viện máy khách hoạt động với API. Trong trường hợp này, bạn sẽ phải đọc đặc tả tài nguyên hiện tại, cập nhật nó rồi thực thi PUT
lời yêu cầu.
Bạn không thể thực hiện bản vá - chúng tôi thực hiện thay thế
Đôi khi bạn cần thực hiện một số thay đổi mà API không thể xử lý được. Trong những trường hợp này, bạn có thể buộc thay thế tài nguyên bằng cách xóa và tạo lại tài nguyên đó. Việc này được thực hiện bằng cách sử dụng kubectl replace --force
. Việc chạy lệnh sẽ ngay lập tức loại bỏ các tài nguyên rồi tạo lại chúng từ thông số kỹ thuật được cung cấp. Không có trình xử lý "bắt buộc thay thế" trong API và để thực hiện điều đó thông qua API, bạn cần thực hiện hai thao tác. Đầu tiên bạn cần xóa tài nguyên bằng cách thiết lập cho nó gracePeriodSeconds
về không (0) và propagationPolicy
trong “Nền” rồi tạo lại tài nguyên này với thông số kỹ thuật mong muốn.
Cảnh báo: Cách tiếp cận này có khả năng nguy hiểm và có thể dẫn đến trạng thái không xác định.
Áp dụng ở phía máy chủ
Như đã đề cập ở trên, các nhà phát triển Kubernetes đang nỗ lực triển khai logic apply
của kubectl
trong API Kubernetes. Logic apply
có sẵn trong Kubernetes 1.18 thông qua kubectl apply --server-side
hoặc thông qua API bằng phương thức PATCH
с content-type
application/apply-patch+YAML
.
Lưu ý: JSON cũng là YAML hợp lệ, vì vậy bạn có thể gửi thông số kỹ thuật dưới dạng JSON ngay cả khi
content-type
sẽapplication/apply-patch+yaml
.
Bên cạnh logic đó kubectl
trở nên có sẵn cho mọi người thông qua API, apply
về phía máy chủ, theo dõi xem ai chịu trách nhiệm về các trường trong đặc tả, do đó cho phép nhiều quyền truy cập an toàn để chỉnh sửa không có xung đột. Nói cách khác, nếu apply
về phía máy chủ sẽ trở nên phổ biến hơn, một giao diện quản lý tài nguyên an toàn phổ quát sẽ xuất hiện cho các máy khách khác nhau, chẳng hạn như kubectl, Pulumi hoặc Terraform, GitOps, cũng như các tập lệnh tự viết bằng thư viện máy khách.
Kết quả
Tôi hy vọng phần tổng quan ngắn gọn này về các cách khác nhau để cập nhật tài nguyên theo cụm sẽ hữu ích cho bạn. Thật tốt khi biết rằng nó không chỉ là áp dụng hay thay thế; còn có thể cập nhật tài nguyên bằng cách sử dụng áp dụng, chỉnh sửa, vá lỗi hoặc thay thế. Xét cho cùng, về nguyên tắc, mỗi phương pháp đều có lĩnh vực ứng dụng riêng. Đối với những thay đổi nguyên tử, thay thế là thích hợp hơn; nếu không, bạn nên sử dụng bản vá hợp nhất chiến lược thông qua áp dụng. Ít nhất, tôi mong bạn hiểu rằng bạn không thể tin tưởng vào Google hoặc StackOerflow khi tìm kiếm "kubernetes áp dụng so với thay thế". Ít nhất cho đến khi bài viết này thay thế câu trả lời hiện tại.
Nguồn: www.habr.com