Omnibus GitLabへの新しいサービスの追加

GitLabに新しいサービスを追加するには、以下の手順に従ってください:

  1. ビルド中にソフトウェアを取得し、コンパイルします。
  2. サービスのトップレベル設定オブジェクトを追加します。
  3. サービスをサービスリストに含める
  4. サービスの有効・無効レシピを作成
  5. ログローテーションの処理方法を決定し、文書化します。

オプションとして、もう1つの一般的なタスクは、サービスのために追加の設定解析を追加することです。

ビルド中にソフトウェアを取得してコンパイル

プロジェクトにまだ含まれていない場合は、サービスの新しいソフトウェア定義を追加する必要があります。

サービスのトップレベル設定オブジェクトを追加します。

files/gitlab-cookbooks にあるクックブックとレシピは、Omnibus GitLab パッケージがインストールされたインスタンスでgitlab-ctl reconfigure の間に実行されるものです。ここで、新しいサービスの設定を追加する必要があります。

デフォルトの属性を定義します。

サービスを設定するために既存のCookbookの1つを選ぶか、サービスがそれ自身を必要とする場合は新しいCookbookを作成してください。

クックブックの内部にはattributes/default.rb ファイルがあるはずです。ここでサービスのデフォルト属性を定義します。サービスにはデフォルトでenable

default['gitlab']['best_service']['enable'] = false
default['gitlab']['best_service']['dir'] = '/var/opt/gitlab/best-service'
default['gitlab']['best_service']['log_directory'] = '/var/log/gitlab/best-service'
  • default これは基本的なクックブックの属性を定義する方法です。
  • ['gitlab'] クックブックの名前をコンテナで指定します。
  • ['best_service'] はサービス名です。
  • enable dirlog_directory は内部設定です。
  • /var/opt/gitlab は作業ディレクトリとサービスの設定ファイルが置かれる場所です。
  • /var/log/gitlab はGitLabパッケージのログが書き込まれる場所です。

パッケージで設定したいことをすべてここで定義します。他の設定に基づいてデフォルトを計算する必要がある場合は、nil をデフォルトにしてください。

命名規約

サービスは主に3つの場面で参照されます:

  1. サービスに対応するChef属性へのアクセス
  2. サービスに対応するユーザー、グループ、パスなどの項目の参照
  3. 以下の例と同様に、サービスプロパティを検索するメソッドにサービス名を渡します:
    • “サービスは有効ですか?”
    • “このサービスに対応するログの所有権の詳細を取得”
    • “このサービスのrunit設定を生成する”

上記の最初のケースでは、サービス名の単語を区別するためにアンダースコアを使っています。他の2つのケースでは、サービス名の単語を区別するためにハイフンを使います。設定は主にRubyオブジェクトとして使用されるため、ハイフンではなくアンダースコアを使用する方が柔軟性があります(例えば、アンダースコアを使用することで、設定ハッシュにシンボルを使用する際にすっきりします)。

たとえば GitLab Pages を例にとると、属性はGitlab['gitlab_pages']node['gitlab_pages'] のようになり、デフォルトのディレクトリやパスは/var/log/gitlab/gitlab-pages/var/opt/gitlab/gitlab-pagesのようになります。同様に、メソッドコールはservice_enabled?("gitlab-pages")のようになります。

サービス用の設定マッシュを作成します。

/etc/gitlab/gitlab.rb からユーザーがサービスを設定できるようにするには、サービスのトップレベルのマッシュを追加する必要があります。

files/gitlab-cookbooks/package/libraries/config/gitlab.rbattribute のメソッドのリストがあります。

もしあなたのサービスが GitLab cookbook の属性内に存在するのであれば、attribute_block('gitlab') ブロック内に属性として追加してください。そうでなければ、もしあなたのサービスが独自のクックブックを持っているなら、それを上に追加してください。

attribute('best_service')

EEのみの属性には、ee_attribute

