Как настроить личный реестр докеров поверх пространств DigitalOcean и использовать его с DigitalOcean Kubernetes

Автор выбралFree and Open Source Fund для получения пожертвования в рамках программыWrite for DOnations.

Вступление

ADocker registry - это система хранения и доставки контента для именованных образов Docker, которые являются отраслевым стандартом для контейнерных приложений. Частный реестр Docker позволяет вам безопасно обмениваться изображениями в вашей команде или организации с большей гибкостью и контролем по сравнению с общедоступными. Размещая свой личный реестр Docker непосредственно в своем кластере Kubernetes, вы можете достичь более высоких скоростей, меньших задержек и лучшей доступности, при этом имея контроль над реестром.

Базовое хранилище реестра делегируется внешним драйверам. Системой хранения по умолчанию является локальная файловая система, но вы можете поменять ее местами для драйвера облачного хранилища. DigitalOcean Spaces - это S3-совместимое объектное хранилище, предназначенное для групп разработчиков и предприятий, которым нужен масштабируемый, простой и доступный способ хранения и обслуживания огромных объемов данных, и очень подходит для хранения образов Docker. Он имеет встроенную сеть CDN, которая может значительно уменьшить задержку при частом доступе к изображениям.

В этом руководстве вы развернете свой частный реестр Docker в кластереDigitalOcean Kubernetes с помощьюHelm, зарезервированного DigitalOcean Spaces для хранения данных. Вы создадите ключи API для назначенного вам пространства, установите реестр Docker в свой кластер с настраиваемой конфигурацией, сконфигурируете Kubernetes для правильной аутентификации на нем и протестируете его, запустив пример развертывания в кластере. В конце этого руководства у вас будет защищенный частный реестр Docker, установленный в вашем кластере DigitalOcean Kubernetes.

Предпосылки

Прежде чем начать этот урок, вам необходимо:

  • Docker установлен на компьютере, с которого вы получите доступ к кластеру. Для Ubuntu 18.04 посетитеHow To Install and Use Docker on Ubuntu 18.04. Вам нужно только выполнить первый шаг. В противном случае посетите Dockerwebsite для других дистрибутивов.

  • Кластер DigitalOcean Kubernetes с вашей конфигурацией подключения, настроенной какkubectl по умолчанию. Инструкции по настройкеkubectl показаны под этапомConnect to your Cluster, показанным при создании кластера. Чтобы узнать, как создать кластер Kubernetes в DigitalOcean, см.Kubernetes Quickstart.

  • DigitalOcean Space с API-ключами (доступ и секрет). Чтобы узнать, как создать DigitalOcean Space и ключи API, см.How To Create a DigitalOcean Space and API Key.

  • Менеджер пакетов Helm установлен на вашем локальном компьютере, а Tiller установлен на вашем кластере. Выполните шаги 1 и 2How To Install Software on Kubernetes Clusters with the Helm Package Manager. Вам нужно только выполнить первые два шага.

  • Nginx Ingress Controller и Cert-Manager установлены в кластере. Чтобы узнать, как это сделать, см.How to Set Up an Nginx Ingress with Cert-Manager on DigitalOcean Kubernetes.

  • Доменное имя с двумя записями DNS A, указывающими на балансировщик нагрузки DigitalOcean, используемый Ingress. Если вы используете DigitalOcean для управления записями DNS своего домена, обратитесь кHow to Manage DNS Records, чтобы создать записи A. В этом руководстве мы будем называть записи Aregistry.example.com иk8s-test.example.com.

[[step-1 -—- configuring-and-install-the-docker-registry]] == Шаг 1. Настройка и установка реестра Docker

На этом этапе вы создадите файл конфигурации для развертывания реестра и установите реестр Docker в свой кластер с заданной конфигурацией с помощью диспетчера пакетов Helm.

В ходе этого руководства вы будете использовать файл конфигурации с именемchart_values.yaml, чтобы переопределить некоторые настройки по умолчанию для Helmchart реестра Docker. Хелм называет свои пакеты, графики; это наборы файлов, в которых описан соответствующий набор ресурсов Kubernetes. Вы измените настройки, указав DigitalOcean Spaces в качестве базовой системы хранения и включив доступ HTTPS, подключив сертификаты Let Encrypt TLS.

В рамках предварительных условий вы должны создать сервисыecho1 иecho2 и входecho_ingress для целей тестирования; они вам не понадобятся в этом руководстве, поэтому теперь вы можете удалить их.

Начните с удаления входа, выполнив следующую команду:

kubectl delete -f echo_ingress.yaml

