APC 技術ブログ

株式会社エーピーコミュニケーションズの技術ブログです。

株式会社 エーピーコミュニケーションズの技術ブログです。

Azure Pipelines×App ServiceでCI/CD環境を構築してみた

こちらはエーピーコミュニケーションズ Advent Calender 2022の15日目の記事です。

はじめに

こんにちは、ACS事業部の過部です。
この記事では、Node.jsアプリを題材にAzure PipelinesとApp Serviceを用いたCI/CD環境の構築手順をご紹介します。 パイプライン構築後は、実際にアプリケーションコードに変更を加えて自動デプロイを試していきます。

前提条件

  • 各種作業でAzure CLIインストール済みのLinuxターミナルを利用します
  • リポジトリにはAzure Reposを利用します
  • Service PrincipalにContributor権限を付与できるAzureアカウントが必要です
  • Azure DevOpsプロジェクトが既に存在すること
  • Azure Reposリポジトリが既に存在すること
  • 利用可能なMicrosoft-hosted agentが存在すること

準備編

まずはパイプライン作成に必要な要素を準備します。

以下の流れで作業を行います。

  • 手順① サンプルアプリを用意
  • 手順② 各種Azureリソースを作成
  • 手順③ Service Principalを作成

準備編:手順① サンプルアプリを用意

Microsoftが公開しているNode.jsのサンプルアプリをAzure Reposリポジトリにクローンしていきます。 サンプルアプリはトップページにHello Worldを表示する簡単なものです。

以下の作業をターミナル上で実施します。

# サンプルアプリをgit clone
git clone https://github.com/Azure-Samples/nodejs-docs-hello-world.git

# リモートリポジトリを自身のAzure Reposリポジトリに変更
cd nodejs-docs-hello-world
git remote remove origin
git remote add origin https://sample-organization@dev.azure.com/sample-organization/sample-project/_git/sample-repository

# git pushを実施
git push origin main

※ 注:Azure ReposリポジトリのURLは自身のものに置き換えて実行してください。

準備編:手順② 各種Azureリソースを作成

Azure CLIを用いてアプリケーションのデプロイ先となるApp Serviceを作成していきます。

以下の作業をターミナル上で実施します。

# 変数設定
webName="app-sample"
rgName='rg-sample'
planName='plan-sample'

# Resource Groupを作成
az group create --name $rgName -l japaneast

# App Service Planを作成
az appservice plan create \
  --name $planName \
  --resource-group $rgName \
  --sku B1 \
  --is-linux

# App Serviceを作成
az webapp create \
  --name $webName \
  --resource-group $rgName \
  --plan $planName \
  --runtime "node|16-lts"

準備編:手順③ Service Principalを作成

App Serviceへのデプロイ時にAzure Pipelinesが使うService Principalを作成していきます。詳細は後述します。

以下の作業をターミナル上で実施します。

# Resource GroupレベルのContributor権限を持つService Principalを作成
az ad sp create-for-rbac --name sp-sample --role Contributor --scopes $(az group show -g $rgName --query id -o tsv)

以下の様な内容が出力されます。後手順で利用するため無くさないように控えておきます。

{
  "appId": "xxxxxxx",
  "displayName": "sp-sample",
  "password": "xxxxxxx",
  "tenant": "xxxxxxx-xxxxxxx-xxxxxxx-xxxxxxx"
}

構築編

次に、CI/CDパイプラインを作成していきます。

以下の流れで作業を行います。

  • 手順④ Service Connectionを作成
  • 手順⑤ パイプラインを作成

構築編:手順④ Service Connectionを作成

Azure PipelinesからAzure Resource Managerにアクセスするために必要なService Connectionと呼ばれる設定を作成していきます。 本題に入る前に簡単にService Connectionについて解説します。

Service Connectionとは

一言でいうと、Azure Pipelinesから外部サービスに接続するために必要な設定です。

今回構築するCI/CDパイプラインでは、App Serviceへのデプロイを行うためにAzure PipelinesからAzure Resource Managerに接続する必要があります。その際にService Connectionが必要になります。
また、Service Connection作成時には外部サービスへアクセスするための認証情報を設定する必要があります。Azure Resource Managerへ接続する際の認証情報にはService Principal, Managed Identity等が利用できますが、今回はService Principalを利用します。

