Сучасні програми на OpenShift, частина 2: пов'язані збірки chained builds

Всім привіт! З вами другий пост з нашої серії, де ми показуємо, як розгортати на Red Hat OpenShift сучасні веб-додатки.

Сучасні програми на OpenShift, частина 2: пов'язані збірки chained builds

У попередньому пості ми трохи торкнулися можливості нового builder-образу S2I (source-to-image), який призначений для складання та розгортання сучасних веб-додатків на платформі OpenShift. Тоді нас цікавила тема швидкого розгортання програми, а сьогодні ми розглянемо, як використовувати S2I-образ як «чистий» builder-образ і поєднувати його зі зв'язаними збірками OpenShift.

Чистий builder-образ

Як ми згадали в першій частині, більшість сучасних веб-додатків мають так званий етап складання, на якому зазвичай виконуються такі операції, як транспіляція коду, конкатенація декількох файлів і мініфікація. Отримані за підсумками цих операцій файли - це статичний HTML, JavaScript і CSS - складаються в output-папку. Розташування цієї папки зазвичай залежить від того, які засоби збирання використовуються, і для React це буде папка ./build (ми докладніше повернемося до цього питання нижче).

Source-to-Image (S2I)

У цьому пості ми зовсім не торкаємося теми «що таке S2I та як його використовувати» (докладніше про це можна почитати тут), але при цьому важливо чітко уявляти два етапи цього процесу, щоб зрозуміти, що ж робить образ Web App Builder.

Етап асемблювання (assemble phase)

Етап асемблювання за своєю суттю дуже схожий на те, що відбувається, коли ви запускаєте docker build і в результаті отримуєте новий образ Docker. Відповідно, цей етап виникає при запуску складання на платформі OpenShift.

У випадку образу Web App Builder за встановлення залежностей вашої програми та запуск складання відповідає assemble script. За замовчуванням builder-образ використовує конструкцію npm run build, але можна перевизначити через змінну оточення NPM_BUILD.

Як ми говорили раніше, розташування готової, вже зібраної програми залежить від того, які інструменти використовувати. Наприклад, у разі React це буде папка./build, а додатків Angular – папка project_name/dist. І, як уже було показано в минулому пості, розташування output-каталогу, який за замовчуванням заданий як build, можна перевизначити через змінну оточення OUTPUT_DIR. Ну і оскільки місце розташування output-папки відрізняється від фреймворку до фреймворку, ви просто копіюєте згенерований output стандартну папку в образі, а саме в /opt/apt-root/output. Це важливо для розуміння подальшої частини цієї статті, а поки давайте швиденько розглянемо наступний етап – запуск (run phase).

Етап запуску (run phase)

Цей етап виникає, коли нового образу, створеного на етапі асемблювання, робиться виклик docker run. Він відбувається і при виконанні розгортання на платформі OpenShift. За замовчуванням запустити сценарій використовує serve module для обслуговування статичного контенту, що лежить у зазначеному вище стандартному output-каталозі.

Цей метод хороший для швидкого розгортання додатків, але обслуговувати статичний контент таким чином не рекомендується. Ну оскільки реально ми обслуговуємо лише статичний контент, то встановлений усередині нашого образу Node.js не потрібно – вистачить веб-сервера.

Інакше кажучи, при складанні нам потрібне одне, при виконанні – інше. У такій ситуації стануть у нагоді пов'язані збірки (chained builds).

Пов'язані зборки (chained builds)

Ось що пишуть про chained builds у документації OpenShift:

«Дві збірки можна пов'язати один з одним, при цьому одна з них генерує скомпільовану сутність, а інша розміщує цю сутність в окремому образі, який використовується для запуску цієї сутності».

Іншими словами, ми можемо використовувати образ Web App Builder для запуску нашої збірки, а потім використовувати образ веб-сервера того ж NGINX, щоб обслуговувати наш контент.

Таким чином, ми можемо застосовувати образ Web App Builder як «чистий» builder-а і мати при цьому невеликий за розміром runtime-образ.

Тепер розберемо на конкретному прикладі.

Для тренування будемо використовувати простий додаток Reactстворене за допомогою інструмента командного рядка create-react-app.

Зібрати все докупи нам допоможе файл шаблону OpenShift.

Розберемо цей файл докладніше і почнемо з розділу параметрів.

parameters:
  - name: SOURCE_REPOSITORY_URL
    description: The source URL for the application
    displayName: Source URL
    required: true
  - name: SOURCE_REPOSITORY_REF
    description: The branch name for the application
    displayName: Source Branch
    value: master
    required: true
  - name: SOURCE_REPOSITORY_DIR
    description: The location within the source repo of the application
    displayName: Source Directory
    value: .
    required: true
  - name: OUTPUT_DIR
    description: The location of the compiled static files from your web apps builder
    displayName: Output Directory
    value: build
    required: false

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