Затем удалите две службы тестирования:

kubectl delete -f echo1.yaml && kubectl delete -f echo2.yaml

Команда kubectldelete принимает файл для удаления при передаче параметра-f.

Создайте папку, которая будет служить вашей рабочей областью:

mkdir ~/k8s-registry

Перейдите к нему, запустив:

cd ~/k8s-registry

Теперь с помощью текстового редактора создайте файлchart_values.yaml:

nano chart_values.yaml

Добавьте следующие строки, убедившись, что вы заменили выделенные строки вашими данными:

chart_values.yaml

ingress:
  enabled: true
  hosts:
    - registry.example.com
  annotations:
    kubernetes.io/ingress.class: nginx
    certmanager.k8s.io/cluster-issuer: letsencrypt-prod
    nginx.ingress.kubernetes.io/proxy-body-size: "30720m"
  tls:
    - secretName: letsencrypt-prod
      hosts:
        - registry.example.com

storage: s3

secrets:
  htpasswd: ""
  s3:
    accessKey: "your_space_access_key"
    secretKey: "your_space_secret_key"

s3:
  region: your_space_region
  regionEndpoint: your_space_region.digitaloceanspaces.com
  secure: true
  bucket: your_space_name

Первый блок,ingress, настраивает Kubernetes Ingress, который будет создан как часть развертывания диаграммы Helm. Объект Ingress указывает, что внешние маршруты HTTP / HTTPS указывают на внутренние службы в кластере, что позволяет осуществлять связь извне. Переопределенные значения:

  • enabled: установите наtrue, чтобы включить Ingress.

  • hosts: список хостов, с которых Ingress будет принимать трафик.

  • annotations: список метаданных, который предоставляет дальнейшие указания другим частям Kubernetes о том, как обращаться с Ingress. Вы устанавливаете Ingress Controller наnginx, эмитент кластера Let's Encrypt для производственного варианта (letsencrypt-prod) и указываете контроллеруnginx принимать файлы с максимальным размером 30 ГБ, что это разумный предел даже для самых больших образов Docker.

  • tls: эта подкатегория настраивает Let's Encrypt HTTPS. Вы заполняете списокhosts, который определяет, с каких защищенных хостов этот Ingress будет принимать HTTPS-трафик с нашим примером доменного имени.

Затем вы устанавливаете хранилище файловой системы наs3 - другой доступный вариант -filesystem. Здесьs3 указывает на использование удаленной системы хранения, совместимой со стандартным отраслевым API Amazon S3, который выполняет DigitalOcean Spaces.

В следующем блокеsecrets вы настраиваете ключи для доступа к вашему пространству DigitalOcean в подкатегорииs3. Наконец, в блокеs3 вы настраиваете параметры, определяющие ваше пространство.

Сохраните и закройте ваш файл.

Теперь, если вы еще этого не сделали, настройте свои записи A так, чтобы они указывали на балансировщик нагрузки, который вы создали как часть установки Nginx Ingress Controller в учебнике по предварительным требованиям. Чтобы узнать, как настроить DNS в DigitalOcean, см.How to Manage DNS Records.

Затем убедитесь, что ваше пространство не пусто. Реестр Docker вообще не запустится, если у вас нет файлов в вашем пространстве. Чтобы обойти это, загрузите файл. Перейдите на вкладку Spaces, найдите свой Space, нажмите кнопкуUpload File и загрузите любой файл, который вам нужен. Вы можете загрузить файл конфигурации, который вы только что создали.

Empty file uploaded to empty Space

Перед установкой чего-либо через Helm необходимо обновить его кеш. Это обновит последнюю информацию о вашем хранилище диаграмм. Для этого выполните следующую команду:

helm repo update

Теперь вы развернете диаграмму реестра Docker с этой пользовательской конфигурацией через Helm, запустив:

helm install stable/docker-registry -f chart_values.yaml --name docker-registry

Вы увидите следующий вывод:

OutputNAME:   docker-registry
...
NAMESPACE: default
STATUS: DEPLOYED

RESOURCES:
==> v1/ConfigMap
NAME                    DATA  AGE
docker-registry-config  1     1s

==> v1/Pod(related)
NAME                              READY  STATUS             RESTARTS  AGE
docker-registry-54df68fd64-l26fb  0/1    ContainerCreating  0         1s

==> v1/Secret
NAME                    TYPE    DATA  AGE
docker-registry-secret  Opaque  3     1s

==> v1/Service
NAME             TYPE       CLUSTER-IP      EXTERNAL-IP  PORT(S)   AGE
docker-registry  ClusterIP  10.245.131.143         5000/TCP  1s

