想ひ出のへっぽこBlogⅡ from35

~ 自身の備忘録および学習促進のためにブログります。~

# 想ひ出25: AWS/OpsWorksに入門する/1

f:id:moqrin3:20190126231935j:plain

おはようございます、moqrinです。

今回も今更感満載ですが、OpsWorksをやってみました。

これもしばらく触らないと忘れるため、個人的後日振り返り用でございます。

OpsWorksはあまり人気がないのか皆さまの記事がない印象でした。

5年近く前のハンズオンとかやってみたんですが、何かうまく出来なかったこと、

Chefともあまり馴染みがないので、、CloudFormationで下準備して、

以前のバージョンChef11のチュートリアルを体験しました。

また後日、Chef12で進めるつもりでございます。

目次

1. AWS OpsWorksとは

2. CloudFormationで準備

3. Chef11のチュートリアルを体験

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 SDKAWS 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

f:id:moqrin3:20190126233336p:plain

② レイヤーを追加

PHP,MySQLともにPublicIPとSecurityGropを付与しましょう。

MySQL root user passwordは d1zethv0sm

f:id:moqrin3:20190126233008p:plain

f:id:moqrin3:20190126233033p:plain

f:id:moqrin3:20190126233107p:plain

f:id:moqrin3:20190126233130p:plain

インスタンスを追加

MySQLレイヤーはPublicサブネットで作成します。

f:id:moqrin3:20190126233445p:plain

④ 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

f:id:moqrin3:20190126233509p:plain

インスタンスを起動
⑥ Deployにライフサイクルイベント設定

各レイヤーのRecipesから設定

  • phpapp::dbsetup
  • phpapp::appsetup

f:id:moqrin3:20190126233717p:plain

f:id:moqrin3:20190126233743p:plain

⑦ Appsのデプロイ

f:id:moqrin3:20190126233801p:plain

f:id:moqrin3:20190126233822p:plain

⑧ ELBレイヤーを追加

f:id:moqrin3:20190126233843p:plain

f:id:moqrin3:20190126233923p:plain

⑨ 確認

f:id:moqrin3:20190126233939p:plain

消すときは、インスタンス->Apps->スタック。

4. 宿題

ま、とりあえずChefから学習しないとですねー。

参考:

AWS OpsWorks とは

AWS Black Belt / AWS OpsWorks