Вибач, OpenShift, ми недостатньо цінували тебе і приймали як належне

Цей пост написано, оскільки у наших співробітників було досить багато розмов з клієнтами про розробку додатків на Kubernetes і про специфіку такої розробки на OpenShift.

Вибач, OpenShift, ми недостатньо цінували тебе і приймали як належне

Починаємо ми зазвичай з тези, що Kubernetes – це просто Kubernetes, а OpenShift – це вже платформа Kubernetes, як Microsoft AKS або Amazon EKS. Кожна з цих платформ має свої плюси, орієнтовані на ту чи іншу цільову аудиторію. І після цього розмова вже перетікає порівняння сильних і слабких сторін конкретних платформ.

Загалом, ми думали написати цей пост з висновком типу «Слухайте, та все одно, де запускати код, на OpenShift або на AKS, на EKS, на якомусь кастомному Kubernetes, та на якому-небудь-Kubernetes (для стислості назвемо його КУК) – це реально просто і там, і там».

Потім ми планували взяти найпростіший "Hello World" і на його прикладі показати, що спільного і в чому відмінності між КУК і Red Hat OpenShift Container Platform (далі, OCP або просто OpenShift).

Однак під час написання цієї посади, ми зрозуміли, що так давно і сильно звикли використовувати OpenShift, що просто не усвідомлюємо, як він виріс і перетворився на приголомшливу платформу, яка стала набагато більшою, ніж просто Kubernetes-дистрибутив. Ми звикли сприймати зрілість і простоту OpenShift як належне, зважаючи на його пишність.

Загалом, настав час діяльного каяття, і зараз ми покроково порівняємо введення в дію свого Hello World на КУК і на OpenShift, і зробимо це максимально об'єктивно (ну хіба що виявляючи іноді особисте ставлення до предмета). Якщо вам цікава суто суб'єктивна думка з цього питання, то її можна прочитати тут (EN). А в цьому пості ми дотримуватимемося фактів і лише фактів.

Кластери

Отже, для нашого Hello World потрібні кластери. Відразу скажемо «ні» всяким публічним хмарам, щоб не платити за сервери, реєстри, мережі, передачу даних тощо. Відповідно, ми вибираємо простий одновузловий кластер на Мінікубе (для КУК) та Контейнери, готові до коду (Для кластера OpenShift). Обидва ці варіанти реально прості в установці, але вимагають чимало ресурсів на вашому ноуті.

Вибач, OpenShift, ми недостатньо цінували тебе і приймали як належне

Складання на КУК-і

Отже, поїхали.

Крок 1 – збираємо наш контейнерний образ

Почнемо я з того, що розгорнемо наш Hello World на minikube. Для цього потрібно:

  1. 1. Встановлений Docker.
  2. 2. Встановлений Git.
  3. 3. Встановлений Maven (загалом у цьому проекті використовується mvnw-бінарник, так що можна обійтися і без цього).
  4. 4. Власне, сам вихідник, тобто. клон репозиторію github.com/gcolman/quarkus-hello-world.git

Насамперед треба створити проект Quarkus. Не лякайтеся, якщо ніколи не працювали із сайтом Quarkus.io – це легко. Просто вибираєте компоненти, які хочете використовувати в проекті (RestEasy, Hibernate, Amazon SQS, Camel і т.д.), а далі Quarkus вже сам, без вашої участі, налаштовує архетип maven і викладає все на github. Тобто буквально один клік мишею – готове. За це ми любимо Quarkus.

Вибач, OpenShift, ми недостатньо цінували тебе і приймали як належне

Найпростіший спосіб зібрати наш Hello World в контейнерний образ - використовувати розширення quarkus-maven для Docker'а, які і пророблять всю необхідну роботу. З появою Quarkus це стало справді легко і просто: додаєте розширення container-image-docker та можете створювати образи командами maven.

./mvnw quarkus:add-extension -Dextensions=”container-image-docker”

І, нарешті, виконуємо збирання нашого образу, використовуючи Maven. В результаті наш вихідний код перетворюється на готовий контейнерний образ, який можна запускати в середовищі виконання контейнерів.

Вибач, OpenShift, ми недостатньо цінували тебе і приймали як належне

./mvnw -X clean package -Dquarkus.container-image.build=true

Ось, власне, і все тепер можна запускати контейнер командою docker run, підмапивши наш сервіс на порт 8080, щоб до нього можна було звертатися.

docker run -i — rm -p 8080:8080 gcolman/quarkus-hello-world

