日: 2018年8月18日

  • GitLabでCIを動かす

    GitLabでCIを動かす

    はじめに

    Gitと連携させCIを動かす事が増えて来た。GitHubと連携させTravis CIもいいし、Circle CIもいいだろう。GitLab CIのいいところは、自前で環境さえ準備できさえすれば非常に低コスト(IaaSの運用コストのみ)で動かす事ができるのが魅力だ

    設定方法

    前提条件

    GitLabが動作できていること

    本手順は、GitLab 10.3.7を前提としている

    GitLabの設定

    GitLabの左メニューで Settings -> CI/CDを選択する

    General piplines settingsで
    「Instance default」を選択し、Runner Tokenをひかえる

     

    CIサーバ側の設定

    GitLab CIサーバでGitLab runnerの設定をいれる

    # sudo gitlab-runner register
    
    Running in system-mode.
    
    Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com/):
    https://git.sumito.jp/
    Please enter the gitlab-ci token for this runner:
    SJxxxxxxxxxxxx
    Please enter the gitlab-ci description for this runner:
    [server]: projectA
    Please enter the gitlab-ci tags for this runner (comma separated):
    
    Whether to lock the Runner to current project [true/false]:
    [true]: true
    Registering runner... succeeded runner=xxxxxxx
    Please enter the executor: parallels, ssh, virtualbox, docker+machine, docker-ssh+machine, docker, docker-ssh, shell, kubernetes:
    shell
    Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!

     

    automatically reloaded!と表示されれば設定は問題ない

    .gitlab-ci.ymlの設定

    .gitlab-ci.yml 
    variables:
    AMI_ID_KUSANAGI: "ami-123456"
    INSTANCE_NAME: "${CI_COMMIT_REF_NAME}_${CI_COMMIT_SHA}_${CI_PIPELINE_ID}"
    TMP_ANSIBLE_DIR: "/tmp/gitlab/${CI_COMMIT_SHA}/${CI_PIPELINE_ID}"
    DEPLOY_SITE: "wordpress"
    SSH_KEY_NAME: "ssh-key"
    INSTANCE_LOG: "/tmp/gitlab/${CI_COMMIT_SHA}/${CI_PIPELINE_ID}/run-instances.json"
    ALLOCATE_ADDRESS_LOG: "/tmp/gitlab/${CI_COMMIT_SHA}/${CI_PIPELINE_ID}/allocate-address.json"
    
    stages:
    - initial
    - build
    - test
    - deploy
    - cleanup
    
    ########################################################
    # STAGE:ANCHORS #
    ########################################################
    
    # These are hidden jobs that contain the anchors
    .server_group_1:
    only: &kusanagi_servers
    /^(wordpress).*$/
    
    ########################################################
    # STAGE:INITIAL #
    ########################################################
    make_tmp_directory:
    stage: initial
    script:
    - mkdir -p ${TMP_ANSIBLE_DIR}
    
    # デプロイテスト用インスタンスを作成@kusanagi& t2.medium
    run_aws_server_kusanagi:
    stage: build
    only:
    - *kusanagi_servers
    script:
    # インスタンスを作成
    - aws ec2 run-instances --key-name ${SSH_KEY_NAME} --image-id ${AMI_ID_KUSANAGI} --count 1 --instance-type t2.medium --security-group-ids sg-12345678 --subnet-id subnet-12345678> ${INSTANCE_LOG}
    # インスタンスにタグ付け
    - instance_id=`jq -r .Instances[].InstanceId ${INSTANCE_LOG}`
    - aws ec2 create-tags --resources $instance_id --tags Key=Name,Value=${INSTANCE_NAME}
    # ElasticIPを払い出してタグ付け
    - aws ec2 allocate-address --domain vpc > ${ALLOCATE_ADDRESS_LOG}
    - allocation_id=`jq -r .AllocationId ${ALLOCATE_ADDRESS_LOG}`
    - aws ec2 create-tags --resources $allocation_id --tags Key=Name,Value=${INSTANCE_NAME}
    # インスタンスのステータスがrunningになるまで待つ
    - i=1; while [ $i -le 120 ]; do sleep 3; if [ "\"running\"" = `aws ec2 describe-instances --instance ${instance_id} | jq '.Reservations[].Instances[].State.Name'` ]; then break; fi; i=$(expr $i + 1); done
    # ElasticIPをインスタンスに紐付け
    - aws ec2 associate-address --allocation-id ${allocation_id} --instance ${instance_id}
    
    # Ansible Playbookをgit clone
    setup_git:
    stage: build
    script:
    - cd ${TMP_ANSIBLE_DIR}
    - git clone git@git.sumito.jp:sumito/projectA.git
    - cd projectA
    - git checkout ${CI_COMMIT_REF_NAME}
    
    ########################################################
    # STAGE:TEST #
    ########################################################
    # 全てのAnsible Playbookの構文チェック
    check_syntax_ansible:
    stage: test
    before_script:
    - sed -e s%__ROLES_PATH__%${TMP_ANSIBLE_DIR}/projectA/Ansible/roles%g /home/gitlab-runner/.ansible_template.cfg > /home/gitlab-runner/.ansible.cfg
    - cd ${TMP_ANSIBLE_DIR}/projectA/Ansible
    script:
    - ansible-playbook -i inventories/staging/hosts sites/staging/wordpress.yml --syntax-check
    
    ########################################################
    # STAGE:DEPLOY #
    ########################################################
    # Ansible Deployを実行
    execute_ansible:
    stage: deploy
    only:
    - *kusanagi_servers
    before_script:
    - elastic_ip=`jq -r .PublicIp ${ALLOCATE_ADDRESS_LOG}`
    - cd ${TMP_ANSIBLE_DIR}/projectA/Ansible
    - sed -si -e s/__IP__/${elastic_ip}/g -e s%__KEY__%/home/gitlab-runner/.ssh/${SSH_KEY_NAME}%g inventories/staging/hosts
    - sleep 20
    script:
    - ansible-playbook -i inventories/staging/hosts sites/staging/${DEPLOY_SITE}.yml -u sumito --limit ${DEPLOY_SITE} --vault-password-file=/home/gitlab-runner/.vault_password
    
    ########################################################
    # STAGE:CLEANUP #
    ########################################################
    # Deployテストしたサーバリソースを削除@on_success
    remove_aws_server_success:
    stage: cleanup
    only:
    - *kusanagi_servers
    before_script:
    - instance_id=`jq -r .Instances[].InstanceId ${INSTANCE_LOG}`
    script:
    - sh /home/gitlab-runner/bin/aws/terminate-instance.sh $instance_id
    after_script:
    - rm -rf ${TMP_ANSIBLE_DIR}
    
    # Deployテストしたサーバリソースを削除@on_failure
    remove_aws_server_manual:
    stage: cleanup
    only:
    - *kusanagi_servers
    before_script:
    - instance_id=`jq -r .Instances[].InstanceId ${INSTANCE_LOG}`
    script:
    - sh /home/gitlab-runner/bin/aws/terminate-instance.sh $instance_id
    after_script:
    - rm -rf ${TMP_ANSIBLE_DIR}
    when: manual

    どのように動くか

    今回実施したPipelineは

    “`
    stages:
    – initial
    – build
    – test
    – deploy
    – cleanup
    “`

    の順番で処理が行われるよう骨格を作った。

    AWSのインスタンスをたちあげ、環境をセットアップし、ansibleを流す。最後にはテストで使ったイメージを削除するPipeline
    gitにpushする度にCIが動くようになり、品質が担保できるようになった。