2021年2月22日月曜日

application_role の Gitlab を docker-compose で立ち上げる

概要

過去に application_role を使って Gitlab を構築する方法を紹介しました
今回はコンテナで application_role な Gitlab を構築し各種コンポーネントと連携する docker-compose.yml を作成してみました

環境

  • Ubuntu 18.04
  • docker 20.10.3
  • Gitlab 13.6.7

docker-compose.yml

  • vim docker-compose.yml
version: "3.6"

services:
  gitlab:
    image: gitlab/gitlab-ee:13.6.7-ee.0
    ports:
      - "22:22"
      - "80:80"
    volumes:
      - config:/etc/gitlab
      - logs:/var/log/gitlab
      - dot_ssh:/var/opt/gitlab/.ssh
      - uploads:/var/opt/gitlab/gitlab-rails/uploads
      - shared:/var/opt/gitlab/gitlab-rails/shared
      - builds:/var/opt/gitlab/gitlab-ci/builds
      - git-data:/var/opt/gitlab/git-data
    environment:
      GITLAB_OMNIBUS_CONFIG: |
        roles ['application_role']

        external_url 'https://gitlab.example.com'
        nginx['enable'] = true
        nginx['listen_port'] = 80
        nginx['listen_https'] = false

        gitlab_rails['registry_enabled'] = true
        gitlab_rails['registry_host'] = "registry-gitlab.example.com"
        gitlab_rails['registry_api_url'] = "http://registry:5000"

        postgresql['enable'] = false
        gitlab_rails['db_adapter'] = 'postgresql'
        gitlab_rails['db_encoding'] = 'unicode'
        gitlab_rails['db_host'] = 'postgres'
        gitlab_rails['db_password'] = 'xxxxxxx'

        redis['enable'] = false
        gitlab_rails['redis_host'] = "redis"

        prometheus['enable'] = false

        gitlab_workhorse['prometheus_listen_addr'] = "0.0.0.0:9229"
        gitaly['prometheus_listen_addr'] = "0.0.0.0:9236"
        node_exporter['listen_address'] = '0.0.0.0:9100'
        gitlab_exporter['listen_address'] = '0.0.0.0'
        gitlab_exporter['listen_port'] = '9168'
        sidekiq['listen_address'] = '0.0.0.0'
        puma['listen'] = '0.0.0.0'
        puma['port'] = 8080
        gitlab_rails['monitoring_whitelist'] = ['127.0.0.0/8', '172.30.1.0/24']
        gitlab_rails['prometheus_address'] = 'prometheus:9090'
        nginx['status']['options'] = {
          "server_tokens" => "off",
          "access_log" => "off",
          "allow" => "172.30.1.0/24",
          "deny" => "all",
        }
    restart: always
    depends_on:
      - redis
  gitlab-runner:
    image: gitlab/gitlab-runner:v13.6.0
    restart: always
  registry:
    image: registry:2
    volumes:
      - registry:/var/lib/registry
    environment:
      REGISTRY_STORAGE_DELETE_ENABLED: 'true'
    restart: always
  registry_web:
    image: nginx:1.19.7
    ports:
      - "81:80"
    volumes:
      - ./registry_nginx/default.conf:/etc/nginx/conf.d/default.conf
    restart: always
    depends_on:
      - registry
    restart: always
  postgres:
    image: postgres:11.10
    volumes:
      - postgres:/var/lib/postgresql/data/pgdata
      - ./postgres/init.sql:/docker-entrypoint-initdb.d/init.sql
    environment:
      POSTGRES_PASSWORD: xxxxxxx
      PGDATA: /var/lib/postgresql/data/pgdata
  redis:
    image: redis:6
    volumes:
      - redis:/data
    depends_on:
      - postgres
    restart: always
    command: ["redis-server", "--appendonly", "yes"]
  prometheus:
    image: prom/prometheus:v2.25.0
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus:/prometheus-data
    restart: always
    command: ["--config.file=/prometheus-data/prometheus.yml"]
 alertmanager:
    image: prom/alertmanager:v0.21.0
    volumes:
      - ./alertmanager:/alertmanager
    ports:
      - "9093:9093"
    restart: always
    command: ["--config.file=/alertmanager/alertmanager.yml"]
    user: "0:0"
  grafana:
    image: grafana/grafana:7.4.2
    ports:
      - "3000:3000"
    volumes:
      - grafana:/var/lib/grafana
      - ./grafana/grafana.ini:/etc/grafana/grafana.ini
    restart: always

