背景
テクノロジーの進化とビジネスの変化(というより、ビジネスが常に流動的になったともいえる)が著しく、そのスピードに対応する必要性がある。
→ ビジネスを問わず、その手法から既存のものと常に比較検討するべきであり、ソフト・アプリ開発においてはそもそものインフラ(環境)構築の部分から手を打つべきである。
つまり、ビジネス……ひいては顧客やユーザーのニーズに即対応できような開発手法・技術の導入を逐次していくべきなのではというのが現在の考え方の主流。
クラウドファースト
前述の背景を踏まえて1番実行力が高いであろう考え方がクラウドファーストなのではないかと言われている。
具体的には
- 技術フレーム(インフラ及び開発環境)……クラウド(IaaS、PaaS、SaaSを利用する)
- 開発手法……アジャイル(要件定義~テスト、リリースまでを1フェーズとし、フェーズを繰り返すことで製品の質を向上させたり、ニーズの変化に対応していく)
- 運用手法……DevOps(開発チームと運用チームを分けるのではなく、運用結果のデータや自動化ツールの共有などで一体・連動させる組織体制を作る)
といったような開発体制を取っていくことを指す。
アジャイルとDevOpsはCI(Continuous Integration、つまり継続的開発)/CD(Continuous Delivery、つまり継続的導入)という考え方にも則っている。
開発手法と開発手順
フェーズごとに以下の手法を利用していく。
- 創造……デザイン思考
- 企画……リーンスタートアップ
- 開発……アジャイル
- 運用……DeVOps
個々の詳細は以下の通りだが、CI/CDに則った開発及びそういった開発手法と相性がいいマイクロサービスとAPIエコノミーという設計思想を採用することで、開発は基本的に新規機能(これもマイクロサービスごと)の実装を除くと、マイクロサービスごとに改修を行っていくことになっていくことが多い。
あとは既存サービスがある場合はこれをマイクロサービス化していくとか。
デザイン思考
ユーザー観察から問題を発見し、プロトタイプのテストを繰り返すことでアイデアを具体的にしていく。
フローは以下の通り。
- 共感……ユーザーからフィードバックを受ける。または既存・同業他社の類似サービスでのユーザーの反応をリサーチする。
- 問題提起……共感フェーズで得た情報から問題の焦点を絞る
- 創造……問題の解決策を不可能であることを承知の上で、出来得る限り提案する
- プロトタイプ……創造フェーズから出た案を具体化する
- テスト……ユーザー等にプロトタイプを試してもらい、フィードバックを得る
リーンスタートアップ
アイディアからビジネスモデルを構築し、試行・計測して学習を繰り返すことで、ビジネスモデルを精緻化する。
フローは以下の通り。
- アイデアを構築することで製品が生まれる
- 製品の使用状況をモニタリングしたり、ユーザーレビューのフィードバックを受け取るとデータが集まる
- 集まったデータを解析・分析することで好評・不評(課題、問題点)を問わず、知見を得る(機械学習を導入しているなら殊更)
- 得た知見から次なるアイディアが生まれ、以下ループ
リーンキャンバスというものを作成して、要素ごとに検討していく。
- 課題(3つに絞る)
- 課題解決のための機能(1つの課題につき1個、計3つ)とKPI(ビジネス達成条件となる主要な指標)
- 独自の価値提供(サービス、商品の差別化要因及び価値の独自性を簡潔にまとめる)
- 圧倒的な優位性(同業他社に模倣されないポイント)
- チャネル(顧客への販売経路)
- 顧客セグメント(顧客ターゲット)
- コスト構造(ビジネスの固定費、変動費、マーケティング、営業などの顧客獲得コスト)
- 売上構造(収益モデル、顧客生涯価値)
アジャイル開発
既存のウォーターフォール開発はフェーズ事に開発を進め、テストも開発が終われば単体テストを行い、問題なければ結合テスト、システムテスト、受け入れテストと進んでいく。
これだと、フェーズが終わらないと先に進めないという問題があるがそれ以上に、要件の変更……つまりニーズの変更に対応できないという欠点がある。
これに対してアジャイルはある一定の期間、例えば1ヶ月弱程度で要件定義~テスト、リリースを繰り返すことでニーズやビジネスの変化に対応する開発手法。
その反面、よっぽどのことがない限りリリースはとりあえず行うが、フィードバックを得て次のリリースフェーズへ進むことありきなので悪く言えば見切り発車なリリースになってしまい、それによってバグや不具合を出してしまうところがデメリット。
アジャイルはこれまで小規模WEB開発に使うという風潮だったが、最近では基幹系等幅広く使うべきではという模索している。
例えば
- SOA(Service Oriented Architecture)からマイクロサービス・APIエコノミーという思想へ
- マイクロサービスは主要な機能さらに細分化し、その集合を作るサービス思想になるので、短い期間で開発を繰り返していくアジャイルと相性はいい
- さらにマイクロサービスをAPI連携させる(これをAPIエコノミーというらしい)ことで、ERP・基幹系サービスにもアジャイルが適用できるのでは?
という考え方もある。
DeVOps
DevelopmentとOperation……つまり開発とシステム運用を相互に連携させる体制や仕組みを指す。
開発チームは開発、運用はサービス展開・運用・モニタリングを行いそれを開発チームへフィードバックすることでニーズ等に即座に対応する。
人材や組織文化、自動化ツール・運用やモニタリングから得られたデータを共有することが肝要となる。
ツールに関しては以下の観点で採用していく。
- 自動化されたインフラストラクチャ(Ansible、Chef、Docker)
- バージョン管理システムの共有(Git、Mercurial)
- ワンステップによるビルドとデプロイ(Jenkins、Capistrano)
- フィーチャーフラグ……コード中の機能の有効や無効を設定ファイルで管理する
- メトリクスの共有(New Relic、Application Insights)などで取得したメトリクスの結果をダッシュボードでお互いに共有する
- IRCとインスタントメッセンジャーのコミュニケーション共有(SlackやHipChatでビルド・デプロイのログやアラートを自動で投稿して互いに共有できるようにする)
AWSの環境自動化サービス
Well-Architected Frameworkでは信頼性及び運用の優秀性の部分であり、ベストプラクティス的には環境の自動化の部分になる。
主要なサービスは以下の通り。
- Auto Scaling(対象サービスで必要時に自動でスケーリング処理を行える)
- Cloud Formation(クラウド環境内のすべてのインフラストラクチャリソースを記述して、テンプレート化できるプロビジョニングサービス)
- Codeシリーズ(開発コードの構築、ビルド、テスト、展開を行うためのサービス、Git上のコミット・実行デプロイを自動化する)
- ECS・EKS(DockerをAWSで使うためのサービス、特にECSはAWS上でDockerFileから環境構築をテンプレート化することができるようにするためのサービス)
- Elastic BeanStalk(Webアプリケーション、サービスをサーバーでデプロイ・スケーリングをできるようにするサービス)
- OpsWorks(インフラ設定や管理担当。ChefやPuppetといったマネージドインスタンスサーバーの設定、デプロイ、管理を自動化する)
- EC2 RUN Command
- Cloud Watch(モニタリング)
個々の詳細は以下の通り。
Codeシリーズ
開発コードのGitベースのリポジトリ上でのコミット・実行・デプロイを自動化するためのサービス。
段階によって使うサービスが異なる。
全体図は以下の通り。
- CodePipeline(元締めでソース管理から展開まで担当、フルマネージド型の継続展開サービス)
- CodeCommit(ソース管理担当、Gitベースのリポジトリをセキュアにホストするためのマネージドサービス)
- CodeBuild(ビルドからテストを担当、ソースコードをコンパイルしてテストもやってくれるフルマネージドサービス)
- CodeDeploy(展開担当、開発・テスト・本番環境へのデプロイを自動化してくれるサービス)
Elastic BeanStalk
Webアプリケーションの定番構成の構築・デプロイの自動化を行うサービス。
- 素早く簡単にアプリケーションをデプロイしたい
- Java、PHP、Ruby、Python、Node.js、.NET、Docker、Goで開発するWebアプリケーションを展開したい
- Apache、Nginx、Passenger、JIS等使い慣れたサーバーを使ってデプロイ・スケーリングを行いたい
といった需要に対応できる。
コードをアップロードすればキャパシティのプロビジョニング、ロードバランシング、Auto Scaling、ヘルスモニタリングに至るまでのデプロイを自動化することができる。
図としてはこんな感じらしい。
出典: AWS Black Belt Online Seminar 2017 AWS Elastic Beanstalk
コードに基づいてWebサーバー或いはワーカー環境を設置してくれるということらしい。
必要な要素は以下の通り。
- アプリケーション……トップレベルの論理単位であり、バージョンや環境や環境設定を含んだ容れ物と表現される
- バージョン……デプロイ可能なコードでありS3で管理する。異なる環境・バージョンでも展開可能でバージョンレポジトリに保持する
- 環境……各環境(Webサーバーまたはワーカー)に応じて構築されるインフラ環境を指す、バージョン(つまりソースコード)をデプロイする
- 環境設定……環境を構築する上でのリソースの動作を定義するパラメーター群。永続データを利用する場合はS3やRDSなどと連携し、そこに保存する
ユースケース(Webサーバー)
- ELBとAuto Scalingでスケーラブルな構成をコード化し、それをバージョンとして管理することでスケーラブルなWebアプリケーションを実行できる
- 単一コンテナのDockerコンテナも実行可能
- 複数コンテナはECSを利用して実行することもできる
ユースケース(ワーカー環境)
こちらはタスクの長いワークロードを展開したいというケースの際に検討する。
- SQSとAuto Scalingでスケーラブルなバッチ処理ワークを実現する
- 定期的なタスク実行基盤の作成もできる(ex. 毎日決まった時間にバックアップ処理を行う)
- ワーカーホスト内でWebアプリケーションを動作させ、ワークロードの時間が係る処理を実行させる
OpsWorks
ChefあるいはPuppetを使用してアプリケーションを設定及び運用するための設定管理サービス。
Chefは様々なインフラへのサーバー及びアプリケーションの展開を容易にする環境自動化フレームワークのことを指す。
ChefまたはPuppetはAWS独自の仕様ではないので運用には色々と準備が必要なので、OpsWorksはそれらをAWS用に用意してくれるマネージドサービスといったところになる。
OpsWorks for Chef Automation
Chefサーバーの作成、及び継続的なデプロイメントとコンプライアンスチェックを行うフルマネージドサーバーサービス。
- Chef Automationとは、Chefのcookbookやレシピを利用してインフラ管理を自動化するサービスである
- インフラ及びアプリの継続的な展開を行うパイプラインを構成することができる
- リソースはChefサーバーからの構成内容のアップデートを取得する
- オペレーション、コンプライアンス、ワークフローイベントを可視化することが可能
- AWSでChefサーバーを構築することができ、Chef Automate APIやChef DKといったツールを利用できる
OpsWorks for Puppets Enterprise
フルマネージド型Puppetマスターにより、アプリケーションのテスト・展開・運用を自動化する。
-
Puppetマスターはインフラ内のノードを管理して、ノード情報を保存し、Puppetモジュールの中央リポジトリとして機能するもの
-
Puppetマスターはソフトウェア及びOSの設定、パッケージのインストール、DB設定、変更管理、ポリシー適用、モニタリング及び品質保証のタスクを処理する全スタックを自動化することができる
-
モジュールはインフラストラクチャの設定方法に関する手順や格納されたPuppetコードの再利用および共有が可能となるユニットを指す
-
Puppetを使用してEC2インスタンスやオンプレミスデバイスにあるノードの設定、デプロイ、管理方法を自動化することができる
OpsWorks スタック
スタックとアプリケーションの作成及び管理のためのシンプルで柔軟な対応を提供するサービス。
- スタック・レイヤー・インスタンス・アプリケーションと呼ばれるコンポーネントによりモデル化を実施する
- コードで構成管理及びオートスケーリングを可能とする
- Linux・Windowsサーバーをサポート
- ライフサイクルイベントによるタスクの自動化が可能
- OpsWorksエージェントがChef Clientのローカルモードでレシピを実行する
- スタックがOpsWorksのトップエンティティである全インスタンスの構成情報をJSON形式で管理する
- AWS OpsWorksスタックではChefサーバーは不要
Elastic BeanStalk と OpsWorksの使い分け
Elastic BeanStalkはWebアプリケーションのデプロイ部分に特化していて、OpsWorksは様々なアプリケーションに対応したインフラ構築もできるという違いがある。
つまり、前者は基本的にはインフラ側は再利用やアプリケーションは違っても似た構成であることが前提で、後者はそもそもバックエンド(インフラ)もアプリケーションによってチューニングしたいという場合に利用する。
CloudFormation
AWSクラウド環境内の全インフラリソースを記述したテンプレートを作成し、それを展開する環境自動化のためのサービス。
DockerでのDockerFileとかdocker-compose.ymlファイルみたいなものを作るということになる。
- プロビジョニングされたリソースの変更・削除が可能である
- 追加リソースへの通常課金のみで利用でき、追加料金無し
- JSON/YAMLで記述する
- クロスリージョンとクロスアカウントで管理する
- 直接サポートされていないリソースや機能を利用する場合はカスタムリソースでスタック作成の一部に独自のロジックを組み込むこともできる
テンプレート化するということは、つまりある環境(特にベストな環境)構築を正確に実施かつ、効率的に展開できるということになる。
例えば
- 開発・テスト・本番環境で利用するインフラの統一、標準化を容易にしたい
- 同じリソースやプロビジョニング設定を利用することが多い
- ソフトウェアと同じように環境構成を管理したい
といった場合に有効である。
構成要素としては
- テンプレート(JSONかYAMLで作成、リソースとパラメーターを定義する)
- CloudFormation(スタックの作成、変更、削除エラー検知及びそれに伴うロールバックとリソース間依存関係を自動判定するためのサービス)
- スタック(AWSリソースの集合のようなもの。スタック単位で管理可能であり、スタックを削除すると紐ついたリソースも削除される)
となる。
テンプレートからスタックが作られ、それをCloudFormationで管理する(作成も含めて)。
機能
- 変更セット……スタックの更新を行う時の概要であり、変更による影響度を確認するためのスタック。スタックの変更は直接更新するか、この変更セットを使って実行する
- ドリフト……テンプレートによって展開したAWSリソースを変更した場合に発生する元のテンプレートとの差分
- スタックセット……複数のAWSアカウントと複数のリージョンに対してスタックを作成できる機能
- スタック間のリソース参照機能……被参照テンプレートの参照地をエクスポートして値を抽出、その後に参照先のテンプレートのインポートをすることでリソース参照を行い、連携したインフラ展開が可能となる機能
テンプレートについて
以下のような書式になる。
ちなみにSAMとはCloudFormationの拡張機能でLambda、API Gateway、DynamoDBといった三種の神器を使った、サーバレスアプリケーションのデプロイに特化した機能である。
# テンプレートバージョン
AWSTemplateFormatVersion: "2010-09-09" # テンプレートバージョン
Description: Create EC2 Instance # テンプレートの概要説明、なくても可
Metadata: # Description以外の追加情報、なくても可
Parameters: # 実行時に必要なパラメーターを記述。例えばキーペアやユーザー名。ここをあとで!Ref関数が参照する。
InstanceType:
Description: WebServer EC2 instance type
Type: String
Default: t2.micro
AllowedValues:
- t1.micro
- t2.nano
- t2.micro
- t2.small
- t2.medium
- t2.large
ConstraintDescription: must be a valid EC2 instance type
SubnetId:
Type: String
Default: subnet-077623daa0224532e
AllowedValues:
- subnet-077623daa0224532e
- subnet-07b6dbdd52d456bbe
- subnet-008b030ebca96f8a3
- subnet-008b030ebca96f8a3
ConstraintDescription: must be a valid SubnetID
KeyName:
Description : Name of an existing EC2 KeyPair.
Type: AWS::EC2::KeyPair::KeyName
ConstraintDescription : Can contain only ASCII characters.
SSHLocation:
Description: IP address range that can be used to SSH to the EC2 instances
Type: String
MinLength: '9'
MaxLength: '18'
Default: 0.0.0.0/0
AllowedPattern: (\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/(\d{1,2})
ConstraintDescription: must be a valid IP CIDR range of the form x.x.x.x/x.
Mappings: # 条件パラメーター値を指定するためのキーと値をマッピングしたものを記述する。この例だとリージョンをマッピングしている。
RegionMap:
ap-northeast-1:
hvm: "ami-02253ef3230bbc5cb"
ap-southeast-1:
hvm: "ami-0fbe0b405ec32abcc"
Conditions: # リソース作成時の条件名や作成する条件内容を記述する。
Transform: # サーバレスアプリを作る場合はここにSAM(Serverless Application Model)バージョンを記述する。
Resources: # 実際にスタックとして生成するリソース、及びその設定プロパティを記述する
MyEC2Instance: # リソースの名称
Type: AWS::EC2::Instance # リソースのタイプ。この例だとAWSのEC2サービスの中のEC2インスタンスということになる。
Properties: # 各プロパティの記述、!Refや!FindInMapなどで任意のParametersなどを参照できる
ImageId: !FindInMap [RegionMap, !Ref 'AWS::Region', hvm]
InstanceType: !Ref InstanceType
SubnetId: !Ref SubnetId
BlockDeviceMappings:
- DeviceName: /dev/xvda
Ebs:
VolumeType: gp2
VolumeSize: 8
Tags:
- Key: Name
Value: myInstance
KeyName: !Ref KeyName
SecurityGroupIds:
- !GetAtt "InstanceSecurityGroup.GroupId"
InstanceSecurityGroup:
Type: AWS::EC2::SecurityGroup # こっちはセキュリティーグループ。
Properties:
GroupDescription: connect with ssh
VpcId: vpc-072dda7d93a109abc
SecurityGroupIngress:
-
IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: !Ref SSHLocation
この他にも意図的に依存関係を作りたい(つまり、先にどちらのリソースを作ってから依存関係にあるもう一方のリソースを作りたいというケース)場合はDependOn
の項目を作って記述したり、Outputs
の項目を作ってスタック構築後に出力させる値や出力先を記述できる。
Outputs
の例は以下の通り。
AWSTemplateFormatVersion: '2010-09-09'
Description:
VPC & subnet create
Resources:
MyFirstVPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
EnableDnsSupport: 'true'
EnableDnsHostnames: 'true'
InstanceTenancy: default
Tags:
- Key: Name
Value: CloudFormation-VPC
PublicRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref MyFirstVPC
Tags:
- Key: Name
Value: CloudFormation-VPC-PublicRT
PrivateRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref MyFirstVPC
Tags:
- Key: Name
Value: CloudFormation-VPC-PrivateRT
PublicSubnet1A:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref MyFirstVPC
CidrBlock: 10.0.0.0/24
AvailabilityZone: "ap-northeast-1a"
Tags:
- Key: Name
Value: CloudFormation-public-subnet-1a
PubSubnet1ARouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnet1A
RouteTableId: !Ref PublicRouteTable
PublicSubnet1C:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref MyFirstVPC
CidrBlock: 10.0.2.0/24
AvailabilityZone: "ap-northeast-1c"
Tags:
- Key: Name
Value: CloudFormation-public-subnet-1c
PubSubnet1CRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnet1C
RouteTableId: !Ref PublicRouteTable
PrivateSubnet1A:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref MyFirstVPC
CidrBlock: 10.0.1.0/24
AvailabilityZone: "ap-northeast-1a"
Tags:
- Key: Name
Value: CloudFormation-private-subnet-1a
PriSubnet1ARouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PrivateSubnet1A
RouteTableId: !Ref PrivateRouteTable
PrivateSubnet1C:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref MyFirstVPC
CidrBlock: 10.0.3.0/24
AvailabilityZone: "ap-northeast-1c"
Tags:
- Key: Name
Value: CloudFormation-private-subnet-1c
PriSubnet1CRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PrivateSubnet1C
RouteTableId: !Ref PrivateRouteTable
myInternetGateway:
Type: "AWS::EC2::InternetGateway"
Properties:
Tags:
- Key: Name
Value: CloudFormation-ING
AttachGateway:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref MyFirstVPC
InternetGatewayId: !Ref myInternetGateway
myRoute:
Type: AWS::EC2::Route
DependsOn: myInternetGateway
Properties:
RouteTableId: !Ref PublicRouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref myInternetGateway
Outputs:
StackVPC:
Description: The ID of the VPC
Value: !Ref MyFirstVPC
Export:
Name: !Sub "${AWS::StackName}-VPCID"
StackPublicSubnet1A:
Description: The ID of the VPC Subnet
Value: !Ref PublicSubnet1A
Export:
Name: !Sub "${AWS::StackName}-PublicSubnet1A"
StackPublicSubnet1C:
Description: The ID of the VPC Subnet
Value: !Ref PublicSubnet1C
Export:
Name: !Sub "${AWS::StackName}-PublicSubnet1C"
StackPrivateSubnet1A:
Description: The ID of the VPC Subnet
Value: !Ref PrivateSubnet1A
Export:
Name: !Sub "${AWS::StackName}-PrivateSubnet1A"
StackPrivateSubnet1C:
Description: The ID of the VPC Subnet
Value: !Ref PrivateSubnet1C
Export:
Name: !Sub "${AWS::StackName}-PrivateSubnet1C"
上記のテンプレートからわかるようにこれまでやってきたEC2インスタンスの作成をこのようにサブネットの作成からセキュリティグループの指定までして展開することをテンプレート化することができる。
ただし、例えばEC2インスタンスであればAMI、セキュリティーグループであればVPCを指定しないといけない。
Amazonのコンテナサービス
DockerをAWSで使えるようにするためのサービス群。
そもそもDockerはコンテナ型の仮想環境でゲストOSを必要とせず、環境をコンテナとして作っていきカーネル自体はホストOSのものを利用する(Windows Homeで利用する場合はvagrantが必要になるケースもある、面倒くさい)。
つまり、コンテナを削除してしまえば環境もすぐに削除でき、再現や共有もDockerFile・docker-compose.ymlファイル等でテンプレート化して配布すれば容易でありCI/CDに則った開発には適しているという仕組みである。
AWSでDockerをサポートするためのサービスは以下の通り。
- レジストリ担当……ECR(コンテナエンジンに実行されるイメージが保管される場所)
- コントロールプレーン担当……ECS、EKS。どちらもコンテナを管理するサービス
- データプレーン担当……Fargate(コンテナが実行される環境)
詳細は下記。
Elastic Container Service(ECS)
Dockerコンテナをサポートする拡張性とパフォーマンスに優れたコンテナに対してのオーケストレーションサービス(コンピュータシステム、アプリケーション及びサービスにおける設定や管理調整の自動化のこと)。
- コンテナ化されたアプリをAWSにおいて簡単に実行及びスケールすることができる
- Fargateを利用することでコンテナのデプロイと管理にサーバーのプロビジョニングや管理は不要となる
- あらゆる種類のコンテナ化されたアプリケーションを簡単に作成できる
- Dockerコンテナの数が数十、数万であっても数秒で簡単に起動できる
- ELB・VPC・IAM・ECR・CloudWatch・CloudFormation・CloudTrailなどのAWSサービスを利用可能である
- VPCネットワークモードでTaskごとにENI(物理環境におけるNIC、ネットワークインターフェースカードのこと)を自動的に割り当てSecurity GroupをTaskごとに設定可能
- VPC内の他のリソースに対してPrivate IPで通信が可能
- Fargate起動タイプとEC2起動タイプという2種類のモードがある
Elastic Container Registry(ECR)
フルマネージドなレジストリサービスでDockerコンテナイメージを簡単に保存、管理しデプロイすることができる。
- ECSとDocker CLIに統合されていて、開発から本稼働までのワークフローを簡略化する
- IAMによる強力な認証管理機構を持つ
- エンドポイントでアクセスできるならAWS外からでも利用できる
- ライフサイクルポリシーでイメージの自動クリーンアップができる
- VPCネットワークモードでタスクごとにENIを自動で割り当て、更にセキュリティグループをタスクごとに設定することもできる
Elastic Kubernetes Service(EKS)
コンテナ化されたアプリケーションのデプロイ、管理、スケールをオープンソースのKubernetesを使って実行するサービス。
Kubernetesとは自動デプロイ、スケーリング、アプリやコンテナの運用自動化のために設計されたオープンソースのプラットフォームのこと。
- Kubernetesのパートナーやコミュニティが作成した既存のプラグインやツールを使用可能
- マネージドなサービスであり、コントロールプレーンの管理は不要
- ワーカーノードとマネージドコントロールプレーンとの間に暗号化処理された安全な通信のチャネルを自動的にセットアップする
- Kubernetes環境で管理されるアプリケーションとの完全な互換性がある
AWS Fargate
サーバーやクラスターの管理なしにコンテナを実行するECSに対応したコンピューティングエンジン。
2つのモードがある。
EC2起動モード
ECSでEC2インスタンスを起動するためのモード。
柔軟性はあるが設定管理は自分で行う。
- コンテナアプリケーションを実行インフラストラクチャに対して、サーバーレベルの詳細なコントロールを実行可能である
- サーバークラスターを管理し、サーバーでのコンテナ配置をスケジュール可能である
- サーバークラスターでのカスタマイズの幅広いオプションが利用できる
Fargate起動モード
ECSで設置できる専用のコンピューティングエンジン。
下記の通りほぼ設定管理は不要でより自動化はできるが、代わりに柔軟性がEC2起動モードよりない。
- EC2インスタンスのクラスターを管理する必要がない
- インスタンスタイプの選択、クラスタースケジューリングの管理、クラスター使用の最適化も不要
- CPU、メモリ等のアプリ要件を定義すると、スケーリングやインフラ管理はFargateが勝手に管理してくれる
- 秒で数万個のコンテナを起動できる
- EKSにも対応している
CodePipelineと他サービスの連携
CodePipelineはソースコード管理・ビルド・テスト・展開までの各Codeシリーズの元締めのようなサービスだったが以下のように他サービスと連携することもできる。
CodePipelineとCloudFormation
CloudFormationで設定したAWS環境に対して、CodePipelineを使うことでテンプレートの変更・実行・展開を自動化することができる。
CodePipelineとECS
ECSで設定したDocker環境に対してもCloudFormationと連携した場合と同じことができる。
ハンズオン
今回はCloudFormationのハンズオンになる。
まずはテンプレートからスタックを作ってみる。
テンプレートはこんな感じ。
EC2インスタンスを作る場合は、事前にAMIのIDを指定する必要があるので注意。
作成自体はいつものようにウィザードで作れる。
CloudFormationに個別にIAMロールがある場合はここで指定もできる。
IAMロールがなければCloudFormationへのアクセスはユーザーの認証情報に基づくことになるらしい。
あとはスタックにもポリシーを作れる、バケットポリシーなどと同じ要領。
ロールバック設定はCloudFormationがスタックの作成・更新時にモニタリングを行い、エラーが出た場合はそれまでの作業を放棄して、ロールバックしてくれるのでそのためのモニタリング時間及び、ロールバックした場合にCloudWatchと連携してアラームを出すように設定できる。
作成するとこのようにコンソールに表示される。
スタックの詳細。
スタックに関するイベント履歴。
そのスタックに含まれるリソース。
テンプレート内容。
EC2インスタンスに行ってみると、スタックで作成したリソースができているのが確認できる。
パラメータを選択できるようにしてみる
今度はインスタンスタイプをスタック作成時に選択できるようにテンプレートを書いてみる。
すると、以下のようにスタック作成時に選択できるようになる。
テンプレートは以下の通り。
リソースもできていることが確認できる。
Mappingを定義してみる。
以下のようなテンプレートのようにMappingを定義すると、定義したリージョンにリソースを作成できる。
ただし、AMIのIDは当該リージョン毎に必要であり、先程のパラメータのようにスタックの作成時に選択するのではなく、CloudFormationコンソール時の右上のリージョン選択でリソースを作成したいリージョンを予め選択しておく必要があることに注意。
サブネットを指定できるようにしてみる
今度はパラメータでサブネットを指定できるようにしてみた。
テンプレートは以下の通り。
勿論、既存のVPCのサブネットIDが必要なので予めリソースを配置したいVPC及びサブネットを作成しておく必要がある。
スタックを作成すると先程指定したサブネットにリソースが配置されていることがわかる。
ちなみにパラメータを指定できるようなテンプレートを書いた場合は、スタックのコンソール画面でこのように確認ができる。
こちらはEBSまで指定したテンプレート。
指定した通りできていることが確認できる。
キーペア、SSH接続(セキュリティグループ設定)も指定してみる
インスタンス起動に必要なキーペアと外部ツールから接続するためのSSH設定(セキュリティグループで設定するところ)もテンプレート化すると以下のように選択や指定ができるようになる。
パラメータ部分。
テンプレートは以下の通り。
指定した通りリソースができていて、
セキュリティグループも新しく出来ていることがわかる。
VPCもスタックで作れる
VPCもこのようなテンプレートでスタック化できる。
見たほうが早いし、基本的にテンプレートはコピペ改修して使うらしいので蛇足になりそうだが一応確認しておく。
# Resourceは当然VPC。
# CIDR諸々及びタグ付けをする。
# VPCに付随してPublic及びPrivateなルートテーブルも定義する。
# VPCIDはこのテンプレートで作成したVPCのものになるのでRefで参照できるようにする。
AWSTemplateFormatVersion: '2010-09-09'
Description:
VPC & subnet create
Resources:
MyFirstVPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
EnableDnsSupport: 'true'
EnableDnsHostnames: 'true'
InstanceTenancy: default
Tags:
- Key: Name
Value: CloudFormation-VPC
PublicRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref MyFirstVPC
Tags:
- Key: Name
Value: CloudFormation-VPC-PublicRT
PrivateRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref MyFirstVPC
Tags:
- Key: Name
Value: CloudFormation-VPC-PrivateRT
# 次に必要に応じてサブネットを定義する。
# サブネット1つに付き必ずセットでRouteTableAssciationも定義する。
PublicSubnet1A:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref MyFirstVPC
CidrBlock: 10.0.0.0/24
AvailabilityZone: "ap-northeast-1a"
Tags:
- Key: Name
Value: CloudFormation-public-subnet-1a
PubSubnet1ARouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnet1A
RouteTableId: !Ref PublicRouteTable
PublicSubnet1C:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref MyFirstVPC
CidrBlock: 10.0.2.0/24
AvailabilityZone: "ap-northeast-1c"
Tags:
- Key: Name
Value: CloudFormation-public-subnet-1c
PubSubnet1CRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnet1C
RouteTableId: !Ref PublicRouteTable
PrivateSubnet1A:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref MyFirstVPC
CidrBlock: 10.0.1.0/24
AvailabilityZone: "ap-northeast-1a"
Tags:
- Key: Name
Value: CloudFormation-private-subnet-1a
PriSubnet1ARouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PrivateSubnet1A
RouteTableId: !Ref PrivateRouteTable
PrivateSubnet1C:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref MyFirstVPC
CidrBlock: 10.0.3.0/24
AvailabilityZone: "ap-northeast-1c"
Tags:
- Key: Name
Value: CloudFormation-private-subnet-1c
PriSubnet1CRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PrivateSubnet1C
RouteTableId: !Ref PrivateRouteTable
# VPCなのでインターネットゲートウェイの周りの設定もしておく。
myInternetGateway:
Type: "AWS::EC2::InternetGateway"
Properties:
Tags:
- Key: Name
Value: CloudFormation-ING
AttachGateway:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref MyFirstVPC
InternetGatewayId: !Ref myInternetGateway
myRoute:
Type: AWS::EC2::Route
DependsOn: myInternetGateway
Properties:
RouteTableId: !Ref PublicRouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref myInternetGateway
# Outputsでリソースを作成したときの値とかを定義しておく。
Outputs:
StackVPC:
Description: The ID of the VPC
Value: !Ref MyFirstVPC
Export:
Name: !Sub "${AWS::StackName}-VPCID"
StackPublicSubnet1A:
Description: The ID of the VPC Subnet
Value: !Ref PublicSubnet1A
Export:
Name: !Sub "${AWS::StackName}-PublicSubnet1A"
StackPublicSubnet1C:
Description: The ID of the VPC Subnet
Value: !Ref PublicSubnet1C
Export:
Name: !Sub "${AWS::StackName}-PublicSubnet1C"
StackPrivateSubnet1A:
Description: The ID of the VPC Subnet
Value: !Ref PrivateSubnet1A
Export:
Name: !Sub "${AWS::StackName}-PrivateSubnet1A"
StackPrivateSubnet1C:
Description: The ID of the VPC Subnet
Value: !Ref PrivateSubnet1C
Export:
Name: !Sub "${AWS::StackName}-PrivateSubnet1C"
あとはスタックを作成すると以下のようにリソースができていることが確認できる。
で、Outputsを定義したスタックを作るとこんな感じでエクスポート欄ができる。
これを利用して先程のVPCスタックを使って、EC2インスタンスのスタックからリソースを作成できることを試してみる。
テンプレートは以下の通り。
AWSTemplateFormatVersion: "2010-09-09"
Description: Create EC2 Instance
Parameters:
InstanceType:
Description: WebServer EC2 instance type
Type: String
Default: t2.micro
AllowedValues:
- t1.micro
- t2.nano
- t2.micro
- t2.small
- t2.medium
- t2.large
ConstraintDescription: must be a valid EC2 instance type
KeyName:
Description : Name of an existing EC2 KeyPair.
Type: AWS::EC2::KeyPair::KeyName
ConstraintDescription : Can contain only ASCII characters.
SSHLocation:
Description: IP address range that can be used to SSH to the EC2 instances
Type: String
MinLength: '9'
MaxLength: '18'
Default: 0.0.0.0/0
AllowedPattern: (\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/(\d{1,2})
ConstraintDescription: must be a valid IP CIDR range of the form x.x.x.x/x.
Mappings:
RegionMap:
ap-northeast-1:
hvm: "ami-02253ef3230bbc5cb"
ap-southeast-1:
hvm: "ami-0fbe0b405ec32abcc"
# 以下の設定で先程のVPCスタックで作ったリソースを指定していることがわかる。
Description: Create EC2 Instance
Resources:
MyEC2Instance:
Type: AWS::EC2::Instance
Properties:
ImageId: !FindInMap [RegionMap, !Ref 'AWS::Region', hvm]
InstanceType: !Ref InstanceType
SubnetId: !ImportValue MyVPC-PublicSubnet1A
BlockDeviceMappings:
-
DeviceName: /dev/xvda
Ebs:
VolumeType: gp2
VolumeSize: 8
Tags:
- Key: Name
Value: MyEC2-7
KeyName: !Ref KeyName
SecurityGroupIds:
- !GetAtt "InstanceSecurityGroup.GroupId"
InstanceSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: connect with ssh
VpcId: !ImportValue MyVPC-VPCID
SecurityGroupIngress:
-
IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: !Ref SSHLocation
スタックを作成すると以下のように指定したVPCやサブネットにリソースができていることがわかる。
これがリソース参照機能ということになる。
変更セット
変更セットってなんじゃいと思ったところ、ここまでMyEC2ナンバリングで複数のインスタンスのスタックを発展的に作ってきたが、これは要はMyEC2インスタンスの変更(更新)なわけでそういうことならいくつもスタックを作るより1つのスタックにおいて変更セットを作って管理した方が早いでしょ?
ということらしい。
1→2で作ってみる。
すると変更セットとして登録される。
もう1つ作ってみると複数できることが確認できる。
あとはここから使いたい変更セットを選択して実行すれば対象のリソース(この場合だとMyEC2-1で予め作られていたEC2インスタンス)が実行した変更セットに基づいて更新されるということになる。
ちなみにリソースがない状態で実行すると、当然このようにエラーでロールバックが起きる。
ドリフト
例えば以下のようにセキュリティグループをデフォルトのものに設定してみる。
すると以下のようにドリフトが検出される。
Gitの差分確認のようなこともできる。
クロスアカウント
まずマスター側のアカウントでロールを作る。
テンプレートはこちら。
次にクロスアカウントで利用させたいアカウント側、つまりリソースを配置したいアカウント側でIAMロールのスタックを作成する。
パラメータにはマスター側のアカウントのIDを指定する。
テンプレートはこんな感じ。
AWSTemplateFormatVersion: 2010-09-09
Description: Configure the AWSCloudFormationStackSetExecutionRole to enable use of your account as a target account in AWS CloudFormation StackSets.
Parameters:
AdministratorAccountId:
Type: String
Description: AWS Account Id of the administrator account (the account in which StackSets will be created).
MaxLength: 12
MinLength: 12
Resources:
ExecutionRole:
Type: AWS::IAM::Role
Properties:
RoleName: AWSCloudFormationStackSetExecutionRole
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
AWS:
- !Ref AdministratorAccountId
Action:
- sts:AssumeRole
Path: /
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AdministratorAccess
あとはStackSetsからいつものように展開したいリソースをテンプレートから作っていく。
あとは先程クロスアカウント先で作ったロールを指定して、
デプロイに関するオプションを指定する。
テンプレートが複数リージョンに展開できるように書いてあれば以下のように一気に複数のリージョンに展開することもできる。
今回は東京のみ指定しておく。
StackSetsができた。
クロスアカウント先に任意のリソースが展開できたことが確認できる。
デザイナー
左のタブからリソースを引っ張ってくると視覚的にテンプレートを作ることができる。
リソースを追加すると下記のテンプレートの記述も自動で変化する。
YAML形式も可。
デザイナーから直接スタック作成もできる。
さらに既存のスタックをデザイナーで変更することもできる。
例えば以下のようにVPCにインターネットゲートウェイをアタッチしたりとかも可能。
ちなみにテンプレート関連は全てS3に保存される。
初回アップロード時に自動で専用のバケットが作成される。