Разработка InnerLoop с помощью NodeJS

1. Обзор

В этой лабораторной работе демонстрируются функции и возможности, разработанные для оптимизации рабочего процесса разработки для инженеров-программистов, занимающихся разработкой приложений NodeJS в контейнеризированной среде. Типичная разработка в контейнерах требует от пользователя понимания деталей контейнеров и процесса сборки контейнеров. Кроме того, разработчикам обычно приходится прерывать свой рабочий процесс, выходя из IDE для тестирования и отладки своих приложений в удаленных средах. С помощью инструментов и технологий, упомянутых в этом руководстве, разработчики могут эффективно работать с контейнеризированными приложениями, не покидая свою IDE.

Что вы узнаете

В этой лабораторной работе вы изучите методы разработки с использованием контейнеров в GCP, в том числе:

  • Создание стартового приложения Nodejs
  • Настройка приложения Nodejs для разработки в контейнерах
  • Разработка простого REST-сервиса для операций CRUD (операции чтения-выполнения)
  • Развертывание в GKE
  • Отладка состояния ошибки
  • Использование точек останова / логов
  • Горячее развертывание изменений обратно в GKE
  • Дополнительно: интеграция CloudSQL для сохранения данных на бэкэнде.

2. Настройка и требования

Настройка среды для самостоятельного обучения

  1. Войдите в консоль Google Cloud и создайте новый проект или используйте существующий. Если у вас еще нет учетной записи Gmail или Google Workspace, вам необходимо ее создать .

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • Название проекта — это отображаемое имя участников данного проекта. Это строка символов, не используемая API Google, и вы можете изменить её в любое время.
  • Идентификатор проекта должен быть уникальным для всех проектов Google Cloud и неизменяемым (его нельзя изменить после установки). Консоль Cloud автоматически генерирует уникальную строку; обычно вам неважно, какая она. В большинстве практических заданий вам потребуется указать идентификатор проекта (обычно он обозначается как PROJECT_ID ), поэтому, если он вам не нравится, сгенерируйте другой случайный идентификатор или попробуйте свой собственный и посмотрите, доступен ли он. Затем он "замораживается" после создания проекта.
  • Существует третье значение — номер проекта , который используется некоторыми API. Подробнее обо всех трех значениях можно узнать в документации .
  1. Далее вам потребуется включить оплату в консоли Cloud, чтобы использовать ресурсы/API Cloud. Выполнение этого практического задания не должно стоить дорого, если вообще что-либо. Чтобы отключить ресурсы и избежать дополнительных расходов после завершения этого урока, следуйте инструкциям по «очистке», приведенным в конце практического задания. Новые пользователи Google Cloud имеют право на бесплатную пробную версию стоимостью 300 долларов США .

Запустить редактор Cloudshell

Данная лабораторная работа разработана и протестирована для использования с редактором Google Cloud Shell. Для доступа к редактору,

  1. Получите доступ к своему проекту Google по адресу https://console.cloud.google.com .
  2. В правом верхнем углу нажмите на значок редактора облачной оболочки.

8560cc8d45e8c112.png

  1. В нижней части вашего окна откроется новое окно.
  2. Нажмите кнопку «Открыть редактор».

9e504cb98a6a8005.png

  1. В начале редактора справа будет изображен исследователь, а в центре — сам редактор.
  2. В нижней части экрана также должна быть доступна панель терминала.
  3. Если терминал НЕ открыт, используйте комбинацию клавиш `Ctrl+`, чтобы открыть новое окно терминала.

Настройте gcloud

В Cloud Shell укажите идентификатор проекта и регион, в который вы хотите развернуть приложение. Сохраните их как переменные PROJECT_ID и REGION .

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

Настройка кластера GKE и базы данных.

  1. Скачайте установочный скрипт и сделайте его исполняемым.
wget https://raw.githubusercontent.com/GoogleCloudPlatform/container-developer-workshop/main/labs/nodejs/setup.sh
chmod +x setup.sh

Обеспечьте наличие инфраструктуры, используемой в этой лаборатории.

В этой лабораторной работе вы развернете код в GKE и получите доступ к данным, хранящимся в базе данных Spanner. Приведенный ниже скрипт настройки подготовит для вас эту инфраструктуру.

  1. Откройте файл setup.sh и отредактируйте значения паролей, которые в данный момент установлены на CHANGEME.
  2. Запустите скрипт настройки, чтобы развернуть кластер GKE и базу данных CloudSQL, которые вы будете использовать в этой лабораторной работе.
