Как загрузить и запустить контейнер во время выполнения из запущенного модуля

Я работаю над вычислительной средой, которая будет работать на Google Container Engine (Kubernetes).

Желаемое поведение заключается в том, что пользователи будут предоставлять контейнер для выполнения (это пользовательская полезная нагрузка, мы в порядке, поскольку пользователей мало и им доверяют). Пользовательский контейнер будет загружен в реестр заранее.

Когда платформа запускается, она запускает несколько рабочих (каждый из них в стручке, слушает очередь из сельдерея), а главный узел загружает кучу аргументов для передачи рабочим (через celery/rabbitmq).

Когда рабочий бежит, он выполняет 3 вещи (для каждого рабочего элемента):

  1. SET UP: Работник будет копировать файлы и конфигурации из облачного хранилища Google и других мест. Файлы будут помещены в томе модуля.
  2. EXECUTION: Рабочий должен загрузить пользовательский контейнер из реестра и запустить его. Я тоже хочу запечатлеть stdout а также stderr из процесса контейнера и, если возможно, добавьте крайний срок (если контейнер не завершил выполнение в течение X секунд, остановите). Пользовательский контейнер будет генерировать свои результаты в виде файлов в каталоге томов.
  3. CLEAN UP and REPORTINGМодуль хоста скопирует некоторые артефакты, сгенерированные пользовательским контейнером, обратно в облако Google. Другие результаты будут сообщены частной заявке.

Я хочу, чтобы инфраструктура была невидимой для пользователей (потому что мы не хотим делиться с ними учетными данными и не позволяем им иметь какую-либо логику управления задачами).

Поскольку хост сам является контейнером, мы не нашли хорошего способа добиться этого (вытащить и запустить контейнер в скрипте, запущенном в другом контейнере).

Можно ли этого достичь в Кубернетесе? Есть ли какая-либо документация или проекты, делающие что-то подобное? и есть ли подводные камни с этим подходом?

Спасибо!

1 ответ

Решение

Закончилось решение его следующим образом:

Во-первых, я создал job определяется следующим образом (фрагмент):

apiVersion: batch/v1
kind: Job
metadata:
  name: item-001
spec: 
  template:
    metadata:
      name: item-xxx 
    spec: 
      containers:
      - name: worker
        image: gcr.io/<something>/worker
        volumeMounts:
        - mountPath: /var/run/docker.sock
          name: docker-socket-mount
        - mountPath: /workspace
          name: workspace 
      volumes:
        - name: docker-socket-mount
          hostPath:
            path: /var/run/docker.sock
        - name: workspace 
          hostPath:
            path: /home/workspace 

Есть 2 крепления, первый docker-socket-mount монтирует /var/run/docker.sock в контейнер, так что я могу использовать Docker изнутри, а во-вторых, он монтирует том, который будет разделен между хостом и гостевым контейнером workspace,

worker запускает скрипт, похожий на этот:

#!/usr/bin/env bash

IMAGE=gcr.io/some/guest/image

# ...

gsutil -m cp -r gs://some/files/I/need/* /workspace

# ...

export DOCKER_API_VERSION=1.23
gcloud docker -- pull ${IMAGE}
docker run -v /home/workspace:/workspace ${IMAGE} 

# ...

Имея док-сокет в наличии, достаточно установить клиент Docker и нормально его вызывать. Хитрость заключалась в том, чтобы смонтировать образ гостя из /home/workspaceкак видно из узла kubernetes, а не из образа хоста (/workspace). Файлы, загруженные в /workspace теперь также доступны в гостевом контейнере.

Наконец, Dockerfile выглядит примерно так:

FROM ubuntu:14.04

# ...

# Install Docker
RUN curl -fsSL https://get.docker.com/ | sh

# Install Google Cloud SDK
ADD xxx.json /home/keys/xxx.json
RUN curl https://sdk.cloud.google.com > /tmp/gcloud.sh
RUN bash /tmp/gcloud.sh --disable-prompts --install-dir=/home/tools/
RUN /home/tools/google-cloud-sdk/bin/gcloud auth activate-service-account name@my-project.iam.gserviceaccount.com --key-file=/home/keys/xxx.json
RUN /home/tools/google-cloud-sdk/bin/gcloud config set project my-project

# ...
Другие вопросы по тегам