Книга: Паттерны Kubernetes: Шаблоны разработки собственных облачных приложений
Назад: Глава 18. Конфигурация в переменных окружения
Дальше: Глава 20. Неизменяемая конфигурация

Глава 19. Конфигурация в ресурсах

Kubernetes предлагает свои ресурсы для хранения обычных и конфиденциальных конфигурационных данных, которые позволяют отделить жизненный цикл конфигурации от жизненного цикла приложения. Паттерн Configuration Resource (Конфигурация в ресурсах) объясняет идеи, заложенные в основу ресурсов ConfigMap и Secret, а также способы их использования и ограничения.

Задача

Один из существенных недостатков паттерна EnvVar Configuration (Конфигурация в переменных окружения) состоит в том, что он подходит для случаев с небольшим количеством параметров и простых конфигураций. Другой недостаток в том, что переменные окружения могут определяться в разных местах, из-за чего часто бывает сложно найти, где определяется та или иная переменная. И даже отыскав ее, нельзя быть полностью уверенным, что она не переопределяется где-то еще. Например, переменные, определяемые в образе Docker, можно переопределить во время выполнения в ресурсе Deployment.

Часто бывает удобнее хранить все конфигурационные данные в одном месте, а не во множестве файлов с определениями ресурсов. Также нет смысла помещать содержимое всего конфигурационного файла в переменную окружения. В таких случаях некоторая дополнительная косвенность может дать большую гибкость, что и предлагает паттерн Configuration Resource (Конфигурация в ресурсах).

Решение

Фреймворк Kubernetes предлагает специализированные ресурсы для хранения конфигураций, более гибкие, чем простые переменные окружения — объекты ConfigMap и Secret для данных общего назначения и конфиденциальных данных соответственно.

Оба ресурса поддерживают одинаковые способы использования, потому что обеспечивают хранение и управление парами ключ/значение. Все приемы, которые далее описываются применительно к ресурсам ConfigMap, в большинстве случаев можно использовать при работе с ресурсами Secret. Кроме кодирования в формат Base64, эти два ресурса не имеют технических различий.

После создания карты конфигурации ConfigMap и сохранения в ней данных есть два способа использования ключей из ConfigMap:

• как ссылки на переменные окружения, где ключ представляет имя переменной;

• как файлы, отображаемые в тома, смонтированные в поде. В этом случае ключ используется как имя файла.

Файл в смонтированном томе ConfigMap обновляется при изменении ConfigMap через Kubernetes API. То есть если приложение поддерживает горячую перезагрузку конфигурационных файлов, такое поведение позволяет получить определенные выгоды. Если ConfigMap используется для представления ссылок на переменные окружения, изменения в нем не отражаются на значениях переменных, потому что переменные окружения нельзя изменить после запуска процесса.

Другой альтернативой ресурсам ConfigMap и Secret является хранение конфигурации непосредственно на внешних томах, которые затем подключаются к поду.

Далее приводятся конкретные примеры использования ресурса ConfigMap, но они могут использоваться также с ресурсом Secret. Правда, есть одно важное обстоятельство: значения в ресурсе Secret хранятся в формате Base64.

Ресурс ConfigMap хранит пары ключ/значение в своем разделе data, как показано в листинге 19.1.

Листинг 19.1. Ресурс ConfigMap

apiVersion: v1

kind: ConfigMap

metadata:

  name: random-generator-config

data:

  PATTERN: Configuration Resource      

  application.properties: |

    # Конфигурация генератора случайных чисел

    log.file=/tmp/generator.log

    server.port=7070

  EXTRA_OPTIONS: "high-secure,native"

  SEED: "432576345"

Карты конфигураций ConfigMap могут быть доступны как переменные окружения и как смонтированные файлы. Мы советуем использовать символы верхнего регистра для обозначения ключей, которые используются как переменные окружения, и допустимые имена файлов при использовании монтируемых файлов.

Ресурс ConfigMap также может переносить содержимое полных конфигурационных файлов, как application.properties для Spring Boot в этом примере. Нетрудно догадаться, что в нетривиальных случаях этот раздел может оказаться весьма большим!

Чтобы не создавать вручную полное описание ресурса, можно воспользоваться командой kubectl. Команда kubectl, которая воспроизводит предыдущий пример, показана в листинге 19.2.

Листинг 19.2. Создание ConfigMap из файла