==> v1beta1/Deployment
NAME             READY  UP-TO-DATE  AVAILABLE  AGE
docker-registry  0/1    1           0          1s

==> v1beta1/Ingress
NAME             HOSTS                 ADDRESS  PORTS  AGE
docker-registry  registry.example.com  80, 443  1s


NOTES:
1. Get the application URL by running these commands:
  https://registry.example.com/

Helm перечисляет все ресурсы, которые он создал в результате развертывания диаграммы реестра Docker. Реестр теперь доступен с указанного вами ранее доменного имени.

Вы настроили и развернули реестр Docker в своем кластере Kubernetes. Далее вы проверите доступность недавно развернутого реестра Docker.

[[step-2 -—- testing-pushing-and-pulling]] == Шаг 2 - Тестирование толкания и вытягивания

На этом этапе вы протестируете свой недавно развернутый реестр Docker, передавая и извлекая из него изображения. В настоящее время реестр пуст. Чтобы что-то подтолкнуть, вам нужно иметь изображение, доступное на машине, с которой вы работаете. Давайте использовать образ Dockermysql.

Начните с загрузкиmysql из Docker Hub:

sudo docker pull mysql

Ваш вывод будет выглядеть так:

OutputUsing default tag: latest
latest: Pulling from library/mysql
27833a3ba0a5: Pull complete
...
e906385f419d: Pull complete
Digest: sha256:a7cf659a764732a27963429a87eccc8457e6d4af0ee9d5140a3b56e74986eed7
Status: Downloaded newer image for mysql:latest

Теперь у вас есть изображение, доступное локально. Чтобы сообщить Docker, куда его отправить, вам нужно пометить его именем хоста, например:

sudo docker tag mysql registry.example.com/mysql

Затем вставьте изображение в новый реестр:

sudo docker push registry.example.com/mysql

Эта команда будет успешно выполнена и покажет, что ваш новый реестр правильно настроен и принимает трафик, включая отправку новых образов. Если вы видите ошибку, дважды проверьте ваши шаги против шагов 1 и 2.

Чтобы проверить чистоту извлечения из реестра, сначала удалите локальные образыmysql с помощью следующей команды:

sudo docker rmi registry.example.com/mysql && sudo docker rmi mysql

Затем вытащите его из реестра:

sudo docker pull registry.example.com/mysql

Эта команда займет несколько секунд. Если он работает успешно, это означает, что ваш реестр работает правильно. Если он показывает ошибку, дважды проверьте, что вы ввели против предыдущих команд.

Вы можете получить список изображений Docker, доступных локально, выполнив следующую команду:

sudo docker images

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

Ваш реестр Docker настроен. Вы добавили к нему изображение и подтвердили, что можете его снять. Теперь давайте добавим аутентификацию, чтобы только определенные люди могли получить доступ к коду.

[[step-3 -—- add-account-authentication-and-configuring-kubernetes-access]] == Шаг 3 - Добавление аутентификации учетной записи и настройка доступа Kubernetes

На этом шаге вы настроите аутентификацию по имени пользователя и паролю для реестра с помощью утилитыhtpasswd.

Утилитаhtpasswd поступает с веб-сервера Apache, который можно использовать для создания файлов, в которых хранятся имена пользователей и пароли для базовой аутентификации пользователей HTTP. Формат файловhtpasswd -username:hashed_password (по одному в строке), что достаточно переносимо, чтобы позволить другим программам использовать его.

Чтобыhtpasswd был доступен в системе, вам необходимо установить его, запустив:

sudo apt install apache2-utils -y

[.Примечание]##

Note:
Если вы запускаете это руководство с Mac, вам нужно будет использовать следующую команду, чтобы сделатьhtpasswd доступным на вашем компьютере:

docker run --rm -v ${PWD}:/app -it httpd htpasswd -b -c /app/htpasswd_file sammy password

Создайте его, выполнив следующую команду:

touch htpasswd_file

Добавьте комбинацию имени пользователя и пароля вhtpasswd_file:

htpasswd -B htpasswd_file username

Docker требует, чтобы пароль был хеширован с использованием алгоритмаbcrypt, поэтому мы передаем параметр-B. Алгоритм bcrypt - это функция хеширования паролей, основанная на блочном шифре Blowfish, с параметромwork factor, который указывает, насколько дорогой будет хеш-функция.

Не забудьте заменитьusername на желаемое имя пользователя. При запускеhtpasswd запросит у вас соответствующий пароль и добавит комбинацию кhtpasswd_file. Вы можете повторить эту команду для любого количества пользователей, которого хотите добавить.

