Nowoczesne aplikacje na OpenShift, część 3: OpenShift jako środowisko programistyczne i OpenShift Pipelines

Witam wszystkich na tym blogu! To trzeci post z serii, w której pokazujemy, jak wdrażać nowoczesne aplikacje internetowe na platformie Red Hat OpenShift.

Nowoczesne aplikacje na OpenShift, część 3: OpenShift jako środowisko programistyczne i OpenShift Pipelines

W poprzednich dwóch postach pokazaliśmy, jak w kilku krokach wdrożyć nowoczesne aplikacje internetowe oraz jak używać nowego obrazu S2I wraz z gotowym obrazem serwera HTTP, takim jak NGINX, wykorzystując kompilacje łańcuchowe do koordynowania wdrożeń produkcyjnych .

Dzisiaj pokażemy jak uruchomić serwer deweloperski dla Twojej aplikacji na platformie OpenShift i zsynchronizować go z lokalnym systemem plików, a także porozmawiamy o tym, czym są OpenShift Pipelines i jak można je wykorzystać jako alternatywę dla połączonych zespołów.

OpenShift jako środowisko programistyczne

Przepływ prac programistycznych

Jak już stwierdzono w pierwszy posttypowy proces tworzenia nowoczesnych aplikacji internetowych to po prostu swego rodzaju „serwer programistyczny”, który śledzi zmiany w plikach lokalnych. Gdy wystąpią, uruchamiana jest kompilacja aplikacji, a następnie jest ona aktualizowana w przeglądarce.

W większości nowoczesnych frameworków taki „serwer programistyczny” jest wbudowany w odpowiednie narzędzia wiersza poleceń.

Lokalny przykład

Najpierw zobaczmy, jak to działa podczas lokalnego uruchamiania aplikacji. Weźmy jako przykład aplikację React z poprzednich artykułów, chociaż prawie te same koncepcje przepływu pracy mają zastosowanie we wszystkich innych nowoczesnych frameworkach.
Aby więc uruchomić „serwer deweloperski” w naszym przykładzie React, wprowadzimy następujące polecenie:

$ npm run start

Następnie w oknie terminala zobaczymy coś takiego:

Nowoczesne aplikacje na OpenShift, część 3: OpenShift jako środowisko programistyczne i OpenShift Pipelines

A nasza aplikacja otworzy się w domyślnej przeglądarce:

Nowoczesne aplikacje na OpenShift, część 3: OpenShift jako środowisko programistyczne i OpenShift Pipelines

Teraz jeśli dokonamy zmian w pliku, aplikacja powinna zaktualizować się w przeglądarce.

OK, wszystko jest jasne w przypadku programowania w trybie lokalnym, ale jak osiągnąć to samo na OpenShift?

Serwer deweloperski na OpenShift

Jeśli pamiętasz, w Poprzedni post, przyjrzeliśmy się tzw. fazie uruchamiania obrazu S2I i zobaczyliśmy, że domyślnie moduł serwujący jest odpowiedzialny za obsługę naszej aplikacji internetowej.

Jeśli jednak przyjrzeć się bliżej uruchom skrypt z tego przykładu zawiera zmienną środowiskową $NPM_RUN, która umożliwia wykonanie polecenia.

Na przykład możemy użyć modułu nodeshift do wdrożenia naszej aplikacji:

$ npx nodeshift --deploy.env NPM_RUN="yarn start" --dockerImage=nodeshift/ubi8-s2i-web-app

Uwaga: Powyższy przykład został skrócony w celu zilustrowania ogólnej idei.

W tym miejscu dodaliśmy do naszego wdrożenia zmienną środowiskową NPM_RUN, która nakazuje środowisku wykonawczemu wykonanie polecenia przędzy start, które uruchamia serwer programistyczny React w naszym module OpenShift.

Jeśli spojrzysz na dziennik działającego kapsuły, będzie on wyglądał mniej więcej tak:

Nowoczesne aplikacje na OpenShift, część 3: OpenShift jako środowisko programistyczne i OpenShift Pipelines

Oczywiście to wszystko nic nie będzie, dopóki nie zsynchronizujemy kodu lokalnego z kodem, który również jest monitorowany pod kątem zmian, ale żyje na zdalnym serwerze.

Synchronizacja kodu zdalnego i lokalnego

Na szczęście nodeshift może z łatwością pomóc w synchronizacji, a do śledzenia zmian można użyć polecenia watch.

Zatem po uruchomieniu polecenia wdrożenia serwera programistycznego dla naszej aplikacji możemy bezpiecznie użyć następującego polecenia:

$ npx nodeshift watch

W rezultacie zostanie nawiązane połączenie z uruchomionym podem, który stworzyliśmy nieco wcześniej, aktywowana zostanie synchronizacja naszych plików lokalnych ze zdalnym klastrem, a pliki w naszym systemie lokalnym zaczną być monitorowane pod kątem zmian.

Dlatego jeśli teraz zaktualizujemy plik src/App.js, system zareaguje na te zmiany, skopiuje je do zdalnego klastra i uruchomi serwer deweloperski, który następnie zaktualizuje naszą aplikację w przeglądarce.

Aby dopełnić obraz, pokażmy jak wyglądają całe te polecenia:

$ npx nodeshift --strictSSL=false --dockerImage=nodeshift/ubi8-s2i-web-app --build.env YARN_ENABLED=true --expose --deploy.env NPM_RUN="yarn start" --deploy.port 3000

$ npx nodeshift watch --strictSSL=false

Polecenie watch stanowi abstrakcję polecenia oc rsync. Możesz dowiedzieć się więcej o jego działaniu tutaj.

To był przykład dla React, ale dokładnie tej samej metody można użyć w innych frameworkach, wystarczy ustawić zmienną środowiskową NPM_RUN, jeśli to konieczne.

Rurociągi Openshift

Nowoczesne aplikacje na OpenShift, część 3: OpenShift jako środowisko programistyczne i OpenShift Pipelines

Następnie porozmawiamy o narzędziu takim jak OpenShift Pipelines i o tym, jak można go wykorzystać jako alternatywę dla kompilacji łańcuchowych.

Co to są potoki OpenShift

OpenShift Pipelines to natywny w chmurze system ciągłej integracji i dostarczania CI/CD, przeznaczony do organizowania potoków za pomocą Tekton. Tekton to elastyczna platforma CI/CD o otwartym kodzie źródłowym, natywna dla Kubernetes, która umożliwia automatyzację wdrażania na różnych platformach (Kubernetes, maszyny bezserwerowe, maszyny wirtualne itp.) poprzez abstrakcję z warstwy bazowej.

Zrozumienie tego artykułu wymaga pewnej wiedzy na temat Pipelines, dlatego zdecydowanie zalecamy zapoznanie się z nim w pierwszej kolejności oficjalny podręcznik.

Konfigurowanie środowiska pracy

Aby pobawić się przykładami z tego artykułu, musisz najpierw przygotować środowisko pracy:

  1. Zainstaluj i skonfiguruj klaster OpenShift 4. W naszych przykładach wykorzystano w tym celu kontenery CodeReady (CRD), których instrukcje instalacji można znaleźć tutaj.
  2. Gdy klaster będzie gotowy, należy zainstalować na nim Pipeline Operator. Nie bój się, to proste, instrukcja montażu tutaj.
  3. Pobierz Tekton CLI (tkn) tutaj.
  4. Uruchom narzędzie wiersza poleceń create-react-app, aby utworzyć aplikację, którą następnie wdrożysz (jest to prosta aplikacja React).
  5. (Opcjonalnie) Sklonuj repozytorium, aby uruchomić przykładową aplikację lokalnie za pomocą npm install, a następnie npm start.

