GitLab non-Omnibus 6.9.2  -> Omnibus 8.13.1 のバージョンアップは7.x系を経由してやるべし

## 概要
- オンプレにあったOpenStackのVM×1台をAWS上のEC2インスタンス×1台に移行する
- 同時にGitLabを現時点の最新版 8.13.1 にバージョンアップする
- MySQL(実際はMariaDB)で動かしてたので、PostgreSQLへのマイグレーションも必要
- 認証はOpenLDAP使ってたので、それも移行する
- ソースは外に漏らしたくないので、AWS上のディスク(EBS)は暗号化しつつ、接続元IPアドレスも絞る
- SSLはELBで終端する

当初 non-Omnibus 6.9.2 -> Omnibus 6.9.2 -> Omnibus 8.13.1 でやったが、データベースのマイグレーションが通らなかったので、一旦 Omnibus 7.13.5 を経由する手順にした。

## 移行先環境を準備する
平日昼間にピークが想定されるので、バーストできるT2を採用。
メモリは4GBぐらいほしいので、t2.mediumで。
Amazon Linuxでいきましょう。

### ディスクを作る

 - 現在の使い方をみつつ、ディスクレイアウトを決める
 - 後で拡張できるようにLVMにしておく
 - Omnibus にすると `/opt/gitlab` に本体、 `/var/opt/gitlab`に設定とかリポジトリとかが入る

```
/opt            10GB    10GBのEBS(gp2)、LVM
/var/opt        300GB  300GBのEBS(gp2)、LVM
/home           20GB    20GBのEBS(gp2)、LVM
```

パーティションを作成。`/opt`と`/home`には既にファイルが存在するので、コピーしておく。

```shell-session
$ sudo fdisk /dev/xvdb
$ sudo fdisk /dev/xvdc
$ sudo fdisk /dev/xvdd

$ sudo pvcreate /dev/xvdb1
$ sudo pvcreate /dev/xvdc1
$ sudo pvcreate /dev/xvdd1

$ sudo vgcreate VG01 /dev/xvdb1
$ sudo vgcreate VG02 /dev/xvdc1
$ sudo vgcreate VG03 /dev/xvdd1

$ sudo lvcreate -l 100%FREE -n LogVol01 VG01
$ sudo lvcreate -l 100%FREE -n LogVol01 VG02
$ sudo lvcreate -l 100%FREE -n LogVol01 VG03

$ sudo mkfs.ext4 /dev/mapper/VG01-LogVol01
$ sudo mkfs.ext4 /dev/mapper/VG02-LogVol01
$ sudo mkfs.ext4 /dev/mapper/VG03-LogVol01

$ sudo e2label /dev/mapper/VG01-LogVol01 /opt
$ sudo e2label /dev/mapper/VG02-LogVol01 /var/opt
$ sudo e2label /dev/mapper/VG03-LogVol01 /home
```

```shell-session
$ sudo mount LABEL=/opt /mnt
$ sudo cp -ax /opt/* /mnt/
$ sudo umount /mnt

$ sudo mount LABEL=/home /mnt
$ sudo cp -ax /home/* /mnt/
$ sudo umount /mnt

$ sudo mv /opt{,_old}
$ sudo mv /home{,_old}

$ sudo mkdir /opt
$ sudo mkdir /home

$ sudo mount LABEL=/home /home
$ sudo mount LABEL=/opt /opt
$ sudo mount LABEL=/var/opt /var/opt

$ sudo vi /etc/fstab

LABEL=/home /home       ext4    defaults        1   2
LABEL=/opt  /opt        ext4    defaults        1   2
LABEL=/var/opt /var/opt ext4    defaults        1   2
```

GitLabのバックアップからのリストア時に一時ファイルが/tmp以下に展開されるので、バックアップファイルと同程度の容量が/tmpで使用できることを確認しておく。

```shell-session
$ df -lh
Filesystem                 Size  Used Avail Use% Mounted on
devtmpfs                   2.0G   92K  2.0G   1% /dev
tmpfs                      2.0G     0  2.0G   0% /dev/shm
/dev/xvda1                 7.8G  1.1G  6.7G  14% /
/dev/mapper/VG03-LogVol01   20G   44M   19G   1% /home
/dev/mapper/VG01-LogVol01  9.8G   65M  9.2G   1% /opt
/dev/mapper/VG02-LogVol01  296G   63M  281G   1% /var/opt
```

