# 想ひ出25: AWS/OpsWorksに入門する/1
おはようございます、moqrinです。
今回も今更感満載ですが、OpsWorksをやってみました。
これもしばらく触らないと忘れるため、個人的後日振り返り用でございます。
OpsWorksはあまり人気がないのか皆さまの記事がない印象でした。
5年近く前のハンズオンとかやってみたんですが、何かうまく出来なかったこと、
Chefともあまり馴染みがないので、、CloudFormationで下準備して、
以前のバージョンChef11のチュートリアルを体験しました。
また後日、Chef12で進めるつもりでございます。
目次
4. 宿題
1. AWS OpsWorksとは
AWS OpsWorksとは(現在)以下の3つ。
- OpsWorks for Puppet Enterprise
- OpsWorks for Chef Automate
- OpsWorks スタック --- 今回触るやつ
OpsWorksスタックとは
下記表で構成される。
構成要素 | 機能 |
---|---|
スタック | 最上位の管理リソース |
レイヤー | LB,DB,ApplicationServerなどの階層を指す |
インスタンス | アプリケーションを提供するためのEC2インスタンスなどのリソース |
アプリケーション(Apps) | アプリケーションサーバーにデプロイするアプリケーション |
どんなか?
ElasticBeanstalkよりも柔軟にアプリケーションに対応できる
スタック、レイヤー単位でモデリング・コード構成管理が可能
サーバーの起動やアプリケーションのデプロイなどのライフサイクルイベントに自動でレシピ実行ができる
インスタンス内部にOpsWorks エージェントが動作しているため、任意のタイミングでインスタンスへ、リモートコマンド(AWSマネージメントコンソール、AWS SDK、AWS CLI)を実⾏可能
2. CloudFormationで準備
OpsWorksではClassic Load Balancer しか対応していないようなのでClassic Load BalancerおよびVPCなどをCloudFormationで適当に作成。
(※ 色々と望ましくない設定です。)
インスタンスはOpsWorksのスタック上のインスタンスで起動させるため、用意しません。
# Opsworks11_sample.json { "AWSTemplateFormatVersion": "2010-09-09", "Parameters" : { "KeyName": { "Description" : "Name of an existing EC2 KeyPair to enable SSH access to the instances", "Type": "String", "MinLength": "1", "MaxLength": "255", "AllowedPattern" : "[\\x20-\\x7E]*", "ConstraintDescription" : "can contain only ASCII characters." }, "SSHLocation": { "Description": " The 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" : { "AWSInstanceType2Arch" : { "t2.micro" : { "Arch" : "HVM64" } }, "AWSRegionArch2AMI" : { "ap-northeast-1" : {"HVM64" : "ami-00a5245b4816c38e6", "HVMG2" : "ami-053cdd503598e4a9d"} } }, "Resources": { "VPC": { "Type": "AWS::EC2::VPC", "Properties": { "CidrBlock": "10.0.0.0/16", "EnableDnsHostnames": "true", "Tags": [ { "Key": "Name", "Value": "OpsWorksVPC" } ] } }, "PublicSubnet1" : { "Type" : "AWS::EC2::Subnet", "Properties" : { "VpcId" : { "Ref" : "VPC" }, "CidrBlock" : "10.0.0.0/24", "AvailabilityZone" : { "Fn::Select" : [ "0", { "Fn::GetAZs" : { "Ref" : "AWS::Region" } }]}, "Tags" : [ {"Key" : "Name", "Value" : "PublicSubnet1" } ] } }, "PublicSubnet2" : { "Type" : "AWS::EC2::Subnet", "Properties" : { "VpcId" : { "Ref" : "VPC" }, "CidrBlock" : "10.0.1.0/24", "AvailabilityZone" : { "Fn::Select" : [ "1", { "Fn::GetAZs" : { "Ref" : "AWS::Region" } }]}, "Tags" : [ {"Key" : "Name", "Value" : "PublicSubnet2"} ] } }, "PrivateSubnet1" : { "Type" : "AWS::EC2::Subnet", "Properties" : { "VpcId" : { "Ref" : "VPC" }, "CidrBlock" : "10.0.2.0/24", "AvailabilityZone" : { "Fn::Select" : [ "0", { "Fn::GetAZs" : { "Ref" : "AWS::Region" } }]}, "Tags" : [ {"Key" : "Name", "Value" : "PrivateSubnet1"} ] } }, "PrivateSubnet2" : { "Type" : "AWS::EC2::Subnet", "Properties" : { "VpcId" : { "Ref" : "VPC" }, "CidrBlock" : "10.0.3.0/24", "AvailabilityZone" : { "Fn::Select" : [ "1", { "Fn::GetAZs" : { "Ref" : "AWS::Region" } }]}, "Tags" : [ {"Key" : "Name", "Value" : "PrivateSubnet2"} ] } }, "InternetGateway": { "Type": "AWS::EC2::InternetGateway", "Properties": { "Tags": [ { "Key": "Name", "Value": "OpsWorksIGW" } ] } }, "DHCPOptions": { "Type": "AWS::EC2::DHCPOptions", "Properties": { "DomainName": "ap-northeast-1.compute.internal", "DomainNameServers": [ "AmazonProvidedDNS" ] } }, "NetworkAcl": { "Type": "AWS::EC2::NetworkAcl", "Properties": { "VpcId": { "Ref": "VPC" } } }, "PublicRouteTable": { "Type": "AWS::EC2::RouteTable", "Properties": { "VpcId": { "Ref": "VPC" }, "Tags": [ { "Key": "Name", "Value": "public" } ] } }, "AttachGateway": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { "VpcId": { "Ref": "VPC" }, "InternetGatewayId": { "Ref": "InternetGateway" } } }, "PublicRoute" : { "Type" : "AWS::EC2::Route", "DependsOn" : "AttachGateway", "Properties" : { "RouteTableId" : { "Ref" : "PublicRouteTable" }, "DestinationCidrBlock" : "0.0.0.0/0", "GatewayId" : { "Ref" : "InternetGateway" } } }, "DBSubnetGroup" : { "Type" : "AWS::RDS::DBSubnetGroup", "Properties" : { "DBSubnetGroupDescription" : "This is a privateSubnet", "SubnetIds": [{"Ref": "PrivateSubnet1"},{ "Ref" : "PrivateSubnet2" }] } }, "WebServerSecurityGroup" : { "Type" : "AWS::EC2::SecurityGroup", "Properties" : { "GroupDescription" : "Enable HTTP access via port 80 locked down to the ELB and SSH access", "SecurityGroupIngress" : [ { "IpProtocol" : "tcp", "FromPort" : "80", "ToPort" : "80", "CidrIp" : "0.0.0.0/0"}, {"IpProtocol" : "tcp", "FromPort" : "22", "ToPort" : "22", "CidrIp" : { "Ref" : "SSHLocation"} } ], "VpcId" : { "Ref" : "VPC" } } }, "DBSecurityGroup" : { "Type" : "AWS::EC2::SecurityGroup", "Properties" : { "GroupDescription" : "Enable WebServer access via port 3306", "SecurityGroupIngress" : [ {"IpProtocol" : "tcp", "FromPort" : "3306", "ToPort" : "3306", "SourceSecurityGroupId" : { "Ref" : "WebServerSecurityGroup"} } ], "VpcId" : { "Ref" : "VPC" } } }, "InboundPublicNetworkAclEntry" : { "Type" : "AWS::EC2::NetworkAclEntry", "Properties" : { "CidrBlock" : "0.0.0.0/0", "Egress" : false, "NetworkAclId" : { "Ref" : "NetworkAcl" }, "Protocol" : "-1", "RuleAction" : "allow", "RuleNumber" : "100" } }, "OutboundPublicNetworkAclEntry" : { "Type" : "AWS::EC2::NetworkAclEntry", "Properties" : { "CidrBlock" : "0.0.0.0/0", "Egress" : true, "NetworkAclId" : { "Ref" : "NetworkAcl" }, "Protocol" : "-1", "RuleAction" : "allow", "RuleNumber" : "100" } }, "PublicSubnet1NetworkAclAssociation" : { "Type" : "AWS::EC2::SubnetNetworkAclAssociation", "Properties" : { "SubnetId" : { "Ref" : "PublicSubnet1" }, "NetworkAclId" : { "Ref" : "NetworkAcl" } } }, "PublicSubnet2NetworkAclAssociation" : { "Type" : "AWS::EC2::SubnetNetworkAclAssociation", "Properties" : { "SubnetId" : { "Ref" : "PublicSubnet2" }, "NetworkAclId" : { "Ref" : "NetworkAcl" } } }, "VPCDHCPOptionsAssociation": { "Type": "AWS::EC2::VPCDHCPOptionsAssociation", "Properties": { "VpcId": { "Ref": "VPC" }, "DhcpOptionsId": { "Ref": "DHCPOptions" } } }, "Public1SubnetRouteTableAssociation" : { "Type" : "AWS::EC2::SubnetRouteTableAssociation", "Properties" : { "SubnetId" : { "Ref" : "PublicSubnet1" }, "RouteTableId" : { "Ref" : "PublicRouteTable" } } }, "Public2SubnetRouteTableAssociation" : { "Type" : "AWS::EC2::SubnetRouteTableAssociation", "Properties" : { "SubnetId" : { "Ref" : "PublicSubnet2" }, "RouteTableId" : { "Ref" : "PublicRouteTable" } } }, "ELB": { "Type": "AWS::ElasticLoadBalancing::LoadBalancer", "DependsOn" : [ "PublicSubnet1", "PublicSubnet2" ], "Properties": { "CrossZone" : "true", "SecurityGroups": [ { "Ref": "ELBSecurityGroup" } ], "Subnets": [ {"Ref": "PublicSubnet1"},{ "Ref" : "PublicSubnet2" } ], "Listeners": [ { "LoadBalancerPort": "80", "InstancePort": "80", "Protocol": "HTTP" } ], "HealthCheck": { "Target": "HTTP:80/", "HealthyThreshold": "10", "UnhealthyThreshold": "2", "Interval": "30", "Timeout": "5" } } }, "ELBSecurityGroup": { "Type": "AWS::EC2::SecurityGroup", "Properties": { "GroupDescription" : "Allow inbound access to the ELB", "VpcId": { "Ref": "VPC" }, "SecurityGroupIngress": [ { "IpProtocol": "tcp", "FromPort": "80", "ToPort": "80", "CidrIp": "0.0.0.0/0" } ], "SecurityGroupEgress": [ { "IpProtocol": "tcp", "FromPort": "80", "ToPort": "80", "CidrIp": "0.0.0.0/0" } ] } } }, "Description": "OpsWorks Tutorial template", "Outputs" : { "ELBIdentifier" : { "Value" : { "Ref" : "ELB" }, "Description" : "ELB Identifier" } } }
# スタックの作成 aws cloudformation create-stack --stack-name opsworks-vpc-elb --template-body file://`pwd`/Opsworks11_sample.json \ --parameters ParameterKey=KeyName,ParameterValue=YOUR_KEY_NAME ParameterKey=SSHLocation,ParameterValue=xxx.xxx.xxx.xxx/32
3. Chef11のチュートリアルを体験
内容は下記です。
Chef 11 シンプルで機能的な PHP アプリケーションサーバーのLinux スタック
① スタックを新規作成
項目 | 入力値 |
---|---|
Stack | MyStack |
VPC | OpsWorksVPC |
Default SSH key | いつものKey |
Custom Cookbook | git://github.com/amazonwebservices/opsworks-example-cookbooks.git |
② レイヤーを追加
PHP,MySQLともにPublicIPとSecurityGropを付与しましょう。
MySQL root user passwordは d1zethv0sm
③ インスタンスを追加
MySQLレイヤーはPublicサブネットで作成します。
④ Appsの追加
項目 | 入力値 |
---|---|
Name | SimplePHPApp |
Document root | web |
Git | git://github.com/awslabs/opsworks-demo-php-simple-app.git |
Branch/Revision | version2 |
Data source type | OpsWorks |
Database name |
⑤ インスタンスを起動
⑥ Deployにライフサイクルイベント設定
各レイヤーのRecipesから設定
- phpapp::dbsetup
- phpapp::appsetup
⑦ Appsのデプロイ
⑧ ELBレイヤーを追加
⑨ 確認
消すときは、インスタンス->Apps->スタック。
4. 宿題
ま、とりあえずChefから学習しないとですねー。