Розробка Kubernetes-оператора “StaleSecretWatch”. Частина-02 “Імплементація Користувацького Ресурсу”

pic

30 років, але цей маленький автомобіль все ще викликає таке ж хвилювання! 🏎️💨 #МолодийДухом

У Частині 1 ми розглядали теорію за Kubernetes Operators і чому ми будуємо StaleSecretWatch Operator. Тепер, у Частині 2, ми зануримося в практичні аспекти створення цього оператора за допомогою Operator SDK. Від налаштування проєкту до написання необхідного коду — цей посібник надасть покрокову інструкцію.

Але перш ніж перейти до технічних деталей, дозвольте поділитися історією, яка пояснить, чому цей оператор такий важливий.

Історія забутих секретів

Уявіть таке: ви керуєте кластером Kubernetes для важливого проєкту. Навколо все кипить — нові деплойменти, масштабування сервісів і постійні оновлення. Як ваша команда зростає, так і кількість секретів — API-ключі, облікові дані баз даних, токени — все зберігається безпечно в вашому кластері. Все здається ідеальним, поки одного дня якийсь сервіс не виходить з ладу. Панічні перевірки показують, що проблема була викликана застарілим секретом. Хтось забув його оновити.

Ви в поспіху намагаєтесь знайти, який секрет вийшов з ладу і скільки інших застарілих секретів може бути прихованих у вашому кластері, чекаючи моменту, щоб спричинити ще більше хаосу. Ви усвідомлюєте, що вручну відслідковувати та керувати секретами стає непосильним завданням. Потрібен кращий спосіб!

Тут на допомогу приходить StaleSecretWatch Operator.

Як у цій історії, застарілі секрети можуть непомітно накопичуватися та становити загрозу безпеці, якщо з ними не працювати належним чином. Автоматизація виявлення та керування цими секретами дозволяє вашій системі залишатися безпечною та ефективною. StaleSecretWatch Operator вирішить цю проблему, автоматично ідентифікуючи секрети, які є занадто старими, і позначаючи їх для подальших дій — щоб ви могли зосередитись на важливих завданнях, а не на забутих секретах.

Мета полягає в моніторингу ресурсів секретів у кластері Kubernetes і виявленні тих, які були створені давно, але не були оновлені з того часу. Ці секрети вважаються застарілими і можуть потребувати уваги, щоб переконатись, що вони залишаються актуальними та безпечними.

Що таке StaleSecretWatch Kubernetes Operator?

StaleSecretWatch Kubernetes Operator автоматизує виявлення та повідомлення про застарілі секрети в Kubernetes кластерах. Нижче наведений покроковий процес, який виконує оператор, а також його функціональні можливості:

  1. Виявлення простору і секретів:
  • Моніторить ресурси Kubernetes Secret, створені в певному просторі імен або по всіх просторах імен, в залежності від конфігурації оператора.

2. Хешування даних секрету:

  • Отримує значення розділу “spec.data” з кожного Secret.
  • Обчислює унікальний хеш для даних секрету для відстеження змін і виявлення дублікатів.

3. Зберігання метаданих:

  • Зберігає обчислені хеші разом з метаданими, такими як назва секрету, простір імен та час створення, в Kubernetes ConfigMap.

4. Оцінка застарілих секретів:

  • Періодично оцінює збережені секрети згідно з пороговим значенням кількості днів, вказаним у конфігурації YAML для користувацького ресурсу StaleSecretWatch.

**5.
pic

30 років, але цей маленький автомобіль досі викликає таке ж хвилювання! 🏎️💨 #МолодийДухом

У Частині 1 ми досліджували теорію Kubernetes Operators і пояснили, чому ми створюємо StaleSecretWatch Operator. Тепер, у Частині 2, ми поринемо в практичні аспекти створення цього оператора за допомогою Operator SDK. Від налаштування проєкту до написання необхідного коду — цей посібник надасть покрокову інструкцію.

Але перед тим, як перейти до технічних деталей, дозвольте поділитися історією, яка ілюструє, чому цей оператор такий важливий.

Історія забутих секретів

Уявіть таке: ви керуєте кластером Kubernetes для важливого проєкту. Всі навколо вируюють — нові деплойменти, масштабування сервісів і постійні оновлення. Як ваша команда зростає, так і кількість секретів — API-ключі, облікові дані бази даних, токени — все зберігається безпечно в вашому кластері. Все здається ідеальним, поки одного дня якийсь сервіс не виходить з ладу. Панічні перевірки показують, що проблема сталася через застарілий секрет. Хтось забув його оновити.

Ви метушливо намагаєтесь з’ясувати, який саме секрет вийшов з ладу і скільки інших застарілих секретів може бути прихованими у вашому кластері, чекаючи моменту, щоб спричинити ще більше хаосу. Ви розумієте, що вручну відслідковувати і керувати секретами стає непосильним завданням. Має бути кращий спосіб!

І ось тут на допомогу приходить StaleSecretWatch Operator.