Вибач, OpenShift, ми недостатньо цінували тебе і приймали як належне

Після того, як контейнерний інстанс запустився, залишається лише перевірити командою curl, що наш сервіс працює:

Вибач, OpenShift, ми недостатньо цінували тебе і приймали як належне

Отже, все працює, і це було справді легко і просто.

Крок 2 – надсилаємо наш контейнер до репозиторій контейнерних образів

Поки створений нами образ зберігається локально, у нашому локальному контейнерному сховищі. Якщо ми хочемо використати цей образ у своєму середовищі КУК, його треба покласти в якийсь інший репозиторій. У Kubernetes немає таких функцій, тому ми будемо використовувати dockerhub. Тому що, по-перше, він безкоштовний, а по-друге, майже так роблять.

Це теж дуже просто, і потрібен тут лише обліковий запис на dockerhub.

Отже, ставимо dockerhub та відправляємо туди наш образ.

Вибач, OpenShift, ми недостатньо цінували тебе і приймали як належне

Крок 3 – запускаємо Kubernetes

Є багато способів зібрати конфігурацію kubernetes для запуску нашого «Hello World», але ми будемо використовувати найпростіший з них, такі ми люди…

Для початку запускаємо кластер minikube:

minikube start

Крок 4 – розгортаємо наш контейнерний образ

Тепер потрібно перетворити наш код і контейнерний образ у конфігурації kubernetes. Інакше кажучи, нам потрібен pod і deployment definition із зазначенням нашого контейнерного образу на dockerhub. Один із найпростіших способів це зробити – запустити команду create deployment, вказавши на наш образ:

Вибач, OpenShift, ми недостатньо цінували тебе і приймали як належне

kubectl create deployment hello-quarkus — image =gcolman/quarkus-hello-world:1.0.0-SNAPSHOT

Цією командною ми сказали нашій КУК створити deployment configuration, яка має містити специфікацію pod'а для нашого контейнерного образу. Ця команда також застосує цю конфігурацію до нашого кластера minikube, та створить deployment, котрий завантажить наш контейнерний образ та запустить pod у кластері.

Крок 5 – відкриваємо доступ до нашого сервісу

Тепер, коли у нас є розгорнутий контейнерний образ, настав час подумати, як налаштувати зовнішній доступ до цього Restful-сервісу, який, власне, і запрограмований у нашому коді.

Тут є багато методів. Наприклад, можна використовувати команду expose, щоб автоматично створювати відповідні Kubernetes-компоненти, такі як services та endpoints. Власне, так ми й зробимо, виконавши команду expose для нашого deployment-об'єкта:

kubectl expose deployment hello-quarkus — type=NodePort — port=8080

Давайте на хвилинку зупинимося на опції «type» команди expose.

Коли ми робимо expose та створюємо компоненти, необхідні для запуску нашого сервісу, нам, серед іншого, треба, щоб зовні можна було підключитися до служби hello-quarkus, яка сидить усередині нашої програмно-визначеної мережі. І параметр тип дозволяє нам створити та підключити такі речі, як балансувальники навантаження, щоб маршрутизувати трафік у цю мережу.

Наприклад, прописавши type=LoadBalancerМи автоматично ініціалізуємо балансувальник навантаження у публічній хмарі, щоб підключатися до нашого кластера Kubernetes. Це, звичайно, чудово, але треба розуміти, що така конфігурація буде жорстко прив'язана до конкретної публічної хмари і її буде складніше переносити між Kubernetes-інстансами в різних середовищах.

У нашому прикладі type=NodePort, тобто звернення до нашого сервісу йде за IP-адресою вузла та номером порту. Такий варіант дозволяє не використовувати публічні хмари, але вимагає ряд додаткових кроків. По-перше, потрібен свій балансувальник навантаження, тому ми розгорнемо у своєму кластері балансувальник навантаження NGINX.

Крок 6 – ставимо балансувальник навантаження

Minikube має ряд платформних функцій, що полегшують створення необхідних для доступу ззовні компонентів, на кшталт ingress-контролерів. Minikube йде в комплекті з ingress-контролером Nginx, і нам залишається лише включити його та налаштувати.

minikube addons enable ingress

Тепер ми лише однією командою створимо ingress-контролер Nginx, який працюватиме всередині нашого кластера minikube:

ingress-nginx-controller-69ccf5d9d8-j5gs9 1/1 Running 1 33m

Крок 7 – Налаштовуємо ingress

