Продолжаем сетапить GitLab в Kubernetes. Первая часть — GitLab: компоненты, архитектура, инфраструктура и запуск из Helm-чарта в Minikube, теперь давайте готовиться деплоить в AWS Elastic Kubernetes Service.
Что будем делать и где:
- деплоим в AWS из Helm-чарта, для начала какой-то «test env»
- Kubernetes — AWS EKS
- object store — AWS S3
- PostgreSQL — из operator
- Redis — пока используем дефолтный, позже переедем на KeyDB, который тоже разворачивается оператором
- Gitaly — попробуем в кластере, возможно, на отдельной ноде — у нас всего 150-200 пользователей, нагрузки большой не должно быть, скейлинг и тем более Praefik не нужны
GitLab Operator выглядит в целом интересно, но в документации через слово Experimental и Beta, так что пока не трогаем — используем чарт.
Содержание
Helm chart prerequisites
По чарту: для начала надо пройтись по доступным параметрам чарта, и посмотреть что нам вообще надо будет из внешних ресурсов (лоад-балансеры, корзины S3, PostgreSQL), и что ещё можно настроить через чарт.
Не забываем посмотреть GitLab chart prerequisites, из которого нам пока интересны:
- PostgreSQL: мы будем использовать оператор, и развернём свой кластер с блекджеком и базами
- Redis: у нас есть KeyDB-оператор, потом будем через него, пока дефолтный из чарта
- Networking and DNS: используем AWS ALB Contoller, создадим ACM сертификат, DNS в Route53, записи создаются через External DNS
- Persistence: интересный нюанс, возможно, надо будет настроить reclaimPolicy to Retain, см. Configuring Cluster Storage
- Prometheus: тоже поинт на подумать — у нас есть Kube Prometheus Stack со своим Prometheus и Alertmanager, надо будет подумать — отключать ли встроенный в GitLab, или оставлять
- Outgoing email: пока не будем настраивать, но потом надо будет подумать. В принципе — есть поддержка AWS SES, где-то в документации встречал, так что нормально
- RBAC: у нас есть, поддерживается, так что оставляем по-умолчанию, т.е. включаем
Учитываем, что чарт включает в себя пачку зависимостей, и полезно пройтись и посмотреть что там ещё деплоится и с какими параметрами.
Структура Helm-чарта и его values.yaml
У GitLab Helm-чарта достаточно сложная структура его values, так как чарт включает в себя набор сабчартов и зависимостей, см. GitLab Helm subcharts.
Что бы представить себе структуру его values — можно посмотреть структуру каталога charts с дочерними чартами:
[simterm]
$ tree -d gitlab/charts/
gitlab/charts/
|-- certmanager-issuer
| `-- templates
|-- gitlab
| |-- charts
| | |-- geo-logcursor
| | | `-- templates
| | |-- gitaly
| | | `-- templates
| | |-- gitlab-exporter
| | | `-- templates
| | |-- gitlab-grafana
| | | `-- templates
| | |-- gitlab-pages
| | | `-- templates
| | |-- gitlab-shell
| | | `-- templates
| | |-- kas
| | | `-- templates
| | |-- mailroom
| | | `-- templates
| | |-- migrations
| | | `-- templates
| | |-- praefect
| | | `-- templates
| | |-- sidekiq
| | | `-- templates
| | |-- spamcheck
| | | `-- templates
| | |-- toolbox
| | | `-- templates
| | `-- webservice
| | `-- templates
| | `-- tests
| `-- templates
|-- minio
| `-- templates
|-- nginx-ingress
| `-- templates
| `-- admission-webhooks
| `-- job-patch
`-- registry
`-- templates
[/simterm]
Кроме того, есть набор внешних зависимостей, см. файл requirements.yaml.
Соотвественно, в values основного чарта параметры разбиты на globals (см. Subcharts and Global Values), которые используются дочерними чартами, и параметры для конкретных чартов. См. Configure charts using globals, т.е. наш values.yaml будет выглядеть так:
global:
hosts:
domain:
hostSuffix: # используется в ./charts/gitlab/charts/webservice, ./charts/gitlab/charts/toolbox/, ./charts/registry/, etc
...
gitlab:
kas:
enabled: # используется ./charts/gitlab/charts/kas/
...
nginx-ingress:
enabled: # используется для ./gitlab/charts/nginx-ingress
...
postgresql:
install: # используется при установке внешнего чарта postgresql
Теперь посмотрим на сами values, и какие из них нам могут быть полезны.
Helm chart values
«Стартовая точка» для работы с чартом — Installing GitLab by using Helm.
Ещё хорошо пройтись по дефолтному values.yaml — там в комментариях есть ссылки на сервисы/параметры.
Собственно, параметры, которые нам могут быть интересны, см. все в Configure charts using globals и GitLab Helm chart deployment options:
global.hosts:domain: указываем корневой домен, в котором будут создавать записи для GitLabexternalIP: он вроде обязательный, но так как у нас будет AWS ALB, то не используемhostSuffix: test — добавим к создаваемым субдоменам, получим домен вида gitlab-test.example.comhttps— true, будет ALB с AWS Certificate Managerssh: тут надо будет задать отдельный субдомен для доступа к GitLab Shell
global.ingress: так как у нас AWS ALB, то см. пример вalb-full.yamlannotations.*annotation-key*: добавим аннотации для ALBconfigureCertmanager: надо будет отключить, т.к. SSL терминейтим на лоад-балансереtls.secretName: в нашем случае не нужен, т.к. SSL терминейтим на лоад-балансереpath: для ALB нужен будет/*provider: для ALB == aws
global.gitlabVersion: думал тут задать версию Gitlab, которую будем деплоить, но оказалось что нет — правильнее через версию чарта, см. GitLab Versionglobal.psql: параметры для подключения к PostgreSQL сервисами GitLab, см. Configure PostgreSQL settingshost: адрес PosgtreSQL Servicedatabase,username: понятноpassword:useSecret: пароль будем хранить в Secretsecret: имя секретаkey: ключ/поле в Секрете, по которому получаем пароль
global.redis: вообще будет внешний, KeyDB, и тут надо будет указать параметры доступа к нему, но для начала оставим дефолтный, см. Configure Redis settings,global.grafana.enabled: включаем — посмотрим, какие там есть дашборды (нету, надо будет настраивать отдельно, см. Grafana JSON Dashboards)global.registry: см. Using the Container Registrybucket: надо будет создать корзину, этот параметр используется в/charts/gitlab/charts/toolbox/для бекапов, сам GitLab Registry настраивается через отдельные параметры, рассмотрим ниже
global.gitaly: пока используем из чарта, несмотря на рекомендации — будем деплоить в виде Kubernetes Pod в кластер, оставляем по-умолчанию, но имеем ввидуglobal.minio: отключим — используем сразу AWS S3global.appConfig: вот тут прям много всего, см. Configure appConfig settings — содержит общие параметры для чартов Webservice, Sidekiq и GitalycdnHost: вообще-то хорошая бы вроде вещь, но посмотрим, как его использовать, пока не трогаемcontentSecurityPolicy: тоже полезная штука, но настроим потом, см. Content Security PolicyenableUsagePing: «телеметрия» для самого GitLab Inc, не вижу смысла, отключимenableSeatLink: не понял, что это, ссылка seat link support ведёт в «никуда» — на странице инфы про seat не нашёл, но видимо это что-то связанное с кол-вом юзеров в лицензии, а так как мы её не покупаем — то можно отключитьobject_store: общие параметры для работы с корзинами типа ключей доступа и proxy, см. Consolidated object storage:
-
connection: тут надо будет создать секрет, в котором описываются настройки подключения к корзинам, в том числе ACCESS/SECRET ключи, но мы вместо ключей используем ServiceAccount и IAM role
- Specify buckets: какие корзины нужны, есть набор дефолтных имён типа gitlab-artifacts, но для dev- и test- имеет смысл переопределить
storage_options: шифрование для корзин, имеет смысл менять если используется AWS KMS, но мы скорее всго оставим дефолтное шифрование
- LFS, Artifacts, Uploads, Packages, External MR diffs, and Dependency Proxy — настройки корзин для различных сервисов, пока не будем трогать, посмотрим по ходу дела
gitlab_kas: настройки для GitLab Agent for Kubernetes, пока оставим по-умолчанию, не уверен, что он нам понадобитсяomniauth: настройки для SSO, как-нибудь потом, вообще будем подключать аутентификацию через Google, см. OmniAuth
global.serviceAccounts: вместо ACCESS/SECRET будем использовать Kubernetes ServiceAccounts с IAM Role для подов:create: включаем создание SA для сервисовannotations: а тут укажем ARN IAM-роли
global.nodeSelector: полезно, потом будем на выделенных нодахglobal.affinity&&global.antiAffinity: плюс можно настроить Affinityglobal.common.labels: зададим тут всякие environment, team, etcglobal.tracing: пока не трогаем, но имеем ввиду на будущее — потом допилим какой-то Jaeger/Grafana Tempoglobal.priorityClassName: возможно полезно или даже нужно, потом потыкаем, см. Pod Priority and Preemption
Из глобальных переменных это вроде всё, кроме них нам надо будет:
- отключить
certmanager— используем AWS Certificate Manager на AWS LoadBalncer - отключить
postgresql— используем внешний - отключить
gitlab-runner— у нас уже есть запущенные раннеры, потом попробуем прикрутить их к этому инстансу GitLab - отключить
nginx-ingress— у нас AWS ALB Controller и AWS ALB балансеры - настроить Services для
webserviceиgitlab-shell - настроить
registry
Теперь, перед деплоем чарта, надо подготовить внешние сервисы:
- кластер и база PostgreSQL
- корзины AWS S3
- сертификат в AWS Certificate Manager для лоад-балансера
Подготовка — создание внешних ресурсов
PostgreSQL
У нас используется PostgreSQL Operator — описываем ему создание кластера.
Параметры по коннектам, памяти, диску и реквестам-лимитам пока дефолтные — посмотрим по ходу дела, как сильно будет нагружаться база.
Описываем создание базы gitlabhq_test и дефолтных юзеров — defaultUsers=true:
kind: postgresql
apiVersion: acid.zalan.do/v1
metadata:
name: gitlab-cluster-test-psql
namespace: gitlab-cluster-test
labels:
team: devops
environment: test
spec:
teamId: devops
postgresql:
version: "14"
parameters:
max_connections: '100'
shared_buffers: 256MB
work_mem: 32MB
numberOfInstances: 3
preparedDatabases:
gitlabhq_test:
defaultUsers: true
schemas:
public:
defaultRoles: false
enableMasterLoadBalancer: false
enableReplicaLoadBalancer: false
enableConnectionPooler: false
enableReplicaConnectionPooler: false
volume:
size: 10Gi
storageClass: encrypted
resources:
requests:
cpu: "100m"
memory: 100Mi
limits:
memory: 1024Mi
enableLogicalBackup: true
logicalBackupSchedule: "0 1 * * *"
sidecars:
- name: exporter
image: quay.io/prometheuscommunity/postgres-exporter:v0.11.1
ports:
- name: exporter
containerPort: 9187
protocol: TCP
resources:
limits:
memory: 50M
requests:
cpu: 50m
memory: 50M
env:
- name: DATA_SOURCE_URI
value: localhost/postgres?sslmode=disable
- name: DATA_SOURCE_USER
value: "$(POSTGRES_USER)"
- name: DATA_SOURCE_PASS
value: "$(POSTGRES_PASSWORD)"
- name: PG_EXPORTER_AUTO_DISCOVER_DATABASES
value: "true"
Создаём неймспейс:
[simterm]
$ kk create ns gitlab-cluster-test
[/simterm]
Деплоим кластер:
[simterm]
$ kk apply -f postgresql.yaml postgresql.acid.zalan.do/gitlab-cluster-test-psql created
[/simterm]
Проверяем поды:
[simterm]
$ kk -n gitlab-cluster-test get pod NAME READY STATUS RESTARTS AGE devops-gitlab-cluster-test-psql-0 2/2 Running 0 24s devops-gitlab-cluster-test-psql-1 0/2 ContainerCreating 0 4s
[/simterm]
Окей, создаются.
Проверяем Секреты — потом используем секрет пользователя postgres в конфигах GitLab:
[simterm]
$ kk -n gitlab-cluster-test get secret NAME TYPE DATA AGE default-token-2z2ct kubernetes.io/service-account-token 3 4m12s gitlabhq-test-owner-user.devops-gitlab-cluster-test-psql.credentials.postgresql.acid.zalan.do Opaque 2 65s gitlabhq-test-reader-user.devops-gitlab-cluster-test-psql.credentials.postgresql.acid.zalan.do Opaque 2 65s gitlabhq-test-writer-user.devops-gitlab-cluster-test-psql.credentials.postgresql.acid.zalan.do Opaque 2 66s postgres-pod-token-p7b4g kubernetes.io/service-account-token 3 66s postgres.devops-gitlab-cluster-test-psql.credentials.postgresql.acid.zalan.do Opaque 2 66s standby.devops-gitlab-cluster-test-psql.credentials.postgresql.acid.zalan.do Opaque 2 66s
[/simterm]
Вроде ОК.
AWS S3
Теперь создадим корзины.
Нам будут нужны:
- для registry — Configure Registry settings
- для бекапов — Backups to S3
- и пачка всяких для LFS, Artifacts, Uploads, Packages, External MR diffs, and Dependency Proxy
К именам корзин добавляем or как свой «идентификатор», ибо имена корзин общие, что бы не было ошибки BucketAlreadyExists, и имя окружения — test, т.е. список получается такой:
- or-gitlab-registry-test
- or-gitlab-artifacts-test
- or-git-lfs-test
- or-gitlab-packages-test
- or-gitlab-uploads-test
- or-gitlab-mr-diffs-test
- or-gitlab-terraform-state-test
- or-gitlab-ci-secure-files-test
- or-gitlab-dependency-proxy-test
- or-gitlab-pages-test
- or-gitlab-backups-test
- or-gitlab-tmp-test
Не факт, что понадобятся все, посмотрим по ходу настройки GitLab и его фич, но пока создадим.
Создаём с AWS CLI:
[simterm]
$ aws --profile internal s3 mb s3://or-gitlab-registry-test make_bucket: or-gitlab-registry-test
[/simterm]
Повторяем для всех остальных.
AWS Certificate Manager
Для Ingress нам нужен TLS-сертификат, см. Requesting a public certificate, а для получения сертификата — очевидно, что домен.
В нашем случае используем internal.example.com, для которого создадим wildcard-сертификат в ACM:
В FQDN указываем *.internal.example.com, что бы включить все субдомены. Затем для GitLab используем параметры global.hosts.domain: iinternal.example.com и hostSuffix: test, что в результате создаст несколько Ingress и Services, которые через ExternalDNS создадут необходимые записи в Route53.
В Validation Method выбираем DNS — самый простой, тем более что доменная зона хостится в Route53 — всё создаётся в пару кликов:
Переходим к сертификату — он сейчас в Pending validation, кликаем Create records in Route53:
Теперь статус Issued, запоминаем его ARN — он нам понадобится в values:
AWS IAM Policy и IAM Role для ServiceAccount
Для ServiceAccount, который должен будет давать доступ к AWS к корзинам, надо создать IAM Policy и IAM Role. Детально см. Kubernetes ServiceAccounts с IAM Role для подов, тут быстренько.
Создаём полиси:
{
"Statement": [
{
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:DeleteObject",
"s3:ListMultipartUploadParts",
"s3:AbortMultipartUpload"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::or-gitlab-registry-test/*",
"arn:aws:s3:::or-gitlab-artifacts-test/*",
"arn:aws:s3:::or-git-lfs-test/*",
"arn:aws:s3:::or-gitlab-packages-test/*",
"arn:aws:s3:::or-gitlab-uploads-test/*",
"arn:aws:s3:::or-gitlab-mr-diffs-test/*",
"arn:aws:s3:::or-gitlab-terraform-state-test/*",
"arn:aws:s3:::or-gitlab-ci-secure-files-test/*",
"arn:aws:s3:::or-gitlab-dependency-proxy-test/*",
"arn:aws:s3:::or-gitlab-backups-test/*",
"arn:aws:s3:::or-gitlab-tmp-test/*"
]
},
{
"Action": [
"s3:ListBucket",
"s3:ListAllMyBuckets",
"s3:GetBucketLocation",
"s3:ListBucketMultipartUploads"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::or-gitlab-registry-test",
"arn:aws:s3:::or-gitlab-artifacts-test",
"arn:aws:s3:::or-git-lfs-test",
"arn:aws:s3:::or-gitlab-packages-test",
"arn:aws:s3:::or-gitlab-uploads-test",
"arn:aws:s3:::or-gitlab-mr-diffs-test",
"arn:aws:s3:::or-gitlab-terraform-state-test",
"arn:aws:s3:::or-gitlab-ci-secure-files-test",
"arn:aws:s3:::or-gitlab-dependency-proxy-test",
"arn:aws:s3:::or-gitlab-backups-test",
"arn:aws:s3:::or-gitlab-tmp-test"
]
}
],
"Version": "2012-10-17"
}
Создаём IAM Role — выбираем Web identity:
Подключаем созданную выше Policy:
Вроде всё? Можно писать values.
Деплой Gitlab Helm
Создание values.yaml
Все дефолтные values тут>>>, можно использовать как пример, но не стоит полностью копировать — в свой values пишем только то, что у нас отличается от дефолтного.
global
hosts
Указываем домен, используя который чарт пропишет значения в Ingress и Services, которые будет создавать — получим набор доменов вида gitlab.internal.example.com, registry.internal.example.com и т.д.
Для SSH в примере для Ingress указан отдельный субдомен, так как под SSH будет создавать отдельный Service с Network Load Balancer для доступа к 22 TCP.
hostSuffix добавит суффикс к создаваемым записям, т.е. в результате будут субдомены вида gitlab-test.internal.example.com и registry-test.internal.example.com.
Но к SSH hostSuffix не применится, поэтому указываем сразу с суффиксом.
Получается так:
global:
hosts:
domain: internal.example.com
hostSuffix: test
ssh: gitlab-shell-test.internal.example.com
ingress
Берём для примера alb-full.yaml, от себя добавим только load_balancing.algorithm.type=least_outstanding_requests:
ingress:
# Common annotations used by kas, registry, and webservice
annotations:
alb.ingress.kubernetes.io/backend-protocol: HTTP
alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:eu-central-1:514***799:certificate/7227a8fa-1124-441c-81d7-ec168180190d
alb.ingress.kubernetes.io/group.name: gitlab
alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS": 443}]'
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-group-attributes: load_balancing.algorithm.type=least_outstanding_request
alb.ingress.kubernetes.io/target-type: ip
kubernetes.io/ingress.class: alb
nginx.ingress.kubernetes.io/connection-proxy-header: "keep-alive"
class: none
configureCertmanager: false
enabled: true
path: /*
pathType: ImplementationSpecific
provider: aws
tls:
enabled: false
Если использовать KAS, то ему нужен будет отдельный LoadBalancer, настроим его чуть позже в блоке gitlab.kas.
psql
Находим имя Service, который был создан во время деплоя PostgreSQL кластера:
[simterm]
$ kk -n gitlab-cluster-test get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE devops-gitlab-cluster-test-psql ClusterIP 172.20.67.135 <none> 5432/TCP 63m devops-gitlab-cluster-test-psql-config ClusterIP None <none> <none> 63m devops-gitlab-cluster-test-psql-repl ClusterIP 172.20.165.249 <none> 5432/TCP 63m
[/simterm]
Пользователя пока возьмём дефолтного postgress, из готового секрета:
[simterm]
$ kk -n gitlab-cluster-test get secret postgres.devops-gitlab-cluster-test-psql.credentials.postgresql.acid.zalan.do NAME TYPE DATA AGE postgres.devops-gitlab-cluster-test-psql.credentials.postgresql.acid.zalan.do Opaque 2 67m
[/simterm]
Для production таки надо будет делать отдельного, ибо postgress == root.
Готовим конфиг:
psql:
host: devops-gitlab-cluster-test-psql
database: gitlabhq_test
username: postgres
password:
useSecret: true
secret: postgres.devops-gitlab-cluster-test-psql.credentials.postgresql.acid.zalan.do
key: password
redis
Configure Redis chart-specific settings
Configure the GitLab chart with an external Redis
Пока оставим всё по-умолчанию — Redis используется только для кеширования, посмотрим, как он будет работать и что по ресурсам.
registry
В globals для registry указываем только корзину:
registry: bucket: or-gitlab-registry-test
gitaly
Пока оставим, как есть. Потом подумаем, может вынесем на отдельную ноду.
Надо будет помониторить как он ресурсы использует, но в случае с нашими 150-200 пользователей вряд ли там будет необходимость сильно его допиливать или тем более разворачивать кластер Praefect.
minio
Отключаем, будем ходить сразу в AWS S3:
minio: enabled: false
grafana
Включим, посмотрим, что в ней есть (ничего 🙂 ):
grafana: enabled: true
appConfig
Список корзин есть в values.
object_store таки надо настраивать — добавить секрет, в котором будут указаны провайдер и регион корзин. Ключи не используем — будет ServiceAccount.
Пример возьмём из rails.s3.yaml, см. connection:
provider: AWS region: eu-central-1
Создаём Secret:
[simterm]
$ kk -n gitlab-cluster-test create secret generic gitlab-rails-storage --from-file=connection=rails.s3.yaml
[/simterm]
И описываем appConfig, получается так:
appConfig:
enableUsagePing: false
enableSeatLink: true # disable?
object_store:
enabled: true
proxy_download: true
connection:
secret: gitlab-rails-storage
key: connection
artifacts:
bucket: or-gitlab-artifacts-test
lfs:
bucket: or-git-lfs-test
packages:
bucket: or-gitlab-packages-test
uploads:
bucket: or-gitlab-uploads-test
externalDiffs:
bucket: or-gitlab-mr-diffs-test
terraformState:
bucket: or-gitlab-terraform-state-test
ciSecureFiles:
bucket: or-gitlab-ci-secure-files-test
dependencyProxy:
bucket: or-gitlab-dependency-proxy-test
backups:
bucket: or-gitlab-backups-test
tmpBucket: or-gitlab-tmp-test
serviceAccount
См. Kubernetes: ServiceAccount з AWS IAM Role для Kubernetes Pod
Вроде можно без создания ServiceAccount, просто через аннотации к сервисам — IAM roles for AWS when using the GitLab chart.
Но мы будем использовать ServiceAccount, роль с политикой уже делали — добавляем:
serviceAccount:
enabled: true
create: true
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::514***799:role/S3GitlabClusterTest
Так, из globals вроде всё.
registry
Defining the Registry Configuration
Тут надо настроить storage, который хранится в Secret, и в котором тоже необходимо указать имя корзины: параметр в globals.registry будет использоваться для бекапов, а параметр тут — самим сервисом Registry, см. Docker Registry images.
Для примера возьмём файл registry.s3.yaml, но без ключей, так как для Registry будет создан свой ServiceAccoumt с IAM Role:
s3: bucket: or-gitlab-registry-test region: eu-central-1 v4auth: true
Создаём секрет:
[simterm]
$ kk -n gitlab-cluster-test create secret generic registry-storage --from-file=config=registry.s3.yaml
[/simterm]
Описываем конфиг:
registry:
enabled: true
service:
type: NodePort
storage:
secret: registry-storage
key: config
gitlab — Services
Отдельно описываем Services для kas, webservice и gitlab-shell, из того же примера alb-full.yaml.
Для gitlab-shell Service в аннотации external-dns.alpha.kubernetes.io/hostname указываем имя хоста:
gitlab:
kas:
enabled: true
ingress:
# Specific annotations needed for kas service to support websockets
annotations:
alb.ingress.kubernetes.io/healthcheck-path: /liveness
alb.ingress.kubernetes.io/healthcheck-port: "8151"
alb.ingress.kubernetes.io/healthcheck-protocol: HTTP
alb.ingress.kubernetes.io/load-balancer-attributes: idle_timeout.timeout_seconds=4000,routing.http2.enabled=false
alb.ingress.kubernetes.io/target-group-attributes: stickiness.enabled=true,stickiness.lb_cookie.duration_seconds=86400
alb.ingress.kubernetes.io/target-type: ip
kubernetes.io/tls-acme: "true"
nginx.ingress.kubernetes.io/connection-proxy-header: "keep-alive"
nginx.ingress.kubernetes.io/x-forwarded-prefix: "/path"
# k8s services exposed via an ingress rule to an ELB need to be of type NodePort
service:
type: NodePort
webservice:
enabled: true
service:
type: NodePort
# gitlab-shell (ssh) needs an NLB
gitlab-shell:
enabled: true
service:
annotations:
external-dns.alpha.kubernetes.io/hostname: "gitlab-shell-test.internal.example.com"
service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: "ip"
service.beta.kubernetes.io/aws-load-balancer-scheme: "internet-facing"
service.beta.kubernetes.io/aws-load-balancer-type: "external"
type: LoadBalancer
Прочее
Отключаем ненужные нам сервисы:
certmanager: install: false postgresql: install: false gitlab-runner: install: false nginx-ingress: enabled: true
Полный values.yaml
В результате получаем такой конфиг:
global:
hosts:
domain: internal.example.com
hostSuffix: test
ssh: gitlab-shell-test.internal.example.com
ingress:
# Common annotations used by kas, registry, and webservice
annotations:
alb.ingress.kubernetes.io/backend-protocol: HTTP
alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:eu-central-1:514***799:certificate/7227a8fa-1124-441c-81d7-ec168180190d
alb.ingress.kubernetes.io/group.name: gitlab
alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS": 443}]'
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-group-attributes: load_balancing.algorithm.type=least_outstanding_requests
alb.ingress.kubernetes.io/target-type: ip
kubernetes.io/ingress.class: alb
nginx.ingress.kubernetes.io/connection-proxy-header: "keep-alive"
class: none
configureCertmanager: false
enabled: true
path: /*
pathType: ImplementationSpecific
provider: aws
tls:
enabled: false
psql:
host: devops-gitlab-cluster-test-psql
database: gitlabhq_test
username: postgres
password:
useSecret: true
secret: postgres.devops-gitlab-cluster-test-psql.credentials.postgresql.acid.zalan.do
key: password
registry:
bucket: or-gitlab-registry-test
minio:
enabled: false
grafana:
enabled: true
appConfig:
enableUsagePing: false
enableSeatLink: true # disable?
object_store:
enabled: true
proxy_download: true
connection:
secret: gitlab-rails-storage
key: connection
artifacts:
bucket: or-gitlab-artifacts-test
lfs:
bucket: or-git-lfs-test
packages:
bucket: or-gitlab-packages-test
uploads:
bucket: or-gitlab-uploads-test
externalDiffs:
bucket: or-gitlab-mr-diffs-test
terraformState:
bucket: or-gitlab-terraform-state-test
ciSecureFiles:
bucket: or-gitlab-ci-secure-files-test
dependencyProxy:
bucket: or-gitlab-dependency-proxy-test
backups:
bucket: or-gitlab-backups-test
tmpBucket: or-gitlab-tmp-test
serviceAccount:
enabled: true
create: true
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::514***799:role/S3GitlabClusterTest
common:
labels:
environment: test
gitlab:
kas:
enabled: true
ingress:
# Specific annotations needed for kas service to support websockets
annotations:
alb.ingress.kubernetes.io/healthcheck-path: /liveness
alb.ingress.kubernetes.io/healthcheck-port: "8151"
alb.ingress.kubernetes.io/healthcheck-protocol: HTTP
alb.ingress.kubernetes.io/load-balancer-attributes: idle_timeout.timeout_seconds=4000,routing.http2.enabled=false
alb.ingress.kubernetes.io/target-group-attributes: stickiness.enabled=true,stickiness.lb_cookie.duration_seconds=86400
alb.ingress.kubernetes.io/target-type: ip
kubernetes.io/tls-acme: "true"
nginx.ingress.kubernetes.io/connection-proxy-header: "keep-alive"
nginx.ingress.kubernetes.io/x-forwarded-prefix: "/path"
# k8s services exposed via an ingress rule to an ELB need to be of type NodePort
service:
type: NodePort
webservice:
enabled: true
service:
type: NodePort
# gitlab-shell (ssh) needs an NLB
gitlab-shell:
enabled: true
service:
annotations:
external-dns.alpha.kubernetes.io/hostname: "gitlab-shell-test.internal.example.com"
service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: "ip"
service.beta.kubernetes.io/aws-load-balancer-scheme: "internet-facing"
service.beta.kubernetes.io/aws-load-balancer-type: "external"
type: LoadBalancer
registry:
enabled: true
service:
type: NodePort
storage:
secret: registry-storage
key: config
certmanager:
install: false
postgresql:
install: false
gitlab-runner:
install: false
nginx-ingress:
enabled: false
Gitlab deploy
Ну и вроде всё? Давайте деплоить:
[simterm]
$ helm repo add gitlab https://charts.gitlab.io/ $ helm repo update $ helm upgrade --install --namespace gitlab-cluster-test gitlab gitlab/gitlab --timeout 600s -f gitlab-cluster-test-values.yaml
[/simterm]
Проверяем Ingresses:
[simterm]
$ kk -n gitlab-cluster-test get ingress NAME CLASS HOSTS ADDRESS PORTS AGE gitlab-grafana-app <none> gitlab-test.internal.example.com k8s-***.eu-central-1.elb.amazonaws.com 80 117s gitlab-kas <none> kas-test.internal.example.com k8s-***.eu-central-1.elb.amazonaws.com 80 117s gitlab-registry <none> registry-test.internal.example.com k8s-***.eu-central-1.elb.amazonaws.com 80 117s gitlab-webservice-default <none> gitlab-test.internal.example.com k8s-***.eu-central-1.elb.amazonaws.com 80 117s
[/simterm]
Открываем URL https://gitlab-test.internal.example.com:
Получаем рутовый пароль:
[simterm]
$ kubectl -n gitlab-cluster-test get secret gitlab-gitlab-initial-root-password -ojsonpath='{.data.password}' | base64 --decode ; echo
cV6***y1t
[/simterm]
Логинимся под root:
Проверка деплоя
Не верится мне, что с первого раза всё завелось…
Repository
Проверяем работу с репозиторием — работу сервисов Gitaly и GitLab Shell.
Создаём тестовый репозиторий:
Копируем адрес — с субдоменом gitlab-shell-test.internal.example.com, который указывали в конфигах:
Клонируем, подверждаем добавления сертификата в /home/setevoy/.ssh/known_hosts:
[simterm]
$ git clone [email protected]:gitlab-instance-da4355a9/test-repo.git Cloning into 'test-repo'... The authenticity of host 'gitlab-shell-test.internal.example.com (3.***.***.79)' can't be established. ED25519 key fingerprint is SHA256:xhC1Q/lduNbg49kGljYUb21YlBBsxrG89xE+iCHD+xc. This key is not known by any other names. Are you sure you want to continue connecting (yes/no/[fingerprint])? yes Warning: Permanently added 'gitlab-shell-test.internal.example.com' (ED25519) to the list of known hosts. remote: Enumerating objects: 3, done. remote: Counting objects: 100% (3/3), done. remote: Compressing objects: 100% (2/2), done. remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 Receiving objects: 100% (3/3), done.
[/simterm]
И содержимое:
[simterm]
$ ll test-repo/ total 8 -rw-r--r-- 1 setevoy setevoy 6274 Feb 4 13:24 README.md
[/simterm]
Попробуем пушнуть какие-то изменения обратно:
[simterm]
$ cd test-repo/ $ echo test > test.txt $ git add test.txt $ git commit -m "test" $ git push Enumerating objects: 4, done. Counting objects: 100% (4/4), done. Delta compression using up to 16 threads Compressing objects: 100% (2/2), done. Writing objects: 100% (3/3), 285 bytes | 285.00 KiB/s, done. Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 To gitlab-shell-test.internal.example.com:gitlab-instance-da4355a9/test-repo.git 7217947..4eb84db main -> main
[/simterm]
И в WebUI:
Окей, работает.
Container Registry
И проверим Registry — примеры команд есть в веб-интерфейсе > Container Registry:
Логинимся с тем же логином:паролем, которые использовали для логина в веб-интерфейс GitLab (пользователь root, пароль из секрета gitlab-gitlab-initial-root-password):
[simterm]
$ docker login registry-test.internal.example.com Username: root Password: ... Login Succeeded
[/simterm]
Создаём Dockerfile:
FROM busybox RUN echo "hello world"
Собираем образ, тегаем с именем нашего Registry:
[simterm]
$ docker build -t registry-test.internal.example.com/gitlab-instance-da4355a9/test-repo:1 .
[/simterm]
И пушим:
[simterm]
$ docker push registry-test.internal.example.com/gitlab-instance-da4355a9/test-repo:1 The push refers to repository [registry-test.internal.example.com/gitlab-instance-da4355a9/test-repo] b64792c17e4a: Mounted from gitlab-instance-da4355a9/test 1: digest: sha256:eb45a54c2c0e3edbd6732b454c8f8691ad412b56dd10d777142ca4624e223c69 size: 528
[/simterm]
Проверяем корзину or-gitlab-registry-test:
[simterm]
$ aws --profile internal s3 ls or-gitlab-registry-test/docker/registry/v2/repositories/gitlab-instance-da4355a9/test-repo/_manifests/tags/1/
PRE current/
PRE index/
[/simterm]
Окей — Registry работает, доступ к S3 работает, с ServiceAccounts проблем вроде нет.
ServiceAccounts и S3 access
Но на всякий случай проверим в других сервисах, например из пода Toolbox:
[simterm]
$ kk -n gitlab-cluster-test exec -ti gitlab-toolbox-565889b874-vgqcb -- bash
git@gitlab-toolbox-565889b874-vgqcb:/$ aws s3 ls or-gitlab-registry-test
PRE docker/
[/simterm]
Окей — тут тоже всё работает.
Grafana
Проверяем Grafana — https://gitlab-test.internal.example.com/-/grafana/.
Логин root, пароль берём из секрета:
[simterm]
$ kubectl -n gitlab-cluster-test get secret gitlab-grafana-initial-password -ojsonpath='{.data.password}' | base64 --decode ; echo
Cqc***wFS
Работает… Дашборды надо подключать отдельно, потом займёмся, как дойдём до мониторинга вообще, пока см. Grafana JSON Dashboards.
В общем, вроде всё.
Посмотрим, что дальше — администрирование, миграция проектов, мониторинг.
















