Развертывание приложения Micronaut, помещенного в контейнер с помощью Jib, в Google Kubernetes Engine.

1. Обзор

О Микронавт

Micronaut — это современная полнофункциональная платформа на базе JVM для создания модульных, легко тестируемых микросервисных и бессерверных приложений. Micronaut стремится обеспечить максимальное время запуска, высокую пропускную способность и минимальное использование памяти. Разработчики могут разрабатывать с помощью Micronaut на Java, Groovy или Kotlin.

Микронавт обеспечивает:

  • Быстрое время запуска и низкое потребление памяти . Платформы IoC на основе отражения загружают и кэшируют данные отражения для каждого отдельного поля, метода и конструктора в вашем коде, тогда как с Micronaut время запуска вашего приложения и потребление памяти не привязаны к размеру вашего кода. кодовая база.
  • Декларативный, реактивный HTTP-клиент времени компиляции . Декларативно создавайте реактивные HTTP-клиенты, которые реализуются во время компиляции, что снижает потребление памяти.
  • Неблокирующий HTTP-сервер, построенный на Netty . Благодаря плавному обучению HTTP-сервер Micronaut максимально упрощает предоставление API-интерфейсов, которые могут использоваться HTTP-клиентами.
  • Быстрое и простое тестирование . Легко запускайте серверы и клиенты в модульных тестах и ​​запускайте их мгновенно.
  • Эффективное внедрение зависимостей во время компиляции и АОП . Micronaut предоставляет простой API-интерфейс аспектно-ориентированного программирования во время компиляции, который не использует отражение.
  • Создавайте полностью реактивные и неблокирующие приложения — Micronaut поддерживает любую платформу, реализующую Reactive Streams, включая RxJava и Reactor.

Для получения дополнительной информации посетите веб-сайт Micronaut .

О Кубернетесе

Kubernetes — это проект с открытым исходным кодом, который может работать в самых разных средах: от ноутбуков до многоузловых кластеров высокой доступности, от публичных облаков до локальных развертываний, от виртуальных машин до «голого железа».

В ходе этой лабораторной работы вы развернете простой микросервис Micronaut на базе Groovy в Kubernetes , работающий на Kubernetes Engine .

Цель этой лаборатории кода — запустить микросервис как реплицируемый сервис, работающий в Kubernetes. Вы берете код, разработанный на своем компьютере, превращаете его в образ контейнера Docker, а затем запускаете этот образ в Kubernetes Engine.

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

Схема Codelab Kubernetes 1 (2).png

Для целей этой лаборатории использование управляемой среды, такой как Kubernetes Engine (размещенная в Google версия Kubernetes, работающая на Compute Engine), позволяет вам больше сосредоточиться на работе с Kubernetes, а не на настройке базовой инфраструктуры.

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

О Джибе

Jib — это инструмент с открытым исходным кодом, который позволяет создавать образы Docker и OCI для ваших приложений Java. Он доступен в виде плагинов для Maven и Gradle, а также в виде библиотеки Java.

Джиб стремится быть:

  • Быстро — быстро развертывайте изменения. Jib разделяет ваше приложение на несколько уровней, отделяя зависимости от классов. Теперь вам не нужно ждать, пока Docker пересоберет все ваше Java-приложение — просто разверните измененные уровни.
  • Воспроизводимость — при пересборке образа контейнера с тем же содержимым всегда создается один и тот же образ. Никогда больше не запускайте ненужное обновление.
  • Daemonless — уменьшите зависимости CLI. Создайте свой образ Docker из Maven или Gradle и отправьте его в любой реестр по вашему выбору. Больше не нужно писать Dockerfiles и вызывать docker build/push.

Более подробную информацию о Jib вы можете найти на странице проекта Github.

Об этом уроке

В этом руководстве используется пример кода из инструмента Jib для создания контейнеров для приложений Java.

Пример представляет собой простой сервис hello world , использующий платформу Micronaut и язык программирования Apache Groovy .