Тепер нам треба настроїти ingress-контролер Nginx, щоб він сприймав запити hello-quarkus.

Вибач, OpenShift, ми недостатньо цінували тебе і приймали як належне

Вибач, OpenShift, ми недостатньо цінували тебе і приймали як належне

І, зрештою, нам треба застосувати цю конфігурацію.

Вибач, OpenShift, ми недостатньо цінували тебе і приймали як належне

kubectl apply -f ingress.yml

Вибач, OpenShift, ми недостатньо цінували тебе і приймали як належне

Оскільки ми робимо все це на своєму комп'ютері, то просто додаємо IP-адресу своєї ноди у файл /etc/hosts, щоб надсилати http-запити до нашого minikube на балансувальник навантаження NGINX.

192.168.99.100 hello-quarkus.info

Все тепер наш сервіс minikube доступний зовні через ingress-контролер Nginx.

Вибач, OpenShift, ми недостатньо цінували тебе і приймали як належне

Ну що, це було легко, так? Чи не дуже?

Вибач, OpenShift, ми недостатньо цінували тебе і приймали як належне

Запуск на OpenShift (Code Ready Containers)

А тепер подивимося, як все це робиться на Red Hat OpenShift Container Platform (OCP).

Як у випадку з minikube, ми вибираємо схему з одновузловим кластером OpenShift у формі Code Ready Containers (CRC). Раніше це називалося minishift і базувалося на проекті OpenShift Origin, а тепер це CRC і побудовано на Red Hat'івській OpenShift Container Platform.

Тут ми, вибачте, не можемо стриматися і не сказати: OpenShift прекрасний!

Спочатку ми думали написати, що технологія на OpenShift нічим не відрізняється від розробки на Kubernetes. І насправді так воно і є. Але в процесі написання цієї посади ми згадали, скільки зайвих рухів доводиться робити, коли у вас немає OpenShift, і тому він, повторимося, чудовий. Ми любимо, коли все робиться легко, і те, як легко порівняно з minikube наш приклад розгортається і запускається на OpenShift, власне, і спонукало нас написати цей пост.

Давайте пробіжимося процесом і подивимося, що нам потрібно зробити.

Отже, у прикладі з minikube ми починали з Docker… Стоп нам більше не треба, щоб на машині був встановлений Docker.

Та локальний git нам не потрібний.
І Maven не потрібний.
І не треба руками створювати контейнерний образ.
І не треба шукати якийсь репозиторій контейнерних образів.
І не треба встановлювати ingress-контролер.
І конфігурувати ingress також не треба.

Ви зрозуміли, правда? Щоб розгорнути та запустити наш додаток на OpenShift, не потрібно нічого з перерахованого вище. А сам процес виглядає так.

Крок 1 - Запускаємо свій кластер OpenShift

Ми використовуємо Code Ready Containers від Red Hat, який є той самий Minikube, але тільки з повноцінним одновузловим кластером Openshift.

crc start

Крок 2 – Виконуємо складання та розгортання програми у кластері OpenShift

Саме на цьому кроці простота та зручність OpenShift проявляються у всій красі. Як і у всіх дистрибутивах Kubernetes, у нас є багато способів запустити додаток у кластері. І, як і у випадку КУК, ми спеціально обираємо найпростіший.

OpenShift завжди будувався як платформа для створення та запуску контейнерних програм. Складання контейнерів завжди було невід'ємною частиною цієї платформи, тому тут є купа додаткових Kubernetes-ресурсів для відповідних завдань.

Ми будемо використовувати OpenShift'івський процес Source 2 Image (S2I), який має кілька різних способів для того, щоб взяти наш вихідник (код або двійкові файли) і перетворити його на контейнерний образ, що запускається в кластері OpenShift.

Для цього нам знадобляться дві речі:

  • Наш вихідний код у репозиторії git
  • Builder-образ, на підставі якого виконуватиметься складання.

Існує безліч таких образів, що супроводжуються як силами Red Hat, так і на рівні спільноти, і ми скористаємося чином OpenJDK, ну оскільки я ж збираю Java-додаток.

Запустити S2I-складання можна, як і з графічної консолі OpenShift Developer, так і з командного рядка. Ми скористаємося командою new-app, вказавши їй де брати builder-образ і наш вихідний код.

Вибач, OpenShift, ми недостатньо цінували тебе і приймали як належне

oc new-app registry.access.redhat.com/ubi8/openjdk-11:latest~https://github.com/gcolman/quarkus-hello-world.git

