Микросервисы Kubernetes на Azure с помощью Cosmos DB

В этом руководстве вы узнаете, как развернуть реактивный микросервис на базе JHipster в Azure Kubernetes Service (AKS). Вы будете использовать Cosmos DB в Azure в качестве постоянного хранилища для одной из служб. Для обеспечения безопасности вы будете использовать Okta в качестве провайдера OAuth 2.0 и OpenID Connect (OIDC). Вы также надежно зашифруете все секреты в конфигурационных файлах проекта с помощью Kubernetes secrets и kubeseal. В этом руководстве основное внимание уделяется развертыванию уже созданного проекта в Azure AKS. В нем нет подробного описания создания проекта. Чтобы увидеть, как проект был создан с помощью JHipster, посмотрите статью Reactive Java Microservices with Spring Boot and JHipster.

Проект состоит из нескольких различных частей:

  • JHipster Registry: сервер Eureka для обнаружения сервисов и сервер Spring Cloud Config для централизованного управления конфигурацией.
  • Шлюз: публичное приложение Spring Cloud Gateway с использованием Vue
  • Магазин: микросервис Spring Boot с использованием Azure’s Cosmo DB API для MongoDB.
  • Блог: Микросервис Spring Boot с использованием базы данных Neo4J

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

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

Обзор архитектуры микросервисов JHipster

JHipster – это платформа разработки, которая упрощает создание, разработку и развертывание как монолитных, так и микросервисных приложений. Она поддерживает головокружительное множество технологий frontend (Angular, React и Vue) и backend (Spring Boot, Micronaut, Quarkus, Node.js и .NET). Он разработан для развертывания с помощью Docker и Kubernetes и может быть легко развернут на всех основных облачных платформах, таких как AWS, Azure, Heroku, Cloud Foundry, Google Cloud Platform и OpenShift.

Проект в этом учебнике использует Spring Boot с серверами ресурсов Java и фронтендом Vue. Он был создан с помощью генератора JHipster, который быстро создает новое приложение на основе интерактивной оболочки или DSL-файла. Подробнее о генерации микросервисов с помощью JHipster можно прочитать в документации. Одной из особенностей генератора JHipster является то, что вместе с приложениями вы можете генерировать сущности данных.

Реестр JHipster, который генерируется вместе с микросервисом, включает две важные функции: сервер Eureka и сервер Spring Cloud Config. Сервер Eureka позволяет микросервисам динамически находить друг друга без необходимости использовать жестко закодированные URI. Это означает, что микросервис может масштабироваться, а сервисы могут быть заменены без возникновения проблем. Это что-то вроде телефонной книги или службы DNS для микросервиса. Сервер Spring Cloud Config позволяет централизовать конфигурацию проекта и распределить ее по всем различным сервисам. В этом руководстве вы будете использовать эту функцию для настройки всех сервисов для Okta OAuth в одном месте.

JHipster API Gateway – это публичное лицо вашего микросервиса. Весь публичный трафик проходит через этот сервис, который также включает фронтенд Vue. Шлюз является одним из трех типов приложений, которые могут быть созданы с помощью DSL генератора JHipster. Два других – это монолит и микросервис. Монолит – это немикросервисное приложение с одним сервисом.

Сервис магазина и сервис блога являются примерами микросервисного типа приложений. Это означает, что каждый сервис представляет собой сервер ресурсов Spring Boot с каким-либо типом бэкенда SQL или NoSQL.

Генератор создает четыре приложения. Они предназначены для создания и запуска в виде контейнеров docker, что позволяет легко упаковывать их в капсулы Kubernetes. Kubernetes – это контейнерный оркестратор, специально разработанный для управления сетями микросервисов. Это нечто похожее на Docker Compose, но созданное для микросервисов, с множеством замечательных функций, таких как обнаружение сервисов, балансировка нагрузки, автоматическое развертывание и перезапуск, управление ресурсами и монтирование хранилищ.

Предварительные условия

Этот учебник состоит из множества частей. Установите необходимое программное обеспечение, указанное ниже, и зарегистрируйте учетную запись Azure Cloud. Вам понадобится бесплатная учетная запись Okta, но вы можете использовать Okta CLI для ее регистрации далее в учебнике.

  • Docker: вам потребуется установить Docker Engine и Docker Compose (если вы установите рабочий стол Docker, он автоматически установит оба. В Linux, если вы устанавливаете Docker Engine отдельно, вам также придется установить Docker Compose).
  • Docker Hub: вам понадобится Docker Hub для размещения образов докеров, чтобы Azure мог их получить.
  • Java 11: для этого руководства требуется Java 11. Если вам нужно управлять несколькими версиями Java, то SDKMAN! является хорошим решением. Ознакомьтесь с их документацией, чтобы установить его.
  • Okta CLI: вы будете использовать Okta для добавления безопасности в сеть микросервисов. Вы можете зарегистрировать бесплатную учетную запись в CLI.
  • Учетная запись Azure Cloud: они предлагают бесплатный уровень учетной записи с кредитом в 200 долларов для начала.
  • Azure CLI: вы будете использовать Azure CLI для управления кластером Kubernetes.
  • kubectl: CLI для управления кластерами Kubernetes.

