Привет, Хабр! Сегодня мы разберёмся, как добавлять кастомные плагины в Gravitee.io
Gravitee.io — open source продукт-шлюз с витриной API. Эта статья рассчитана на тех, кто уже знаком с системой. Общая информация о продукте хорошо описана в статье: Что такое системы API Management.
Большинство кейсов по работе с запросами можно сделать, используя уже имеющиеся плагины, но при желании можно писать собственные. Если в этом деле преисполниться, то приходишь к тому, что легче написать собственный плагин, чем разбираться с уже имеющимися. Иногда использование встроенных плагинов весьма сложное искусство, но если вы наткнулись на эту статью, то уже знаете это.
Также написание собственных плагинов добавляет кучу возможностей при работе с Gravitee
О чём?
В статье мы не будем рассматривать, как писать собственные плагины, будем полагаться на то, что вы учитесь это делать и достигли определенных успехов, а теперь хотите их подключить, протестировать и использовать. Бонусом мы научимся логировать в Graylog.
Приступим
Свои манипуляции я буду производить на последней версии Gravitee на момент публикации (3.20.10), но всё описанное ниже справедливо и для прошлых версий.
Для начала возьмём docker-compose.yml из официального источника и начнём вносить изменения.
Установим необходимую версию Gravitee
В раздел volumes для management_api пробросим папку для кастомных плагинов:
— ./apim-management-api/plugins:/opt/graviteeio-management-api/plugins-ext
Здесь мы задали путь папки с плагинами в рамках нашей системы, а также в рамках контейнера
В раздел environment для management_api добавим пути до наших плагинов:
— gravitee_plugins_path_0=/opt/graviteeio-management-api/plugins
— gravitee_plugins_path_1=/opt/graviteeio-management-api/plugins-ext
Аналогично в раздел volumes для gateway пробросим папку для кастомных плагинов:
— ./apim-gateway/plugins:/opt/graviteeio-gateway/plugins-ext
Аналогично в раздел environment для gateway добавим пути до наших плагинов:
— gravitee_plugins_path_0=/opt/graviteeio-gateway/plugins
— gravitee_plugins_path_1=/opt/graviteeio-gateway/plugins-ext
Готовый файл docker-compose.yml приведён ниже:
docker-compose.yml
version: '3.5' networks: frontend: name: frontend storage: name: storage volumes: data-elasticsearch: data-mongo: services: mongodb: image: mongo:3.6 restart: always ports: - "27017:27017" volumes: - data-mongo:/data/db - ./logs/apim-mongodb:/var/log/mongodb networks: - storage elasticsearch: image: docker.elastic.co/elasticsearch/elasticsearch:7.7.0 container_name: gio_apim_elasticsearch restart: always volumes: - data-elasticsearch:/usr/share/elasticsearch/data environment: - http.host=0.0.0.0 - transport.host=0.0.0.0 - xpack.security.enabled=false - xpack.monitoring.enabled=false - cluster.name=elasticsearch - bootstrap.memory_lock=true - discovery.type=single-node - "ES_JAVA_OPTS=-Xms512m -Xmx512m" ulimits: memlock: soft: -1 hard: -1 nofile: 65536 networks: - storage gateway: image: graviteeio/apim-gateway:3.20.10 container_name: gio_apim_gateway restart: always ports: - "8082:8082" depends_on: - mongodb - elasticsearch volumes: - ./logs/apim-gateway:/opt/graviteeio-gateway/logs - ./apim-gateway/plugins:/opt/graviteeio-gateway/plugins-ext environment: - gravitee_management_mongodb_uri=mongodb://mongodb:27017/gravitee?serverSelectionTimeoutMS=5000&connectTimeoutMS=5000&socketTimeoutMS=5000 - gravitee_ratelimit_mongodb_uri=mongodb://mongodb:27017/gravitee?serverSelectionTimeoutMS=5000&connectTimeoutMS=5000&socketTimeoutMS=5000 - gravitee_reporters_elasticsearch_endpoints_0=http://elasticsearch:9200 - gravitee_plugins_path_0=/opt/graviteeio-gateway/plugins - gravitee_plugins_path_1=/opt/graviteeio-gateway/plugins-ext networks: - storage - frontend management_api: image: graviteeio/apim-management-api:3.20.10 container_name: gio_apim_management_api restart: always ports: - "8083:8083" links: - mongodb - elasticsearch depends_on: - mongodb - elasticsearch volumes: - ./logs/apim-management-api:/opt/graviteeio-management-api/logs - ./apim-management-api/plugins:/opt/graviteeio-management-api/plugins-ext environment: - gravitee_management_mongodb_uri=mongodb://mongodb:27017/gravitee?serverSelectionTimeoutMS=5000&connectTimeoutMS=5000&socketTimeoutMS=5000 - gravitee_analytics_elasticsearch_endpoints_0=http://elasticsearch:9200 - gravitee_plugins_path_0=/opt/graviteeio-management-api/plugins - gravitee_plugins_path_1=/opt/graviteeio-management-api/plugins-ext networks: - storage - frontend management_ui: image: graviteeio/apim-management-ui:3.20.10 container_name: gio_apim_management_ui restart: always ports: - "8084:8080" depends_on: - management_api environment: - MGMT_API_URL=http://localhost:8083/management/organizations/DEFAULT/environments/DEFAULT/ volumes: - ./logs/apim-management-ui:/var/log/nginx networks: - frontend portal_ui: image: graviteeio/apim-portal-ui:3.20.10 container_name: gio_apim_portal_ui restart: always ports: - "8085:8080" depends_on: - management_api environment: - PORTAL_API_URL=http://localhost:8083/portal/environments/DEFAULT volumes: - ./logs/apim-portal-ui:/var/log/nginx networks: - frontend
Следующим шагом мы поднимаем Gravitee, используя docker-compose up -d, либо в ручную создаём пути для плагинов в каталоге с нашим docker-compose.yml файлом.
Путь для gateway: /apim-gateway/plugins
Путь для managment: /apim-management-api/plugins
Добавление плагина
После создания необходимых путей нам необходимо собрать наш плагин. Перейти в папку target и взять zip архив, полученный при сборке. Плагин на основе которого я работал будет доступен на GitHub
Теперь мы помещаем наш плагин в оба созданных каталога и запускаем/перезапускаем Gravitee. Важное уточнение: после каждого обновления\добавления плагина необходимо будет перезагрузить Gravitee либо отдельно его модули gateway и managment-api
После запуска нам необходимо создать API, перейти на вкладку Design и в правом списке найти наш плагин. Как это выглядит в моём случае:
Категория плагина зависит от того, в какую категорию вы его поместите с помощью plugin.properties
Теперь ваш плагин готов к использованию! Можно приступить к конфигурированию. Не забывайте делать «deploy your api» после каждого изменения конфигурации плагина.
Бонус
Логирование в Graylog нельзя настроить отдельно для какого-то определённого плагина, но можно для отдельного компонента например managment, gateway и другие.
В каждом компоненте присутствует директория для конфигураций, в которой находятся файл logback.xml, который мы и будем рассматривать, а также gravitee.yml (важный конфигурационный файл) и некоторые другие файлы в зависимости от модуля, который мы не будем рассматривать.
Изначально файл logback.xml выглядит вот так:
logback.xml
<!-- ~ Copyright (c) 2015-2016, The Gravitee team (http://www.gravitee.io) ~ ~ Licensed under the Apache License, Version 2.0 (the "License"); ~ you may not use this file except in compliance with the License. ~ You may obtain a copy of the License at ~ ~ http://www.apache.org/licenses/LICENSE-2.0 ~ ~ Unless required by applicable law or agreed to in writing, software ~ distributed under the License is distributed on an "AS IS" BASIS, ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ~ See the License for the specific language governing permissions and ~ limitations under the License. --> <configuration> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <!-- encoders are assigned the type ch.qos.logback.classic.encoder.PatternLayoutEncoder by default --> <encoder> <pattern>%d{HH:mm:ss.SSS} [%thread] [%X{api}] %-5level %logger{36} - %msg%n</pattern> </encoder> </appender> <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${gravitee.home}/logs/gravitee.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- daily rollover --> <fileNamePattern>${gravitee.home}/logs/gravitee_%d{yyyy-MM-dd}.log</fileNamePattern> <!-- keep 30 days' worth of history --> <maxHistory>30</maxHistory> </rollingPolicy> <encoder> <pattern>%d{HH:mm:ss.SSS} [%thread] [%X{api}] %-5level %logger{36} - %msg%n</pattern> </encoder> </appender> <appender name="async-file" class="ch.qos.logback.classic.AsyncAppender"> <appender-ref ref="FILE" /> </appender> <appender name="async-console" class="ch.qos.logback.classic.AsyncAppender"> <appender-ref ref="STDOUT" /> </appender> <logger name="io.gravitee" level="INFO" /> <logger name="com.graviteesource" level="INFO" /> <logger name="org.reflections" level="WARN" /> <logger name="org.springframework" level="WARN" /> <logger name="org.eclipse.jetty" level="WARN" /> <!-- Strictly speaking, the level attribute is not necessary since --> <!-- the level of the root level is set to DEBUG by default. --> <root level="WARN"> <appender-ref ref="async-console" /> <appender-ref ref="async-file" /> </root> </configuration>
Нам необходимо добавить конфигурации в зависимости от того, каким образом мы будем логировать в Graylog. Например, в случае с UDP мы допишем:
<appender name="GELF" class="biz.paluch.logging.gelf.logback.GelfLogbackAppender"> <host>udp:host</host> <port>port</port> <facility>НАЗВАНИЕ КОМПОНЕНТА</facility> <extractStackTrace>true</extractStackTrace> <filterStackTrace>true</filterStackTrace> <includeFullMdc>true</includeFullMdc> </appender> <logger name="io.gravitee.rest.api.service.impl.upgrade" level="INFO"> <appender-ref ref="FILE-UPGRADERS"/> </logger> <logger name="io.gravitee" level="INFO"/> <logger name="org.eclipse.jetty" level="INFO"/> <logger name="org.reflections" level="WARN" /> <logger name="org.springframework" level="WARN" /> <logger name="org.eclipse.jetty" level="WARN" /> <!-- Strictly speaking, the level attribute is not necessary since --> <!-- the level of the root level is set to DEBUG by default. --> <root level="WARN"> <appender-ref ref="GELF"/> <appender-ref ref="async-console" /> <appender-ref ref="async-file" /> </root>
Дополненный logback.xml
<!-- ~ Copyright (c) 2015-2016, The Gravitee team (http://www.gravitee.io) ~ ~ Licensed under the Apache License, Version 2.0 (the "License"); ~ you may not use this file except in compliance with the License. ~ You may obtain a copy of the License at ~ ~ http://www.apache.org/licenses/LICENSE-2.0 ~ ~ Unless required by applicable law or agreed to in writing, software ~ distributed under the License is distributed on an "AS IS" BASIS, ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ~ See the License for the specific language governing permissions and ~ limitations under the License. --> <configuration> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <!-- encoders are assigned the type ch.qos.logback.classic.encoder.PatternLayoutEncoder by default --> <encoder> <pattern>%d{HH:mm:ss.SSS} [%thread] [%X{api}] %-5level %logger{36} - %msg%n</pattern> </encoder> </appender> <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${gravitee.home}/logs/gravitee.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- daily rollover --> <fileNamePattern>${gravitee.home}/logs/gravitee_%d{yyyy-MM-dd}.log</fileNamePattern> <!-- keep 30 days' worth of history --> <maxHistory>30</maxHistory> </rollingPolicy> <encoder> <pattern>%d{HH:mm:ss.SSS} [%thread] [%X{api}] %-5level %logger{36} - %msg%n</pattern> </encoder> </appender> <appender name="async-file" class="ch.qos.logback.classic.AsyncAppender"> <appender-ref ref="FILE" /> </appender> <appender name="async-console" class="ch.qos.logback.classic.AsyncAppender"> <appender-ref ref="STDOUT" /> </appender> <appender name="GELF" class="biz.paluch.logging.gelf.logback.GelfLogbackAppender"> <host>udp:host</host> <port>port</port> <facility>НАЗВАНИЕ КОМПОНЕНТА</facility> <extractStackTrace>true</extractStackTrace> <filterStackTrace>true</filterStackTrace> <includeFullMdc>true</includeFullMdc> </appender> <logger name="io.gravitee.rest.api.service.impl.upgrade" level="INFO"> <appender-ref ref="FILE-UPGRADERS"/> </logger> <logger name="io.gravitee" level="INFO"/> <logger name="org.eclipse.jetty" level="INFO"/> <logger name="org.reflections" level="WARN" /> <logger name="org.springframework" level="WARN" /> <logger name="org.eclipse.jetty" level="WARN" /> <!-- Strictly speaking, the level attribute is not necessary since --> <!-- the level of the root level is set to DEBUG by default. --> <root level="WARN"> <appender-ref ref="GELF"/> <appender-ref ref="async-console" /> <appender-ref ref="async-file" /> </root> </configuration>
Теперь осталось лишь дополнить docker-compose.yml , пробросив папку config внутрь контейнера. Например для managment-api это будет так:
- .\apim-management-api\config:/opt/apim-management-api/config
Данную конфигурацию можно применить для всех модулей Gravitee и все дружно будут писать в Graylog.
Следующим шагом будет «обогащение» нашего Gravitee библиотекой biz.paluch.logging.logstash-gelf. Для этого мы обратимся на maven-central, где получим jar библиотеки и поместим по пути /opt/название компонента/lib
(в рамках контейнера). Для этого мы вновь «пробросим» папку наружу, для отдельного или всех компонентов. Например для компонента gateway:
- .\apim-gateway\lib:/opt/graviteeio-gateway/lib
Осталось лишь сконфигурировать Graylog, что я оставлю на совести читателя
Заключение
В статье мы рассмотрели способ добавления кастомных плагинов в Gravitee.io, используя docker-compose.yml. Также бонусом научили наш Gravitee писать в Graylog. Исходный код плагина и docker-compose.yml (версия до бонуса) доступен на GitHub
ссылка на оригинал статьи https://habr.com/ru/articles/741034/
Добавить комментарий