Як у цій історії, застарілі секрети можуть непомітно накопичуватися і становити загрозу безпеці, якщо з ними не працювати належним чином. Автоматизація виявлення та керування цими секретами гарантує, що ваша система залишатиметься безпечною та ефективною. StaleSecretWatch Operator вирішить цю проблему, автоматично ідентифікуючи секрети, які занадто старі, і позначаючи їх для дій — так ви зможете зосередитись на важливому, не турбуючись про забуті секрети.

Мета цього оператора — моніторити ресурси секретів у кластері Kubernetes і виявляти ті, які були створені давно, але не були оновлені з того часу. Ці секрети вважаються застарілими і можуть вимагати уваги, щоб переконатись, що вони залишаються актуальними та безпечними.

Що таке StaleSecretWatch Kubernetes Operator?

StaleSecretWatch Kubernetes Operator автоматизує виявлення та сповіщення про застарілі секрети в кластерах Kubernetes. Ось покроковий процес, який виконує оператор, а також його функціональні можливості:

  1. Виявлення простору і секретів:
  • Моніторить ресурси Kubernetes Secret, створені в певному просторі імен або по всіх просторах імен, в залежності від конфігурації оператора.

2. Хешування даних секрету:

  • Отримує значення розділу “spec.data” з кожного Secret.
  • Обчислює унікальний хеш для даних секрету, щоб відслідковувати зміни і ефективно виявляти дублікати.

3. Зберігання метаданих:

  • Зберігає обчислені хеші разом з метаданими, такими як назва секрету, простір імен та час створення, в Kubernetes ConfigMap.

4. Оцінка застарілих секретів:

  • Періодично оцінює збережені секрети на основі порогового числа днів, зазначеного в YAML-конфігурації для користувацького ресурсу StaleSecretWatch.

5.
**Сповіщення про застарілі секрети
:

  • Ідентифікує секрети, які перевищили поріг і вважаються застарілими (наприклад, прострочені або застарілі).
  • Надсилає сповіщення в Slack, щоб проінформувати користувачів про застарілі секрети з наступними деталями:
  • Назва секрету
  • Простір імен
  • Час створення
  • Статус застарілості (наприклад, Прострочено)

Автоматизуючи ці процеси, StaleSecretWatch Operator підвищує безпеку кластерів Kubernetes і оперативну ефективність, проактивно виявляючи та сповіщаючи про потенційно вразливі секрети.

pic

Пояснення користувацького ресурсу StaleSecretWatch

Користувацький ресурс StaleSecretWatch призначений для моніторингу та керування секретами Kubernetes, які можуть застаріти з часом. Залежно від вказаної конфігурації в ресурсі, оператор поводиться по-різному, щоб задовольнити різні вимоги. Нижче наведено деталі двох прикладів конфігурацій:

Версія 1: Моніторинг усіх просторів імен

У цій версії поле namespace під staleSecretToWatch встановлено в all. Це інструктує оператора моніторити всі ресурси секретів у всіх просторах імен кластера. Проте певні простори імен та секрети можна виключити з моніторингу, вказавши їх у списку excludeList.

Нижче наведена yaml-конфігурація для нашого користувацького ресурсу staleSecretToWatch.

apiVersion: security.stalesecretwatch.io/v1beta1  
kind: StaleSecretWatch  
metadata:  
 labels:  
 app.kubernetes.io/name: stalesecretwatch  
 name: stalesecretwatch-sample  
spec:  
 staleThresholdInDays: 50 #день, після якого секрет вважається застарілим  
 refreshInterval: 24h  
 staleSecretToWatch:  
 namespace: all #якщо вказано "all", це означає моніторинг усіх секретів у всіх просторах імен  
 excludeList:  
 - namespace: kube-system #виключити наступні секрети в цьому просторі імен   
 secretName: sh.helm.release.v1.traefik-crd.v1, sh.helm.release.v1.traefik.v1 #через кому вказати імена секретів для ігнорування  

---  
# можна також створити ресурс таким чином  

apiVersion: security.stalesecretwatch.io/v1beta1  
kind: StaleSecretWatch  
metadata:  
 labels:  
 app.kubernetes.io/name: stalesecretwatch  
 name: stalesecretwatch-sample  
spec:  
 staleThresholdInDays: 90  
 refreshInterval: 24h  
 staleSecretToWatch:  
 namespace: all  
 excludeList:  
 - namespace: namespace1  
 secretName: secret1,secret2  
 - namespace: namespace2  
 secretName: secret3,secret4

Ключові поля:

  • staleSecretToWatch.staleThresholdInDays : день, після якого секрет вважається застарілим
  • refreshInterval : час, через який буде виконано цикл узгодження
  • spec.staleSecretToWatch.namespace: якщо встановлено в all, дозволяє моніторинг секретів по всіх просторах імен.
  • excludeList: Визначає простори імен та імена секретів, які мають бути виключені з моніторингу. Наприклад:
  • namespace: kube-system — це назва простору імен, що виключає секрети, як-от sh.helm.release.v1.traefik-crd.v1 та sh.helm.release.v1.traefik.v1, присутні в цьому просторі імен.
  • secretName: Список імен секретів через кому, які потрібно ігнорувати в зазначеному просторі імен.

Ця конфігурація корисна для всебічного моніторингу секретів з можливістю виключення конкретних критичних секретів або просторів імен.

