OSS 버전 drone 0.4 + terraform으로 인프라 CI

개요



drone0.4의 terraform plugin으로 인프라 CI
  • 리포지토리는 Github의 개인 리포지토리를 만듭니다
  • 배포 대상은 AWS

  • drone 0.4의 환경 구축에 대해서는 이전 기사 참조

    terraform plugin에 대한 자세한 내용은 여기

    전제


  • drone OAuth applications 등록됨
  • terraform의 tfstate는 S3에서 관리한다

  • 준비



    리포지토리 만들기
    Github에서 CI에 대한 새 리포지토리 만들기


    리포지토리 Activate
    Drone에 액세스하여 만든 리포지토리를 선택하고 Activate


    Deploy Key는 자동으로 등록되므로 Github, Drone 설정은 이제 완료

    S3 Bucket 만들기



    tfstate 관리를 위한 S3 Bucket 만들기
    $ aws s3 mb s3://quickguard-terraform-config
    

    secret variable 작성



    Drone 화면의 SECRETS에서 환경 변수를 입력하여 secret variable을 만듭니다.



    환경 변수 내용
  • AWS_ACCESS_KEY_ID
  • AWS_SECRET_ACCESS_KEY
  • AWS_DEFAULT_REGION
  • SSH_KEY_NAME : EC2 인스턴스에 설정 SSH Key Name
  • TFSTATE_BUCKET : tfstate 관리용 S3 Bucket Name
  • TFSTATE_KEY : tfstate Name

  • 생성 된 secret variable을 .drone.sec 파일로 저장하고 커밋하십시오.
    $ git add .drone.sec
    $ git commit -m "[CI SKIP]added .drone.sec file"
    

    .drone.yml 만들기



    .drone.yml
    build:
      image: docker-registry:5000/terraform
      environment:
        - AWS_ACCESS_KEY_ID=$$AWS_ACCESS_KEY_ID
        - AWS_SECRET_ACCESS_KEY=$$AWS_SECRET_ACCESS_KEY
        - AWS_DEFAULT_REGION=$$AWS_DEFAULT_REGION
        - SSH_KEY_NAME=$$SSH_KEY_NAME
        - TFSTATE_BUCKET=$$TFSTATE_BUCKET
        - TFSTATE_KEY=$$TFSTATE_KEY
      commands:
        - cd $DRONE_DIR
        - rm -rf .terraform
        - terraform remote config -backend=s3 -backend-config=region=${AWS_DEFAULT_REGION} -backend-config=bucket=${TFSTATE_BUCKET} -backend-config=key=${TFSTATE_KEY}
        - terraform remote pull
        - terraform plan -var access_key=${AWS_ACCESS_KEY_ID} -var secret_key=${AWS_SECRET_ACCESS_KEY} -var region=${AWS_DEFAULT_REGION} -var key_name=${SSH_KEY_NAME}
      when:
        branch: "!master"
    
    deploy:
      terraform:
        plan: false
        sensitive: true
        remote:
          backend: S3
          config:
            access_key: $$AWS_ACCESS_KEY_ID
            secret_key: $$AWS_SECRET_ACCESS_KEY
            region: $$AWS_DEFAULT_REGION
            bucket: $$TFSTATE_BUCKET
            key: $$TFSTATE_KEY
        vars:
          access_key: $$AWS_ACCESS_KEY_ID
          secret_key: $$AWS_SECRET_ACCESS_KEY
          region: $$AWS_DEFAULT_REGION
          key_name: $$SSH_KEY_NAME
        when:
          branch: master
    

    ※image 는 alpine 을 베이스로 terraterm 0.6.11 을 인스톨 한 컨테이너를 사용
    terraform plan 는 master branch 이외에 commit 되었을 때에 실행
    terraform apply 는 master branch 에 commit 시에만 실행

    테스트시 terraform 컨테이너의 Dockerfile은 다음과 같습니다.

    Dockerfile
    FROM alpine:3.2
    
    ENV TERRAFORM_VERSION 0.6.11
    
    RUN apk add --update wget bash git perl libxml2-utils openssh ca-certificates unzip && \
        wget -q "https://circle-artifacts.com/gh/andyshinn/alpine-pkg-glibc/6/artifacts/0/home/ubuntu/alpine-pkg-glibc/packages/x86_64/glibc-2.21-r2.apk" && \
        apk add --allow-untrusted glibc-2.21-r2.apk && \
        wget -q -O /terraform.zip "https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_linux_amd64.zip" && \
        unzip /terraform.zip -d /bin && \
        apk del --purge wget ca-certificates unzip && \
        rm -rf /var/cache/apk/* glibc-2.21-r2.apk /terraform.zip
    
    VOLUME ["/data"]
    
    WORKDIR /data
    
    ENTRYPOINT ["/bin/terraform"]
    
    CMD ["--help"]
    
    .drone.sec 파일 및 .drone.yml 파일을 리포지토리에 커밋합니다.
    (terraform 코드가 아직 없으므로 commit 메시지에 [CI SKIP]를 입력하여 건너 뜁니다)

    인프라 CI 시도



    terraform 의 코드는 우선 example 를 적당히 수정해 작성

    main.tf
    provider "aws" {
        access_key = "${var.access_key}"
        secret_key = "${var.secret_key}"
        region = "${var.region}"
    }
    
    resource "aws_eip" "default" {
      instance = "${aws_instance.web.id}"
      vpc = true
    }
    
    resource "aws_security_group" "default" {
      name = "eip_example"
      description = "Used in the terraform"
    
      ingress {
        from_port = 22
        to_port = 22
        protocol = "tcp"
        cidr_blocks = ["0.0.0.0/0"]
      }
    
      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"]
      }
    }
    
    resource "aws_instance" "web" {
      instance_type = "t2.micro"
      ami = "${lookup(var.aws_amis, var.region)}"
      key_name = "${var.key_name}"
      security_groups = ["${aws_security_group.default.name}"]
    
      user_data = "${file("userdata.sh")}"
      tags {
        Name = "eip-example"
      }
    }
    

    outputs.tf
    output "address" {
      value = "${aws_instance.web.private_ip}"
    }
    output "elastic ip" {
      value = "${aws_eip.default.public_ip}"
    }
    

    variables.tf
    variable "access_key" {
      description = "AWS access key"
    }
    
    variable "secret_key" {
      description = "AWS secret key"
    }
    
    variable "region" {
      description = "The AWS region to create things in."
    }
    
    # ubuntu-trusty-14.04 (x64)
    variable "aws_amis" {
      default = {
        "ap-northeast-1" = "ami-a21529cc"
      }
    }
    
    variable "key_name" {
      description = "Name of the SSH keypair to use in AWS."
    }
    

    userdata.sh
    #!/bin/bash -v
    apt-get update -y
    apt-get install -y nginx > /tmp/nginx.log
    

    적당한 branch 작성해 terraform 의 코드를 push ,`Pull Request 를 작성한다



    테스트 (terraform plan) 결과


    문제가 없으면 Merge

    terraform apply 결과


    terraform의 output도 확인할 수 있다

    좋은 웹페이지 즐겨찾기