Как стать автором
Обновить
Флант
DevOps-as-a-Service, Kubernetes, обслуживание 24×7

Готовим Gitea со вкусом werf CI/CD и Dex-авторизации в кластере Deckhouse Kubernetes Platform. Часть 1

Уровень сложностиСредний
Время на прочтение13 мин
Количество просмотров3.5K

Всем привет! На связи Виктор Ашакин, DevOps-инженер компании «Флант». Периодически к нам приходят клиенты с вопросом поиска альтернативы GitLab, GitHub c блэкджеком удобным CI\CD и on-premise размещением. Наш взгляд пал на Open Source-инструмент Gitea.

Gitea — достаточно популярное решение, у него 44,6K звёзд на GitHub. Приложение написано на Go, легковесно и не требовательно к системным ресурсам. В сравнении с GitLab, который под капотом имеет сложный комбайн из технологий, сервис Gitea прост и потребляет в два раза меньше ресурсов. Конечно, его можно прокачать по вкусу с помощью кэширующего кластера Redis или отказоустойчивого кластера PostgreSQL. Это добавит определённую гибкость, но для большинства потребителей будет избыточно.

Gitea имеет схожий с GitHub интерфейс и функционал. CI/CD Gitea Actions — практически полный аналог GitHub Actions и в большинстве с ним совместим. За период работы с Gitea Actions из отличий я нашёл только отсутствие функционала repository_dispatch, но и он планируется к внедрению в версии 1.23. Также Gitea можно использовать, как OAuth 2.0 authentication identity provider, что даёт нам функционал Authentication, Аuthorization and Аccounting (AAA), то есть аутентификацию, авторизацию и управление пользователями, и может являться единой точкой входа для доступа к сторонним веб-ресурсам (SSO).

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

В первой части статьи будет описано, как установить и настроить сервер Gitea, а также как с помощью него организовать авторизацию через Dex в кластере Deckhouse Kubernetes Platform (DKP). Во второй и третьей части настроим Gitea act_runner и подготовим Gitea Actions-пайплайн, в котором развернём в кластере приложение с помощью werf.

Установка и серверы Gitea

В работе нам понадобятся серверы для Gitea и Gitea act_runner, а также кластер Deckhouse Kubernetes Platform. Разумеется, последний пригодится только в случае, если вам нужен Kubernetes. А если нет, то Gitea отлично работает без него, и вы можете воспользоваться этой инструкцией для установки сервиса, хотя часть функционала при этом использоваться не будет. 

Как развернуть кластер DKP, подробно описано в статье моего коллеги, так что сосредоточусь на двух первых пунктах. Здесь я расскажу о настройке сервера Gitea, а к act_runner вернёмся во второй части.

Подготовка

Для Gitea нам понадобится сервер, соответствующий следующим минимальным требованиям:

  • не менее 2 ядер CPU;

  • не менее 4 ГБ RAM;

  • не менее 20 ГБ дискового пространства;

  • сконфигурированный доступ по SSH.

В качестве ОС я остановился на Ubuntu 22.04, но можно выбрать то, что вам больше по душе: Linux, Windows, macOS, FreeBSD и так далее.

Установка и настройка БД

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

Gitea поддерживает следующие СУБД: PostgreSQL (⩾12), MySQL (⩾ 8.0), MariaDB (⩾ 10.4), SQLite (builtin) и MSSQL (⩾ 2012 SP4). Я буду использовать MySQL 8.1.

Первым делом заходим на сервер Gitea и выполняем команды по установке пакетов MySQL:

apt update
apt install mysql-common=5.8+1.0.8 mysql-server-8.0=8.0.28-0ubuntu4 mysql-client-8.0=8.0.28-0ubuntu4 mysql-server-core-8.0=8.0.28-0ubuntu4 mysql-client-core-8.0=8.0.28-0ubuntu4
# Фиксируем версию mysql (это опционально)
apt-mark hold mysql-common=5.8+1.0.8 mysql-server-8.0=8.0.28-0ubuntu4 mysql-client-8.0=8.0.28-0ubuntu4 mysql-server-core-8.0=8.0.28-0ubuntu4 mysql-client-core-8.0=8.0.28-0ubuntu4

Создаём базу данных и её пользователя, под которым сервис Gitea будет заходить в MySQL. Для этого и нам нужно зайти в MySQL:

$ mysql
# Смена пароля для пользователя root
ALTER USER 'root'@'localhost' IDENTIFIED BY '<your_secret_root_password>';
FLUSH PRIVILEGES;

