Sebastian_B
Sebastian_B

Reputation: 61

Cant create VM instance from artifact image via node sdk

I am trying to create a VM instance based on a artifact image which works fine in the console and creating VM instances works as well via the sdk even attaching the image works even tho this is no public api via the metadata but as soon as I define service accounts the instance will be created and deleted right away. The retuned result form that all is the same and look just as a successful one. without the service account defined it works fine but I need them to access the image.

I am not using the GKE as I dont need the managed stuff around it and feel like this way will be more cost efficient and the instance is fixed and doesnt need to scale

import express, { Request, Response } from "express";
import { InstancesClient } from "@google-cloud/compute";

const app = express();
const port = process.env.PORT || 3000;

// Initialize the Google Cloud Compute client
const instancesClient = new InstancesClient({
  keyFilename: "./src/service-account.json",
});

app.use(express.json());

app.post("/create-vm", async (req: Request, res: Response) => {
  try {
    const { name, zone, machineType, sourceImage } = req.body;

    const instanceName = "dummy-service-v8";
    const result = await instancesClient.insert({
      project: "stellar-cumulus-******-n4",
      zone: "us-central1-a",
      instanceResource: {
        name: instanceName,
        machineType: "zones/us-central1-a/machineTypes/e2-micro",
        tags: {
          items: ["p3000"],
        },
        disks: [
          {
            boot: true,
            autoDelete: true,
            initializeParams: {
              diskName: instanceName + "-disk",
              diskSizeGb: 10,
              diskType:
                "projects/stellar-cumulus-******-n4/zones/us-central1-a/diskTypes/pd-balanced",
              labels: {},
              sourceImage:
                "projects/cos-cloud/global/images/cos-stable-117-18613-0-79",
            },
          },
        ],
        labels: {
          "goog-ec-src": "vm_add-rest",
          "container-vm": "cos-stable-117-18613-0-79",
        },
        serviceAccounts: [
          {
            email: "*********[email protected]",
            scopes: ["https://www.googleapis.com/auth/cloud-platform"],
          },
        ],
        metadata: {
          items: [
            {
              key: "gce-container-declaration",
              value: `spec:\n  containers:\n  - name: ${instanceName}\n    image: us-central1-docker.pkg.dev/stellar-cumulus-******-n4/dummy-service/dummy-service:v8\n    stdin: false\n    tty: false\n  restartPolicy: Always\n# This container declaration format is not public API and may change without notice. Please\n# use gcloud command-line tool or Google Cloud Console to run Containers on Google Compute Engine.`,
            },
          ],
        },
        networkInterfaces: [
          {
            accessConfigs: [
              {
                name: "External NAT",
                networkTier: "PREMIUM",
              },
            ],
            stackType: "IPV4_ONLY",
            subnetwork:
              "projects/stellar-cumulus-******-n4/regions/us-central1/subnetworks/default",
          },
        ],
      },
    });

    res.json({ message: "VM created successfully", result });
  } catch (error) {
    console.error("Error creating VM:", error);
    res.status(500).json({ error: "Failed to create VM" });
  }
});

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

Upvotes: 0

Views: 61

Answers (1)

DazWilkin
DazWilkin

Reputation: 40296

Your Node.JS code mostly works for me.

BILLING="..."
PROJECT="..."
REGION="..."

gcloud projects create ${PROJECT}

gcloud billing projects link ${PROJECT} \
--billing-account=${BILLING}

gcloud services enable compute.googleapis.com \
--project=${PROJECT}

package.json:

{
  "name": "79093452",
  "version": "0.0.1",
  "type": "commonjs",
  "main": "index.js",
  "dependencies": {
    "@google-cloud/compute": "^4.9.0",
    "express": "^4.21.2"
  }
}

index.js:

const express = require("express");

const { InstancesClient } = require("@google-cloud/compute");

const app = express();
const port = process.env.PORT || 3000;

//const KEY = process.env.KEY;
const PROJECT = process.env.PROJECT;
const NUMBER = process.env.NUMBER;
const REGION = process.env.REGION;
const IMAGE = process.env.IMAGE;

// Initialize the Google Cloud Compute client
const instancesClient = new InstancesClient({
//  keyFilename: KEY,
});

app.use(express.json());
app.post("/create-vm", async (req, res) => {
  try {
    const { name, zone, machineType, sourceImage } = req.body;

    const result = await instancesClient.insert({
      project: PROJECT,
      zone: zone,
      instanceResource: {
        name: name,
        machineType: `zones/${zone}/machineTypes/${machineType}`,
        tags: {
          items: ["p3000"],
        },
        disks: [
          {
            boot: true,
            autoDelete: true,
            initializeParams: {
              diskName: `${name}-disk`,
              diskSizeGb: 10,
              diskType: `projects/${PROJECT}/zones/${zone}/diskTypes/pd-balanced`,
              labels: {},
              sourceImage: `projects/cos-cloud/global/images/${sourceImage}`,
            },
          },
        ],
        labels: {
          "goog-ec-src": "vm_add-rest",
          "container-vm": sourceImage,
        },
        serviceAccounts: [
          {
            email: `${NUMBER}[email protected]`,
            scopes: ["https://www.googleapis.com/auth/cloud-platform"],
          },
        ],
        metadata: {
          items: [
            {
              key: "gce-container-declaration",
              value: `spec:\n  containers:\n  - name: ${name}\n    image: ${IMAGE}\n    stdin: false\n    tty: false\n  restartPolicy: Always`
            },
          ],
        },
        networkInterfaces: [
          {
            accessConfigs: [
              {
                name: "External NAT",
                networkTier: "PREMIUM",
              },
            ],
            stackType: "IPV4_ONLY",
            subnetwork: `projects/${PROJECT}/regions/${REGION}/subnetworks/default`,
          },
        ],
      },
    });

    res.json({ message: "VM created successfully", result });
  } catch (error) {
    console.error("Error creating VM:", error);
    res.status(500).json({ error: "Failed to create VM" });
  }
});

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

Run:

IMAGE="gcr.io/kuar-demo/kuard-amd64:blue"

PROJECT=${PROJECT} \
NUMBER=$(\
  gcloud projects describe ${PROJECT} \
  --format="value(projectNumber)") \
REGION=${REGION} \
IMAGE=${IMAGE} \
node index.js

Then:

NAME="..."
ZONE="${REGION}-c"

curl \
--request POST \
--header "Content-Type: application/json" \
http://localhost:3000/create-vm \
-d "{
  \"name\":\"${NAME}\",
  \"zone\":\"${ZONE}\",
  \"machineType\":\"e2-micro\",
  \"sourceImage\":\"cos-stable-117-18613-0-79\"
}"

Then:

gcloud compute instances describe ${NAME} \
--zone=${ZONE} \
--project=${PROJECT} \
--format="value(status)"
RUNNING

And:

COMMAND='docker container ls --format="{{.Image}}"'

gcloud compute ssh ${NAME} \
--zone=${ZONE} \
--project=${PROJECT} \
--command="${COMMAND}"
gcr.io/kuar-demo/kuard-amd64:blue

Upvotes: 0

Related Questions