CentOS8にGitLab Runnerをインストールする

自前のサーバで構築したGitLabでCI/CDを動かしたい場合はGitLab Runnerをインストールする必要がある。自分のGitLabサーバにGitLab Runnerをインストールする機会があったのでここに備忘録として残しておく。

前提

  • 自前のGitLabを既に構築しておりブラウザからrootアカウントでログインできる
  • GitLab RunnerサーバにSSHログインできてroot権限で作業できる
    • 今回はGitLabサーバとGitLab Runnerサーバを同一サーバに構築した
  • SELinuxを無効化している

バージョン

  • OS: CentOS8
  • GitLab: 13.2.3-ee
  • GitLab Runner: 13.2.2

準備

事前に以下の手順で設定情報をメモしておく。この情報はRunnerの設定時に利用する。

  1. GitLabにrootアカウントでログイン
  2. 「Admin Area」にアクセス
  3. Overview -> Runners ページにアクセス
  4. 「Set up a shared Runner manually」のURLとトークンをメモしておく

作業開始

ここからインストール、設定、起動の作業をする。GitLab RunnerサーバにSSHログインしrootアカウントになっておく。

Docker

今回はExecutor(CI/CDのjobを実行する実行環境)にDockerを採用するため、先にDockerをインストールし起動しておく。

インストール

curl -O https://download.docker.com/linux/centos/7/x86_64/stable/Packages/containerd.io-1.2.13-3.2.el7.x86_64.rpm
dnf install -y containerd.io-1.2.13-3.2.el7.x86_64.rpm
dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
dnf install -y docker-ce docker-ce-cli
systemctl start docker
systemctl enable docker

NAPTを設定

CentOS8のDockerではコンテナが名前解決のためホストと同じDNSサーバに問い合わせし、Firewallを起動している場合はIP到達性がなくなるためネットワークのエラーが発生してしまう。こちらの記事に載せられていた対策を実施する。

firewall-cmd --add-masquerade --permanent
firewall-cmd --reload

GitLab Runner

インストール

公式サイトを参考にした。

curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.rpm.sh | bash
dnf -y install gitlab-runner

設定

公式サイトを参考にした。以下のコマンドを実行して対話形式で情報を入力していく。

gitlab-runner register
Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com/):
https://xxxx.xxxx.xxxx/(ここに先ほどメモしたURLを貼り付ける)
Please enter the gitlab-ci token for this runner:
xxxxxxxxxxxxxx(ここに先ほどメモしたトークンを貼り付ける)
Please enter the gitlab-ci description for this runner:
[GitLab]: my-runner(この名前がRunner一覧ページに表示される)
Please enter the gitlab-ci tags for this runner (comma separated):
(指定しなくてもよい)
Please enter the executor: parallels, shell, ssh, kubernetes, custom, docker, docker-ssh, virtualbox, docker+machine, docker-ssh+machine:
docker(Executorはdockerにする)
Please enter the default Docker image (e.g. ruby:2.6):
alpine:latest(デフォルトにしたいDockerイメージを指定する)

確認

以下のコマンドでサービスが起動しているか確認できる。

systemctl status gitlab-runner

GitLabのWebページにrootアカウントでAdmin Areaにアクセスし、Runner一覧で今設定したのが登録されていることを確認する。

CI/CDを試してみる

簡単なPipelineを書いてRunnerを動かしてみる。

リポジトリを作成

GitLabのページからテスト用リポジトリを作成する。下の図では「runner-test」というリポジトリを作成している。

.gitlab-ci.ymlを作成

ブラウザでファイル作成、編集する便利機能があるのでそれを使ってみる。下の図の「New file」をクリックする。


「Select a template type」から「.gitlab-ci.yml」を選択


「Apply a template」から「Bash」を選択


「Commit changes」をクリックして、 .gitlab-ci.yml ファイルをリポジトリに追加する。

Pipelineの実行を確認

