Tuan-Anh Tran
March 3, 2023

Almost** instant k8s secret update for your application

Posted on March 3, 2023  •  5 minutes  • 867 words

Thinh Nguyen có chia sẻ 1 bài khá tổng quan về secret trên k8s . Mình thấy gãi đúng chỗ ngứa vấn đề của mấy năm trước nên gõ nhanh bài này chia sẻ cùng mọi người.

The problem

Có 1 vấn đề từ những ngày đầu của k8s (những năm 2014-2016) là khi configmap/secret đc update thì làm sao để application nhận được các thay đổi đó.

Giải pháp thời ấy đơn giản nhất là tự đi mà rolling update pods. Sau này đỡ cực hơn chút là xài stakater/Reloader .

Reloader là 1 controller tự động watch các thay đổi của configmap/secrets và rolling update lần lượt các pod tương ứng.

Nếu bạn cảm thấy như vậy là xong thì chắc ko cần đọc tiếp :D

Mục đích của bài này là làm thế nào mà ko cần phải rolling update các pods mà pods vẫn nhận được các thay đổi configmap/secrets 1 cách nhanh nhất có thể? Nhanh hơn cả giải pháp dùng reloader trên kia và ko disruptive (ko cần rolling update).

Mình cùng đi tìm hiểu nhé.

Để giải quyết vấn đề này, chúng ta cần giải quyết được 2 vấn đề nhỏ:

  1. Làm sao để thay đổi được reflect vào trong pod
  2. Làm sao để application được alert và reload configuration mỗi khi có các thay đổi đó.

Vấn đề số 1

Về lý thuyết thì kubelet, mình lấy ví dụ cụ thể ở đây là secret manager chẳng hạn, nó watch thẳng cái secret thì khi nào secret được update thì kubelet sẽ biết ngay luôn rồi.

  1. Vậy tại sao lại có delay để secret được update trong pod???

Đơn giản là vì k8s ko impelement cơ chế nào để “sync” lại mounted secret volume ngay lập tức.

  1. Vậy khi nào thì k8s/configmap được update trong pod?

Khi nào mà pod cần update vì bất kì lý do nào đó. hoặc sau 1 khoảng thời gian không cố định.

Vì sau lại là 1 khoảng mà ko cố định? Đó là vì default resyncInterval60s<code>workerResyncIntervalJitterFactor</code>0.5. Đó là lý do bạn thấy khoảng thời gian lúc đo thực tế bị dao động từ 60 tới 90 giây.

Giờ chúng ta biết cách thức secret/configmap được update vào trong pod như thế nào rồi, làm thế nào để nó nhanh hơn nhỉ?

Cái này là 1 mẹo đơn giản mình có POC thời ở Techcombank. Nhớ đoạn trên mình viết là nếu bất cứ pod event nào thì nó sẽ trigger lại đoạn “sync” kia ko?

Chúng ta cần 1 event nào đó mà ko rolling update pod (vì nếu rolling update thì mình làm kiểu này làm quái gì, xài Reloader cho xong).

Hmmm, vậy update labels hoặc annotations là được chứ gì. Vì labels còn dành cho 1 số mục đích khác nên mình chọn annotations.

Giải pháp là mình sử dụng

  1. Viết controller để watch secret/configmap. Cái này mình dùng Kyverno luôn cho tiện vì lúc đó ở Techcombank đang triển khai Kyverno. Thay vì phải viết 1 cái controller đơn giản để watch secret/configmap cho việc này.

  2. Setup 1 policy để mutate các pod tương ứng mỗi khi các secret/configmap đang dùng đc update. Add thêm 1 field là foo: $randomValue chẳng hạn.

Mọi người có thể verify cái này bằng 1 app cực kì đơn giản print cái secret kia liên tục và sẽ thấy nó được update instantly sau khi bạn add annotation.

Vấn đề số 2

Mình sẽ nói về các app chung chung, ko chỉ app deploy trên k8s nhé.

Về việc làm sao để nhận secret mỗi khi có thay đổi thì các bạn dev đơn giản chỉ là watch cái file secret thôi (inotify syscall). Quá đơn giản phải ko, vài dòng code là xong. DONE.

Mình cũng từng làm như vậy thời trước. Thế nhưng khi deploy lên k8s thì cơ chế ấy lại không hoạt động đúng và lỗi.

Lý do thực ra lại rất đơn giản.

Mỗi lần cái event “sync” kia được thực hiện để update secret/configmap thì cái file sẽ bị xóa đi và symlinked lại.

Vì sao lại xóa đi, và vì sao lại là symlinked???

Mình cũng ko rõ đoạn này lắm nhưng nếu bạn mount secret vào trong pod thì bạn sẽ verify đc nó chỉ là symlink.

Mỗi lần “sync” thì cái symlink kia sẽ được update, cái đích của symlink cũ sẽ bị xóa và bởi vậy trigger cái event file bị xóa đi ở trên.

Lúc này thì đoạn code bình thường watch cái file của mình sẽ bị lỗi vì cái watch kia bị broken. Trong trường hợp này, mình chỉ việc update lại cái lib của mình để re-establish lại cái watch trong sự kiện file bị xóa kia thôi.

Kết luận

Đây là 1 vấn đề khá hay ho trong k8s và mình ko thấy nhiều người tìm hiểu sâu về việc này. Kiểu xài Reloader xong rồi là xong, cần gì phải tìm hiểu thêm ý.

Nhưng nó thực sự rất thú vị nếu bạn tìm hiểu kĩ cách k8s hoạt động, cách linux system hoạt động, etc…

Enjoy the weekend :)

Follow me

Here's where I hang out in social media