Azure PipelinesでAKSプライベートクラスタにデプロイを行う

AKSはAPIサーバーへの通信をプライベートに限定するプライベートクラスタを構築することが可能です。

ただしDevOpsでCI/CD組もうとすると通常のAKSクラスタだと簡単に統合できたところが、プライベートクラスタだと上手くいきません。(API叩けないので当然ですが)

実際にこちらののサイトにも制限事項として記載があります。

docs.microsoft.com

No support for Azure DevOps integration out of the box with private clusters

Self-hosted agentsによる実現方法

それでもAzure Pipelinesを利用してCI/CDを行いたい場合の方法としてSelf-hosted agentsを使う方法があります。

通常のPipelineではMicrosoft-hosted agentsというAzureのマネージドのワンタイムマシンでビルドやデプロイ処理が実行されますが、これを自分のマシンで動かす方法になります。

自分のマシンをプライベートネットワーク内に置くことで、プライベートクラスタへの命令とAzure Pipelineを連携することができます。以下の絵がわかりやすいです。

Azure Pipelines Agents - Azure Pipelines | Microsoft Docs

f:id:yomon8:20200428204130p:plain

github.com

Self-hosted Agentのインストール

インストール方法は以下のURLにも手順があります。

docs.microsoft.com

このサイトの方法以外にもインストールのオプションがあります。以下のように、config.shのヘルプを見ると色々出てきます。

ここではPersonal Access Tokenを使う方式で設定を行ってみます。

$ ./config.sh --help
# 省略
VSTS authentication
./config.sh --unattended --url https://myaccount.visualstudio.com --auth pat --token myToken --pool default --agent myAgent --acceptTeeEula
# 省略

自動インストールも可能なので、簡単なAnsibleでインストール処理を書いてみました。何やっているかわかると思います。

- name: Create directory for pipeline agent
  file:
    path: ~/pipeline
    state: directory

- name: Download pipeline agent
  get_url:
    url: https://vstsagentpackage.azureedge.net/agent/2.166.3/vsts-agent-linux-x64-2.166.3.tar.gz
    dest: /tmp/devops_agent.tar.gz

- name: Unarchive pipeline agent
  unarchive:
    remote_src: yes
    src: /tmp/devops_agent.tar.gz
    dest: ~/pipeline

- name: Configure pipeline agent
  shell: >-
    ./config.sh --unattended --url https://dev.azure.com/{{devops_org}}/ --auth pat --token {{pat}} --pool my_agent_pool --agent {{agent_name}} --replace --acceptTeeEula
  args:
    chdir: ~/pipeline

- name: Install pipeline agent
  shell: >-
    sudo ./svc.sh install
  args:
    chdir: ~/pipeline

- name: Enable pipeline agent
  become: true
  systemd:
    name: vsts.agent.{{devops_org}}.my_agent_pool.{{agent_name}}.service
    enabled: yes
    state: started

Self-hosted Agentの登録

あとはSelf-hosted Agentを登録したAgent Poolをプロジェクトに登録します。

f:id:yomon8:20200428213658p:plain

先程のAnsibleの最後にあるようにサービスを起動するとAgent PoolにAgentがOnlineとなっているはずです。

f:id:yomon8:20200428213506p:plain

CI/CD Pipelineの定義

こちらも簡単な定義の例を書いておきます。今からやりたいのは以下のようなイメージです。

f:id:yomon8:20200428213306p:plain

プライベートなのでPipelineのビルトインの定義がほとんど使えないので、普通にコマンドを順番に流すような処理になっています。

trigger:
  branches:
    include:
      - "refs/tags/test-job*"

variables:
  - group: my-variable-group
  - name: jobName
    value: test-job
  - name: containerRegistry
    value: "myacr.azurecr.io"
  - name: agentPool
    value: "my_agent_pool"
  - name: tag
    value: "$(Build.SourceVersion)-$(Build.BuildId)"

resources:
  - repo: self

stages:
  - stage: Build
    displayName: Build stage
    jobs:
      - job: Build
        displayName: Build
        pool: $(agentPool)
        steps:
          - checkout: self
          - task: Bash@3
            displayName: Desc Build Env
            inputs:
              targetType: "inline"
              script: |
                echo "HOST -> $(hostname)"
                echo "USER -> $(whoami)"
                echo "Current Dir -> $(pwd)"
                ls -l
                git branch

          - task: Bash@3
            displayName: Login Azure with MSI
            inputs:
              filePath: "/usr/bin/az"
              arguments: "login -i"

          - task: Bash@3
            displayName: Login ACR
            inputs:
              filePath: "/usr/bin/az"
              arguments: "acr login --name $(containerRegistry)"

          - task: CmdLine@2
            displayName: Build Image
            inputs:
              script: "docker build -t $(containerRegistry)/$(jobName):$(tag) ./src/$(jobName)"

          - task: CmdLine@2
            displayName: Push Image
            inputs:
              script: "docker push $(containerRegistry)/$(jobName):$(tag)"

  - stage: Deploy
    displayName: Deploy Stage
    dependsOn: Build

    jobs:
      - deployment: Deploy
        condition: and(succeeded(), not(startsWith(variables['Build.SourceBranch'], 'refs/pull/')))
        displayName: Deploy
        environment: null
        pool: $(agentPool)
        strategy:
          runOnce:
            deploy:
              steps:
                - checkout: self
                - task: CmdLine@2
                  displayName: Kustomize and Deploy
                  inputs:
                    script: 'kubectl kustomize ./k8s-manifests/$(jobName)/overlays/$(envName)/ | sed  "s/image:.*$/image: $(containerRegistry)\/$(jobName):$(tag)/" | kubectl apply -f -'

実際に動いているところです、Self hosted Agentの入っているマシンをセットアップしておくことでプライベートのAKSクラスタへの処理が問題無く実行できています。

f:id:yomon8:20200428214524p:plain

ここではAnsibleを利用してインストールしましたが、Azure Portalから仮想マシンの拡張機能としてインストールすることも可能です。

f:id:yomon8:20200512132610p:plain