Версія 2: Моніторинг конкретного простору імен

У цій версії поле namespace під staleSecretToWatch встановлено на конкретний простір імен (наприклад, kube-system). Це обмежує область оператора моніторити тільки секрети в зазначеному просторі імен.
Сповіщення про застарілі секрети:

  • Ідентифікує секрети, які перевищили поріг і вважаються застарілими (наприклад, прострочені або застарілі).
  • Надсилає сповіщення в Slack, щоб інформувати користувачів про застарілі секрети з наступними деталями:
  • Назва секрету
  • Простір імен
  • Час створення
  • Статус застарілості (наприклад, Прострочено)

Автоматизуючи ці процеси, StaleSecretWatch Operator підвищує безпеку кластерів Kubernetes і оперативну ефективність, проактивно виявляючи та сповіщаючи про потенційно вразливі секрети.

pic

Пояснення користувацького ресурсу StaleSecretWatch

Користувацький ресурс StaleSecretWatch призначений для моніторингу та керування секретами Kubernetes, які можуть застаріти з часом. Залежно від вказаної конфігурації в ресурсі, оператор поводиться по-різному, щоб задовольнити різні вимоги. Нижче наведено деталі двох прикладів конфігурацій:

Версія 1: Моніторинг усіх просторів імен

У цій версії поле namespace під staleSecretToWatch встановлено в all. Це інструктує оператора моніторити всі ресурси секретів у всіх просторах імен кластера. Проте певні простори імен та секрети можна виключити з моніторингу, вказавши їх у списку excludeList.

Нижче наведена yaml-конфігурація для нашого користувацького ресурсу staleSecretToWatch.

apiVersion: security.stalesecretwatch.io/v1beta1  
kind: StaleSecretWatch  
metadata:  
 labels:  
 app.kubernetes.io/name: stalesecretwatch  
 name: stalesecretwatch-sample  
spec:  
 staleThresholdInDays: 50 #день, після якого секрет вважається застарілим  
 refreshInterval: 24h  
 staleSecretToWatch:  
 namespace: all #якщо вказано "all", це означає моніторинг усіх секретів у всіх просторах імен  
 excludeList:  
 - namespace: kube-system #виключити наступні секрети в цьому просторі імен   
 secretName: sh.helm.release.v1.traefik-crd.v1, sh.helm.release.v1.traefik.v1 #через кому вказати імена секретів для ігнорування  

---  
# можна також створити ресурс таким чином  

apiVersion: security.stalesecretwatch.io/v1beta1  
kind: StaleSecretWatch  
metadata:  
 labels:  
 app.kubernetes.io/name: stalesecretwatch  
 name: stalesecretwatch-sample  
spec:  
 staleThresholdInDays: 90  
 refreshInterval: 24h  
 staleSecretToWatch:  
 namespace: all  
 excludeList:  
 - namespace: namespace1  
 secretName: secret1,secret2  
 - namespace: namespace2  
 secretName: secret3,secret4

Ключові поля:

  • staleSecretToWatch.staleThresholdInDays : день, після якого секрет вважається застарілим
  • refreshInterval : час, через який буде виконано цикл узгодження
  • spec.staleSecretToWatch.namespace: якщо встановлено в all, дозволяє моніторинг секретів по всіх просторах імен.
  • excludeList: Визначає простори імен та імена секретів, які мають бути виключені з моніторингу. Наприклад:
  • namespace: kube-system — це назва простору імен, що виключає секрети, як-от sh.helm.release.v1.traefik-crd.v1 та sh.helm.release.v1.traefik.v1, присутні в цьому просторі імен.
  • secretName: Список імен секретів через кому, які потрібно ігнорувати в зазначеному просторі імен.

Ця конфігурація корисна для всебічного моніторингу секретів з можливістю виключення конкретних критичних секретів або просторів імен.

Версія 2: Моніторинг конкретного простору імен

У цій версії поле namespace під staleSecretToWatch встановлено на конкретний простір імен (наприклад, kube-system). Це обмежує область оператора моніторити тільки секрети в зазначеному просторі імен.
Подібно до Версії 1, список excludeList дозволяє уточнити моніторинг, виключаючи певні секрети в цільовому просторі імен.

apiVersion: security.stalesecretwatch.io/v1beta1  
kind: StaleSecretWatch  
metadata:  
 labels:  
 app.kubernetes.io/name: stalesecretwatch  
 name: stalesecretwatch-sample  
spec:  
 staleThresholdInDays: 90  
 refreshInterval: 24h  
 staleSecretToWatch:  
 namespace: kube-system #це буде моніторити лише секрети в цьому просторі імен  
 excludeList:  
 - namespace: kube-system #назва простору імен  
 #вищезгаданий простір імен може містити багато ресурсів секретів  
 #якщо ви не хочете моніторити певні секрети, вкажіть їх тут  
 secretName: sh.helm.release.v1.traefik-crd.v1, sh.helm.release.v1.traefik.v1
  • Ключові поля:
  • spec.staleSecretToWatch.namespace: Визначає простір імен для моніторингу (наприклад, kube-system).
  • spec.staleSecretToWatch.namespace: простір імен може містити багато ресурсів секретів, тут ви можете вказати імена секретів в цьому просторі, які потрібно виключити з моніторингу.
  • spec.staleSecretToWatch.secretName: Список імен секретів, розділений комами, які слід ігнорувати в зазначеному просторі імен.

