はじめに
JenkinsからAWS CloudFormationを利用しVPCを構築するサンプルです。JenkinsからAWS CLIを利用するやり方はたくさんあります。これはあくまでひとつの例です。
検証環境
OS: CentOS7
Jenkinsのバージョン: 2.1以降
必要なプラグイン: Jenkinsの初期設定画面でインストールされるプラグイン + Pipeline: AWS Steps
Jenkinsの設定
必要なパッケージ
Jenkinsサーバに以下のパッケージがインストールされている必要があります。
- Git
- AWS CLI
こちらのAnsible PlaybookでJenkinsを構築することも可能です。
Pipeline: AWS Stepsをインストールする
「Jenkinsの管理」→「プラグインの管理」→「利用可能タブ」から AWS CodePipeline を選択しインストールする(Jenkinsサーバ側ではプラグイン名が「Pipeline: AWS Steps」ではないので注意!)
このプラグインをインストールすると他の依存関係にあるプラグインもインストールされる

AWS Credentialsを登録する
-
AWSのIAMのコンソールでEC2とCloudFormationの実行権限を付与したアクセスキーを作成する
-
「認証情報」→「システム」→「 認証情報の追加」→「種類」から「AWS Credentials」を選択し「Access Key ID」と「Secret Access Key」を入力する
-
IDの部分は入力しない

JenkinsへPipelineファイルを登録する
こちらのPipelineファイルを登録していきます。
# !groovy
pipeline {
agent any
parameters {
string(
name: 'AWS_CREDENTIALS_ID',
defaultValue: '',
description: 'AWS credentials id, stored in Jenkins credentials'
)
string(
name: 'EXTRA_ARGS',
defaultValue: '',
description: 'aws cloudformation create-stack command extra arguments'
)
string(
name: 'GIT_BRANCHES_CFN',
defaultValue: '*/master',
description: "Git branch or tag name or commit id to retrieve of GIT_URL of CloudFormation template file"
)
string(
name: 'GIT_URL',
defaultValue: '',
description: "GitHub URL to retrieve CloudFormation template"
)
string(
name: 'REGION',
defaultValue: '',
description: 'AWS CLI region name'
)
string(
name: 'STACK_NAME',
defaultValue: '',
description: 'CloudFormation stack name'
)
string(
name: 'TEMPLATE_FILE_PATH',
defaultValue: '',
description: 'CloudFormation template file path'
)
string(
name: 'WORKING_DIR',
defaultValue: 'cfn',
description: 'Job working directory'
)
}
stages {
stage('Initialize wokring directory') {
steps {
dir ("${params.WORKING_DIR}") {
cleanWs()
}
}
}
stage('Retrieve CloudFormation template file from Github') {
steps {
checkout(
[
$class: 'GitSCM',
branches: [
[
name: "${params.GIT_BRANCHES_CFN}"
]
],
extensions: [
[
$class: 'RelativeTargetDirectory',
relativeTargetDir: "${params.WORKING_DIR}"
]
],
doGenerateSubmoduleConfigurations: false,
submoduleCfg: [],
userRemoteConfigs: [
[
url: "${params.GIT_URL}"
]
]
]
)
}
}
stage('Create Stack') {
steps {
withAWS(credentials:"${params.AWS_CREDENTIALS_ID}", region:"${params.REGION}") {
dir ("${params.WORKING_DIR}") {
// Create Stack
sh "aws cloudformation create-stack \
--stack-name ${params.STACK_NAME} \
--template-body file://${params.TEMPLATE_FILE_PATH} \
${params.EXTRA_ARGS}"
// Wait until Stack is created completely
sh "aws cloudformation wait stack-create-complete \
--stack-name ${params.STACK_NAME}"
// Print CloudFormation create command resutls
sh "aws cloudformation describe-stacks \
--stack-name ${params.STACK_NAME}"
}
}
}
}
}
}
- 「新規ジョブ作成」→パイプライン名を入力して「パイプライン」をクリック

- パイプラインで以下を設定
リポジトリURL
Script Path
create-stack/Jenkinsfile

Jobを実行する
作成したJobを一回空実行します。一度実行するとパラメータが指定できる様になります。

パラメータ設定例です。
AWS_CREDENTIALS_IDはJenkinsで発行される一意のIDです。
利用したCloudFormationテンプレートはこちらです。
AWSTemplateFormatVersion: '2010-09-09'
Parameters:
InstanceType:
Description: EC2 instance type
Type: String
Default: t2.micro
ConstraintDescription: must be a valid EC2 instance type.
KeyName:
Description: Name of an existing EC2 KeyPair to enable SSH access to the instances
Type: AWS::EC2::KeyPair::KeyName
ConstraintDescription: must be the name of an existing EC2 KeyPair.
Mappings:
StackConfigs:
VPC:
CidrBlock: 10.0.0.0/16
EnableDnsSupport: 'true'
EnableDnsHostnames: 'true'
PublicSubnet:
AvailabilityZone: "ap-northeast-1a"
CidrBlock: 10.0.1.0/24
Name: "10.0.1.0 - ap-northeast-1a"
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: !FindInMap [StackConfigs, VPC, CidrBlock]
EnableDnsSupport: !FindInMap [StackConfigs, VPC, EnableDnsSupport]
EnableDnsHostnames: !FindInMap [StackConfigs, VPC, EnableDnsHostnames]
Tags:
- Key: Name
Value: !Ref AWS::StackName
GatewayAttachment:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId:
Ref: VPC
InternetGatewayId:
Ref: InternetGateway
PublicSubnet:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: !FindInMap [StackConfigs, PublicSubnet, AvailabilityZone]
CidrBlock: !FindInMap [StackConfigs, PublicSubnet, CidrBlock]
MapPublicIpOnLaunch: 'true'
VpcId:
Ref: VPC
Tags:
- Key: Name
Value: !FindInMap [StackConfigs, PublicSubnet, Name]
centos7:
Type: AWS::EC2::Instance
DependsOn: InternetGateway
Properties:
BlockDeviceMappings:
- DeviceName: /dev/sda1
Ebs:
DeleteOnTermination: true
VolumeType: gp2
ImageId: ami-045f38c93733dd48d
InstanceType: !Ref 'InstanceType'
KeyName: !Ref 'KeyName'
SecurityGroupIds:
- !Ref sshSG
- !Ref httpSG
SubnetId:
Ref: PublicSubnet
Tags:
- Key: Name
Value: !Ref AWS::StackName
- Key: ansible_inventory_group_name
Value: centos7
- Key: ansible_user
Value: centos
- Key: ansible_port
Value: 22
sshSG:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: ssh
GroupDescription: SSH access rule
SecurityGroupIngress:
- CidrIp: 0.0.0.0/0
FromPort: 22
IpProtocol: tcp
ToPort: 22
VpcId:
Ref: VPC
httpSG:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: http
GroupDescription: http access rule
SecurityGroupIngress:
- CidrIp: 0.0.0.0/0
FromPort: 80
IpProtocol: tcp
ToPort: 80
VpcId:
Ref: VPC
InternetGateway:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: InternetGateway
PublicRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId:
Ref: VPC
Tags:
- Key: Name
Value: public
PublicRoute:
Type: AWS::EC2::Route
DependsOn: InternetGateway
Properties:
RouteTableId:
Ref: PublicRouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId:
Ref: InternetGateway
PublicSubnetRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId:
Ref: PublicSubnet
RouteTableId:
Ref: PublicRouteTable
Outputs:
VpcId:
Value: !Ref VPC
Jobを実行するとスタックが作成されます。