Что вы узнаете

  • Как упаковать простое Java-приложение в контейнер Docker с помощью Jib
  • Как создать кластер Kubernetes на Kubernetes Engine.
  • Как развернуть службу Micronaut в Kubernetes на Kubernetes Engine
  • Как масштабировать свой сервис и выполнить обновление.
  • Как получить доступ к графической панели управления Kubernetes.

Что вам понадобится

  • Проект облачной платформы Google
  • Браузер, например Chrome или Firefox.
  • Знакомство со стандартными текстовыми редакторами Linux, такими как Vim, EMAC или Nano.

Как вы будете использовать этот урок?

Прочтите только до конца Прочитайте его и выполните упражнения.

Как бы вы оценили свой опыт создания веб-приложений HTML/CSS?

Новичок Средний Опытный

Как бы вы оценили свой опыт использования сервисов Google Cloud Platform?

Новичок Средний Опытный

2. Настройка и требования

Самостоятельная настройка среды

  1. Войдите в Cloud Console и создайте новый проект или повторно используйте существующий. (Если у вас еще нет учетной записи Gmail или G Suite, вам необходимо ее создать .)

dMbN6g9RawQj_VXCSYpdYncY-DbaRzr2GbnwoV7jFf1u3avxJtmGPmKpMYgiaMH-qu80a_NJ9p2IIXFppYk8x3wyymZXavjglNLJJhuXieCem56H30hwXtd8PvXGpXJO9gEUDu3cZw

ci9Oe6PgnbNuSYlMyvbXF1JdQyiHoEgnhl4PlV_MFagm2ppzhueRkqX4eLjJllZco_2zCp0V0bpTupUSKji9KkQyWqj11pqit1K1faS1V6aFxLGQdkuzGp4rsQTan7F01iePL5DtqQ

8-tA_Lheyo8SscAVKrGii2coplQp2_D1Iosb2ViABY0UUO1A8cimXUu6Wf1R9zJIRExL5OB2j946aIiFtyKTzxDcNnuznmR45vZ2HMoK3o67jxuoUJCAnqvEX6NgPGFjCVNgASc-lg

Запомните идентификатор проекта — уникальное имя для всех проектов Google Cloud (имя, указанное выше, уже занято и не подойдет вам, извините!). Позже в этой лаборатории он будет называться PROJECT_ID .

  1. Далее вам необходимо включить биллинг в Cloud Console, чтобы использовать ресурсы Google Cloud.

Прохождение этой лаборатории кода не должно стоить много, если вообще стоит. Обязательно следуйте всем инструкциям в разделе «Очистка», в которых рассказывается, как отключить ресурсы, чтобы вам не приходилось нести расходы, выходящие за рамки этого руководства. Новые пользователи Google Cloud имеют право на участие в программе бесплатной пробной версии стоимостью 300 долларов США .

3. Получите образец исходного кода Micronaut.

После запуска Cloud Shell вы можете использовать командную строку для клонирования исходного кода примера в домашнем каталоге и перейти в каталог, содержащий наш пример сервиса:

$ git clone https://github.com/GoogleContainerTools/jib.git
$ cd jib/examples/micronaut/

4. Беглый взгляд на код

Наш простой сервис Micronaut состоит из контроллера, который выводит печально известное сообщение Hello World:

@Controller("/hello")
class HelloController {
    @Get("/")
    String index() {
        "Hello World"
    }
}

Контроллер HelloController отвечает на запросы по пути /hello , а метод index() принимает запросы HTTP GET.

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

class HelloControllerSpec extends Specification {
    @Shared
    @AutoCleanup
    EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer)

    @Shared
    @AutoCleanup
    RxHttpClient client = embeddedServer.applicationContext.createBean(RxHttpClient, embeddedServer.getURL()) 

    void "test hello world response"() {
        when:
        HttpRequest request = HttpRequest.GET('/hello')
        String rsp  = client.toBlocking().retrieve(request)

        then:
        rsp == "Hello World"
    }
}

Это не просто модульный тест, этот тест фактически запускает тот же стек серверов Micronaut (на основе платформы Netty ), который используется в рабочей среде. Таким образом, поведение вашего кода в продукте будет таким же, как и в ваших тестах.

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