Ця конфігурація ідеально підходить, коли потрібно моніторити секрети в одному просторі імен без впливу на інші частини кластера.

Виключені секрети

виключити secret.Type == kubernetes.io/service-account-token та bootstrap.kubernetes.io/token згідно з бізнес-логікою, оскільки вони є:

Рідко змінювані секрети:

  • kubernetes.io/service-account-token: Ці секрети автоматично генеруються Kubernetes для кожного ServiceAccount для надання токенів доступу для автентифікації з API Kubernetes. Токени сервісних облікових записів зазвичай мають довгий термін дії і використовуються для цілей автентифікації, тому вони не змінюються часто, якщо тільки сам ServiceAccount не було змінено або видалено.
  • bootstrap.kubernetes.io/token: Токени bootstrap використовуються під час початкової настройки кластерів Kubernetes для автентифікації вузлів, що приєднуються. Після генерації ці токени зазвичай не змінюються часто, якщо тільки не потрібно створювати нові кластери або додавати нові вузли.

ConfigMap, що підтримується StaleSecretWatch

ConfigMap, який створюється і підтримується staleSecretToWatch, слугує як централізоване сховище даних для відстежування інформації про ресурси секретів Kubernetes. Цей ConfigMap є критично важливим для моніторингу та ідентифікації застарілих секретів. Нижче наводиться пояснення його структури та призначення кожного поля.

коли configmap створюється і підтримується staleSecretToWatch, він виглядатиме ось так:

kubectl get cm hashed-secrets-stalesecretwatch -o jsonpath='{.binaryData.data}' | base64 -d | jq .

Подібно до Версії 1, список `excludeList` дозволяє додатково уточнити моніторинг, виключаючи певні секрети в цільовому просторі імен.