Теперь покажите содержимоеhtpasswd_file, выполнив следующую команду:

cat htpasswd_file

Выберите и скопируйте показанное содержимое.

Чтобы добавить аутентификацию в реестр Docker, вам нужно отредактироватьchart_values.yaml и добавить содержимоеhtpasswd_file в переменнуюhtpasswd.

Откройтеchart_values.yaml для редактирования:

nano chart_values.yaml

Найдите строку, которая выглядит так:

chart_values.yaml

  htpasswd: ""

Отредактируйте его, чтобы он соответствовал следующему, заменивhtpasswd\_file\_contents содержимым, которое вы скопировали изhtpasswd_file:

chart_values.yaml

  htpasswd: |-
    htpasswd_file_contents

Будьте осторожны с отступом, перед каждой строкой содержимого файла должно быть четыре пробела.

Как только вы добавите свое содержимое, сохраните и закройте файл.

Чтобы распространить изменения в вашем кластере, выполните следующую команду:

helm upgrade docker-registry stable/docker-registry -f chart_values.yaml

Вывод будет аналогичен показанному при первом развертывании реестра Docker:

OutputRelease "docker-registry" has been upgraded. Happy Helming!
LAST DEPLOYED: ...
NAMESPACE: default
STATUS: DEPLOYED

RESOURCES:
==> v1/ConfigMap
NAME                    DATA  AGE
docker-registry-config  1     3m8s

==> v1/Pod(related)
NAME                              READY  STATUS   RESTARTS  AGE
docker-registry-6c5bb7ffbf-ltnjv  1/1    Running  0         3m7s

==> v1/Secret
NAME                    TYPE    DATA  AGE
docker-registry-secret  Opaque  4     3m8s

==> v1/Service
NAME             TYPE       CLUSTER-IP      EXTERNAL-IP  PORT(S)   AGE
docker-registry  ClusterIP  10.245.128.245         5000/TCP  3m8s

==> v1beta1/Deployment
NAME             READY  UP-TO-DATE  AVAILABLE  AGE
docker-registry  1/1    1           1          3m8s

==> v1beta1/Ingress
NAME             HOSTS                ADDRESS        PORTS    AGE
docker-registry  registry.example.com  159.89.215.50  80, 443  3m8s


NOTES:
1. Get the application URL by running these commands:
  https://registry.example.com/

Эта команда вызывает Helm и инструктирует его обновить существующий выпуск, в вашем случаеdocker-registry, с его диаграммой, определенной вstable/docker-registry в репозитории диаграмм, после применения файлаchart_values.yaml.

Теперь попробуйте снова извлечь изображение из реестра:

sudo docker pull registry.example.com/mysql

Вывод будет выглядеть следующим образом:

OutputUsing default tag: latest
Error response from daemon: Get https://registry.example.com/v2/mysql/manifests/latest: no basic auth credentials

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

Чтобы войти в реестр, выполните следующую команду:

sudo docker login registry.example.com

Не забудьте заменитьregistry.example.com на адрес своего домена. Он попросит вас ввести имя пользователя и пароль. Если он показывает ошибку, дважды проверьте, что содержит вашhtpasswd_file. Вы должны определить комбинацию имени пользователя и пароля вhtpasswd_file, которую вы создали ранее на этом шаге.

Чтобы проверить логин, вы можете попытаться снова выполнить команду, выполнив следующую команду:

sudo docker pull registry.example.com/mysql

Вывод будет выглядеть примерно так:

OutputUsing default tag: latest
latest: Pulling from mysql
Digest: sha256:f2dc118ca6fa4c88cde5889808c486dfe94bccecd01ca626b002a010bb66bcbe
Status: Image is up to date for registry.example.com/mysql:latest

Теперь вы настроили Docker и можете безопасно войти в систему. Чтобы настроить Kubernetes для входа в реестр, выполните следующую команду:

sudo kubectl create secret generic regcred --from-file=.dockerconfigjson=/home/sammy/.docker/config.json --type=kubernetes.io/dockerconfigjson

Вы увидите следующий вывод:

Outputsecret/regcred created

Эта команда создает секрет в вашем кластере с именемregcred, берет содержимое файла JSON, в котором Docker хранит учетные данные, и анализирует его какdockerconfigjson, который определяет учетные данные реестра в Kubernetes.

Вы использовалиhtpasswd для создания файла конфигурации входа в систему, настроили реестр для аутентификации запросов и создали секрет Kubernetes, содержащий учетные данные для входа. Далее вы протестируете интеграцию между вашим кластером Kubernetes и реестром.