Все, наша програма створена. При цьому процес S2I виконав такі речі:

  • Створив службовий build-pod для будь-яких речей, пов'язаних зі складанням програми.
  • Створив конфіг OpenShift Build.
  • Завантажив builder-образ у внутрішній docker-реєстр OpenShift.
  • Клонував Hello World в локальний репозиторій.
  • Побачив, що там є maven pom, і тому скомпілював програму за допомогою maven.
  • Створив новий контейнерний образ, що містить скомпільовану Java-додаток, і поклав цей образ у внутрішній реєстр контейнерів.
  • Створив Kubernetes Deployment зі специфікаціями pod'а, сервісу тощо.
  • Запустив deploy контейнерного образу.
  • Вилучив службовий build-pod.

У цьому списку багато всього, але головне, що все збирання відбувається виключно всередині OpenShift, внутрішній Docker-реєстр знаходиться всередині OpenShift, а процес збирання створює всі компоненти Kubernetes і запускає їх у кластері.

Якщо візуально відслідковувати запуск S2I в консолі, можна побачити, як під час збирання запускається build pod.

Вибач, OpenShift, ми недостатньо цінували тебе і приймали як належне

А тепер поглянемо логи builder pod'а: по-перше, там видно, як maven робить свою роботу та скачує залежності для складання нашого java-додатка.

Вибач, OpenShift, ми недостатньо цінували тебе і приймали як належне

Після того, як закінчено maven-складання, запускається складання контейнерного образу, і потім цей зібраний образ відправляється у внутрішній репозиторій.

Вибач, OpenShift, ми недостатньо цінували тебе і приймали як належне

Все, процес збирання завершено. Тепер переконаємося, що в кластері запустилися pod'и та сервіси нашої програми.

oc get service

Вибач, OpenShift, ми недостатньо цінували тебе і приймали як належне

От і все. І лише одна команда. Нам залишається тільки зробити expose цього сервісу для доступу ззовні.

Крок 3 – робимо expose сервіс для доступу ззовні

Як і у випадку КУК, на платформі OpenShift нашому Hello World теж потрібен роутер, щоб направляти зовнішній трафік на сервіс усередині кластера. У OpenShift це дуже просто. По-перше, у кластері за умовчанням встановлений компонент маршрутизації HAProxy (його можна поміняти на той самий NGINX). По-друге, тут є спеціальні та допускаючі широкі можливості налаштування ресурси, які називаються Routes і нагадують Ingress-об'єкти в старому доброму Kubernetes (насправді OpenShift'івкі Routes сильно вплинули на дизайн Ingress-об'єктів, які тепер можна використовувати і в OpenShift) Але для нашого «Hello World», та й майже у всіх інших випадках, нам вистачить стандартного Route без додаткового налаштування.

Щоб створити для Hello World маршрутизований FQDN (так, в OpenShiift є свій DNS для маршрутизації по іменах сервісів), ми просто виконаємо expose для нашого сервісу:

Вибач, OpenShift, ми недостатньо цінували тебе і приймали як належне

oc expose service quarkus-hello-world

Якщо подивитися щойно створений Route, то там можна знайти FQDN та інші відомості щодо маршрутизації:

oc get route

Вибач, OpenShift, ми недостатньо цінували тебе і приймали як належне

І нарешті, звертаємось до нашого сервісу з браузера:

Вибач, OpenShift, ми недостатньо цінували тебе і приймали як належне

А ось тепер це було справді легко!

Ми любимо Kubernetes і все, що дозволяє робити ця технологія, а також ми любимо простоту та легкість. Kubernetes створювався, щоб неймовірно спростити експлуатацію розподілених масштабованих контейнерів, але для введення в дію додатків його простоти сьогодні вже недостатньо. І тут у гру вступає OpenShift, що йде в ногу з часом і пропонує Kubernetes, орієнтований насамперед на розробника. Було вкладено багато зусиль, щоб заточити платформу OpenShift саме під розробника, включаючи створення таких інструментів, як S2I, ODI, Developer Portal, OpenShift Operator Framework, інтеграція з IDE, Developer Catalogues, інтеграція з Helm, моніторинг та багато інших.

Сподіваємося, що ця стаття була для вас цікавою та корисною. А знайти додаткові ресурси, матеріали та інші корисні для розробки на платформі OpenShift можна на порталі Red Hat Developers.

Джерело: habr.com

Додати коментар або відгук