もりはやメモφ(・ω・ )

ITとか読書感想文とか

GitHub Actions で Ansible の playbook を生成して特定のTagのEC2をターゲットに実行

GitHub Actions で Ansible の playbook を生成して特定のTagのEC2をターゲットに実行するYAMLを書いたので、備忘でメモしておきます。

本来であれば以下のようなオープンなActionsを利用すべきでしょう。(自前で頑張るのは極力避けておくのが良いはず)

github.com

どんな仕組みか

簡単な構成が以下の通り。

f:id:morihaya:20210605024104p:plain

何を書いたか

こんな感じのGitHub Actions用のYAMLを書きました。

name: deploy

on:
  push:
    workflow_dispatch: #手動実行を許可
    branches: [ master ]
    paths:
    - "deploy_files/**"
    - ".github/workflows/deploy.yml"
jobs:
  build:
    runs-on: self-hosted
    steps:
    - uses: actions/checkout@v2

    - name: Install dependencies
      run: |
        pip3 install virtualenv
        virtualenv ansible-venv
        pip3 install ansible

    - name: Create Ansible inventory
      env:
        # Valiables for aws-cli to get ec2 list
        AWS_ACCESS_KEY_ID: "${{secrets.AWS_ACCESS_KEY_ID}}"
        AWS_SECRET_ACCESS_KEY: "${{secrets.AWS_SECRET_ACCESS_KEY}}"
        AWS_DEFAULT_REGION: "ap-northeast-1"
        # Valiables for aws-cli's "--filter"
        TAG_ENV: "dev"
        TAG_SERVICE: "web"
        ## deployするのは起動中のサーバのみとする
        TAG_INSTANCE_STATE: "running"
      run: |
        echo "[target]" > inventory
        aws ec2 describe-instances \
          --filters "Name=tag:Service,Values=${TAG_SERVICE}" "Name=tag:Env,Values=${TAG_ENV}" "Name=instance-state-name,Values=${TAG_INSTANCE_STATE}" \
          --query 'Reservations[].Instances[].PrivateIpAddress' | jq -r @csv | tr ',' '\n' >> inventory

    - name: Create ansible-playbook
      env:
        # Valiables for SSH
        SSH_USER: sre_github_actions
      run: |
        # RSYNCの準備
        sudo apt-get install -y rsync
        echo "${{secrets.SSH_PRIVATE_KEY_ANSIBLE}}" > /tmp/sshkey
        chmod 400 /tmp/sshkey
        # Ansibleのためのユーザ設定
        echo "[defaults]" > ansible.cfg
        echo "remote_user = ${SSH_USER}" >> ansible.cfg
        # Create ansible-playbook
        cat << EOF > playbook.yaml
        ---
        - name: Do playbook
          hosts: target
          become: yes
          gather_facts: no
          tasks:
          - name: Copy files
            ansible.builtin.copy:
              src: deploy_files/
              dest: /tmp/
              owner: root
              group: root
        EOF
        # Check playbook
        cat playbook.yaml

    - name: Deploy
      run: |
        hostname
        date
        pwd
        ls -l
        # Deployを実行
        ansible-playbook --key-file "/tmp/sshkey" -i inventory playbook.yaml

実行に必要なもの

RepositoryのSecretsに以下を設定しておく必要があります。

  • aws cli で特定のEC2のIPリストを取得するための変数
    • AWS_ACCESS_KEY_ID
    • AWS_SECRET_ACCESS_KEY
  • ansibleで利用する、sshの秘密鍵
    • SSH_PRIVATE_KEY_ANSIBLE

加えて runs-on: self-hosted でセルフホステッドのランナーを指定しています。 理由はansibleを各サーバへ実行するためには、内部のネットワークで動作するランナーを利用するのが簡単だからです。