ee_attribute('best_service')

設定テンプレートへのサービス設定の追加

グローバル設定テンプレートをメンテナーしており、サービスの設定方法の例がコメントアウトされています。

このファイルはパッケージの新規インストール時に/etc/gitlab/gitlab.rb となります。

サービスの設定をユーザーに公開し、ユーザーが変更できるようにしたい場合は、このファイルに追加してください。files/gitlab-config-template/gitlab.rb.template

### Best Service configuration
# best_service['enable'] = true
# best_service['dir'] = '/var/opt/gitlab/best-service'
# best_service['log_directory'] = '/var/log/gitlab/best-service'

提供される値はデフォルトを反映するためのものではなく、サービスを使用するためにコメントを解除しやすくするためのものです。それが不可能な場合は、YOURSECRET などのように、明らかに置き換えることを意図した値を使うことができます。または、最も理にかなっている場合はデフォルトを使用してください。

サービスリストにサービスを含める

レシピの中でサービスを簡単に有効/無効にできるようにするには、サービスリストに追加し、適切なグループを与える必要があります。

files/gitlab-cookbooks/package/libraries/config/services.rb ファイルで、サービスが GitLab EE 専用かどうかに応じて、適切な Config クラス、Base または EE にサービスを追加します。

service 'best_service', groups: ['bestest']

グループを指定することで、関連する複数のサービスを一度に無効化/有効化することが簡単になります。

もし既存のグループがどれもあなたのサービスが行うことと一致せず、現在グループを使用してサービスを有効/無効にする必要がない場合。この時点でわざわざ追加する必要はありません。

既存のグループの例をいくつか挙げておきます:

  • サービスがデフォルトで Omnibus で有効になっている場合、DEFAULT_GROUP グループが追加されるはずです。
  • サービスがほとんどすべてのシナリオで無効になってはいけない場合は、SYSTEM_GROUP を追加してください。
  • サービスが GitLab Rails の設定に依存している場合は、rails グループを追加してください。
  • サービスが新しい Prometheus Exporter の場合は、prometheus グループを追加してください。

サービスの有効・無効レシピを作成します。

有効化レシピ

既存のクックブックに追加される場合、enableレシピはfiles/gitlab-cookbooks/<cookbook-name>/recipes/<service-name>.rb 。サービスが独自のクックブックを持っている場合、有効化レシピはfiles/gitlab-cookbooks/<cookbook-name>/recipes/enable.rb として作成できます。

レシピの中で、サービスの作業ディレクトリを/var/opt/gitlab に作成します。サービスを実行するシステムユーザーが作成されていることを確認します。サービスに必要な設定ファイルを作業ディレクトリにレンダリングします。

レシピの最後のほうで、レシピを定義するためにrunitサービス定義を呼び出します。この作業を行うためには、cookbookstemplates/default ディレクトリに run ファイルを作成する必要があります。これらのファイル名はsv- で始まり、サービス名、runitアクション名が続きます。

サービスには通常、runlog-runlog-configが必要です。

sv-best-service-log-config.erb:

<%= "s#@svlogd_size" if @svlogd_size %>
<%= "n#@svlogd_num" if @svlogd_num %>
<%= "t#@svlogd_timeout" if @svlogd_timeout %>
<%= "!#@svlogd_filter" if @svlogd_filter %>
<%= "u#@svlogd_udp" if @svlogd_udp %>
<%= "p#@svlogd_prefix" if @svlogd_prefix %>

sv-best-service-log-run.erb:

#!/bin/sh
exec chpst -P \
  -U root:<%= @options[:log_group] || 'root' %> \
  -u root:<%= @options[:log_group] || 'root' %> \
  svlogd -tt <%= @options[:log_directory] %>

sv-best-service-run.erb:

#!/bin/sh
exec 2>&1
<%= render("mount_point_check.erb") %>
cd <%= node['gitlab']['best-service']['dir'] %>
exec chpst -P /opt/gitlab/embedded/bin/best-service -config-flags -etc

