Содержание:

Подключение к экземпляру Kafka
Безопасная передача учетных данных
Привязка сервиса в Kubernetes
Простота использования привязок сервисов с помощью kube-service-bindings
Настройка привязки сервисов в OpenShift
Node.js и Apache Kafka: дополнительные ресурсы

Apache Kafka — это система обмена сообщениями, работающая по принципу «публикация — подписка», которая обычно используется для создания слабо связанных между собой приложений. Такие приложения часто называют реактивными приложениями.

Наша команда подготовила пример простого реактивного приложения, демонстрирующий использование Kafka. Если вы уже интересовались приложениями такого типа, то вам известно, что, несмотря на отсутствие связей между компонентами, им требуется доступ к общему экземпляру Kafka. Доступ к такому общему экземпляру должен быть защищен. Это означает, что каждому компоненту требуется собственный набор учетных данных, которые тот сможет использовать для подключения к экземпляру Kafka.

Как безопасно и без лишнего труда открыть доступ к этим учетным данным и использовать их при разработке на Node.js? Ответу на этот вопрос посвящена эта статья.

Примечание. Подробнее об использовании Node.js в реактивных приложениях рассказывается в статье Построение реактивных систем с помощью Node.js.

Подключение к экземпляру Kafka

Для подключения к экземпляру Kafka обычно требуется следующая информация:

  • один или несколько URL-адресов для кластера Kafka;

  • информация о механизме подключения/аутентификации;

  • идентификатор пользователя;

  • секретный ключ пользователя.

При предоставлении доступа к двум последним пунктам, несомненно, следует соблюдать осторожность. В идеале первый пункт также не должен быть публичным. В результате для подключения к экземпляру Kafka вам необходимо указать что-то вроде этого:

KAFKA_BOOTSTRAP_SERVER=michael--wmc-utegzxlxds-fhyltiy-j-j.bf2.kafka.cloud.com:443
KAFKA_CLIENT_ID=srvc-acct-123456789-1234-1234-1234-24bda5a97b89
KAFKA_CLIENT_SECRET=abcdef12-1234-1234-1234-da90b53e893e
KAFKA_SASL_MECHANISM=plain

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

Важно также отметить, что для Node.js существует несколько различных клиентов Kafka и способ передачи этой информации отличается для каждого клиента. Если вы не знаете, какой клиент выбрать, ознакомьтесь с разделом Kafka в справке по Node.js.

В качестве простого примера передачи информации при использовании клиента KafkaJS можно использовать такой код:

  kafkaConnectionBindings = {
    brokers: [process.env.KAFKA_BOOTSTRAP_SERVER ]
  };

  if (process.env.KAFKA_SASL_MECHANISM === 'plain') {
    kafkaConnectionBindings.sasl = {
      mechanism: process.env.KAFKA_SASL_MECHANISM,
      username: process.env.KAFKA_CLIENT_ID,
      password: process.env.KAFKA_CLIENT_SECRET
    };
    kafkaConnectionBindings.ssl = true;
  }
  const kfk = new Kafka(kafkaConnectionBindings);

Использование переменных среды — самый простой способ настройки соединения, но он не всегда безопасен. Если задать переменные среды из командной строки, то любой человек, имеющий доступ к этой среде, сможет получить доступ и к ним. Различные инструменты и фреймворки также часто облегчают доступ к переменным среды в целях отладки. Например, в Red Hat OpenShift можно просматривать переменные среды из консоли, как показано на рис. 1.

Рис. 1. Переменные среды, перечисленные в консоли OpenShift
Рис. 1. Переменные среды, перечисленные в консоли OpenShift

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

Безопасная передача учетных данных

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

Вместо того чтобы задавать учетные данные непосредственно в среде, безопаснее будет воспользоваться пакетом вроде dotenv, чтобы получать учетные данные из файла и передавать их в среду приложения на Node.js. Преимуществом при использовании dotenv будет то, что учетные данные не будут отображаться в среде за пределами процесса Node.js.

Этот подход лучше, однако учетные данные все равно могут быть раскрыты, если сделать дампы среды Node.js для отладки с использованием диагностического отчета Node.js. Также открытым остается вопрос о том, как безопасно передать файл dotenv в приложение. В случае развертывания приложения в Kubernetes можно сопоставить файл развернутым контейнерам, но это потребует определенных усилий по планированию и координации разработок.

Вам может показаться, что это весьма трудозатратная задача, и, возможно, вы задаетесь вопросом, нужно ли решать ее отдельно для каждого типа сервиса и набора учетных данных, которые необходимы приложению. Хорошая новость заключается в том, что для сред Kubernetes эта проблема уже решена.

Привязка сервиса в Kubernetes

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

Спецификация не определяет, какие файлы сопоставляются для того или иного типа сервиса. Однако в OpenShift, например, привязка к экземпляру Red Hat OpenShift Streams для Apache Kafka приводит к сопоставлению следующих файлов контейнеру приложения:

$SERVICE_BINDING_ROOT/<kafka-instance-name>

├── bootstrapServers
├── password
├── provider
├── saslMechanism
├── securityProtocol
├── type
└── user

В этом случае SERVICE_BINDING_ROOT передается в приложение через среду.

Простота использования привязок сервисов с помощью kube-service-bindings

Теперь, когда учетные данные доступны приложению, запущенному в контейнере, осталось прочитать их из этих файлов и затем передать клиенту Kafka, используемому в приложении на Node.js. Хм… Звучит не слишком ободряюще — куча работы, да еще и жесткая привязка к используемому клиенту.