apiVersion: security.stalesecretwatch.io/v1beta1
kind: StaleSecretWatch
metadata:
labels:
app.kubernetes.io/name: stalesecretwatch
name: stalesecretwatch-sample
spec:
staleThresholdInDays: 90
refreshInterval: 24h
staleSecretToWatch:
namespace: kube-system #це буде моніторити лише секрети в цьому просторі імен
excludeList:
- namespace: kube-system #назва простору імен
#вищезгаданий простір імен може містити багато ресурсів секретів
#якщо ви не хочете моніторити певні секрети, вкажіть їх тут
secretName: sh.helm.release.v1.traefik-crd.v1, sh.helm.release.v1.traefik.v1
```

  • Ключові поля:
  • spec.staleSecretToWatch.namespace: Визначає простір імен для моніторингу (наприклад, kube-system).
  • spec.staleSecretToWatch.namespace: простір імен може містити багато ресурсів секретів, тут ви можете вказати імена секретів у цьому просторі імен, які потрібно виключити з моніторингу.
  • spec.staleSecretToWatch.secretName: Список імен секретів, розділений комами, які слід ігнорувати в зазначеному просторі імен.

Ця конфігурація ідеально підходить для моніторингу секретів в одному просторі імен без впливу на інші частини кластера.

Виключені секрети

виключити secret.Type == kubernetes.io/service-account-token та bootstrap.kubernetes.io/token згідно з бізнес-логікою, оскільки це є:

Рідко змінювані секрети:

  • kubernetes.io/service-account-token: Ці секрети автоматично генеруються Kubernetes для кожного ServiceAccount для надання токенів доступу для автентифікації з API Kubernetes. Токени сервісних облікових записів зазвичай мають довгий термін дії та використовуються для цілей автентифікації, тому вони не змінюються часто, якщо лише сам ServiceAccount не було змінено або видалено.
  • bootstrap.kubernetes.io/token: Токени bootstrap використовуються під час початкової настройки кластерів Kubernetes для автентифікації вузлів, що приєднуються. Після їх генерації ці токени зазвичай не змінюються часто, якщо тільки не потрібно створювати нові кластери або додавати нові вузли.

ConfigMap, що підтримується StaleSecretWatch

ConfigMap, який створюється і підтримується staleSecretToWatch, слугує як централізоване сховище даних для відстежування інформації про ресурси секретів Kubernetes. Цей ConfigMap є критично важливим для моніторингу та ідентифікації застарілих секретів. Нижче наводиться пояснення його структури та призначення кожного поля.

коли configmap створюється і підтримується staleSecretToWatch, він виглядатиме ось так:

kubectl get cm hashed-secrets-stalesecretwatch -o jsonpath='{.binaryData.data}' | base64 -d | jq .

output:  

{  
 "namespaces": [  
 {  
 "name": "kube-system",  
 "secrets": [  
 {  
 "name": "chart-values-traefik",  
 "last_modified": "2024-04-12T09:19:30Z",  
 "created": "2024-04-11T11:01:16Z",  
 "history": [  
 {  
 "data": "d20df341de4e2d1ce7200c0340afdb72f9bce78bb87e35604a1904e921d36b63"  
 },  
 {  
 "data": "02d36b6334021afd20df341de4e2d1ce720bb87e356040cdb7f9bce78a1904e9"  
 }  
 ]  
 },  
 {  
 "name": "chart-values-traefik-crd",  
 "last_modified": "2024-04-11T11:01:16Z",  
 "created": "2024-04-11T11:01:16Z",  
 "history": [  
 {  
 "data": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"  
 }  
 ]  
 },  
 {  
 "name": "k3s-serving",  
 "created": "2024-04-11T11:01:11Z",  
 "last_modified": "2024-04-11T11:01:11Z",  
 "history": [  
 {  
 "data": "8ceb357e39811df7a56e55355aa07a69b1c1b1eaf0a7a908422ee7d09030b749"  
 }  
 ]  
 },  
 {  
 "name": "lima-rancher-desktop.node-password.k3s",  
 "created": "2024-04-11T11:01:13Z",  
 "last_modified": "2024-04-11T11:01:13Z",  
 "history": [  
 {  
 "data": "1d1e1d45514ff1b4520114fbb18fb857090d22beacd35fe946dfb47ab35fdd0b"  

 }  
 ]  
 },  
 {  
 "name": "serving-ca",  
 "created": "2024-04-11T11:01:11Z",  
 "last_modified": "2024-04-11T11:01:11Z",  
 "history": [  
 {  
 "data": "5041fc91a467039c85b668a051b537abf2cac14b231393f18ca3c38e3bfb71d7"  

 }  
 ]  
 },  
 {  
 "name": "serving-cert",  
 "created": "2024-04-11T11:01:14Z",  
 "last_modified": "2024-04-11T11:01:14Z",  
 "history": [  
 {  
 "data": "14678391149da9dc1fce31c768c2fcb1c6169a23761b78d7f48fef7768168a1f"  
 }  
 ]  
 }  
 ]  
 },  
 {  
 "name": "vivid",  
 "secrets": [  
 {  
 "name": "chef-user-secret",  
 "created": "2024-04-11T11:06:53Z",  
 "last_modified": "2024-04-11T11:06:53Z",  
 "history": [  
 {  
 "data": "d85d88fc09beef87ec306c9167d80dcef03752c4c0ab8a8e63620e827d670a84"  

 }  
 ]  
 }  
 ]  
 },  
 {  
 "name": "vivid2",  
 "secrets": [  
 {  
 "name": "chef-user-secret2",  
 "created": "2024-04-11T11:08:02Z",  
 "last_modified": "2024-04-11T11:08:02Z",  
 "history": [  
 {  
 "data": "96efbc43a462ab9d9c6a8173e5b322e17f218b56eb3a05a4bbc53221adebc7b3"  
 }  
 ]  
 }  
 ]  
 },  
 {  
 "name": "vivid3",  
 "secrets": [  
 {  
 "name": "chef-user-secret3",  
 "created": "2024-04-11T17:19:04Z",  
 "last_modified": "2024-04-11T18:09:12Z",  
 "history": [  
 {  
 "data": "b30ffee89ff49f962b11ba2fd707872cd4d37a15548ae7552e6d4cff592d8771"  
 }  
 ]  
 }  
 ]  
 }  
 ]  
}

Структура на верхньому рівні:

  • namespaces:
    Це масив об'єктів, де кожен об'єкт представляє конкретний простір імен Kubernetes, що моніториться для ресурсів секретів. Кожен простір імен містить список секретів та їх супутню метаінформацію.

Поля на рівні простору імен:

  1. name:
    Назва простору імен, що моніториться.
    Призначення: Для поділу секретів за простором імен для зручнішої ідентифікації та організації.
  2. secrets:
    Масив об'єктів, де кожен об'єкт містить метаінформацію та історію для конкретного ресурсу секрету в межах простору імен.

Поля на рівні секрету:

  1. name:
    Назва ресурсу секрету, що моніториться.
    Призначення: Для унікальної ідентифікації секрету в межах простору імен.
  2. created:
    Мітка часу, коли секрет був створений (формат ISO 8601).
    Призначення: Для відстеження часу існування секрету.
  3. last_modified:
    Мітка часу останньої модифікації секрету (формат ISO 8601).
    Призначення: Для визначення, чи був секрет нещодавно оновлений або він потенційно є застарілим.
  4. history:
    Масив об'єктів, де кожен об'єкт містить історичний запис даних секрету.
  • data: Хешоване значення, яке представляє вміст секрету на певний момент часу.
    output:

{
"namespaces": [
{
"name": "kube-system",
"secrets": [
{
"name": "chart-values-traefik",
"lastmodified": "2024-04-12T09:19:30Z",
"created": "2024-04-11T11:01:16Z",
"history": [
{
"data": "d20df341de4e2d1ce7200c0340afdb72f9bce78bb87e35604a1904e921d36b63"
},
{
"data": "02d36b6334021afd20df341de4e2d1ce720bb87e356040cdb7f9bce78a1904e9"
}
]
},
{
"name": "chart-values-traefik-crd",
"last
modified": "2024-04-11T11:01:16Z",
"created": "2024-04-11T11:01:16Z",
"history": [
{
"data": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
}
]
},
{
"name": "k3s-serving",
"created": "2024-04-11T11:01:11Z",
"lastmodified": "2024-04-11T11:01:11Z",
"history": [
{
"data": "8ceb357e39811df7a56e55355aa07a69b1c1b1eaf0a7a908422ee7d09030b749"
}
]
},
{
"name": "lima-rancher-desktop.node-password.k3s",
"created": "2024-04-11T11:01:13Z",
"last
modified": "2024-04-11T11:01:13Z",
"history": [
{
"data": "1d1e1d45514ff1b4520114fbb18fb857090d22beacd35fe946dfb47ab35fdd0b"

}
]
},
{
"name": "serving-ca",
"created": "2024-04-11T11:01:11Z",
"last_modified": "2024-04-11T11:01:11Z",
"history": [
{
"data": "5041fc91a467039c85b668a051b537abf2cac14b231393f18ca3c38e3bfb71d7"

}
]
},
{
"name": "serving-cert",
"created": "2024-04-11T11:01:14Z",
"lastmodified": "2024-04-11T11:01:14Z",
"history": [
{
"data": "14678391149da9dc1fce31c768c2fcb1c6169a23761b78d7f48fef7768168a1f"
}
]
}
]
},
{
"name": "vivid",
"secrets": [
{
"name": "chef-user-secret",
"created": "2024-04-11T11:06:53Z",
"last
modified": "2024-04-11T11:06:53Z",
"history": [
{
"data": "d85d88fc09beef87ec306c9167d80dcef03752c4c0ab8a8e63620e827d670a84"

}
]
}
]
},
{
"name": "vivid2",
"secrets": [
{
"name": "chef-user-secret2",
"created": "2024-04-11T11:08:02Z",
"lastmodified": "2024-04-11T11:08:02Z",
"history": [
{
"data": "96efbc43a462ab9d9c6a8173e5b322e17f218b56eb3a05a4bbc53221adebc7b3"
}
]
}
]
},
{
"name": "vivid3",
"secrets": [
{
"name": "chef-user-secret3",
"created": "2024-04-11T17:19:04Z",
"last
modified": "2024-04-11T18:09:12Z",
"history": [
{
"data": "b30ffee89ff49f962b11ba2fd707872cd4d37a15548ae7552e6d4cff592d8771"
}
]
}
]
}
]
}
```

