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

1. Обзор

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

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

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

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

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

Самостоятельная настройка среды

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

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • Имя проекта — это отображаемое имя для участников этого проекта. Это строка символов, не используемая API Google, и вы можете обновить ее в любое время.
  • Идентификатор проекта должен быть уникальным для всех проектов Google Cloud и неизменяемым (нельзя изменить после его установки). Cloud Console автоматически генерирует уникальную строку; обычно тебя не волнует, что это такое. В большинстве лабораторий кода вам потребуется указать идентификатор проекта (обычно он обозначается как PROJECT_ID ), поэтому, если он вам не нравится, создайте другой случайный идентификатор или попробуйте свой собственный и посмотрите, доступен ли он. Затем он «замораживается» после создания проекта.
  • Существует третье значение — номер проекта , который используют некоторые API. Подробнее обо всех трех этих значениях читайте в документации .
  1. Затем вам необходимо включить выставление счетов в Cloud Console, чтобы использовать облачные ресурсы/API. Прохождение этой лаборатории кода не должно стоить много, если вообще стоит. Чтобы отключить ресурсы и не платить за выставление счетов за пределами этого руководства, следуйте инструкциям по «очистке», которые можно найти в конце лаборатории кода. Новые пользователи 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 , поэтому давайте добавим эту зависимость в этот файл 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 предоставляет интегрированные инструменты для упрощения разработки контейнеров. На этом этапе вы инициализируете скаффолд, который автоматически создаст базовые 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 для контейнеризации этого приложения.

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

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: Run/Debug — Detailed» в раскрывающемся списке каналов справа, чтобы просмотреть дополнительные сведения и журналы, транслируемые в реальном времени из контейнеров.

94acdcdda6d2108.png

  1. Вернитесь к упрощенному представлению, выбрав «Kubernetes: Run/Debug» в раскрывающемся списке.
  2. Когда сборка и тесты завершены, на вкладке «Вывод» отображается сообщение: Resource deployment/mynodejsapp status completed successfully » и отображается URL-адрес: «Перенаправленный URL-адрес из демонстрационного приложения службы: 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 .
  • Обратите внимание, что в окне Kubernetes Run/Debug - Detailed представление Output » 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. Разработка простой службы отдыха CRUD

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

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

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

  1. Добавьте еще две зависимости pg и sequelize в файл package.json , чтобы создать Postgres CRUD-приложение. После внесения изменений раздел зависимостей будет выглядеть так.
    "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

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

  • папка моделей с моделью объекта для item
  • папка контроллеров с кодом, выполняющим операции 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 что-то не так, поскольку она не возвращает желаемый результат. Итак, вы должны установить точку останова в методе itemcontroller.js -> exports.delete .
  • Запустите пошаговое выполнение и наблюдайте за переменными на каждом шаге, чтобы увидеть значения локальных переменных в левом окне.
  • Чтобы наблюдать за конкретными значениями, такими как 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. Удалите проект, чтобы удалить всю связанную инфраструктуру и ресурсы.