Подготовка окружения#
Предварительные условия#
Проверка версии утилиты Dactl в дистрибутиве#
Утилита расположена в дистрибутиве K8S-2.2.3-fstec-58-distrib.zip. Получив дистрибутив в виде zip-архива, загрузите его на машину администратора, вся дальнейшая работа будет вестись с машины администратора.
Разархивируйте дистрибутив, получив вложенные архивы и файлы:
k8sf-2.2.3-owned-distrib.zip;k8sf-2.2.3-owned.pom.
Архив имеет большой размер - более 10 Гб, рекомендуется перед разархивацией установить переменную окружения UNZIP_DISABLE_ZIPBOMB_DETECTION=TRUE
Разархивируйте архив K8S-2.2.3-fstec-58-distrib.zip, состоящий из следующих вложенных файлов:
k8sf-lsc-images-2.2.3-distrib.zip;k8sf-binaries-2.2.3-distrib.zip;k8sf-scripts-2.2.3-distrib.zip;k8sf-rpms-alt-2.2.3-distrib.zip;k8sf-images-2.2.3-distrib.zip;k8sf-rpms-2.2.3-distrib.zip.
Разархивируйте архив k8sf-binaries-2.2.3-distrib.zip и получите утилиту Dactl по пути ./package/bh/dactl-2.2.3-fstec.zip..
Проверьте версию Dactl:
$ ./dactl version
Platform V DropApp version: 2.2.3-fstec
Общая схема развертывания представлена на диаграмме:
Требования к виртуальной машине администратора кластера#
DropApp настраивается администратором на виртуальной машине с предустановленной ОС
.
Для установки требуется машина администратора кластера с которой будет запускаться утилита Dactl.
Машина администратора кластера должна быть в одном сетевом контуре с:
будущими машинами-узлами кластера;
image registry (реестром образов), куда будут загружены образы контейнеров DropApp.
Планирование пула IP-адресов#
DropApp использует балансировщик Metallb для развертывания приложений.
Для использования Metallb необходимо зарезервировать диапазон IP-адресов.
Например, 10 адресов из той же подсети, в которой развернуты серверы для установки DropApp.
DNS#
В DNS должны быть зарегистрированы записи для приложений, а также для стартовый реестр Harbor. Формат hostname: <tool>.<clusteName>.<domain>. Пример указан в таблице ниже.
Стартовый реестр Harbor:
Приложение |
Пример записи |
IP-адрес |
|---|---|---|
Harbor |
harbor.bootstrap.domain.ru |
Адрес машины для стартового реестра |
Основной реестр Harbor:
Приложение |
Пример записи |
IP-адрес |
|---|---|---|
Console |
console.registry.domain.ru |
Первый из пула адресов Metallb |
Harbor |
harbor.registry.domain.ru |
Первый из пула адресов Metallb |
Dex |
auth.registry.domain.ru |
Первый из пула адресов Metallb |
Основной кластер DropApp:
Приложение |
Пример записи |
IP-адрес |
|---|---|---|
Console |
console.fstec-cluster.domain.ru |
Первый из пула адресов Metallb |
Dex |
auth.fstec-cluster.domain.ru |
Первый из пула адресов Metallb |
Grafana |
grafana.fstec-cluster.domain.ru |
Первый из пула адресов Metallb |
Имена должны разрешаться c nodes кластера.
LDAP-каталог или IPA-сервер#
DropApp использует сертифицированный LDAP-каталог пользователей и групп. Например IPA-сервер из дистрибутива Platform V SberLinux OS Server.
В IPA-сервере должны быть настроены группы, согласно ролевой модели.
Стартовый реестр образов#
Для установки DropApp необходим реестр образов контейнеров. Далее описан процесс создания стартового реестра Harbor из поставки DropApp.
Создание реестра образов контейнеров состоит из следующих шагов:
Создать стартовый реестр Harbor, он необязательно должен быть на сертифицированной ОС и служит для загрузки всех образов из дистрибутива.
Создать сертифицированный кластер DropApp для установки основного реестра Harbor. При установке используется стартовый реестр Harbor. Основной реестр Harbor будет использоваться источником образов контейнеров для всех сертифицированных кластеров DropApp.
Создать основной сертифицированный кластер DropApp для установок пользовательских приложений, использующий реестр Harbor из шага 2.
Подготовка к установке#
Для установки стартового реестра Harbor требуется:
Машина с необязательно сертифицированной версией ОС (так как это стартовый реестр):
у пользователя в системе должны быть административные полномочия (root или аналогичные);
машина должна быть в одном сетевом контуре с будущими машинами-узлами кластера;
на машине должны быть установлены Docker или Podman.
Дистрибутив
K8S-2.2.3-fstec-58-distrib.zip;DNS-запись вида
harbor.bootstrap.<public_domain>с хостом, на котором осуществляется развертывание Harbor, см. раздел «DNS».
Примечание
Средство контейнеризации Podman версии 5.2.2-11 входит в состав ОС Plarform V SberLinux OS Server версии 9.1.0-fstec.
Для стартового реестра Harbor будет достаточно одной машины.
Значение |
Размер |
|---|---|
ЦПУ [CPU] (в ядрах) |
4 (с поддержкой VT*) |
ОЗУ [RAM] |
8192 Мб |
Размер диска [HDD/SSD] |
50 Гб |
Примечание
После развертывания основного реестра Harbor машину стартового реестра Harbor можно удалить.
Работа с дистрибутивом#
Получение образов#
Из состава дистрибутива K8S-2.2.3-fstec-58-distrib.zip разархивируйте архив k8sf-images-2.2.3-distrib.zip (подробнее в подразделе «Предварительные условия»):
$ unzip k8sf-images-2.2.3-distrib.zip -d ./images
Archive: k8sf-images-2.2.3-distrib.zip
inflating: ./images/harbor-portal-v2.9.3.tar
....
Загрузка образов Harbor в локальный cache#
Для загрузка образов Harbor в локальный cache выполните следующие шаги:
Создайте каталог
harborи перейдите в него.Создайте в каталоге
harborскриптload_harbor_images.sh:load_harbor_images.sh
#!/bin/bash set -e CONTAINER_ENGINE="podman" IMAGES_PATH="" usage() { echo "Использование: $0 --images-path <путь> [--container-engine <docker|podman>]" exit 1 } while [[ "$#" -gt 0 ]]; do case $1 in --images-path) if [[ -n "$2" ]]; then IMAGES_PATH="$2" shift 2 else echo "Ошибка: Для --images-path не указано значение." usage fi ;; --container-engine) if [[ -n "$2" ]]; then CONTAINER_ENGINE="$2" shift 2 else echo "Ошибка: Для --container-engine не указано значение." usage fi ;; *) echo "Неизвестный параметр: $1" usage ;; esac done if [[ -z "$IMAGES_PATH" ]]; then echo "Ошибка: Параметр --images-path является обязательным." usage fi if [[ ! -d "$IMAGES_PATH" ]]; then echo "Ошибка: Указанный путь к образам '$IMAGES_PATH' не существует или не является каталогом." exit 1 fi if ! command -v "$CONTAINER_ENGINE" &> /dev/null; then echo "Ошибка: Команда '$CONTAINER_ENGINE' не найдена. Убедитесь, что она установлена." exit 1 fi echo "Используется контейнерный движок: $CONTAINER_ENGINE" echo "Путь к образам: $IMAGES_PATH" CURRENT_DIR=$(pwd) echo "Загружаем образы Harbor ..." cd "$IMAGES_PATH" $CONTAINER_ENGINE load -i prepare-v2.9.3.tar $CONTAINER_ENGINE load -i harbor-core-v2.9.3.tar $CONTAINER_ENGINE load -i harbor-db-v2.9.3.tar $CONTAINER_ENGINE load -i harbor-exporter-v2.9.3.tar $CONTAINER_ENGINE load -i harbor-jobservice-v2.9.3.tar $CONTAINER_ENGINE load -i harbor-log-v2.9.3.tar $CONTAINER_ENGINE load -i harbor-portal-v2.9.3.tar $CONTAINER_ENGINE load -i harbor-registryctl-v2.9.3.tar $CONTAINER_ENGINE load -i harbor-scanner-trivy-0.30.22.tar $CONTAINER_ENGINE load -i nginx-fstec-v2.9.3.tar $CONTAINER_ENGINE load -i redis-fstec-v2.9.3.tar $CONTAINER_ENGINE load -i registry-fstec-v2.9.3.tar cd "$CURRENT_DIR"Чтобы выгрузить образы, которые требует Harbor воспользуйтесь скриптом
load_harbor_images.sh:./load_harbor_images.sh --images-path ../images --container-engine <docker|podman>
Генерация сертификатов для реестра Harbor#
Для генерации сертификатов для реестра Harbor выполните следующие шаги:
Создайте в каталоге
harborскриптharbor_certs.sh:harbor_certs.sh
#!/bin/bash set -e # Парсинг аргументов while [[ "$#" -gt 0 ]]; do case $1 in --ip) IP="$2"; shift ;; --hostname) HOSTNAME="$2"; shift ;; --passphrase) PASSPHRASE="$2"; shift ;; --container-engine) CONTAINER_ENGINE="$2"; shift ;; *) echo "Unknown parameter passed: $1"; exit 1 ;; esac shift done # Если IP не передан, используем первый IP из вывода hostname -I if [ -z "$IP" ]; then IP=$(hostname -I | awk '{print $1}') fi # Если HOSTNAME не передан, используем текущий hostname if [ -z "$HOSTNAME" ]; then HOSTNAME=$(hostname) fi if [ -z "$CONTAINER_ENGINE" ]; then CONTAINER_ENGINE="podman" fi # Создаем директорию certs if [ -d "./certs" ]; then rm -rf ./certs fi mkdir ./certs # Генерация корневого ключа и сертификата openssl genrsa -out ./certs/harbor_internal_ca.key 4096 if [ -z "$PASSPHRASE" ]; then openssl req -x509 -new -nodes -key ./certs/harbor_internal_ca.key -sha512 -days 3650 -out ./certs/harbor_internal_ca.crt -subj "/C=RU/L=Moscow/O=Platform V DropApp/CN=dropapp_internal_ca" else openssl req -x509 -new -key ./certs/harbor_internal_ca.key -sha512 -days 3650 -out ./certs/harbor_internal_ca.crt -subj "/C=RU/L=Moscow/O=Platform V DropApp/CN=dropapp_internal_ca" -passin pass:"$PASSPHRASE" fi # Генерация ключа для сертификата приложения openssl genrsa -out ./certs/harbor.key 4096 # Создание конфигурационного файла для расширений сертификата cat > ./certs/v3.ext <<-EOF authorityKeyIdentifier=keyid,issuer basicConstraints=CA:FALSE keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment subjectAltName = @alt_names [alt_names] IP.1 = $IP DNS.1 = $HOSTNAME DNS.2 = portal DNS.3 = core DNS.4 = registry DNS.5 = job_service DNS.6 = trivy_adapter DNS.7 = harbor_db DNS.8 = redis DNS.9 = registryctl DNS.8 = proxy EOF # Генерация CSR для сертификата приложения openssl req -new -key ./certs/harbor.key -out ./certs/harbor.csr -subj "/C=RU/L=Moscow/O=Platform V DropApp/CN=$HOSTNAME" # Подписание сертификата приложения корневым сертификатом if [ -z "$PASSPHRASE" ]; then openssl x509 -req -in ./certs/harbor.csr -CA ./certs/harbor_internal_ca.crt -CAkey ./certs/harbor_internal_ca.key -CAcreateserial -out ./certs/harbor.crt -days 3650 -sha512 -extfile ./certs/v3.ext else openssl x509 -req -in ./certs/harbor.csr -CA ./certs/harbor_internal_ca.crt -CAkey ./certs/harbor_internal_ca.key -CAcreateserial -out ./certs/harbor.crt -days 3650 -sha512 -extfile ./certs/v3.ext -passin pass:"$PASSPHRASE" fi for NAME in portal core registry job_service trivy_adapter harbor_db redis proxy registryctl; do cp ./certs/harbor.crt "./certs/${NAME}.crt" cp ./certs/harbor.key "./certs/${NAME}.key" done echo "Сертификаты успешно созданы в директории ./certs" echo "Копируем harbor.crt в директорию /etc/containers/certs.d/$HOSTNAME" sudo rm -rf /etc/containers/certs.d/$HOSTNAME sudo mkdir -p /etc/containers/certs.d/$HOSTNAME sudo cp ./certs/harbor.crt /etc/containers/certs.d/$HOSTNAME/ca.crt # Условие для container-engine if [[ "$CONTAINER_ENGINE" == "docker" ]]; then echo "Копируем harbor.crt в директорию /etc/docker/certs.d/$HOSTNAME" sudo rm -rf /etc/docker/certs.d/$HOSTNAME sudo mkdir -p /etc/docker/certs.d/$HOSTNAME sudo cp ./certs/harbor.crt /etc/docker/certs.d/$HOSTNAME/ca.crt sudo systemctl restart docker fi if [[ "$CONTAINER_ENGINE" == "podman" ]]; then sudo systemctl restart podman fiПараметры скрипта
harbor_certs.sh:--ip- опциональный параметр, по умолчанию равен выводуhostname -I, то есть публичному IP текущей машины;--hostname- обязательный параметр, сертификат будет выписан на этот hostname;--passphrase- опциональный параметр для пароля сертификата;--container-engine- опциональный параметр, можно передатьdockerилиpodman, по умолчаниюpodman.
Запустите скрипт, он сгенерирует самоподписанные сертификаты для реестра и расположит их в каталоге
certs.dдляcontainer runtime:./harbor_certs.sh --hostname harbor.bootstrap.domain.ru --container-engine <docker|podman>
Установка стартового реестра Harbor#
Конфигурация Harbor#
Создайте в каталоге
harborфайлharbor.yml:harbor.yml
# Configuration file of Harbor # The IP address or hostname to access admin UI and registry service. # DO NOT use localhost or 127.0.0.1, because Harbor needs to be accessed by external clients. hostname: harbor.bootstrap.domain.ru # http related config http: # port for http, default is 80. If https enabled, this port will redirect to https port # port: 80 # https related config https: # https port for harbor, default is 443 port: 443 # The path of cert and key files for nginx certificate: /home/user/harbor/certs/harbor.crt private_key: /home/user/harbor/certs/harbor.key # # Uncomment following will enable tls communication between all harbor components #internal_tls: # # set enabled to true means internal tls is enabled # enabled: true # # put your cert and key files on dir # dir: /root/harbor/certs # # enable strong ssl ciphers (default: false) # strong_ssl_ciphers: false # Uncomment external_url if you want to enable external proxy # And when it enabled the hostname will no longer used # external_url: https://reg.mydomain.com:8433 # The initial password of Harbor admin # It only works in first time to install harbor # Remember Change the admin password from UI after launching Harbor. harbor_admin_password: <harbor-admin-password> # Harbor DB configuration database: # The password for the root user of Harbor DB. Change this before any production use. password: <root-password> # The maximum number of connections in the idle connection pool. If it <=0, no idle connections are retained. max_idle_conns: 100 # The maximum number of open connections to the database. If it <= 0, then there is no limit on the number of open connections. # Note: the default number of connections is 1024 for postgres of harbor. max_open_conns: 900 # The maximum amount of time a connection may be reused. Expired connections may be closed lazily before reuse. If it <= 0, connections are not closed due to a connection's age. # The value is a duration string. A duration string is a possibly signed sequence of decimal numbers, each with optional fraction and a unit suffix, such as "300ms", "-1.5h" or "2h45m". Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h". conn_max_lifetime: 5m # The maximum amount of time a connection may be idle. Expired connections may be closed lazily before reuse. If it <= 0, connections are not closed due to a connection's idle time. # The value is a duration string. A duration string is a possibly signed sequence of decimal numbers, each with optional fraction and a unit suffix, such as "300ms", "-1.5h" or "2h45m". Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h". conn_max_idle_time: 0 # The default data volume data_volume: ./data_harbor # Harbor Storage settings by default is using /data dir on local filesystem # Uncomment storage_service setting If you want to using external storage # storage_service: # # ca_bundle is the path to the custom root ca certificate, which will be injected into the truststore # # of registry's containers. This is usually needed when the user hosts a internal storage with self signed certificate. # ca_bundle: # # storage backend, default is filesystem, options include filesystem, azure, gcs, s3, swift and oss # # for more info about this configuration please refer https://docs.docker.com/registry/configuration/ # filesystem: # maxthreads: 100 # # set disable to true when you want to disable registry redirect # redirect: # disable: false # Trivy configuration # # Trivy DB contains vulnerability information from NVD, Red Hat, and many other upstream vulnerability databases. # It is downloaded by Trivy from the GitHub release page https://github.com/aquasecurity/trivy-db/releases and cached # in the local file system. In addition, the database contains the update timestamp so Trivy can detect whether it # should download a newer version from the Internet or use the cached one. Currently, the database is updated every # 12 hours and published as a new release to GitHub. trivy: # ignoreUnfixed The flag to display only fixed vulnerabilities ignore_unfixed: false # skipUpdate The flag to enable or disable Trivy DB downloads from GitHub # # You might want to enable this flag in test or CI/CD environments to avoid GitHub rate limiting issues. # If the flag is enabled you have to download the `trivy-offline.tar.gz` archive manually, extract `trivy.db` and # `metadata.json` files and mount them in the `/home/scanner/.cache/trivy/db` path. skip_update: false # # skipJavaDBUpdate If the flag is enabled you have to manually download the `trivy-java.db` file and mount it in the # `/home/scanner/.cache/trivy/java-db/trivy-java.db` path skip_java_db_update: false # # The offline_scan option prevents Trivy from sending API requests to identify dependencies. # Scanning JAR files and pom.xml may require Internet access for better detection, but this option tries to avoid it. # For example, the offline mode will not try to resolve transitive dependencies in pom.xml when the dependency doesn't # exist in the local repositories. It means a number of detected vulnerabilities might be fewer in offline mode. # It would work if all the dependencies are in local. # This option doesn't affect DB download. You need to specify "skip-update" as well as "offline-scan" in an air-gapped environment. offline_scan: false # # Comma-separated list of what security issues to detect. Possible values are `vuln`, `config` and `secret`. Defaults to `vuln`. security_check: vuln # # insecure The flag to skip verifying registry certificate insecure: true # github_token The GitHub access token to download Trivy DB # # Anonymous downloads from GitHub are subject to the limit of 60 requests per hour. Normally such rate limit is enough # for production operations. If, for any reason, it's not enough, you could increase the rate limit to 5000 # requests per hour by specifying the GitHub access token. For more details on GitHub rate limiting please consult # https://docs.github.com/rest/overview/resources-in-the-rest-api#rate-limiting # # You can create a GitHub token by following the instructions in # https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line # # github_token: xxx jobservice: # Maximum number of job workers in job service max_job_workers: 10 # The jobLoggers backend name, only support "STD_OUTPUT", "FILE" and/or "DB" job_loggers: - STD_OUTPUT - FILE # - DB # The jobLogger sweeper duration (ignored if `jobLogger` is `stdout`) logger_sweeper_duration: 1 #days notification: # Maximum retry count for webhook job webhook_job_max_retry: 3 # HTTP client timeout for webhook job webhook_job_http_client_timeout: 3 #seconds # Log configurations log: # options are debug, info, warning, error, fatal level: info # configs for logs in local storage local: # Log files are rotated log_rotate_count times before being removed. If count is 0, old versions are removed rather than rotated. rotate_count: 50 # Log files are rotated only if they grow bigger than log_rotate_size bytes. If size is followed by k, the size is assumed to be in kilobytes. # If the M is used, the size is in megabytes, and if G is used, the size is in gigabytes. So size 100, size 100k, size 100M and size 100G # are all valid. rotate_size: 200M # The directory on your host that store log location: /var/log/harbor # Uncomment following lines to enable external syslog endpoint. # external_endpoint: # # protocol used to transmit log to external endpoint, options is tcp or udp # protocol: tcp # # The host of external endpoint # host: localhost # # Port of external endpoint # port: 5140 #This attribute is for migrator to detect the version of the .cfg file, DO NOT MODIFY! _version: 2.9.0 # Uncomment external_database if using external database. # external_database: # harbor: # host: harbor_db_host # port: harbor_db_port # db_name: harbor_db_name # username: harbor_db_username # password: harbor_db_password # ssl_mode: disable # max_idle_conns: 2 # max_open_conns: 0 # Uncomment redis if need to customize redis db # redis: # # db_index 0 is for core, it's unchangeable # # registry_db_index: 1 # # jobservice_db_index: 2 # # trivy_db_index: 5 # # it's optional, the db for harbor business misc, by default is 0, uncomment it if you want to change it. # # harbor_db_index: 6 # # it's optional, the db for harbor cache layer, by default is 0, uncomment it if you want to change it. # # cache_db_index: 7 # Uncomment redis if need to customize redis db # redis: # # db_index 0 is for core, it's unchangeable # # registry_db_index: 1 # # jobservice_db_index: 2 # # trivy_db_index: 5 # # it's optional, the db for harbor business misc, by default is 0, uncomment it if you want to change it. # # harbor_db_index: 6 # # it's optional, the db for harbor cache layer, by default is 0, uncomment it if you want to change it. # # cache_layer_db_index: 7 # Uncomment external_redis if using external Redis server # external_redis: # # support redis, redis+sentinel # # host for redis: <host_redis>:<port_redis> # # host for redis+sentinel: # # <host_sentinel1>:<port_sentinel1>,<host_sentinel2>:<port_sentinel2>,<host_sentinel3>:<port_sentinel3> # host: redis:6379 # password: # # Redis AUTH command was extended in Redis 6, it is possible to use it in the two-arguments AUTH <username> <password> form. # # there's a known issue when using external redis username ref:https://github.com/goharbor/harbor/issues/18892 # # if you care about the image pull/push performance, please refer to this https://github.com/goharbor/harbor/wiki/Harbor-FAQs#external-redis-username-password-usage # # username: # # sentinel_master_set must be set to support redis+sentinel # #sentinel_master_set: # # db_index 0 is for core, it's unchangeable # registry_db_index: 1 # jobservice_db_index: 2 # trivy_db_index: 5 # idle_timeout_seconds: 30 # # it's optional, the db for harbor business misc, by default is 0, uncomment it if you want to change it. # # harbor_db_index: 6 # # it's optional, the db for harbor cache layer, by default is 0, uncomment it if you want to change it. # # cache_layer_db_index: 7 # Uncomment uaa for trusting the certificate of uaa instance that is hosted via self-signed cert. # uaa: # ca_file: /path/to/ca # Global proxy # Config http proxy for components, e.g. http://my.proxy.com:3128 # Components doesn't need to connect to each others via http proxy. # Remove component from `components` array if want disable proxy # for it. If you want use proxy for replication, MUST enable proxy # for core and jobservice, and set `http_proxy` and `https_proxy`. # Add domain to the `no_proxy` field, when you want disable proxy # for some special registry. proxy: http_proxy: https_proxy: no_proxy: components: - core - jobservice - trivy # metric: # enabled: false # port: 9090 # path: /metrics # Trace related config # only can enable one trace provider(jaeger or otel) at the same time, # and when using jaeger as provider, can only enable it with agent mode or collector mode. # if using jaeger collector mode, uncomment endpoint and uncomment username, password if needed # if using jaeger agetn mode uncomment agent_host and agent_port # trace: # enabled: true # # set sample_rate to 1 if you wanna sampling 100% of trace data; set 0.5 if you wanna sampling 50% of trace data, and so forth # sample_rate: 1 # # # namespace used to differenciate different harbor services # # namespace: # # # attributes is a key value dict contains user defined attributes used to initialize trace provider # # attributes: # # application: harbor # # # jaeger should be 1.26 or newer. # # jaeger: # # endpoint: http://hostname:14268/api/traces # # username: # # password: # # agent_host: hostname # # # export trace data by jaeger.thrift in compact mode # # agent_port: 6831 # # otel: # # endpoint: hostname:4318 # # url_path: /v1/traces # # compression: false # # insecure: true # # # timeout is in seconds # # timeout: 10 # Enable purge _upload directories upload_purging: enabled: true # remove files in _upload directories which exist for a period of time, default is one week. age: 168h # the interval of the purge operations interval: 24h dryrun: false # Cache layer configurations # If this feature enabled, harbor will cache the resource # `project/project_metadata/repository/artifact/manifest` in the redis # which can especially help to improve the performance of high concurrent # manifest pulling. # NOTICE # If you are deploying Harbor in HA mode, make sure that all the harbor # instances have the same behaviour, all with caching enabled or disabled, # otherwise it can lead to potential data inconsistency. cache: # not enabled by default enabled: false # keep cache for one day by default expire_hours: 24 # Harbor core configurations # Uncomment to enable the following harbor core related configuration items. # core: # # The provider for updating project quota(usage), there are 2 options, redis or db, # # by default is implemented by db but you can switch the updation via redis which # # can improve the performance of high concurrent pushing to the same project, # # and reduce the database connections spike and occupies. # # By redis will bring up some delay for quota usage updation for display, so only # # suggest switch provider to redis if you were ran into the db connections spike aroud # # the scenario of high concurrent pushing to same project, no improvment for other scenes. # quota_update_provider: redis # Or dbОтредактируйте файл
harbor.yml:заполните
hostnameкорректным адресом, для которого были сгенерированы сертификаты в разделе «Генерация сертификатов для реестра Harbor» выше;в секции
httpsзаполните полный путь до директорииcerts, которая была создана скриптомharbor_certs.shиз шага 2 в разделе «Генерация сертификатов для реестра Harbor» выше, для полейcertificateиprivate_key;поменяйте преднастроенный пароль администратора (по умолчанию
<harbor-admin-password>).
Запуск Harbor#
Создайте в каталоге
harborскриптharbor_install.sh:harbor_install.sh
#!/bin/bash set -e CONTAINER_ENGINE="podman" while [[ "$#" -gt 0 ]]; do case $1 in --container-engine) if [[ -n "$2" ]]; then CONTAINER_ENGINE="$2" shift else echo "Ошибка: Для --container-engine не указано значение." exit 1 fi ;; *) echo "Неизвестный параметр: $1" exit 1 ;; esac shift done if ! command -v "$CONTAINER_ENGINE" &> /dev/null; then echo "Ошибка: Команда '$CONTAINER_ENGINE' не найдена. Убедитесь, что она установлена." exit 1 fi echo "Используется контейнерный движок: $CONTAINER_ENGINE" if [[ -n "$HARBOR_BUNDLE_DIR" ]]; then harbor_prepare_path=$HARBOR_BUNDLE_DIR else harbor_prepare_path="$( cd "$(dirname "$0")" ; pwd -P )" fi echo "Подготовительная директория: ${harbor_prepare_path}" rm -rf ${harbor_prepare_path}/input mkdir -p ${harbor_prepare_path}/input input_dir=${harbor_prepare_path}/input if [[ ! "$1" =~ ^\-\- ]] && [ -f "$1" ] then cp $1 $input_dir/harbor.yml shift else if [ -f "${harbor_prepare_path}/harbor.yml" ];then cp ${harbor_prepare_path}/harbor.yml $input_dir/harbor.yml else echo "Не найден конфиг файл ${harbor_prepare_path}/harbor.yml" exit 1 fi fi data_path=$(grep '^[^#]*data_volume:' $input_dir/harbor.yml | awk '{print $NF}') echo "Директория с данными: ${data_path}" mkdir -p $data_path previous_secretkey_path=/data/secretkey previous_defaultalias_path=/data/defaultalias if [ -f $previous_secretkey_path ]; then mkdir -p $data_path/secret/keys mv $previous_secretkey_path $data_path/secret/keys fi if [ -f $previous_defaultalias_path ]; then mkdir -p $data_path/secret/keys mv $previous_defaultalias_path $data_path/secret/keys fi secret_dir=${data_path}/secret config_dir=$harbor_prepare_path/common/config mkdir -p $secret_dir mkdir -p $config_dir $CONTAINER_ENGINE run --rm -v $input_dir:/input \ -v $data_path:/data \ -v $harbor_prepare_path:/compose_location \ -v $config_dir:/config \ -v /:/hostfs \ --privileged \ sberworks.ru/k8sf/2.2.3/dapp-harbor/prepare:v2.9.3 prepare --with-trivy echo "Удаляем input директорию" rm -rf ${harbor_prepare_path}/input sed -i 's|goharbor/trivy-adapter-photon:v2.9.3|sberworks.ru/k8sf/2.2.3/dapp-harbor-scanner-trivy/harbor-scanner-trivy:0.30.22|g' docker-compose.yml sed -i 's|goharbor|sberworks.ru/k8sf/2.2.3/dapp-harbor|g' docker-compose.yml sed -i 's|photon|fstec|g' docker-compose.yml sed -i 's|"syslog"|"journald"|g' docker-compose.yml sed -i '/syslog-address:/d' docker-compose.yml sudo chmod -R 777 ./data_harbor/database sudo chmod -R 777 ./data_harbor/redis mkdir ${data_path}/cert sudo cp certs/* ${data_path}/cert/ sudo chown -R 10000:10000 ${data_path}/cert/ sudo chmod -R 777 ${data_path}/cert/ echo "Запускаем Harbor" sudo $CONTAINER_ENGINE compose up -dЗапустите скрипт
harbor_install.sh:./harbor_install.sh --container-engine <docker|podman>
Валидация установки#
Выполните sudo <docker|podman> compose ps и убедитесь, что все контейнеры запущены, рестартов нет:
sudo podman compose ps
Пользовательский интерфейс Harbor будет доступен в браузере по адресу, который был указан в harbor.yml, например https://harbor.bootstrap.domain.ru.
Создание проекта для образов#
Зайдите в пользовательский интерфейс Harbor под учетной записью администратора и создайте проект dapp:

