LoginSignup
2
3

More than 3 years have passed since last update.

github actionsを使って aws + terraform + ansible でCI/CD環境を構築してみた

Last updated at Posted at 2020-05-28

概要

最近github actionsが楽しいのでaws環境でteraform + ansible実行してみた。
EC2を構築し、httpdをインストールする所まで実施。

目次

・事前準備
・ディレクトリ構成
・バケット作成
・IAMユーザ作成
・terraformコード作成
・ansible コード作成
・github actions 作成
・githu actions 実行結果

事前準備

  • EC2のIPの自動取得にdyanamic inventoryが使用できること

ディレクトリ構成

├── README.md
├── ansible
│   ├── ansible.cfg
│   ├── ec2.ini
│   ├── ec2.py
│   ├── roles
│   │   ├── common
│   │   │   ├── files
│   │   │   │   └── main.yml
│   │   │   └── tasks
│   │   └── nginx
│   │       ├── files
│   │       └── tasks
│   │           └── main.yml
│   ├── sandbox.yml
└── terraform
    ├── backend.tf
    ├── data.tf
    ├── main.tf
    ├── output
    ├── output.tf
    ├── provider.tf
    └── variables.tf

S3バケット作成

tfstate保存用のバケットを作成する。

バケット作成
% aws s3 mb s3://tf-sandbox-masa3521
make_bucket: tf-sandbox-masa3521

IAMユーザ作成

terraform,ansibleの実行用のIAMユーザを作成する。
EC2とS3、key系はパラメータストアから取得するので必要な権限を付与する。

IAMユーザ作成
% aws iam create-user --user-name cicd_user

{
    "User": {
        "Path": "/",
        "UserName": "cicd_user",
        "UserId": "***************",
        "Arn": "arn:aws:iam::***************:user/cicd_user",
        "CreateDate": "2020-05-21T15:05:18Z"
    }
}
アクセスキー付与
% aws iam create-access-key --user-name cicd_user
{
    "AccessKey": {
        "UserName": "cicd_user",
        "AccessKeyId": "***************",
        "Status": "Active",
        "SecretAccessKey": "***************",
        "CreateDate": "2020-05-22T00:42:37Z"
    }
}
権限付与〜policy確認
% aws iam attach-user-policy --policy-arn arn:aws:iam::aws:policy/AmazonS3FullAccess  --user-name cicd_user
% aws iam attach-user-policy --policy-arn arn:aws:iam::aws:policy/AmazonEC2FullAccess --user-name cicd_user
% aws iam attach-user-policy --policy-arn arn:aws:iam::aws:policy/AmazonSSMReadOnlyAccess --user-name cicd_user
% aws iam list-attached-user-policies --user-name cicd_user
{
    "AttachedPolicies": [
        {
            "PolicyName": "AmazonEC2FullAccess",
            "PolicyArn": "arn:aws:iam::aws:policy/AmazonEC2FullAccess"
        },
        {
            "PolicyName": "AmazonS3FullAccess",
            "PolicyArn": "arn:aws:iam::aws:policy/AmazonS3FullAccess"
        },
        {
            "PolicyName": "AmazonSSMReadOnlyAccess",
            "PolicyArn": "arn:aws:iam::aws:policy/AmazonSSMReadOnlyAccess"
        }
    ]
}

key作成

EC2に設定する公開鍵/秘密鍵を作成し、作成したものをパラメータストアに登録する。

key作成
% ssh-keygen -t rsa -b 4096  
parameter_storeに登録
% aws ssm put-parameter --name "publickey" \
                      --type SecureString \
                      --value  "$(cat id_rsa.pub)"

{
    "Version": 1,
    "Tier": "Standard"
}

% aws ssm put-parameter --name "pravatekey" \
                      --type SecureString \
                      --value  "$(cat id_rsa)"

{
    "Version": 1,
    "Tier": "Standard"
}

terraformコード作成

  • data.tfで公開鍵をパラメータストアから取得
  • backend.tfでtfstateをリモートで管理
  • output.tfでセキュリティーグループのgroupidをファイルに出力 ※後のgithub-actionsで使用
provider.tf
provider "aws" {
  profile = "default"
  version = "= 2.61"
  region  = "ap-northeast-1"
}
backend.tf
terraform {
  backend "s3" {
    bucket  = "tf-sandbox-masa3521"
    region  = "ap-northeast-1"
    key     = "terraform.tfstate"
    encrypt = true
  }
}
data.tf
data "aws_ssm_parameter" "publickey" {
  name            = "publickey"
  with_decryption = true
}
variables.tf
variable "region" {
  default = "ap-northeast-1"
}

variable "system" {
  default = "sandbox"
}
output.tf
resource "local_file" "sgroupid" {
  filename = "./group_id"
  content  = aws_security_group.sandboxSG.id
}
main.tf

resource "aws_vpc" "sandboxVPC" {
  cidr_block           = "10.1.0.0/16"
  instance_tenancy     = "default"
  enable_dns_support   = "true"
  enable_dns_hostnames = "false"
  tags = {
    Name = var.system
    Env  = terraform.workspace
  }
}