```shell-session
$ sudo reboot
```

## Omnibus 6.9.2を入れる

 - なにはともあれ、yum update
 - GitLabのYumリポジトリには 6.9.2 がないので、手動でダウンロードして localinstallする

```shell-session
$ sudo yum update -y
```

移行元と同じバージョンのOmnibusパッケージを探す。

https://about.gitlab.com/downloads/archives/

6.9.2はこちら↓

https://downloads-packages.s3.amazonaws.com/centos-6.5/gitlab-6.9.2_omnibus.2-1.el6.x86_64.rpm

```shell-session
$ curl -LJO https://downloads-packages.s3.amazonaws.com/centos-6.5/gitlab-6.9.2_omnibus.2-1.el6.x86_64.rpm
$ sudo yum localinstall gitlab-6.9.2_omnibus.2-1.el6.x86_64.rpm
$ sudo gitlab-ctl reconfigure
```

## オンプレで移行するデータを作って移行先にコピーする

 - オンプレでバックアップをとる
 - データベース部分のファイルのみ MySQL -> PostgreSQLに変換してから差し替える
 - LDAPもダンプして持っていく
 - scpなどで移行先にコピーする

> Updating GitLab via omnibus-gitlab
> https://docs.gitlab.com/omnibus/update/README.html#upgrading-from-non-omnibus-mysql-to-an-omnibus-installation-version-68


バックアップとMySQLのダンプをPostgreSQLフレンドリーなオプションをつけてとっておく。

GitLabを止めてから、バックアップを作る。

```shell-session
$ sudo systemctl stop nginx gitlab
$ cd /home/git/gitlab
$ sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
```

MySQLのバックアップファイルをPostgreSQLに変換して差し替える。

```shell-session
$ sudo -u git -H mkdir -p tmp/backups/postgresql
$ sudo -u git -H mv tmp/backups/TIMESTAMP_gitlab_backup.tar tmp/backups/postgresql/
```

※TIMESTAMPは適宜読み替えること。

PostgreSQLコンパチ形式でMySQLのダンプを吐き出す。

```shell-session
$ cd tmp/backups/postgresql
$ sudo -u git -H mysqldump --compatible=postgresql --default-character-set=utf8 -r gitlabhq_production.mysql -u root gitlabhq_production -p
```

データベースコンバーターをダウンロードする。

```shell-session
$ sudo -u git -H git clone https://github.com/gitlabhq/mysql-postgresql-converter.git -b gitlab
```

MySQLのダンプをPostgreSQLに変換する。

```shell-session
$ sudo -u git -H mkdir db
$ sudo -u git -H python mysql-postgresql-converter/db_converter.py gitlabhq_production.mysql db/database.sql
$ sudo -u git -H ed -s db/database.sql < mysql-postgresql-converter/move_drop_indexes.ed
```

バックアップファイルの中のデータベース部分(tarの中身)を差し替える。

```shell-session
$ sudo -u git -H tar rf TIMESTAMP_gitlab_backup.tar db/database.sql
```

これを移行先サーバーにコピー。

```shell-session
$ scp -i .ssh/yoursshkey.pem TIMESTAMP_gitlab_backup.tar ec2-user@ec2-xx-xx-xx-xx.ap-northeast-1.compute.amazonaws.com:~
```

LDAPもダンプして持っていく。

```shell-session
$ mkdir ldap_backup
$ sudo slapcat -l ldap_backup/backup.ldif
$ sudo slapcat -b cn=config -l ldap_backup/backup_config.ldif
$ tar zcvf ldap_backup.tar.gz ldap_backup
```

scp でオンプレから移行先にコピーする。

```shell-session
$ scp -i .ssh/yoursshkey.pem ldap_backup.tar.gz ec2-user@ec2-xx-xx-xx-xx.ap-northeast-1.compute.amazonaws.com:~
```

## 移行先でバックアップから復元する

> https://gitlab.com/gitlab-org/omnibus-gitlab/blob/98b1bfb0d70082953d63abbc329cd6f2c628d3bc/README.md#restoring-an-application-backup

OmnibusのGitlabのバックアップディレクトリに、PostgreSQL変換済みのバックアップファイルを置く。

