今日は、CI(Continuous Integrations:継続的インテグレーション)、CD(Continuous Delivery:継続的デリバリー)の話をしようと思います。
タスクランナー Envoy
最近、人気のフレームワークであるLaravelで提供されている、Envoyというタスクランナーツールがあります。
これを使用すると、ダウンタイムゼロでの自動デプロイメントができるようになります。
導入は至って簡単で、以下のコマンドでインストールできます。
※ 要composer環境
composer global require laravel/envoy
Envoyは、Laravelを使用していないシステムでも、単独で使用することができます。
非常に優秀なEnvoyですが、PHP7以上の環境でしか使用することができません。
新しく開発するサービスなどの場合は全く問題ありませんが、既存サービスなどの場合は、レガシーなPHPバージョンを使用しているというケースも多いのではないでしょうか。
レガシー環境の大規模リファクタリング
レガシーなPHP環境のシステムを、ある程度の範囲でリファクタリングを行った際の話ですが、諸事情により、システムをスクラッチから再度開発することができず、部分的に開発し直すというケースも結構多いのではないかと思います。
レガシーな開発フロー
今までは、開発サーバーと本番サーバーがあり、以下のようなステップでリリース作業を行なっていました。
開発フローも、レガシーな状態でした。
- 開発サーバーで開発
- 更新ファイルをローカルにダウンロード
- 手作業で本番のファイルを差分を確認し、マージ
- 本番サーバーへ更新ファイル群をアップロード
ただし、このステップでは、リファクタリングなど改修範囲が大きくなった際に、以下のような問題点があります。
- アップロードするファイルが足りていないなど、リリースの際にミスが発生する可能性が非常に高い。
- 複数人での作業が困難。
- 既存システムへの機能追加などが発生した場合、対処できない。
- ファイルを順次アップロードしていくことになるので、少なからずダウンタイムや挙動がおかしくなる時間が発生する。
また、今回はリファクタリングの一環として、今までPHPファイルにフロントエンドの記述が一緒にされていたものを、Model(モデル)、View(ビュー)、Controller(コントローラー)に基づいた設計に変更したこともあり、大量ファイルの追加・削除・変更が発生しました。
これを手作業でリリースをするのは非現実的、という状況でした。
理想的な開発フロー
そこで、前述のEnvoyを使用して、以下のフローを確立させたいと考えました。
- ローカルのDocker環境で開発
- Gitlabのdevelopブランチへプッシュ
- 開発サーバーへ自動デプロイ
- 開発サーバーで確認
- 問題がなければ、masterブランチへマージリクエスト
- masterブランチでマージ
- 手動でデプロイタスクを実行(ボタンクリック)
ここで問題になるのが、レガシーなPHPのバージョンでした。
使用したEnvoyは、PHP7以上でないと使用できない。。。
ちょっとどうしようかと途方に暮れた感もあったのですが、Envoyを実行するのは、開発しているシステム側ではなく、あくまでGitlabランナー側です。
なので、Gitlabランナーで稼働させるDocker環境をPHP7にすれば、問題なくEnvoyを使用することができます。
もちろん、レガシーなPHP用にPHPUnitなどでテストを実行させている場合は難しいかもしれませんが、幸い必要だったのは、デプロイだけだったので、GitlabランナーのDockerにPHP7.1のイメージを読み込んで、無事にEnvoyタスクを実行し、ダウンタイムゼロでのデプロイフローを確立させることができました。
ダウンタイムゼロのデプロイメント
実際にEnvoyでどのようなタスクを実行しているかと言うと、、、
- 新規リリース用にディレクトリ作成
- 新規リリースディレクトリでgit clone
- composer installなどアプリケーション構築に必要な初期コマンドなど、もろもろ実行
- アプリケーションのカレントバージョンへのシンボリックリンクを新規リリースへ変更
このように簡単なステップにはなっていますが、
事前にドキュメントルートなどの設定を変更しておく必要があるので、注意してください。
Gitlab、Envoyを使用したデプロイフローの構築に関しては、
以下のGitlab側のドキュメントで詳しく紹介されていますので、参考にしてください。
Test and deploy Laravel applications with GitLab CI/CD and Envoy