Шифрование в Kubernetes: основы

31c5d37c09303779dc5960d39939b430.png

Привет, Хабр!

Многие приложения работающие в Kubernetes обрабатывают конфиденциальную информацию, требующую защиты от несанкционированного доступа. Kubernetes предлагает удобные способы для защиты данных. Рассмотрим основные из них в этой статье, а именно — шифрование в покое, шифрование в передаче и зашифрованные томы в Pods.

Шифрование в покое

Шифрование данных в покое позволяет защитить данные, находящиеся в etcd, где Kubernetes хранит всю информацию о состоянии объектов, таких как Secrets и ConfigMaps.

Для включения шифрования данных в покое необходимо юзать файл конфигурации --encryption-provider-config, указывающий на спецификацию конфигурации шифрования. В этой конфигурации задаются поставщики шифрования, которые определяют, каким образом будут зашифрованы данные.

Пример элементарной конфигурации для шифрования объектов типа Secrets и ConfigMaps:

apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
  - resources:
      - secrets
      - configmaps
    providers:
      - aesgcm:
          keys:
            - name: key1
              secret: c2VjcmV0IGlzIHNlY3VyZQ==
            - name: key2
              secret: dGhpcyBpcyBwYXNzd29yZA==
      - identity: {}

В этом конфиге юзаем AES-GCM для шифрования, где secret является закодированным в base64 ключом. Провайдер identity указывается для обработки объектов без шифрования.

Для прокачки безопасности Kubernetes позволяет интегрировать внешние KMS для управления ключами шифрования. С версии Kubernetes 1.10 введена поддержка KMS провайдеров, которая позволяет API серверу отправлять ключи шифрования в KMS для их безопасного хранения и управления.

Схема работы с KMS предполагает использование оболочечного шифрования, при котором данные шифруются локально с помощью ключа шифрования данных, который, в свою очередь, шифруется с использованием ключа шифрования ключей, управляемого в KMS.

Для конфигурации KMS провайдера необходимо добавить его в файл конфигурации шифрования API сервера. Пример конфигурации с KMS провайдером:

apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
  - resources:
      - secrets
    providers:
      - kms:
          name: myKMSProvider
          endpoint: unix:///var/run/kms-plugin/socket.sock
          cachesize: 100
          timeout: 3s

endpoint указывает на UNIX сокет, через который API сервер будет общаться с KMS плагином. cachesize определяет количество ключей шифрования данных, которые будут кэшироваться для ускорения процесса шифрования/дешифрования.

С версии Kubernetes 1.28 началась поддержка KMS v2, которая предлагает лучшие характеристики производительности и улучшенное управление ключами по сравнению с KMS v1. В KMS v2 сервер API использует функцию выработки ключей для генерации одноразовых ключей шифрования данных из секретного семени в сочетании с некоторыми случайными данными. Семя вращается при каждой смене ключа шифрования ключей.

Шифрование в передаче

Шифрование данных в передаче относится к защите информации, которая перемещается между компонентами системы или между системой и её пользователями. В Kubernetes это включает в себя шифрование трафика между нодами, а также между клиентами и API-сервером. Подобная защита данных часто достигается за счёт TLS.

В Kubernetes предоставляется API certificates.k8s.io, который позволяет генерировать TLS сертификаты, подписанные управляемым CA. Эти сертификаты и CA могут быть использованы рабочими нагрузками для установления доверия.

Для того чтобы начать использовать TLS в кластере, необходимо сначала сгенерировать ключи и сертификаты. Существует полно инструментов, наши любимые — cfssl и mkcert. Например, с помощью cfssl можно создать частный ключ и запрос на подпись сертификата, который затем может быть отправлен в Kubernetes API для создания объекта CertificateSigningRequest.

Пример создания CSR с использованием cfssl:

cat <

Это создаст файлы server.csr и server-key.pem, содержащие запрос на подпись сертификата и частный ключ соответственно.

Для локал разработки и тестирования можно использовать mkcert, который создает доверенные сертификаты для домена. Это юзают для проверки TLS в условиях, максимально приближенных к продакшену, без необходимости работы с реальным CA.

Для безопасного доступа к приложениям, развернутым в Kubernetes также часто используется Ingress Controller, например, Nginx. С его помощью можно настроить маршрутизацию трафика и применить TLS сертификаты для шифрования трафика. Создание объекта Ingress с аннотацией nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" позволяет перенаправлять весь входящий трафик на HTTPS.

Пример ingress.yaml для настройки TLS:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: demo-payment-app-ingress
  annotations:
    kubernetes.io/ingress.class: "nginx"
spec:
  tls:
  - hosts:
    - my-demo-app.local
    secretName: my-demo-app-tls
  rules:
  - host: my-demo-app.local
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: demo-payment-app
            port:
              number: 80

Настроили Ingress для использования сертификата TLS, указанного в my-demo-app-tls Secret.

Зашифрованные томы в Pods

Для подключения зашифрованных томов к контейнерам в Pods в Kubernetes можно юзать такие решения, как Portworx и CSI.

Portworx предлагает решение для интеграции хранилищ с поддержкой CSI, начиная с Kubernetes версии 1.10. Это позволяет управлять хранилищем независимо от циклов выпуска Kubernetes, обновляя и улучшая драйверы хранилища без необходимости обновления самого Kubernetes. С Portworx можно:

  • Создавать и использовать постоянные тома с поддержкой CSI.

  • Защищать тома с помощью авторизации токенов и шифрования на уровне StorageClass или PVC.

  • Создавать снимки томов.

  • Использовать тома sharedv4 с поддержкой CSI.

Portworx поддерживает основные функции CSI, включая создание, подключение и монтирование томов, снимки томов, управление объемом и использование эфемерных томов с начиная с определенных версий Portworx и Kubernetes.

NFS позволяет монтировать существующие NFS-шары в Pod. В отличие от временного хранилища emptyDir, содержимое тома NFS сохраняется после удаления Pod, и потом просто отмонтировывается. Т.е NFS-том может быть предварительно заполнен данными, которые могут быть разделены между несколькими Pods. NFS поддерживает одновременную запись несколькими процессами.

Пример манифеста Pod для монтирования NFS-тома:

apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: registry.k8s.io/test-webserver
    name: test-container
    volumeMounts:
    - mountPath: /my-nfs-data
      name: test-volume
  volumes:
  - name: test-volume
    nfs:
      server: my-nfs-server.example.com
      path: /my-nfs-volume
      readOnly: true

* для использования NFS необходимо иметь работающий NFS-сервер с экспортированным шаром

С введением CSI в Kubernetes 1.23 для Portworx началась поддержка миграции с использованием CSIMigrationPortworx, которая была включена по умолчанию в Kubernetes 1.25. Это позволяет перенаправлять все операции плагина из существующего встроенного плагина к драйверу CSI pxd.portworx.com. Для использования этой функции необходимо установить драйвер CSI Portworx в кластере и активировать фичу на контроллере kube-controller-manager и kubelet.

Как и в любом аспекте безопасности, здесь нет одной «серебряной пули». Хорошее шифрование Kubernetes требует комплексного подхода, включающего в себя тщательное планирование, реализацию и постоянную адаптацию к возникающим угрозам.

Больше о подходах и инструментах можно узнать на онлайн-курсе «Инфраструктура высоконагруженных систем» от практиков.

© Habrahabr.ru