./gradlew test

5. Запустите приложение локально.

Вы можете запустить службу Micronaut в обычном режиме с помощью следующей команды Gradle:

$ ./gradlew run

После запуска приложения вы можете открыть дополнительный экземпляр Cloud Shell благодаря маленькому значку +, а затем проверить с помощью Curl, что вы получили ожидаемый результат:

$ curl localhost:8080/hello

И вы должны увидеть простое сообщение «Hello World».

6. Упакуйте приложение как контейнер Docker с помощью Jib.

Затем подготовьте свое приложение для работы в Kubernetes. Для этой цели мы воспользуемся преимуществами Jib, который сделает всю тяжелую работу за нас, поскольку нам не придется самим трогать Dockerfile !

Давайте запустим команду для сборки нашего контейнера:

$ ./gradlew jibDockerBuild

Вот результат, который вы должны увидеть:

Tagging image with generated image reference micronaut-jib:0.1. If you'd like to specify a different tag, you can set the jib.to.image parameter in your build.gradle, or use the --im
age=<MY IMAGE> commandline flag.

Containerizing application to Docker daemon as micronaut-jib:0.1...
warning: Base image 'gcr.io/distroless/java' does not use a specific image digest - build may not be reproducible
Getting base image gcr.io/distroless/java...
Building dependencies layer...
Building resources layer...
Building classes layer...
Finalizing...

