Установка и запуск Garage S3 в Kubernetes с помощью Helm
Опубликовано:
Используемые термины: Kubernetes, Helm.
В этой инструкции развернём S3-совместимое хранилище Garage в кластере Kubernetes через Helm, настроим топологию узлов и опубликуем сервис наружу через Ingress. Garage — это лёгкая, geo-distributed система хранения объектов, совместимая с S3 API.
Предварительные действия
Установка Garage S3
Настройка топологии и репликации
Создание ключа доступа
Создание бакета и выдача прав
Публикация через Ingress
Подготовка окружения
Создадим каталог для установки и перейдём в него:
mkdir -p /opt/helm && cd /opt/helm
Склонируем репозиторий с Helm-чартом Garage:
git clone https://git.deuxfleurs.fr/Deuxfleurs/garage
Перейдём в каталог с чартом:
cd garage/script/helm
Установка Garage через Helm
Рассмотрим 2 варианта установки: с переопределением параметров опцией --set и через создание отдельного файла
Установка с использованием опции --set
Установим Garage в отдельный namespace, сразу задав размеры томов под данные и метаданные:
helm install --create-namespace --namespace garage garage ./garage --set persistence.data.size=50Gi --set persistence.meta.size=5Gi
* размеры томов подбираем под объём хранимых данных — persistence.data.size под сами объекты, persistence.meta.size под метаданные много места не нужно. На практике в Garage рекомендуется указывать емкость data.size, максимально близкую к реальному доступному размеру файловой системы.
Убедимся, что поды запустились:
kubectl get pods -n garage
Мы должны увидеть что-то на подобие:
NAME READY STATUS RESTARTS AGE
garage-0 1/1 Running 0 5m
garage-1 1/1 Running 0 5m
garage-2 1/1 Running 0 5m
* в колонке READY мы должны видеть 1/1, а STATUS — Running.
Проверим статус узлов кластера:
kubectl exec -it -n garage garage-0 -- ./garage status
Мы должны увидеть три узла без назначенной роли:
ID Hostname Address Tags Zone Capacity DataAvail Version
7d05699d9f1173a7 garage-2 10.42.0.43:3901 NO ROLE ASSIGNED v2.3.0
b672bea7a1cfd055 garage-0 10.42.0.37:3901 NO ROLE ASSIGNED v2.3.0
eb236c280f257190 garage-1 10.42.0.40:3901 NO ROLE ASSIGNED v2.3.0
Установка через values.yaml
Флаги --set удобны для быстрого теста, но в продакшене параметры стоит хранить в отдельном файле — так их проще версионировать и переиспользовать. Создадим файл values.yaml:
vi values.yaml
persistence:
data:
size: 50Gi
storageClass: local-path
meta:
size: 5Gi
storageClass: local-path
replicaCount: 3
resources:
limits:
cpu: "1"
memory: 1Gi
requests:
cpu: "250m"
memory: 256Mi
* storageClass указываем свой — тот, что доступен в кластере; список доступных классов хранилищ можно командой kubectl get storageclass.
local-path создаёт том непосредственно на диске той ноды, где запущен под — это не распределённое хранилище. Если нода выйдет из строя, под с этим томом не сможет переехать на другой узел: данные физически останутся привязаны к упавшей машине. Для продакшена стоит рассмотреть распределённое хранилище (Rook/Ceph, Longhorn) — тогда данные реплицируются между узлами и под может безопасно мигрировать. Если сознательно остаётесь на local-path, привяжите под к конкретной ноде через nodeAffinity — так поды и данные всегда будут разъезжаться синхронно, без попыток бесполезного failover.
Установим Garage, указав файл вместо отдельных --set:
helm install --create-namespace --namespace garage garage ./garage -f values.yaml
Если понадобится изменить параметры уже работающего кластера — правим values.yaml и используем команду:
helm upgrade -n garage garage ./garage -f values.yaml
... а не переустанавливаем чарт заново.
Чарт установлен с параметрами из файла.
Настройка топологии и репликации
Каждому узлу назначим ёмкость и зону. Именно на этом шаге задаётся схема репликации данных между узлами — Garage распределяет копии объектов по зонам, поэтому от разбивки на зоны напрямую зависит отказоустойчивость хранилища:
kubectl exec -it -n garage garage-0 -- ./garage layout assign 7d05699d9f1173a7 -c 50G -z local
kubectl exec -it -n garage garage-0 -- ./garage layout assign b672bea7a1cfd055 -c 50G -z local
kubectl exec -it -n garage garage-0 -- ./garage layout assign eb236c280f257190 -c 50G -z local
* в нашем примере все три узла находятся в одной зоне local — для полноценной геораспределённой репликации узлы стоит разносить по разным зонам.
** 50G в layout assign — это десятичные гигабайты (10? байт), а 50Gi в values.yaml — бинарные (2³? байт, на ~7% больше). Для двух-трёх узлов разница несущественна, но при расчёте ёмкости на больших объёмах данных её стоит учитывать отдельно и не считать значения взаимозаменяемыми.
*** обратите внимание, что идентификаторы нужно заменить на свои.
Применим новую топологию:
kubectl exec -it -n garage garage-0 -- ./garage layout apply --version 1
Топология кластера настроена.
Создание ключа доступа
Создадим ключ, через который приложения будут обращаться к хранилищу по S3 API:
kubectl exec -it -n garage garage-0 -- ./garage key create kube-key
Мы должны увидеть Key ID и Secret key — их понадобится сохранить для подключения клиентов:
==== ACCESS KEY INFORMATION ====
Key ID: GK9c076c849021ec2491343722
Key name: kube-key
Secret key: d9941f32c37c4945ddaeb1e05660cb61f596febd74281b849c767a49e9bb8e7b
Created: 2026-07-08 14:17:32.956 +00:00
Validity: valid
Expiration: never
Создание бакета и выдача прав
Создадим бакет для хранения объектов:
kubectl exec -it -n garage garage-0 -- ./garage bucket create kube-bucket
Выдадим созданному ключу права на чтение и запись в этот бакет:
kubectl exec -it -n garage garage-0 -- ./garage bucket allow kube-bucket --read --write --key kube-key
Ещё раз проверим статус — теперь у всех узлов должна быть назначена роль:
kubectl exec -it -n garage garage-0 -- ./garage status
Хранилище готово к работе.
Публикация через Ingress
Чтобы обращаться к Garage по S3 API снаружи кластера, опубликуем сервис через Ingress — он выступит reverse proxy и шлюзом (gateway) между внешними клиентами и подами Garage. Создадим файл описания:
vi ingress.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: garage-ingress
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: websecure
traefik.ingress.kubernetes.io/router.tls.certresolver: default
spec:
ingressClassName: traefik
tls:
- hosts:
- s3.dmosk.ru
secretName: garage-tls-cert
rules:
- host: s3.dmosk.ru
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: garage
port:
name: s3-api
* домен s3.dmosk.ru указываем свой — под конкретный домен и используемый certresolver.
Применим конфигурацию:
kubectl apply -n garage -f ingress.yml
Установка завершена.
Мы можем пробовать подключиться к настроенному S3. Пример настроек, которые нужно указать в приложении для подключения:
- API URL (Endpoint): https://s3.dmosk.ru
- Key ID (Access Key): GK9c076c849021ec2491343722
- Secret key (Secret Key): d9941f32c37c4945ddaeb1e05660cb61f596febd74281b849c767a49e9bb8e7b
- Region: garage
- Path style: path
- Security: SSL/TLS
Замените значения пути и ключей на свои. В качестве приложения на Windows для проверки можно использовать S3 Browser или WinSCP.