volumes:
  config:
    driver: local
  logs:
    driver: local
  dot_ssh:
    driver: local
  uploads:
    driver: local
  shared:
    driver: local
  builds:
    driver: local
  git-data:
    driver: local
  registry:
    driver: local
  postgres:
    driver: local
  redis:
    driver: local
  grafana:
    driver: local

networks:
  default:
    attachable: true
    ipam:
     driver: default
     config:
       - subnet: 172.30.1.0/24
         gateway: 172.30.1.1

registry

  • mkdir registry
  • vim registry/default.conf
server {
  listen *:80;
  server_name registry-gitlab.example.com;
  server_tokens off;
  client_max_body_size 0;
  chunked_transfer_encoding on;

  location / {
    proxy_set_header Host $http_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 https;
    proxy_set_header X-Forwarded-Ssl on;

    proxy_read_timeout 900;
    proxy_cache off;
    proxy_buffering off;
    proxy_request_buffering off;
    proxy_http_version 1.1;

    proxy_pass http://registry:5000;
  }
}

PostgreSQL

  • mkdir postgres
  • vim postgres/init.sql
create user gitlab with password 'xxxxxxx';
create database gitlabhq_production owner gitlab;
alter role gitlab with superuser;

Grafana

  • mkdir grafana
  • vim grafana/grafana.ini
[server]
root_url = http://192.168.100.10:3000

[auth.gitlab]
enabled = true
allow_sign_up = true
client_id = xxxxx
client_secret = xxxxx
scopes = api
auth_url = https://gitlab.example.com/oauth/authorize
token_url = https://gitlab.example.com/oauth/token
api_url = https://gitlab.example.com/api/v4
allowed_groups =
[auth.basic]
enabled = false
disable_login_form = true

Prometheus

  • mkdir prometheus
  • vim prometheus/prometheus.yml
global:
  scrape_interval:     15s
  evaluation_interval: 15s

alerting:
  alertmanagers:
  - static_configs:
    - targets:
      - alertmanager:9093

rule_files:
  - '/prometheus-data/alerts.rule'

scrape_configs:
  - job_name: nginx
    static_configs:
      - targets:
        - gitlab:8060
  - job_name: gitlab-workhorse
    static_configs:
      - targets:
        - gitlab:9229
  - job_name: gitlab-rails
    metrics_path: "/-/metrics"
    static_configs:
      - targets:
        - gitlab:8080
  - job_name: gitlab-sidekiq
    static_configs:
      - targets:
        - gitlab:8082
  - job_name: gitlab_exporter_database
    metrics_path: "/database"
    static_configs:
      - targets:
        - gitlab:9168
  - job_name: gitlab_exporter_sidekiq
    metrics_path: "/sidekiq"
    static_configs:
      - targets:
        - gitlab:9168
  - job_name: gitlab_exporter_metrics
    metrics_path: "/metrics"
    static_configs:
      - targets:
        - gitlab:9168
  - job_name: gitaly
    static_configs:
      - targets:
        - gitlab:9236
  • vim prometheus/alerts.rule
groups:
  - name: 'gitlab-rails database connections'
    rules:
    - alert: 'Too many database connections'
      expr: gitlab_database_connection_pool_connections{job="gitlab-rails"} > 100
      for: 5s
      annotations:
        summary: 'instance: {{ $labels.instance }}, value: {{ $value }}'

Alertmanager

  • mkdir alertmanager
  • vim alertmanager/alertmanager.yml