Еще одна хорошая новость! Мы создали npm-пакет kube-service-bindings, который позволяет приложениям на Node.js легко использовать эти секретные ключи, при этом разработчикам не нужно разбираться с привязкой сервисов.

Этот пакет предоставляет метод getBinding(), который делает примерно следующее:

  1. ищет переменную $SERVICE_BINDING_ROOT, чтобы проверить, доступны ли привязки;

  2. считывает информацию из файлов;

  3. сопоставляет имена файлов с именами опций, необходимых клиентам Node.js, которые будут подключаться к сервису.

Этот процесс наглядно показан на рис. 2.

Рис. 2. Использование привязок сервисов с помощью пакета kube-service-bindings
Рис. 2. Использование привязок сервисов с помощью пакета kube-service-bindings

Разработчику достаточно лишь вызвать метод getBinding(), сообщить ему, какой клиент используется, а затем передать возвращенный объект клиенту Kafka. Без проверки на ошибки получается вот такой простой код:

const serviceBindings = require('kube-service-bindings');
try {
  kafkaConnectionBindings = 
    serviceBindings.getBinding('KAFKA', 'kafkajs');
} catch (err) { // proper error handling here
};
const kfk = new Kafka(kafkaConnectionBindings);

Первый параметр — KAFKA, поскольку мы подключаемся к сервису Kafka (в будущем kube-service-bindings сможет создавать привязки и к другим типам сервисов).

Данный пример реактивного кода позволяет получать учетные данные из среды, файла dotenv или автоматически, если учетные данные доступны через привязки сервисов. В репозитории присутствуют две ветки: kafkajs и node-rdkafka. Открыв эти ветки, вы можете посмотреть код для предпочитаемого вами клиента и узнать, каким образом kube-service-bindings предоставляет учетные данные в нужном формате для этого клиента.

Настройка привязки сервисов в OpenShift

Мы рассмотрели, как с помощью kube-service-bindings разработчики на Node.js с легкостью могут использовать учетные данные, доступные через привязки сервисов.

Пора переходить ко второй части — настройке самих привязок сервисов. В статье Подключение приложений на Node.js к Red Hat OpenShift Streams для Apache Kafka посредством привязки сервисов описываются шаги по настройке привязки сервиса для подключения приложения на Node.js к экземпляру Red Hat OpenShift Streams для Apache Kafka. Как и следовало ожидать, в среде Kubernetes сначала необходимо установить несколько операторов. Затем с помощью YAML одному из этих операторов сообщается о необходимости привязать экземпляр OpenShift Streams для Apache Kafka к приложению.

Еще одной приятной новостью является то, что с выходом OpenShift 4.8 можно использовать для выполнения привязки пользовательский интерфейс OpenShift! Таким образом, администратор/операторы кластера могут легко настроить экземпляр Kafka для организации. После этого разработчики могут подключать свои приложения без необходимости знать учетные данные. Пользовательский интерфейс облегчает использование привязок на этапе первоначальной разработки. Впоследствии же для более автоматизированного/производственного развертывания можно использовать YAML.

Чтобы самостоятельно убедиться в том, насколько это просто, выполните следующие шаги для подключения приложения к настроенному экземпляру Kafka:

  1. Наведите указатель мыши на значок приложения, как показано на рис. 3 (consumer-backend — один из компонентов примера реактивного приложения).

Рис. 3. Значок приложения consumer-backend в пользовательском интерфейсе OpenShift
Рис. 3. Значок приложения consumer-backend в пользовательском интерфейсе OpenShift

2. Щелкните левой кнопкой мыши и перетащите кончик стрелки на значок объекта KafkaConnection (рис. 4).

Рис. 4. Объект KafkaConnection в пользовательском интерфейсе OpenShift
Рис. 4. Объект KafkaConnection в пользовательском интерфейсе OpenShift

3. Отпустите левую кнопку мыши, чтобы создать привязку сервиса.

Вот и все! Если в вашем коде используется пакет kube-service-bindings, то учетные данные будут автоматически найдены посредством привязки, а затем будет выполнено подключение к серверу для вашего экземпляра Kafka.

Node.js и Apache Kafka: дополнительные ресурсы

В этой статье мы рассмотрели учетные данные, необходимые для подключения к серверу Kafka, и узнали, каким образом их можно безопасно передавать приложениям на Node.js. Если вы хотите погрузиться в эту тему глубже, попробуйте следующее:

  1. Установите пример реактивного приложения и поэкспериментируйте с ним, чтобы лучше разобраться с кодом и пакетом kube-service-bindings (самые смелые могут создать свои собственные файлы и задать SERVICE_BINDING_ROOT для указания на них).

  2. Изучите настройки привязки сервисов для экземпляра Kafka, описанные в статье Подключение приложений на Node.js к Red Hat OpenShift Streams для Apache Kafka посредством привязки сервисов.

  3. Изучите краткую инструкцию по ручному подключению Node.js к Kafka, опубликованную на клиентском портале Red Hat.

  4. Ознакомьтесь с руководством по автоматической привязке Node.js к Kafka, опубликованным на клиентском портале Red Hat.

  5. Если вы установили оператор RHOAS, изучите краткую инструкцию по автоматической привязке Node.js.

Все новости о деятельности Red Hat в сфере Node.js доступны на нашей странице, посвященной Node.js.


Материал подготовлен в рамках курса «Node.js Developer». Если вам интересно узнать подробнее о формате обучения и программе, познакомиться с преподавателем курса — приглашаем на день открытых дверей онлайн. Регистрация здесь.

Комментарии (0)