Posted at

gitlab-ciとansibleでgolangのデプロイ環境を作る

More than 1 year has passed since last update.

この記事は 富士通クラウドテクノロジーズ Advent Calendar 2017の17日目の記事です。

16日目は@clutterさんの「OK, Google. サーバーをスペックアップして」でした。

最近はやりの音声アシスタントをサーバのスペックアップに使うという発想面白くていいですね。

今回私はgitlab-ciとansibleでgolangのデプロイ環境を整えるお話をしたいと思います。


gitlab-ciとは


  • gitlab バージョン8以降にデフォルトで付いているCIツールです。

  • 特別な設定が不要で、リポジトリに.gitlab-ci.ymlを追加するだけで利用できます。


デプロイ環境の概要


  • gitlabにpushするとgitlab runnerが動き出します。

  • gitlab runnerがデプロイのため以下の動作をするように.gitlab-ciを作成します。


    1. ソースをビルドしgitlab上に保存

    2. ビルドでできたバイナリをvmへ転送

    3. AnsibleでVMにinit.dでサービス登録




ディレクトリ構成

gitlab.com/UminoShohei05/go-gitlabci

├── .gitlab-ci.yml
├── ansible
│ ├── inventories
│ └── roles
└── server/



  • .gitlab-ciはビルドからAnsibleの実行まで行うジョブが定義されています。


  • ansibleにはgoのバイナリをserviceとして登録するplay-bookが入っています。


  • serverにはHelloWorld!を返すだけのgo+echoでできたAPIが入っています。

  • OSはCentos6.7で試しています。


やってみる


まずはビルドジョブの作成

build_jobではserver/にあるソースをビルドし、できたバイナリをgitlab上に保存します。

ビルドジョブは以下のようになります。


.gitlab-ci.yml

build_job:

image: golang:1.8
stage: build
script:
- mkdir -p $GOPATH/src/gitlab.com/UminoShohei05/go-gitlabci/server
- mv $CI_PROJECT_DIR/server/* $GOPATH/src/gitlab.com/UminoShohei05/go-gitlabci/server
- cd $GOPATH/src/gitlab.com/UminoShohei05/go-gitlabci/server/
- go get -u github.com/golang/dep/cmd/dep
- dep ensure
- go build -o test-api
- cp test-api $CI_PROJECT_DIR
artifacts:
paths:
- test-api

ジョブの内容を解説していきます。


image

使いたいdockerイメージを指定します。


script

実行したい命令を記述していきます。

今回はビルドするため一度GOPATHに移動し、ビルドでできた成果物をartifactsで使うために$CI_PROJECT_DIRにコピーしています。

$CI_PROJECT_DIRは、CI実行時にリポジトリがクローンされるディレクトリを表しています。

これはPredefined variablesというCI上で使うために元から定義されている変数で、詳細はこちらで確認することができます。


artifacts

ジョブの中で作成した成果物などをpathで指定してgitlab上に保存できます。

pathは$CI_PROJECT_DIRからの相対パスとなっています。

今回artifactsではpathのみ指定していますが、成果物の名前を変更したり、保存期間を指定することもできます。(何も指定しないと無限に残り続けます)

保存されたartifactsは画像のようにgitlab上からzip形式でダウンロードすることもできます。

Repository

CI/CD -> Pipeline


デプロイジョブの作成

deploy_jobではbuild_jobでできたバイナリのサーバへの転送と、Ansibleを使いバイナリをinit.dでサーバにサービス登録します。

デプロイジョブは以下のようになります。


.gitlab-ci.yml

deploy_job:

image: webdevops/ansible
stage: deploy
before_script:
- 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client git -y )'
- eval $(ssh-agent -s)
- echo "$SSH_KEY" | tr -d '\r' | ssh-add - > /dev/null
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
- ssh-keyscan $SERVER_IP >> ~/.ssh/known_hosts
- chmod 644 ~/.ssh/known_hosts
script:
- scp test-api root@$SERVER_IP:/opt/api/bin/release
- cd ansible
- ansible-playbook -i inventories/production.yaml deploy-api.yaml


before script

scriptを実行する前の準備を記述していきます。

今回のデプロイジョブではscpやAnsibleでSSH keyを使うためssh-agentへの鍵の登録を行い、known_hostsへホストの登録をしています。

また、SSH keyはリポジトリに入れることが憚られるため、gitlabのSecret variablesという機能を使い参照できるようにしています。

画像のようにgitlab上でKeyとValueを入れ登録すると、CI上で$Keyで参照することができます。

APIのアクセスキーやシークレットキーの登録などもこちらで行うと安全に使えます。


script

scpコマンドを見てもらうとわかるように、前のジョブでartifactsに保存したtest-apiをそのまま使っています。このように前のジョブの成果物を引き継ぎたい時にartifactsは便利です。

デプロイのジョブは最後にserviceにtest-apiを登録するansibleを流して終了です。

Ansibleの内容については今回使ったリポジトリを貼っておくので、こちらで確認をしてみてください。


動作確認

ちゃんとデプロイされているか一応動作確認をしてみます。


さいごに

今回はデプロイをするだけの簡単なgitlab-ciですが、実際に仕事で使うにはbuildの前にlintやtestを追加するとより良いと思います。

また、今回は最低限の機能しか使っていませんが、指定されたブランチのpush時のみジョブを指定するonlyやジョブの障害時や失敗した場合に実行されるジョブを定義するwhenなど様々な機能があります。

一方で、gitlab-ciはpassphraseのついたssh keyが使えなかったり、パラメータを取るようなジョブの場合は向いていなかったりもします。

個人的にはgitlab-ciの機能面だけでなく、設定いらずで管理するツールも増えない部分にメリットを感じているので、gitlab-ciをこれからもっと使っていきたいなと思います。

あしたは@cooの「ニフクラの物理ネットワークを支える人たち」です。宜しくお願いします!