kubectl create cm spring-boot-config \

    --from-literal=JAVA_OPTIONS=-Djava.security.egd=file:/dev/urandom \

    --from-file=application.properties

Этот ресурс ConfigMap можно использовать везде, где доступны переменные окружения, как демонстрирует листинг 19.3.

Листинг 19.3. Установка переменной окружения из ConfigMap

apiVersion: v1

kind: Pod

metadata:

  name: random-generator

spec:

  containers:

  - env:

    - name: PATTERN

      valueFrom:

        configMapKeyRef:

          name: random-generator-config

          key: PATTERN

....

Если в ConfigMap присутствует большое число записей, которые должны быть доступны в виде переменных окружения, использование специального синтаксиса может сэкономить немало времени. Вместо объявления каждой записи по отдельности, как показано в предыдущем примере в разделе env:, можно определить раздел envFrom:, который отобразит все записи из ConfigMap с ключами, которые можно использовать как допустимые имена переменных окружения. Также есть возможность добавить определенный префикс, как показано в листинге 19.4.

Листинг 19.4. Установка переменных окружения из значений в ConfigMap

apiVersion: v1

kind: Pod

metadata:

  name: random-generator

spec:

  containers:

    envFrom:                         

    - configMapRef:

      name: random-generator-config

      prefix: CONFIG_                

Выбрать все ключи из ресурса ConfigMap с именем random-generator-config, которые можно использовать в качестве имен переменных окружения.

Все отобранные ключи из ConfigMap предваряются префиксом CONFIG_. В результате для ConfigMap из примера 19.1 будут созданы переменные CONFIG_PATTERN_NAME, CONFIG_EXTRA_OPTIONS и CONFIG_SEED.

Ресурсы Secret тоже можно использовать для создания переменных окружения, как и ConfigMap, либо из каждой записи в отдельности, либо сразу из всех записей. Чтобы задействовать Secret вместо ConfigMap, нужно заменить configMapKeyRef на secretKeyRef.

При использовании в качестве тома весь ресурс ConfigMap проецируется в указанный том, при этом ключи используются как имена файлов (см. листинг 19.5).

Листинг 19.5. Монтирование ConfigMap как тома

apiVersion: v1

kind: Pod

metadata:

  name: random-generator

spec:

  containers:

  - image: k8spatterns/random-generator:1.0

    name: random-generator

    volumeMounts:

    - name: config-volume

      mountPath: /config

  volumes:

  - name: config-volume

    configMap:                         

    name: random-generator-config

Том на основе ConfigMap будет содержать файлы по числу записей в ресурсе. Ключи будут использованы как имена файлов, а значения — как их содержимое.

Конфигурация из листинга 19.1, смонтированная как том, создаст два файла в папке /config: application.properties с содержимым, определенным в ConfigMap, и файл PATTERN с единственной строкой.

Добавляя дополнительные свойства в объявление тома, можно более тонко настроить отображение конфигурационных данных. Вместо отобра-

насколько защищены ресурсы Secret?

Ресурсы Secret хранят данные в формате Base64 и декодируют их перед передачей в переменные окружения или смонтированные тома. Многие ошибочно считают такое кодирование безопасным. Base64 не является алгоритмом шифрования и с точки зрения безопасности данные в этом формате являются не более защищенными, чем открытый текст. Формат Base64 в Secret просто позволяет хранить двоичные данные. Тогда почему ресурсы Secret считаются более безопасными, чем ресурсы ConfigMap? Потому что есть еще ряд деталей реализации Secret, которые делают эти ресурсы безопасными. В этом направлении постоянно появляются новые улучшения, но к основным деталям реализации относятся следующие:

• ресурсы Secret передаются только на узлы, где действуют поды, использующие их;

• на узлах ресурсы Secret хранятся в памяти, в файловой системе tmpfs, никогда не записываются в физическое хранилище и удаляются после остановки пода;

• в Etcd ресурсы Secret хранятся в зашифрованном виде.

