Omnibus GitLab에 새로운 서비스 추가

GitLab에 새로운 서비스를 추가하려면 다음 단계를 따르셔야 합니다.

  1. 빌드 중 소프트웨어를 가져와 컴파일하기
  2. 서비스를 위한 최상위 구성 객체 추가
  3. 서비스를 서비스 목록에 포함하기
  4. 서비스를 위한 활성화 및 비활성화 레시피 생성
  5. 로그 회전을 처리하는 방법 결정 및 문서화

옵션으로 다른 일반적인 작업은 서비스에 대한 추가 구성 구문 분석입니다.

빌드 중 소프트웨어를 가져와 컴파일하기

프로젝트에 이미 포함되어 있지 않다면 서비스를 위한 새로운 소프트웨어 정의를 추가해야 합니다.

서비스를 위한 최상위 구성 객체 추가

files/gitlab-cookbooks에 위치한 Cookbooks 및 Recipes는 Omnibus GitLab 패키지가 설치된 인스턴스에서 gitlab-ctl reconfigure 실행 시 실행됩니다. 여기에 새로운 서비스의 설정을 추가해야 합니다.

기본 속성 정의

기존 Cookbooks 중 하나를 선택하여 서비스를 구성하거나, 서비스가 별도로 필요한 경우 새로운 Cookbook을 만드셔도 됩니다.

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’는 기본적인 Cookbook 속성을 정의하는 방법입니다.
  • ['gitlab']은 Cookbook 이름을 포함합니다.
  • ['best_service']는 서비스의 이름입니다.
  • ‘enable’, ‘dir’, ‘log_directory’는 설정입니다.
  • /var/opt/gitlab는 서비스의 작업 디렉토리 및 구성 파일이 위치하는 곳입니다.
  • /var/log/gitlab은 GitLab 패키지의 로그가 기록된 위치입니다.

여기에 패키지에서 구성 가능한 모든 설정을 정의하셔서, 필요한 경우 다른 설정을 기반으로 기본값을 계산하려면 일단 ‘nil’로 설정하십시오.

명명 규칙

서비스는 주로 세 가지 시나리오에서 언급됩니다.

  1. 서비스에 해당하는 Chef 속성에 액세스하는 경우
  2. 사용자, 그룹 및 해당 서비스의 경로와 같은 항목을 참조하는 경우
  3. 서비스 이름을 해당 서비스 속성을 찾는 메서드에 전달하여 확인하는 경우
    • “서비스가 활성화되었습니까?”
    • “이 서비스에 해당하는 로그 소유권 세부 정보 가져오기”
    • “이 서비스에 대한 runit 구성 생성하기”

위에서 언급된 첫 번째 경우에는 서비스 이름의 단어를 구분하는 데 밑줄을 사용합니다. 나머지 두 경우에는 서비스 이름의 단어를 구분하는 데 하이픈을 사용합니다. 구성이 주로 Ruby 객체로 사용되므로 밑줄을 사용하는 것이 더 유연합니다(예: 밑줄을 사용하면 구성 해시에서 심볼을 더 깔끔하게 사용할 수 있음).

예를 들어, GitLab Pages를 살펴보면 속성은 Gitlab['gitlab_pages']node['gitlab_pages']로 사용 가능하며, 기본 디렉토리 및 경로는 /var/log/gitlab/gitlab-pages/var/opt/gitlab/gitlab-pages와 비슷할 것입니다. 비슷하게 메서드 호출은 service_enabled?("gitlab-pages")와 같이 보일 것입니다.

서비스를 위한 구성 Mash 생성

사용자가 /etc/gitlab/gitlab.rb에서 서비스를 구성할 수 있도록 하려면 서비스를 위한 최상위 Mash를 추가해야 합니다.

files/gitlab-cookbooks/package/libraries/config/gitlab.rb에서는 attribute 메서드 목록을 찾을 수 있습니다.

만약 서비스가 GitLab Cookbook의 속성 내에 있는 경우 attribute_block('gitlab') 블록 내에 해당 속성을 추가해야 합니다. 그렇지 않은 경우, 서비스가 고유한 Cookbook을 갖는 경우에는 그 위에 추가하셔야 합니다.

attribute('best_service')

EE 전용 속성인 경우, 대신 ee_attribute을 사용하십시오.

ee_attribute('best_service')

서비스 구성을 설정 템플릿에 추가

우리는 전역 구성 템플릿을 유지하고 있으며, 이 템플릿에는 서비스를 구성하는 방법에 대한 예제가 주석 처리되어 있습니다.

이 파일은 패키지를 새로 설치할 때 /etc/gitlab/gitlab.rb로 사용됩니다.

서비스의 구성을 변경할 수 있도록 하려면 해당 파일에 추가하셔야 합니다. files/gitlab-config-template/gitlab.rb.template

### 최고의 서비스 구성
# 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 파일에 서비스를 적절한 Config 클래스, Base 또는 EE에 추가해야 합니다(서비스가 GitLab EE 전용일 때).

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

그룹을 지정하면 한꺼번에 여러 관련 서비스를 비활성화/활성화하는 것이 더 쉬워집니다.

기존의 그룹 중 어느 것도 서비스와 일치하지 않고, 현재 시점에서 그룹을 사용하여 서비스를 활성화/비활성화할 필요가 없다면 일단 추가하지 마십시오.

