Technical Articles
SAP CPで開発したアプリをJenkinsでDevOps
第2回 東京公共交通オープンデータチャレンジに応募した「まよワン!じっこくん」の連載記事の第6回です。
- 東京公共交通オープンデータチャレンジに応募してみた
- 「まよワン!じっこくん」とは?(アプリケーション説明とアーキテクチャ概要)
- デザインシンキングでアプリ要件を考えてみる(デザインシンキング)
- チャットボットの開発(SAP Conversational AI)
- SAP CP上でのバックエンド開発(Node.jsとSAP HANA)
- SAP CPで開発したアプリをJenkinsでDevOps ←今回はコチラ
今回はDevOpsの記事ということで「まよワン!じっこくん」を開発するにあたって使用したJenkinsの話を中心にしていきます。
「まよワン!じっこくん」は大きく分けて
- SAP Conversational AI
- Nodeアプリケーション
- SAP HANA
というコンポーネントで構成されていますが、今回のプロジェクトでJenkinsを使用したデプロイ管理の対象はNodeアプリケーションとSAP HANAになります。全体のアーキテクチャ図の中の赤枠の部分が該当コンポーネントです。
目的
今回Cloud Foundryを使用したNodeアプリケーション開発は以下のような点を考慮する必要がありました。
- Nodeの開発者は基本的に開発経験の少ないメンバーをアサインし、社内技術スタックの裾野を広げたいという思惑
- 開発期間が2ヶ月弱と非常にタイト
- ボランティアベースの開発
- リリース後のパッチ方針などは特に考慮しなくて良い
上記特徴を鑑みた上で品質を高めるための施策を講じる際、最初はテストフレームワークの選定などを行っていたのですが、上記理由より早々に自動テストは諦め、メンバーの経験不足をマンパワーで補い品質を担保する方針を取ることに決めました。
また、リポジトリ管理者やビルド担当者のようなアプリケーション開発に通じた専任担当者を置くことも出来なかったため、極めて単純なデプロイ方針を取る必要がありました。
そこで最終的に採った施策は、
- ソースリポジトリは単純にMasterブランチのみとする
- セントラルビルドを行うことにより開発者はGitHubのorigin/masterにPushするだけで変更点が反映される
- GitHubのプロジェクトでIssue管理を行い、誰でも現在どのようなIssueが、どのようなステータスであるか確認できる
- Issueにコミットコメントを紐づけることにより現行ビルドがどのIssueに対応したものか開発者以外のメンバーもひと目で把握できる
- GitHubのIssue内容/ステータスをSlackのChannelと連携させることで、GitHubにアクセスしなくてもIssueのトラックを可能とする
- ビルド結果を開発で使用していたSlackのChannelと連携させることで、関係者全員が対応Issueに紐付いた機能の実機テストをデプロイ後即座に行うことを可能とする
といった運用を徹底することで、結果これら施策により開発に負荷をかけず、且つ品質を高めるといった当初の目標を達成することができました。
本Blogはこのうち、
- セントラルビルドを行うことにより開発者はGitHubのorigin/masterにPushするだけで変更点が反映される
- ビルド結果を開発で使用していたSlackのChannelと連携させることで、関係者全員が対応Issueに紐付いた機能の実機テストをデプロイ後即座に行うことを可能とする
についての実現方法を技術的な観点で説明します。
じっこくんDevOpsのアーキテクチャ
当初Jenkinsを運用する上でオンプレミスの運用を考えましたが、どうせならと最終的にCloud Foundry上にJenkinsのDockerイメージをpushして運用することにしました。SAPのCloud Foundryはdiego_dockerフィーチャーフラグがデフォルトでenableになっているのでDockerイメージをそのままpushすることが可能なのです。全体図は以下の通りになります。
社内LAN内にあるGitHub EnterpriseをJenkinsから呼び出す場合、Cloud Connectorを使用するなどネットワーク的な考慮ポイントが出てきてしまうため上図のGitHubはPublicなものになります。
ちなみにCloud Foundry上のLinux DockerイメージからCloud Connector経由でLAN内に入っていくシナリオはFeasiblity含めて検証していません。また、Jenkinsを再起動するとCloud Foundry上のDocker Imageは初期化されます。そのためJenkinsのWebコンソールで設定した内容を永続化したい場合は、$JENKINS_HOMEを物理DirectoryにBindする必要が出てきます。こちらはSAP Cloud Foundryのサービスfs-strageを使用すべきなのですが、こちらに関しても上記全体図に記述はありますが、Jenkinsの再起動の必要性は特に感じず今回は設定を見送っています。
mtarとDockerfile
SAP Cloud Foundryで開発する場合Multi-Target Application(以下mtarとする)というアプリケーションアーキテクチャが推奨されています。mtarアプリケーションは最終的にmtar Archiveという特殊なArchiveに固められ、そのArchive内にUAAがBindされているアプリケーションルーターや、ビジネスロジックが実装されているJavaやNodeのアプリケーションプロジェクト、HANAのアーティファクトなどアプリケーション構成部品すべてが含まれます。つまり開発環境へのBuild/DeployはmtarをArhiveし、最終的にCloud FoundryにPushする必要があります。そのためJenkinsを使用してセントラルビルドを行う場合、JenkinsがInstallされているLinux DockerイメージにmtarでArhive/push可能な各種設定が行われていなければいけません。
具体的には以下の設定がLinuxに必要になります。
- npmのインストール
- npmのレジストリサーバーにSAP提供のhttps://npm.sap.comを追加する
- Cloud FoundryのCliをインストールする
- cfコマンドでmtarのdeployを可能にするmtar CF Cliプラグインをインストールする
- mtarアーカイブを作成するためJava製のmtar Archive Builderを用意する
当然これらに加え、例えばapt-getを使用できる状態にしたり、Java SDKのインストールなど事前作業が必須になります。これらを満たすDockerfileは例えば以下のようになります。
FROM node
FROM jenkins:latest
#node関連設定
USER root
COPY --from=0 /usr/local /usr/local
RUN npm --version
RUN npm -g config set @sap:registry https://npm.sap.com
#cli install前処理
RUN apt-get update
RUN apt-get install apt-transport-https
#cli install
RUN wget -q -O - https://packages.cloudfoundry.org/debian/cli.cloudfoundry.org.key | apt-key add -
RUN echo "deb https://packages.cloudfoundry.org/debian stable main" | tee /etc/apt/sources.list.d/cloudfoundry-cli.list
RUN apt-get update
RUN apt-get install cf-cli
#mtar cf plug-in
RUN mkdir /mtartool
USER jenkins
COPY --chown=jenkins ./cf-cli-mta-plugin.bin /mtartool
RUN cf install-plugin /mtartool/cf-cli-mta-plugin.bin -f
#mtar jarの設定
COPY --chown=jenkins ./mta_archive_builder-1.1.7.jar /mtartool
RUN chmod 700 /mtartool/mta_archive_builder-1.1.7.jar
このDockerfileのベースはnodeオフィシャルイメージにjenkinsオフィシャルイメージを重ねたものです。イメージを作成する際にパッケージマネージャで取得することの出来ないmtar CF Cliプラグインとmtar Archive Builderは事前に用意しImageと同階層に配置して下さい。配置したファイルはLinuxイメージの/mtartoolに格納されBuild時、及びでDeploy時に使用されます。
ちなみに上記ファイルは両ファイルとも以下サイトから入手可能です。
https://tools.hana.ondemand.com/#cloud
適宜最新Versionのファイルを入手し、dockerfile内のVersion情報を変更して使用して下さい。
Imageの作成とcf push
Cloud Foundryにpush可能なのはあくまでDockerイメージです。Cloud Foundryはコンテナを実行する機能しかありません。dockerfileをpushし、イメージがCloud Foundry上でビルドされることはないので注意して下さい。そのためまずは上記Dockerファイルをローカルでビルドしイメージを作成して下さい。またDockerイメージをpushする際には、DockerイメージがDocker Repositoryに登録されている必要があります。デフォルトではDocker hubを見に行くので、作成したDockerイメージをDocker hubに登録して下さい。
Docker imageをpushする際には以下パラメータを指定します。
APP-NAME: アプリケーション名
REPO: Docker repository名
IMAGE: イメージ名
TAG: Dockerイメージのタグ(latest指定の場合は不要です)
また、Jenkinsの使用メモリーは非常に大きいので最低でも4GBほどHeapを確保して下さい。
Jenkinsの設定
無事Dockerイメージのpushが成功したら、JenkinsのWeb Consoleを開きます。Web Consoleはルートコンテキストに何も指定しない形のURLになります。初回Web Consoleアクセス時はAdministratorパスワードを要求されます。AdministratorパスワードはJenkins初回起動時の標準エラーに出力されるので、SAP CPのApplicationログより取得して下さい。無事ログオン出来たらまずはSlack連携の設定です。まずは以下プラグインをインストールします。
- Global Slack Notifier
プラグインのインストールが終了したら、SlackにてTeam Sub domainとターゲットとなるChannelのIntegration Tokenを取得します。これらをJenkinsの以下システム設定にそれぞれCopy & Pastして下さい。
- Global Slack Notifier > Global Slack Notifier Settings
・Team subdomain
・Integration Token
これでSlack連携の設定は完了です。続いての作業はジョブを実際作成し、各種設定を行います。
まずは、新規ジョブ作成リンクよりジョブを作成しソースコード管理にGitHubのURLを指定します。今回はmasterがデプロイターゲットブランチです。
この設定でJenkinsがセントラルリポジトリよりソースコードを取得するようになります。後はセントラルビルドを行うトリガーを設定し、ビルド作業を行うshを記述すれば設定終了です。
ビルド・トリガ
今回は日時で日本時間の深夜にセントラルビルドを行うよう設定を行ったので以下のような設定をしています。GitHubがソースリポジトリの場合WebHookを使用したgit pushタイミングで都度ビルドスクリプトを走らせることも可能です。
TZ=Japan
H 2 * * *
ビルドスクリプト
スクリプトで行うことは以下の通りです。
- Cloud Foundry CliのSAPプラグインをインストール
- GitHubから取得したソースコードをmtar Archiveに固める
- cfコマンドでAPIを指定する
- cfコマンドでログオン
- cfコマンドでSAP Cliプラグインで実行可能なdeployコマンドを実行する
注意するポイントはLinuxイメージの/mtartoolディレクトリに必要ファイルをすべて格納している点です。cf install-pluginコマンドはそのため/mtartoot直下にあるbinを指定います。具体的なsh内容は例えば以下のようになります。
cf install-plugin /mtartool/cf-cli-mta-plugin.bin -f
java -jar /mtartool/mta_archive_builder-1.1.7.jar --build-target CF --mtar ./target/mymta.mtar build
cf api https://api.cf.jp10.hana.ondemand.com
cf login -u <User ID> -p <Password>
cf deploy target/mymta.mtar
Slack連携設定
ジョブ設定内のビルド後の処理でSlack Notificationsを選択します。Notificationしたい内容を選択します。今回のプロジェクトでは、
- Notify Success
- Notify Failure
のみ選択しました。
これで日時で深夜、最新のソースコードをGitHubより取得し、Jenkins内でArchiveを作成し、SAP Cloud Foundryにpushすることが出来るようになりました。
このプロジェクトではBotフレームワークのConversational AIが、この作業でRuntimeに配備された最新のArchiveを直接コールします。これは毎日朝起きると最新のソースベースのテストがメンバーの各モバイルに追加しているLINEアカウントより即テスト可能になることを意味します。
前述した通り改修内容はgitのコミットコメントを通して最終的にSlackまで通知されるので、メンバーは気になっていた機能が実装されたら即時にその機能を試すことが出来ます。また、フィードバックもその流れでSlack上で投稿する運用にしていたので、改修、更なるテストのサイクルを幾度も回すことが出来、結果として非常に堅牢な、また機能的に充実したアプリケーションを作成することができました。
終わりに
SAPプロジェクトではDevOpsを意識した開発はあまり行っていないケースが多いかと思いますが、SAP CPがリリースされ、リリースサイクルの短いマイクロサービスの開発など従来のウォーターフォール型開発をベースにした管理手法ではハマらないケースが多々出てきていると思います。本ブログはそうした新しい開発スタイルに挑戦するプロジェクトの一助となれば幸いです。それではみなさま良き開発を!