LoginSignup
6
2

More than 5 years have passed since last update.

JenkinsとECSとSpot Fleetを使ってコンテナ上でJenkins Jobを実行する

Last updated at Posted at 2016-12-27

背景

クラウドサービスではインスタンスが時間課金のため、JenkinsなどのCIサーバを起動すると利用しない時間は無駄なコストが発生してしまいます。
コンバートなどの高負荷ジョブを実行している場合はインスタンスタイプも大きなものを用意する必要があるため、AWS Batchを利用したくなります。
AWS Batch – AWSでバッチ処理ジョブを実行する
ですが、AWS Batchはプレビューのため、申請しないと使うことができません。
そんな時、以下の二つの記事
Jenkinsのジョブの実行環境にAmazon EC2 Container Service ( ECS ) を活用
Spot FleetでAmazon ECSクラスタを強力に
を見つけたので、JenkinsとECSとSpot Fleetをうまく組み合わせられないかということで試してみました。

本記事で利用しているCFnテンプレートはGitHubで公開しています。
https://github.com/shigewa/jenkins-using-ecs-and-spotfleet

aws cliのバージョン確認

aws --version
aws-cli/1.11.32 Python/2.7.10 Darwin/15.6.0 botocore/1.4.89

構成概要

Jenkins&ECS&SpotFleet

Jenkinsインスタンス構築前の準備

SpotFleetが利用するIAMロール作成

  • SpotFleet初回利用時にデフォルトで作成されるIAMロールが存在するか確認
aws iam get-role \
         --role-name "aws-ec2-spot-fleet-role"

存在する場合は JenkinsインスタンスとECS Clusterが利用するIAMロールの作成 に進んでください。

  • デフォルトIAMロールを作成
aws cloudformation --region ap-northeast-1 create-stack \
--stack-name SpotFleetRole \
--capabilities CAPABILITY_NAMED_IAM \
--template-body file://create-spotfleet-role.yaml
  • ロールのARNを確認
SPOT_FLEET_ROLE_ARN=$( \
  aws iam get-role \
         --role-name "aws-ec2-spot-fleet-role" \
         --query "Role.Arn" \
         --output text \
) \
  && echo "${SPOT_FLEET_ROLE_ARN}"

JenkinsインスタンスとECS Clusterが利用するIAMロール、インスタンスプロファイルの作成

  • IAMロール名の決定
JENKINS_ROLE_NAME='Jenkins_Instance_Role'
  • 同じ名前のロールがないことを確認 既に存在する場合は別名にするもしくは IAMロールの確認作業 までスキップしてください。
aws iam get-role \
         --role-name ${JENKINS_ROLE_NAME}
  • IAMロールポリシーの決定 管理ポリシーを確認します。
aws iam list-policies \
        --scope AWS \
        --max-items 1000 \
        --query 'Policies[].PolicyName'

利用するポリシーを決めます。
以下は設定例です。

IAM_POLICY_NAME1='AmazonEC2FullAccess'
IAM_POLICY_NAME2='AmazonEC2ContainerServiceFullAccess'
  • IAMロールにアタッチするポリシーのARNを取得
IAM_POLICY_ARN1=$( \
  aws iam list-policies \
    --max-items 1000 \
    --query "Policies[?PolicyName==\`${IAM_POLICY_NAME1}\`].Arn" \
    --output text \
) \
  && echo "${IAM_POLICY_ARN1}"
IAM_POLICY_ARN2=$( \
  aws iam list-policies \
    --max-items 1000 \
    --query "Policies[?PolicyName==\`${IAM_POLICY_NAME2}\`].Arn" \
    --output text \
) \
  && echo "${IAM_POLICY_ARN2}"
aws cloudformation --region ap-northeast-1 create-stack \
--stack-name ${JENKINS_ROLE_NAME} \
--capabilities CAPABILITY_NAMED_IAM \
--template-body file://create-jenkins-instance-role.yaml \
--parameters \
ParameterKey=AttachJenkinsRoleARNs,ParameterValue="${IAM_POLICY_ARN1}\,${IAM_POLICY_ARN2} \
ParameterKey=RoleName,ParameterValue="{JENKINS_ROLE_NAME}"
  • 作成したIAMロールとインスタンスプロファイルのARNを確認
JENKINS_INSTANCE_PROFILE_ARN=$( \
  aws iam list-instance-profiles \
  --query "InstanceProfiles[?contains(Arn,\`${JENKINS_ROLE_NAME}\`)].Arn" \
  --output text \
  )
  && echo "${JENKINS_INSTANCE_PROFILE_ARN}"
JENKINS_ROLE_ARN=$( \
  aws iam list-instance-profiles \
  --query "InstanceProfiles[?contains(Arn,\`${JENKINS_ROLE_NAME}\`)].Roles[].Arn" \
  --output text \
  )
  && echo "${JENKINS_ROLE_ARN}"

結果が返却されない場合はCFnがスタック生成中の可能性がありますので、時間を置いて再実行してみてください。

Jenkinsインスタンスの構築

  • 以下の変数は実行環境に応じて修正してください。