Service Connection作成画面へ移動

Azure DevOps上でService Connectionを作成していきます。


Azure DevOpsのプロジェクトトップ画面から、Project settings -> Service connections -> New service connectionをクリックします。

接続タイプを選択


Azure Resource Managerを選択し、右下のNextをクリックします。

認証方式を選択


Service Principal(manual)を選択し、右下のNextをクリックします。

Service Principal(automatic)を選択した場合、現在Azure PipelinesにログインしているアカウントがAzure Resource Manager接続用の認証情報としてそのまま利用されます。 セキュリティ及びアクセス制限の観点からAzure Pipelinesへのログインに使用するアカウントとApp Serviceへのデプロイに使用するアカウントは分離するのが望ましいです。 今回はService Principal(manual)を選択し、準備編で作成したService Principalを認証情報として利用します。

各種パラメーターを入力


準備編で作成したService Principalの資格情報や、Azure Portal上の情報を基に各項目を埋めて、左下のVerifyをクリックします。

※ Service Principal資格情報のappIdは上記のService Principal Id、Service Principal資格情報のpasswordは上記のService principal keyに該当します。


問題無ければ、Service Connection名を入力し、右下のVerify and Saveをクリックします。

構築編:手順⑤ パイプラインを作成

Azure DevOps上でパイプラインを作成していきます。

パイプライン作成画面へ移動


Azure DevOpsのプロジェクトトップ画面から、Pipelines -> New Pipeline をクリックします。

リポジトリ種類を選択


Azure Repos Git をクリックします。

対象リポジトリを選択


作成済みのリポジトリ をクリックします。

パイプラインを設定

リポジトリ内容と関連するテンプレートが表示されます。 今回は、Node.jsテンプレートをカスタマイズする形でYAMLファイルを書いていきます。
Node.js をクリックします。

YAMLファイルを変更

以下の様に変更します。
※ 注:variablesのazureSubscriptionの値は、前手順で自身が設定したService Connection名に置き換えてください。

# トリガー条件:mainブランチへのgit push
trigger:
- main

# 実行環境のVMイメージ:最新版Ubuntu
pool:
  vmImage: ubuntu-latest

# 変数設定
variables:
  # Service Connection名
  azureSubscription: 'sc-sample'
  
  # App Service名
  webAppName: 'app-sample'

