Съвременни приложения на 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.

Нека разгледаме файла по-подробно, като започнем с раздела за параметрите.

параметри:
  - име: SOURCE_REPOSITORY_URL
    описание: Източникът на URL за приложението
    displayName: URL на източника
    задължително: да
  - име: SOURCE_REPOSITORY_REF
    описание: Името на клон за приложението
    displayName: Източен клон
    стойност: master
    задължително: да
  - име: SOURCE_REPOSITORY_DIR
    описание: Местоположението в източника на репото на приложението
    displayName: Източна директория
    стойност: .
    задължително: да
  - име: OUTPUT_DIR
    описание: Местоположението на компилираните статични файлове от вашия строител на уеб приложения
    displayName: Изходна директория
    стойност: build
    задължително: не

Тук всичко е доста ясно, но е важно да се обърне внимание на параметъра OUTPUT_DIR. За React приложението от примера ни, няма причина за притеснение, тъй като React използва стойността по подразбиране за изходна папка, но в случай с 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 на Docker hub.

Четвъртият – образът на NGINX (версия 1.12) с етикет latest на Docker hub.

Сега погледнете двата първи образа. Те са и двамата празни в началото и се създават само на етапа на сглобяване (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, който преди малко видяхме в секцията ImageStreams.

Редът с етикет 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. Днес разгледахме какво прави образа на уеб приложението и как може да се комбинира с чист уеб-сървър като NGINX с помощта на свързани билдове (chained builds) за осигуряване на по-подходяща за производствени условия билд на приложения. В следващата, заключителна статия от тази серия, ще покажем как да стартирате на OpenShift сървър за разработка за вашето приложение и да осигурите синхронизация между локални и отдалечени файлове.

Съдържание на тази серия статии

  • Част 1: как да разгръщате съвременни уеб приложения само за няколко стъпки;
  • Част 2: как да приложите новия образ S2I заедно с вече съществуващия образ на HTTP-сървър, например NGINX, използвайки свързани билдове на OpenShift, за организиране на производствено разгръщане;
  • Част 3: как да стартирате на платформата OpenShift сървър за разработка за вашето приложение и да го синхронизирате с локалната файлова система.

Допълнителни ресурси

Източник: habr.com

Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри 🔥 Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри | ProHoster