Загрузка образов в стартовый реестр Harbor#
Разархивируйте архив k8sf-binaries-2.2.3-distrib.zip и получите утилиту Dactl, выполнив шаги из подраздела «Предварительные условия».
Выполните вход в созданный реестр. Логин (Username) - это admin, пароль установлен в harbor.yml поле harbor_admin_password:
podman login harbor.bootstrap.domain.ru
Username: admin
Password:
Login Succeeded!
Запустите копирование образов в созданный реестр:
./dactl copy images --src ../images --dest harbor.bootstrap.domain.ru/dapp
Примечание
Поскольку этот Harbor является стартовым, он может не включать базу данных Trivy из состава поставки DropApp.
В случае необходимости добавления базы данных Trivy в созданный Harbor, воспользуйтесь утилитой Cosign из поставки DropApp.
Для добавления Trivy воспользуйтесь сценарием:
Разархивируйте содержимое
trivy-db.tar:tar xvf ./images/trivy-db.tarИспользуя утилиту Cosign, загрузите каталог в реестр, там он будет храниться в виде образа:
./cosign-linux-amd64 load --dir ./trivy-db harbor.bootstrap.domain.ru/dapp/2.2.3-fstec/trivy-db:2 --allow-insecure-registry=true
Стартовый реестр Harbor установлен.
Создание robot-аккаунта для доступа в проект dapp#
Чтобы стягивать образы из реестра создайте robot-аккаунт в Harbor для проекта dapp.
Для этого зайдите в проект dapp, перейдите на вкладку «Robot Accounts» и создайте аккаунт dapp-guest с ограниченными правами на read, pull, list и create/stop scan:

Нажмите кнопку Add и сохраните secret - он понадобится для работы реестра кластера.
RPM репозиторий#
Загрузите необходимые RPM-пакеты из репозитория продукта в репозиторий пользователя.
Примечание
RPM-репозиторий поставляется в составе дистрибутива отдельным архивом. Пример названия - k8sf-rpms-2.2.3-distrib.zip.
Настройки node кластера#
Следующие настройки node кластера устанавливаются автоматически при развертывании кластера с помощью Dactl:
Включение IPv6;
Отключение использования
swap;Переадресация IPv4;
Загрузка модулей
br_netfilterиoverlay;Проверка системных переменных.
Подготовка и запуск основного реестра Harbor#
Основной реестр Harbor будет установлен в отдельный кластер DropApp.
Данный кластер будет использоваться Harbor, а не пользовательскими приложениями. С помощью Harbor будет осуществляться эксплуатация пользовательских приложений в основном кластере DropApp.
Подготовка#
Для того чтобы начать установку отдельного кластера требуется машина администратора кластера, с которой будет запускаться утилита Dactl. Эта машина должна быть:
в одном сетевом контуре с будущими nodes кластера;
в одном сетевом контуре со стартовым реестром Harbor, куда загружены образы контейнеров DropApp;
на архитектуре linux x86 amd64 (например, ОС Platform V SberLinux OS Server)
Примечание
Эта машина не будет node будущего кластера. На эту машину будут сохранены артефакты установки: kubeconfig реестра кластера, файл с паролем сервисного пользователя - администратора кластера для доступа в UI консоль.
Машины для реестра кластера#
Создание SSH-ключа#
Сгенерируйте пару SSH-ключей, используя команду ssh-keygen.
Для генерации SSH-ключей с использованием RSA используйте команду:
ssh-keygen -t rsa -b 4096 -C "your_email@example.com" -f ~/.ssh/id_dappДля генерации SSH-ключей с использованием Ed25519 используйте команду:
ssh-keygen -t ed25519 -C "your_email@example.com" -f ~/.ssh/id_dapp
Используемые в примерах параметры:
-t - тип ключа, например rsa или ed25519;
-b - длина ключа (для RSA рекомендуется 4096 бит);
-C - комментарий, обычно email;
-f - путь и имя файла для сохранения ключей.
Создание машин#
Для основного реестра Harbor достаточно две машины - control plane и worker.
Значение |
Размер |
|---|---|
ЦПУ [CPU] (в ядрах) |
4 (с поддержкой VT*) |
ОЗУ [RAM] |
8192 Мб |
Размер диска [HDD/SSD] |
15 Гб |
Значение |
Размер |
|---|---|
ЦПУ [CPU] (в ядрах) |
4 (с поддержкой VT*) |
ОЗУ [RAM] |
16000 Мб |
Размер диска [HDD/SSD] |
50 Гб |
На каждой машине:
создайте пользователя
dapp;поместите публичный ключ
~/.ssh/id_dapp.pubв домашний каталог;обеспечьте пользователю беспарольный
sudo;обеспечьте доступ к необходимой сети и IP адрес каждой машине, доступный с машины администратора.
Остальные настройки обеспечит Dactl.
Важно!
Образы DropApp занимают примерно 25 Гб. Планируйте место в своём хранилище с учетом объема образов, а также с учетом того, что сертифицированный кластер должен брать образы из этого Harbor. Значит все образы пользовательских приложений тоже должны храниться в устанавливаемом Harbor.
Формирование конфигурационного файла DropAppConfiguration#
Перед формированием конфигурационного файла DropAppConfiguration для Dactl, убедитесь в наличии:
стартового реестра Harbor с образами контейнеров
K8S-2.2.3-fstec-58-distrib.zip, напримерharbor.bootstrap.domain.ru/dapp;сертификат от реестра, например в каталоге
./harbor/certs/harbor.crtна машинеbootstrap Harbor registry;репозиторий с RPM-пакетами
K8S-2.2.3-fstec-58-distrib.zip, напримерhttp://my-rpm-repo.com/dapp/2.2.3-fstec;репозиторий с baseos RPM-пакетами Platform V SberLinux OS Server, например
http://my-rpm-repo.com/SLO/9.1-fstec, в этом репозитории есть зависимости дляK8S-2.2.3-fstec-58-distrib.zip;две машины с пользователем
dapp, пример адресов00.00.10.01и00.00.10.02;адрес пула
metallb, для секцииspec.network.metallb;LDAP-каталог с пользователями, настроенный по инструкции, например его адрес
freeipa.fstec.domain.ru.
Создайте конфигурационный файл da-harbor.yaml:
da-harbor.yaml
apiVersion: config.dropapp.ru/v1alpha1
kind: DropAppConfiguration
metadata:
name: "registry"
spec:
network:
publicDomain: domain.ru
metallb:
pools:
- addresses: "00.00.00.31/32"
name: "dapp"
l2Advertisement: true
artifacts:
imageRegistry:
host: harbor.bootstrap.domain.ru
path: dapp
credentials: ZEh...Q== # токен аутентификации в base64, в нашем примере это echo -n 'robot$dapp-guest:fvnk38AJmTv3behe1pLFaYqjidfJSiNe' | base64 -w0 | base64 -w0
certificate: <cert-part>... # cat harbor.crt | base64 -w0
rpmRepository:
- name: "dapp-2.2.3-fstec"
baseUrl: http://my-rpm-repo.com/dapp/2.2.3-fstec
gpgCheck: 1
enabled: 1
gpgKey: "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-SberLinux"
- name: "slo-baseos-9.1-fstec"
baseUrl: http://my-rpm-repo.com/SLO/9.1-fstec
gpgCheck: 1
enabled: 1
gpgKey: "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-SberLinux"
compute:
sshAccess:
user: dapp
privateKeyPath: "~/.ssh/id_dapp"
userProvisioned:
nodes:
controlPlane:
- ip: "00.00.10.01"
nodePool: "control-plane"
worker:
- ip: "00.00.10.02"
nodePool: "worker"
k8s:
podSubnetCIDR: 00.000.0.0/16 # можно настроить сеть для pods
serviceSubnetCIDR: 00.00.0.1/16 # можно настроить сеть для сервисов
# если необходимо, настраиваем ingressTLS, если не указан, то будет сгенерирован автоматически
ingressTLS:
cert: <ingressTLS-cert>...
key: <ingressTLS-key>...
# настраиваем аудит для kube-apiserver
apiServer:
extraArgs:
audit-policy-file: "/etc/kubernetes/policies/audit-policy.yaml"
audit-log-path: "/var/log/kubernetes/audit.log"
audit-log-format: "json"
audit-log-maxbackup: "5"
audit-log-maxsize: "128"
audit-log-maxage: "7"
audit-log-mode: "batch"
extraVolumes:
- name: policies
hostPath: /etc/kubernetes/policies
mountPath: /etc/kubernetes/policies
- name: kube-audit
hostPath: /var/log/kubernetes
mountPath: /var/log/kubernetes
# подключение LDAP каталога
components:
- name: auth
tools:
- name: dex
values:
config:
connectors:
- type: ldap
name: Ipa Server
id: ldap
config:
bindDN: uid=dapp-sync-svc,cn=users,cn=accounts,dc=dapp,dc=un,dc=sbt
bindPW: qwerty12345
groupSearch:
baseDN: cn=groups,cn=accounts,dc=dapp,dc=un,dc=sbt
filter: (objectClass=groupOfNames)
nameAttr: cn
userMatchers:
- groupAttr: member
userAttr: DN
host: freeipa.fstec.domain.ru:636
insecureNoSSL: false
insecureSkipVerify: true
userSearch:
baseDN: cn=users,cn=accounts,dc=dapp,dc=un,dc=sbt
emailAttr: mail
filter: (objectClass=person)
idAttr: DN
nameAttr: uid
preferredUsernameAttr: uid
username: uid
usernamePrompt: 'Username:'
Запуск установки кластера#
Для установки кластера выполните команду:
./dactl create cluster --config ./da-harbor.yaml
В конце установки появится сообщение:
======================================
Done! DropApp cluster with name 'registry' and version '2.2.3-fstec' is successfully installed!
Next steps are:
- Cluster config is stored to this machine as /home/dapp/.dropapp/registry/kubeconfig
you may need to export this path to the KUBECONFIG environment variable
or copy it as '~/.kube/config'
otherwise use it as --kubeconfig parameter value for kubectl or dactl commands
- Check pods and nodes by executing `kubectl get pods -A; kubectl get nodes`
- Check installed Platform V DropApp components by executing `kubectl get components -o wide`
- Check installed Platform V DropApp tools by executing `kubectl get tools -o wide`
- Visit Platform V DropApp UI: https://console.fstec-cluster.domain.ru
login: kubeadmin
password is stored in: /home/dapp/.dropapp/registry/kubeadmin-password
Артефакты установки#
По выполнению установки артефактами являются:
конфигурационный файл от кластера:
/home/dapp/.dropapp/registry/kubeconfig;суперадмин
kubeadmin, пароль для учетной записи в файле/home/dapp/.dropapp/registry/kubeadmin-password, этот пароль можно использовать для доступа в пользовательскую консоль по адресу из примераhttps://console.fstec-cluster.domain.ru.
Установка основного реестра Harbor#
Создадайте манифест tool-harbor.yaml, настройте в нем пароль для доступа к базе данных trivy-db, которую пользователь расположил в стартовом реестре Harbor:
apiVersion: config.dropapp.ru/v1alpha1
kind: Tool
metadata:
name: "harbor"
Для установки инструмента Harbor примените манифест, используя Kubectl из дистрибутива поставки:
kubectl apply -f tool-harbor.yaml
Проверка установки#
Дождитесь установки pods Harbor:
kubectl get pods -n dapp-security
Pods Harbor устанавливаются в namespace dapp-security, этот namespace создается в процессе установки кластера автоматически.
Все pods должны получить статус Running и Ready, это означает, что основной реестр Harbor, предназначенный для эксплуатации основных кластеров Platform V DropApp 2.2.3-fstec-1 установлен.
Использование постоянного хранилища#
После установки основного реестра Harbor, инструмент Harbor разворачивается с использованием томов EmptyDir. Для промышленной эксплуатации необходимо переконфигурировать их на использование постоянных томов - Persistent Volumes. В результате создания кластера с утилитой Dactl по умолчанию создается StorageClass local-storage.
Для этого необходимо:
Установить и настроить
StorageProvider. В составе DropApp используется Trident, при необходимости можно использовать иной адаптер.Зарегистрировать
StorageClass- в результате создания кластера с утилитой Dactl по умолчанию создаетсяStorageClasslocal-storage.Настроить
Persistent Volume Claimsдля использованияStorageClassPersistent Volumes.
Настройка постоянного хранилища для Harbor#
Создайте файл
tool-harbor-persistence.yamlи настройтеpersistenceдля Harbor:tool-harbor-persistence.yaml
apiVersion: config.dropapp.ru/v1alpha1 kind: Tool metadata: name: harbor spec: values: persistence: enabled: true persistentVolumeClaim: registry: storageClass: "openebs-hostpath" # openebs в качестве примера accessMode: ReadWriteOnce size: 15Gi jobservice: jobLog: storageClass: "openebs-hostpath" accessMode: ReadWriteOnce size: 1Gi database: storageClass: "openebs-hostpath" # openebs в качестве примера accessMode: ReadWriteOnce size: 1Gi redis: storageClass: "openebs-hostpath" # openebs в качестве примера accessMode: ReadWriteOnce size: 1Gi trivy: storageClass: "openebs-hostpath" # openebs в качестве примера accessMode: ReadWriteOnce size: 1GiПримечание
Просто обновить конфигурацию не получится, так как Kubernetes не позволяет обновлять разделы
volumeдляStatefulSet, в данном случае этоharbor_database,harbor_registry,harbor_jobservice,harbor_trivy, поэтому нужно удалить инструмент Harbor.Удалите инструмент Harbor:
kubectl delete tool harborПересоздайте ресурсы конфигурационного файла с персистентным хранилищем, применив манифест:
kubectl apply -f ./tool-harbor-persistence.yaml
Ресурсы инструмента Harbor будут пересозданы.
Доступ в Harbor#
Пользовательский интерфейс Harbor будет доступен по адресу: https://harbor.registry.domain.ru.
Доступ в пользовательский интерфейс Harbor происходит через LDAP-каталог, настроенный при установке кластера. По ролевой модели администратор Harbor должен быть LDAP-пользователь с ролью harbor-sysadmin.
Получите для него сертификат с помощью команды:
kubectl get secret ingress-tls -n dapp-security -o jsonpath="{.data['tls\.crt']}"
Полученную base64-строку используйте для конфигурации секции imageRegistry для основного кластера DropApp.
Создание проекта для образов#
Зайдите в пользовательский интерфейс Harbor администратором и создайте проект dapp:

Создание robot-аккаунта для доступа в проект dapp#
Чтобы стягивать образы из реестра создайте robot-аккаунт в Harbor для проекта dapp.
Для этого зайдите в проект dapp, перейдите на вкладку «Robot Accounts» и создайте аккаунт dapp-guest с ограниченными правами на read, pull, list и create/stop scan:

Нажмите кнопку Add и сохраните secret - он понадобится для работы реестра кластера.
Для подключения robot-аккаунта для Harbor выполните следующие шаги:
Создайте файл
robot-harbor.yamlс манифестом:robot-harbor.yaml
apiVersion: config.dropapp.ru/v1alpha1 kind: Tool metadata: name: harbor spec: values: trivy: trivy_db: harbor.registry.domain.ru/dapp/2.2.3-fstec/trivy-db trivyDBImagePullSecret: enabled: true username: robot$dapp+dapp-guest password: <password> # пароль secret полученный при добавлении робот аккаунта registry: harbor.registry.domain.ruПримените файл:
kubectl apply -f robot-harbor.yaml
Загрузка образов в основной реестр Harbor#
Загрузка образов контейнеров#
На машине администратора получите сертификат для Harbor:
kubectl get secret ingress-tls -n dapp-security -o jsonpath="{.data['tls\.crt']}" | base64 --decode > harbor-fstec.crtСоздадайте каталог для сертификата:
для
container-engineDocker:sudo mkdir -p /etc/docker/certs.d/harbor.registry.domain.ru sudo cp ./harbor-fstec.crt /etc/docker/certs.d/harbor.registry.domain.ru/ca.crt sudo systemctl restart dockerддля
container-enginePodman:sudo mkdir -p /etc/containers/certs.d/harbor.registry.domain.ru sudo cp ./harbor-fstec.crt /etc/containers/certs.d/harbor.registry.domain.ru/ca.crt sudo systemctl restart podman
Выполните вход в созданный реестр:
podman login harbor.registry.domain.ru Username: admin Password: Login Succeeded!Учетной записью может быть:
admin, с паролем по умолчанию<harbor-admin-password>;LDAP-пользователь с паролем, который он получает в пользовательском меню Harbor (не LDAP-паролем).
Запустите копирование образов в созданный реестр:
./dactl copy images --src ../images --dest harbor.registry.domain.ru/dapp
Результатом выполнения описанных шагов будет являться основной реестр Harbor с образами для установки основного кластера DropApp.
Загрузка образа Trivy-db#
Образ Trivy-db - не классический docker-образ и имеет отличную от других образов структуру. Его нельзя стянуть, используя Docker, Podman или Crictl - Trivy стягивает его своими способами. При этом, dactl copy images не копирует его вместе с другими образами в реестр. Загрузить его нужно отдельно утилитой Cosign-linux-amd64 из состава поставки.
Разархивация trivy-db.tar#
Разархивируйте содержимое trivy-db.tar:
tar xvf ./images/trivy-db.tar
Загрузка trivy-db в реестр образов#
Используя утилиту Cosign загрузите каталог в реестр, там он будет храниться в виде образа:
./cosign-linux-amd64 load --dir ./trivy-db harbor.registry.domain.ru/dapp/2.2.3-fstec/trivy-db:2 --allow-insecure-registry=true
Сам путь до базы данных Trivy прописан по умолчанию в скрытых values инструмента Harbor, отдельно настраивать не нужно.
Подпись загруженных образов с Cosign#
Для подписи образов воспользуйтесь утилитой Cosign-linux-amd64 из состава поставки.
Генерация подписи#
На машине администратора создайте каталог cosign_prepare и создайте в ней скрипт generate_sign.sh.
generate_sign.sh
#!/bin/bash
# Функция для вывода справки
usage() {
echo "Использования: $0 --passphrase <your_passphrase>"
exit 1
}
# Проверка наличия аргументов
if [ "$#" -lt 2 ]; then
usage
fi
# Парсинг аргументов командной строки
while [[ "$#" -gt 0 ]]; do
case $1 in
--passphrase)
PASSPHRASE="$2"
shift 2
;;
*)
echo "Неизвестный параметр: $1"
usage
;;
esac
done
# Проверка, что passphrase был передан
if [ -z "$PASSPHRASE" ]; then
echo "Ошибка: Passphrase обязательный параметр."
usage
fi
echo "Генерирую pkey через openssl"
openssl genpkey -algorithm ed25519 -out private.pem
# Импорт ключевой пары с помощью cosign
echo "Импортирую ключ в cosign"
echo "$PASSPHRASE" | ./cosign-linux-amd64 import-key-pair --key private.pem --output-key-prefix cosign
Запустите скрипт generate_sign.sh, передав в параметр --passphrase секретный пароль для подписи, например:
chmod +x ./generate_sign.sh
./generate_sign.sh --passphrase dropapp
Результатом будет пара ключей:
cosign.key
cosign.pub
Все образы, которые были загружены в harbor.registry.domain.ru, нужно подписать с ключом cosign.key. Для этого создайте скрипт sign_images.sh
generate_sign.sh
#!/bin/bash
# Функция для вывода справки
usage() {
echo "Использование: $0 --harbor-url URL --harbor-project PROJECT --harbor-path PATH --cosign-key KEY --username USER --password PASS --passphrase PHRASE"
exit 1
}
# Проверка наличия аргументов
if [[ $# -eq 0 ]]; then
usage
fi
# Парсинг аргументов
while [[ $# -gt 0 ]]; do
case "$1" in
--harbor-url)
HARBOR_URL=$2
shift 2
;;
--harbor-project)
HARBOR_PROJECT=$2
shift 2
;;
--harbor-path)
HARBOR_PATH=$2
shift 2
;;
--cosign-key)
COSIGN_KEY=$2
shift 2
;;
--username)
USERNAME=$2
shift 2
;;
--password)
PASSWORD=$2
shift 2
;;
--passphrase)
PASSPHRASE=$2
shift 2
;;
*)
echo "Неизвестный параметр: $1"
usage
;;
esac
done
# Проверка обязательных параметров
if [[ -z "$HARBOR_URL" || -z "$HARBOR_PROJECT" || -z "$HARBOR_PATH" || -z "$COSIGN_KEY" || -z "$USERNAME" || -z "$PASSWORD" || -z "$PASSPHRASE" ]]; then
echo "Ошибка: Не все обязательные параметры указаны."
usage
fi
# Функция для кодирования символов в URL
urlencode() {
local string="${1}"
local strlen=${#string}
local encoded=""
for (( pos=0 ; pos<strlen ; pos++ )); do
c=${string:$pos:1}
case "$c" in
[-_.~a-zA-Z0-9] ) o="${c}" ;;
* ) printf -v o '%%%02x' "'$c" ;;
esac
encoded+="${o}"
done
echo "${encoded}"
}
# Функция для получения списка репозиториев из проекта с фильтром по пути
get_repository_list() {
local url="https://${HARBOR_URL}/api/v2.0/projects/${HARBOR_PROJECT}/repositories?page_size=100&name=~${HARBOR_PATH}"
curl -s -k -u "${USERNAME}:${PASSWORD}" "${url}" | jq -r '.[].name' | grep "/${HARBOR_PATH}"
}
# Функция для получения тегов репозитория
get_repository_tags() {
local repository=$1
# Убираем имя проекта и кодируем символ /
local encoded_repo=$(urlencode "${repository#${HARBOR_PROJECT}/}")
local url="https://${HARBOR_URL}/api/v2.0/projects/${HARBOR_PROJECT}/repositories/${encoded_repo}/artifacts"
curl -s -k -u "${USERNAME}:${PASSWORD}" "${url}" | jq -r '.[].tags[].name'
}
# Функция для подписания образа с помощью cosign
sign_image_with_cosign() {
local image_name=$1
echo "$PASSPHRASE" | ./cosign-linux-amd64 sign --key "${COSIGN_KEY}" "${image_name}" --registry-username $USERNAME --registry-password $PASSWORD --tlog-upload=false --allow-insecure-registry
}
# Основной скрипт
echo "Получение списка репозиториев..."
# Получаем список репозиториев с фильтром по пути
REPOSITORIES=$(get_repository_list)
if [[ -z "$REPOSITORIES" ]]; then
echo "Ошибка: Не найдено репозиториев в проекте '$HARBOR_PROJECT' с путем '$HARBOR_PATH'."
exit 1
fi
echo "Репозитории: $REPOSITORIES"
# Для каждого репозитория получаем теги и подписываем образы
for REPO in $REPOSITORIES; do
echo "Обрабатывается репозиторий: $REPO"
TAGS=$(get_repository_tags "$REPO")
if [[ -z "$TAGS" ]]; then
echo " Теги не найдены."
continue
fi
for TAG in $TAGS; do
echo " Найден тег: $TAG"
FULL_IMAGE_NAME="${HARBOR_URL}/${REPO}:${TAG}"
echo " Подписываю образ $FULL_IMAGE_NAME"
sign_image_with_cosign "$FULL_IMAGE_NAME"
done
done
echo "Подписание завершено."
Запустите скрипт, передав в параметры адрес реестра, логин и пароль, имя созданного проекта, ключ cosign и секретный пароль:
chmod +x ./sign_images.sh
./sign_images.sh \
--harbor-registry harbor.registry.domain.ru \
--harbor-project dapp \
--harbor-path 2.2.3-fstec \
--cosign-key cosign.key \
--username admin \
--password <harbor-admin-password> \
--passphrase dropapp
Результатом вывода будет:
Получение списка репозиториев...
...
Подписание завершено.
Подготовка окружения завершена.
Результатом подготовки окружения являтся безопасно настроенный реестр образов, который можно использовать для установки основного кластера DropApp.