左メニューから「CI/CD」をクリックし、先ほどのcommitでパイプラインが実行されていることを確認する。(「Status」が「running」になっている)


しばらく待って「Status」が「passed」になればOK

AzureでCentOS8の仮想マシンを構築する

AzureでCentOS8の仮想マシンを構築する方法

仮想マシンを構築

まずはAzureのポータルにアクセスする。

トップページ左上の三本線をクリック

「Virtual Machines」をクリック

「+追加」をクリック

以下の情報を入力または選択し、「確認および作成」をクリック

  • 仮想マシン名:testVM(なんでもいい)
  • 地域:(Asia Pacific) 東日本
  • イメージ:CentOS-based 8.1
  • サイズ:Standard_B1ls(なんでもいいが検証なので一番安いやつ)
  • 認証の種類:パスワード
  • パスワード、パスワードの確認:任意のパスワード

確認ページが表示されるので問題なければ「作成」をクリック

デプロイが完了するまで待つ

デプロイが完了したら「リソースに移動」をクリック

仮想マシンにSSHログイン

「パブリックIPアドレス」をコピー

何かしらのSSHクライアントでログイン(下の図はPowerShell)

ssh AzureUser@(Public IP address)

ログインできた。

SSHできるIPアドレスを制限

このままだとどこからでもSSHログインできてしまうので、IPアドレスで制限する方法を載せておく。

仮想マシンのページから「ネットワーク」をクリックし、名前が「SSH」の行をクリック

以下の情報を入力し「保存」をクリック

  • ソース:IP Addresses
  • ソースIPアドレス/CIDR範囲:自分が使っているグローバルIPアドレス

リソースを削除

検証用途の場合、リソースを削除することを忘れずに。

仮想マシンを作ると他にもリソースが勝手に作られるのでリソースグループごと消すのが安心。

トップページ左上の三本線をクリックし、「リソースグループ」をクリック

今回作成したリソースグループ(今回は「testVM_group」)をクリック

「リソースグループの削除」をクリック

削除確認があるのでテキストボックスにリソースグループ名を入力して「削除」をクリック

これで今回作成した仮想マシンに関連するリソースがすべて削除される。

HAProxyとKeepalivedを使ってオンプレ環境で冗長構成を実現

検証環境

  • ホストOS: CentOS7.5
  • 仮想環境: Vagrant (VirtualBox)
    • ゲストOS: CentOS7.5
    • haproxy1, haproxy2, app1, app2, postgres
  • HAProxy: 1.5.18
  • Keepalived: v1.3.5
  • PostgreSQL: 9.2.23

要件

第一の要件を可用性、次に運用容易性に設定して、自前のサーバでアプリケーション基盤を実現する方法を考えてみた。

構成イメージ図

前段のロードバランサー(HAProxy)はKeepalivedで冗長化し、LBの可用性を確保。

LBのバックにはアプリケーション本体を2台にデプロイするようにして、片方が落ちてもサービス継続できるようにした。(今時で言うとKubernetesやDocker Swarmなんだけど、運用容易性の観点から単純にアプリのプロセス立ち上げるだけで良いようにした)

その後段にはデータベースを配置。ここの可用性については今回の記事では省略。いつかpgpool的なのを使った場合の記事書きたい。

構成イメージ図

ネットワーク図

構成イメージでは階層構造になっているが、実際には全サーバ同一サブネット(192.168.33.0/24)に繋いで検証した。(すべて同じprivate networkに接続)
性能を求めているわけではないので、今回はこれで手打ち。

ネットワーク図

サーバ設定

データベース(PostgreSQL)

PostgreSQLをインストール

yum -y install postgresql-server
postgresql-setup initdb

/var/lib/pgsql/data/postgresql.confを編集

listen_addresses = '*'
timezone = 'Asia/Tokyo'
log_timezone = 'Asia/Tokyo'

/var/lib/pgsql/data/pg_hba.confを編集

host    all             all             192.168.33.0/24            md5

サービス起動

systemctl start postgresql
systemctl enable postgresql