Container entrypoint set to [java, -cp, /app/resources:/app/classes:/app/libs/*, example.micronaut.Application]
Loading to Docker daemon...

Built image to Docker daemon as micronaut-jib:0.1

Теперь, когда наш образ создан, давайте проверим, можем ли мы увидеть наше дружелюбное приветственное сообщение, запустив наш образ Docker на первой вкладке Cloud Shell:

$ docker run -it -p 8080:8080 micronaut-jib:0.1
16:57:20.255 [main] INFO  i.m.context.env.DefaultEnvironment - Established active environments: [cloud, gcp]
16:57:23.203 [main] INFO  io.micronaut.runtime.Micronaut - Startup completed in 2926ms. Server Running: http://97b7d76ccf3f:8080

Наша служба запущена, поэтому теперь мы можем запустить команду Curl на второй вкладке Cloud Shell, чтобы проверить, работает ли она должным образом:

$ curl localhost:8080/hello
Hello World

Вы можете остановить контейнер, нажав Ctrl+C в Cloud Shell.

7. Добавление нашего контейнерного сервиса в реестр.

Теперь, когда образ работает так, как задумано, вы можете отправить его в реестр контейнеров Google — частный репозиторий для ваших образов Docker, доступный из каждого проекта Google Cloud (а также из-за пределов Google Cloud Platform).

Прежде чем отправлять данные в реестр, давайте убедимся, что реестр контейнеров включен для нашего проекта, перейдя в Инструменты > Реестр контейнеров . Если он не включен, вы должны увидеть следующее диалоговое окно, затем нажмите « Включить API реестра контейнеров », чтобы включить его:

ac812e6260ac7dfb.png

Когда реестр будет готов, чтобы отправить образ в реестр, запустите следующие команды:

$ gcloud auth configure-docker
$ docker tag micronaut-jib:0.1 \
         gcr.io/$GOOGLE_CLOUD_PROJECT/micronaut-jib:0.1
$ docker push gcr.io/$GOOGLE_CLOUD_PROJECT/micronaut-jib:0.1

Приведенные выше команды позволяют gcloud SDK настроить и разрешить Docker отправлять изображения в ваш экземпляр реестра контейнеров, помечать образ так, чтобы он указывал на его местоположение в реестре, а затем отправлять его в реестр.

Если все пойдет хорошо, через некоторое время вы сможете увидеть образ контейнера, указанный в консоли: Инструменты > Реестр контейнера . На этом этапе у вас есть доступный образ Docker для всего проекта, к которому Kubernetes может получить доступ и который можно оркестровать, как вы увидите через несколько минут.

12224c4e42183b4e.png

8. Создайте свой кластер

Хорошо, теперь вы готовы создать кластер Kubernetes Engine, но перед этим перейдите в раздел Google Kubernetes Engine веб-консоли и дождитесь инициализации системы (это займет всего несколько секунд).

20c0587c0108b8ba.png

Кластер состоит из главного API-сервера Kubernetes, управляемого Google, и набора рабочих узлов. Рабочие узлы — это виртуальные машины Compute Engine. Давайте воспользуемся CLI gcloud из вашего сеанса CloudShell, чтобы создать кластер с двумя узлами n1-standard-1 (это займет несколько минут):

$ gcloud container clusters create hello-cluster \
  --num-nodes 2 \
  --machine-type n1-standard-1 \
  --zone us-central1-c

В конце вы должны увидеть созданный кластер.

Creating cluster hello-cluster in us-central1-c...done.
Created [https://container.googleapis.com/v1/projects/mn-gke-test/zones/us-central1-c/clusters/hello-cluster].
To inspect the contents of your cluster, go to: https://console.cloud.google.com/kubernetes/workload_/gcloud/us-central1-c/hello-cluster?project=mn-gke-test
kubeconfig entry generated for hello-cluster.
NAME           LOCATION       MASTER_VERSION  MASTER_IP       MACHINE_TYPE   NODE_VERSION  NUM_NODES  STATUS
hello-cluster  us-central1-c  1.9.7-gke.7     35.239.224.115  n1-standard-1  1.9.7-gke.7   2          RUNNING

Теперь у вас должен быть полнофункциональный кластер Kubernetes на базе Google Kubernetes Engine:

d9e1e314769753e7.png

Пришло время развернуть собственное контейнерное приложение в кластере Kubernetes! С этого момента вы будете использовать командную строку kubectl (уже настроенную в вашей среде Cloud Shell). Для остальной части этой лаборатории кода требуется, чтобы версия клиента и сервера Kubernetes была 1.2 или выше. kubectl version покажет вам текущую версию команды.

9. Разверните свое приложение в Kubernetes.

Развертывание Kubernetes позволяет создавать, управлять и масштабировать несколько экземпляров вашего приложения, используя только что созданный образ контейнера. Давайте создадим развертывание вашего приложения в Kubernetes с помощью команды kubectl create deployment :

$ kubectl create deployment hello-micronaut \
  --image=gcr.io/$GOOGLE_CLOUD_PROJECT/micronaut-jib:0.1

Чтобы просмотреть только что созданное развертывание, просто запустите:

$ kubectl get deployments
NAME              DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
hello-micronaut   1         1         1            1           5m

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

$ kubectl get pods
NAME                               READY     STATUS    RESTARTS   AGE
hello-micronaut-5647fb98c5-lh5h7   1/1       Running   0          5m

На этом этапе ваш контейнер должен работать под контролем Kubernetes, но вам все равно придется сделать его доступным для внешнего мира.

10. Разрешить внешний трафик

По умолчанию модуль доступен только по внутреннему IP-адресу внутри кластера. Чтобы сделать контейнер hello-micronaut доступным за пределами виртуальной сети Kubernetes, вам необходимо представить модуль как службу Kubernetes.

Из Cloud Shell вы можете предоставить модуль общедоступному Интернету с помощью команды kubectl expose в сочетании с флагом --type=LoadBalancer . Этот флаг необходим для создания IP-адреса, доступного извне:

$ kubectl expose deployment hello-micronaut --type=LoadBalancer --port=8080

Флаг, используемый в этой команде, указывает, что вы будете использовать балансировщик нагрузки, предоставляемый базовой инфраструктурой (в данном случае балансировщик нагрузки Compute Engine ). Обратите внимание, что вы предоставляете доступ к развертыванию, а не к поду напрямую. Это приведет к тому, что результирующая служба будет балансировать трафик между всеми модулями, управляемыми развертыванием (в данном случае только 1 модуль, но вы добавите дополнительные реплики позже).

Мастер Kubernetes создает балансировщик нагрузки и связанные с ним правила переадресации Compute Engine, целевые пулы и правила брандмауэра, чтобы сделать сервис полностью доступным за пределами Google Cloud Platform.

Чтобы найти общедоступный IP-адрес службы, просто запросите kubectl , чтобы получить список всех служб кластера:

$ kubectl get services
NAME              TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)          AGE
hello-micronaut   LoadBalancer   10.39.243.251   aaa.bbb.ccc.ddd 8080:30354/TCP   1m
kubernetes        ClusterIP      10.39.240.1     <none>          443/TCP          31m

Обратите внимание, что для вашей службы указано 2 IP-адреса, оба обслуживают порт 8080 . Одним из них является внутренний IP-адрес, который виден только внутри вашей облачной виртуальной сети; другой — внешний IP-адрес с балансировкой нагрузки. В этом примере внешний IP-адрес — aaa.bbb.ccc.ddd .

Теперь вы сможете получить доступ к службе, указав в браузере этот адрес: http://<EXTERNAL_IP> :8080 /hello

11. Расширьте свой сервис

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

$ kubectl scale deployment hello-micronaut --replicas=3
deployment.extensions "hello-micronaut" scaled

$ kubectl get deployment
NAME              DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
hello-micronaut   3         3         3            3           16m

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

12. Обновите свой сервис

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

Во-первых, давайте изменим приложение. Откройте редактор кода из Cloud Shell.

5aee8f3d1e003571.png

Перейдите к /jib/examples/micronaut/src/main/groovy/example/micronaut/HelloController.groovy и обновите значение ответа:

@Controller("/hello")
class HelloController {
    @Get("/")
    String index() {
        "Hello Kubernetes World"
    }
}

В /jib/examples/micronaut/build.gradle мы обновим версию нашего образа с 0,1 до 0,2, обновив эту строку:

version '0.2'

Затем пересоберите и упакуйте приложение с последними изменениями:

$ ./gradlew jibDockerBuild

Пометьте и поместите образ в реестр образов контейнера:

$ docker tag micronaut-jib:0.2 \
         gcr.io/$GOOGLE_CLOUD_PROJECT/micronaut-jib:0.2
$ docker push gcr.io/$GOOGLE_CLOUD_PROJECT/micronaut-jib:0.2

Теперь вы готовы к тому, что Kubernetes сможет плавно обновить ваш контроллер репликации до новой версии приложения. Чтобы изменить метку образа для работающего контейнера, вам необходимо отредактировать существующее hello-micronaut deployment и изменить образ с gcr.io/PROJECT_ID/micronaut-jib:0.1 на gcr.io/PROJECT_ID/micronaut-jib:0.2 .

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

$ kubectl set image deployment/hello-micronaut \
          micronaut-jib=gcr.io/$GOOGLE_CLOUD_PROJECT/micronaut-jib:0.2

deployment.apps "hello-micronaut" image updated

Проверьте http://EXTERNAL_IP:8080 еще раз, чтобы убедиться, что он возвращает новый ответ.

13. Откат назад

Упс — вы ошиблись с новой версией приложения? Возможно, новая версия содержала ошибку и вам необходимо быстро выполнить откат. С Kubernetes вы можете легко вернуться к предыдущему состоянию. Давайте откатим приложение, выполнив:

$ kubectl rollout undo deployment/hello-micronaut

Если вы посмотрите на выходные данные службы, мы вернемся к нашему первоначальному сообщению «Hello World».

14. Резюме

На этом этапе вы настроите простую службу приветствия World Micronaut на базе Apache Groovy, запустите ее непосредственно из Cloud Shell, упакуете как контейнер с помощью Jib и развернете в Google Kubernetes Engine.

15. Поздравляем!

Вы узнали, как создать и развернуть новый веб-микросервис Apache Groovy/Micronaut в Kubernetes в Google Kubernetes Engine.

Узнать больше

Лицензия

Эта работа распространяется под лицензией Creative Commons Attribution 2.0 Generic License.