Programowanie InnerLoop z użyciem Node.js

1. Omówienie

W tym module prezentowane są funkcje i możliwości zaprojektowane w celu usprawnienia przepływu pracy programistów, których zadaniem jest tworzenie aplikacji NodeJS w środowisku skonteneryzowanym. Typowe tworzenie kontenerów wymaga, aby użytkownik znał szczegóły kontenerów i proces ich tworzenia. Poza tym deweloperzy zwykle muszą przerwać przepływ pracy, wychodząc z IDE, aby przetestować i debugować aplikacje w środowiskach zdalnych. Dzięki narzędziom i technologiom wspomnianym w tym samouczku deweloperzy mogą wydajnie pracować z aplikacjami skonteneryzowanymi bez opuszczania IDE.

Czego się nauczysz

W tym module nauczysz się, jak tworzyć aplikacje z wykorzystaniem kontenerów w GCP, takich jak:

  • Tworzenie startowej aplikacji Nodejs
  • Konfigurowanie aplikacji Nodejs na potrzeby tworzenia kontenerów
  • Kodowanie prostego kodu CRUD Rest Service
  • Wdrażanie w GKE
  • Debugowanie stanu błędu
  • Wykorzystanie punktu przerwania / logów
  • Wdrażanie zmian z powrotem w GKE
  • Opcjonalnie: integrowanie Cloud SQL w celu zapewnienia trwałości backendu

2. Konfiguracja i wymagania

Samodzielne konfigurowanie środowiska

  1. Zaloguj się w konsoli Google Cloud i utwórz nowy projekt lub wykorzystaj już istniejący. Jeśli nie masz jeszcze konta Gmail ani Google Workspace, musisz je utworzyć.

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • Nazwa projektu jest wyświetlaną nazwą uczestników tego projektu. To ciąg znaków, który nie jest używany przez interfejsy API Google i w każdej chwili możesz go zaktualizować.
  • Identyfikator projektu musi być unikalny we wszystkich projektach Google Cloud i nie można go zmienić (nie można go zmienić po ustawieniu). Cloud Console automatycznie wygeneruje unikalny ciąg znaków. zwykle nieważne, co ona jest. W większości ćwiczeń w Codelabs musisz odwoływać się do identyfikatora projektu (który zwykle nazywa się PROJECT_ID), więc jeśli Ci się nie podoba, wygeneruj kolejny losowy projekt lub wypróbuj swój własny identyfikator i sprawdź, czy jest dostępny. Potem urządzenie jest „zawieszone”. po utworzeniu projektu.
  • Występuje trzecia wartość – numer projektu – używany przez niektóre interfejsy API. Więcej informacji o wszystkich 3 wartościach znajdziesz w dokumentacji.
  1. Następnie musisz włączyć płatności w konsoli Cloud, aby móc korzystać z zasobów i interfejsów API Cloud. Ukończenie tego ćwiczenia z programowania nie powinno kosztować zbyt wiele. Aby wyłączyć zasoby, aby nie naliczać opłat po zakończeniu tego samouczka, wykonaj czynności „wyczyść” znajdziesz na końcu tego ćwiczenia. Nowi użytkownicy Google Cloud mogą skorzystać z programu bezpłatnego okresu próbnego o wartości 300 USD.

Uruchom edytor Cloud Shell

Ten moduł został opracowany i przetestowany pod kątem użycia z edytorem Google Cloud Shell. Aby uzyskać dostęp do edytora:

  1. wejdź na stronę swojego projektu Google na https://console.cloud.google.com.
  2. W prawym górnym rogu kliknij ikonę edytora Cloud Shell.

8560cc8d45e8c112.png

  1. Na dole okna otworzy się nowy panel
  2. Kliknij przycisk Otwórz edytor