```shell-session
$ sudo cp TIMESTAMP_gitlab_backup.tar /var/opt/gitlab/backups/
```

Gitlab(unicornとsidekiq)を停止して、リストアコマンドを発行する。

```shell-session
$ sudo gitlab-ctl stop unicorn
ok: down: unicorn: 0s, normally up

$ sudo gitlab-ctl stop sidekiq
ok: down: sidekiq: 0s, normally up

$ sudo gitlab-rake gitlab:backup:restore BACKUP=TIMESTAMP

$ sudo gitlab-ctl start
```


## LDAPはOpenLDAP Serverを新しく作って、ダンプしたファイル(LDIF)を見ながら戻していく

```shell-session
$ sudo yum install openldap-servers openldap-clients openldap
$ sudo cp /usr/share/openldap-servers/DB_CONFIG.example /var/lib/ldap/DB_CONFIG
$ sudo vi /etc/rsyslog.conf


--- /etc/rsyslog.conf.back      2014-11-11 00:28:01.000000000 +0000
+++ /etc/rsyslog.conf   2016-10-29 10:03:11.405303294 +0000
@@ -56,6 +56,8 @@
 # Save boot messages also to boot.log
 local7.*                                                /var/log/boot.log
 
+# Ldap
+local4.*                                               /var/log/slapd.log
 
 # ### begin forwarding rule ###
 # The statement between the begin ... end define a SINGLE forwarding


$ sudo service rsyslog restart
```

バックアップファイルをもとに、LDAPを構成していく。

```shell-session
$ sudo service slapd start
$ sudo ldapadd -Y EXTERNAL -H ldapi:// -f 1_change_RootPW.ldif
$ sudo ldapmodify -x -D cn=config -W -f ./2_initial_config.ldif
$ sudo ldapadd -x -D "cn=Manager,dc=r-stack,dc=jp" -W -f 3_add_base.ldif
$ sudo ldapadd -x -D "cn=Manager,dc=r-stack,dc=jp" -W -f 4_add_users.ldif

$ sudo chkconfig slapd on
```

ご参考までに、各ファイルはこんな感じです。

 - 1_change_RootPW.ldif 

```shell-session
dn: olcDatabase={0}config,cn=config
changetype: modify
add: olcRootPW
olcRootPW: {SSHA}XXXXXXXXXXXXXXXXXXXXXXXXXXXXX
```

- 2_initial_config.ldif 

```shell-session
dn: olcDatabase={1}monitor,cn=config
changetype: modify
replace: olcAccess
olcAccess: {0}to * by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" read by dn.base="cn=Manager,dc=example,dc=com" read by * none

dn: olcDatabase={2}bdb,cn=config
changetype: modify
replace: olcSuffix
olcSuffix: dc=example,dc=com

dn: olcDatabase={2}bdb,cn=config
changetype: modify
replace: olcRootDN
olcRootDN: cn=Manager,dc=example,dc=com

dn: olcDatabase={2}bdb,cn=config
changetype: modify
replace: olcRootPW
olcRootPW: {SSHA}XXXXXXXXXXXXXXXXXXX
```

 - 3_add_base.ldif

```shell-session
dn: dc=example,dc=com
objectClass: dcObject
objectClass: organization
o: example.com
dc: example

dn: cn=Manager,dc=example,dc=com
objectClass: organizationalRole
objectClass: simpleSecurityObject
cn: Manager
description: LDAP Administrator
userPassword:: XXXXXXXXXXXXXXXXXXXXXXXX

dn: ou=People,dc=example,dc=com
objectClass: organizationalUnit
ou: People

dn: ou=Group,dc=example,dc=com
objectClass: organizationalUnit
ou: Group
```

 - 4_add_users.ldif

```shell-session
dn: ou=Sales,ou=Group,dc=example,dc=com
objectClass: groupOfNames
objectClass: top
cn: Sales
member: cn=user1,ou=People,dc=example,dc=com
ou: Sales

dn: cn=Taro Nihon,ou=People,dc=example,dc=com
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
objectClass: top
cn: Taro Nihon
sn: Nihon
uid: user1
mail: user1@example.com
o: Example, Inc.
ou: Sales
userPassword:: XXXXXXXXXXXXXXXXXXXX

... snip ...

```