./setup.sh
  1. В Cloud Shell создайте новую директорию с именем mynodejsapp
mkdir mynodejsapp
  1. Перейдите в этот каталог и откройте его как рабочую область. Это перезагрузит редактор, создав конфигурацию рабочей области в только что созданной папке.
cd mynodejsapp && cloudshell workspace .
  1. Установите Node и NPM с помощью 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. Создайте новое стартовое приложение.

  1. Инициализируйте приложение.

Создание файла package.json путем выполнения следующей команды.

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. Добавить точку входа

Отредактируйте этот файл, добавив команду запуска в скрипт "start": "node src/index.js", . После внесения изменений скрипты должны выглядеть как в приведенном ниже фрагменте кода:

"scripts": {
    "start": "node src/index.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  1. Добавьте зависимость Express.

Код, который мы собираемся добавить, также использует express поэтому давайте добавим эту зависимость в файл package.json . Таким образом, после всех изменений файл package.json должен выглядеть так, как показано ниже.

​​{
  "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. Создайте файл index.js.

Создайте исходный каталог с именем src.

Создайте файл src/index.js со следующим кодом.

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}/`);

});

Обратите внимание, что для параметра PORT установлено значение 8080

Создать манифесты

Skaffold предоставляет интегрированные инструменты для упрощения разработки контейнеров. На этом шаге вы инициализируете Skaffold, который автоматически создаст базовые YAML-файлы Kubernetes. Выполните команду ниже, чтобы начать процесс.

Выполните следующую команду в терминале.

skaffold init --generate-manifests

При появлении запроса:

  • Введите 8080 для порта.
  • Введите y для сохранения конфигурации.

В рабочую область добавлены два файла: skaffold.yaml и deployment.yaml

Обновить название приложения

Значения по умолчанию, указанные в конфигурации, в настоящее время не соответствуют названию вашего приложения. Обновите файлы, чтобы они ссылались на название вашего приложения, а не на значения по умолчанию.

  1. Измените записи в конфигурации Skaffold.
  • Откройте skaffold.yaml
  • Выберите имя изображения, которое в данный момент задано как package-json-image
  • Щелкните правой кнопкой мыши и выберите «Изменить все вхождения».
  • Введите новое имя как mynodejsapp
  1. Измените записи в конфигурации Kubernetes.
  • Откройте файл deployment.yaml
  • Выберите имя изображения, которое в данный момент задано как package-json-image
  • Щелкните правой кнопкой мыши и выберите «Изменить все вхождения».
  • Введите новое имя как mynodejsapp

Обратите внимание, что в файле skaffold.yaml раздел build использует buildpacks для контейнеризации приложения. В этом коде нет Dockerfile, и разработчику не требуется никаких знаний о Docker для контейнеризации этого приложения.

Кроме того, данная конфигурация Skaffold автоматически включает синхронизацию между редактором и запущенным контейнером. Для включения синхронизации дополнительная настройка не требуется.

4. Обзор процесса разработки.

В этом разделе вы шаг за шагом изучите основные процессы с помощью плагина Cloud Code, а также проверите конфигурацию и настройку вашего стартового приложения.

Cloud Code интегрируется со Skaffold для оптимизации процесса разработки. При развертывании в GKE на следующих этапах Cloud Code и Skaffold автоматически создадут образ контейнера, загрузят его в реестр контейнеров, а затем развернут ваше приложение в GKE. Это происходит в фоновом режиме, абстрагируя детали от процесса разработки. Cloud Code также улучшает процесс разработки, предоставляя традиционные возможности отладки и синхронизации для разработки на основе контейнеров.

Развертывание в Kubernetes

  1. В нижней части окна редактора Cloud Shell выберите Cloud Code.

fdc797a769040839.png

  1. В появившейся вверху панели выберите «Запустить в Kubernetes» . Если появится запрос, выберите «Да», чтобы использовать текущий контекст Kubernetes.

cfce0d11ef307087.png

  1. При первом запуске команды в верхней части экрана появится запрос, спрашивающий, хотите ли вы использовать текущий контекст Kubernetes. Выберите «Да», чтобы принять запрос и использовать текущий контекст.

817ee33b5b412ff8.png

  1. Далее появится запрос о том, какой реестр контейнеров использовать. Нажмите Enter, чтобы принять предоставленное значение по умолчанию.

eb4469aed97a25f6.png

  1. Чтобы просмотреть ход выполнения и уведомления, выберите вкладку «Вывод» в нижней панели.

f95b620569ba96c5.png

  1. Выберите «Kubernetes: Запуск/Отладка — Подробная информация» в раскрывающемся списке каналов справа, чтобы просмотреть дополнительные сведения и журналы, транслируемые в режиме реального времени из контейнеров.

94acdcdda6d2108.png

  1. Вернитесь к упрощенному представлению, выбрав в раскрывающемся списке «Kubernetes: Run/Debug».
  2. После завершения сборки и тестирования на вкладке «Вывод» отображается сообщение: Resource deployment/mynodejsapp status completed successfully , а также URL-адрес: «Перенаправленный URL-адрес из сервиса demo-app: http://localhost:8080».
  3. В терминале Cloud Code наведите курсор на URL-адрес в выводе (http://localhost:8080), а затем во всплывающей подсказке выберите «Открыть предварительный просмотр веб-страницы».

Ответ будет следующим:

{"message":"Greetings from Node"}

Горячая перезарядка

  1. Перейдите в src/index.js . Отредактируйте код, заменив приветственное сообщение на 'Hello from Node'

Обратите внимание, что в окне Output , в представлении Kubernetes: Run/Debug , наблюдатель синхронизирует обновленные файлы с контейнером в 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. Если вы переключитесь на Kubernetes: Run/Debug - Detailed просмотр, вы заметите, что он распознает изменения файлов и перезапускает узел.
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. Обновите страницу в браузере, чтобы увидеть обновленные результаты.

Отладка

  1. Перейдите в режим отладки и остановите текущий поток. 647213126d7a4c7b.png .
  2. В нижнем меню нажмите на Cloud Code и выберите Debug on Kubernetes , чтобы запустить приложение в режиме debug .
  • В окне «Подробный просмотр Output Kubernetes Run/Debug - Detailed обратите внимание, что skaffold развернет это приложение в режиме отладки.
  • Сборка и развертывание приложения займут несколько минут. На этот раз вы заметите, что отладчик подключен.
Port forwarding pod/mynodejsapp-6bbcf847cd-vqr6v in namespace default, remote port 9229 -> http://127.0.0.1:9229
[mynodejsapp]Debugger attached.
  1. Цвет нижней строки состояния меняется с синего на оранжевый, указывая на то, что устройство находится в режиме отладки.
  2. В окне Kubernetes Run/Debug обратите внимание, что запущен отлаживаемый контейнер.
**************URLs*****************
Forwarded URL from service mynodejsapp-service: http://localhost:8080
Debuggable container started pod/mynodejsapp-deployment-6bc7598798-xl9kj:mynodejsapp (default)
Update succeeded
***********************************

Используйте точки останова

  1. Откройте файл src/index.js
  2. Найдите оператор, который выглядит следующим образом var message="Greetings from Node";
  3. Установите точку останова на этой строке, щелкнув по пустому месту слева от номера строки. Красный индикатор покажет, что точка останова установлена.
  4. Перезагрузите браузер и обратите внимание, что отладчик останавливает процесс в точке останова и позволяет вам исследовать переменные и состояние приложения, работающего удаленно в GKE.
  5. Прокрутите вниз в раздел переменных, пока не найдете переменную "message" .
  6. Выполните строку, нажав кнопку «Шаг через». 7cfdee4fd6ef5c3a.png
  7. Обратите внимание, что текущее значение переменной "message" изменилось на "Greetings from Node"
  8. Дважды щелкните по имени переменной "target" и во всплывающем окне измените значение на что-нибудь другое, например, "Hello from Node"
  9. Нажмите кнопку «Продолжить» на панели управления отладкой.
  10. Проверьте ответ в браузере, где теперь отображается обновленное значение, которое вы только что ввели.
  11. Остановите режим отладки, нажав кнопку «Стоп». 647213126d7a4c7b.png и снимите точку останова, снова щелкнув по ней.

5. Разработка простого REST-сервиса с операциями CRUD.

На этом этапе ваше приложение полностью настроено для контейнерной разработки, и вы прошли базовый рабочий процесс разработки с помощью Cloud Code. В следующих разделах вы попрактикуетесь в применении полученных знаний, добавив конечные точки REST-сервиса, подключающиеся к управляемой базе данных в Google Cloud.

Настройка зависимостей

Код приложения использует базу данных для сохранения данных REST-сервиса. Убедитесь в наличии зависимостей, добавив следующее в файл package.json

  1. Добавьте еще две зависимости: pg и sequelize в файл package.json , чтобы создать CRUD-приложение на базе PostgreSQL. После внесения изменений раздел зависимостей будет выглядеть следующим образом.
    "dependencies": {
    "express": "^4.16.4",
    "pg": "^8.7.3",
    "sequelize": "^6.17.0"
  }

Напишите код для REST-сервиса

  1. Добавьте код CRUD-приложения в это приложение.
wget -O app.zip https://github.com/GoogleCloudPlatform/container-developer-workshop/raw/main/labs/nodejs/app.zip

unzip app.zip

Этот код имеет

  • Папка models содержит модель сущности для item
  • Папка controllers содержит код, выполняющий операции CRUD (операции чтения-вывода, чтения-записи, удаления и сохранения).
  • Папка маршрутов , которая перенаправляет определенные шаблоны URL-адресов на различные вызовы.
  • Папка config с информацией о подключении к базе данных.
  1. Обратите внимание, что конфигурация базы данных в файле db.config.js относится к переменным среды, которые необходимо указать для подключения к базе данных. Также необходимо проверить входящий запрос на кодировку URL.
  2. Добавьте следующий фрагмент кода в src/index.js , чтобы иметь возможность подключаться к CRUD-коду из вашего основного JavaScript-файла, непосредственно перед последним разделом, начинающимся с 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. Отредактируйте файл deployment.yaml , добавив переменные среды для предоставления информации о подключении к базе данных.

Обновите запись спецификации в конце файла, чтобы она соответствовала следующему определению.

    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. Замените значение DB_HOST адресом вашей базы данных.
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

Развертывание и проверка приложения

  1. В нижней части окна редактора Cloud Shell выберите Cloud Code , а затем в верхней части экрана выберите Debug on Kubernetes .
  2. После завершения сборки и тестирования на вкладке «Вывод» отображается сообщение: Resource deployment/mynodejsapp status completed successfully , а также указан URL-адрес: «Перенаправленный URL-адрес из сервиса mynodejsapp: http://localhost:8080».
  3. Добавьте пару предметов.

В терминале CloudShell выполните следующие команды.

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. Проверьте правильность выполнения запроса GET, запустив команду `$URL/items` в браузере. Также можно запустить curl из командной строки.
curl -X GET $URL/items
  1. Тестовое удаление: Теперь попробуйте удалить элемент, запустив команду. При необходимости измените значение item-id.
curl -X DELETE $URL/items/1
    This throws an error message
{"message":"Could not delete Item with id=[object Object]"}

Выявите и устраните проблему.

  1. Перезапустите приложение в режиме отладки и найдите проблему. Вот несколько советов:
  • Мы знаем, что что-то не так с оператором DELETE, поскольку он не возвращает желаемый результат. Поэтому вам следует установить точку останова в методе exports.delete в файле itemcontroller.js .
  • Выполните пошаговое выполнение программы и наблюдайте за переменными на каждом шаге, чтобы увидеть значения локальных переменных в левом окне.
  • Чтобы отслеживать определенные значения, такие как request.params добавьте эту переменную в окно «Отслеживание».
  1. Обратите внимание, что значение, присвоенное переменной id , undefined . Измените код, чтобы исправить эту проблему.

Исправленный фрагмент кода будет выглядеть так.

// Delete a Item with the specified id in the request
exports.delete = (req, res) => {
    const id = req.params.id;
  1. После перезапуска приложения проверьте еще раз, попробовав удалить файл.
  2. Остановите сеанс отладки, нажав на красный квадрат на панели инструментов отладки. 647213126d7a4c7b.png

6. Уборка

Поздравляем! В этой лабораторной работе вы создали новое приложение Nodejs с нуля и настроили его для работы в режиме «горячего развертывания» с использованием контейнеров. Затем вы развернули и отладили свое приложение в удаленном кластере GKE, следуя тому же процессу разработки, что и в традиционных стеках приложений.

После завершения лабораторной работы необходимо провести уборку:

  1. Удалите файлы, использованные в лабораторной работе.
cd ~ && rm -rf mynodejsapp && rm -f setup.sh
  1. Удалите проект, чтобы удалить всю связанную с ним инфраструктуру и ресурсы.