# パイプライン内で実行される具体的な処理
stages:
- stage: Build
  displayName: Build stage # Azure DevOps上での表示名を指定
  jobs:  
  - job: Build
    displayName: Build
    steps:
    # Node.jsインストール用Task
    # https://learn.microsoft.com/ja-jp/azure/devops/pipelines/tasks/reference/node-tool-v0?view=azure-pipelines
    - task: NodeTool@0
      inputs:
        versionSpec: '16.x'
      displayName: 'Install Node.js'

    # スクリプト実行用Taskの省略形
    # https://learn.microsoft.com/ja-jp/azure/devops/pipelines/tasks/reference/cmd-line-v2?view=azure-pipelines&viewFallbackFrom=azure-devops
    - script: |
        npm install
        npm run build --if-present
      displayName: 'npm install and build'

    # アーカイブ用Task
    # https://learn.microsoft.com/ja-jp/azure/devops/pipelines/tasks/reference/archive-files-v2?view=azure-pipelines
    - task: ArchiveFiles@2
      displayName: 'Archive files'
      inputs:
        rootFolderOrFile: '$(System.DefaultWorkingDirectory)'
        includeRootFolder: false
        archiveType: zip
        archiveFile: $(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip
        replaceExistingArchive: true

    # Azure Pipelinesでは実行環境がjob単位で共有されます。そのためDeployステージからBuildステージの成果物へ直接アクセスできません。
    # 今回の例では、ビルド成果物のPublish及びDownloadを行うことでデプロイに必要な成果物をステージ間で受け渡しています。

    # ビルド成果物公開用Task
    # https://learn.microsoft.com/ja-jp/azure/devops/pipelines/tasks/reference/publish-build-artifacts-v1?view=azure-pipelines
    - task: PublishPipelineArtifact@1
      displayName: 'Publish npm artifact'
      inputs:
        targetPath: '$(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip'
        artifactName: npm

- stage: Deploy
  displayName: Deploy stage
  dependsOn: Build # Buildステージ完了時のみDeployステージを実行
  condition: succeeded()
  jobs:  
  - job: Deploy
    displayName: Deploy
    steps:
    # ビルド成果物ダウンロード用Task
    # https://learn.microsoft.com/ja-jp/azure/devops/pipelines/tasks/reference/download-package-v1?view=azure-pipelines
    - task: DownloadBuildArtifacts@1
      displayName: "Download npm artifact"
      inputs:
        artifactName: npm
        downloadPath: $(System.ArtifactsDirectory)

    # App Serviceデプロイ用Task
    # https://learn.microsoft.com/ja-jp/azure/devops/pipelines/tasks/reference/azure-web-app-v1?view=azure-pipelines
    - task: AzureWebApp@1
      displayName: 'Azure Web App Deploy'
      inputs:
        azureSubscription: $(azureSubscription)
        appType: webAppLinux
        appName: $(webAppName)
        runtimeStack: 'NODE|16-lts'
        package: $(System.ArtifactsDirectory)/$(Build.BuildId).zip
        startUpCommand: 'npm run start'

YAMLファイルを保存及び実行


YAMLファイルを編集後、Save and run をクリックします。


コミットメッセージ確認画面が表示されるので、再度Save and run をクリックします。

パイプラインの実行結果を確認


パイプラインの実行完了を暫く待ちます。
Build, Deployステージ共にステータスが緑色であることを確認します。

App Serviceへアクセス


パイプラインの正常完了が確認できたので、App Serviceへ正常デプロイできたか確認していきます。 Azure Portal等からApp ServiceのURLを入手しアクセスします。 トップページにHello World!と表示されていればデプロイ成功です。

動作確認編

CI/CDパイプラインの動作確認を行っていきます。

以下の流れで作業を行います。

  • 手順⑥ アプリケーションコードを変更
  • 手順⑦ パイプラインの実行結果をを確認
  • 手順⑧ App Service上で変更内容を確認

動作確認編:手順⑥ アプリケーションコードを変更

トップページに表示される文字列を変更していきます。

index.jsの中身を書き換え

index.jsの58行目のHello World!を任意の文字列に書き換えます。

app.get('/', function (req, res) {
    return res.send("Hello World!"); # 変更対象
})

# 書き換え例
app.get('/', function (req, res) {
    return res.send("Hello APC!");
})
リモートリポジトリへgit push

変更後、commitしてpushします。

# git commit
git commit -a -m"トップページを変更"

# git push
git push origin main

動作確認編:手順⑦ パイプラインの実行結果を確認

mainブランチへのgit pushを実行したためパイプラインがトリガーされているはずです。 Azure DevOpsへ移動し実行結果を確認していきます。

対象パイプラインへ移動


Pipelines -> (作成したパイプライン) をクリックします。

対象実行結果へ移動


(最新の実行結果) をクリックします。

パイプラインの実行結果を確認


パイプラインの実行完了を暫く待ちます。
Build, Deployステージ共にステータスが緑色であることを確認します。

動作確認編:手順③ App Service上で変更内容を確認

パイプラインの正常完了が確認できたので、App Serviceへ変更内容が反映されたか確認していきます。

ブラウザを更新


トップページに変更内容が反映されていれば作業は完了です。

おわりに

私達ACS事業部はAzure・AKSを活用した内製化のご支援をしております。ご相談等ありましたらぜひご連絡ください。

www.ap-com.co.jp

また、一緒に働いていただける仲間も募集中です!
切磋琢磨しながらスキルを向上できる、エンジニアには良い環境だと思います。ご興味を持っていただけたら嬉しく思います。

www.ap-com.co.jp

本記事の投稿者: 過部 太智
sugibe taichi - Credly