Если у вас никогда раньше не было учетной записи Azure, вы можете создать новую, которая будет предоставлять свободный доступ и на которую выделено 200 долларов. Этого более чем достаточно для завершения данного руководства. Однако срок действия кредита истекает через 30 дней. Если у вас не осталось кредитов или срок их действия истек, стоимость этого учебника составит всего несколько долларов, если вы будете останавливать и запускать кластер AKS, когда не работаете над ним. Вы можете следить за своими расходами с помощью проводника расходов на портале Azure и устанавливать предупреждения, если вас это беспокоит. Переход на оплату по факту может также облегчить некоторые проблемы с дросселированием ресурсов при тестировании кластеров AKS.

Микросервисы Spring Boot для Azure и Cosmos DB

Этот проект основан на двух учебниках Мэтта Рэйбла: Reactive Java Microservices with Spring Boot and JHipster и Kubernetes to the Cloud with Spring Boot and JHipster. В этих руководствах он создает реактивную Java-микросервисную архитектуру и показывает, как развернуть ее в Google Cloud (GCP). Я модифицировал проект для работы с Azure и Cosmos DB.

Сначала вы запустите проект с помощью Docker Compose. После этого проект будет запущен как кластер Kubernetes на Azure. Мои изменения были относительно незначительными и включали удаление ненужных экземпляров MongoDB (как из файла docker-compose.yml, так и из дескрипторов Kubernetes), а также обновление значений окружения для указания службы store на экземпляр Cosmos DB вместо экземпляра MongoDB.

Ниже приводится краткий список изменений, которые я сделал на основе сообщений Мэтта Рэйбла, чтобы заставить это работать с Azure и Cosmos DB. Вы можете пропустить этот список (и следующий раздел) и сразу перейти к клонированию Git-репозитория, если хотите, но поскольку здесь описано, как обновить проект, созданный на JHipster, для использования Cosmos DB, я подумал, что это стоит включить.

В файле docker-compose/docker-compose.yml:

  • удалена служба MongoDB
  • обновлено свойство store сервиса SPRING_DATA_MONGODB_URI для указания на экземпляр Cosmos DB через файл .env
  • удалили сервис Keycloak и переменные окружения, которые настраивали auth на использование Keycloak, из оставшихся сервисов (не строго обязательно, но порядок навели)

В директории k8s/store-k8s:

  • удалили файл store-mongodb.yml (Он создает службу MongoDB Kubernetes, которая не нужна нашему проекту).
  • в store-deployment.yml:
    • удален initContainers (Контейнер init ожидает экземпляр MongoDB, который удаляется).
    • обновлено значение переменной SPRING_DATA_MONGODB_URI контейнера store-app на URI Cosmos DB (Это указывает магазину на экземпляр Cosmos DB).
    • правильно защитили строку подключения к Cosmos DB с помощью секретов Kubernetes и kubeseal.

Установка начального статуса приложения магазина для Eureka

Создавая этот учебник, я столкнулся с проблемой, когда приложение магазина застряло в состоянии OUT_OF_SERVICE. Когда я просмотрел журналы, я обнаружил, что служба начиналась как UP, быстро переходила в DOWN, а затем OUT_OF_SERVICE. Позже он вернулся к UP, но сервер Eureka так и не зарегистрировал это изменение.

Существует открытый вопрос, документирующий эту проблему на Spring Cloud Netflix и Netflix Eureka.

Временное решение, взятое из проблемы на GitHub, заключается в переопределении реализации отчетов о состоянии здоровья таким образом, чтобы она возвращала DOWN вместо OUT_OF_SERVICE во время запуска программы. Это блокирует ее от сообщения OUT_OF_SERVICE. Вы можете увидеть исправление в файле EurekaFix.java в приложении магазина.

Клонируйте проект микросервисов с GitHub

Клонируйте модифицированный проект реактивного микросервиса JHipster с GitHub и проверьте тег start.

git clone https://github.com/oktadev/okta-azure-kubernetes-cosmosdb-example.git 
  azure-k8s-cosmosdb
cd azure-k8s-cosmosdb
git fetch --all --tags
git checkout tags/start -b working
Войдите в полноэкранный режим Выйдите из полноэкранного режима

Создание Azure Cosmos DB с API для MongoDB

Вам необходимо создать экземпляр Azure Cosmos DB. Вы можете использовать либо портал Azure Portal, либо CLI для создания нового экземпляра Cosmos DB. Убедитесь, что вы создаете экземпляр Azure Cosmos DB с API для MongoDB (Cosmos DB поддерживает различные типы баз данных). Если вы используете портал, все довольно просто, но не забудьте включить бесплатный уровень и включить публичную сеть.

Ниже приведены инструкции по использованию CLI.

Войдите в Azure CLI с помощью оболочки Bash. Это перенаправит вас в браузер для входа на портал Azure.

az login
Войдите в полноэкранный режим Выйдите из полноэкранного режима

Должны отобразиться подписки для вашей учетной записи.

[
  {
    "cloudName": "AzureCloud",
    "homeTenantId": "21c44b6d-a007-4d48-80cb-c45966ca1af9",
    "id": "90eb9f51-b4be-4a9f-a69f-11b7668a874d",
    "isDefault": true,
    "managedByTenants": [],
    "name": "Azure subscription 1",
    "state": "Enabled",
    "tenantId": "21c44b6d-a007-4d48-80cb-c45966ca1af9",
    "user": {
      "name": "andrewcarterhughes@outlook.com",
      "type": "user"
    }
  }
]
Войти в полноэкранный режим Выйти из полноэкранного режима