データベースを作成

# su - postgres
-bash-4.2$ psql -c "CREATE ROLE django WITH LOGIN PASSWORD 'django';"
CREATE ROLE
-bash-4.2$ psql -c "CREATE DATABASE django OWNER django ENCODING 'utf8';"
CREATE DATABASE

アプリケーションサーバ

今回はDjangoで作ったシンプルWebアプリケーションを使う。
まずはDockerとdocker-composeをインストール

yum -y install git docker
systemctl start docker
systemctl enable docker
curl -L https://github.com/docker/compose/releases/download/1.21.2/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose

アプリケーション本体をGitHubから持ってきてデプロイ

git clone https://github.com/tetsis/nginx-gunicorn-django-postgres.git
cd nginx-gunicorn-django-postgres/
docker-compose -f docker-compose-without-postgres.yml up -d
docker exec nginx-gunicorn-django-postgres_django_1 ./init.sh

上記の手順をアプリケーションサーバ2台(app1, app2)両方で実施する

ロードバランサー

HAProxyとKeepalivedをインストール
psmiscはプロセスチェックコマンドkillallのために必要

yum -y install haproxy keepalived psmisc

/etc/haproxy/haproxy.cfgを編集

# デフォルトのfrontend句を以下のように変更
frontend  main *:80
    default_backend             app

# デフォルトのbackend句を以下のように変更
backend app
    balance     roundrobin
    server  app1 192.168.33.103:80 check
    server  app2 192.168.33.104:80 check

/etc/keepalived/keepalived.confを以下のように修正

! Configuration File for keepalived

global_defs {
    router_id LVS_DEVEL
}

vrrp_script chk_haproxy {
    script "/usr/bin/killall -0 haproxy" # check the haproxy process
    interval 2 # every 2 seconds
    weight 2 # add 2 points if OK
}

vrrp_instance VI_1 {
    interface eth1 # interface to monitor
    state MASTER # MASTER on haproxy1, BACKUP on haproxy2
    virtual_router_id 51
    priority 101 # 101 on haproxy1, 100 on haproxy2
    virtual_ipaddress {
        192.168.33.100 # virtual ip address
    }
    track_script {
        chk_haproxy
    }
}

サービス起動

systemctl start haproxy
systemctl enable haproxy
systemctl start keepalived
systemctl enable keepalived

上記の手順をロードバランサーサーバ2台(haproxy1, haproxy2)両方で実施する
※ keepalived.confについては、stateとpriorityはhaproxy1とhaproxy2で設定値が異なる

CentOS7にmod_dumpostをインストールする

POSTメソッドのデータ部分もログ出力してくれるApacheのモジュールmod_dumpost。

テスト環境

OS: CentOS7.4
Apache: 2.4.6

準備

# yum install httpd-devel
# yum install gcc

mod_dumpostインストール

# git clone https://github.com/danghvu/mod_dumpost
# cd mod_dumpost
# make
# make install

Apacheの設定ファイル編集と再起動

/etc/httpd/conf/httpd.conf

LogLevel info
# systemctl restart httpd

確認

下の例はローカルホストから実行しているが他ホストから確認しても同様の結果が得られる。
(その場合はもちろんTCP/80ポートを開放すること)

# curl http://127.0.0.1/test -X POST -d "data1" -d "data2"

/var/log/httpd/error_log

[Tue Jan 09 14:09:02.886789 2018] [:info] [pid 4042] [client 127.0.0.1:34154] "POST /test HTTP/1.1" data1&data2

ちゃんとデータ「data1&data2」がログに出力されている。

SSLの場合

SSL化した場合も同じようにPOSTのデータをログ出力できる。

# yum install mod_ssl

/etc/httpd/conf.d/ssl.conf

LogLevel info
# systemctl restart httpd

確認

# curl --insecure https://127.0.0.1/test -X POST -d "data1" -d "data2"

/var/log/httpd/ssl_error_log