다음은 사용할 수 있는 일부 기존 그룹의 예입니다:

  • 서비스가 Omnibus에서 기본적으로 활성화되어야 하는 경우 DEFAULT_GROUP 그룹에 추가해야 합니다.
  • 거의 모든 시나리오에서 서비스를 비활성화하지 말아야 하는 경우 SYSTEM_GROUP을 추가해야 합니다.
  • 서비스가 GitLab Rails가 구성되어 있어야 하는 경우 rails 그룹을 추가해야 합니다.
  • 새로운 Prometheus 익스포터인 경우 prometheus 그룹을 추가해야 합니다.

서비스를 위한 활성화 및 비활성화 레시피 생성

활성화 레시피

활성화 레시피는 기존 쿡북에 추가되는 경우 files/gitlab-cookbooks/<cookbook-name>/recipes/<service-name>.rb으로 작성되어야 합니다. 서비스가 자체 쿡북을 갖고 있는 경우, 활성화 레시피는 files/gitlab-cookbooks/<cookbook-name>/recipes/enable.rb으로 작성할 수 있습니다.

레시피에서는 서비스를 위한 작업 디렉토리를 /var/opt/gitlab에 생성해야 합니다. 서비스를 실행하는 시스템 사용자를 생성해야 합니다. 서비스에 필요한 모든 구성 파일을 작업 디렉토리에 렌더링해야 합니다.

레시피의 끝 부분에서는 레시피를 정의하기 위해 runit 서비스 정의를 호출해야 합니다. 이를 위해 쿡북의 templates/default 디렉토리에 run 파일을 만들어야 합니다. 이러한 파일 이름은 서비스 이름으로 시작하고 이를 runit 작업 이름이 따릅니다.

서비스는 일반적으로 run, log-run, log-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

로그 디렉토리

위에서 언급된 예제 설정은 LogfilesHelper 클래스를 활용하여 서비스 로그 디렉토리, 로그 디렉토리에 할당된 로그 그룹 및 svlogd 실행에 사용되는 그룹에 대한 구성 설정에 일관적인 참조를 제공합니다.

이러한 설정을 사용하려면 enable.rb에 서비스에 대한 LogfilesHelper 클래스를 포함해야 합니다. 예시:

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

기본 로그 디렉토리 소유권(user/group)에 대한 기본 사용자/그룹을 지정하려면 default_logdir_ownership 클래스 메서드의 서비스 목록에 best-service를 추가하세요. 구체적인 사용자/그룹 요구 사항이 없는 경우에는 username: gitlab_user, group: gitlab_group로 기본 설정하세요.

비활성화 레시피

비활성화 레시피는 기존 쿡북에 추가되는 경우 files/gitlab-cookbooks/<cookbook-name>/recipes/<service-name>_disable.rb으로 작성되어야 합니다. 서비스가 자체 쿡북을 갖고 있는 경우, 비활성화 레시피는 files/gitlab-cookbooks/<cookbook-name>/recipes/disable.rb로 작성할 수 있습니다.

레시피는 서비스가 비활성화될 때 수행할 모든 정리 작업을 포함해야 하며, runit 서비스를 비활성화하는 호출을 가져야 합니다.

runit_service "best-service" do
  action :disable
end

로그 회전 처리 방법 결정 및 문서화

Omnibus에서 특정 서비스에 대한 로그 회전logrotate, svlogd, 양쪽 또는 어느 쪽도 담당할 수 있습니다. 새 서비스를 Omnibus GitLab에 추가할 때 다음을 수행해야 합니다:

  • 새 서비스에 대해 로그 회전이 제대로 이루어졌는지 확인하세요.
  • 새 서비스가 로그 회전 테이블에 추가되도록 하는 병합 요청을 오픈하세요.

runit (svlogd)를 사용하지 않는 새로운 로그가 추가되는 경우, 해당 로그를 수동으로 logrotate 구성에 추가해야 합니다. Improve logrotate handling 문제에서 자세한 정보를 확인할 수 있습니다.

서비스를 위한 추가 구성 구문 분석

사용자가 설정한 다른 옵션에 따라 특정 구성 옵션을 채우고 싶다면, 해당 서비스의 변수를 구문 분석하는 라이브러리를 추가해야 합니다.

해당 라이브러리는 files/gitlab-cookbooks/<쿡북 이름>/libraries/<service-name>.rb에 추가되어야 합니다.

이 라이브러리는 서비스 이름을 따르는 모듈이어야 하며 parse_variables 메서드를 가져야 합니다.

module BestService
  class << self
    def parse_variables
      # 사용자가 제공한 구성 값에 기반한 추가 구성 설정 설정
    end
  end
end

그런 다음 GitLab 구성에서 구문 분석 변수의 메서드를 호출해야 합니다.

files/gitlab-cookbooks/package/libraries/config/gitlab.rb로 이동하여 속성을 라이브러리를 사용하도록 업데이트하세요.

attribute('best_service').use { BestService }

구문 분석 변수의 순서가 중요합니다. 따라서 라이브러리가 다른 서비스의 라이브러리 후에 구문 분석되길 원하는 경우 priority 값을 나중에 오는 값으로 업데이트해야 합니다. (기본 priority 값은 20입니다)

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