Установите подписку в оболочке. Ваша подписка, вероятно, Azure subscription 1, поскольку она используется по умолчанию. Убедитесь, что вы используете подписку, которая была создана при регистрации бесплатной учетной записи (или любую другую подписку, если у вас уже есть учетная запись).

az account set --subscription <you-subscription-name>
Вход в полноэкранный режим Выход из полноэкранного режима

Откройте оболочку Bash. Создайте группу ресурсов с помощью следующей команды.

az group create --name australia-east --location australiaeast
Войти в полноэкранный режим Выйти из полноэкранного режима

Создайте учетную запись Cosmos DB в группе ресурсов. Подставьте имя вашей подписки Azure в команду ниже (вероятно, это Azure subscription 1, то есть то, что у меня установлено по умолчанию).

az cosmosdb create --name jhipster-cosmosdb --resource-group australia-east 
  --kind MongoDB --subscription <you-subscription-name> --enable-free-tier true 
  --enable-public-network true
Войдите в полноэкранный режим Выйдите из полноэкранного режима

После возврата команды (это может занять несколько минут) в списке должно быть много JSON, показывающих свойства созданной учетной записи Cosmos DB.

Если вы получите ошибку с надписью:

(BadRequest) DNS record for cosmosdb under zone Document is already taken.
Войдите в полноэкранный режим Выйти из полноэкранного режима

Тогда вам нужно изменить параметр --name на что-то другое. Поскольку он используется для генерации публичного URI для базы данных, он должен быть уникальным для всей Azure. Попробуйте добавить свое имя или несколько случайных чисел.

Я использую расположение Australia East, потому что именно в этом месте были доступны узлы AKS бесплатного уровня, когда я писал это руководство. Вы можете использовать любую группу ресурсов, если она позволяет вам создать кластер AKS, о котором пойдет речь далее в руководстве. Даже если вы не можете использовать бесплатный уровень или бесплатные кредиты, если вы останавливаете и запускаете кластер AKS между работой над учебником, затраты должны быть очень небольшими (мои составили менее нескольких долларов). Приложение будет работать, если база данных Cosmos DB находится в другой группе ресурсов и регионе, поскольку URI базы данных настроен на открытый доступ.

Перечислите строку подключения для конечной точки Cosmos DB API для MongoDB с помощью следующей команды. Если вы изменили имя базы данных выше, вам нужно будет обновить его в команде ниже.

az cosmosdb keys list --type connection-strings --name jhipster-cosmosdb 
  --resource-group australia-east
Вход в полноэкранный режим Выйти из полноэкранного режима

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

{
  "connectionStrings": [
    {
      "connectionString": "mongodb://jhipster-cosmosdb:XBq5KZ81V8hM63KjCOezi1arq...",
      "description": "Primary MongoDB Connection String"
    },
    ...
  ]
}
Войти в полноэкранный режим Выход из полноэкранного режима

Отредактируйте файл .env в подкаталоге docker-compose. Добавьте в него следующие переменные, заменив строку подключения на заполнитель. Убедитесь, что строка подключения заключена в кавычки. Это значение будет использоваться в файле docker-compose.yml и передаваться службе store, указывая ей на базу данных Cosmos DB MongoDB.

Ключ ENCRYPT_KEY будет использоваться в качестве ключа для шифрования конфиденциальных значений, хранящихся в Spring Cloud Config и используемых реестром JHipster. Вы можете поместить туда любое значение, какое захотите. Хорошо работает UUID, но подойдет любое строковое значение. Чем длиннее, тем лучше.

docker-compose/.env

SPRING_DATA_MONGO_URI=<your-connection-string>
ENCRYPT_KEY=<your-encryption-key>
Вход в полноэкранный режим Выход из полноэкранного режима

Настройка идентификации с помощью Okta

Прежде чем начать, вам понадобится бесплатная учетная запись разработчика Okta. Установите Okta CLI и выполните команду okta register, чтобы зарегистрировать новую учетную запись. Если у вас уже есть учетная запись, выполните команду okta login. Затем выполните команду okta apps create jhipster. Выберите имя приложения по умолчанию или измените его по своему усмотрению. Примите значения URI перенаправления по умолчанию, предоставленные для вас.

Что делает Okta CLI?

Okta CLI упрощает настройку приложения JHipster и делает несколько вещей за вас:

  1. Создает приложение OIDC с правильными URI перенаправления:
    • login: http://localhost:8080/login/oauth2/code/oidc и http://localhost:8761/login/oauth2/code/oidc.
    • выход из системы: http://localhost:8080 и http://localhost:8761.
  2. Создает группы ROLE_ADMIN и ROLE_USER, которые ожидает JHipster
  3. Добавляет вашего текущего пользователя в группы ROLE_ADMIN и ROLE_USER
  4. Создает утверждение groups в вашем стандартном сервере авторизации и добавляет в него группы пользователя

ПРИМЕЧАНИЕ: URI перенаправления http://localhost:8761* предназначены для реестра JHipster, который часто используется при создании микросервисов с JHipster. Okta CLI добавляет их по умолчанию.

Запустите cat .okta.env (или type .okta.env в Windows), чтобы увидеть эмитента и учетные данные для вашего приложения.

