Привет, Хабр!
Многие приложения работающие в 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 <<EOF | cfssl genkey - | cfssljson -bare server
{
"hosts": [
"my-svc.my-namespace.svc.cluster.local",
"my-pod.my-namespace.pod.cluster.local",
"192.0.2.24",
"10.0.34.2"
],
"CN": "my-pod.my-namespace.pod.cluster.local",
"key": {
"algo": "ecdsa",
"size": 256
}
}
EOF
Это создаст файлы 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 требует комплексного подхода, включающего в себя тщательное планирование, реализацию и постоянную адаптацию к возникающим угрозам.
Больше о подходах и инструментах можно узнать на онлайн-курсе «Инфраструктура высоконагруженных систем» от практиков.