環境
macOS Big Sur バージョン11.2.2
構成図
今回やること
上記図の左側にあるEC2A(Jenkins Server)の環境をCloudFormationで作成します。
(一度、手動で作成してみることをお勧めします)
この構成図の全体の作成の流れについては別記事を参照してください
簡単に作成するリソースの説明
・VPC
・IGW(インターネットゲートウェイ)
・VPCGatewayAttachment(VPCとIGWの接続)
・パブリックサブネット
・RouteTable
・SubnetRouteTableAssociation(ルートテーブルにパブリックサブネットの紐付け)
・Route(ルートテーブルとIGWの紐付け)
・EC2(ユーザーデータで Jenkins,Ansibleのインストール)
・セキュリティグループ
・IamUser(Jenkinsユーザーの作成)
それでは早速見ていきましょう!
Parameters
AWSTemplateFormatVersion: 2010-09-09
Parameters:
StackEnv:
Description: Stack Environment
Type: String
LatestAmiId:
Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2
KeyName:
Description: The EC2 Key Pair to allow SSH access to the instance
Type: AWS::EC2::KeyPair::KeyName
解説:
パラメータの設定は自由ですが、個人で判断して必要なら作成してください。
使いこなすと、より容易にセキュアにテンプレートが作成できます。
【StackEnv】
スタック作成時に環境(Dev、Staging、Prov)を指定します。
【LatestAmiId】
AWS固有のSSMパラメータで、最初からAWSで設定してあるSSMパラメータを使用しています。
デフォルトで指定しているのは最新のAMIのEC2です。
【KeyName】
スタック作成時にEC2のキーペア名を指定します。
Resources
Resources:
myVPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
EnableDnsSupport: true
Tags:
- Key: Name
Value: !Sub "${StackEnv}-vpc"
IGW:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: !Sub "${StackEnv}-igw"
VPCAttachGateway:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref myVPC
InternetGatewayId: !Ref IGW
PublicSubnet1a:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: ap-northeast-1a
VpcId: !Ref myVPC
CidrBlock: 10.0.0.0/24
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: !Sub "${StackEnv}-public-subnet1a"
RouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref myVPC
Tags:
- Key: Name
Value: !Sub "${StackEnv}-routetable"
SubnetRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnet1a
RouteTableId: !Ref RouteTable
Route:
Type: AWS::EC2::Route
Properties:
RouteTableId: !Ref RouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref IGW
解説:
「簡単に作成するリソースの説明」で述べた通りに作成してます。
実際に手動で作成したらそれぞれの繋がりがよくわかると思います。
特に難しいことはやっておらず、必要最低限の設定なのでサブネットも一つだけです。
・タグを付けられるものに関しては、Parameterで設定しておいたStackEnvの値を変数として定義しています。
・!Ref関数を使えばテンプレ内のリソースを論理名(myVPCなど)を使用して使いまわせるので便利です。
・論理名の名前は好きな名前でOKです。ただし、わかりやすい名前にしましょう。
EC2
EC2a:
Type: AWS::EC2::Instance
Properties:
SubnetId: !Ref PublicSubnet1a
AvailabilityZone: ap-northeast-1a
KeyName: !Ref KeyName
ImageId: !Ref LatestAmiId
InstanceType: t2.medium
Monitoring: false
SecurityGroupIds:
- !Ref SecurityGroup
UserData: !Base64 |
#!/bin/bash -ex
sudo yum update -y
sudo amazon-linux-extras install -y ansible2
sudo yum install -y java-1.8.0-openjdk-devel.x86_64
sudo wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat/jenkins.repo
sudo rpm --import https://pkg.jenkins.io/redhat/jenkins.io.key
sudo yum install -y jenkins git
sudo systemctl start jenkins
Tags:
- Key: Name
Value: !Sub "${StackEnv}-ec2a"
解説:
【InstanceType】
t2.microだとJenkinsでAnsibleなど色々構築する際にスペックが低すぎてサーバーが落ちることがあるそうです。
t2.mediumか低くてもt2.small以上が無難らしいです。
【UserData】
ここでEC2起動時に記載したコマンドが発動します。
見ての通り、yum updateから
・ansible
・Jenkinsのインストールに必要なjava
・Jenkinsをインストールするためのリポジトリのダウンロード
・Jenkinsのインストール
・gitと連携するためにgitのインストール
・Jenkinsの起動
上記の操作をコマンドで打ち込んでいます。
手動でやる手間が省けるので、便利です。
*UserDataのコードがうまく機能してなかったら、下記のコードでEC2立ち上げた時のログが見れます。
sudo cat /var/log/cloud-init-output.log
SecurityGroup
SecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: ec2 for jenkins
VpcId: !Ref myVPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
Description: for http
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 0.0.0.0/0
Description: for ssh
- IpProtocol: tcp
FromPort: 8080
ToPort: 8080
CidrIp: 0.0.0.0/0
Description: for jenkins
SecurityGroupEgress:
- IpProtocol: -1
CidrIp: 0.0.0.0/0
Tags:
- Key: Name
Value: !Sub "${StackEnv}-ec2sg"
解説:
SecurityGroupIngressがインバウンド、SecurityGroupEgressがアウトバウンドです。
HTTP 80
SSH 22
Jenkins 8080
それぞれのポートをオープンにしています。
・ IpProtocol: -1
全てのプロトコルを指定しています。
つまりここではアウトバウンドはフルオープンと言うことですね。
IamUser
JenkinsUser:
Type: AWS::IAM::User
Properties:
LoginProfile:
Password: '{{resolve:ssm-secure:test2:1}}'
Policies:
- PolicyName: AdministratorAccess
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- '*'
Resource:
- '*'
Tags:
- Key: Name
Value: !Sub "${StackEnv}-jenkinsuser"
UserName: jenkins-from-cfn
解説:
IamUserの作成です。
*本来なら必要な権限だけ与えるべきですが、ここではとりあえずサーバーを作って動作させることが目的だったため、フル権限を付与してます。
ここではjenkins-from-cfn
というUSERNAMEにしています。
Passwordに関しては、AWS Systems ManagerのSSM Secure Stringパラメータを使用しています。
このパラメータの使用方法として、
1、まずはAWS Systems Managerでパラメータを作成する必要があります。
(コンソールからでもCLIからでも作れます)
2、作成したパラメータの名前とバージョンをテンプレに代入して貼り付けるだけです。
*パラメータの種類には
・SSMパラメータ(String型、StringList型)
・SSM String Secureパラメータ
があります。
今回僕が使用したのはSSM String Secureパラメータなので、
'{{resolve:ssm-secure:parameter-name:version}}'
に当てはめてコードを記述しています。
参考にした記事