Тепер погляньмо на розділ ImageStream-ів.

- apiVersion: v1
  kind: ImageStream
  metadata:
    name: react-web-app-builder  // 1 
  spec: {}
- apiVersion: v1
  kind: ImageStream
  metadata:
    name: react-web-app-runtime  // 2 
  spec: {}
- apiVersion: v1
  kind: ImageStream
  metadata:
    name: web-app-builder-runtime // 3
  spec:
    tags:
    - name: latest
      from:
        kind: DockerImage
        name: nodeshift/ubi8-s2i-web-app:10.x
- apiVersion: v1
  kind: ImageStream
  metadata:
    name: nginx-image-runtime // 4
  spec:
    tags:
    - name: latest
      from:
        kind: DockerImage
        name: 'centos/nginx-112-centos7:latest'

Погляньте на третій та четвертий образи. Обидва вони визначені як Docker-образи, і тут чітко видно, звідки вони беруться.

Третій образ – це web-app-builder, і він береться з nodeshift/ubi8-s2i-web-app із тегом 10.x на Докер-концентратор.

Четвертий – це образ NGINX (версії 1.12) з тегом latest на Докер-концентратор.

Тепер поглянемо на два перші образи. Вони порожні на старті і створюються тільки на етапі складання (build phase). Перший образ – react-web-app-builder – стане результатом етапу асемблювання, який об'єднає образ web-app-builder-runtime та наш вихідний код. Саме тому ми і вписали в ім'я цього образу builder.

Другий образ – react-web-app-runtime – стане результатом об'єднання nginx-image-runtime та файлів з образу react-web-app-builder. Цей образ також буде використовуватися при розгортанні та міститиме лише веб-сервер та статичний HTML, JavaScript, CSS нашої програми.

Заплутано? Тепер поглянемо на зміни збірки і стане трохи зрозумілішим.

У нашому шаблоні є дві конфігурації збирання. Ось перша з них і вона досить стандартна:

  apiVersion: v1
  kind: BuildConfig
  metadata:
    name: react-web-app-builder
  spec:
    output:
      to:
        kind: ImageStreamTag
        name: react-web-app-builder:latest // 1
    source:   // 2 
      git:
        uri: ${SOURCE_REPOSITORY_URL}
        ref: ${SOURCE_REPOSITORY_REF}
      contextDir: ${SOURCE_REPOSITORY_DIR}
      type: Git
    strategy:
      sourceStrategy:
        env:
          - name: OUTPUT_DIR // 3 
            value: ${OUTPUT_DIR}
        from:
          kind: ImageStreamTag
          name: web-app-builder-runtime:latest // 4
        incremental: true // 5
      type: Source
    triggers: // 6
    - github:
        secret: ${GITHUB_WEBHOOK_SECRET}
      type: GitHub
    - type: ConfigChange
    - imageChange: {}
      type: ImageChange

Як бачимо, рядок з міткою 1 каже, що результат цієї збірки буде поміщений у той самий образ react-web-app-builder, який ми раніше бачили в розділі ImageStream-ів.

Рядок із міткою 2 каже, звідки брати код. У нашому випадку це репозиторій git, а розташування, ref та папка контексту визначені параметрами, які ми вже бачили вище.

Рядок із міткою 3 – це ми вже бачили у розділі parameters. Вона додає змінну оточення OUTPUT_DIR, яка у прикладі дорівнює build.
Рядок з міткою 4 каже використовувати образ web-app-builder-runtime, який ми вже бачили у розділі ImageStream.

Рядок з міткою 5 говорить, що ми хочемо використовувати інкрементний білд, якщо S2I-образ його підтримує, а образ Web App Builder – підтримує. При першому запуску після завершення етапу асемблювання образ збереже папку node_modules в архівний файл. Потім при наступних запусках образ просто розархівуватиме цю папку, щоб скоротити тривалість складання.

І, нарешті, рядок з міткою 6 – це лише кілька тригерів, щоб складання запускалося автоматично, без ручного втручання, коли щось змінюється.

Загалом це досить стандартна конфігурація збірки.

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

