TECHSTEP

ITインフラ関連の記事を公開してます。

GitLab Self-managed環境をAmazon EC2に構築する

今回はGitLab Self-managed環境をAmazon EC2上に構築する例を紹介します。なお、ここではあくまでテスト用の環境構築を想定しているので、本番環境では使用しないでください。

背景

GitLabは大きくSaaS版とSelf-managed版の2つの形で提供しています (正確にはDedicatedという形態もあります)。このうちSelf-managed版はGitLabを動かす基盤を利用者が管理し、パッケージ等をインストールしてGitLab環境を用意する形態です。

docs.gitlab.com

GitLabの特徴として、このSelf-managed版を利用することで、自社のプライベート環境に閉じた形でバージョン管理システムを利用できる点があります。そのため検証環境を構築・利用する機会も多くなります。

今回はAmazon EC2上にGitLab Self-managed環境を構築する例を紹介します。検証環境ということですべてを有効化はしていませんが、よく使うであろうコンテナレジストリの有効化は行っています。

なお、リソースはAWS CloudFormationである程度作成していますが、一部は手動作業を含みます。

検証

今回構築した環境は以下の通りです。異なるGitLabのバージョンでは手順が異なる可能性もあるので、ご注意ください。

  • バージョン: GitLab Enterprise Edition v16.7.0-ee
  • 環境: AWS

今回は以下のような手順で環境を構築します。

AWS CloudFormationによるインスタンス等の作成

今回は以下のテンプレートを使用し、VPCなどのネットワーク、EC2インスタンスを作成しました。

gitlab-ec2.yaml

AWSTemplateFormatVersion: '2010-09-09'
Description: "EC2 instance for starting GitLab environment"
Parameters:
  ImageId:
    Default: "/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2"
    Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
  InstanceType:
    Default: "t3.xlarge"
    Type: String
  KeyName:
    Type: String
  VPCCidr:
    Default: "10.0.0.0/16"
    Type: String
  PublicSubnetCidr:
    Default: "10.0.0.0/24"
    Type: String
  PublicSubnetAZ:
    Default: "ap-northeast-1a"
    Type: String
  EnvName:
    Default: "GitLab-Test"
    Type: String

Resources:
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: !Ref VPCCidr
      EnableDnsHostnames: true
      EnableDnsSupport: true
      Tags:
        - Key: Name
          Value: !Ref EnvName
  PublicSubnet:
    Type: AWS::EC2::Subnet
    DependsOn: AttachGateway
    Properties:
      CidrBlock: !Ref PublicSubnetCidr
      VpcId: !Ref VPC
      AvailabilityZone: !Ref PublicSubnetAZ
      Tags:
        - Key: Name
          Value: !Ref EnvName
  InternetGateway:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
        - Key: Name
          Value: !Ref EnvName
  AttachGateway:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref VPC
      InternetGatewayId: !Ref InternetGateway
  PublicRouteTable:
    Type: AWS::EC2::RouteTable
    DependsOn: AttachGateway
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Ref EnvName
  PublicRoute:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref PublicRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway
  PublicSubnetRouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnet
      RouteTableId: !Ref PublicRouteTable
  EIP:
    Type: AWS::EC2::EIP
    Properties:
      Domain: vpc
      Tags:
        - Key: Name
          Value: !Ref EnvName
  EIPAssociation:
    Type: AWS::EC2::EIPAssociation
    Properties:
      AllocationId: !GetAtt EIP.AllocationId
      InstanceId: !Ref GitLabInstance
  EC2SecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: EC2SecurityGroup
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub ${EnvName}-EC2SecurityGroup
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: '0.0.0.0/0'
        - IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          CidrIp: '0.0.0.0/0'
        - IpProtocol: tcp
          FromPort: 5050
          ToPort: 5050
          CidrIp: '0.0.0.0/0'
  EC2IAMRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub ${EnvName}-SSM-role
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - ec2.amazonaws.com
            Action:
              - sts:AssumeRole
      Path: /
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
  EC2InstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Path: /
      Roles:
        - Ref: EC2IAMRole
      InstanceProfileName: !Sub ${EnvName}-EC2InstanceProfile
  GitLabInstance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !Ref ImageId
      KeyName: !Ref KeyName
      InstanceType: !Ref InstanceType
      SecurityGroupIds:
        - !Ref EC2SecurityGroup
      IamInstanceProfile: !Ref EC2InstanceProfile
      SubnetId: !Ref PublicSubnet
      UserData:
        Fn::Base64: |
          #!/bin/bash
          http="http://"
          ExtraUrl=`curl ifconfig.io`
          ExtraUrl=$http$ExtraUrl
          curl https://packages.gitlab.com/install/repositories/gitlab/gitlab-ee/script.rpm.sh | sudo bash
          sudo EXTERNAL_URL=$ExtraUrl yum install -y gitlab-ee
      Tags:
        - Key: Name
          Value: !Sub ${EnvName}-EC2

作成してしばらく待ち、作成されたパブリックIPアドレスを指定するとGitLabのUIにアクセスできるようになります。

