Как заставить экземпляр GCE остановиться, когда завершится его развернутый контейнер? - PullRequest
0 голосов
/ 10 октября 2018

У меня есть контейнер Docker, который выполняет одно большое вычисление.Это вычисление требует много памяти и занимает около 12 часов.

Я могу создать виртуальную машину Google Compute Engine соответствующего размера и использовать опцию «Развернуть образ контейнера на этом экземпляре виртуальной машины» для запуска этого задания.в совершенстве.Однако, как только задание завершено, контейнер закрывается, но виртуальная машина все еще работает (и заряжается).

Как заставить ВМ выйти / остановить / удалить при выходе из контейнера?

КогдаВиртуальная машина находится в режиме зомби, работают только контейнеры стековых драйверов:

$ docker ps
CONTAINER ID        IMAGE                                                                COMMAND                  CREATED             STATUS              PORTS               NAMES
bfa2feb03180        gcr.io/stackdriver-agents/stackdriver-logging-agent:0.2-1.5.33-1-1   "/entrypoint.sh /u..."   17 hours ago        Up 17 hours                             stackdriver-logging-agent
161439a487c2        gcr.io/stackdriver-agents/stackdriver-metadata-agent:0.2-0.0.17-2    "/bin/sh -c /opt/s..."   17 hours ago        Up 17 hours         8000/tcp            stackdriver-metadata-agent

Я создаю виртуальную машину следующим образом:

gcloud beta compute --project=abc instances create-with-container vm-name \
                    --zone=us-central1-c --machine-type=custom-1-65536-ext \
                    --network=default --network-tier=PREMIUM --metadata=google-logging-enabled=true \
                    --maintenance-policy=MIGRATE \
                    --service-account=xyz \
                    --scopes=https://www.googleapis.com/auth/cloud-platform \
                    --image=cos-stable-69-10895-71-0 --image-project=cos-cloud --boot-disk-size=10GB \
                    --boot-disk-type=pd-standard --boot-disk-device-name=vm-name \
                    --container-image=gcr.io/abc/my-image --container-restart-policy=on-failure \
                    --container-command=python3 \
                    --container-arg="a" --container-arg="b" --container-arg="c" \
                    --labels=container-vm=cos-stable-69-10895-71-0

Ответы [ 2 ]

0 голосов
/ 15 октября 2018

Я написал автономную функцию Python, основанную на ответе Винсента.

def kill_vm():
    """
    If we are running inside a GCE VM, kill it.
    """
    # based on https://stackoverflow.com/q/52748332/321772
    import json
    import logging
    import requests

    # get the token
    r = json.loads(
        requests.get("http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token",
                     headers={"Metadata-Flavor": "Google"})
            .text)

    token = r["access_token"]

    # get instance metadata
    # based on https://cloud.google.com/compute/docs/storing-retrieving-metadata
    project_id = requests.get("http://metadata.google.internal/computeMetadata/v1/project/project-id",
                              headers={"Metadata-Flavor": "Google"}).text

    name = requests.get("http://metadata.google.internal/computeMetadata/v1/instance/name",
                        headers={"Metadata-Flavor": "Google"}).text

    zone_long = requests.get("http://metadata.google.internal/computeMetadata/v1/instance/zone",
                             headers={"Metadata-Flavor": "Google"}).text
    zone = zone_long.split("/")[-1]

    # shut ourselves down
    logging.info("Calling API to delete this VM, {zone}/{name}".format(zone=zone, name=name))

    requests.delete("https://www.googleapis.com/compute/v1/projects/{project_id}/zones/{zone}/instances/{name}"
                    .format(project_id=project_id, zone=zone, name=name),
                    headers={"Authorization": "Bearer {token}".format(token=token)})

Простой atexit хук дает мне желаемое поведение:

import atexit
atexit.register(kill_vm)
0 голосов
/ 13 октября 2018

Когда вы создаете виртуальную машину, вам нужно предоставить ей доступ для записи, чтобы вы могли удалить экземпляр изнутри.Вы также должны установить переменные среды контейнера, такие как gce_zone и gce_project_id в это время.Они понадобятся вам для удаления экземпляра.

gcloud beta compute instances create-with-container {NAME} \
    --container-env=gce_zone={ZONE},gce_project_id={PROJECT_ID} \
    --service-account={SERVICE_ACCOUNT} \
    --scopes=https://www.googleapis.com/auth/compute,...
    ...

Затем в контейнере, когда вы решите, что ваша задача выполнена:

  1. запросите токен API (я использую curl дляпростота и учетная запись службы DEFAULT gce)
curl "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token" -H "Metadata-Flavor: Google"

Это ответит json, который выглядит как

{
  "access_token": "foobarbaz...",
  "expires_in": 1234,
  "token_type": "Bearer"
}
Возьмите этот токен доступа и подключитесь к конечной точке API instances.delete (обратите внимание на переменные среды)
curl -XDELETE -H 'Authorization: Bearer {TOKEN}' https://www.googleapis.com/compute/v1/projects/$gce_project_id/zones/$gce_zone/instances/$HOSTNAME
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...