apiVersion: v1
  kind: BuildConfig
  metadata:
    name: react-web-app-runtime
  spec:
    output:
      to:
        kind: ImageStreamTag
        name: react-web-app-runtime:latest // 1
    source: // 2
      type: Image
      images:                              
        - from:
            kind: ImageStreamTag
            name: react-web-app-builder:latest // 3
          paths:
            - sourcePath: /opt/app-root/output/.  // 4
              destinationDir: .  // 5
             
    strategy: // 6
      sourceStrategy:
        from:
          kind: ImageStreamTag
          name: nginx-image-runtime:latest
        incremental: true
      type: Source
    triggers:
    - github:
        secret: ${GITHUB_WEBHOOK_SECRET}
      type: GitHub
    - type: ConfigChange
    - type: ImageChange
      imageChange: {}
    - type: ImageChange
      imageChange:
        from:
          kind: ImageStreamTag
          name: react-web-app-builder:latest // 7

Отже, друга конфігурація складання – react-web-app-runtime, і вона починається цілком стандартно.

У рядку з міткою 1 немає нічого нового – вона просто каже, що результат збирання кладеться в образ react-web-app-runtime.

Рядок з позначкою 2, як і попередньої конфігурації, вказує, звідки брати вихідний код. Але зверніть увагу, що ми говоримо, що він береться з образу. Причому з того образу, який ми щойно створили, – з react-web-app-builder (зазначений у рядку з позначкою 3). Файли, які ми хочемо використовувати, знаходяться всередині образу і їхнє розташування там задається в рядку з міткою 4, у нашому випадку це /opt/app-root/output/. Якщо пам'ятаєте, саме туди складаються файли, що згенеровані за результатами складання нашої програми.

Папка призначення, задана в терміні з міткою 5 - це просто поточний каталог (це все, нагадаємо, крутиться всередині чарівної речі під назвою OpenShift, а не на вашому локальному комп'ютері).

Секція strategy - рядок з міткою 6 - теж схожа на першу конфігурацію збірки. Тільки на цей раз ми збираємося використовувати nginx-image-runtime, який вже бачили в розділі ImageStream.

Нарешті, рядок з міткою 7 – це розділ тригерів, який активує цю збірку щоразу, коли змінюється образ react-web-app-builder.

В іншому цей шаблон містить цілком стандартну конфігурацію розгортання, а також речі, які відносяться до сервісів і маршрутів, але ми не будемо в цьому заглиблюватися. Зверніть увагу, що образ, який розгортатиметься – це образ react-web-app-runtime.

Розгортання програми

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

Ми можемо використовувати клієнтський інструмент OpenShift під назвою oc, щоб розгорнути наш шаблон:

$ find . | grep openshiftio | grep application | xargs -n 1 oc apply -f

$ oc new-app --template react-web-app -p SOURCE_REPOSITORY_URL=https://github.com/lholmquist/react-web-app

Перша команда на скрині вище – це спеціально інженерний спосіб знайти шаблон./openshiftio/application.yaml.

Друга команда просто створює нову програму на основі цього шаблону.

Після того, як ці команди відпрацюють, ми побачимо, що у нас з'явилися дві збірки:

Сучасні програми на OpenShift, частина 2: пов'язані збірки chained builds

А повернувшись на екран Overview, побачимо запуск, що запустився:

Сучасні програми на OpenShift, частина 2: пов'язані збірки chained builds

Клацніть за посиланням – і ми перейдемо до нашої програми, яка є сторінкою програми React App за замовчуванням:

Сучасні програми на OpenShift, частина 2: пов'язані збірки chained builds

доповнення 1

Для любителів Angular у нас також є приклад програми.

Шаблон тут такий самий, за винятком змінної OUTPUT_DIR.

доповнення 2

У цій статті ми використовували як веб-сервер NGINX, але його досить легко замінити на Apache, просто поміняйте у файлі шаблон образ NGINX на образ Apache.

Висновок

У першій частині цієї серії ми показали, як швидко розгортати сучасні веб-програми на платформі OpenShift. Сьогодні ми розглянули, що робить образ Web App і як його можна поєднувати з чистим веб-сервером типу NGINX за допомогою пов'язаних збірок (chained build) при організації більш придатної для продакшн умов зборки додатків. У наступній, заключній статті цієї серії, ми покажемо, як запускати на OpenShift сервер розробки для своєї програми та забезпечувати синхронізацію локальних та віддалених файлів.

Зміст цієї серії статей

  • Частина 1: як розгортати сучасні веб-застосунки всього за кілька кроків;
  • Частина 2: як застосовувати новий образ S2I разом з наявним чином HTTP-сервера, наприклад, NGINX, використовуючи пов'язані збірки OpenShift, для організації продакшн-розгортання;
  • Частина 3: як запустити на платформі OpenShift сервер розробки для своєї програми та синхронізувати його з локальною файловою системою.

Додаткові ресурси

Джерело: habr.com

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