Структура на верхньому рівні:

  • namespaces:
    Це масив об'єктів, де кожен об'єкт представляє конкретний простір імен Kubernetes, що моніториться для ресурсів секретів. Кожен простір імен містить список секретів та їх супутню метаінформацію.

Поля на рівні простору імен:

  1. name:
    Назва простору імен, що моніториться.
    Призначення: Для поділу секретів за простором імен для зручнішої ідентифікації та організації.
  2. secrets:
    Масив об'єктів, де кожен об'єкт містить метаінформацію та історію для конкретного ресурсу секрету в межах простору імен.

Поля на рівні секрету:

  1. name:
    Назва ресурсу секрету, що моніториться.
    Призначення: Для унікальної ідентифікації секрету в межах простору імен.
  2. created:
    Мітка часу, коли секрет був створений (формат ISO 8601).
    Призначення: Для відстеження часу існування секрету.
  3. last_modified:
    Мітка часу останньої модифікації секрету (формат ISO 8601).
    Призначення: Для визначення, чи був секрет нещодавно оновлений або він потенційно є застарілим.
  4. history:
    Масив об'єктів, де кожен об'єкт містить історичний запис даних секрету.
  • data: Хешоване значення, яке представляє вміст секрету на певний момент часу.
    output:

Purpose: Для збереження версованої історії даних секрету, що дозволяє порівнювати зміни та проводити аудити.

Декілька полів будуть взяті з вищезазначеного configmap і надіслані як повідомлення в Slack.

Давайте створимо Kubernetes оператор...

Необхідні умови

Перед тим, як почати, переконайтеся, що у вас встановлено наступне:

Змініть параметри в наведених командах відповідно до ваших потреб..

Крок 1: Створіть репозиторій на GitHub

