読者です 読者をやめる 読者になる 読者になる

ITの隊長のブログ

ITの隊長のブログです。いや、まだ隊長と呼べるほどには至っていないけど、日々がんばります。CakePHPとPlayFrameworkを使って仕事しています。最近はAngular2をさわりはじめたお(^ω^ = ^ω^)

GM◯ iClusta and Jenkinsという最悪のコンビネーションで自動デプロイのやり方メモ

Jenkins GMO iCLUSTA GitLab PHP ShellScript Shell

スポンサードリンク

カオスだったお(^ω^

でもそんなに難しいことじゃないので、一応読めばできると思う。だけど逃げ出したくなるめんどくささ。

普通のエンジニアにはAWSをポチってJenkinsにリモートでシェルを叩いてもらいましょう。それでもこのカオスな環境を作りたい人はメモを読んでね。

やりたいこと

GM◯ iClustaのサーバにJenkinsを使ってCakePHPを自動デプロイしたい

f:id:aipacommander:20151208204621p:plain

構成

社内環境

  • gitlab
  • jenkins

本番サーバ

  • GM◯ iClusta

  • 本番のディレクトリ

/root_dir/document_root/workspace/script/      # script格納用ディレクトリ
/root_dir/document_root/workspace/tmp_release/ # リリース前のコピー元ディレクトリ
/root_dir/document_root/production/            # 本番ディレクトリ

今回のデプロイ先の通信はFTPオンリーのため、Jenkinsの「リモートでシェルを実行」が使えない。ただ、sshが使えないだけで、サーバはLinuxサーバなので、内部でのshellは実行することができる。なのでちょっとだけ工夫する必要がある。

今回はShellはPHPから実行するようにした。また、外部から実行する必要があるためscript格納用ディレクトリはDocumentRootの中に配置してあげないといけない。ただ、セキュリティ上問題だろうなと思うので、処理が終了したらscriptディレクトリごと削除するような処理を書いたほうがいいかも。

gitlab -> jenkinsの連携

リリース用のリポジトリ作成

gitlabで新規リポジトリを作成すればおkです。手順は割愛。

jenkinsでデプロイのjob作成

3つ作成しました。

  • switch-trigger ・・・ 特定のブランチにpushされた時に、デプロイのjobを叩く
  • upload ・・・ gitリポジトリからリリース用のブランチを取得して、サーバへアップロード
  • exec-deploy ・・・ アップロードされたデータを本番ディレクトリへデプロイするためのコマンドを実行するShellを叩くjob(長い)

上から順にjobをつなげてリリースしようと思います。

必要なplugin

  • build pipeline ・・・ 他jobがビルドされたら自分のjobを叩くみたいなことができる
  • GIT plugin ・・・ Gitを使うために必要
  • Publish Over FTP ・・・ サーバへのアップロードはFTPのみなので、これで対応しました(´・ω・`)
  • Fiexible publish ・・・ ビルド後に条件を用意して通ったら別jobを叩くみたいなことができます。

設定の詳細

switch-trigger

こいつの役割は上に書いたとおりですが、もう少し詳しく書くと、gitlabのhookでこのjobを叩く用に設定します。pushでhookしてあげてください。

で、そのpushのhookはどのブランチがpushされてもこのjobが叩かれる用になります。これはちょっと面倒です。だってリリースしたいブランチが更新されたときだけデプロイしたいから。

なので、このjobでリリースのブランチがpushされたかどうかを確認しないといけません。

  • リリースしたいブランチがpushされた => upload jobを叩く
  • リリースしたいブランチ以外のブランチがpushされた => 何もしない

ってな感じです。

それでは設定のお話。

switch-triggerの設定から下記設定を行います。

ソースコード管理

知っている人は多いと思いますので詳しくは割愛です。gitlabのurlを登録して上げましょう。

1点だけ。あとから「ビルド後の処理」でリリースしたいブランチがpushされたかチェックするって処理を書きますが、それを対応するためにはすべてのブランチを落としてこないといけないっぽいです。

ちゃんと検証したわけじゃないので、これが正解かわかりませんが、とりあえずBranches to build -> Branch Specifier (blank for 'any') **で登録してください。

ビルド後の処理

ここで、Fiexible publishを選択し、Run?の項目をExecute Shellで下記ソースコードを実行するようにします。

#!/bin/sh

PUSHED_BRANCH=`git branch -r --contains ${GIT_COMMIT}`

# *master* の箇所を任意に変更
# リリースしたいブランチ名をここに記載します
if [[ ${PUSHED_BRANCH} == *master* ]]; then
  exit 0
fi

exit 1

んで、Actionのほうは他のプロジェクトをビルドを選択して、uploadのjobを選択してあげましょう。

これでおk

ここまでの参考

qiita.com

qiita.com

upload

こっちもswitch-triggerと同様、gitの設定を行います。違うのはリリース対象のだけのブランチ名を指定してあげること。

んで、ビルド後の処理Publish Over FTPの設定を登録してください。

これでアップロードのjobの用意はおk。

exec-deploy

3つ目はアプリケーションアップロード後、シェルを叩くためのjobになります。

エンジニアの皆さんは通常はリモートでシェルを叩けばいいと思いますが、私は強制縛りプレイなのでシェルを叩くPHPをサーバへ配置してそいつをアクセスするシェルを叩くようにします。

その前に、build pipelineuploadのjobが終了したらexec-deployのjobを実行するようにします。

ビルド・トリガ

ここから他プロジェクトの後にビルドにチェックをいれて対象プロジェクトuploadで登録します。これでuploadのjobが安全に終了したらexec-deployのjobが起動するようになります。

ビルド

ここで目的のPHPを叩くシェルを登録します。

シェルの実行を選択して、下記コマンドを登録。

curl -s 'http://hogehoge.com/script/shell_exec.php'

これでおk

ここまでがJenkinsの設定になります。

テストしてみた。

試しにexec-deploy以外を叩きテストしてみたところ「response 421 received」(°ω°

ファイル数が多い -> アップロード時間が長くなる -> 切られる

・・・

さすが安定のGM◯ですね!

ということで、今回デプロイ対象のアプリケーションはCakePHPだったので、/lib/ディレクトリは初回のアップだけにして、次回から変更するまではアップしないでおこうと思います。/app/だけアップします。

scriptの話

叩くシェルスクリプトはいくつか用意しました。下記が(大雑把な)内容になります。

  • shell_exec.php 下2つのシェルを叩くphpファイル
  • release.sh バックアップ取得 => アップロードしたディレクトリから本番のディレクトリにrsyncを実行します
  • reset.sh 下記に参考URLがありますが、あれを全くコピペしたファイルです

詳しくはまたいつかあげようかなと思います。(今内部情報がいっぱい記載されているのでリファクタが必要なので)

参考

qiita.com

これからやること

とりあえずここまでできれば、アップロードの作業は自動化することができます。ただ、これじゃまだまだなところが何個かあります。

今後対応完了したら追記していこうかなと思います。

テスト

リリース前にテストが組み込めていません。が、どちらかといえば、リリース用のブランチにマージする前に行うことだと思いますのでこれはまた別のフェーズな気がします。

DB Migration

これがいまいち理解できていなくて頭を悩ましています。

一応マイグレーションファイルを作成するなどのチュートリアルは一通り理解していますが・・・

  1. リリースで動作しているデータはどうなるの?
  2. DBの構造を大きく変えた場合、前のバージョンデータをどう移行するのか?

などなどがうまく理解出来ていません。個人的な考えとしては、本番のデータを一旦開発環境に落としそれを組み替えてから本番に適応する。ってのが一番現実的ななのかな。って思いました。

が、リアルタイムでリリースしたいのに結局準備しないといけないってのはどうなの? ひとつのサーバで運用するからダメなのかね? やっぱりまだよくわからん(´・ω・`)

ロールバックについて

これはテストをしっかり行えばそもそも行わなくて良いフェーズだと思いますが、万が一なにか発生した場合も考慮しないといけないのかなと思います。

一応今回作ったスクリプトではrsync前に、前のアプリケーションファイルを指定のディレクトリにバックアップ。んでsql dumpを行う。って流れにしています。

もし戻したい場合は別jobとscriptの用意が必要かな。

雑な感想

工数にして約6h...かかり過ぎやで。

でも前向きな考えで。これから手動で行ってた作業が自動化されるのでいいかなと思う。元は余裕でとれるはず。

しかし、そもそもサーバが遅いのがアレなので、VPSとかクラウドサービスにしてほしいなと本気で感じた1日でもありました。

だって、アップロードの処理をこんな分割せずとも、jenkinsのLinuxホストから本番にrsyncで一発だもんね。泣きたい。

早く会社のサーバがAWSとかGCPとかになりますよーに。