LoginSignup
7

More than 1 year has passed since last update.

お前らのCFデプロイはダサい

Last updated at Posted at 2019-12-20

これはよくある煽り系釣りタイトルみたいなものです。怒らないでください。
怒った方はごめんなさい。
(※ この記事は SAP Advent Calendar 2019 の12月21日分の記事としても執筆しています)

2020年2月追記
本記事をさらにアップグレードした、やはりお前らのCFデプロイはダサいを公開しました。

ダサいデプロイとは - パラダイムへの反骨

わたくし、お片づけが大好きな"片づけコンサルタント"でございます。
特に、心ときめくようなシンプル、かつモダンでイケてるシステムアーキテクチャを作ることに興奮を隠しきれません。

そんな片づけコンサルタントがSAP Cloud PlatformのCloud Foundry(CF)での開発で許せないことの一つに、MTAアプリケーションの手動ビルド、手動デプロイというプロセスがあります。

イチイチBuildボタンをポチポチしては、
image.png
完了までシバシバ待ち、
完了したらデプロイボタンを押してまたムクムク待ち…
image.png

時は令和です。
みなさん、こんなダサいことをしている場合ではございません。

今回はこんな、心ときめかない手動ビルド、手動デプロイというプロセスをブチコリと排除して、かわいく自動でビルド、デプロイを行ってくれるアーキテクチャを作ってスッキリしたDevOps※実行環境の構築を目指しましょう。

※DevOpsについてはこちら

それでは早速方法を見てみましょう。

理想的なアーキテクチャ -ユートピア

本来、SAP Cloud PlatformのCFで作られるべきDevOpsを実現するアーキテクチャは、だいたいこんな感じであるとわたくしは思っております。

image.png

あぁ・・・・//

失礼、取り乱してしまいました。
上記で何を行っているかといいますと、ざっくり以下のような感じです。

  • ローカル、もしくはNeo環境のWebIDEから、CF環境に置いたGitlabコンテナに対してMTAプロジェクトのプッシュ
  • GitlabへのプッシュをトリガーにしてJenkinsコンテナ内でMTAプロジェクトをビルド
  • MTAビルド時に、共通ライブラリをnexusコンテナから取得する
  • JenkinsからCFランタイム環境へMTAアプリケーションをデプロイ
  • JenkinsからGitlabへ.mtarファイルをプッシュし、.mtarファイルをCTS+にて各CF環境へ配備

あぁ、なんと美しいのでしょう。
これにて手動のビルド、デプロイや移送などというダサい作業からは解脱できるのです。

ですが
こちらは2019年現在実現できません。。
何故なら、現在SAP Cloud PlatformのCF環境にはストレージサービス(NFS)が存在しないのです!
そのため、JenkinsやGitlabなどのコンテナを立てることはできても、開発オブジェクトやユーザ情報、コンフィグなどを永続化させることができず、コンテナの再起動がかかる度に消えてしまうのです。。

そのことを知った時、私は途方に暮れました。
悔しくて夜も眠れず、朝も起きられませんでした。

しかし!
そんな私を救ってくれたのがAzure DevOpsだったのです!!

2020年2月追記
Cloud Foundry環境にコンテナを立ててDevOpsを実現することがベストプラクティスだと悦に入っていましたが、現時点ではAzure DevOpsの方が断然楽にDevOpsを実現できて良いです。
完全に寝返ってしまいました。すいません。

Azure DevOpsの登場 -メシアの出現

image.png

このAzure DevOpsとは、Microsoft Azureの中の1サービスであり、GitやJenkinsのようなCI/CDツールとしての役割を包含したものです。
今回はこの、美しいサービスを利用してDevOpsを実現していくことにします!

前提プロジェクト -MTA

今回は、workshop1128というMTAプロジェクトの自動ビルド、自動デプロイを行っていきます。
その構成はこちらです。
image.png

MTAプロジェクトの下にJavaモジュール、UI5モジュール、hdiモジュールを作成した形です。
もう少し詳しく見るためにmta.yamlを添えておきます。

mta.yaml
ID: workshop1128
_schema-version: '2.1'
parameters:
  deploy_mode: html5-repo
version: 0.0.1
modules:
  - name: workshop1128_appRouter
    type: approuter.nodejs
    path: workshop1128_appRouter
    parameters:
      disk-quota: 256M
      memory: 256M
    requires:
      - name: workshop1128_html5_repo_runtime
      - name: uaa_workshop1128
  - name: workshop1128_ui_deployer
    type: com.sap.html5.application-content
    path: workshop1128_ui_deployer
    requires:
      - name: workshop1128_html5_repo_host
    build-parameters:
      requires:
        - name: workshop1128ui5
          artifacts:
            - './*'
          target-path: resources/workshop1128ui5
  - name: hdi1128
    type: hdb
    path: hdi1128
    requires:
      - name: hdi_hdi1128
  - name: workshop1128java
    type: java
    path: workshop1128java
    parameters:
      memory: 1024M
    provides:
      - name: workshop1128java_api
        properties:
          url: '${default-url}'
    requires:
      - name: ls_tokyo-connectivity
      - name: dest_workshop1128
      - name: uaa_workshop1128
      - name: hdi_hdi1128
        properties:
          JBP_CONFIG_RESOURCE_CONFIGURATION: '[tomcat/webapps/ROOT/META-INF/context.xml: {"service_name_for_DefaultDB" : "~{hdi-container-name}"}]'
  - name: workshop1128ui5
    type: html5
    path: workshop1128ui5
    build-parameters:
      builder: grunt
      supported-platforms: []
      build-result: dist