[[step-4 -—- testing-kubernetes-integration-by-running-a-sample-deployment]] == Шаг 4 - Тестирование интеграции Kubernetes путем запуска образца развертывания

На этом шаге вы запустите пример развертывания с образом, хранящимся в реестре внутри кластера, чтобы проверить соединение между вашим кластером Kubernetes и реестром.

На последнем шаге вы создали секрет под названиемregcred, содержащий учетные данные для входа в ваш частный реестр. Он может содержать учетные данные для входа в несколько реестров, и в этом случае вам придется соответствующим образом обновить секрет.

Вы можете указать, какой секрет Kubernetes должен использовать при извлечении контейнеров в определении пода, указавimagePullSecrets. Этот шаг необходим, когда реестр Docker требует аутентификации.

Теперь вы развернете образецHello World image из частного реестра Docker в свой кластер. Во-первых, чтобы отправить его, вы вытащите его на свой компьютер, выполнив следующую команду:

sudo docker pull paulbouwer/hello-kubernetes:1.5

Затем пометьте его, запустив:

sudo docker tag paulbouwer/hello-kubernetes:1.5 registry.example.com/paulbouwer/hello-kubernetes:1.5

Наконец, поместите его в свой реестр:

sudo docker push registry.example.com/paulbouwer/hello-kubernetes:1.5

Удалите его со своего компьютера, так как он вам больше не нужен локально:

sudo docker rmi registry.example.com/paulbouwer/hello-kubernetes:1.5

Теперь вы развернете пример приложения Hello World. Сначала создайте новый файлhello-world.yaml с помощью текстового редактора:

nano hello-world.yaml

Затем вы определите Сервис и Вход, чтобы сделать приложение доступным за пределами кластера. Добавьте следующие строки, заменив выделенные строки вашими доменами:

hello-world.yaml

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: hello-kubernetes-ingress
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: k8s-test.example.com
    http:
      paths:
      - path: /
        backend:
          serviceName: hello-kubernetes
          servicePort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: hello-kubernetes
spec:
  type: NodePort
  ports:
  - port: 80
    targetPort: 8080
  selector:
    app: hello-kubernetes
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-kubernetes
spec:
  replicas: 3
  selector:
    matchLabels:
      app: hello-kubernetes
  template:
    metadata:
      labels:
        app: hello-kubernetes
    spec:
      containers:
      - name: hello-kubernetes
        image: registry.example.com/paulbouwer/hello-kubernetes:1.5
        ports:
        - containerPort: 8080
      imagePullSecrets:
      - name: regcred

Сначала вы определяете Ingress для развертывания Hello World, который вы будете маршрутизировать через балансировщик нагрузки, которым владеет Nginx Ingress Controller. Затем вы определяете сервис, который может обращаться к модулям, созданным в развертывании. В фактической спецификации развертывания вы указываетеimage как тот, который находится в вашем реестре, и устанавливаетеimagePullSecrets наregcred, который вы создали на предыдущем шаге.

Сохраните и закройте файл. Чтобы развернуть это в своем кластере, выполните следующую команду:

kubectl apply -f hello-world.yaml

Вы увидите следующий вывод:

Outputingress.extensions/hello-kubernetes-ingress created
service/hello-kubernetes created
deployment.apps/hello-kubernetes created

Теперь вы можете перейти в свой тестовый домен - вторая запись A,k8s-test.example.com в этом руководстве. Вы увидите страницу KubernetesHello world!.

Hello World page

На странице Hello World приведена некоторая информация об окружении, например, версия ядра Linux и внутренний идентификатор модуля, из которого был получен запрос. Вы также можете получить доступ к своему пространству через веб-интерфейс, чтобы увидеть изображения, с которыми вы работали в этом руководстве.

Если вы хотите удалить это развертывание Hello World после тестирования, выполните следующую команду:

kubectl delete -f hello-world.yaml

Вы создали пример развертывания Hello World, чтобы проверить, правильно ли Kubernetes извлекает изображения из вашего личного реестра.

Заключение

Теперь вы успешно развернули свой собственный реестр Docker в своем кластере DigitalOcean Kubernetes, используя DigitalOcean Spaces в качестве нижнего слоя хранения. Количество изображений, которые вы можете хранить, не ограничено, пробелы могут расширяться до бесконечности, обеспечивая при этом одинаковую безопасность и надежность. Однако в производственной среде вы всегда должны стремиться максимально оптимизировать образы Docker, взгляните на руководствоHow To Optimize Docker Images for Production.

Related