Сучасныя прыкладанні на 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. Па змаўчанні run script выкарыстоўвае 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, убачым які запусціўся pod:

Сучасныя прыкладанні на 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

Дадаць каментар