Repozytorium aplikacji będzie również zawierać folder k8s, który będzie zawierał pliki YAML Kubernetes/OpenShift użyte do wdrożenia aplikacji. Będą w tym zadania Zadania, Zadania Klastra, Zasoby i Potoki, które utworzymy repozytoria.

Zejść

Pierwszym krokiem w naszym przykładzie jest utworzenie nowego projektu w klastrze OpenShift. Nazwijmy ten projekt webapp-pipeline i utwórz go za pomocą następującego polecenia:

$ oc new-project webapp-pipeline

Ta nazwa projektu pojawi się w kodzie później, więc jeśli zdecydujesz się nadać mu inną nazwę, nie zapomnij odpowiednio edytować przykładowego kodu. Zaczynając od tego momentu, nie będziemy iść z góry na dół, ale z dołu do góry: to znaczy najpierw stworzymy wszystkie elementy przenośnika, a dopiero potem sam przenośnik.

Więc przede wszystkim...

Zadania

Stwórzmy kilka zadań, które następnie pomogą wdrożyć aplikację w naszym potoku. Pierwsze zadanie - Apply_manifests_task - odpowiada za zastosowanie YAML tych zasobów Kubernetesa (usługa, wdrożenie i trasa), które znajdują się w folderze k8s naszej aplikacji. Drugie zadanie – update_deployment_task – odpowiada za aktualizację już wdrożonego obrazu do utworzonego przez nasz potok.

Nie martw się, jeśli nie jest to jeszcze całkiem jasne. W rzeczywistości zadania te przypominają narzędzia i przyjrzymy się im bardziej szczegółowo nieco później. Na razie utwórzmy je:

$ oc create -f https://raw.githubusercontent.com/nodeshift/webapp-pipeline-tutorial/master/tasks/update_deployment_task.yaml
$ oc create -f https://raw.githubusercontent.com/nodeshift/webapp-pipeline-tutorial/master/tasks/apply_manifests_task.yaml

Następnie za pomocą polecenia tkn CLI sprawdzimy, czy zadania zostały utworzone:

$ tkn task ls

NAME                AGE
apply-manifests     1 minute ago
update-deployment   1 minute ago

Uwaga: są to zadania lokalne dla bieżącego projektu.

Zadania klastra

Zadania klastrowe zasadniczo nie różnią się od prostych zadań. Oznacza to, że jest to zbiór kroków wielokrotnego użytku, które są łączone w ten czy inny sposób podczas wykonywania określonego zadania. Różnica polega na tym, że zadanie klastra jest dostępne w każdym miejscu klastra. Aby zobaczyć listę zadań klastra, które są tworzone automatycznie podczas dodawania Pipeline Operator, ponownie użyjemy komendy tkn CLI:

$ tkn clustertask ls

NAME                       AGE
buildah                    1 day ago
buildah-v0-10-0            1 day ago
jib-maven                  1 day ago
kn                         1 day ago
maven                      1 day ago
openshift-client           1 day ago
openshift-client-v0-10-0   1 day ago
s2i                        1 day ago
s2i-go                     1 day ago
s2i-go-v0-10-0             1 day ago
s2i-java-11                1 day ago
s2i-java-11-v0-10-0        1 day ago
s2i-java-8                 1 day ago
s2i-java-8-v0-10-0         1 day ago
s2i-nodejs                 1 day ago
s2i-nodejs-v0-10-0         1 day ago
s2i-perl                   1 day ago
s2i-perl-v0-10-0           1 day ago
s2i-php                    1 day ago
s2i-php-v0-10-0            1 day ago
s2i-python-3               1 day ago
s2i-python-3-v0-10-0       1 day ago
s2i-ruby                   1 day ago
s2i-ruby-v0-10-0           1 day ago
s2i-v0-10-0                1 day ago

Utwórzmy teraz dwa zadania klastrowe. Pierwszy wygeneruje obraz S2I i wyśle ​​go do wewnętrznego rejestru OpenShift; drugim jest zbudowanie naszego wizerunku w oparciu o NGINX, wykorzystując jako treść już zbudowaną aplikację.

