Статьи

Верховая езда на верблюдах в облаке с помощью JBoss Fuse и OpenShift

Red Hat недавно выпустила инструментарий интеграции Microservices для запуска наших микросервисов в среде Docker и Kubernetes на OpenShift v3 . Чтобы помочь людям понять это немного лучше, я перенес приложение Rider Auto , которое некоторое время назад использовалось для демонстрации Apache Camel и JBoss Fuse, в набор микросервисов, которые можно запускать в OpenShift / Kubernetes через контейнеры Docker. , В этом блоге подробно рассказывается об этом и приводятся конкретные примеры практических рекомендаций для наиболее нетривиального приложения. Я также сделаю несколько видеороликов, демонстрирующих это, поэтому следите за обновлениями в этом блоге ( http://blog.christianposta.com ) или следите за мной в твиттере @christianposta .

новления

Что такое Fuse Integration Services (FIS) для OpenShift?

FIS — это набор инструментов для разработчиков и образов Docker из вышестоящего сообщества fabric8.io, предназначенных для упаковки и развертывания наших приложений, которые соответствуют модели, основанной на архитектуре микросервисов и передовых практических методах развертывания приложений, управления версиями и управления жизненным циклом. FIS — это опция, поддерживаемая Red Hat для Fuse в OpenShift.

fabric8-логотип

Два основных способа развертывания Fuse Integration Services — это подход Karaf, основанный на OSGI, который традиционно использовался Fuse, а также более простой вариант загрузчика с плоским классом, который загружает Camel из простой старой Java-магистрали. Оба варианта упакованы и отправлены в виде контейнеров Docker. Оба варианта хороши в зависимости от того, что вы делаете, поэтому давайте посмотрим.

Ботинок верблюда

Camel Boot — это опция начальной загрузки JVM, которая позволяет нам упаковать наше приложение, используя тот же путь к классам, который используется в нашем проекте maven, и загрузить наши интеграции Apache Camel с помощью простого старого Java Main. Этот подход имеет ряд преимуществ, которые упрощают сборку, сборку, распространение и эксплуатацию наших микросервисов. Прежде всего, нам не нужно догадываться, что поведение нашего приложения основано на иерархиях или графиках сложных загрузчиков классов и включили ли мы правильные метаданные и зависимости, чтобы классы могли или не могли разрешать / конфликтовать / переопределять / динамически загружать / и т.д. , Мы можем упростить модель, просто используя один плоский загрузчик классов, чтобы упростить анализ приложений не только в Dev, но и на протяжении всего жизненного цикла приложения (например, в IST, UAT, PM, PROD и т. Д. И т. Д.).

верблюжья загрузка

Поскольку эта опция не предназначена для развертывания на каком-либо сервере приложений (сервере приложений Java EE, контейнере сервлетов, контейнере OSGI и т. Д.), Мы будем полагаться на то, что наше приложение предоставит «достаточно» функциональных возможностей, которые в противном случае вы ожидаете в сервер приложений — такие вещи, как HTTP, JMS, постоянство и т. д. Таким образом, вы можете встроить сервер Jetty или Undertow в наше приложение, чтобы получать службы HTTP для конечных точек REST или SOAP, а также встраивать JMS-клиенты, такие как библиотеки Spring-JMS и ActiveMQ, для обмена сообщениями. клиентов. Это также облегчает модульное тестирование нашего приложения, поскольку все эти зависимости включены в состав приложения и могут запускаться, останавливаться, повторно развертываться и т. Д. Независимо от сервера приложений.

Я бы предложил эту опцию Camel Boot для большинства случаев использования, когда вы разлагали и модульно настраивали свои приложения и вам нужно запускать, настраивать, масштабировать и рассуждать о них по отдельности. Тем не менее, существуют случаи, когда совместное размещение сервисов необходимо и до тех пор, пока путь к классу приложения не становится слишком сложным (то есть конфликтующие зависимости), Camel Boot должен быть хорошим вариантом. Если ваша микросервис усложняется из-за сплоченных, совмещенных сервисов, рассмотрите следующий вариант с Apache Karaf, который позволяет вам точно контролировать поведение загрузчика классов и изолировать модули и API в рамках одного процесса приложения / JVM.

«Неизменный» Apache Karaf

Fuse Integration Services также предлагает возможность развертывания на JVM на основе Apache Karaf, хотя модель немного отличается, потому что мы следуем модели Docker «неизменных» развертываний. Может быть довольно сложно рассуждать о состоянии JVM после горячего развертывания / повторного развертывания приложений в / из работающей JVM. Фактически, вы можете столкнуться с неприятными, трудно выявляемыми утечками JVM в результате этой «динамической» изменчивости JVM во время выполнения (особенно плохая идея в производстве). Модель, поддерживаемая FIS, — это «снимать старую и заменять ее» новой версией (и полагаться на то, что менеджер кластера организует ее для вас с помощью непрерывных обновлений или сине-зеленых развертываний и т. Д.)

Что это значит для Apache Karaf для FIS? Динамическая загрузка и выгрузка пакетов или изменение значений конфигурации во время выполнения для изменения состояния приложения не рекомендуется. Вместо этого мы поощряем предсказуемую последовательность запуска, понятные значения конфигурации и предварительно запеченные приложения в JVM. Если что-то должно измениться, то вы проходите через конвейер доставки приложений, чтобы изменить / собрать / протестировать / развернуть новую версию (в идеале через процесс CI / CD) так же, как и в случае с вышеуказанным параметром Camel-Boot. Таким образом, для Karaf для FIS ваше приложение и все его зависимости упаковываются, устанавливаются, разрешаются и встраиваются во время сборки в сборку Karaf, которая представляет собой пользовательский дистрибутив Karaf, в который встроено ваше приложение. Больше не нужно гадать о метаданных OSGI и разрешении классов во время развертывания; все это заранее рассчитано и быстро завершается неудачно во время сборки, если что-то не разрешается. Вы можете быть намного увереннее в своем приложении OSGI, если все будет успешно.

Хотя вариант загрузки с верблюда рекомендуется для большинства случаев использования, для существующих развертываний JBoss Fuse за пределами OpenShift / Kubernetes / Docker этот вариант на основе Karaf может быть вашим лучшим вариантом для переноса существующих рабочих нагрузок Fuse в эту модель (и использовать преимущества CI / CD обнаружение сервисов, управление кластерами и т. д. — уже встроено в OpenShift). Кроме того, если вы совместно размещаете множество сервисов, которые в конечном итоге загрязняют единый путь к классу, опция неизменяемого Karaf отлично подходит для обеспечения более детальной изоляции пути к классам и моделирования API / модульности.

Развертывание в Кубернетес / OpenShift

Для развертывания в OpenShift нам нужно сделать следующее:

  • Упакуйте нашу JVM (или верблюжий сапог или неизменный караф)
  • Сборка наших контейнеров Docker
  • Создайте и примените нашу конфигурацию OpenShift / Kubernetes

Упаковка приложений Camel Boot

Чтобы упаковать наши приложения Camel Boot, все, что нам нужно, это включить плагин maven <build/> который обрабатывает все это за нас.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
<plugin>
  <groupId>io.fabric8</groupId>
  <artifactId>hawt-app-maven-plugin</artifactId>
  <version>${fabric8.version}</version>
  <executions>
    <execution>
      <id>hawt-app</id>
      <goals>
        <goal>build</goal>
      </goals>
      <configuration>
        <javaMainClass>org.apache.camel.spring.Main</javaMainClass>
      </configuration>
    </execution>
  </executions>
</plugin>

В приведенной выше конфигурации для hawt-app-maven-plugin мы можем видеть, что мы просто указываем простой старый Java Main, который загрузит верблюд в контекст внедрения зависимостей или по вашему выбору (Spring, CDI и т. Д.) И обнаружит все ваши Spring / CDI ресурсы, а также открыть и запустить ваши маршруты Camel. Вы можете использовать следующие типы файлов Main.java:

  • org.apache.camel.spring.Mainorg.apache.camel.spring.Main ваши контекстные файлы Spring (расположение по умолчанию META-INF / spring / *. xml
  • org.apache.camel.cdi.Main — загружает контейнер CDI и компоненты маршрутизации Camel
  • org.apache.camel.main.Main — контейнер для инъекций без зависимостей; реализация по умолчанию SimpleRegistry
  • org.apache.camel.spring.javaconfig.Main — конфигурация Spring с использованием конфигурации Java
  • org.apache.camel.guice.Main — Контейнер внедрения зависимостей Guice

Вероятно, стоит добавить exec-maven-plugin в ваш pom.xml чтобы вы могли поэкспериментировать и попробовать загрузиться через Java Main выше:

1
2
3
4
5
6
7
8
<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>exec-maven-plugin</artifactId>
  <version>1.4.0</version>
  <configuration>
    <mainClass>org.apache.camel.spring.Main</mainClass>
  </configuration>
</plugin>

Затем, если вы mvn exec:java вы получите то же поведение, что и приложение, упакованное с помощью hawt-app-maven-plugin который сохраняет порядок и поведение пути классов Maven для нашего автономного микросервиса Camel Boot.

Когда вы делаете сборку maven, вы должны увидеть, что ваше приложение упаковано с зависимостями Maven в файле zip / tar.gz. Если вы распакуете этот файл, есть файл bin/run.sh который можно использовать для загрузки вашего верблюжьего микросервиса.

Чтобы преобразовать это в образ Docker, добавьте следующий docker-maven-plugin в ваш pom.xml

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<plugin>
  <groupId>org.jolokia</groupId>
  <artifactId>docker-maven-plugin</artifactId>
  <version>${docker.maven.plugin.version}</version>
  <configuration>
    <images>
      <image>
        <name>our-company/app-name:1.0</name>
        <build>
          <from>jboss-fuse-6/fis-java-openshift:1.0</from>
          <assembly>
            <basedir>/deployments</basedir>
            <descriptorRef>hawt-app</descriptorRef>
          </assembly>
          <env>
            <JAVA_LIB_DIR>/deployments/lib</JAVA_LIB_DIR>
            <JAVA_MAIN_CLASS>org.apache.camel.spring.Main</JAVA_MAIN_CLASS>
          </env>
        </build>
      </image>
    </images>
  </configuration>
</plugin>

Для более подробных инструкций по настройке и запуску, пожалуйста, смотрите документацию Rider Auto OpenShift

Упаковка неизменяемых приложений Karaf

Если вы пользуетесь микросервисами на основе Karaf, мы пойдем по тому же пути, что и Camel Boot Мы karaf-maven-plugin наше приложение karaf-maven-plugin в неизменяемую сборку karaf-maven-plugin с помощью karaf-maven-plugin , добавив плагин в нашу сборку maven:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<plugin>
  <groupId>org.apache.karaf.tooling</groupId>
  <artifactId>karaf-maven-plugin</artifactId>
  <version>${karaf.plugin.version}</version>
  <extensions>true</extensions>
  <executions>
    <execution>
      <id>karaf-assembly</id>
      <goals>
        <goal>assembly</goal>
      </goals>
      <phase>install</phase>
    </execution>
    <execution>
      <id>karaf-archive</id>
      <goals>
        <goal>archive</goal>
      </goals>
      <phase>install</phase>
    </execution>
  </executions>
  <configuration>
    <karafVersion>v24</karafVersion>
    <javase>1.8</javase>
    <useReferenceUrls>true</useReferenceUrls>
    <!-- do not include build output directory -->
    <includeBuildOutputDirectory>false</includeBuildOutputDirectory>
    <!-- no startupFeatures -->
    <startupFeatures>
      <feature>karaf-framework</feature>
      <feature>shell</feature>
      <feature>jaas</feature>
      <feature>spring</feature>
      <feature>camel-spring</feature>
      <feature>camel-jaxb</feature>
      <feature>camel-cxf</feature>
      <feature>camel-bindy</feature>
      <feature>cxf-http-jetty</feature>
      <feature>activemq-client</feature>
      <feature>activemq-camel</feature>
    </startupFeatures>
    <startupBundles>
      <!--  this needs to be here for spring-dm to resolve properly!!-->
      <bundle>mvn:org.apache.karaf.bundle/org.apache.karaf.bundle.core/3.0.4</bundle>
      <bundle>mvn:io.fabric8.mq/mq-client/2.2.0.redhat-079</bundle>
      <bundle>mvn:io.fabric8/fabric8-utils/2.2.0.redhat-079</bundle>
      <bundle>mvn:${project.groupId}/${project.artifactId}/${project.version}</bundle>
    </startupBundles>
  </configuration>
</plugin>

Обратите внимание, что в приведенном выше примере создается полный дистрибутив Karaf с нашими микросервисными модулями / API и всеми зависимостями, встроенными в дистрибутив. В конфиге вы можете видеть, что мы можем точно контролировать, какие функции, пакеты, JRE и т. Д. Мы хотим предварительно запечь в дистрибутив.

Docker docker-maven-plugin также следует использовать для создания образа Docker для этого модуля. Снова, проверьте документацию Rider Auto OpenShift для полноценного, работающего примера.

Создать манифест компонента OpenShift / Kubernetes

На данный момент в FIS есть несколько опций для генерации файлов манифеста OpenShift / Kubernetes (json / yaml — хотя на данный момент поддерживается только опция JSON. В сообществе разработчиков более высокого уровня мы также поддерживаем опцию yaml). Для генерации контроллеров / модулей / служб репликации нам нужно добавить плагин fabric8-maven-plugin и несколько <properties/> maven <properties/> maven:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
<plugin>
  <groupId>io.fabric8</groupId>
  <artifactId>fabric8-maven-plugin</artifactId>
  <version>${fabric8.version}</version>
  <executions>
    <execution>
      <id>json</id>
      <phase>generate-resources</phase>
      <goals>
        <goal>json</goal>
      </goals>
    </execution>
    <execution>
      <id>attach</id>
      <phase>package</phase>
      <goals>
        <goal>attach</goal>
      </goals>
    </execution>
  </executions>
</plugin>
01
02
03
04
05
06
07
08
09
10
<fabric8.service.name>${project.artifactId}</fabric8.service.name>
        <fabric8.service.headless>true</fabric8.service.headless>
 
        <fabric8.metrics.scrape>true</fabric8.metrics.scrape>
        <fabric8.metrics.port>9779</fabric8.metrics.port>
        <docker.port.container.soap>8183</docker.port.container.soap>
 
        <fabric8.service.name>${project.artifactId}</fabric8.service.name>
        <fabric8.service.port>80</fabric8.service.port>
        <fabric8.service.containerPort>8183</fabric8.service.containerPort>

С помощью этих записей pom.xml мы можем выполнить mvn fabric8:json и сгенерировать файл kubernetes.json для target/classes/kubernetes.json .

Мы также можем сгенерировать более сложные объекты манифеста Kubernetes, такие как PersistentVolumes, Secrets, несколько сервисов и т. Д., Используя безопасный для типов DSL для расширения или генерации файла kubernetes.json. Посмотрите модуль rider-auto-file для некоторых примеров и объяснений этого.

Особенности, продемонстрированные в репо микросервисов Rider Auto

Пожалуйста, взгляните на проект Rider Auto, чтобы узнать больше об этих функциях:

  • Создание файла kubrenetes.json с помощью плагина fabric8 maven
  • Добавление PersistentVolumes в файл kubernetes.json с помощью безопасного для типов DSL
  • Создание приложений Camel Boot
  • Создание неизменных приложений Karaf
  • Откройте для себя JBoss AMQ в окружении Куберне
  • Сборка Docker изображений для Camel Boot и неизменного Карафа
  • Развертывание приложений в OpenShift
  • Как объединить несколько файлов kubernets.json в один файл kubernetes.json для развертывания «все в одном»
  • Подключение к локальным / удаленным установкам Docker Daemon / OpenShift
  • Предоставление сервисов SOAP и REST HTTP через сервисы Kubernetes
  • Используя Spring внутри Karaf
  • Интеграционное тестирование на Кубернетесе с матрицей8
Ссылка: Верховая езда на верблюдах в облаке С JBoss Fuse и OpenShift от нашего партнера по JCG Кристиана Поста в блоге