[Tue Jan 09 14:19:00.910862 2018] [:info] [pid 7994] [client 127.0.0.1:55982] "POST /test HTTP/1.1" data1&data2

捕捉

画像アップロード等の大容量データを全部ログに書き出すとログファイルがすぐいっぱいになってしまうので、それを防ぐ設定があるみたい(まだ確かめてないけど)。

/etc/httpd/conf/httpd.conf

DumpPostMaxSize 1024

参考URL

https://www.shadan-kun.com/blog/tool/entry-184.html

https://hacknote.jp/archives/25059/

CentOS7.4でポート開放する

いつまでも覚えられないので備忘録に追加

ゾーンの確認

下のコマンドを実行して「(active)」がついているところが現在有効になっているゾーン
通常は「public」

firewall-cmd --list-all

ポートの追加

8888番TCPポートを開放したい場合の例
zoneオプションには現在有効になっているゾーンを指定する

firewall-cmd --add-port=8888/tcp --zone=public --permanent

設定の反映

忘れずに

firewall-cmd --reload

CentOS7.4にVirtualBoxとVagrantをインストール

執筆時のバージョン

  • CentOS 7.4
  • VirtualBox 5.2.4
  • Vagrant 2.0.1

VirtualBoxをインストール

依存関係の問題でlibSDLが必要
このサイトからCentOS7.4用libSDLのrpmをダウンロードしてインストール

# rpm -ivh SDL-1.2.15-14.el7.x86_64.rpm

公式サイトからCentOS7用のrpmをダウンロードしてインストール

# rpm -ivh VirtualBox-5.2-5.2.4_119785_el7-1.x86_64.rpm

Vagrantをインストール

公式サイトからCentOS(64bit)のrpmをダウンロードしてインストール

# rpm -ivh vagrant_2.0.1_x86_64.rpm

以下のコマンドを入力して不足しているパッケージがあればインストール

# /sbin/vboxconfig

私の環境では以下のパッケージを追加インストール
インストール後に再度セットアップする

# yum install gcc kernel-devel
# /sbin/vboxconfig

VagrantにCentOS7のイメージをダウンロード

参考サイト

$ vagrant box add centos/7
==> box: Loading metadata for box 'centos/7'
box: URL: https://vagrantcloud.com/centos/7
This box can work with multiple providers! The providers that it
can work with are listed below. Please review the list and choose
the provider you will be working with.

1) hyperv
2) libvirt
3) virtualbox
4) vmware_desktop

Enter your choice: 3
==> box: Adding box ‘centos/7’ (v1710.01) for provider: virtualbox
box: Downloading: https://vagrantcloud.com/centos/boxes/7/versions/1710.01/providers/virtualbox.box
==> box: Successfully added box ‘centos/7’ (v1710.01) for ‘virtualbox’!

CentOS7をインストールした時にすること(GNOME Desktop)

HP EliteBook 1030 G1 に CentOS7.4 をインストールしたときに設定した内容です。

トラックパッドのタップでクリック

「設定」>「Mouse & Touchpad」>「タップでクリックする」をオン

Caps LockキーをCtrlキーにする

「Tweak Tool」>「タイピング」>「Ctrlキーの位置」>「Caps LockをCtrlとして扱う」をチェック

全角/半角切り替えを変換/無変換キーに割り当て(Mac風)

「設定」>「Region & Language」>「日本語(かな漢字)」>「設定」(歯車アイコン)

「ショートカット」>「ひらがな」>「元の候補」を変更
(直接入力モード変更に使いた無変換キーがここで使われているため別のキーを割り当てる)

「ショートカット」>「ひらがな」>「直接入力モードに変更」に無変換キーを割り当て

「ショーカット」>「直接入力」>「ひらがな入力モードに変更」に変換キーを割り当て

端末の起動をショートカット追加

「設定」>「Keyoard」>「+」

  • 名前:端末を開く
  • Command:gnome-terminal
  • Shortcut:Ctrl + Alt + T