# Создание пользователя БД gitea
CREATE USER 'gitea'@'%' IDENTIFIED BY '<your_secret_gitea_password>';

# Создание инстанса БД
CREATE DATABASE giteadb CHARACTER SET 'utf8mb4' COLLATE 'utf8mb4_bin';

# Добавление прав на БД
GRANT ALL PRIVILEGES ON giteadb.* TO 'gitea'@'%';
FLUSH PRIVILEGES;

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

Установка Gitea

Для установки Gitea нужно скопировать бинарный файл, создать сервисного пользователя, под которым сервис Gitea будет запущен в ОС, и подготовить структуру каталогов.

Поехали! Устанавливаем пакет Git:

apt install git

Скачиваем бинарник Gitea и готовим его к запуску:

wget -O gitea https://dl.gitea.com/gitea/1.22.2/gitea-1.22.2-linux-amd64
chmod +x gitea
mv gitea /usr/local/bin/gitea

Создаём сервисного пользователя:

adduser \
    --system \
    --shell /bin/bash \
    --gecos 'Git Version Control' \
    --group \
    --disabled-password \
    --home /home/git git

Готовим структуру каталогов:

mkdir -p /var/lib/gitea/{custom,data,log,public,indexers}
chown -R git:git /var/lib/gitea/
chmod -R 750 /var/lib/gitea/
mkdir /etc/gitea
chown root:git /etc/gitea
chmod 770 /etc/gitea

Отлично, теперь сервер Gitea практически готов к запуску. Остаётся последний штрих — создать сервис systemd:

vim /etc/systemd/system/gitea.service 

Копируем текст юнита systemd:

[Unit]
Description=Gitea
After=syslog.target
After=network.target
After=mysql.service

[Service]
RestartSec=2s
Type=simple
User=git
Group=git
WorkingDirectory=/var/lib/gitea/
ExecStart=/usr/local/bin/gitea web --config /etc/gitea/app.ini
Restart=always
Environment=USER=git HOME=/home/git GITEA_WORK_DIR=/var/lib/gitea

[Install]
WantedBy=multi-user.target

Инициализируем, запускаем и проверяем наш сервис Gitea:

systemctl daemon-reload
systemctl start gitea
systemctl status gitea
systemctl enable gitea

Настройка nginx

Для доступа по HTTP нам нужно настроить обратный прокси-сервер. Устанавливаем nginx и готовим его конфиг для работы с Gitea и Gitea container registry:

apt install nginx
vim /etc/nginx/sites-available/gitea.conf
ln -s /etc/nginx/sites-available/gitea.conf /etc/nginx/sites-enabled/gitea.conf

В файле /etc/nginx/sites-available/gitea.conf нам нужно указать следующие настройки, где вместо <your_gitea_domain_name> — DNS-имя вашего Gitea-сервера:

server {
    listen 80;
    server_name <your_gitea_domain_name>;
    root /var/lib/gitea/public;
    access_log off;
    error_log off;

    location /v2/ { # https://github.com/go-gitea/gitea/issues/21092#issuecomment-1749965397
        client_max_body_size 512m;
        proxy_pass http://127.0.0.1:3000/v2/;
    }

    location / {
        client_max_body_size 512m;
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Connection $http_connection;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
} 

Для безопасности рекомендую не выставлять сервер Gitea голым задом в открытую сеть, пока не выполните шаги из следующего раздела статьи — «Конфигурация Gitea». Вместо этого стоит «повесить» nginx на IP-адрес в локальной сети или на localhost.

Для этого в конфигурационном файле gitea.conf можно поправить:

server {
         listen 127.0.0.1 8080
...

На локальной машине добавить запись в /etc/hosts:

...
127.0.0.1 your_gitea_domain

Пробросить порт 8080 до сервера Gitea:

ssh -L 8080:127.0.0.1:8080 gitea-host

После этого на веб-интерфейс Gitea можно заходить по адресу http://your_gitea_domain:8080. Эти действия не обязательны  — просто рекомендация.

Заказ сертификата и настройки nginx для работы по HTTPS я опущу. В моём случае перед nginx Gitea находится другой обратный прокси-сервер, который занимается заказом сертификатов и обслуживанием HTTPS-трафика. Gitea умеет сам заказывать сертификаты у ACME-провайдера, по умолчанию это Let's Encrypt. Настройки ACME описаны в официальной документации.

Отмечу, что в моём конфиге nginx указана секция для настройки location /v2/, о которой ничего не сказано в официальной документации. У нас была проблема с тем, что Kubernetes-кластер не мог забрать образ из registry (crictl pull), решение нашлось в issue.

Конфигурация Gitea

Следующим шагом в веб-интерфейсе Gitea нам нужно задать основные настройки работы сервера. Открываем в браузере домен, который указывали в конфигурационном файле nginx, и заполняем поля для подключения к БД:

Основные параметры Gitea:

Дополнительные параметры опционально, по вашему вкусу:

Задаём логин и пароль для администратора. Если вдруг вы забыли пароль, его можно сменить через CLI с помощью команды gitea admin user change-password --username user --password password --config /etc/gitea/app.ini:

Нажимаем кнопку Install Gitea. После этого сервер какое-то время будет выполнять инициализацию и заполнит конфигурационный файл /etc/gitea/app.ini.

Наш сервис Gitea готов угощать нас своим ароматом :).

Проверка работы Gitea

Теперь стоит проверить, работает ли наш сервер. В браузере логинимся в Gitea с кредами, которы задали на предыдущем шаге. Если пропустили, то пользователя можно создать через консоль.

Организационная структура доступа в Gitea выглядит следующим образом: Organization → Teams. Здесь Organization — это группа верхнего уровня, а Teams — подгруппы нижнего уровня. 

Давайте создадим тестовую организацию для проверки работы Gitea. В правом верхнем углу выбираем плюсик → New Organization → название организации (у меня это team-romeo), галочка Visibility limited.

После создания организации в ней автоматически появится команда Owners, членом которой и будет пользователь, создавший организацию.

Для удобной работы с репозиториями добавим в свой профиль открытую часть SSH-ключа: после этого можно без ввода пароля пулить и пушить код. Если ключа ещё нет, то RSA-ключ можно сформировать командой ssh-keygen -t ed25519.

Копируем открытую часть своего RSA-ключа:

cat ~/.ssh/id_ed25519.pub

# У себя скопировать всю строку полностью
ssh-ed25519
 your_public_rsa_key user@pc.local

Добавляем ключ к себе в профиль: нажимаем на аватар → Settings → SSH / GPG Keys → Add key. Задаём произвольное название в поле Key Name и вставляем открытую часть нашего ed25519-ключа.

Перейдём в свою организацию и создадим тестовый репозиторий под названием Hello-world. Можем клонировать к себе новосозданный репозиторий без регистрации и смс ввода пароля:

git clone git@your_gitea.com:team-romeo/hello-world.git
cd hello-worl
touch README.md
git add README.md
git commit -m "first commit"
git push

На этом мы закончили с настройкой Gitea. Время перейти к аутентификации и авторизации в кластер DKP.

Настройка аутентификации и авторизации в кластере Deckhouse Kubernetes Platform через Gitea с помощью Dex

Как я уже говорил в начале статьи, Gitea может выступать как провайдер OAuth2, то есть обеспечить аутентификацию и авторизацию пользователей во внешних источниках, поддерживающих стандарт OpenID. Вишенкой на торте будет функционал Dex, который позволяет закрывать аутентификацией любой ingress в кластере. Он добавит безопасности приложениям и позволит скрыть чувствительные ресурсы от внешних глаз.

Итак, для авторизации пользователей в DKP через Gitea OAuth2 воспользуемся Dex. Это Open Source-решение, которое служит связующим звеном между различными сервисами идентификации (Identity Provider) и веб-ресурсами. Один из основных мейнтейнеров Dex — мой коллега Максим Набоких. Dex входит в модуль user-authn Deckhouse Kubernetes Platform.

Настройка аутентификации

Чтобы задействовать сервис Dex, необходимо лишь включить модуль DKP user-authn, что значительно упрощает настройку. Давайте зайдём в кластер DKP и проверим, включён ли модуль:

kubectl get mc user-authn

NAME         ENABLED   VERSION   AGE    MESSAGE
Error from server (NotFound): moduleconfigs.deckhouse.io "user-authn" not found

Видим, что модуль не включён, создадим YAML-манифест для его включения:

kubectl create -f - <<EOF
apiVersion: deckhouse.io/v1alpha1
kind: ModuleConfig
metadata:
  name: user-authn
spec:
  enabled: true
EOF

После включения модуля user-authn проверяем доменное имя сервиса dex. На этот домен Identity Provider (Gitea OAuth2) будет возвращаться callback-запрос с информацией об авторизации пользователей и их атрибутами.

$ kubectl -n d8-user-authn get ing | grep dex
dex                    nginx   dex.<your_d8_domain_name>          10.0.1.199   80, 443   1m

Теперь нам нужно «подружить» наш Dex и Gitea OAuth2. Для этого сначала создадим в Gitea сущность Application, а затем в DKP — YAML-манифест DexProvider

Всё достаточно просто. Заходим в веб-интерфейс Gitea, затем в Site Administration → Integrations → Applications. Далее:

  1. В поле Application Name указываем произвольное название, к примеру Dex DKP.

  2. В поле Redirect URIs указываем наш callback-домен сервиса Dex: https://dex.<your_d8_domain_name>/callback.

  3. Нажимаем Create Application. Важно скопировать значения полей Client ID и Client Secret — это условные логин и пароль для нашего сервиса Dex. В дальнейшем эти данные не будут доступны для просмотра, в случае их утери можно только пересоздать Application.

  4. Нажимаем кнопку Save для завершения процедуры создания Application.

В кластере Deckhouse создаём ресурс DexProvider, с помощью которого настроим Dex для авторизации через Gitea. Другие примеры с описанием настроек DexProvider OIDC вы найдёте в документации.

В DexProvider нужно указать адрес сервера Gitea, а также значение для clientID и clientSecret, которые мы записали при создании Application в Gitea:

kubectl create -f - <<EOF
apiVersion: deckhouse.io/v1
kind: DexProvider
metadata:
  name: gitea
spec:
  type: OIDC
  displayName: gitea
  oidc:
    issuer: https://<your_gitea_domain_name>/ # адрес целевого gitea сервера
    clientID: gitea_app_client_id # gitea Application client ID
    clientSecret: gitea_app_client_secret # gitea Application client Secret
    insecureSkipEmailVerified: true
    getUserInfo: true
EOF

Проверим работу аутентификации. Для этого зайдём на какой-нибудь веб-ресурс DKP, например в Grafana.

Получаем адрес:

$ kubectl -n d8-monitoring get ing -l app.kubernetes.io/managed-by=Helm,app=grafana,heritage=deckhouse,module=prometheus
NAME      CLASS   HOSTS                           ADDRESS      PORTS     AGE
grafana   nginx   grafana.<your_d8_domain_name>   10.0.1.199   80, 443   150d

Вводим в браузере адрес сервиса Grafana и получаем окно Dex с выбором провайдера авторизации:

Затем — окно Gitea с разрешением передавать в сервис Dex данные аккаунта:

Если всё прошло успешно и аутентификация настроена, откроется нужная нам страница с Grafana. Если же по какой-то причине аутентификация не работает, можно посмотреть логи Dex:

kubectl -n d8-user-authn logs -l app=dex -f

{"time":"2024-11-06T10:01:58.85570082Z","level":"INFO","msg":"login successful","connector_id":"gitea","username":"","preferred_username":"tester","email":"tester@tester.com","groups":null,"client_remote_addr":"176.14.136.71","request_id":"878414e4-c8ef-4705-9c55-92844fa4a8ac"}

Настройка авторизации

За разграничение прав доступа пользователей к ресурсам DKP отвечает модуль user-authz.

С его помощью мы можем ограничить пользователям доступ к определённым пространствам имён, разрешить просмотр или запретить изменение ресурсов в них. Настройка прав доступа выполняется стандартным для RBAC Kubernetes способом: с помощью создания ресурсов RoleBinding или ClusterRoleBinding. Пользователи могут выписывать себе kubeconfig для доступа к кластеру через утилиту kubectl,  использовать веб-интерфейс Kubernetes Dashboard или аналогичные решения.

Для настройки авторизации в кластере нужно включить модуль user-authz и создать ресурс RoleBinding, в котором описано, кому, куда и какие права мы даём. Ресурс ClusterRoleBinding используется, если мы настраиваем manage-роль (networking, Kubernetes, observability и так далее), а RoleBinding — для настроек доступа к пользовательским окружениям.

Для начала создадим в кластере Deckhouse тестовое пространство имён с названием gitea-authz-test и тестовое приложение tester-app в нём:

kubectl create namespace gitea-authz-test
kubectl -n gitea-authz-test create deployment tester-app --image=nginx:1.27

Включаем модуль user-authz:

kubectl create -f - <<EOF
apiVersion: deckhouse.io/v1alpha1
kind: ModuleConfig
metadata:
  name: user-authz
spec:
  enabled: true
EOF

Предоставим пользователю viktor.ashakin права админа пространства имён тестового приложения, для этого создадим ресурс RoleBinding:

kubectl create -f - <<EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: app-admin
  namespace: gitea-authz-test
subjects:
- kind: Group
  name: team-romeo
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: d8:use:role:admin
  apiGroup: rbac.authorization.k8s.io
EOF

Проверяем работу авторизации. Для этого зайдём в Kubernetes Dashboard. За работу Dashboard отвечает модуль d8-dashboard, который включён по умолчанию.

Определяем доменное имя сервиса Dashboard:

# Получаем адрес Dashboard
kubectl -n d8-dashboard get ing -l app.kubernetes.io/managed-by=Helm,app=dashboard
NAME        CLASS   HOSTS
dashboard   nginx   dashboard.<your_d8_domain_name>

В браузере открываем страницу сервиса Dashboard https://dashboard.<your_d8_domain_name>, вводим название пространства имён (namespace) нашего приложения: gitea-authz-test.

Откроется страница со всеми ресурсами в пространстве имён. Права админа позволяют нам редактировать или удалять ресурсы, изменять количество реплик тестового приложения. Удалим deployment нашего приложения:

Полный доступ мы посмотрели, теперь проверим, как работают ограниченные права доступа. Создадим тестового пользователя tester в Gitea: в веб-интерфейсе нажимаем на иконку пользователя → Site Administration → Identity & Access → User Accounts → Create User Account.

Создаём в кластере ресурс RoleBinding для пользователя tester с ролью viewer:

kubectl create -f - <<EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: app-viewer
  namespace: gitea-authz-test
subjects:
- kind: User
  name: tester@tester.com # Для пользователя указывается его email
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: d8:use:role:viewer
  apiGroup: rbac.authorization.k8s.io
EOF

Возвращаем тестовое приложение к жизни:

kubectl -n gitea-authz-test create deployment tester-app --image=nginx:1.27

Открываем в браузере вкладку-инкогнито и логинимся в Gitea под новым пользователем tester. В соседней инкогнито-вкладке открываем страницу Dashboard и указываем gitea-authz-test в качестве названия пространства имён. При попытке удалить deployment приложения получим ошибку:

Теперь предоставим доступ с правами админа ко всем ресурсам в пространстве имён кластера Deckhouse группе team-romeo:owners. Данная группа была создана ранее на этапе проверки Gitea.

Описанный ниже функционал работает только в режиме enableMultiTenancy, который доступен в DKP версии Enterprise Edition. С помощью enableMultiTenancy мы можем предоставлять доступ к пространству имён на основе лейблов.

Включаем MultiTenancy в модуле user-authz, для этого редактируем ресурс:

kubectl edit mc user-authz

и добавляем опцию spec.settings.enableMultiTenancy: true:

apiVersion: deckhouse.io/v1alpha1
kind: ModuleConfig
metadata:
  name: user-authz
spec:
  enabled: true
  settings:
    enableMultiTenancy: true

Теперь в кластере Deckhouse создаём ресурс ClusterAuthorizationRule. Подробные примеры можно посмотреть в документации к модулю user-authz.

kubectl create -f - <<EOF
apiVersion: deckhouse.io/v1
kind: ClusterAuthorizationRule
metadata:
  name: admins
spec:
  accessLevel: SuperAdmin
  allowAccessToSystemNamespaces: true
  allowScale: true
  portForwarding: true
  subjects:
  - kind: Group
    name: team-romeo:owners
EOF

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

Для примера выберем d8-monitoring:

После этого у нас откроется страница со всеми ресурсами, находящимися в пространстве имён d8-monitoring. Ресурс ClusterAuthorizationRule позволяет нам гибко управлять доступом для групп и отдельных пользователей. Достаточно повесить нужный лейбл на пространство имён и задать matchExpressions в ClusterAuthorizationRule.

Промежуточный итог

Теперь у нас есть готовый сервер Gitea, а также настроены аутентификация и авторизация в Deckhouse Kubernetes Platform.

В двух следующих частях статьи поговорим о Gitea Actions. Настроим инфраструктуру, напишем Actions CI/CD-пайплайны и развернём приложение в кластере DKP с помощью werf.

P. S. 

Читайте также в нашем блоге:

Теги:
Хабы:
+36
Комментарии7
1

Публикации

Информация

Сайт
flant.ru
Дата регистрации
Дата основания
Численность
201–500 человек
Местоположение
Россия
Представитель
Александр Лукьянов