Заповніть деталі репозиторію:

  • Назва репозиторію: stale-secret-watch-operator
  • Опис: (необов'язково) “Kubernetes оператор для управління застарілими секретами.”
  • Встановіть репозиторій як Публічний або Приватний, залежно від вашого вибору.
  • Відмітьте “Ініціалізувати цей репозиторій з README”, якщо ви хочете додати файл README.
  • Натисніть “Створити репозиторій” для завершення.

Після створення репозиторію, клонувати його на ваш локальний комп'ютер:

git clone https://github.com//stale-secret-watch.git  
cd stale-secret-watch

Крок 2: Ініціалізація проекту оператора

Щоб створити наш оператор, ми будемо використовувати інструмент командного рядка operator-sdk, який спрощує розробку операторів.

Запустіть наступну команду для ініціалізації нового Go-базованого оператора:

operator-sdk init --project-name stale-secrets-watch --domain=stalesecretwatch.io --repo=github.com/sourav977/stale-secrets-watch --skip-go-version-check
  • --domain: Домен API групи.
  • --repo: Шлях Go модуля, де буде розміщено ваш оператор.

Це створить базову структуру проекту для вашого оператора.

Крок 3: Опис API

Наступним кроком потрібно визначити GVK (Group, Version, Kind) та API для користувацького ресурсу (CR), який буде керувати нашим оператором. Для цього ми створимо новий API за допомогою operator-sdk:

operator-sdk create api --group=security --version=v1beta1 --kind=StaleSecretWatch --resource=true --controller=true

Ця команда виконує наступне:

  • --group security: Група API.
  • --version v1beta1: Версія CR.
  • --kind StaleSecretWatch: Назва користувацького ресурсу.
  • --resource: Генерація CRD (Custom Resource Definition).
  • --controller: Створення контролера для керування CR.

Після виконання цієї команди ви знайдете нові файли в каталогах api/v1beta1/ та internal/controllers/.

Крок 4: Опис вашого Custom Resource Definition (CRD)

Після генерації API та контролера, вам потрібно буде описати структуру вашого StaleSecretWatch CRD у Go типі. Для цього потрібно редагувати файл _types.go (у цьому випадку stalesecretwatch_types.go), що знаходиться в каталозі api/v1beta1 вашого проєкту. Ви будете визначати поля вашого CRD (такі як staleThresholdInDays, refreshInterval, StaleSecretToWatch і excludeList), які обговорюються в розділі “Пояснення CustomResource StaleSecretWatch_” згідно зі схемою, яку ви надали.

Я рекомендую ознайомитись з файлом https://github.com/sourav977/stale-secrets-watch/blob/main/api/v1beta1/stalesecretwatch_types.go, щоб дізнатися призначення структур, чому їх було створено і які значення вони містять.

// +kubebuilder анотації в файлах ресурсів Kubernetes (джерело Go коду) — це спеціальні директиви, що використовуються фреймворком Kubebuilder. Ці анотації виконують кілька функцій у процесі розробки, генерації та управління Custom Resource Definitions (CRD) та пов'язаними ресурсами. Ось детальне пояснення:

Призначення анотацій // +kubebuilder

1.

output:

Purpose: Для збереження версованої історії даних секрету, що дозволяє порівнювати зміни та проводити аудити.

Декілька полів будуть взяті з вищезазначеного configmap і надіслані як повідомлення в Slack.

Давайте створимо Kubernetes оператор...

Необхідні умови

Перед тим, як почати, переконайтеся, що у вас встановлено наступне:

Змініть параметри в наведених командах відповідно до ваших потреб..

Крок 1: Створіть репозиторій на GitHub

Заповніть деталі репозиторію:

  • Назва репозиторію: stale-secret-watch-operator
  • Опис: (необов'язково) “Kubernetes оператор для управління застарілими секретами.”
  • Встановіть репозиторій як Публічний або Приватний, залежно від вашого вибору.
  • Відмітьте “Ініціалізувати цей репозиторій з README”, якщо ви хочете додати файл README.
  • Натисніть “Створити репозиторій” для завершення.

Після створення репозиторію, клонувати його на ваш локальний комп'ютер:

git clone https://github.com//stale-secret-watch.git  
cd stale-secret-watch

Крок 2: Ініціалізація проекту оператора

Щоб створити наш оператор, ми будемо використовувати інструмент командного рядка operator-sdk, який спрощує розробку операторів.

Запустіть наступну команду для ініціалізації нового Go-базованого оператора:

operator-sdk init --project-name stale-secrets-watch --domain=stalesecretwatch.io --repo=github.com/sourav977/stale-secrets-watch --skip-go-version-check
  • --domain: Домен API групи.
  • --repo: Шлях Go модуля, де буде розміщено ваш оператор.

Це створить базову структуру проекту для вашого оператора.

Крок 3: Опис API

Наступним кроком потрібно визначити GVK (Group, Version, Kind) та API для користувацького ресурсу (CR), який буде керувати нашим оператором. Для цього ми створимо новий API за допомогою operator-sdk:

operator-sdk create api --group=security --version=v1beta1 --kind=StaleSecretWatch --resource=true --controller=true

Ця команда виконує наступне:

  • --group security: Група API.
  • --version v1beta1: Версія CR.
  • --kind StaleSecretWatch: Назва користувацького ресурсу.
  • --resource: Генерація CRD (Custom Resource Definition).
  • --controller: Створення контролера для керування CR.

Після виконання цієї команди ви знайдете нові файли в каталогах api/v1beta1/ та internal/controllers/.

Крок 4: Опис вашого Custom Resource Definition (CRD)

Після генерації API та контролера, вам потрібно буде описати структуру вашого StaleSecretWatch CRD у Go типі. Для цього потрібно редагувати файл _types.go (у цьому випадку stalesecretwatch_types.go), що знаходиться в каталозі api/v1beta1 вашого проєкту. Ви будете визначати поля вашого CRD (такі як staleThresholdInDays, refreshInterval, StaleSecretToWatch і excludeList), які обговорюються в розділі “Пояснення CustomResource StaleSecretWatch” згідно зі схемою, яку ви надали.

Я рекомендую ознайомитись з файлом https://github.com/sourav977/stale-secrets-watch/blob/main/api/v1beta1/stalesecretwatch_types.go, щоб дізнатися призначення структур, чому їх було створено і які значення вони містять.

// +kubebuilder анотації в файлах ресурсів Kubernetes (джерело Go коду) — це спеціальні директиви, що використовуються фреймворком Kubebuilder. Ці анотації виконують кілька функцій у процесі розробки, генерації та управління Custom Resource Definitions (CRD) та пов'язаними ресурсами. Ось детальне пояснення:

Призначення анотацій // +kubebuilder

1.

output:

Налаштування специфікації CRD

  • Анотації +kubebuilder дозволяють розробникам вказувати, як CRD мають бути згенеровані та налаштовані.
  • Вони визначають метадані, правила валідації та значення за замовчуванням для полів CRD.

Приклад:

// +kubebuilder:validation:Maximum=100  
// +kubebuilder:validation:Minimum=1  
MyField int `json:"myField"`

Цей приклад гарантує, що значення поля MyField у користувацькому ресурсі повинно бути між 1 і 100.

2. Генерація схеми OpenAPI

  • Kubebuilder використовує ці анотації для генерації схеми OpenAPI v3 для CRD.
  • Схема є важливою для валідації структури та даних користувацького ресурсу під час виконання.
  • Вона забезпечує дотримання вказаних правил під час створення, оновлення або видалення ресурсу.

Приклад:

// +kubebuilder:validation:Pattern=`^a.*z$`  
MyString string `json:"myString"`

Гарантує, що MyString має починатися з 'a' та закінчуватися на 'z'.

Аналогічно:

// +kubebuilder:rbac:groups=core,resources=pods,verbs=get;list;watch

Визначає права доступу RBAC (Role-Based Access Control) для контролера для керування ресурсами Kubernetes, такими як Pods.

// +kubebuilder:default=5  
MyIntField int `json:"myIntField,omitempty"`

Гарантує, що MyIntField за замовчуванням буде мати значення 5, якщо воно не задано явно.

// +kubebuilder:subresource:status

Генерує підресурс status для користувацького ресурсу, який часто використовується для відображення поточного стану ресурсу.

Тепер давайте завершим цей блог, не розтягуємо його занадто. В цій частині ми розглянули призначення StaleSecretWatch Kubernetes Operator, його шаблон дизайну CustomResource, як він зберігає метадані, пов'язані з секретами, у ConfigMap, структуру дизайну ConfigMap та анотації Kubebuilder, що спрощують валідацію CRD.

У наступному блозі ми зробимо крок вперед, реалізувавши логіку контролера та запустимо оператора локально, щоб побачити його в дії. Залишайтеся з нами!

Sourav Patnaik
output:

Налаштування специфікації CRD

  • Анотації +kubebuilder дозволяють розробникам вказувати, як CRD повинні бути згенеровані та налаштовані.
  • Вони визначають метадані, правила валідації та значення за замовчуванням для полів CRD.

Приклад:

// +kubebuilder:validation:Maximum=100  
// +kubebuilder:validation:Minimum=1  
MyField int `json:"myField"`

Цей приклад гарантує, що значення поля MyField у користувацькому ресурсі повинно бути між 1 і 100.

2. Генерація схеми OpenAPI

  • Kubebuilder використовує ці анотації для генерації схеми OpenAPI v3 для CRD.
  • Схема є важливою для валідації структури та даних користувацького ресурсу під час виконання.
  • Вона гарантує, що ресурс відповідає вказаним правилам при створенні, оновленні або видаленні.

Приклад:

// +kubebuilder:validation:Pattern=`^a.*z$`  
MyString string `json:"myString"`

Гарантує, що MyString має починатися з 'a' та закінчуватися на 'z'.

Аналогічно:

// +kubebuilder:rbac:groups=core,resources=pods,verbs=get;list;watch

Визначає права доступу RBAC (Role-Based Access Control) для контролера для керування ресурсами Kubernetes, такими як Pods.

// +kubebuilder:default=5  
MyIntField int `json:"myIntField,omitempty"`

Гарантує, що MyIntField за замовчуванням буде мати значення 5, якщо воно не задано явно.

// +kubebuilder:subresource:status

Генерує підресурс status для користувацького ресурсу, який часто використовується для відображення поточного стану ресурсу.

Тепер давайте завершим цей блог, не розтягуємо його занадто. В цій частині ми розглянули призначення StaleSecretWatch Kubernetes Operator, його шаблон дизайну CustomResource, як він зберігає метадані, пов'язані з секретами, у ConfigMap, структуру дизайну ConfigMap та анотації Kubebuilder, що спрощують валідацію CRD.

У наступному блозі ми зробимо крок вперед, реалізувавши логіку контролера та запустимо оператора локально, щоб побачити його в дії. Залишайтеся з нами!

Sourav Patnaik

Перекладено з: Design a “StaleSecretWatch” Kubernetes Operator. Part-02 “Implementation of CustomResource”

Leave a Reply

Your email address will not be published. Required fields are marked *