Firefoxの起動をショートカット追加

「設定」>「Keyoard」>「+」

  • 名前:Firefoxを開く
  • Command:firefox
  • Shortcut:Ctrl + Alt + F

Let’s EncryptでWebサイトSSL化に挑戦したら簡単過ぎた(ConoHa, CentOS7)

昨今の時代の流れに乗ってサイトのSSL化をやってみた。以前別のサービスを使ってSSL化していたことがあったけど、そのためにはSSL化するドメインのメールサーバを立ててないといけなくて、メールのやりとりとかも必要で正直メンドくさかった(しかも英語で)。

↑の経験からSSL化っていろいろ面倒なんだろうなーとか思ってたけど、Let’s Encryptで挑戦してみたら一瞬にできてしまった。すごい。

必要なWebサーバ環境

メールサーバとかは立てなくて大丈夫。でも一応最低限必要な環境を用意しないといけないので念のため記載。

  • ドメイン名(DNS名)でアクセスできるサーバであること
  • http(80番ポート/tcp)、https(443番ポート/tcp)でアクセスできること

また、今回はApacheが動いている状態で実行。他のWebサーバ(Nginxとか)が動いている場合も同じコマンドでいけるみたい。
Webサーバが動いていないサーバでもオプション追加でOK。詳しくは参考サイトを参照。

インストール

# yum install epel-release
# yum install certbot

証明書取得

-wオプションはドキュメントルートディレクトリ、-dはドメイン(FQDN)

[root@www ~]# certbot certonly --webroot -w /var/www/html -d www.tetsis.com
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator webroot, Installer None
Enter email address (used for urgent renewal and security notices) (Enter 'c' to
cancel): (連絡がとれるメールアドレス)
Starting new HTTPS connection (1): acme-v01.api.letsencrypt.org

-------------------------------------------------------------------------------
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.1.1-August-1-2016.pdf. You must agree
in order to register with the ACME server at
https://acme-v01.api.letsencrypt.org/directory
-------------------------------------------------------------------------------
(A)gree/(C)ancel: A

-------------------------------------------------------------------------------
Would you be willing to share your email address with the Electronic Frontier
Foundation, a founding partner of the Let's Encrypt project and the non-profit
organization that develops Certbot? We'd like to send you email about EFF and
our work to encrypt the web, protect its users and defend digital rights.
-------------------------------------------------------------------------------
(Y)es/(N)o: Y
Starting new HTTPS connection (1): supporters.eff.org
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for www.tetsis.com
Using the webroot path /var/www/html for all unmatched domains.
Waiting for verification...
Cleaning up challenges

IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/www.tetsis.com/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/www.tetsis.com/privkey.pem
Your cert will expire on 2018-01-27. To obtain a new or tweaked
version of this certificate in the future, simply run certbot
again. To non-interactively renew *all* of your certificates, run
"certbot renew"
- Your account credentials have been saved in your Certbot
configuration directory at /etc/letsencrypt. You should make a
secure backup of this folder now. This configuration directory will
also contain certificates and private keys obtained by Certbot so
making regular backups of this folder is ideal.
- If you like Certbot, please consider supporting our work by:

Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
Donating to EFF:                    https://eff.org/donate-le

Apacheに証明書を設定

# vim /etc/httpd/conf.d/ssl.conf

SSLCertificateFile /etc/letsencrypt/live/www.tetsis.com/fullchain.pem

SSLCertificateKeyFile /etc/letsencrypt/live/www.tetsis.com/privkey.pem

# systemctl restart httpd

これで完了。いい時代になりました。

参考

https://letsencrypt.jp/usage/

オレオレ認証局のクライアント証明書失効方法

前回の投稿の続き

発行したクライアント証明書を使えないようにさせたくなったときの方法

クライアント証明書の無効化

# cd /etc/pki/tetsis-client
# openssl ca -config openssl.cnf -gencrl -revoke tetsis.cert.pem

失効リストの更新