## GitLabの初期設定

 - OmnibusのGitLabは、`/etc/gitlab/gitlab.rb` 経由で設定する
 - 直接 `gitlab.yml` とかをいじっても `gitlab-ctl reconfigure` すると消えるので注意

```shell-session
$ sudo vi /etc/gitlab/gitlab.rb
$ sudo gitlab-ctl reconfigure
$ sudo gitlab-rake gitlab:check

... snip ...

LDAP users with access to your GitLab server (only showing the first 100 results)
rake aborted!
ArgumentError: host,port,method,uid or filter,base MUST be provided
```

なぜかLDAP関連パラメータが`gitlab.yml`に反映されてない。バグっぽいのでバージョンアップすると直ると信じて、とりあえず手動で設定する。


## 移行先サーバーでの Omnibus 6.9.2の動作確認

 - この時点でブラウザで接続してみて、ちゃんとデータが移っているか、ちゃんと動くか、など確認
 - リバプロやELBなどでSSLを終端している構成だと、公式手順でやってたらアバターの画像が見れない

> https://gitlab.com/gitlab-org/gitlab-ce/issues/14287

StaticコンテンツもUnicornで処理させようとしているので、Unicornで処理してくれればそれはそれでいいんですが、URL生成する際に外部URLではなくて内部URL(HTTP)をとってきちゃってます。

> https://gitlab.com/gitlab-org/gitlab-ce/blob/master/app/models/user.rb#L673

ということで、無理くりNginxの設定ファイルを直接いじって、`/uploads`をStaticホスティングするようにしておく。`gitlab-ctl reconfigure`すると上書きされるので要注意。

```shell-session
$ sudo vi /var/opt/gitlab/nginx/etc/gitlab-http.conf

... snip ...

  location /uploads {
    root /var/opt/gitlab/gitlab-rails/uploads;
  }

```

## GitLabを段階アップデートをする

 - いきなり最新版の8.xにいくとデータベースのマイグレーションに失敗する
 - 6.9.2 -> 7.14.3 -> 8.13.1 と段階アップデートする

アップデートの仕方は、公式サイトの手順のとおり。

> https://about.gitlab.com/downloads/#centos6

```shell-session
$ sudo yum install postfix

$ sudo service sendmail stop
Shutting down sm-client:                                   [  OK  ]
Shutting down sendmail:                                    [  OK  ]
$ sudo chkconfig sendmail off
$ sudo service postfix start
Starting postfix:                                          [  OK  ]
$ sudo chkconfig postfix on
$ sudo alternatives --config mta

There are 2 programs which provide 'mta'.

  Selection    Command
-----------------------------------------------
*+ 1           /usr/sbin/sendmail.sendmail
   2           /usr/sbin/sendmail.postfix

Enter to keep the current selection[+], or type selection number: 2

... snip ...

$ curl -sS https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.rpm.sh | sudo bash
$ sudo yum install gitlab-ce-7.13.5
$ sudo gitlab-ctl reconfigure
$ sudo gitlab-rake gitlab:check

...snip...

CI / portal ... no
  Try fixing it:
  sudo -u git -H bundle exec rake gitlab:satellites:create RAILS_ENV=production
  If necessary, remove the tmp/repo_satellites directory ...
  ... and rerun the above command
  For more information see:
  doc/raketasks/maintenance.md
  Please fix the error above and rerun the checks.
```

satellitesがないと怒られるので、作っておく。

```shell-session
$ sudo gitlab-rake gitlab:satellites:create RAILS_ENV=production
$ sudo gitlab-rake gitlab:check
```

7.14.3 を入れる。

```shell-session
$ sudo yum update gitlab-ce-7.14.3
$ sudo gitlab-ctl reconfigure
$ sudo gitlab-rake gitlab:check
```

動作確認したら、8.13.1を入れる。

```shell-session
$ sudo yum update gitlab-ce-8.13.1
$ sudo gitlab-ctl reconfigure
$ sudo gitlab-rake gitlab:check
```

忘れずにNginxの設定を直しておく。

```shell-session

$ sudo vi /var/opt/gitlab/nginx/etc/gitlab-http.conf

  location /uploads {
    root /var/opt/gitlab/gitlab-rails/uploads;
  }

$ sudo gitlab-ctl restart nginx
```

おしまい。