ПРИМЕЧАНИЕ: Вы также можете использовать консоль администратора Okta для создания приложения. Дополнительную информацию смотрите в разделе Создание приложения JHipster на Okta.

Обратите внимание на название, потому что вам нужно будет найти приложение в консоли администратора Okta и обновить URI перенаправления немного позже. Команда okta apps создает файл конфигурации с именем .okta.env. Он будет выглядеть примерно так, как показано ниже. В нем полезно перечислить значения, которые понадобятся вам на следующем шаге.

export SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_OIDC_ISSUER_URI="https://dev-13337.okta.com/oauth2/default"
export SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_OIDC_CLIENT_ID="2989u928u383..."
export SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_OIDC_CLIENT_SECRET="09328uu098u4..."
Войти в полноэкранный режим Выйти из полноэкранного режима

И проект Docker Compose, и проект Kubernetes используют Spring Cloud Config для централизации конфигурации. Служба реестра JHipster делает эти значения конфигурации доступными для всех других служб в кластере.

Откройте docker-compose/central-server-config/application.yml и добавьте следующее в конец, заполнив issuer-uri, client-id и client-secret, взятые из файла .okta.env. Это файл Spring Cloud Config для проекта Docker Compose.

docker-compose/central-server-config/application.yml

spring:
  security:
    oauth2:
      client:
        provider:
          oidc:
            issuer-uri: https://<your-okta-domain>/oauth2/default
        registration:
          oidc:
            client-id: <client-id>
            client-secret: <client-secret>
Вход в полноэкранный режим Выход из полноэкранного режима

Сборка образов Docker и запуск приложения с помощью Docker Compose

Вы готовы к локальному запуску приложения с помощью Docker и Docker Compose. Вам нужно собрать образ docker для каждого из проектов: gateway, store и blog (вам не нужно собирать registry, так как он использует образ).

В трех разных каталогах приложений выполните следующую команду Gradle.

./gradlew -Pprod bootJar jibDockerBuild
Войти в полноэкранный режим Выйдите из полноэкранного режима

Настроек ресурсов Docker по умолчанию может быть недостаточно для запуска этого проекта. Вам может потребоваться изменить их. Эти настройки сработали для меня.

  • Процессоры: 8
  • Память: 25 ГБ
  • Своп: 2 ГБ
  • Размер образа диска: 120 ГБ

Перейдите в каталог docker-compose и запустите приложение. Вы можете использовать параметр -d, чтобы запустить его как демон, но на данный момент мне нравится видеть журналы. В любом случае, вы просто запускаете приложение в Docker Compose в качестве разминки перед развертыванием в Azure.

docker-compose up
Вход в полноэкранный режим Выйдите из полноэкранного режима

Дайте ему минуту или две, чтобы закончить запуск всех служб.

Откройте службу шлюза по адресу http://localhost:8080.

Перейдите в раздел “Учетная запись” и “Войти”. Вы должны быть направлены на форму входа в Okta.

Вы должны иметь возможность аутентифицироваться с помощью учетных данных Okta.

Убедитесь, что все части приложения работают. Сначала протестируйте магазин (который использует базу данных Cosmos DB Mongo), перейдя в Entities и Product. Убедитесь, что вы можете добавить новый продукт и увидеть его в списке продуктов. Затем создайте блог (Entities and Blog).

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

Вы также можете проверить реестр JHipster по адресу http://localhost:8761.

Шифрование клиентского секрета

Оставлять секреты открытым текстом в репозиториях – это риск для безопасности. В этом приложении есть два значения, которые являются конфиденциальными: строка подключения к Cosmos DB, включающая имя пользователя и пароль, и секрет клиента приложения Okta OIDC. Вы смогли избежать раскрытия учетных данных базы данных, используя файл .env. Однако секрет клиента Okta раскрывается в виде обычного текста в файле Spring Cloud Config (docker-compose/central-server-config/application.yml). Его можно зашифровать с помощью реестра JHipster.