rootアカウントでログイン、パスワードの変更

ログインする前にログイン用のパスワードを取得します。上記テンプレートを使用した場合はSession Managerからログインし、以下のコマンドを実行してrootアカウント用の初期パスワードを確認します。

#ec2-userにスイッチ
$ sudo su - ec2-user

#パスワードの確認
sh-4.2$ sudo su - ec2-user
[ec2-user@ip-10-0-0-238 ~]$ sudo cat /etc/gitlab/initial_root_password
# WARNING: This value is valid only in the following conditions
#          1. If provided manually (either via `GITLAB_ROOT_PASSWORD` environment variable or via `gitlab_rails['initial_root_password']` setting in `gitlab.rb`, it was provided beforedatabase was seeded for the first time (usually, the first reconfigure run).
#          2. Password hasn't been changed manually, either via UI or via command line.
#
#          If the password shown here doesn't work, you must reset the admin password following https://docs.gitlab.com/ee/security/reset_user_password.html#reset-your-root-password.

Password: vRC36YdBkHwRX4NlIZlecLMqd/OG0UIEaLyIJO/ghd0=

# NOTE: This file will be automatically deleted in the first reconfigure run after 24 hours.
[ec2-user@ip-10-0-0-238 ~]$

上記パスワードでGitLabにログインします。

上記パスワードは24時間で破棄されるので、rootユーザーのパスワードを変更します。

パスワードの変更後は再度ログインを要求されます。

Route53でドメイン登録、Aレコード追加

次に、構築したGitLabインスタンスで利用するドメインを登録します。後続の作業でhttps化を行いますが、これにはドメイン登録が必要になります。

今回はAmazon Route53を利用していますが、ごく一般的な手順なので必要な方だけご覧ください。

Amazon Route53でのドメイン取得と登録の手順


ここではドメインを取得するところから行います。 Amazon Route53のページに移動し、 登録済みドメイン から ドメインを登録 を選択します。

ドメイン検索に利用したいドメインを検索します。表示されたものから適当なものを選択します。

連絡先情報などを登録してドメイン取得のリクエストを作成します。

AWSから登録した連絡先のメールアドレスに連絡が届くので確認します。まずはメールアドレスの確認依頼が飛ぶので、リンク先をクリックします。

しばらく待つとリクエストしたドメインが利用可能となります。

登録済みドメインにリクエストしたドメインが含まれているので、ドメインを選択します。

作成したGitLabインスタンスIPアドレスに対するAレコードを登録します。


今後の作業のため、事前に test-project という名称でProjectを作成しています。この時点ではhttps化はされていないので、URL部分は以下のような表示となります。

また、この時点ではコンテナレジストリの有効化もされていないので、コンテナレジストリの項目も表示されません。

Let’s Encryptによるhttps化

次にhttps化を行います。GitLabでは Let’s Encrypt を使用したhttpsへの設定変更が用意されています。今回は検証目的なのでこちらを利用します。

docs.gitlab.com

Let’s Encryptを利用するには、GitLabの設定を変更するだけで可能です。まずGitLabインスタンスにログインし、/etc/gitlab/gitlab.rb というファイルを修正します。このファイルはGitLabの設定情報を管理するファイルで、ここでは external_url というパラメータに利用するURL (ここでは gitlabtest.com を利用) を設定します。

# バックアップの取得
[ec2-user@ip-10-0-0-238 ~]$ sudo cp -pi /etc/gitlab/gitlab.rb /etc/gitlab/gitlab.rb.bkup

# 修正
[ec2-user@ip-10-0-0-238 ~]$ sudo vi /etc/gitlab/gitlab.rb
[ec2-user@ip-10-0-0-238 ~]$ sudo diff /etc/gitlab/gitlab.rb /etc/gitlab/gitlab.rb.bkup
32c32
< external_url 'https://gitlabtest.com'
---
> external_url 'http://<GitLabインスタンスのパブリックIPアドレス>'

/etc/gitlab/gitlab.rb に対する修正を反映するには、 gitlab-ctl reconfigure コマンドを実行します。

[ec2-user@ip-10-0-0-238 ~]$ sudo gitlab-ctl reconfigure
[2023-12-29T03:13:34+00:00] INFO: Started Cinc Zero at chefzero://localhost:1 with repository at /opt/gitlab/embedded (One version per cookbook)
Cinc Client, version 17.10.0
Patents: https://www.chef.io/patents
Infra Phase starting

(割愛)

[2023-12-29T03:15:10+00:00] INFO: Report handlers complete
Infra Phase complete, 88/1059 resources updated in 01 minutes 36 seconds
[2023-12-29T03:15:10+00:00] WARN: This release of Cinc Client became end of life (EOL) on May 1st 2023. Please update to a supported release to receive new features, bug fixes, and security updates.
gitlab Reconfigured!

更新ができていれば、WebブラウザからGitLabにアクセスしたとき、以下のようになります。

コンテナレジストリの有効化