route:
  receiver: 'slack'
receivers:
- name: 'slack'
  slack_configs:
    - api_url: 'https://hooks.slack.com/services/xxxxx/xxxxxx/xxxxxxxxxxxxxx'
      channel: '#general'
      text: "{{ .CommonAnnotations.summary }}"
      send_resolved: true

解説

今回の構成は application_role の上に LB やリバースプロキシがある前提になります
https を受けるのはそれらの LB やリバースプロキシになります
Gitlab 側は 80 番で受ける想定になっています

application_role な gitlab コンテナはスケールできるように 5 箇所 (/var/opt/gitlab/.ssh, /var/opt/gitlab/gitlab-rails/uploads, /var/opt/gitlab/gitlab-rails/shared, /var/opt/gitlab/gitlab-ci/builds, /var/opt/gitlab/git-data) をコンテナボリュームでマウントしています
これにより必要なデータをコンテナボリュームで共有しています
もし docker swarm などを使ってホストをまたぐ場合は nfs を使ってボリュームを作成してください
/etc/gitlab は永続化しておかないとコンテナが再起動した際にうまく動作しないので永続化しましょう
/var/log/gitlab は過去のログが見れるようにしています

Gitlab の設定は gitlab.rb を書かずに GITLAB_OMNIBUS_CONFIG にすべて設定しています
PostgreSQL や Redis の参照はこの中にすべて記載します

application_role 以外のコンポーネント (PostgreSQL, Redis, registry, Prometheus, Grafana, Alertmanager) はすべてコンテナで作成します
各コンポーネントの設定ファイルは volumes でマウントしてコンテナに渡す方式にしています
また永続化が必要な領域はすべてコンテナボリュームを作成してマウントしています

Gitlab コンテナを起動した際にデータベースのマイグレーションが走るのでデータベースが起動してから Gitlab コンテナが起動するように depends_on で制御しています

PostgreSQL のバージョンが少し古い 11.10 なのは Gitlab が pg_dump 可能なバージョンが最新版に対応していないためです

22 番ポートを EXPOSE していますがホスト側ですでに 22 番ポートを LISTEN している場合は EXPOSE するポートを変更するとホスト側の sshd の LISTEN ポートを 22 以外に変更してください
また registry 用で nginx を起動します
すでに Gitlab コンテナで 80 番ポートを使っているので 81 番ポートを EXPOSE するようにしています
このあたりは別ホストがある場合は Gitlab コンテナが動作していないホストで registry 用の nginx を起動して 80 番ポートで EXPOSE しても OK です
gitlab コンテナを冗長化することもできますが EXPOSE するポートが重複するのでその場合は Swarm などを組んで複数のホストを準備してください

Grafana の Gitlab OAuth 用の client_idclient_secret はどうしても Gitlab 構築後に Admin Area からアプリケーションを作成する必要があるのでアプリケーション作成後に設定しなおし grafana コンテナを再起動しましょう

ネットワークでは ipam でアドレス帯を決めています
nginx の設定で IP もしくは CIDR を必ず指定する必要があるためです

動作確認

  • docker-compose up -d

ですべてのコンテナが起動するか確認します
問題なく起動したら external_url にアクセスして Gitlab が動作しているか確認しましょう
502 などになる場合は puma が立ち上がっているのかやログを確認してエラーが出ていないか確認しましょう

  • docker-compose exec gitlab gitlab-ctl status
  • docker-compose logs -f gitlab

トラブルシューティング: クリーンアップ

もし初回起動でミスした場合は誤った設定がデータベースのボリュームコンテナに残る可能性があるのですべてのコンテナを削除後にボリュームコンテナも削除してから再度起動するようにしてください

  • docker-compose down
  • docker volume rm $(docker volume ls -q)
  • docker-compose up -d

トラブルシューティング: SKIP=registry

バックアップを取得する際は SKIP=registry を入れないとエラーになります

  • docker-compose exec gitlab gitlab-backup create SKIP=registry

0 件のコメント:

コメントを投稿