Ошибка containerd не удалось найти пользователя по uid при создании контейнера докеров ejbca на Azure

Когда я пытаюсь создать экземпляр контейнера Azure для EJBCA-ce, я получаю сообщение об ошибке и не вижу никаких журналов.

Ожидаю следующего результата:  Успех событий экземпляра контейнера портала azure

Но я получаю следующую ошибку:

сбой событий экземпляра контейнера портала Azure

Failed to start container my-azure-container-resource-name, Error response: to create containerd task: failed to create container e9e48a_________ffba97: guest RPC failure: failed to find user by uid: 10001: expected exactly 1 user matched '0': unknown

Некоторый контекст:

Я запускаю контейнер на экземпляре контейнера лазурного облака

Я пытался

  • из шаблона ARM
  • с портала Azure.
  • с установленным файловым ресурсом
  • с переменной env базы данных
  • без каких-либо переменных env

Он отлично работает локально, используя ту же переменную env (конфигурация базы данных). Пару недель назад он работал с такой же конфигурацией.

Вот несколько журналов, которые я получаю, когда присоединяю группу контейнеров из az cli.

(count: 1) (last timestamp: 2020-11-03 16:04:32+00:00) pulling image "primekey/ejbca-ce:6.15.2.3"
(count: 1) (last timestamp: 2020-11-03 16:04:37+00:00) Successfully pulled image "primekey/ejbca-ce:6.15.2.3"
(count: 28) (last timestamp: 2020-11-03 16:27:52+00:00) Error: Failed to start container aci-pulsy-ccm-ejbca-snd, Error response: to create containerd task: failed to create container e9e48a06807fba124dc29633dab10f6229fdc5583a95eb2b79467fe7cdffba97: guest RPC failure: failed to find user by uid: 10001: expected exactly 1 user matched '0': unknown

Выдержка из { "type": "Microsoft.ContainerInstance/containerGroups", "apiVersion": "2019-12-01", "name": "[variables('ejbcaContainerGroupName')]", "location": "[parameters('location')]", "tags": "[variables('tags')]", "dependsOn": [ "[resourceId('Microsoft.DBforMariaDB/servers', variables('ejbcaMariadbServerName'))]", "[resourceId('Microsoft.DBforMariaDB/servers/databases', variables('ejbcaMariadbServerName'), variables('ejbcaMariadbDatabaseName'))]" ], "properties": { "sku": "Standard", "containers": [ { "name": "[variables('ejbcaContainerName')]", "properties": { "image": "primekey/ejbca-ce:6.15.2.3", "ports": [ { "protocol": "TCP", "port": 443 }, { "protocol": "TCP", "port": 8443 } ], "environmentVariables": [ { "name": "DATABASE_USER", "value": "[concat(parameters('mariadbUser'),'@', variables('ejbcaMariadbServerName'))]" }, { "name": "DATABASE_JDBC_URL", "value": "[variables('ejbcaEnvVariableJdbcUrl')]" }, { "name": "DATABASE_PASSWORD", "secureValue": "[parameters('mariadbAdminPassword')]" } ], "resources": { "requests": { "memoryInGB": 1.5, "cpu": 2 } } , "volumeMounts": [ { "name": "certificates", "mountPath": "/mnt/external/secrets" } ] } } ], "initContainers": [], "restartPolicy": "OnFailure", "ipAddress": { "ports": [ { "protocol": "TCP", "port": 443 }, { "protocol": "TCP", "port": 8443 } ], "type": "Public", "dnsNameLabel": "[parameters('ejbcaContainerGroupDNSLabel')]" }, "osType": "Linux", "volumes": [ { "name": "certificates", "azureFile": { "shareName": "[parameters('ejbcaCertsFileShareName')]", "storageAccountName": "[parameters('ejbcaStorageAccountName')]", "storageAccountKey": "[parameters('ejbcaStorageAccountKey')]" } } ] } }

Он отлично работает на моем локальном компьютере в Linux (ubuntu 20.04)

docker run -it --rm -p 8080:8080 -p 8443:8443 -h localhost -e DATABASE_USER="mymaridbuser@my-db" -e DATABASE_JDBC_URL="jdbc:mariadb://my-azure-domain.mariadb.database.azure.com:3306/ejbca?useSSL=true" -e DATABASE_PASSWORD="my-pwd" primekey/ejbca-ce:6.15.2.3

person Marc Bouvier    schedule 03.11.2020    source источник
comment
Похоже, что Azure не использует пользователей для Docker или, возможно, они используют другую среду выполнения контейнера, а не сам Docker. Вероятно, вы можете использовать этот образ с рынка Azure, потому что, если это не сработает, вы можете получить поддержку от Bitnami: azuremarketplace.microsoft.com/en-us/marketplace/apps/   -  person Boynux    schedule 27.11.2020


Ответы (2)


В образе контейнера EJBCA-ce, я думаю, они пытаются предоставить пользователя, отличного от root, для запуска сервера EJBCA. Согласно документации Docker:

Инструкция USER устанавливает имя пользователя (или UID) и, возможно, группу пользователей (или GID) для использования при запуске образа и для любых инструкций RUN, CMD и ENTRYPOINT, которые следуют за ним в Dockerfile.

В Dockerfile они ссылаются на двух пользователей, root, соответствующих UID 0, и еще одного, с UID 10001.

Как правило, в системах Linux и UNIX идентификаторы UID могут быть организованы в различных диапазонах: это в значительной степени зависит от конкретной операционной системы и практики управления пользователями, но весьма вероятно, что первая учетная запись пользователя, созданная в системе Linux, будет назначена UID. 1001 или 10001, как в этом случае. См., Например, запись UID в википедии или эта статья.

AFAIK, указанный USER не обязательно должен существовать в вашем контейнере для его правильного запуска: на самом деле, если вы запустите его локально, он запустится без дальнейших проблем.

Пользователь с UID 10001 будет фактически настроен в вашем контейнере с помощью сценария, который запускается в CMD, определенном в Dockerfile, /opt/primekey/bin/start.sh, этим фрагментом кода:

if ! whoami &> /dev/null; then
  if [ -w /etc/passwd ]; then
    echo "${APPLICATION_NAME}:x:$(id -u):0:${APPLICATION_NAME} user:/opt:/sbin/nologin" >> /etc/passwd
  fi
fi

Имейте в виду, что APPLICATION_NAME в этом контексте принимает значение ejbca и что пользователь, который запускает этот сценарий, как указано в Dockerfile, - это 10001. Это будет значение, предоставленное командой id -u в этом коде.

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

docker run -it -p 8080:8080 -p 8443:8443 -h localhost primekey/ejbca-ce:6.15.2.3

И инициируем в него bash:

 docker exec -it container_name /bin/bash

Если вы запустите whoami, он сообщит вам ejbca.

Если вы запустите id, он выдаст следующий результат:

uid=10001(ejbca) gid=0(root) groups=0(root)

Вы также можете проверить существование пользователя в /etc/passwd:

bash-4.2$ cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
ejbca:x:10001:0:ejbca user:/opt:/sbin/nologin

Причина, по которой Пьер не получил этот вывод, состоит в том, что он запустил контейнер, перезаписав предоставленный CMD и, как следствие, не выполнив сценарий start.sh, ответственный за создание пользователя, как упоминалось выше.

По любой причине, и именно здесь мои знания меня не подводят, когда Azure пытается запустить ваш контейнер, он терпит неудачу, потому что USER 10001, указанный в Dockerfile, не существует.

Я думаю, это могло быть связано с использованием containerd вместо docker.

Ошибка, о которой сообщает Azure, похоже, связана с проектом Microsoft opengcs.

О проекте говорят:

Open Guest Compute Service - это проект Linux с открытым исходным кодом, направленный на дальнейшее развитие производственной реализации контейнера Linux Hyper-V в Windows (LCOW). Он разработан для работы в специальной ОС Linux для поддержки полезной нагрузки контейнера Linux.

А также:

В центре внимания LCOW v2 как замены LCOW v1 - координация и работа, которые вошли в containerd / containerd и его интерфейс Runtime V2. Чтобы увидеть нашу прокладку на стороне хоста контейнера, пожалуйста, посмотрите здесь Microsoft / hcsshim / cmd / containerd-shim-runhcs-v1.

Ошибка, которую вы видите в консоли, поднята файлом spec.go, который вы можете найти в их базе кода, когда они пытаются установить пользователя, от имени которого должен запускаться процесс контейнера:

func setUserID(spec *oci.Spec, uid int) error {
    u, err := getUser(spec, func(u user.User) bool {
        return u.Uid == uid
    })
    if err != nil {
        return errors.Wrapf(err, "failed to find user by uid: %d", uid)
    }
    spec.Process.User.UID, spec.Process.User.GID = uint32(u.Uid), uint32(u.Gid)
    return nil
}

Этот код выполняется другим фрагментом кода - вы можете увидеть здесь полный код функции:

parts := strings.Split(userstr, ":")
switch len(parts) {
case 1:
    v, err := strconv.Atoi(parts[0])
    if err != nil {
        // evaluate username to uid/gid
        return setUsername(spec, userstr)
    }
    return setUserID(spec, int(v))

И функция getUser:

func getUser(spec *oci.Spec, filter func(user.User) bool) (user.User, error) {
    users, err := user.ParsePasswdFileFilter(filepath.Join(spec.Root.Path, "/etc/passwd"), filter)
    if err != nil {
        return user.User{}, err
    }
    if len(users) != 1 {
        return user.User{}, errors.Errorf("expected exactly 1 user matched '%d'", len(users))
    }
    return users[0], nil
}

Как видите, это именно те ошибки, о которых вам сообщает Azure.

Подводя итог, я думаю, что они предоставляют решение Windows LCOW, которое соответствует спецификации формата изображения OCI подходит для запуска контейнеров с containerd.

Как вы указали, если он работал с той же конфигурацией пару недель назад, моим лучшим гостем является то, что, возможно, они переключили ваши контейнеры с чистой реализации среды выполнения Linux containerd на реализацию, основанную на Windows и вышеупомянутое программное обеспечение, и именно поэтому ваши контейнеры теперь не работают.

Возможным обходным решением может быть создание пользовательского образа на основе официального, предоставленного PrimeKey, и создание пользователя 10001, как также указал Пьер.

Для выполнения этой задачи сначала создайте новый пользовательский файл Dockerfile. Вы можете попробовать, например:

FROM primekey/ejbca-ce:6.15.2.3

USER 0

RUN echo "ejbca:x:10001:0:ejbca user:/opt:/sbin/nologin" >> /etc/passwd

USER 10001

Обратите внимание, что вам может потребоваться определить некоторые переменные среды из официального образа EJBCA.

С помощью этого Dockerfile вы можете создать свой образ с помощью docker или docker compose с соответствующим docker-compose.yaml файлом, например:

version: "3"

services:
  ejbca:
    image: <your repository>/ejbca
    build: .
    ports:
      - "8080:8080"
      - "8443:8443"

Пожалуйста, настройте его по своему усмотрению.

При такой настройке новый контейнер по-прежнему будет правильно работать в локальной среде так же, как и исходный: я надеюсь, что так будет и в Azure.

person jccampanero    schedule 19.11.2020
comment
@MarcBouvier Я обновил ответ информацией, связанной с кодом, который, как мне кажется, Microsoft использует в реализации контейнеров Azure. Как указано в ответе, они, вероятно, переключили ваши контейнеры с реализации среды выполнения Linux containerd на версию, основанную на Windows и указанном программном обеспечении, и именно поэтому ваши контейнеры теперь выходят из строя. Боюсь, что у вашей проблемы нет однозначного решения. Мой лучший совет - попробуйте некоторые из предлагаемых обходных решений или обратитесь в службу поддержки Microsoft. - person jccampanero; 24.11.2020
comment
Вот ответ от службы поддержки Azure. Кажется, это соответствует вашей гипотезе. Для изображения требуются несколько пользователей. .docker.com / Layers / Primekey / ejbca-ce / 6.15.2.3 / images /, который не поддерживается во время выполнения контейнера. В качестве решения они предлагают закрепить подписку для развертывания только в контейнерной инфраструктуре. - person Marc Bouvier; 24.11.2020
comment
Я копался в деталях ваших новых материалов. Спасибо за столь подробный ответ. Позвольте мне принять ваш ответ, когда решение запроса в службу поддержки подтвердит ваш ответ. - person Marc Bouvier; 24.11.2020
comment
Добро пожаловать, @MarcBouvier. И большое спасибо за отзыв. Мне очень жаль, что я не смог помочь вам с ответом. Пожалуйста, дайте мне знать, если вы думаете, что я могу чем-нибудь помочь. - person jccampanero; 24.11.2020
comment
@MarcBouvier Большое спасибо, я очень ценю, что вы создали новую награду для присуждения существующего ответа, в этом не было необходимости. Пожалуйста, если вам когда-нибудь понадобится помощь, дайте мне знать, я буду рад помочь, если смогу. - person jccampanero; 02.12.2020
comment
В конце я также создал образ на основе официального, добавив пользователя 10001. Он работает. - person Marc Bouvier; 14.12.2020
comment
Это нормально @MarcBouvier. Я очень рад услышать, что вы, наконец, смогли развернуть ejbca. Кстати, отличный продукт! - person jccampanero; 14.12.2020
comment
Да, поначалу мне было не очень приятно поддерживать собственный образ докера. Но это очень просто: несколько строк dockerfile и очень простой конвейер сборки. Это небольшое усилие того стоит. - person Marc Bouvier; 07.02.2021
comment
эдерра! Это чертовски ответ - person aran; 20.02.2021
comment
Большое спасибо @aran !! Я очень ценю ваш комментарий. - person jccampanero; 20.02.2021
comment
Извините, @MarcBouvier. Я только что понял ваш комментарий. Замечательно, Марк. Да, думаю, оно того стоит. Рад слышать, что все работает нормально. - person jccampanero; 20.02.2021

Пользователь с UID 10001 не существует на вашем изображении. Это не мешает команде USER в вашем Dockerfile работать или самому образу быть недействительным, но, похоже, это вызывает проблемы с контейнером Azure.

Я не могу найти документ или какую-либо ссылку о том, почему он не работает в Azure (обновлю, если да), но добавление пользователя в образ должно решить проблему. Попробуйте добавить что-то подобное в свой Dockerfile, чтобы создать пользователя с UID 10001 (это должно быть сделано как root, то есть с пользователем 0):

useradd -u 10001 myuser

Дополнительные примечания для просмотра пользователя 10001 не существуют:

# When running container, not recognized by system
$ docker run docker.io/primekey/ejbca-ce:6.15.2.3 whoami
whoami: cannot find name for user ID 10001

# Not present in /etc/passwd
$ docker run docker.io/primekey/ejbca-ce:6.15.2.3 cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
person Pierre B.    schedule 17.11.2020