次にコンテナレジストリの有効化を行います。コンテナレジストリの有効化も先ほどと同様 /etc/gitlab/gitlab.rb を修正します。ここでは registry_external_url というパラメータを有効にし、利用するURL (ここでは gitlabtest.com:5050 ) を設定します。

docs.gitlab.com

[ec2-user@ip-10-0-0-238 ~]$ sudo vi /etc/gitlab/gitlab.rb
[ec2-user@ip-10-0-0-157 ~]$ sudo diff /etc/gitlab/gitlab.rb /etc/gitlab/gitlab.rb.bkup
32c32
< external_url 'https://gitlabtest.com'
---
> external_url 'http://<GitLabインスタンスのパブリックIPアドレス>'
928c928
< registry_external_url 'https://gitlabtest.com:5050'
---
> # registry_external_url 'https://registry.example.com'

こちらも修正後に反映します。

[ec2-user@ip-10-0-0-238 ~]$ sudo gitlab-ctl reconfigure
[2023-12-29T03:23:13+00:00] INFO: Started Cinc Zero at chefzero://localhost:1 with repository at /opt/gitlab/embedded (One version per cookbook)
Cinc Client, version 17.10.0
Patents: https://www.chef.io/patents
Infra Phase starting

(割愛)

[2023-12-29T03:23:33+00:00] INFO: Report handlers complete
Infra Phase complete, 5/934 resources updated in 20 seconds
[2023-12-29T03:23:33+00:00] WARN: This release of Cinc Client became end of life (EOL) on May 1st 2023. Please update to a supported release to receive new features,bug fixes, and security updates.
gitlab Reconfigured!
[ec2-user@ip-10-0-0-238 ~]$

設定変更ができていれば、以下のようにコンテナレジストリが利用可能となります。

動作確認

ここから動作確認をします。今回はGitLabインスタンス上からコンテナイメージをPushし、コンテナレジストリが機能するのを確認しました。

まずはGitLabインスタンスにDockerのインストールをします。

# Dockerのインストール
[ec2-user@ip-10-0-0-238 ~]$ sudo yum update -y
[ec2-user@ip-10-0-0-238 ~]$ sudo amazon-linux-extras install -y docker
[ec2-user@ip-10-0-0-238 ~]$ amazon-linux-extras | grep docker
 20docker=latest            enabled      \

# Dockerの有効化
[ec2-user@ip-10-0-0-238 ~]$ sudo systemctl start docker
[ec2-user@ip-10-0-0-238 ~]$ systemctl status docker
● docker.service - Docker Application Container Engine
   Loaded: loaded (/usr/lib/systemd/system/docker.service; disabled; vendor preset: disabled)
   Active: active (running) since Fri 2023-12-29 03:26:31 UTC; 5s ago
     Docs: https://docs.docker.com

(割愛)

[ec2-user@ip-10-0-0-238 ~]$ sudo systemctl enable docker
Created symlink from /etc/systemd/system/multi-user.target.wants/docker.service to /usr/lib/systemd/system/docker.service.

# sudo無しでdockerコマンドを実行可能にする
[ec2-user@ip-10-0-0-238 ~]$ grep docker /etc/group
docker:x:986:
[ec2-user@ip-10-0-0-238 ~]$ sudo usermod -a -G docker ec2-user
[ec2-user@ip-10-0-0-238 ~]$ grep docker /etc/group
docker:x:986:ec2-user
[ec2-user@ip-10-0-0-238 ~]$ exit
logout
sh-4.2$ sudo su - ec2-user
Last login: Fri Dec 29 03:08:21 UTC 2023 on pts/0
[ec2-user@ip-10-0-0-238 ~]$ docker version
Client:
 Version:           20.10.25
 API version:       1.41
 Go version:        go1.20.10
 Git commit:        b82b9f3
 Built:             Fri Oct 13 22:46:12 2023
 OS/Arch:           linux/amd64
 Context:           default
 Experimental:      true

(割愛)

[ec2-user@ip-10-0-0-238 ~]$

Dockerをインストールしたので、適当なイメージを取得し、レジストリに配置します。

# nginxイメージの取得
[ec2-user@ip-10-0-0-238 ~]$ docker pull nginx:latest

# GitLabコンテナレジストリへのログイン
# rootアカウントのIDとPWを使用してログインする
[ec2-user@ip-10-0-0-238 ~]$ docker login gitlabtest.com:5050

# コンテナレジストリへのPush
[ec2-user@ip-10-0-0-238 ~]$ docker tag nginx:latest gitlabtest.com:5050/root/test-project
[ec2-user@ip-10-0-0-238 ~]$ docker image ls
REPOSITORY                              TAG       IMAGE ID       CREATED        SIZE
nginx                                   latest    d453dd892d93   2 months ago   187MB
gitlabtest.com:5050/root/test-project   latest    d453dd892d93   2 months ago   187MB

[ec2-user@ip-10-0-0-238 ~]$ docker push gitlabtest.com:5050/root/test-project

GitLabを確認すると、以下のようにコンテナが格納されているのを確認できます。