何を実行するか、どのユーザーが実行するかによって、実行ファイルの設定は異なります。私たちの他の-run.erb に例があります。

レシピの中で、runitサービスを呼び出し、開始する必要があります:

runit_service "best-service" do
  options({
    configItem: 'value',
    [...]
    log_directory: logging_settings[:log_directory],
    log_user: logging_settings[:runit_owner],
    log_group: logging_settings[:runit_group],
  }.merge(params))
  log_options logging_settings[:options]
end

if node['gitlab']['bootstrap']['enable']
  execute "/opt/gitlab/bin/gitlab-ctl start best-service" do
    retries 20
  end
end

ログディレクトリ

logging_settings を含む上記の設定例では、サービスログディレクトリの設定、ログディレクトリに割り当てられたロググループ、および svlogd の実行に使用されるグループへの一貫した参照を提供するために、LogfilesHelper クラスを使用しています。

これらの設定を利用するには、LogfilesHelper クラスをenable.rb にインクルードしてください:

[...]
logfiles_helper = LogfilesHelper.new(node)
logging_settings = logfiles_helper.logging_settings('best-service')
[...]

default_logdir_ownership クラスメソッドのサービスリストに、ログディレクトリのユーザー/グループに使用するデフォルトのユーザー/グループを指定して、best-service を追加してください。特定のユーザー/グループが必要でない場合は、デフォルトで{ username: gitlab_user, group: gitlab_group }

レシピを無効にします

既存のクックブックに追加される場合、disableレシピはfiles/gitlab-cookbooks/<cookbook-name>/recipes/<service-name>_disable.rb 。サービスに独自のクックブックがある場合、disable レシピはfiles/gitlab-cookbooks/<cookbook-name>/recipes/disable.rb として作成できます。

レシピには、サービスが無効になったときに行いたいクリーンアップを記述し、runitサービスを無効にするコールを記述する必要があります。

runit_service "best-service" do
  action :disable
end

ログのローテーションがどのように処理されるかを決定し、文書化します。

Omnibusでは、指定されたサービスのログローテーションはlogrotatesvlogd、その両方、またはそのどちらでも処理できます。新しいサービスをログローテーションテーブルに含め、そのサービスのログを管理しローテーションする責任者を示す必要があります。サービスをOmnibus GitLabに追加するときは、次のようにします:

  • 新しいサービスのログローテーションが実施されていることを確認します。
  • 新しいサービスをログローテーションテーブルに追加するためにマージリクエストを開きます。

runit (svlogd) を使用していない新しいログが追加された場合、そのログを logrotate 設定に手動で追加する必要があります。logrotate 処理の改善イシューに詳細情報があります。

サービスの追加設定解析

ユーザーによって設定された他のオプションに基づいて特定の設定オプションを入力したい場合、変数を解析するためのライブラリをサービスに追加します。

ライブラリはfiles/gitlab-cookbooks/<cookbook name>/libraries/<service-name>.rb

ライブラリは、parse_variables メソッドを持つ、サービスにちなんだ名前のモジュールでなければなりません。

module BestService
  class << self
    def parse_variables
      # setup some additional configuration based on the values of the user provided configuration
    end
  end
end

GitLabの設定からparse_variablesメソッドを呼び出すようにします。

files/gitlab-cookbooks/package/libraries/config/gitlab.rb にアクセスし、ライブラリを使うように属性を更新します。

attribute('best_service').use { BestService }

変数をパースする順序は重要です。そのため、もしあなたのライブラリが他のサービスのライブラリの後にパースされることを期待する場合、あなたの属性にpriority 後から来る priority値を更新する必要があります。priority (デフォルト priority値は20です。)

attribute('expected_service').use { ExpectedService }
attribute('best_service', sequence: 25).use { BestService }