REAGION="ap-northeast-1"
VPC_ID="hogehoge"
JENKINS_MASRER_SUBNET="fugafuga"
JENKINS_SLAVE_SUBNET='hoge\,fuga'
IAM_FLEET_ROLE_ARN=$( \
  aws iam get-role \
         --role-name "aws-ec2-spot-fleet-role" \
         --query "Role.Arn" \
         --output text \
) \
IAM_INSTANCE_PROFILE_ARN=$( \
  aws iam list-instance-profiles \
  --query "InstanceProfiles[?contains(Arn,\`${JENKINS_ROLE_NAME}\`)].Arn" \
  --output text \
  )
KEY_NAME="Jenkins_Using_ECS_and_SpotFleet"
MASTER_JENKINS_INSTNCE_TYPE="t2.micro"
SLAVE_JENKINS_SPOT_INSTANCE_TYPE="c3.large"
# Amazon Linux
MASTER_JENKINS_AMIID="ami-0c11b26d"
# ECS Optimized Amazon linux
SLAVE_JENKINS_AMIID="ami-08f7956f"
SLAVE_CAPACITY=1
MAX_SPOT_PRICE=0.128
  • Master Slave Jenkinsが通信するSGを作成
aws cloudformation --region ${REAGION} create-stack \
--stack-name JenkinsSG \
--template-body file://create-jenkins-sg.yaml \
--parameters ParameterKey=VpcId,ParameterValue=${VPC_ID}
  • Master Jenkinsインスタンスを作成 デフォルトでアタッチするSG等がある場合は create-jenkins-master-instance.yamlSecurityGroupIdsを修正してください
aws cloudformation --region ${REAGION} create-stack \
--stack-name JenkinsMasterStack \
--template-body file://create-jenkins-master-instance.yaml \
--parameters \
ParameterKey=VpcId,ParameterValue=${VPC_ID} \
ParameterKey=SubnetId,ParameterValue=${JENKINS_MASRER_SUBNET} \
ParameterKey=KeyName,ParameterValue=${KEY_NAME} \
ParameterKey=AmiId,ParameterValue=${MASTER_JENKINS_AMIID} \
ParameterKey=InstanceType,ParameterValue=${MASTER_JENKINS_INSTNCE_TYPE}
  • Slave Jenkins用のインスタンスとECS Clusterを作成 デフォルトでアタッチするSG等がある場合は create-spotfleet-jenkins-slave.yamlSecurityGroupsを修正してください
aws cloudformation --region ${REAGION} create-stack \
--stack-name SpotFleetJenkinsSlave \
--template-body file://create-spotfleet-jenkins-slave.yaml \
--parameters \
ParameterKey=MaxSpotPrise,ParameterValue=${MAX_SPOT_PRICE} \
ParameterKey=TargetCapacity,ParameterValue=${SLAVE_CAPACITY} \
ParameterKey=InstanceType,ParameterValue=${SLAVE_JENKINS_SPOT_INSTANCE_TYPE} \
ParameterKey=SpotFleetAMI,ParameterValue=${SLAVE_JENKINS_AMIID} \
ParameterKey=KeyName,ParameterValue=${Diffchecker_Jenkins} \
ParameterKey=IamFleetRoleARN,ParameterValue=${IAM_FLEET_ROLE_ARN} \
ParameterKey=SubnetId,ParameterValue=${JENKINS_SLAVE_SUBNET}

Jenkinsの初期設定

構築されたJenkins masterインスタンスにアクセスし、画面表示どおり /var/lib/jenkins/secrets/initialAdminPassword に書かれたパスワードを入力します。
特にこだわりの設定がない場合は「Install suggested plugins」を選択肢、デフォルトのプラグインをインストールします。
adminユーザー情報を入力します。

Jenkins pluginの導入

以下の手順に従ってECS pluginを導入し、指定するECS Clusterは上記で作成したECS Clusterを指定してください。
https://wiki.jenkins-ci.org/display/JENKINS/Amazon+EC2+Container+Service+Plugin

環境の削除

aws cloudformation --region ${REAGION} delete-stack \
--stack-name SpotFleetJenkinsSlave

aws cloudformation --region ${REAGION} delete-stack \
--stack-name JenkinsMasterStack

aws cloudformation --region ${REAGION} delete-stack \
--stack-name JenkinsSG

aws cloudformation --region ${REAGION} delete-stack \
--stack-name SpotFleetRole

備考

SpotFleetを利用しているため、 MAX_SPOT_PRICE が低すぎる場合はスポットインスタンスが起動できません。

参考URL

Jenkins Amazon EC2 Container Service Plugin
AWSで継続的インテグレーション 〜 Jenkins編 | アドカレ2013 : CFn #9
Jenkinsのジョブの実行環境にAmazon EC2 Container Service ( ECS ) を活用
[JAWS-UG CLI] IAM:#22 IAMロールの作成 (ECSコンテナインスタンス)
Spot FleetでAmazon ECSクラスタを強力に

6
2
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
6
2