resources:
  - name: workshop1128_html5_repo_runtime
    parameters:
      service-plan: app-runtime
      service: html5-apps-repo
    type: org.cloudfoundry.managed-service
  - name: workshop1128_html5_repo_host
    parameters:
      service-plan: app-host
      service: html5-apps-repo
    type: org.cloudfoundry.managed-service
  - name: hdi_hdi1128
    parameters:
      config:
        schema: sawayaka
    properties:
      hdi-container-name: '${service-name}'
    type: com.sap.xs.hdi-container
  - name: uaa_workshop1128
    parameters:
      path: ./xs-security.json
      service-plan: application
      service: xsuaa
    type: org.cloudfoundry.managed-service
  - name: dest_workshop1128
    parameters:
      service-plan: lite
      service: destination
    type: org.cloudfoundry.managed-service
  - name: ls_tokyo-connectivity
    parameters:
      service-plan: lite
      service: connectivity
    type: org.cloudfoundry.existing-service

Azure DevOpsをさわってみよう -初体験

ということで早速上記で用意したMTAプロジェクトをAzure DevOpsでブチコリと料理する方法をご紹介しましょう。

Gitリポジトリの利用

まずはAzure DevOpsのGitサービスであるReposから新しいRepositoryを作成していきます。

image.png

元々GitにあるオブジェクトをCloneしてくることが出来るので、既にSAP Cloud Platformで利用しているGitリポジトリを入力すればOKです。

image.png

そうするとこのような形で先ほどのworkshop1128プロジェクトをAzure DevOps上に持ってくることができます。

もし継続してAzure DevOpsを使う場合は、こちらのリポジトリをリモートリポジトリとして使用すれば、後述するCI/CDパイプラインをGitへのプッシュをトリガにして実行することも可能です。

image.png

CI/CDツールとしてのパイプライン構築

メインとなる自動ビルド、自動デプロイを実行する、パイプラインの構築を行っていきます。
まずはPipelinesを選択します。

image.png

New build pipelineを選択して新規パイプラインを作成します。

image.png

パイプラインで扱うプロジェクトを、先ほどのAzure DevOpsのGitから持ってきます。
他にもGithubやBitbucketがあり、SAP Cloud PlatformのGitサービスも選択できるように見えていますが、パイプラインを自由に定義できなくなってしまうので、Azure DevOpsのGitを使うのが良いかと思います。

image.png

先ほど移したworkshop1128プロジェクトを選択する。

image.png

ここからパイプラインの定義をしていきます。
様々な言語でビルド、デプロイを行うためのテンプレートyamlが用意されていますが、MTAのテンプレートは用意されていないので、今回はNode.jsのテンプレートを暫定的に選択して中身を入れ替えることにします。

image.png

このNode.jsのために書かれたazure-pipeline.yamlを以下のように書き換えてください。
image.png

azure-pipelines.yml
# Starter pipeline

name: sawayaka-mta-project
resources:
  containers:
  - container: mta
    image: 'ppiper/mta-archive-builder:latest'
    options: --user 0:0
  - container: cfcli
    image: 'ppiper/cf-cli'
    options: --user 0:0 --privileged
  - container: node
    image: 'geekykaran/headless-chrome-node-docker:latest'
    options: --privileged


trigger:
- master


stages:
- stage: build
  displayName: Build MTA for SAP Cloud Platform
  jobs:
    - job: build
      pool:
        vmImage: 'ubuntu-latest'
      container: mta
      steps:
        - bash: 'mtaBuild --build-target CF --mtar MySampleApp.mtar build'
        - publish: $(System.DefaultWorkingDirectory)/.
          artifact: WebApp


- stage: deploy
  displayName: Deployment to SAP Cloud Platform (cf)
  jobs:
    - job: deploy
      pool:
        vmImage: 'ubuntu-latest'
      container: cfcli
      steps:
        - download: current
          artifact: WebApp
        - bash: 'cf login -u "$(CF-USER)" -p "$(CF-PASSWORD)" -a "$(CF-API)" -o "$(CF-ORG)" -s "$(CF-SPACE)" && cf deploy $(Pipeline.Workspace)/WebApp/MySampleApp.mtar -f'

この中でMTAプロジェクトのビルド、デプロイを定義しています。
デプロイに必要な環境情報などは、セキュリティの観点から変数化して渡してあげます。
Variablesを開くと、keyとvalueの形で変数化することが可能であるとわかります。
image.png

image.png

必要なのは、CF-API, CF-ORG, CF-PASSWORD, CF-SPACE, CF-USERです。
それぞれに、APIエンドポイント(https://api.cf.eu10.hana.ondemand.com など)、サブアカウント名、CFログインパスワード、スペース名、ログインユーザを定義すればよいです。

image.png

ここまでできれば後は実行するだけです。

image.png

対象となるGitブランチを選択します。
たったこれだけでお片づけが完了です。スッキリ☆
image.png

他の開発でもしながら放っておいている内に、勝手にビルド、デプロイが成功しております。成功すると赤枠のように緑色のバッチが付きます。
image.png

中身を見てみると、ビルド、デプロイの過程で出力されたログも見られます。
この辺りはCF-CLIで操作した時とほとんど変わらないログが吐かれているはずです。
image.png
image.png

実際に、CF環境を見てみるとworkshop1128の中にあるモジュールたちがちゃんとデプロイされていることがわかります。
なんて素敵なんでしょう・・//
image.png

おわりに -ココロトキメク

いかがでしたか?
意外と簡単にDevOps環境って構築できると思えたのではないでしょうか?
今後はテストコードの実行などもパイプライン上で行うことで、よりCI/CDの概念に近づけたり、Ansibleのようなサービスを使って構成管理を実現することがしたいですね☆

みなさまココロトキメク開発ライフを楽しみましょう~

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
7