Cloudプロビジョニングツール
AWS、Microsoft Azure、GoogleCloud Platformなどパブリッククラウドが台頭してきて
それに追従するよういろいろなプロビジョニングツールが出てきた
その他プロビジョニングのみにとどまらず、SaaSサービスでは色々ある
ただどれもクラウド基盤側の仕様に左右されたり、追従対応速度にはどうしても上手く行かない部分がある
マルチクラウドでも利用、検討してない限りは実際に使うクラウド環境をある程度決め打ちして
そこに適した提供ツールを利用するのがいいんじゃないかな
仕事で使う AWS について考えていく
AWS CDK
AWSで IaC を行おうとすると CLoudFormation になるが 独自仕様、構文になっていて学習コストがかかる割にはそこまで IaC 感が無い
そこで登場したのが AWS CDK
いい感じにマニュアルがあるのでそれに習って進めていく
PREREQUISITES FOR THE WORKSHOP
IAM アカウントの用意
CDKが利用する AIM アカウントを作成しておく
管理ポリシー
- AWSCloudFormationFullAccess
インラインポリシー
CloudFormation でサービスデプロイしようとするとそれなりに強い権限をもたせる必要がある
CloudFormation は 管理ポリシーでフルアクセス権限を設定し、個別サービスについてはインラインポリシーで権限を限定する
CloudFormation 経由の場合のみその権限を使えるよう下記を参考にインラインポリシーを設定しておく
AWSサービスによって呼び出されるアクションの最小特権アクセス許可を定義する方法
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"cloudformation:CreateStack",
"cloudformation:Describe*",
"cloudformation:Validate*",
"cloudformation:Update*",
"cloudformation:List*",
"cloudformation:GetT*",
"cloudformation:CreateChangeSet",
"cloudformation:ExecuteChangeSet",
"cloudformation:DeleteChangeSet",
"iam:Get*",
"iam:Create*",
"iam:Attach*",
"iam:Add*",
"iam:PassRole",
"iam:DeleteRole",
"iam:DetachRolePolicy",
"iam:PutRolePolicy",
"iam:DeleteRolePolicy",
"iam:RemoveRoleFromInstanceProfile",
"iam:DeleteInstanceProfile",
"logs:*",
"ssm:Get*"
],
"Resource": "*",
"Condition": {
"ForAnyValue:StringEquals": {
"aws:CalledVia": [
"cloudformation.amazonaws.com"
]
}
}
}
]
}
CDK、どんな環境でも標準的に必要になりそうな権限を CDK ロールみたいの作っておいて
環境毎に必要な各種他サービスの権限は別ロールかグループで付与してって管理したほうが使い勝手良さそう
CDK のインストール
作業環境は Windows
npm install -g aws-cdk
AWS Credential の設定
CDKを使うのであれば 別 IAM を用意し、環境毎に使い分ける事になりそうなので profile をちゃんと指定しておく
aws configure --profile hogehoge
AWS Access Key ID [None]:
AWS Secret Access Key [None]:
Default region name [None]: ap-northeast-1
Default output format [None]: json
cli で利用する AWS Credential を指定しておく
setx AWS_PROFILE hogehoge
IDE環境の準備
AWS の製品ページで IDE とツールとして下記がおすすめされていたのでインストールしておく
AWS Toolkit for Visual Studio Code
プロジェクトの作成
CDKで対応している言語は下記
- JavaScript, TypeScript (Node.js ≥ 10.3.0)
- Python (Python ≥ 3.6)
- Java (Java ≥ 8 and Maven ≥ 3.5.4)
- .NET (.NET Core ≥ 3.0)
初期化
mkdir test
cd test
cdk init --language typescript
# Welcome to your CDK TypeScript project!
This is a blank project for TypeScript development with CDK.
The `cdk.json` file tells the CDK Toolkit how to execute your app.
## Useful commands
* `npm run build` compile typescript to js
* `npm run watch` watch for changes and compile
* `npm run test` perform the jest unit tests
* `cdk deploy` deploy this stack to your default AWS account/region
* `cdk diff` compare deployed stack with current state
* `cdk synth` emits the synthesized CloudFormation template
git化もしとこうかな
git init
初期化された内容は下記のようになっている
|- bin/
|- lib/
|- node_modules/
|- test/
|- .gitignore
|- .npmignore
|- cdk.json
|- jest.config.js
|- package.json
|- README.md
|- tsconfig.json
マニュアルに簡単に説明があり
lib/cdk-workshop-stack.ts
CDKアプリケーションのメインスタックが定義される場所bin/cdk-workshop.ts
CDKアプリケーションのエントリポイント、lib/cdk-workshop-stack.ts
で定義された内容をロードしますpackage.json
npmモジュールのマニフェストcdk.json
ツールキットにアプリの実行方法を指示tsconfig.json
プロジェクトのタイプスクリプト設定
サンプルのアプリケーションスタックファイルを見てみる
import * as cdk from '@aws-cdk/core';
export class StudyStack extends cdk.Stack {
constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// The code that defines your stack goes here
}
}
なんもねぇ
のでマニュアルのを参考にしておく
コードのコンパイル
TypeScriptにて記述した場合変更を加えるたびにソースをコンパイルする必要がある
そのため、自動的にコンパイルしてくれるよう監視サービスを実行しておくことも出来る
監視処理の実行には別ターミナルで立ち上げましょう
npm run watch
[18:40:18] Starting compilation in watch mode...
[18:40:23] Found 0 errors. Watching for file changes.
構文エラーもここでわかるので基本的にはずっと立ち上げておく
準備
bootstrap のインストール
> cdk bootstrap
⏳ Bootstrapping environment aws://**************/ap-northeast-1...
CDKToolkit: creating CloudFormation changeset...
0/2 | 13:13:18 | CREATE_IN_PROGRESS | AWS::CloudFormation::Stack | CDKToolkit User Initiated
0/2 | 13:13:21 | CREATE_IN_PROGRESS | AWS::S3::Bucket | StagingBucket
0/2 | 13:13:22 | CREATE_IN_PROGRESS | AWS::S3::Bucket | StagingBucket Resource creation Initiated
1/2 | 13:13:44 | CREATE_COMPLETE | AWS::S3::Bucket | StagingBucket
2/2 | 13:13:46 | CREATE_COMPLETE | AWS::CloudFormation::Stack | CDKToolkit
✅ Environment aws://**************/ap-northeast-1 bootstrapped.
**************************************************
*** Newer version of CDK is available [1.32.2] ***
*** Upgrade recommended ***
**************************************************
このへんで AWS Cli の Credential 情報も読み込まれてる感じ
bootstrap を実行すると AWS 上に CDKToolkit という CloudFormationStack と S3 のバケットが作成される
CDK Package.json の修正
CDKは今現在も開発が頻繁でマイナーバージョンが毎週のように変わる
なのでCDK書きながら次の週に新しいサービスを定義しようとモジュール追加するとバージョンがずれてエラーが出たりする
なのでそうならないよう package.json
で CDK関連のバージョンは固定するか、常にアップデートするようにしておく
※デフォルトで CDK だけ インストール時の固定バージョンになってるのが悪い
ここでは検証なので常に最新化 ^
するようにしておく
$ vim package.json
"devDependencies": {
"@aws-cdk/assert": "^1.54.0",
"@types/jest": "^25.2.1",
"@types/node": "10.17.5",
"aws-cdk": "^1.53.0",
"jest": "^25.5.0",
"ts-jest": "^25.3.1",
"ts-node": "^8.1.0",
"typescript": "~3.7.2"
},
"dependencies": {
"@aws-cdk/aws-ec2": "^1.54.0",
"@aws-cdk/aws-efs": "^1.54.0",
"@aws-cdk/aws-elasticloadbalancingv2": "^1.54.0",
"@aws-cdk/aws-elasticloadbalancingv2-targets": "^1.54.0",
"@aws-cdk/aws-iam": "^1.54.0",
"@aws-cdk/aws-s3": "^1.54.0",
"@aws-cdk/core": "^1.54.0",
"source-map-support": "^0.5.16"
}
コードを書いて行く中でバージョンが変わってったら都度都度アップデートして対応しいく
> npm update -g aws-cdk
> npm update
コードを書く
AWS CDK API Reference
CDKのドキュメントを見ながら EC2 を立ててみる
AWSアカウント情報の読み込み
新規でまっさらな状況から作るというわけでもない限り、既存のAWSアカウントと環境情報を読み込ませる
$ vim bin/test.ts
const app = new cdk.App();
new TestStack(app, 'TestStack', {
// import aws account info
env: {
account: process.env.CDK_DEFAULT_ACCOUNT,
region: process.env.CDK_DEFAULT_REGION
}
});
キーペアの作成
EC2で利用するキーペアは事前にコンソールで作成、登録しておく
VPCの作成
VPCはすでにあるVPC上に立てたいので既存の環境を利用する
$ vim lib/test-stack.ts
// Import VPC
let myVpc = ec2.Vpc.fromLookup(this, 'VPC', { vpcId: 'vpc-****' });
// Import Subet
let myPrivateSubnet1 = ec2.Subnet.fromSubnetAttributes(this, 'PrivateSubnet1', {
subnetId: 'subnet-****',
availabilityZone: 'ap-northeast-1c',
routeTableId: 'rtb-****',
});
let myPrivateSubnet2 = ec2.Subnet.fromSubnetAttributes(this, 'PrivateSubnet2', {
subnetId: 'subnet-****',
availabilityZone: 'ap-northeast-1a',
routeTableId: 'rtb-****',
});
セキュリティグループの作成
EC2用の新規セキュリティグループを作成
$ vim lib/test-stack.ts
// Create Ec2 security group
let mySecurityGroup = new ec2.SecurityGroup(this, 'SecurityGroup', {
vpc: myVpc,
description: `${projectName} Server Side SecurityGroup`,
securityGroupName: `${projectName}-ec2-sg`,
allowAllOutbound: true
});
mySecurityGroup.addIngressRule(ec2.Peer.ipv4('172.25.0.0/16'), ec2.Port.allTcp(), 'All VPC');
EC2用サービスロールの作成
EC2で利用するサービスロールを作成
$ vim lib/test-stack.ts
// Create Ec2 service role
let myRole = new iam.Role(this, 'Ec2role', {
assumedBy: new iam.ServicePrincipal('ec2.amazonaws.com'),
roleName: `${projectName}-ec2-role`,
});
AMIの定義
EC2で利用するAMIを定義
ここでは公式の AmazonLinux2 を利用
$ vim lib/test-stack.ts
// Set AMI
let myAMI = new ec2.AmazonLinuxImage({
generation: ec2.AmazonLinuxGeneration.AMAZON_LINUX_2,
edition: ec2.AmazonLinuxEdition.STANDARD,
virtualization: ec2.AmazonLinuxVirt.HVM,
storage: ec2.AmazonLinuxStorage.GENERAL_PURPOSE,
});
似たようなので ec2.MachineImage.latestAmazonLinux
もありこちらは常に最新のAMIを利用したい場合に利用する
もちろん常になので新シAMIのバージョンが出たら deploy したタイミング等で EC2 の置き換えが発生する
こちらを利用したい場合はそもそもの EC2 運用からちゃんと考えよう
じゃないと事故る(事故った)
怖い人は CDK で EC2 作成後に削除保護を必ず有効化しておこう
EC2の作成
EC2作成したいだけなのに VPC、IAM、等々一通りの準備に手間がかかる
最後に 使う KeyPair、インスタンスタイプ、EBSのサイズを指定
$ vim lib/test-stack.ts
// InstanceType
let myInstanceType = new ec2.InstanceType(ec2InstanceType);
// Keypair
let myKey = keyPair;
// EBS
let myEBS = ec2.BlockDeviceVolume.ebs(50);
// Create EC2
let myInstance1 = new ec2.Instance(this, 'Instance1', {
instanceType: myInstanceType,
machineImage: myAMI,
vpc: myVpc,
instanceName: `${projectName}-01`,
keyName: myKey,
role: myRole,
securityGroup: mySecurityGroup,
blockDevices: [
{
deviceName: '/dev/xvda',
volume: myEBS,
}
],
vpcSubnets: {
subnets: [myPrivateSubnet1],
},
});
myInstance2.addUserData(
"yum check-update -y",
"yum upgrade -y",
);
myRole.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonEC2FullAccess'));
myRole.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AmazonEC2RoleforSSM'));
7/30 ここで EC2 の削除保護有効化とか出来ればいいんだけど標準APIの方には無いみたいだ
また CDK のエラーは本当に親切じゃない
IAM の権限が足らない場合はある程度わかるようになってるが、それ以外は下記のようなエラーになっていて何が問題か分からない
The requested configuration is currently not supported. Please check the documentation for supported configurations. (Service: AmazonEC2; Status Code: 400; Error Code: Unsupported; Request ID:
57477a70-e44e-4f3c-b606-2ab180098516)
例えば上記の問題は Cfn ではまだ東京リージョンではサポートされていないインスタンスタイプを指定したためだった
※リージョン自体には対応していてコンソール上は選択できる
こういうのが出ると調査にめやくちゃ時間かかるので将来に期待したい
※同様に AWS Backup は Vault の作成でどうにもこうにもコケるため諦めた
Taging
$ vim lib/test-stack.ts
// Taging
cdk.Tag.add(this, tagKey, tagValue);
ここまで定義して npm run watch
上でエラーがなければデプロイに進める
デプロイ
CDKの定義を Cfn 化
> cdk synth
ここでも構文チェックを行ってくれる
そしてデプロイされる内容、変更箇所を確認し
> cdk diff
問題なければデプロイ
> cdk deploy
7/30 中途半端に下書きしていたやつを間違って公開してしまっていたため加筆修正
基本は CloudFormation を好きな言語で書ける!なので Cfn 自体のメリット、デメリットはそのままある
シンプルな分変数の再利用や環境別の分け方などは自身で上手くやる方法を見つけるしか無い-c
オプションがあるのでなんとかはなりそうだけど
とりあえず Typescript らしさはかけらもないベタ書きになってしまっているのでなんとかこのへんはスマートにしたいな
とにかくまだ絶賛開発中という印象
毎週リリースがあるのもちろん、開発中の定義だよというのがいろんなサービスのAPIにあるし
ドキュメント自体もそこまで親切じゃない
CDKの記事とか調べてると Cfn~ のクラスを利用している人が多いがそちらのほうが安定しているし
Cfn ベースなので定義できることもなんかエラーで出来ないという事が少ないからのよう
でもそれだったら CDK の価値が…と思って意地でもなるべく使わないようにしてみた
取り急ぎコアサービスはこれで管理、コピペできるようにしつつ 細かいところは今まで通りコンソールで操作しつつ適宜置き換えていく感じかなー
触ってみた印象結局 Terraform とかでいいんじゃねと思ってもいる