Utwórz i wyślij obraz

Tworząc pierwsze zadanie, powtórzymy to, co zrobiliśmy już w poprzednim artykule o połączonych złożeniach. Przypomnijmy, że do „budowania” naszej aplikacji użyliśmy obrazu S2I (ubi8-s2i-web-app), w wyniku czego otrzymaliśmy obraz przechowywany w wewnętrznym rejestrze OpenShift. Teraz użyjemy tego obrazu aplikacji internetowej S2I do utworzenia pliku DockerFile dla naszej aplikacji, a następnie użyjemy Buildah do wykonania faktycznej kompilacji i przekazania powstałego obrazu do wewnętrznego rejestru OpenShift, ponieważ dokładnie to robi OpenShift podczas wdrażania aplikacji przy użyciu NodeShift .

Zapytacie, skąd to wszystko wiemy? Z oficjalna wersja oficjalnego Node.js, po prostu go skopiowaliśmy i zmodyfikowaliśmy dla siebie.

Utwórzmy teraz zadanie klastrowe s2i-web-app:

$ oc create -f https://raw.githubusercontent.com/nodeshift/webapp-pipeline-tutorial/master/clustertasks/s2i-web-app-task.yaml

Nie będziemy tego szczegółowo analizować, skupimy się jedynie na parametrze OUTPUT_DIR:

params:
      - name: OUTPUT_DIR
        description: The location of the build output directory
        default: build

Domyślnie ten parametr jest równy build, czyli miejsce, w którym React umieszcza zmontowaną treść. Inne frameworki używają innych ścieżek, na przykład w Ember jest to dist. Wynikiem naszego pierwszego zadania klastrowego będzie obraz zawierający zebrane przez nas kody HTML, JavaScript i CSS.

Zbuduj wizerunek w oparciu o NGINX

Jeśli chodzi o nasze drugie zadanie klastrowe, powinno ono zbudować dla nas obraz w oparciu o NGINX, korzystając z zawartości zbudowanej już przez nas aplikacji. Zasadniczo jest to część poprzedniej sekcji, w której przyjrzeliśmy się kompilacjom łańcuchowym.

W tym celu – dokładnie tak samo jak powyżej – utworzymy zadanie klastrowe webapp-build-runtime:

$ oc create -f https://raw.githubusercontent.com/nodeshift/webapp-pipeline-tutorial/master/clustertasks/webapp-build-runtime-task.yaml

Jeśli spojrzysz na kod tych zadań klastrowych, zobaczysz, że nie określa on repozytorium Git, z którym pracujemy, ani nazw obrazów, które tworzymy. Określamy jedynie, co dokładnie przesyłamy do Gita, czyli konkretny obraz, na który ma zostać wyrzucony finalny obraz. Dlatego te zadania klastrowe można ponownie wykorzystać podczas pracy z innymi aplikacjami.

I tu z gracją przechodzimy do następnego punktu...

Ресурсы

Ponieważ więc, jak właśnie powiedzieliśmy, zadania klastrowe powinny być tak ogólne, jak to możliwe, musimy utworzyć zasoby, które będą używane jako dane wejściowe (repozytorium Git) i jako dane wyjściowe (końcowe obrazy). Pierwszym zasobem, którego potrzebujemy, jest Git, w którym znajduje się nasza aplikacja, mniej więcej tak:

# This resource is the location of the git repo with the web application source
apiVersion: tekton.dev/v1alpha1
kind: PipelineResource
metadata:
  name: web-application-repo
spec:
  type: git
  params:
    - name: url
      value: https://github.com/nodeshift-starters/react-pipeline-example
    - name: revision
      value: master

Tutaj PipelineResource jest typu git. Klucz url w sekcji params wskazuje na konkretne repozytorium i określa gałąź master (jest to opcjonalne, ale zapisujemy je dla kompletności).

Teraz musimy utworzyć zasób obrazu, w którym zostaną zapisane wyniki zadania s2i-web-app. Robi się to w następujący sposób:

# This resource is the result of running "npm run build",  the resulting built files will be located in /opt/app-root/output
apiVersion: tekton.dev/v1alpha1
kind: PipelineResource
metadata:
  name: built-web-application-image
spec:
  type: image
  params:
    - name: url
      value: image-registry.openshift-image-registry.svc:5000/webapp-pipeline/built-web-application:latest

Tutaj PipelineResource jest typu image, a wartość parametru url wskazuje na wewnętrzny rejestr obrazów OpenShift, w szczególności ten znajdujący się w przestrzeni nazw webapp-pipeline. Nie zapomnij zmienić tego ustawienia, jeśli używasz innej przestrzeni nazw.

I wreszcie ostatni zasób, którego będziemy potrzebować, będzie również typu image i będzie to ostateczny obraz NGINX, który będzie następnie używany podczas wdrażania:

# This resource is the image that will be just the static html, css, js files being run with nginx
apiVersion: tekton.dev/v1alpha1
kind: PipelineResource
metadata:
  name: runtime-web-application-image
spec:
  type: image
  params:
    - name: url
      value: image-registry.openshift-image-registry.svc:5000/webapp-pipeline/runtime-web-application:latest

Ponownie zauważ, że ten zasób przechowuje obraz w wewnętrznym rejestrze OpenShift w przestrzeni nazw webapp-pipeline.

Aby utworzyć wszystkie te zasoby na raz, używamy polecenia create:

$ oc create -f https://raw.githubusercontent.com/nodeshift/webapp-pipeline-tutorial/master/resources/resource.yaml

Możesz upewnić się, że zasoby zostały utworzone w następujący sposób:

$ tkn resource ls

Rurociąg przenośnika

Teraz, gdy mamy już wszystkie niezbędne komponenty, złóżmy z nich potok, tworząc go za pomocą następującego polecenia:

$ oc create -f https://raw.githubusercontent.com/nodeshift/webapp-pipeline-tutorial/master/pipelines/build-and-deploy-react.yaml

Zanim jednak uruchomimy to polecenie, przyjrzyjmy się tym komponentom. Pierwsza to nazwa:

apiVersion: tekton.dev/v1alpha1
kind: Pipeline
metadata:
  name: build-and-deploy-react

Następnie w sekcji specyfikacji widzimy wskazanie zasobów, które utworzyliśmy wcześniej:

spec:
  resources:
    - name: web-application-repo
      type: git
    - name: built-web-application-image
      type: image
    - name: runtime-web-application-image
      type: image

Następnie tworzymy zadania, które musi wykonać nasz potok. Przede wszystkim musi wykonać utworzone już przez nas zadanie s2i-web-app:

tasks:
    - name: build-web-application
      taskRef:
        name: s2i-web-app
        kind: ClusterTask

To zadanie pobiera parametry wejściowe (zasób gir) i wyjściowe (zasób obrazu wbudowanej aplikacji internetowej). Przekazujemy mu również specjalny parametr, aby nie sprawdzał protokołu TLS, ponieważ używamy certyfikatów z podpisem własnym:

resources:
        inputs:
          - name: source
            resource: web-application-repo
        outputs:
          - name: image
            resource: built-web-application-image
      params:
        - name: TLSVERIFY
          value: "false"

Kolejne zadanie jest prawie takie samo, tyle że tutaj utworzone już przez nas zadanie klastrowe webapp-build-runtime nazywa się:

name: build-runtime-image
    taskRef:
      name: webapp-build-runtime
      kind: ClusterTask

Podobnie jak w przypadku poprzedniego zadania, przekazujemy zasób, ale teraz jest to obraz-aplikacji internetowej (wynik naszego poprzedniego zadania). I jako wyjście ponownie ustawiamy obraz. Ponieważ to zadanie musi zostać wykonane po poprzednim, dodajemy pole runAfter:

resources:
        inputs:
          - name: image
            resource: built-web-application-image
        outputs:
          - name: image
            resource: runtime-web-application-image
        params:
        - name: TLSVERIFY
          value: "false"
      runAfter:
        - build-web-application

Kolejne dwa zadania odpowiadają za korzystanie z plików YAML usługi, trasy i wdrożenia, które znajdują się w katalogu k8s naszej aplikacji internetowej, a także za aktualizację tego wdrożenia podczas tworzenia nowych obrazów. Te dwa zadania klastrowe zdefiniowaliśmy na początku artykułu.

Uruchomienie przenośnika

Tak więc wszystkie części naszego potoku zostały utworzone i uruchomimy je za pomocą następującego polecenia:

$ tkn pipeline start build-and-deploy-react

Na tym etapie linia poleceń używana jest interaktywnie i w odpowiedzi na każde z jej żądań należy wybrać odpowiednie zasoby: dla zasobu git wybierz web-application-repo, następnie dla pierwszego zasobu obrazu, wbudowaną aplikację internetową -image i na koniec drugi zasób obrazu – runtime-web-application-image:

? Choose the git resource to use for web-application-repo: web-application-repo (https://github.com/nodeshift-starters/react-pipeline-example)
? Choose the image resource to use for built-web-application-image: built-web-application-image (image-registry.openshift-image-registry.svc:5000/webapp-pipeline/built-web-
application:latest)
? Choose the image resource to use for runtime-web-application-image: runtime-web-application-image (image-registry.openshift-image-registry.svc:5000/webapp-pipeline/runtim
e-web-application:latest)
Pipelinerun started: build-and-deploy-react-run-4xwsr

Sprawdźmy teraz status potoku za pomocą następującego polecenia:

$ tkn pipeline logs -f

Po uruchomieniu potoku i wdrożeniu aplikacji możemy zażądać opublikowanej trasy za pomocą następującego polecenia:

$ oc get route react-pipeline-example --template='http://{{.spec.host}}'

Aby uzyskać lepszą wizualizację, możesz wyświetlić nasz potok w trybie programisty konsoli internetowej w sekcji Rurociągi, jak pokazano na rys. 1.

Nowoczesne aplikacje na OpenShift, część 3: OpenShift jako środowisko programistyczne i OpenShift Pipelines

Ryc.1. Przegląd działających rurociągów.

Kliknięcie działającego potoku powoduje wyświetlenie dodatkowych szczegółów, jak pokazano na rysunku 2.

Nowoczesne aplikacje na OpenShift, część 3: OpenShift jako środowisko programistyczne i OpenShift Pipelines

Ryż. 2. Dodatkowe informacje o gazociągu.

Po uzyskaniu większej ilości informacji możesz zobaczyć działające aplikacje w widoku Topologia, jak pokazano na rys.3.

Nowoczesne aplikacje na OpenShift, część 3: OpenShift jako środowisko programistyczne i OpenShift Pipelines

Ryc. 3. Wystrzelony kapsuła.

Kliknięcie kółka w prawym górnym rogu ikony otwiera naszą aplikację, jak pokazano na rys. 4.

Nowoczesne aplikacje na OpenShift, część 3: OpenShift jako środowisko programistyczne i OpenShift Pipelines

Ryż. 4. Uruchomienie aplikacji React.

wniosek

Pokazaliśmy więc, jak uruchomić serwer programistyczny dla aplikacji na OpenShift i zsynchronizować go z lokalnym systemem plików. Przyjrzeliśmy się także, jak symulować szablon kompilacji łańcuchowej przy użyciu potoków OpenShift. Można znaleźć wszystkie przykładowe kody z tego artykułu tutaj.

Dodatkowe zasoby (EN)

Zapowiedzi dotyczące nadchodzących webinariów

Rozpoczynamy cykl piątkowych webinarów na temat natywnych doświadczeń z wykorzystaniem Red Hat OpenShift Container Platform i Kubernetes:

Źródło: www.habr.com

Dodaj komentarz