9E504cb98a6a8005.png

  1. Edytor otworzy się z eksploratorem po prawej stronie i edytorem w obszarze środkowym.
  2. Okienko terminala powinno być też dostępne u dołu ekranu
  3. Jeśli terminal NIE jest otwarty, użyj kombinacji klawiszy „Ctrl+”, aby otworzyć nowe okno terminala

Konfigurowanie gcloud

W Cloud Shell ustaw identyfikator projektu i region, w którym chcesz wdrożyć aplikację. Zapisz je jako zmienne PROJECT_ID i REGION.

export PROJECT_ID=$(gcloud config get-value project)
export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format='value(projectNumber)')

Skonfiguruj klaster i bazę danych GKE

  1. Pobierz skrypt konfiguracji i uruchom go.
wget https://raw.githubusercontent.com/GoogleCloudPlatform/container-developer-workshop/main/labs/nodejs/setup.sh
chmod +x setup.sh

Udostępnij infrastrukturę używaną w tym module

W tym module wdrożysz kod w GKE i uzyskasz dostęp do danych przechowywanych w bazie danych Spanner. Poniższy skrypt konfiguracji przygotowuje dla Ciebie tę infrastrukturę.

  1. Otwórz plik setup.sh i zmień wartości haseł, które są obecnie ustawione na CHANGEME
  2. Uruchom skrypt konfiguracji, aby utworzyć klaster GKE i bazę danych Cloud SQL, których użyjesz w tym module
./setup.sh
  1. W Cloud Shell utwórz nowy katalog o nazwie mynodejsapp
mkdir mynodejsapp
  1. Przejdź do tego katalogu i otwórz go jako obszar roboczy. Spowoduje to ponowne załadowanie edytora przez utworzenie konfiguracji obszaru roboczego w nowo utworzonym folderze.
cd mynodejsapp && cloudshell workspace .
  1. Zainstaluj Node i NPM za pomocą NVM.
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash
        
        # This loads nvm bash_completion
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"  

nvm install stable

nvm alias default stable

3. Utwórz nową aplikację startową

  1. Zainicjowanie aplikacji

Tworzę plik package.json, uruchamiając następujące polecenie

npm init
    Choose the entry point: (index.js) src/index.js and default values for the rest of the parameters. This will create the file with following contents
{
  "name": "mynodejsapp",
  "version": "1.0.0",
  "description": "",
  "main": "src/index.js",,
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}
  1. Dodawanie punktu wejścia

Edytuj ten plik, aby uwzględnić polecenie start w skrypcie "start": "node src/index.js",. Po zmianie skrypty powinny wyglądać tak, jak pokazano poniżej:

"scripts": {
    "start": "node src/index.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  1. Dodaj zależność ekspresową

Kod, który dodamy, również korzysta z zależności express, więc dodajmy tę zależność do tego pliku package.json. Po wszystkich zmianach plik package.json powinien wyglądać tak jak poniżej.

​​{
  "name": "mynodejsapp",
  "version": "1.0.0",
  "description": "",
  "main": "src/index.js",
  "scripts": {
    "start": "node src/index.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Your Name",
  "license": "ISC",
  "dependencies": {
    "express": "^4.16.4"
  }
}
  1. Tworzenie pliku index.js

Utwórz katalog źródłowy o nazwie src.

Utwórz plik src/index.js z tym kodem

const express = require('express');
const app = express();
const PORT = 8080;

app.get('/', (req, res) => {
    var message="Greetings from Node";
    res.send({ message: message });
  });

app.listen(PORT, () => {
  console.log(`Server running at: http://localhost:${PORT}/`);

});

Zwróć uwagę, że port ma wartość 8080

Generuj pliki manifestu

Skaffold udostępnia zintegrowane narzędzia, które upraszczają tworzenie kontenerów. W tym kroku zainicjujesz skaffold, który automatycznie utworzy podstawowe pliki YAML Kubernetes. Aby rozpocząć proces, wykonaj poniższe polecenie.

Wykonaj w terminalu to polecenie

skaffold init --generate-manifests

Gdy pojawi się komunikat:

  • Wpisz 8080 jako numer portu
  • Wpisz y, aby zapisać konfigurację.

Do obszaru roboczego zostaną dodane 2 pliki: skaffold.yaml i deployment.yaml

Zaktualizuj nazwę aplikacji

Domyślne wartości uwzględnione w konfiguracji nie są obecnie zgodne z nazwą Twojej aplikacji. Zaktualizuj pliki, aby odwoływały się do nazwy aplikacji zamiast do wartości domyślnych.

  1. Zmień wpisy w konfiguracji Skaffold
  • Otwórz: skaffold.yaml
  • Wybierz nazwę obrazu, który jest obecnie ustawiony jako package-json-image
  • Kliknij prawym przyciskiem myszy i wybierz Zmień wszystkie wystąpienia
  • Wpisz nową nazwę jako mynodejsapp
  1. Zmień wpisy w konfiguracji Kubernetes
  • Otwórz plik deployment.yaml
  • Wybierz nazwę obrazu, który jest obecnie ustawiony jako package-json-image
  • Kliknij prawym przyciskiem myszy i wybierz Zmień wszystkie wystąpienia
  • Wpisz nową nazwę jako mynodejsapp

Zwróć uwagę, że w pliku skaffold.yaml sekcja build używa buildpacks do skonteneryzowania aplikacji. Ten kod nie zawiera pliku Dockerfile, a deweloper nie potrzebuje dockera, aby skonteneryzować tę aplikację.

Ta konfiguracja skaffold włącza też automatycznie synchronizację na gorąco między edytorem a uruchomionym kontenerem. Włączenie synchronizacji „na gorąco” nie wymaga dodatkowej konfiguracji.

4. Omówienie procesu programowania

W tej sekcji zapoznasz się z kilkoma krokami korzystania z wtyczki Cloud Code, które pozwolą Ci poznać podstawowe procesy i sprawdzić konfigurację oraz konfigurację aplikacji startowej.

Cloud Code integruje się ze skaffold, aby usprawnić proces programowania. Gdy wdrożysz obraz kontenera w GKE w poniższych krokach, Cloud Code i Skaffold automatycznie skompilują obraz kontenera, wypchnie go do Container Registry, a następnie wdroży aplikację w GKE. Dzieje się to za kulisami, odbierając szczegóły od procesu deweloperskiego. Cloud Code usprawnia też proces programowania, udostępniając tradycyjne funkcje debugowania i synchronizacji przy użyciu kontenerów podczas programowania.

Wdróż w Kubernetes

  1. W panelu u dołu edytora Cloud Shell wybierz Cloud Code .

fdc797a769040839.png

  1. W panelu, który się pojawi, kliknij Uruchom w Kubernetes. W razie potrzeby wybierz Tak, aby użyć bieżącego kontekstu Kubernetes.

cfce0d11ef307087.png

  1. Przy pierwszym uruchomieniu polecenia u góry ekranu pojawi się prompt z pytaniem, czy chcesz uzyskać bieżący kontekst Kubernetes. Wybierz „Tak”. aby zaakceptować i wykorzystać bieżący kontekst.

817ee33b5b412ff8.png

  1. Pojawi się pytanie, którego rejestru kontenerów użyć. Naciśnij Enter, aby zaakceptować podaną wartość domyślną

eb4469aed97a25f6.png

  1. Wybierz kartę Wyniki w dolnym panelu, aby zobaczyć postęp i powiadomienia.

f95b620569ba96c5.png

  1. Wybierz „Kubernetes: Run/Debug - detail”. w menu kanału po prawej stronie, aby wyświetlić dodatkowe szczegóły i logi, które są przesyłane na żywo z kontenerów.

94acdcdda6d2108.png

  1. Wróć do widoku uproszczonego, wybierając „Kubernetes: Run/Debug”. z menu
  2. Po zakończeniu kompilacji i testów na karcie Dane wyjściowe będzie widoczny komunikat Resource deployment/mynodejsapp status completed successfully oraz adres URL: „Przekierowany adres URL z aplikacji demonstracyjnej usługi: http://localhost:8080”.
  3. W terminalu Cloud Code najedź kursorem na adres URL w danych wyjściowych (http://localhost:8080), a następnie w wyświetlonej wskazówce narzędzia wybierz Otwórz podgląd w przeglądarce.

Odpowiedź będzie:

{"message":"Greetings from Node"}

Ponowne załadowanie „na gorąco”

  1. Wejdź na src/index.js. Zmień kod wiadomości powitalnej na 'Hello from Node'

Od razu zauważysz, że w oknie Output, widoku Kubernetes: Run/Debug obserwator synchronizuje zaktualizowane pliki z kontenerem w Kubernetes.

Update initiated
File sync started for 1 files for gcr.io/myproject/mynodejsapp:latest@sha256:f554756b3b4d6c301c4b26ef96102227cfa2833270db56241248ae42baa1971a
File sync succeeded for 1 files for gcr.io/myproject/mynodejsapp:latest@sha256:f554756b3b4d6c301c4b26ef96102227cfa2833270db56241248ae42baa1971a
Update succeeded
  1. Jeśli przełączysz się na widok Kubernetes: Run/Debug - Detailed, zauważysz, że rozpozna on zmiany w plikach i ponownie uruchomi węzeł
files modified: [src/index.js]
Copying files:map[src/index.js:[/workspace/src/index.js]]togcr.io/myproject/mynodejsapp:latest@sha256:f554756b3b4d6c301c4b26ef96102227cfa2833270db56241248ae42baa1971a
Syncing 1 files for gcr.io/myproject/mynodejsapp:latest@sha256:f554756b3b4d6c301c4b26ef96102227cfa2833270db56241248ae42baa1971a
Watching for changes...
[mynodejsapp]
[mynodejsapp]> mynodejsapp@1.0.0 start /workspace
[mynodejsapp]> node src/index.js
[mynodejsapp]
[mynodejsapp]Server running at: http://localhost:8080/
  1. Aby zobaczyć zaktualizowane wyniki, odśwież przeglądarkę.

Debugowanie

  1. Otwórz widok debugowania i zatrzymaj bieżący wątek 647213126d7a4c7b.png.
  2. Kliknij Cloud Code w dolnym menu i wybierz Debug on Kubernetes, aby uruchomić aplikację w trybie debug.
  • W widoku Kubernetes Run/Debug - Detailed okna Output zwróć uwagę, że skaffold wdroży tę aplikację w trybie debugowania.
  • Skompilowanie i wdrożenie aplikacji może potrwać kilka minut. Tym razem będziesz mieć włączony debuger.
Port forwarding pod/mynodejsapp-6bbcf847cd-vqr6v in namespace default, remote port 9229 -> http://127.0.0.1:9229
[mynodejsapp]Debugger attached.
  1. Kolor dolnego paska stanu zmieni się z niebieskiego na pomarańczowy, co oznacza, że urządzenie działa w trybie debugowania.
  2. Zwróć uwagę na to, że w widoku Kubernetes Run/Debug został uruchomiony kontener z możliwością debugowania.
**************URLs*****************
Forwarded URL from service mynodejsapp-service: http://localhost:8080
Debuggable container started pod/mynodejsapp-deployment-6bc7598798-xl9kj:mynodejsapp (default)
Update succeeded
***********************************

Wykorzystuj punkty przerwania

  1. Otwórz: src/index.js
  2. Znajdź instrukcję, która brzmi: var message="Greetings from Node";
  3. Dodaj do tego wiersza punkt przerwania, klikając puste miejsce po lewej stronie numeru wiersza. Pojawi się czerwony wskaźnik informujący o ustawieniu punktu przerwania
  4. Załaduj ponownie przeglądarkę. Pamiętaj, że debuger zatrzymuje proces w punkcie przerwania i umożliwia zbadanie zmiennych oraz stanu aplikacji uruchomionej zdalnie w GKE.
  5. Przejdź do sekcji zmiennych, aż znajdziesz zmienną "message".
  6. Wykonaj linię, naciskając przycisk Przejdź nad 7cfdee4fd6ef5c3a.png
  7. Obserwuj bieżącą zmianę zmiennej "message" na "Greetings from Node"
  8. Kliknij dwukrotnie zmienną o nazwie „target”. i w wyskakującym okienku zmień wartość na inną, np. "Hello from Node".
  9. Kliknij przycisk Dalej w panelu sterowania debugowania.
  10. Sprawdź odpowiedź w przeglądarce, w której wyświetla się wprowadzona przed chwilą zaktualizowana wartość.
  11. Zatrzymaj „Debugowanie” naciśnij przycisk zatrzymania 647213126d7a4c7b.png i usuń punkt przerwania, ponownie klikając go.

5. Opracowanie prostej usługi CRUD Rest Service

Na tym etapie Twoja aplikacja jest w pełni skonfigurowana do programowania skonteneryzowanego i masz już za sobą podstawowy przepływ pracy programistyczny w Cloud Code. W kolejnych sekcjach przećwiczysz zdobyte informacje, dodając punkty końcowe usługi spoczynkowej łączące się z zarządzaną bazą danych w Google Cloud.

Skonfiguruj zależności

Kod aplikacji używa bazy danych do utrwalania danych usługi reszty. Zapewnij dostępność zależności, dodając w pliku package.json ten kod

  1. Dodaj jeszcze 2 zależności pg i sequelize do pliku package.json, aby utworzyć aplikację CRUD Postgres. Po wprowadzeniu zmian sekcja zależności będzie wyglądać tak.
    "dependencies": {
    "express": "^4.16.4",
    "pg": "^8.7.3",
    "sequelize": "^6.17.0"
  }

Kodowanie usługi REST

  1. Dodaj kod CRUD do tej aplikacji
wget -O app.zip https://github.com/GoogleCloudPlatform/container-developer-workshop/raw/main/labs/nodejs/app.zip

unzip app.zip

Ten kod zawiera

  • Folder models z modelem encji item
  • folder controllers z kodem, który wykonuje operacje CRUD
  • trasuje folder, który kieruje określone wzorce adresów URL do różnych wywołań.
  • folder config ze szczegółami połączenia z bazą danych
  1. Pamiętaj, że konfiguracja bazy danych w pliku db.config.js odnosi się do zmiennych środowiskowych, które muszą być podane, aby możliwe było połączenie z bazą danych. Musisz również przeanalizować przychodzące żądanie dotyczące kodowania adresów URL.
  2. Dodaj w polu src/index.js ten fragment kodu, aby utworzyć połączenie z kodem CRUD z głównego pliku JavaScript tuż przed ostatnią sekcją, która zaczyna się od app.listen(PORT, () => {
const bodyParser = require('body-parser')
app.use(bodyParser.json())
app.use(
 bodyParser.urlencoded({
   extended: true,
 })
)
const db = require("../app/models");
db.sequelize.sync();
require("../app/routes/item.routes")(app);
  1. Zmodyfikuj wdrożenie w pliku deployment.yaml, aby dodać zmienne środowiskowe służące do dostarczania informacji o połączeniach z bazą danych.

Zaktualizuj wpis specyfikacji na końcu pliku, aby był zgodny z tą definicją

    spec:
      containers:
      - name: mynodejsapp
        image: mynodejsapp
        env:
        - name: DB_HOST
          value: ${DB_INSTANCE_IP}        
        - name: DB_PORT
          value: "5432"  
        - name: DB_USER
          valueFrom:
            secretKeyRef:
              name: gke-cloud-sql-secrets
              key: username
        - name: DB_PASS
          valueFrom:
            secretKeyRef:
              name: gke-cloud-sql-secrets
              key: password
        - name: DB_NAME
          valueFrom:
            secretKeyRef:
              name: gke-cloud-sql-secrets
              key: database
  1. Zastąp wartość DB_HOST adresem swojej bazy danych
export DB_INSTANCE_IP=$(gcloud sql instances describe mytest-instance \
    --format=json | jq \
    --raw-output ".ipAddresses[].ipAddress")

envsubst < deployment.yaml > deployment.new && mv deployment.new deployment.yaml

Wdróż i zweryfikuj aplikację

  1. W panelu u dołu edytora Cloud Shell kliknij Cloud Code, a następnie wybierz Debug on Kubernetes u góry ekranu.
  2. Po zakończeniu kompilacji i testów na karcie Dane wyjściowe będzie widoczny komunikat Resource deployment/mynodejsapp status completed successfully oraz adres URL: „Przekierowany adres URL z usługi mynodejsapp: http://localhost:8080”.
  3. Dodaj kilka elementów.

W terminalu Cloud Shell uruchom poniższe polecenia

URL=localhost:8080
curl -X POST $URL/items -d '{"itemName":"Body Spray", "itemPrice":3.2}' -H "Content-Type: application/json"
curl -X POST $URL/items -d '{"itemName":"Nail Cutter", "itemPrice":2.5}' -H "Content-Type: application/json"
  1. Przetestuj metodę GET, uruchamiając w przeglądarce parametr $URL/items. Możesz też uruchomić curl z wiersza poleceń
curl -X GET $URL/items
  1. Testowanie usuwania: teraz spróbuj usunąć element poprzez jego uruchomienie. W razie potrzeby zmień wartość parametru item-id.
curl -X DELETE $URL/items/1
    This throws an error message
{"message":"Could not delete Item with id=[object Object]"}

Zidentyfikuj i rozwiąż problem

  1. Uruchom aplikację ponownie w trybie debugowania i znajdź problem. Oto kilka porad:
  • Wiemy, że coś jest nie tak z funkcją DELETE, ponieważ nie zwraca ona oczekiwanych wyników. Punkt przerwania ustawia się więc w metodzie itemcontroller.js->exports.delete.
  • Uruchom wykonanie krok po kroku i obserwuj zmienne w każdym kroku, aby obserwować wartości zmiennych lokalnych w lewym oknie.
  • Aby obserwować określone wartości, takie jak request.params, dodaj tę zmienną do okna odtwarzania filmu.
  1. Zwróć uwagę, że atrybut id ma wartość undefined. Zmień kod, aby rozwiązać problem.

Poprawiony fragment kodu będzie wyglądać tak.

// Delete a Item with the specified id in the request
exports.delete = (req, res) => {
    const id = req.params.id;
  1. Po ponownym uruchomieniu aplikacji przetestuj ją jeszcze raz, próbując ją usunąć.
  2. Zatrzymaj sesję debugowania, klikając czerwony kwadrat 647213126d7a4c7b.png na pasku narzędzi debugowania

6. Czyszczenie

Gratulacje! W tym module udało Ci się utworzyć od zera nową aplikację Nodejs i skonfigurować ją do pracy w trybie wdrażania „gorące” z kontenerami. Następnie wdrożono i debugowałeś(-aś) aplikację w zdalnym klastrze GKE, postępując zgodnie z procedurą programistyczną obowiązującą w tradycyjnych stosach aplikacji.

Aby posprzątać po ukończeniu modułu:

  1. Usuń pliki używane w module
cd ~ && rm -rf mynodejsapp && rm -f setup.sh
  1. Usuń projekt, aby usunąć całą powiązaną infrastrukturę i zasoby