Azure Pipelines에서 Ansible 사용

이 기사는 Azure DevOps Advent Calendar 2020의 둘째 날 기사입니다.

MS Hosted Agent와 azure-pipelines.yml을 사용하여 이동하는 방법입니다. Self Hosted Agent를 사용하는 것은 참조에 링크로 기재되어 있습니다.

전제 조건


  • 관리 대상 서버(배포 대상 서버)에 SSH 키와 같은 자격 증명이 올바르게 설정되어 있어야 합니다.
  • Azure Pipelines Library에 Private SSH 키가 업로드되었습니다.


  • 구현



    경량 버전과 권장 버전의 두 가지로 나뉩니다. 어느 쪽이든 구현 가능합니다. MS Hosted Agent의 ubuntu-latest에는 Ansible이 built-in되어 있기 때문에 그대로 Ansible 명령을 실행할 수 있습니다. 트리거나 변수 그룹 등은 프로젝트에 따라 추가합니다.

    경량판



    하나의 파일로 완결되었습니다. 필요한 경우 빌드 및 테스트 단계를 추가합니다.

    azure-pipelines.yml
    trigger:
    - none
    
    pool:
      vmImage: 'ubuntu-latest'
    
    steps:
    - task: DownloadSecureFile@1
      displayName: 'Download ansible key file'
      name: ansibleKey
      inputs:
        secureFile: private_key
    
    - script: |
        chmod 600 $(ansibleKey.secureFilePath)
        export ANSIBLE_HOST_KEY_CHECKING=False
        ansible-playbook ansible.yml -i inventory --private-key=$(ansibleKey.secureFilePath) -vvv
      displayName: 'Run ansible'
    

    추천 버전



    빌드와 릴리스에 스테이지를 나누고 있는 것과, 개발 환경과 프로덕션 환경에 YAML 를 나누고 있습니다. 여기도 필요에 따라 빌드 및 테스트 단계를 추가합니다.



    azure-pipelines-production.yml
    trigger:
    - none
    
    stages:
    - stage: Build
      jobs: 
      - job: Build
        pool:
          vmImage: 'ubuntu-latest'
        steps:
        - template: pipelines/build-template.yml
    
    - stage: Release
      dependsOn:
      - Build
      condition: succeeded()
      jobs:
      - deployment: Deploy
        pool:
          vmImage: 'ubuntu-latest'
        environment: production
        strategy:
          runOnce:
            deploy:
              steps:
              - template: pipelines/release-template.yml
                parameters:
                  SERVER_ENV: production
    

    azure-pipelines-development.yml
    trigger:
    - none
    
    stages:
    - stage: Build
      jobs: 
      - job: Build
        pool:
          vmImage: 'ubuntu-latest'
        steps:
        - template: pipelines/build-template.yml
    
    - stage: Release
      dependsOn:
      - Build
      condition: succeeded()
      jobs:
      - deployment: Deploy
        pool:
          vmImage: 'ubuntu-latest'
        environment: development
        strategy:
          runOnce:
            deploy:
              steps:
              - template: pipelines/release-template.yml
                parameters:
                  SERVER_ENV: development
    

    pipelines/build-template.yml
    steps:
    - script: |
        tar zvcf app.tar.gz \
          --exclude='app.tar.gz' \
          --exclude='.git' \
          --warning=no-file-changed \
          . || [[ $? == 1 ]]
      displayName: 'compress code'
    
    - publish: app.tar.gz
      artifact: app
      displayName: 'Publish Build artifact'
    
    - publish: pipelines
      artifact: pipelines
      displayName: 'Publish pipelines artifact'
    

    pipelines/release-template.yml
    parameters:
      SERVER_ENV: ''
    
    steps:
    - task: DownloadSecureFile@1
      displayName: 'Download ansible key file'
      name: ansibleKey
      inputs:
        secureFile: private_key
    
    - task: DownloadPipelineArtifact@2
      displayName: 'Download app'
      inputs:
        artifact: 'app'
        path: ./
    
    - task: DownloadPipelineArtifact@2
      displayName: 'Download pipelines'
      inputs:
        artifact: 'pipelines'
        path: ./pipelines
    
    - script: |
        chmod 600 $(ansibleKey.secureFilePath)
        export ANSIBLE_HOST_KEY_CHECKING=False
        ansible-playbook pipelines/ansible.yml -i pipelines/inventory-${{ parameters.SERVER_ENV }} --private-key=$(ansibleKey.secureFilePath) -vvv
      displayName: 'Run ansible'
    

    문제해결



    관리 대상 서버에 SSH IP 필터링이있는 경우



    MS Hosted Agent의 IP는 가변적이므로 배포 전에 IP 필터링을 허용하고 배포 후 허용한 IP 필터링을 제거해야 합니다.
    가상 머신은 SSH 를 IP 필터링하고 있는 것이 당연하기 때문에, 귀찮은 경우는 발판 서버를 구축해, 거기에 Self Hosted Agent 를 도입하는 것이 좋다고 생각합니다.

    Azure VM에 배포할 때는 이 명령과 단계입니다. 파라미터는 필요에 따라 설정합니다. AWS 의 경우도 마찬가지로 AWS CLI 를 사용하여 허가, 삭제하면 대응 가능합니다.
    - script: |
        GIP=$(curl inet-ip.info)
        echo "##vso[task.setvariable variable=AgentMachineGIP]${GIP}"
      displayName: 'Get agent global IP'
    
    - task: AzureCLI@1
      displayName: 'Allow network security group'
      inputs:
        azureSubscription: 'azureSubscription'
        scriptLocation: inlineScript
        inlineScript: |
          az network nsg rule create \
            -g ${{ parameters.RG_NAME }} \
            -n allow-AzureDevOpsAgent-inbound \
            --nsg-name ${{ parameters.NSG_NAME }} \
            --priority 2222 \
            --access Allow \
            --direction Inbound \
            --protocol "*" \
            --destination-port-ranges "*" \
            --source-address-prefixes "$(AgentMachineGIP)" 
    
    # NSG への設定反映は即時ではないため、 ansible コマンドに --timeout=180 を設定して SSH 接続を待つ必要があります。
    # ansible-playbook ansible.yml -i inventory --private-key=$(ansibleKey.secureFilePath) --timeout=180 -vvv
    
    - task: AzureCLI@1
      displayName: 'Delete network security group'
      condition: always()
      inputs:
        azureSubscription: 'azureSubscription'
        scriptLocation: inlineScript
        inlineScript: |
          az network nsg rule delete \
            -g ${{ parameters.RG_NAME }} \
            -n allow-AzureDevOpsAgent-inbound \
            --nsg-name ${{ parameters.NSG_NAME }}
    

    참고



    Self Hosted Agent를 사용하는 경우 여기를 참조하십시오.
  • Automating Infrastructure Deployments in the Cloud with Ansible and Azure Pipelines | Azure DevOps Hands-on-Labs
  • Azure Pipelines로 구현되는 IaC - 제 4 회 OS 및 MW 구성 | SB 기술 (SBT)
  • 좋은 웹페이지 즐겨찾기