Откройте реестр (http://localhost:8761) и нажмите на Configuration and Encryption.

Вставьте свой клиентский секрет в текстовое поле. Нажмите Шифровать.

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

Теперь вы можете скопировать зашифрованное значение и вставить его обратно в файл application.yml. Убедитесь, что вы включили часть {cipher}. Это должно выглядеть примерно так, как показано ниже. Не забудьте про кавычки!

docker-compose/central-server-config/application.yml

...
spring:
  security:
    oauth2:
      client:
        provider:
          oidc:
            issuer-uri: https://dev-123456.okta.com/oauth2/default
        registration:
          oidc:
            client-id: 0oa6ycm987987uy98
            client-secret: "{cipher}88acb434dd088acb434dd088acb434dd0..."
Войти в полноэкранный режим Выйти из полноэкранного режима

Остановите приложение, если вы этого еще не сделали, используя control-c. Перезапустите его.

docker-compose up
Войти в полноэкранный режим Выйдите из полноэкранного режима

Убедитесь, что вы все еще можете войти в шлюз по адресу http://localhost:8080.

Вы можете задаться вопросом (как и я вначале), почему я не могу просто поместить секрет клиента в файл .env? Это не работает, потому что файл .env обрабатывается Spring Cloud Config и реестром JHipster после создания контейнера, а не Docker Compose во время создания контейнера, когда обрабатывается файл .env.

Вы закончили с реализацией Docker Compose. Чтобы очистить систему, вы можете выполнить следующую команду. Это остановит и удалит контейнеры, сети, тома и образы, созданные командой docker-compose up.

docker-compose down --remove-orphans
Войти в полноэкранный режим Выход из полноэкранного режима

Создание кластера Azure Kubernetes

Приложение работает локально. Теперь пришло время развернуть его в кластере Azure Kubernetes (AKS). Первым шагом будет создание кластера AKS.

Для создания кластера очень просто использовать CLI. Я покажу вам команду ниже. Однако здесь есть одна сложность. Бесплатный уровень не может создать кластер во многих регионах из-за квот на ресурсы. По крайней мере, так было, когда я работал над этим руководством. Также нет простого способа быстро увидеть, в каких регионах можно создать кластер бесплатного уровня. Вот почему я использовал в качестве региона Восточную Австралию – она позволила мне создать свободный кластер.

Если команда ниже не работает, я предлагаю перейти на портал Azure и создать кластер Kubernetes там. Выберите Create a service и Kubernetes Service. Вам придется выбрать разные регионы и посмотреть, какие размеры доступны (в разделе Node size и Change size), пока вы не найдете регион, который позволит вам создать что-то в бесплатном уровне. Но, надеюсь, команда сработает, и вам не придется беспокоиться об этом.

Размер, который я использую в этом руководстве – Standard B4ms с двумя узлами. Я обнаружил, что мне нужно два узла для правильного запуска кластера.

Выполните следующую команду для создания кластера AKS.

az aks create --resource-group australia-east --name jhipster-demo 
  --node-count 2 --enable-addons monitoring --generate-ssh-keys --node-vm-size standard_b4ms
Войти в полноэкранный режим Выйдите из полноэкранного режима

Это, вероятно, займет несколько минут.

В качестве примечания, вы можете остановить кластер в любой момент. Это приостановит биллинг на кластере.

az aks stop --resource-group australia-east --name jhipster-demo 
Вход в полноэкранный режим Выйти из полноэкранного режима

И вы можете запустить его снова.

az aks start --resource-group australia-east --name jhipster-demo 
Войти в полноэкранный режим Выход из полноэкранного режима

Остановить и запустить кластер можно также с портала Azure.

Следующим шагом будет получение учетных данных для кластера и их объединение в .kube/config, чтобы kubectl мог их использовать. Используйте следующую команду.

az aks get-credentials --resource-group australia-east --name jhipster-demo
Войти в полноэкранный режим Выйдите из полноэкранного режима

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

Merged "jhipster-demo" as current context in /home/andrewcarterhughes/.kube/config
Войти в полноэкранный режим Выйти из полноэкранного режима

Вы должны иметь возможность использовать kubectl для получения узла на Azure.

kubectl get nodes
Войти в полноэкранный режим Выход из полноэкранного режима
NAME                                STATUS   ROLES   AGE    VERSION
aks-nodepool1-21657131-vmss000000   Ready    agent   105s   v1.22.6
aks-nodepool1-21657131-vmss000001   Ready    agent   108s   v1.22.6
Войти в полноэкранный режим Выйти из полноэкранного режима

Вы также можете вывести много информации о кластере в формате JSON с помощью:

az aks list --resource-group australia-east
Войти в полноэкранный режим Выйти из полноэкранного режима

Настройка Kubernetes для Okta и Cosmos DB

Файлы Kubernetes в каталоге k8s были созданы с помощью подгенератора JHipster Kubernetes (см. документацию для получения информации). Чтобы увидеть, как создавался оригинальный проект, посмотрите учебник по JHipster и Kubernetes от Matt Raible. Как указано выше, эти файлы были изменены для работы с Azure Cosmos DB вместо MongoDB в Kubernetes pod (что и предполагает подгенератор).

Настройте Spring OAuth в Kubernetes pod, обновив k8s/registry-k8s/application-configmap.yml. Вы можете использовать те же значения, которые вы использовали выше в разделе Docker Compose, в docker-compose/central-server-config/application.yml.

Убедитесь, что вы используете зашифрованный секрет клиента, заключенный в кавычки с префиксом {cipher}. Вы собираетесь скопировать ключ шифрования и зашифрованный клиентский секрет из конфигурации Docker Compose, чтобы избежать необходимости повторного шифрования клиентского секрета новым ключом.

data:
  application.yml: |-
    ...
    spring:
      security:
        oauth2:
          client:
            provider:
              oidc:
                issuer-uri: https://<your-okta-domain>/oauth2/default
            registration:
              oidc:
                client-id: <client-id>
                client-secret: "{cipher}<encrypted-client-secret>"
Вход в полноэкранный режим Выход из полноэкранного режима

Чтобы настроить JHipster Registry на использование OIDC для аутентификации, необходимо изменить k8s/registry-k8s/jhipster-registry.yml, чтобы включить профиль oauth2. Это уже сделано для вас в примере приложения в Git-репозитории проекта.

- name: SPRING_PROFILES_ACTIVE
  value: prod,k8s,oauth2
Вход в полноэкранный режим Выход из полноэкранного режима

Также в k8s/registry-k8s/jhipster-registry.yml обновите значение ENCRYPT_KEY, чтобы использовать тот же ключ шифрования, который вы использовали выше в разделе Docker Compose в файле .env.

- name: ENCRYPT_KEY
  value: <your-encryption-key>
Вход в полноэкранный режим Выход из полноэкранного режима

Чтобы настроить службу store на использование базы данных Cosmo, вам нужно поместить строку подключения в k8s/store-k8s/store-deployment.yml.

- name: SPRING_DATA_MONGODB_URI
  value: "<your-connection-string>"
Вход в полноэкранный режим Выход из полноэкранного режима

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

Сборка образов Docker и отправка в Docker Hub

Ранее вы создали образы докеров, но оставили их в локальном хранилище. Теперь вам нужно загрузить их в Docker Hub, чтобы Azure AKS мог их найти. Если вы еще не зарегистрировали учетную запись Docker Hub, сделайте это сейчас.

В каждой из трех директорий (blog, store и gateway) выполните следующую команду. Сохраните имя пользователя Docker Hub в переменной Bash, как показано ниже, и вы сможете скопировать и вставить эти команды и запустить их в каждом каталоге служб.

DOCKER_HUB_USERNAME=<docker-hub-username>
# in blog
./gradlew bootJar -Pprod jib -Djib.to.image=$DOCKER_HUB_USERNAME/blog
# in store
./gradlew bootJar -Pprod jib -Djib.to.image=$DOCKER_HUB_USERNAME/store
# in gateway
./gradlew bootJar -Pprod jib -Djib.to.image=$DOCKER_HUB_USERNAME/gateway
Вход в полноэкранный режим Выход из полноэкранного режима

Чтобы кратко объяснить, что здесь происходит, взгляните на файл дескриптора Kubernetes службы блогов. Он определяет контейнер с именем blog-app, который использует образ docker andrewcarterhughes/blog, который является моим именем пользователя Docker Hub и образом блога.

k8s/blog-k8s/blog-deployment.yml

containers:
  - name: blog-app
    image: andrewcarterhughes/blog
Войдите в полноэкранный режим Выйти из полноэкранного режима

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

Чтобы использовать только что созданные образы в Kubernetes, выполните поиск и замену в каталоге k8s. Замените все экземпляры andrewcarterhughes на ваше имя пользователя Docker Hub (<docker-hub-username>).

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

Развертывание ваших микросервисов в Azure AKS

Вы можете управлять службой Kubernetes исключительно с помощью kubectl. Однако есть несколько довольно полезных инструментов для мониторинга и протоколирования. Отлично подходят k9s и Kubernetes Lens. Я рекомендую установить один или оба из них и использовать их для проверки и мониторинга ваших служб Kubernetes. Они особенно полезны, когда что-то идет не так (не то чтобы что-то никогда не шло не так, я ничего об этом не знаю, я просто слышал об этом от друзей, клянусь). Kubernetes Lens – это полноценное настольное приложение, которое описывает себя как Kubernetes IDE. Для сравнения, k9s – это более легкий текстовый инструмент.

Откройте оболочку Bash и перейдите в подкаталог k8s проекта.

Разверните свою микросервисную архитектуру в Azure с помощью:

./kubectl-apply.sh -f
Войдите в полноэкранный режим Выйти из полноэкранного режима

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

...
suffix=k8s
kubectl apply -f namespace.yml
kubectl apply -f registry-${suffix}/
kubectl apply -f blog-${suffix}/
kubectl apply -f gateway-${suffix}/
kubectl apply -f store-${suffix}/
...
Вход в полноэкранный режим Выход из полноэкранного режима

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

kubectl get pods -n demo
Вход в полноэкранный режим Выход из полноэкранного режима
NAME                                  READY   STATUS    RESTARTS   AGE
blog-6896f6dd58-mbjkn                 1/1     Running   0          3m51s
blog-neo4j-0                          1/1     Running   0          3m48s
gateway-7f6d57765f-2fhfb              1/1     Running   0          3m46s
gateway-postgresql-647476b4d5-jdp5c   1/1     Running   0          3m44s
jhipster-registry-0                   1/1     Running   0          3m52s
store-7889695569-k4wkv                1/1     Running   0          3m41s
Вход в полноэкранный режим Выход из полноэкранного режима

Вот пример того, как это выглядит с Kubernetes Lens (контейнеры все еще загружались).

Еще одна полезная команда – describe. Я не буду воспроизводить ее вывод здесь, но если вам нужна более подробная информация для отладки, вы можете выполнить следующее.

kubectl describe pods -n demo
Войти в полноэкранный режим Выйти из полноэкранного режима

Для вывода хвостовых логов можно использовать имя стручка.

kubectl logs <pod-name> --tail=-1 -n demo
Войти в полноэкранный режим Выйти из полноэкранного режима

Хотя, как я уже сказал, для более детального осмотра лучше всего использовать k9s и Lens.

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

Вы можете использовать переадресацию портов для просмотра реестра JHipster.

kubectl port-forward svc/jhipster-registry -n demo 8761
Вход в полноэкранный режим Выход из полноэкранного режима

Откройте браузер и перейдите по адресу http://localhost:8761. Вы будете перенаправлены на экран входа в Okta, после чего попадете в реестр.

Убедитесь, что все отмечено зеленым цветом. Если у вас возникла ошибка, проверьте журналы на наличие модуля, который вызвал ошибку. Вы можете перезапустить конкретное развертывание, удалив его и применив заново. Например, чтобы перезапустить магазин, вы можете использовать команды ниже из каталога k8s.

kubectl delete -f store-k8s/
kubectl apply -f store-k8s/
Войти в полноэкранный режим Выйти из полноэкранного режима

Когда все будет в порядке, control-c, чтобы остановить пересылку реестра. Выставьте шлюз и откройте его.

kubectl port-forward svc/gateway -n demo 8080
Войдите в полноэкранный режим Выйдите из полноэкранного режима

Перейдите по адресу http://localhost:8080.

Пройдите аутентификацию с помощью Okta. Убедитесь, что вы можете добавлять блоги, посты, теги и продукты. Поскольку служба магазина использует тот же экземпляр Cosmos DB, который вы использовали в Docker Compose локально, все тестовые продукты, созданные вами ранее, все еще будут там.

Для подготовки к следующему шагу удалите все, что вы только что развернули на AKS в пространстве имен demo.

kubectl delete all --all -n demo
Вход в полноэкранный режим Выход из полноэкранного режима

Первый all относится ко всем типам ресурсов. Второй --all относится к каждому объекту в типах ресурсов (в отличие от указания имени или ID объекта). Таким образом, указывая пространство имен, вы удаляете каждый объект каждого типа ресурсов в этом пространстве имен.

Это одно из преимуществ использования пространства имен. Вы можете выполнить удаление подобным образом. Если вы сделаете это из пространства имен по умолчанию, вы рискуете удалить то, что не хотели удалять, или стручки, добавленные Kubernetes и Azure для администрирования инфраструктуры.

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

kubectl delete namespace demo
Войти в полноэкранный режим Выход из полноэкранного режима

Шифрование важных параметров конфигурации

Есть два действительно важных значения конфигурации, которые необходимо зашифровать: (1) строка подключения Cosmos DB (которая содержит учетные данные базы данных) и (2) секрет клиента OIDC. Поскольку эти два значения обрабатываются по-разному, вы будете использовать два немного разных метода для их шифрования.

Здесь есть три разных уровня шифрования. Мне это показалось немного запутанным, поэтому я объясню это вкратце.

  • Шифрование реестра JHipster для значений Spring Cloud Config (значения в k8s/registry-k8s/application-configmap.yml)
  • “Шифрование” Kubernetes (обфускация, на самом деле), которое перемещает секреты, найденные в файлах развертывания Kubernetes, в файлы секретов в base64-кодировке.

Первая из перечисленных выше функций предназначена только для значений Spring Cloud Config. Последние два используются для шифрования значений в файлах дескрипторов Kubernetes (другие файлы yml в каталоге k8s).

Когда вы используете шифрование реестра JHipster, вы должны определить значение ENCRYPT_KEY, которое используется JHipster для шифрования секретов. Однако, поскольку это значение хранится в файлах yml, которые будут зафиксированы в репозитории, это значение должно быть надлежащим образом зашифровано для обеспечения безопасности значений Spring Cloud Config.

Строка подключения Cosmos DB (переменная окружения SPRING_DATA_MONGODB_URI) является значением развертывания Kubernetes, как и ENCRYPT_KEY, а не значением Spring Cloud Config.

Таким образом, чтобы усилить секрет клиента OIDC, вы должны (1) определить ENCRYPT_KEY, чтобы включить шифрование реестра JHipster, (2) использовать реестр JHipster для шифрования идентификатора клиента и поместить зашифрованное значение в application-configmap. yml, и (3) используйте секреты Kubernetes и kubeseal для правильного шифрования ENCRYPT_KEY.

Защита строки подключения Cosmos DB такая же, как и ENCRYPT_KEY: используйте секреты Kubernetes и kubeseal для правильного шифрования.

Мэтт Рэйбл проделал большую работу по объяснению управления секретами в Kubernetes в своем посте Kubernetes to the Cloud with Spring Boot and JHipster. Он также дал ссылки на множество отличных ресурсов. Я не буду вдаваться в подробности, объясняя это здесь. Ознакомьтесь с его статьей, чтобы получить больше информации.

Первое, что вам нужно сделать, это установить kubeseal в кластер AKS. Вы можете взглянуть на страницу kubeseal GitHub для получения дополнительной информации.

kubectl apply -f https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.17.5/controller.yaml
Вход в полноэкранный режим Выход из полноэкранного режима

Получение пары ключей сертификата, которую генерирует этот контроллер.

kubectl get secret -n kube-system -l sealedsecrets.bitnami.com/sealed-secrets-key -o yaml
Войти в полноэкранный режим Выйти из полноэкранного режима

Скопируйте необработанное значение tls.crt и декодируйте его. Вы можете использовать командную строку или узнать больше о кодировании/декодировании base64 в нашей документации.

echo -n <paste-value-here> | base64 --decode
Вход в полноэкранный режим Выйдите из полноэкранного режима

Поместите необработанное значение в файл tls.crt.

Далее установите Kubeseal. На macOS вы можете использовать Homebrew. Для других платформ смотрите примечания к выпуску.

brew install kubeseal
Войдите в полноэкранный режим Выход из полноэкранного режима

Зашифруйте ENCRYPT_KEY и SPRING_DATA_MONGODB_URI (строка подключения к Cosmos DB). Для этого выполните следующую команду, заменив эти два значения ключом шифрования и строкой подключения.

kubectl create secret generic project-secrets 
  --from-literal=ENCRYPT_KEY='<your-encryption-key>' 
  --from-literal=SPRING_DATA_MONGODB_URI='<your-connection-string>' 
  --dry-run=client -o yaml > secrets.yml
Вход в полноэкранный режим Выйти из полноэкранного режима

Если вы ранее удалили пространство имен, вам нужно создать его снова (если вы не удаляли пространство имен, выполнить эту команду не помешает).

kubectl apply -f namespace.yml
Вход в полноэкранный режим Выйдите из полноэкранного режима

Теперь используйте kubeseal для преобразования секретов в зашифрованные секреты.

kubeseal --cert tls.crt --format=yaml -n demo < secrets.yml > sealed-secrets.yml
Войти в полноэкранный режим Выйдите из полноэкранного режима

Удалите исходный файл секретов и разверните ваши зашифрованные секреты.

rm secrets.yml
kubectl apply -n demo -f sealed-secrets.yml && kubectl get -n demo sealedsecret project-secrets
Войти в полноэкранный режим Выход из полноэкранного режима

Вам необходимо обновить файлы yml, чтобы они ссылались на зашифрованные значения. Добавьте следующую переменную env в контейнер jhister-registry в k8s/registry-k8s/jhipster-registry.yml (если ENCRYPT_KEY уже существует, замените ее).

env:
  ...
  - name: ENCRYPT_KEY
    valueFrom:
      secretKeyRef:
        name: project-secrets
        key: ENCRYPT_KEY
Вход в полноэкранный режим Выход из полноэкранного режима

В k8s/store-k8s/store-deployment.yml измените переменную окружения SPRING_DATA_MONGODB_URI, чтобы использовать запечатанный секрет.

env:
  ...
  - name: SPRING_DATA_MONGODB_URI
    valueFrom:
      secretKeyRef:
        name: project-secrets
        key: SPRING_DATA_MONGODB_URI
Вход в полноэкранный режим Выход из полноэкранного режима

Разверните кластер.

./kubectl-apply.sh -f
Войти в полноэкранный режим Выход из полноэкранного режима

Дайте кластеру немного запуститься. Проверьте его с помощью одного из упомянутых мною инструментов или следующим образом:

kubectl get pods -n demo
Войти в полноэкранный режим Выйти из полноэкранного режима

Когда все будет готово, пробросьте порт в реестр для проверки служб.

kubectl port-forward svc/jhipster-registry -n demo 8761
Войти в полноэкранный режим Выйти из полноэкранного режима

Убедитесь, что вы можете войти в систему и что все службы отмечены зеленым цветом. Вы должны либо автоматически войти в систему и перенаправить вас обратно на главную страницу, либо направить вас на вход в систему с помощью экрана входа в Okta.

Это счастливый танец.

Переадресуйте шлюз и протестируйте приложение.

kubectl port-forward svc/gateway -n demo 8080
Войдите в полноэкранный режим Выйдите из полноэкранного режима

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

Когда вы все сделаете, вы можете удалить группу ресурсов. Это также приведет к удалению всех ресурсов в группе ресурсов, включая базу данных Cosmos и кластер AKS. Если у вас несколько подписок, вам может понадобиться добавить параметр --subscription.

az group delete --name australia-east
Войти в полноэкранный режим Выход из полноэкранного режима

Подождите, пока это завершится. После этого, вероятно, стоит войти в Azure Portal и убедиться, что кластер AKS, экземпляр Cosmos DB и группа ресурсов были удалены.

Azure AKS, Kubernetes и микросервисы Spring Boot развернуты!

Спасибо Julien Dubois за помощь в завершении этого руководства!

В этом проекте вы увидели, как развернуть микросервис JHipster в Azure AKS. Вы увидели, как можно использовать управляемый экземпляр Cosmos DB вместо MongoDB pod в Kubernetes. Вы увидели, как развернуть приложение сначала с помощью Docker Compose, а затем с помощью kubectl и Azure CLI. Наконец, вы должным образом зашифровали все важные значения конфигурации с помощью комбинации шифрования реестра JHipster, секретов Kubernetes и kubeseal.

Как я уже упоминал в начале, этот проект основан на двух учебниках Мэтта Рэйбла:

  • Реактивные Java-микросервисы с Spring Boot и JHipster
  • Kubernetes в облаке с Spring Boot и JHipster

Deepu Sasidharan написал учебник “Развертывание микросервисов JHipster на Azure Kubernetes Service (AKS)”, который также оказал большую помощь.

Если вам понравилась эта статья, есть большая вероятность, что вам понравятся похожие статьи:

  • Introducing Spring Native for JHipster: Бессерверный Full-Stack Made Easy
  • Как защитить кластеры Kubernetes с помощью лучших практик
  • Мобильная разработка с Ionic, React Native и JHipster
  • Быстрая Java, упрощенная с помощью Quarkus и JHipster
  • Spring Cloud Config для совместной конфигурации микросервисов
  • Kubernetes To The Cloud With AWS: Развертывание приложения Node.js в EKS

Если у вас есть вопросы, пожалуйста, задавайте их в комментариях ниже! Если вы любите социальные сети, следите за нами: @oktadev в Twitter, Okta for Developers на LinkedIn и OktaDev на Facebook. Если вам нравится учиться на видео, подпишитесь на наш канал YouTube.

Оцените статью
Procodings.ru
Добавить комментарий