# cd /etc/pki/tetsisCA
# openssl ca -config openssl.cnf -gencrl -out crl.pem

失効リストの確認

# openssl crl -in crl.pem -text

参考

http://www.nina.jp/server/slackware/openssl/openssl-command.html#revoke

オレオレ認証局でクライアント証明書をつくる(CentOS7)

前回の投稿の続き

新規ディレクトリ作成

# cd /etc/pki
# mkdir tetsis-client
# cp tetsisCA/openssl.cnf tetsis-client/

openssl設定ファイル編集

/etc/pki/tetsis-client/openssl.cnf を編集

(以下を追加)
[ client_cert ]
basicConstraints=CA:FALSE
keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer

Apacheの設定

/etc/httpd/conf.d/ssl.conf を編集

# SSLCACertificateFileかSSLCARevocationFileの下あたりに以下を追加
<Directory />
SSLRequireSSL
SSLVerifyClient require
SSLUserName SSL_CLIENT_S_DN_CN
Satisfy Any
Allow from All
SSLRequire %{SSL_CLIENT_S_DN_CN} in {"tetsis"} # 認証ユーザ。複数のユーザを設定するにはカンマ区切りで書く。
</Directory>

Apacheの再起動

# systemctl restart httpd

クライアント証明書の作成

# cd /etc/pki/tetsis-client
# openssl req -config openssl.cnf -new -days 3650 -keyout tetsis.key.pem -out tetsis.req.pem -days 3650 -extensions client_cert
Generating a 2048 bit RSA private key

writing new private key to 'tetsis.key.pem'
Enter PEM pass phrase:  # 秘密鍵のパスフレーズ入力
Verifying - Enter PEM pass phrase:  # 秘密鍵のパスフレーズ入力

Country Name (2 letter code) [JP]:
State or Province Name (full name) [Tokyo]:
Locality Name (eg, city) [Shinagawa-ku]:
Organization Name (eg, company) [tetsis company]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:tetsis  # 認証するユーザ名
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

秘密鍵のパスフレーズ削除

# openssl rsa -in tetsis.key.pem -out tetsis.key.pem
Enter pass phrase for tetsis.key.pem:
writing RSA key

CSRにCA秘密鍵で署名

# openssl ca -config openssl.cnf -days 3650 -policy policy_anything -out tetsis.cert.pem -extensions client_cert -infiles tetsis.req.pem
Using configuration from openssl.cnf
Enter pass phrase for /etc/pki/tetsisCA/private/cakey.pem:  # パスフレーズ入力
Check that the request matches the signature
Signature ok

Certificate is to be certified until Oct  8 08:37:09 2028 GMT (3650 days)
Sign the certificate? [y/n]:y

1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
  • 秘密鍵: tetsis.key.pem
  • CSR(署名リクエスト): tetsis.req.pem
  • クライアント証明書: tetsis.cert.pem

ブラウザにインポートするp12ファイル作成

# openssl pkcs12 -export -in tetsis.cert.pem -inkey tetsis.key.pem -certfile /etc/pki/tetsisCA/cacert.pem -out tetsis.p12
Enter Export Password:  # パスフレーズ入力(ユーザがアクセスする際に必要になる)
Verifying - Enter Export Password:  # パスフレーズ入力(ユーザがアクセスする際に必要になる)

ブラウザにクライアント証明書(tetsis.p12)をインポート

(20171027追記)クライアント証明書をインポートする場合は、CA証明書も自動的にインポートされる。この場合でも「信頼の設定」が必要なため、CA証明書の方もチェックを忘れないように。

  • 現時点でページにアクセスするとエラーになる
  • 「設定」→「証明書の管理」→「ユーザの証明書」タブを選択し、「インポート」をクリック
  • 作成したp12ファイルを選択し、パスワードを入力
  • 追加したクライアント証明書が表示される
  • 再度ページにアクセスすると「証明書の選択」ウィンドウが表示されるため、「OK」をクリック
  • ページが表示される。成功

参考サイト