Знакомство с Kubernetes. Часть 7: Образы (Images)

Jun 11, 2018 07:05 · 743 words · 4 minute read kubernetes

Перед тем, как описывать в манифесте какого-либо объекта Kubernetes образ контейнера, его необходимо создать и разместить в реестре образов. Давайте разберемся!

Примечание. В данной статье будем говорить прежде всего о docker-образах и docker-registry.

Поле image в описании контейнера поддерживает тот же синтаксис, что и команда docker, включая частные реестры (private registries) и тэги.

По умолчанию для скачивания docker-образов установлена политика IfNotPresent, которая заставляет Kubelet пропускать скачивание образа, если он уже существует локально. Если необходимо всегда скачивать docker-образы перед запуском контейнеров, изменить данную политику можно следующими вариантами:

  • установить для поля imagePullPolicy контейнера значение Always;
  • использовать тэг :latest при описании образа;
  • включить контроллер AlwaysPullImages.

Если не задать в явном виде тэг docker-образа, то он будет автоматически установлен в :latest, а политика скачивания образа будет иметь вид imagePullPolicy=Always.

Примечание. Следует избегать использования тэга :latest - подробнее здесь.

При использовании частных реестров образов (private registries) могут потребоваться учетные данные для скачивания образов. Такие данные (ключи) можно предоставлять несколькими способами, в зависимости от типа реестра:

  • средствами GCR (Google Container Registry);
  • средствами AWS EC2 Container Registry (ECR);
  • средствами ACR (Azure Container Registry);
  • настраивая узлы кластера для аутентификации в частных реестрах;
  • скачивая образы до запуска подов;
  • указывая ImagePullSecrets в описании пода.

Рассмотрим каждый вариант более детально.

GCR Kubernetes имеет встроенную поддержку Google Container Registry (GCR) при работе c GCE/GKE. Если используется кластер в Google Compute Engine или Google Kubernetes Engine, достаточно указать полное имя образа, например, gcr.io/my_project/image:tag. Все поды кластера будут иметь доступ к данному реестру образов. Kubelet получит доступ к GCR с помощью служебной учетной записи (instance’s Google service account) с правами read_only.

ECR Kubernetes имеет встроенную поддержку реестра контейнеров AWS EC2, если узлы кластера являются экземплярами AWS EC2. В таком случае достаточно использовать полное имя образа - например, ACCOUNT.dkr.ecr.REGION.amazonaws.com/imagename:tag в описании пода. Все пользователи кластера с правами запуска подов получают также права на скачивание docker-образов из ECR.

Kubelet (начиная с версии v1.2.0) будет проверять и периодически обновлять учетные данные ECR. Для этого ему необходимы следующие разрешения:

  • ecr:GetAuthorizationToken
  • ecr:BatchCheckLayerAvailability
  • ecr:GetDownloadUrlForLayer
  • ecr:GetRepositoryPolicy
  • ecr:DescribeRepositories
  • ecr:ListImages
  • ecr:BatchGetImage

ACR При работе с Azure Container Registry можно получить доступ к реестру образов либо с учетными данными администратора, либо с помощью стандартной аутентификации Docker. Второй вариант предполагает использование инструмента командной строки azure-cli. Создать реестр и сгенерировать учетные данные можно следуя документации, после чего можно использовать учетные данные для входа в систему:

DOCKER_USER: главный администратор или администратор службы DOCKER_PASSWORD: пароль главного администратора или администратора службы DOCKER_REGISTRY_SERVER: $ {some-registry-name} .azurecr.io DOCKER_EMAIL: $ {some-email-address}

Настройка узлов кластера для аутентификации в частных реестрах Docker хранит ключи для частных реестров образов в файле $HOME/.dockercfg или $HOME/.docker/config.json. Необходимо разместить этот файл в домашнем каталоге пользователя root на всех узлах кластера с запущенным kubelet. Для этого:

  • На рабочем компьютере нужно выполнить docker login [server] для всех наборов учетных записей / реестров, которые вы планируете использовать. Эти команды актуализируют конфигурационный файл $HOME/.docker/config.json.
  • Проверьте данный файл ($HOME/.docker/config.json) в текстовом редакторе и убедитесь, что в нем есть все необходимые данные.
  • Получите все имена или ip-адреса узлов кластера Kubernetes:
nodes=$(kubectl get nodes -o jsonpath='{range.items[*].metadata}{.name} {end}')

или

nodes=$(kubectl get nodes -o jsonpath='{range .items[*].status.addresses[?(@.type=="ExternalIP")]}{.address} {end}')
  • Скопируйте конфигурационный файл $HOME/.docker/config.json на все узлы кластера, например так:
for n in $nodes; do scp ~/.docker/config.json root@$n:/root/.docker/config.json; done
  • Проверьте доступ в частному реестру - например, создайте манифест для пода, использующий образ из реестра.

Скачивая образы до запуска подов Не самый оптимальный вариант, но все же - если вы хотите использовать локально размещенные docker-образы (например, если хотите сэкономить время на скачивании образов из реестра или нет учетных данных для доступа к реестру), то убедитесь, что эти образы есть на всех узлах кластера.

Указывая ImagePullSecrets в описании пода С помощью следующей команды (с заменой соответствующих значений на ваши) генерируем секретную переменную (создание секретов рассмотрим в одной из следующих статей):

kubectl create secret docker-registry myregistrykey --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL
secret "myregistrykey" created.

Примечание. Если необходим доступ к нескольким частным реестрам образов, для каждого из них генерируем отдельный secret.

Альтернативный вариант описания секретной переменной - создаем манифест для объекта Secret следующего вида:

apiVersion: v1
kind: Secret
metadata:
  name: myregistrykey
  namespace: awesomeapps
data:
  .dockerconfigjson: ewogICJhdXRocyIgOiB7CiAgICAiaHR0cHM6Ly9yZWdpc3RyeS5naXRsYWIubGM6NTAwMCIgOiB7CgogICAgfSwKICAgICJyZWdpc3RyeS5naXRsYWIubGM6NTAwMCIgOiB7CgogICAgfQogIH0sCiAgIkh0dHBIZWFkZXJzIiA6IHsKICAgICJVc2VyLUFnZW50IiA6ICJEb2NrZXItQ2xpZW50LzE4LjAyLjAtY2UtcmMyIChkYXJ3aW4pIgogIH0sCiAgImV4cGVyaW1lbnRhbCIgOiAiZW5hYmxlZCIsCiAgImNyZWRzU3RvcmUiIDogIm9zeGtleWNoYWluIiwKICAib3JjaGVzdHJhdG9yIiA6ICJzd2FybSIKfQ==
type: kubernetes.io/dockerconfigjson

Убедитесь, что:

  • имя элемента данных в поле data установлено в .dockerconfigjson;
  • значением для параметра .dockerconfigjson установлена строка, полученная как результат кодирования файла $HOME/.docker/config.json (см. выше) в base64;
  • тип (type) объекта установлен в kubernetes.io/dockerconfigjson.

Примечание. Команда для кодирования строки выглядит так: cat ~/.docker/config.json | base64.

Теперь, при описании манифеста для каждого пода, использующего частный реестр образов, не забудьте добавить поле imagePullSecrets:

apiVersion: v1
kind: Pod
metadata:
  name: foo
  namespace: awesomeapps
spec:
  containers:
    - name: foo
      image: janedoe/awesomeapp:v1
  imagePullSecrets:
    - name: myregistrykey
tweet Share