Как бы то ни было, есть вполне законные способы получить доступ к ресурсам Secret, например, обратившись от имени пользователя root или даже создав под и смонтировав нужный ресурс Secret в него. Можно, конечно, применить приемы управления доступом на основе ролей (Role-Based Access Control, RBAC) к ресурсам Secret (так же, как для ConfigMap или других ресурсов) и разрешить их чтение только определенным подам с предопределенными учетными записями служб. Пользователи, имеющие возможность создавать поды в пространстве имен, могут повышать свои привилегии в этом пространстве имен, запускать поды под учетной записью с более высокими привилегиями и читать ресурсы Secret. Пользователь или контроллер с привилегиями, разрешающими создавать поды в пространстве имен, сможет действовать от имени любой учетной записи службы и получить доступ ко всем ресурсам Secret и ConfigMap в этом пространстве имен. По этой причине на уровне приложений часто выполняется дополнительное шифрование конфиденциальной информации.

жения всех записей в файлы можно выбрать конкретные ключи и имена файлов, под которыми они должны быть доступны. За более подробной информацией обращайтесь к документации с описанием ConfigMap.

Еще один способ хранения конфигурации в Kubernetes — использование томов gitRepo. Тома этого типа монтируются в пустые каталоги в подах, и в них клонируются заданные репозитории Git. Хранение конфигурации в Git автоматически дает возможность управления версиями и аудита. Но тома gitRepo требуют доступа к внешним репозиториям Git, которые не являются ресурсами Kubernetes, могут находиться вне кластера и требовать отдельного мониторинга и управления. Клонирование и монтирование происходит во время запуска пода, и локальная копия не обновляется автоматически при изменении основного репозитория. Тома этого типа работают подобно паттерну Immutable Configuration (Неизменяемая конфигурация), описанному в главе 20, и с использованием паттерна Init Container (Init-контейнер) для копирования конфигурации в локальный том.

В настоящее время тома типа gitRepo считаются устаревшими и вместо них рекомендуется использовать решения на основе паттерна Init Container (Init-контейнер), потому что эти решения более универсальны и поддерживают другие источники данных, а не только Git. Вы тоже можете использовать этот подход для извлечения конфигурационных данных из внешних систем и сохранения их в томе, но вместо предопределенного тома gitRepo использовать более гибкий метод Init Container (Init-контейнер). Подробнее этот прием мы обсудим в разделе «Init-контейнеры в Kubernetes» главы 20.

Пояснение

Ресурсы ConfigMap и Secret позволяют хранить конфигурационную информацию в специализированных объектах ресурсов, которые легко управляются с помощью Kubernetes API. Самое большое преимущество ConfigMap и Secret в том, что они отделяют определение конфигурационных данных от их использования. Такое разделение позволяет управлять объектами, используя конфигурации независимо от конфигураций.

Еще одно преимущество в том, что ConfigMap и Secret являются неотъемлемой частью платформы. Они не требуют никаких нестандартных конструкций, подобных тем, что описаны в главе 20 «Неизменяемая конфигурация».

Тем не менее паттерн Configuration Resource (Конфигурация в ресурсах) тоже имеет свои ограничения: ресурсы Secret не могут иметь размер больше 1 Мбайт, то есть они не могут хранить произвольные объемы данных и не годятся для хранения прикладных данных, не имеющих отношения к конфигурации. Ресурсы Secret могут хранить двоичные данные, но из-за того что данные хранятся в формате Base64, чистый их объем не может превышать 700 Кбайт.

Кроме того, многие действующие кластеры Kubernetes устанавливают свои квоты на число ресурсов ConfigMap, которые можно использовать в пространстве имен или в проекте, поэтому ConfigMap тоже не является универсальным решением.

В следующих двух главах мы познакомимся с приемами хранения очень больших объемов конфигурационных данных, основанных на паттернах Immutable Configuration (Неизменяемая конфигурация) и Configuration Template (Макет конфигурации).

Дополнительная информация

• Пример конфигурации в ресурсах (http://bit.ly/2YeGymi).

• Документация с описанием ConfigMap (http://bit.ly/2Cs59uQ).

• Документация с описанием Secret (https://kubernetes.io/docs/concepts/configuration/secret/).

• Стационарное шифрование данных в Secret (http://bit.ly/2ORsavt).

• Безопасное распространение учетных данных с помощью Secret (http://bit.ly/2FfcvCn).

• Тома gitRepo (http://bit.ly/2HxuGqO).

• Ограничения на размеры ConfigMap (http://bit.ly/2UkHRRy).

Назад: Глава 18. Конфигурация в переменных окружения
Дальше: Глава 20. Неизменяемая конфигурация