resource "aws_route_table" "sanbboxRT" {
  vpc_id = aws_vpc.sandboxVPC.id

  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.sandboxGW.id
  }

  tags = {
    Name = var.system
    Env  = terraform.workspace
  }
}

resource "aws_subnet" "sandboxSUBNET" {
  vpc_id     = aws_vpc.sandboxVPC.id
  cidr_block = "10.1.0.0/24"
  tags = {
    Name = var.system
    Env  = terraform.workspace
  }
}

resource "aws_internet_gateway" "sandboxGW" {
  vpc_id = aws_vpc.sandboxVPC.id
  tags = {
    Name = var.system
    Env  = terraform.workspace
  }
}

resource "aws_route_table_association" "sandboxRTA" {
  subnet_id      = aws_subnet.sandboxSUBNET.id
  route_table_id = aws_route_table.sanbboxRT.id
}

resource "aws_security_group" "sandboxSG" {
  name        = "sandboxSG"
  description = "Allow SSH inbound traffic"
  vpc_id      = aws_vpc.sandboxVPC.id
  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
  tags = {
    Name = var.system
    Env  = terraform.workspace
  }
}

resource "aws_key_pair" "publickey" {
  key_name   = "key"
  public_key = data.aws_ssm_parameter.publickey.value
  tags = {
    Name = var.system
    Env  = terraform.workspace
  }
}

resource "aws_instance" "sandboxinstance" {
  key_name      = aws_key_pair.publickey.id
  ami           = "ami-0f310fced6141e627"
  instance_type = "t2.nano"
  vpc_security_group_ids = [
    aws_security_group.sandboxSG.id
  ]

  subnet_id                   = aws_subnet.sandboxSUBNET.id
  associate_public_ip_address = "true"
  tags = {
    Name = var.system
    Env  = terraform.workspace
  }
}

ansible 作成

ansile.cfg
[defaults]
deprecation_warnings = False
remote_user = ec2-user
private_key_file = ./privatekey
host_key_checking = False
sandbox.yml
- hosts: tag_Name_sandbox
  roles:
    - htted
roles/tasks/main.yml
---
- name: install apache
  yum:
   name: httpd
   state: present
  become: true
- name: Start httpd
  service:
    name: httpd
    state: started
    enabled: yes
  become: true

github-actions作成

  • 実行の為にsecretsの登録が必要
  • IPを自動で取得するためDynamic Inventoryで取得する。
  • ansble実行の為秘密鍵のダウンロード
  • ansible実行前にセキュリティーグループに自分のIPを登録、実行後に自分のIPを削除

secrets登録

スクリーンショット 2020-05-29 1.59.30.png

terraform-ansible.yml

name: Terraform deploy to Azure

on:
  push:
    branches:    
      - master

jobs:
  terraform-ansible:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2

    - name: Configure AWS Credentials
      uses: aws-actions/configure-aws-credentials@v1
      with:
        aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
        aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
        aws-region: ap-northeast-1

    - name: Setup Terraform
      uses: hashicorp/setup-terraform@v1
      with:
        terraform_version: 0.12.9

    - name: Terraform Init
      run: terraform init
      working-directory: ${{ github.workspace }}/terraform

    - name: Terraform select
      run: terraform workspace select dev
      working-directory: ${{ github.workspace }}/terraform

    - name: Terraform Format
      run: terraform fmt -check
      working-directory: ${{ github.workspace }}/terraform

    - name: Terraform Plan
      run: terraform plan
      working-directory: ${{ github.workspace }}/terraform

    - name: Terraform Apply
      if: github.ref == 'refs/heads/master' && github.event_name == 'push'
      run: terraform apply -auto-approve
      working-directory: ${{ github.workspace }}/terraform

    - name: Set up Python 3.7
      uses: actions/setup-python@v2
      with:
        python-version: 3.7

    - name: Install dependencies
      run: |
        python -m pip install --upgrade pip
        pip install boto ansible==2.9.2

    - name: Download privatekey
      run: aws ssm get-parameter --name "privatekey" --with-decryption | jq -r .Parameter.Value > ./privatekey
      working-directory: ${{ github.workspace }}/ansible

    - name: modify permission privatekey
      run: chmod 400 ./privatekey
      working-directory: ${{ github.workspace }}/ansible

    - name: open sg
      run:  aws ec2 authorize-security-group-ingress --group-id "$(cat ../terraform/group_id)" --protocol tcp --port 22 --cidr `curl inet-ip.info`/32
      working-directory: ${{ github.workspace }}/ansible

    - name: exec ansible
      run: ansible-playbook -i ec2.py sandbox.yml
      working-directory: ${{ github.workspace }}/ansible

    - name: close sg
      run:  aws ec2 revoke-security-group-ingress --group-id "$(cat ../terraform/group_id)" --protocol tcp --port 22 --cidr `curl inet-ip.info`/32
      working-directory: ${{ github.workspace }}/ansible

github-actions 結果

スクリーンショット 2020-05-29 2.07.50.png

[参考]
https://www.terraform.io/docs/github-actions/setup-terraform.html
https://github.com/aws-actions/configure-aws-credentials
https://docs.ansible.com/ansible/latest/user_guide/intro_dynamic_inventory.html

2
3
0

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
  3. You can use dark theme
What you can do with signing up
2
3