2012年11月30日金曜日

CloudFormationでVPCの構築

スズキです。

下記のように、VPCの設計指針の一つを示し、
SUZ-LAB最前線(VPCのサブネット/ ルーティング/セキュリティ)
サブネットのアドレス体系も定義したので、
VPCのSubnetのCIDRの設計方針(一例として)
最後に、これらを"Cloud Formation"化します。というか、しました。
SUZ-LAB Formation VPC Basic 0.0.1
(上記からダウンロードできますし、全ソースは本記事の最後に置いています)

それでは、早速、このテンプレートでVPCを構築してみます。

まずは適当な"Stack Name"をつけて"Provide a Template URL"を選択して、
上記のテンプレート(JSON)のURLを入力します。


次にパラメータとして、VPCに設定するCIDRの最初の2オクテットを入力します。


するとCIDRが"X.X.0.0/16"のVPCが構築され始めます。

CloudFormationが終了すると下記のようになります。


実際にVPCを確認すると、次のように問題なく構築されていることがわかります。



ただし、このままだと、NATインスタンスが無いので、Protectedなサブネットから、
外部に通信することができません。(つまり、まだProtectedじゃありません...)

ということで、次回はNATインスタンスも組み込んで、ちゃんとProtectedサブネットが
機能するようにします。

最後にCloudFormationのテンプレートを載せておきます。(長いですが...)

suz-lab_vpc-basic-0.0.1.json
{
    "AWSTemplateFormatVersion": "2010-09-09", 
    "Description": "SUZ-LAB Formation VPC Basic 0.0.1", 
    "Mappings": {
        "AvailabilityZoneMap": {
            "ap-northeast-1": {
                "AZA": "ap-northeast-1a", 
                "AZB": "ap-northeast-1b", 
                "AZC": "ap-northeast-1c"
            }
        }
    }, 
    "Parameters": {
        "VPCCIDR": {
            "AllowedPattern": "^(\\d|[01]?\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d|[01]?\\d\\d|2[0-4]\\d|25[0-5])", 
            "Default": "10.0", 
            "Description": "VPC CIDR (X.X.0.0/16)", 
            "Type": "String"
        }
    }, 
    "Resources": {
        "EC2VPC": {
            "Properties": {
                "CidrBlock": {
                    "Fn::Join": [
                        "", 
                        [
                            {
                                "Ref": "VPCCIDR"
                            }, 
                            ".0.0/16"
                        ]
                    ]
                }
            }, 
            "Type": "AWS::EC2::VPC"
        },
        "EC2InternetGateway": {
            "Properties": {}, 
            "Type": "AWS::EC2::InternetGateway"
        },
        "EC2VPCGatewayAttachmentInternet": {
            "Properties": {
                "InternetGatewayId": {
                    "Ref": "EC2InternetGateway"
                }, 
                "VpcId": {
                    "Ref": "EC2VPC"
                }
            }, 
            "Type": "AWS::EC2::VPCGatewayAttachment"
        },
        "EC2NetworkAclExternal": {
            "Properties": {
                "VpcId": {
                    "Ref": "EC2VPC"
                }
            }, 
            "Type": "AWS::EC2::NetworkAcl"
        }, 
        "EC2NetworkAclInternal": {
            "Properties": {
                "VpcId": {
                    "Ref": "EC2VPC"
                }
            }, 
            "Type": "AWS::EC2::NetworkAcl"
        }, 
        "EC2NetworkAclEntryExternalInbound": {
            "Properties": {
                "CidrBlock": "0.0.0.0/0", 
                "Egress": "false", 
                "NetworkAclId": {
                    "Ref": "EC2NetworkAclExternal"
                }, 
                "Protocol": "-1", 
                "RuleAction": "allow", 
                "RuleNumber": "100"
            }, 
            "Type": "AWS::EC2::NetworkAclEntry"
        }, 
        "EC2NetworkAclEntryExternalOutbound": {
            "Properties": {
                "CidrBlock": "0.0.0.0/0", 
                "Egress": "true", 
                "NetworkAclId": {
                    "Ref": "EC2NetworkAclExternal"
                }, 
                "Protocol": "-1", 
                "RuleAction": "allow", 
                "RuleNumber": "100"
            }, 
            "Type": "AWS::EC2::NetworkAclEntry"
        }, 
        "EC2NetworkAclEntryInternalInbound": {
            "Properties": {
                "CidrBlock": "0.0.0.0/0", 
                "Egress": "false", 
                "NetworkAclId": {
                    "Ref": "EC2NetworkAclInternal"
                }, 
                "Protocol": "-1", 
                "RuleAction": "allow", 
                "RuleNumber": "100"
            }, 
            "Type": "AWS::EC2::NetworkAclEntry"
        }, 
        "EC2NetworkAclEntryInternalOutbound": {
            "Properties": {
                "CidrBlock": "0.0.0.0/0", 
                "Egress": "true", 
                "NetworkAclId": {
                    "Ref": "EC2NetworkAclInternal"
                }, 
                "Protocol": "-1", 
                "RuleAction": "allow", 
                "RuleNumber": "100"
            }, 
            "Type": "AWS::EC2::NetworkAclEntry"
        }, 
        "EC2RouteTablePrivate": {
            "Properties": {
                "VpcId": {
                    "Ref": "EC2VPC"
                }
            }, 
            "Type": "AWS::EC2::RouteTable"
        }, 
        "EC2RouteTableProtected": {
            "Properties": {
                "VpcId": {
                    "Ref": "EC2VPC"
                }
            }, 
            "Type": "AWS::EC2::RouteTable"
        }, 
        "EC2RouteTablePublic": {
            "Properties": {
                "VpcId": {
                    "Ref": "EC2VPC"
                }
            }, 
            "Type": "AWS::EC2::RouteTable"
        },
        "EC2RoutePublic": {
            "Properties": {
                "DestinationCidrBlock": "0.0.0.0/0", 
                "GatewayId": {
                    "Ref": "EC2InternetGateway"
                }, 
                "RouteTableId": {
                    "Ref": "EC2RouteTablePublic"
                }
            }, 
            "Type": "AWS::EC2::Route"
        },
        "EC2SubnetPrivateFixA72": {
            "Properties": {
                "AvailabilityZone": {
                    "Fn::FindInMap": [
                        "AvailabilityZoneMap", 
                        {
                            "Ref": "AWS::Region"
                        }, 
                        "AZA"
                    ]
                }, 
                "CidrBlock": {
                    "Fn::Join": [
                        "", 
                        [
                            {
                                "Ref": "VPCCIDR"
                            }, 
                            ".72.0/24"
                        ]
                    ]
                }, 
                "VpcId": {
                    "Ref": "EC2VPC"
                }
            }, 
            "Type": "AWS::EC2::Subnet"
        }, 
        "EC2SubnetPrivateFixB73": {
            "Properties": {
                "AvailabilityZone": {
                    "Fn::FindInMap": [
                        "AvailabilityZoneMap", 
                        {
                            "Ref": "AWS::Region"
                        }, 
                        "AZB"
                    ]
                }, 
                "CidrBlock": {
                    "Fn::Join": [
                        "", 
                        [
                            {
                                "Ref": "VPCCIDR"
                            }, 
                            ".73.0/24"
                        ]
                    ]
                }, 
                "VpcId": {
                    "Ref": "EC2VPC"
                }
            }, 
            "Type": "AWS::EC2::Subnet"
        }, 
        "EC2SubnetPrivateFixC74": {
            "Properties": {
                "AvailabilityZone": {
                    "Fn::FindInMap": [
                        "AvailabilityZoneMap", 
                        {
                            "Ref": "AWS::Region"
                        }, 
                        "AZC"
                    ]
                }, 
                "CidrBlock": {
                    "Fn::Join": [
                        "", 
                        [
                            {
                                "Ref": "VPCCIDR"
                            }, 
                            ".74.0/24"
                        ]
                    ]
                }, 
                "VpcId": {
                    "Ref": "EC2VPC"
                }
            }, 
            "Type": "AWS::EC2::Subnet"
        }, 
        "EC2SubnetPrivateVarA64": {
            "Properties": {
                "AvailabilityZone": {
                    "Fn::FindInMap": [
                        "AvailabilityZoneMap", 
                        {
                            "Ref": "AWS::Region"
                        }, 
                        "AZA"
                    ]
                }, 
                "CidrBlock": {
                    "Fn::Join": [
                        "", 
                        [
                            {
                                "Ref": "VPCCIDR"
                            }, 
                            ".64.0/24"
                        ]
                    ]
                }, 
                "VpcId": {
                    "Ref": "EC2VPC"
                }
            }, 
            "Type": "AWS::EC2::Subnet"
        }, 
        "EC2SubnetPrivateVarB65": {
            "Properties": {
                "AvailabilityZone": {
                    "Fn::FindInMap": [
                        "AvailabilityZoneMap", 
                        {
                            "Ref": "AWS::Region"
                        }, 
                        "AZB"
                    ]
                }, 
                "CidrBlock": {
                    "Fn::Join": [
                        "", 
                        [
                            {
                                "Ref": "VPCCIDR"
                            }, 
                            ".65.0/24"
                        ]
                    ]
                }, 
                "VpcId": {
                    "Ref": "EC2VPC"
                }
            }, 
            "Type": "AWS::EC2::Subnet"
        }, 
        "EC2SubnetPrivateVarC66": {
            "Properties": {
                "AvailabilityZone": {
                    "Fn::FindInMap": [
                        "AvailabilityZoneMap", 
                        {
                            "Ref": "AWS::Region"
                        }, 
                        "AZC"
                    ]
                }, 
                "CidrBlock": {
                    "Fn::Join": [
                        "", 
                        [
                            {
                                "Ref": "VPCCIDR"
                            }, 
                            ".66.0/24"
                        ]
                    ]
                }, 
                "VpcId": {
                    "Ref": "EC2VPC"
                }
            }, 
            "Type": "AWS::EC2::Subnet"
        }, 
        "EC2SubnetProtectedFixA40": {
            "Properties": {
                "AvailabilityZone": {
                    "Fn::FindInMap": [
                        "AvailabilityZoneMap", 
                        {
                            "Ref": "AWS::Region"
                        }, 
                        "AZA"
                    ]
                }, 
                "CidrBlock": {
                    "Fn::Join": [
                        "", 
                        [
                            {
                                "Ref": "VPCCIDR"
                            }, 
                            ".40.0/24"
                        ]
                    ]
                }, 
                "VpcId": {
                    "Ref": "EC2VPC"
                }
            }, 
            "Type": "AWS::EC2::Subnet"
        }, 
        "EC2SubnetProtectedFixB41": {
            "Properties": {
                "AvailabilityZone": {
                    "Fn::FindInMap": [
                        "AvailabilityZoneMap", 
                        {
                            "Ref": "AWS::Region"
                        }, 
                        "AZB"
                    ]
                }, 
                "CidrBlock": {
                    "Fn::Join": [
                        "", 
                        [
                            {
                                "Ref": "VPCCIDR"
                            }, 
                            ".41.0/24"
                        ]
                    ]
                }, 
                "VpcId": {
                    "Ref": "EC2VPC"
                }
            }, 
            "Type": "AWS::EC2::Subnet"
        }, 
        "EC2SubnetProtectedFixC42": {
            "Properties": {
                "AvailabilityZone": {
                    "Fn::FindInMap": [
                        "AvailabilityZoneMap", 
                        {
                            "Ref": "AWS::Region"
                        }, 
                        "AZC"
                    ]
                }, 
                "CidrBlock": {
                    "Fn::Join": [
                        "", 
                        [
                            {
                                "Ref": "VPCCIDR"
                            }, 
                            ".42.0/24"
                        ]
                    ]
                }, 
                "VpcId": {
                    "Ref": "EC2VPC"
                }
            }, 
            "Type": "AWS::EC2::Subnet"
        }, 
        "EC2SubnetProtectedVarA32": {
            "Properties": {
                "AvailabilityZone": {
                    "Fn::FindInMap": [
                        "AvailabilityZoneMap", 
                        {
                            "Ref": "AWS::Region"
                        }, 
                        "AZA"
                    ]
                }, 
                "CidrBlock": {
                    "Fn::Join": [
                        "", 
                        [
                            {
                                "Ref": "VPCCIDR"
                            }, 
                            ".32.0/24"
                        ]
                    ]
                }, 
                "VpcId": {
                    "Ref": "EC2VPC"
                }
            }, 
            "Type": "AWS::EC2::Subnet"
        }, 
        "EC2SubnetProtectedVarB33": {
            "Properties": {
                "AvailabilityZone": {
                    "Fn::FindInMap": [
                        "AvailabilityZoneMap", 
                        {
                            "Ref": "AWS::Region"
                        }, 
                        "AZB"
                    ]
                }, 
                "CidrBlock": {
                    "Fn::Join": [
                        "", 
                        [
                            {
                                "Ref": "VPCCIDR"
                            }, 
                            ".33.0/24"
                        ]
                    ]
                }, 
                "VpcId": {
                    "Ref": "EC2VPC"
                }
            }, 
            "Type": "AWS::EC2::Subnet"
        }, 
        "EC2SubnetProtectedVarC34": {
            "Properties": {
                "AvailabilityZone": {
                    "Fn::FindInMap": [
                        "AvailabilityZoneMap", 
                        {
                            "Ref": "AWS::Region"
                        }, 
                        "AZC"
                    ]
                }, 
                "CidrBlock": {
                    "Fn::Join": [
                        "", 
                        [
                            {
                                "Ref": "VPCCIDR"
                            }, 
                            ".34.0/24"
                        ]
                    ]
                }, 
                "VpcId": {
                    "Ref": "EC2VPC"
                }
            }, 
            "Type": "AWS::EC2::Subnet"
        }, 
        "EC2SubnetPublicFixA08": {
            "Properties": {
                "AvailabilityZone": {
                    "Fn::FindInMap": [
                        "AvailabilityZoneMap", 
                        {
                            "Ref": "AWS::Region"
                        }, 
                        "AZA"
                    ]
                }, 
                "CidrBlock": {
                    "Fn::Join": [
                        "", 
                        [
                            {
                                "Ref": "VPCCIDR"
                            }, 
                            ".8.0/24"
                        ]
                    ]
                }, 
                "VpcId": {
                    "Ref": "EC2VPC"
                }
            }, 
            "Type": "AWS::EC2::Subnet"
        }, 
        "EC2SubnetPublicFixB09": {
            "Properties": {
                "AvailabilityZone": {
                    "Fn::FindInMap": [
                        "AvailabilityZoneMap", 
                        {
                            "Ref": "AWS::Region"
                        }, 
                        "AZB"
                    ]
                }, 
                "CidrBlock": {
                    "Fn::Join": [
                        "", 
                        [
                            {
                                "Ref": "VPCCIDR"
                            }, 
                            ".9.0/24"
                        ]
                    ]
                }, 
                "VpcId": {
                    "Ref": "EC2VPC"
                }
            }, 
            "Type": "AWS::EC2::Subnet"
        }, 
        "EC2SubnetPublicFixC10": {
            "Properties": {
                "AvailabilityZone": {
                    "Fn::FindInMap": [
                        "AvailabilityZoneMap", 
                        {
                            "Ref": "AWS::Region"
                        }, 
                        "AZC"
                    ]
                }, 
                "CidrBlock": {
                    "Fn::Join": [
                        "", 
                        [
                            {
                                "Ref": "VPCCIDR"
                            }, 
                            ".10.0/24"
                        ]
                    ]
                }, 
                "VpcId": {
                    "Ref": "EC2VPC"
                }
            }, 
            "Type": "AWS::EC2::Subnet"
        }, 
        "EC2SubnetPublicVarA00": {
            "Properties": {
                "AvailabilityZone": {
                    "Fn::FindInMap": [
                        "AvailabilityZoneMap", 
                        {
                            "Ref": "AWS::Region"
                        }, 
                        "AZA"
                    ]
                }, 
                "CidrBlock": {
                    "Fn::Join": [
                        "", 
                        [
                            {
                                "Ref": "VPCCIDR"
                            }, 
                            ".0.0/24"
                        ]
                    ]
                }, 
                "VpcId": {
                    "Ref": "EC2VPC"
                }
            }, 
            "Type": "AWS::EC2::Subnet"
        }, 
        "EC2SubnetPublicVarB01": {
            "Properties": {
                "AvailabilityZone": {
                    "Fn::FindInMap": [
                        "AvailabilityZoneMap", 
                        {
                            "Ref": "AWS::Region"
                        }, 
                        "AZB"
                    ]
                }, 
                "CidrBlock": {
                    "Fn::Join": [
                        "", 
                        [
                            {
                                "Ref": "VPCCIDR"
                            }, 
                            ".1.0/24"
                        ]
                    ]
                }, 
                "VpcId": {
                    "Ref": "EC2VPC"
                }
            }, 
            "Type": "AWS::EC2::Subnet"
        }, 
        "EC2SubnetPublicVarC02": {
            "Properties": {
                "AvailabilityZone": {
                    "Fn::FindInMap": [
                        "AvailabilityZoneMap", 
                        {
                            "Ref": "AWS::Region"
                        }, 
                        "AZC"
                    ]
                }, 
                "CidrBlock": {
                    "Fn::Join": [
                        "", 
                        [
                            {
                                "Ref": "VPCCIDR"
                            }, 
                            ".2.0/24"
                        ]
                    ]
                }, 
                "VpcId": {
                    "Ref": "EC2VPC"
                }
            }, 
            "Type": "AWS::EC2::Subnet"
        }, 
        "EC2SubnetNetworkAclAssociationPrivateFixA72": {
            "Properties": {
                "NetworkAclId": {
                    "Ref": "EC2NetworkAclInternal"
                }, 
                "SubnetId": {
                    "Ref": "EC2SubnetPrivateFixA72"
                }
            }, 
            "Type": "AWS::EC2::SubnetNetworkAclAssociation"
        }, 
        "EC2SubnetNetworkAclAssociationPrivateFixB73": {
            "Properties": {
                "NetworkAclId": {
                    "Ref": "EC2NetworkAclInternal"
                }, 
                "SubnetId": {
                    "Ref": "EC2SubnetPrivateFixB73"
                }
            }, 
            "Type": "AWS::EC2::SubnetNetworkAclAssociation"
        }, 
        "EC2SubnetNetworkAclAssociationPrivateFixC74": {
            "Properties": {
                "NetworkAclId": {
                    "Ref": "EC2NetworkAclInternal"
                }, 
                "SubnetId": {
                    "Ref": "EC2SubnetPrivateFixC74"
                }
            }, 
            "Type": "AWS::EC2::SubnetNetworkAclAssociation"
        }, 
        "EC2SubnetNetworkAclAssociationPrivateVarA64": {
            "Properties": {
                "NetworkAclId": {
                    "Ref": "EC2NetworkAclInternal"
                }, 
                "SubnetId": {
                    "Ref": "EC2SubnetPrivateVarA64"
                }
            }, 
            "Type": "AWS::EC2::SubnetNetworkAclAssociation"
        }, 
        "EC2SubnetNetworkAclAssociationPrivateVarB65": {
            "Properties": {
                "NetworkAclId": {
                    "Ref": "EC2NetworkAclInternal"
                }, 
                "SubnetId": {
                    "Ref": "EC2SubnetPrivateVarB65"
                }
            }, 
            "Type": "AWS::EC2::SubnetNetworkAclAssociation"
        }, 
        "EC2SubnetNetworkAclAssociationPrivateVarC66": {
            "Properties": {
                "NetworkAclId": {
                    "Ref": "EC2NetworkAclInternal"
                }, 
                "SubnetId": {
                    "Ref": "EC2SubnetPrivateVarC66"
                }
            }, 
            "Type": "AWS::EC2::SubnetNetworkAclAssociation"
        }, 
        "EC2SubnetNetworkAclAssociationProtectedFixA40": {
            "Properties": {
                "NetworkAclId": {
                    "Ref": "EC2NetworkAclInternal"
                }, 
                "SubnetId": {
                    "Ref": "EC2SubnetProtectedFixA40"
                }
            }, 
            "Type": "AWS::EC2::SubnetNetworkAclAssociation"
        }, 
        "EC2SubnetNetworkAclAssociationProtectedFixB41": {
            "Properties": {
                "NetworkAclId": {
                    "Ref": "EC2NetworkAclInternal"
                }, 
                "SubnetId": {
                    "Ref": "EC2SubnetProtectedFixB41"
                }
            }, 
            "Type": "AWS::EC2::SubnetNetworkAclAssociation"
        }, 
        "EC2SubnetNetworkAclAssociationProtectedFixC42": {
            "Properties": {
                "NetworkAclId": {
                    "Ref": "EC2NetworkAclInternal"
                }, 
                "SubnetId": {
                    "Ref": "EC2SubnetProtectedFixC42"
                }
            }, 
            "Type": "AWS::EC2::SubnetNetworkAclAssociation"
        }, 
        "EC2SubnetNetworkAclAssociationProtectedVarA32": {
            "Properties": {
                "NetworkAclId": {
                    "Ref": "EC2NetworkAclInternal"
                }, 
                "SubnetId": {
                    "Ref": "EC2SubnetProtectedVarA32"
                }
            }, 
            "Type": "AWS::EC2::SubnetNetworkAclAssociation"
        }, 
        "EC2SubnetNetworkAclAssociationProtectedVarB33": {
            "Properties": {
                "NetworkAclId": {
                    "Ref": "EC2NetworkAclInternal"
                }, 
                "SubnetId": {
                    "Ref": "EC2SubnetProtectedVarB33"
                }
            }, 
            "Type": "AWS::EC2::SubnetNetworkAclAssociation"
        }, 
        "EC2SubnetNetworkAclAssociationProtectedVarC34": {
            "Properties": {
                "NetworkAclId": {
                    "Ref": "EC2NetworkAclInternal"
                }, 
                "SubnetId": {
                    "Ref": "EC2SubnetProtectedVarC34"
                }
            }, 
            "Type": "AWS::EC2::SubnetNetworkAclAssociation"
        }, 
        "EC2SubnetNetworkAclAssociationPublicFixA08": {
            "Properties": {
                "NetworkAclId": {
                    "Ref": "EC2NetworkAclExternal"
                }, 
                "SubnetId": {
                    "Ref": "EC2SubnetPublicFixA08"
                }
            }, 
            "Type": "AWS::EC2::SubnetNetworkAclAssociation"
        }, 
        "EC2SubnetNetworkAclAssociationPublicFixB09": {
            "Properties": {
                "NetworkAclId": {
                    "Ref": "EC2NetworkAclExternal"
                }, 
                "SubnetId": {
                    "Ref": "EC2SubnetPublicFixB09"
                }
            }, 
            "Type": "AWS::EC2::SubnetNetworkAclAssociation"
        }, 
        "EC2SubnetNetworkAclAssociationPublicFixC10": {
            "Properties": {
                "NetworkAclId": {
                    "Ref": "EC2NetworkAclExternal"
                }, 
                "SubnetId": {
                    "Ref": "EC2SubnetPublicFixC10"
                }
            }, 
            "Type": "AWS::EC2::SubnetNetworkAclAssociation"
        }, 
        "EC2SubnetNetworkAclAssociationPublicVarA00": {
            "Properties": {
                "NetworkAclId": {
                    "Ref": "EC2NetworkAclExternal"
                }, 
                "SubnetId": {
                    "Ref": "EC2SubnetPublicVarA00"
                }
            }, 
            "Type": "AWS::EC2::SubnetNetworkAclAssociation"
        }, 
        "EC2SubnetNetworkAclAssociationPublicVarB01": {
            "Properties": {
                "NetworkAclId": {
                    "Ref": "EC2NetworkAclExternal"
                }, 
                "SubnetId": {
                    "Ref": "EC2SubnetPublicVarB01"
                }
            }, 
            "Type": "AWS::EC2::SubnetNetworkAclAssociation"
        }, 
        "EC2SubnetNetworkAclAssociationPublicVarC02": {
            "Properties": {
                "NetworkAclId": {
                    "Ref": "EC2NetworkAclExternal"
                }, 
                "SubnetId": {
                    "Ref": "EC2SubnetPublicVarC02"
                }
            }, 
            "Type": "AWS::EC2::SubnetNetworkAclAssociation"
        }, 
        "EC2SubnetRouteTableAssociationPrivateFixA72": {
            "Properties": {
                "RouteTableId": {
                    "Ref": "EC2RouteTablePrivate"
                }, 
                "SubnetId": {
                    "Ref": "EC2SubnetPrivateFixA72"
                }
            }, 
            "Type": "AWS::EC2::SubnetRouteTableAssociation"
        }, 
        "EC2SubnetRouteTableAssociationPrivateFixB73": {
            "Properties": {
                "RouteTableId": {
                    "Ref": "EC2RouteTablePrivate"
                }, 
                "SubnetId": {
                    "Ref": "EC2SubnetPrivateFixB73"
                }
            }, 
            "Type": "AWS::EC2::SubnetRouteTableAssociation"
        }, 
        "EC2SubnetRouteTableAssociationPrivateFixC74": {
            "Properties": {
                "RouteTableId": {
                    "Ref": "EC2RouteTablePrivate"
                }, 
                "SubnetId": {
                    "Ref": "EC2SubnetPrivateFixC74"
                }
            }, 
            "Type": "AWS::EC2::SubnetRouteTableAssociation"
        }, 
        "EC2SubnetRouteTableAssociationPrivateVarA64": {
            "Properties": {
                "RouteTableId": {
                    "Ref": "EC2RouteTablePrivate"
                }, 
                "SubnetId": {
                    "Ref": "EC2SubnetPrivateVarA64"
                }
            }, 
            "Type": "AWS::EC2::SubnetRouteTableAssociation"
        }, 
        "EC2SubnetRouteTableAssociationPrivateVarB65": {
            "Properties": {
                "RouteTableId": {
                    "Ref": "EC2RouteTablePrivate"
                }, 
                "SubnetId": {
                    "Ref": "EC2SubnetPrivateVarB65"
                }
            }, 
            "Type": "AWS::EC2::SubnetRouteTableAssociation"
        }, 
        "EC2SubnetRouteTableAssociationPrivateVarC66": {
            "Properties": {
                "RouteTableId": {
                    "Ref": "EC2RouteTablePrivate"
                }, 
                "SubnetId": {
                    "Ref": "EC2SubnetPrivateVarC66"
                }
            }, 
            "Type": "AWS::EC2::SubnetRouteTableAssociation"
        }, 
        "EC2SubnetRouteTableAssociationProtectedFixA40": {
            "Properties": {
                "RouteTableId": {
                    "Ref": "EC2RouteTableProtected"
                }, 
                "SubnetId": {
                    "Ref": "EC2SubnetProtectedFixA40"
                }
            }, 
            "Type": "AWS::EC2::SubnetRouteTableAssociation"
        }, 
        "EC2SubnetRouteTableAssociationProtectedFixB41": {
            "Properties": {
                "RouteTableId": {
                    "Ref": "EC2RouteTableProtected"
                }, 
                "SubnetId": {
                    "Ref": "EC2SubnetProtectedFixB41"
                }
            }, 
            "Type": "AWS::EC2::SubnetRouteTableAssociation"
        }, 
        "EC2SubnetRouteTableAssociationProtectedFixC42": {
            "Properties": {
                "RouteTableId": {
                    "Ref": "EC2RouteTableProtected"
                }, 
                "SubnetId": {
                    "Ref": "EC2SubnetProtectedFixC42"
                }
            }, 
            "Type": "AWS::EC2::SubnetRouteTableAssociation"
        }, 
        "EC2SubnetRouteTableAssociationProtectedVarA32": {
            "Properties": {
                "RouteTableId": {
                    "Ref": "EC2RouteTableProtected"
                }, 
                "SubnetId": {
                    "Ref": "EC2SubnetProtectedVarA32"
                }
            }, 
            "Type": "AWS::EC2::SubnetRouteTableAssociation"
        }, 
        "EC2SubnetRouteTableAssociationProtectedVarB33": {
            "Properties": {
                "RouteTableId": {
                    "Ref": "EC2RouteTableProtected"
                }, 
                "SubnetId": {
                    "Ref": "EC2SubnetProtectedVarB33"
                }
            }, 
            "Type": "AWS::EC2::SubnetRouteTableAssociation"
        }, 
        "EC2SubnetRouteTableAssociationProtectedVarC34": {
            "Properties": {
                "RouteTableId": {
                    "Ref": "EC2RouteTableProtected"
                }, 
                "SubnetId": {
                    "Ref": "EC2SubnetProtectedVarC34"
                }
            }, 
            "Type": "AWS::EC2::SubnetRouteTableAssociation"
        }, 
        "EC2SubnetRouteTableAssociationPublicFixA08": {
            "Properties": {
                "RouteTableId": {
                    "Ref": "EC2RouteTablePublic"
                }, 
                "SubnetId": {
                    "Ref": "EC2SubnetPublicFixA08"
                }
            }, 
            "Type": "AWS::EC2::SubnetRouteTableAssociation"
        }, 
        "EC2SubnetRouteTableAssociationPublicFixB09": {
            "Properties": {
                "RouteTableId": {
                    "Ref": "EC2RouteTablePublic"
                }, 
                "SubnetId": {
                    "Ref": "EC2SubnetPublicFixB09"
                }
            }, 
            "Type": "AWS::EC2::SubnetRouteTableAssociation"
        }, 
        "EC2SubnetRouteTableAssociationPublicFixC10": {
            "Properties": {
                "RouteTableId": {
                    "Ref": "EC2RouteTablePublic"
                }, 
                "SubnetId": {
                    "Ref": "EC2SubnetPublicFixC10"
                }
            }, 
            "Type": "AWS::EC2::SubnetRouteTableAssociation"
        }, 
        "EC2SubnetRouteTableAssociationPublicVarA00": {
            "Properties": {
                "RouteTableId": {
                    "Ref": "EC2RouteTablePublic"
                }, 
                "SubnetId": {
                    "Ref": "EC2SubnetPublicVarA00"
                }
            }, 
            "Type": "AWS::EC2::SubnetRouteTableAssociation"
        }, 
        "EC2SubnetRouteTableAssociationPublicVarB01": {
            "Properties": {
                "RouteTableId": {
                    "Ref": "EC2RouteTablePublic"
                }, 
                "SubnetId": {
                    "Ref": "EC2SubnetPublicVarB01"
                }
            }, 
            "Type": "AWS::EC2::SubnetRouteTableAssociation"
        }, 
        "EC2SubnetRouteTableAssociationPublicVarC02": {
            "Properties": {
                "RouteTableId": {
                    "Ref": "EC2RouteTablePublic"
                }, 
                "SubnetId": {
                    "Ref": "EC2SubnetPublicVarC02"
                }
            }, 
            "Type": "AWS::EC2::SubnetRouteTableAssociation"
        }
    },
    "Outputs": {
        "Guideline": {
            "Value": "https://docs.google.com/a/suz-lab.com/document/pub?id=1nIF-CUBs_rqIEvzHIs9Vn1M9M-fZVn0kGszgh_mWevA"
        }, 
        "VPCCIDR": {
            "Value": {
                "Fn::Join": [
                    "", 
                    [
                        {
                            "Ref": "VPCCIDR"
                        }, 
                        ".0.0/16"
                    ]
                ]
            }
        }
    }
}

条件分岐や繰り返しが使えると、もっと嬉しいかも...
--------
http://www.suz-lab.com

2012年11月29日木曜日

VPCのSubnetのCIDRの設計方針(一例として)

スズキです。

以前、下記でVPCのサブネットやルーティング、セキュリティに関する一つの方針を
書きました。
SUZ-LAB最前線(VPCのサブネット/ ルーティング/セキュリティ)



しかし、上記の図は少し変更されています。変更点はサブネットの切り方(CIDR)です。
今まではAZがCIDR指定でまとまるように切っていましたが、よく考えたら、AZ単位で
CIDRを指定することは、まずありません。
むしろ、Public/Protected/PrivateをCIDRでまとめれた方がいいはずです。

ということで、そうなるようにサブネットを切り直してみました。詳細は下記となります。

Routing Type AZ Subnet(CIDR) Note
Public 10.0.0.0/20
インターネット(IGW)へのInbound/Outboundの両アクセスが可能
Var
10.0.0.0/22
任意にIPが付与されるプロダクトを配置
  • EC2 (Auto Scaling)
  • ELB (internet-facing)
A
10.0.0.0/24
B 10.0.1.0/24
C 10.0.2.0/24
(D) (10.0.3.0/24) (予備)
(10.0.4.0/22) (予備)
Fix 10.0.8.0/22
IPを固定しなければいけないプロダクトを配置
  • EC2 (ネット公開、マスター、Active/Standby...)
  • Active/Standby構成は2つのAZを利用
A
10.0.8.0/24
B 10.0.9.0/24
C 10.0.10.0/24
(D) (10.0.11.0/24) (予備)
(10.0.12.0/22) (予備)
(10.0.16.0/20) (予備)
Protected 10.0.32.0/20
インターネット(IGW)へのOutboundのみNAT経由でアクセス可能
Var 10.0.32.0/22

任意にIPが付与されるプロダクトを配置
  • EC2 (Auto Scaling)
A 10.0.32.0/24
B 10.0.33.0/24
C 10.0.34.0/24
(D) (10.0.35.0/24) (予備)
(10.0.36.0/22) (予備)
Fix 10.0.40.0/22

IPを固定しなければいけないプロダクトを配置
  • EC2 (マスター、Active/Standby...)
  • Active/Standby構成は2つのAZを利用
A
10.0.40.0/24
B 10.0.41.0/24
C 10.0.42.0/24
(D) (10.0.43.0/24) (予備)
(10.0.44.0/22) (予備)
(10.0.48.0/20) (予備)
Private 10.0.64.0/20
インターネット(IGW)へのアクセスは不可能
Var 10.0.64.0/22

任意にIPが付与されるプロダクトを配置
  • EC2 (Auto Scaling)
  • ELB (internal)
  • RDS (Multi-AZは全AZ利用)
A
10.0.64.0/24
B 10.0.65.0/24
C 10.0.66.0/24
(D) (10.0.67.0/24) (予備)
(10.0.68.0/22) (予備)
Fix 10.0.72.0/22

IPを固定しなければいけないプロダクトを配置
  • EC2 (マスター、Active/Standby...)
  • Active/Standby構成は2つのAZを利用
A
10.0.72.0/24
B 10.0.73.0/24
C 10.0.74.0/24
(D) (10.0.75.0/24) (予備)
(10.0.76.0/22) (予備)
(10.0.80.0/20) (予備)

見ての通り、CIDRでまとまる優先順位は次のようになっています。
Public/Protected/Private > Var/Fix > AZ

そして、"SUZ-LAB Formation"へ...
--------
http://www.suz-lab.com

2012年11月26日月曜日

サイズの小さなAMIからブートディスク(EBS)を大きくしてEC2を起動

スズキです。

久しぶりのCDPネタです。今回の対象は「Snapshotパターン」です。


実はV2(次バージョン)へのアップデートとして、下記の「注意点」が追記されています。
ブート領域とデータ領域をひとつのディスクで構築するか、
分けるかについてはメリット・デメリットのトレードオフがある。
一つで構築した場合、スナップショットの取得やEC2インスタンスの起動が
用意である。一方で、ブートディスクのデータサイズは小さい方が
仮想サーバーの起動は早い。また、定期的に行わるディスクチェック
(Linuxの場合はfsck)の際に時間もかからない。
特に下記についてですが
「一つで構築した場合、スナップショットの取得やEC2インスタンスの起動が用意である。」
現在、今までAPIでしかできなかったEC2起動時でのEBS(ルートディスクも)の
サイズ変更が、AWSマネジメントコンソールでもできるようになりました。

ディスクサイズの小さなAMIから、同じEBSの数(だいたいが一つでしょう)で
ディスクサイズの大きなEC2を起動することが容易にできるようになり、
下記のような構築/運用時の課題を減らすことができるはずです。
  • データ用EBSへのデータの移動のし忘れ
  • データ用EBSへのシンボリックリンクの張り忘れ
  • 構築時にどのファイルをデータ用EBSに配置するのかの検討
以下、サイズの小さい(6G)ブートディスク(EBS)を大きく(100G)して、
EC2を起動する方法を紹介します。

まず下記のAWSマネジメントコンソールから、起動時のディスクの調整が
可能となっています。


そして、ブートディスクもデフォルトのサイズ(6G)より大きく(100G)した状態で
起動することができます。


しかし、このままでは下記のように実際の(ファイルシステム上の)サイズは増えていません。
# df -h
Filesystem            Size  Used Avail Use% マウント位置
/dev/xvde1            6.0G  2.2G  3.5G  38% /
none                  296M     0  296M   0% /dev/shm

ファイルシステム上のサイズも増やすには、Linuxなどなら下記のコマンドを
実行する必要があります。
# resize2fs /dev/xvde1 
resize2fs 1.41.12 (17-May-2010)
Filesystem at /dev/xvde1 is mounted on /; on-line resizing required
old desc_blocks = 1, new_desc_blocks = 7
Performing an on-line resize of /dev/xvde1 to 26214400 (4k) blocks.
The filesystem on /dev/xvde1 is now 26214400 blocks long.

すると無事、ファイルシステムレベルでもサイズが増えていることが確認できます。
# df -h
Filesystem            Size  Used Avail Use% マウント位置
/dev/xvde1             99G  2.2G   92G   3% /
none                  296M     0  296M   0% /dev/shm

ファイルシステムレベルでサイズを増やす方法は、以前、下記でまとめています。
中身をそのままにEBSのサイズを増やす方法のまとめ
当然、ブートディスクも含めたサイズの大きなEBS一本で運用するか、
ブートディスクのEBSはサイズを小さくし、他のデータは別EBSに移して運用するかは、
トレードオフなので、メリット・デメリットを確認して選択する必要があるでしょう。

今から成田へ...
--------
http://www.suz-lab.com

2012年11月25日日曜日

SUZ-LAB謹製 CentOS AMI (6.3.4 ap-northeast-1)

スズキです。

下記をアップデートしました。
SUZ-LAB謹製 CentOS AMI (6.3.3 64bit ap-northeast-1)
AMIを「suz」で検索してもらえれば、
811118151095/suz-lab_centos-core-6.3.4
として見つかるはずです。


今回のアップデートは下記となります。
  • Kernelを"2.6.32-279.14.1"に
  • "/boot/grub/menu.lst"を"grub.conf"からのシンボリックリンクに
  • AKI(Amazon Kernel Image)を"aki-44992845"に
  • NRPEをインストール
  • Fluentdをインストール
  • "AWS SDK for PHP Version 2"をインストール

Kernelを"2.6.32-279.14.1"に

次の通り、いつもの手順です。
# yum -y update
...
==========================================================================================
 Package    Arch      Version                Repository    Size
==========================================================================================
Installing:
 kernel     x86_64    2.6.32-279.14.1.el6    updates       25 M
...

# uname -a
Linux ip-10-120-7-217 2.6.32-279.9.1.el6.x86_64 #1 SMP Tue Sep 25 21:43:11 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux

# cat /boot/grub/menu.lst 
default=0
timeout=0
hiddenmenu
title SUZ-LAB CentOS 6
root (hd0)
kernel /boot/vmlinuz-2.6.32-279.14.1.el6.x86_64 ro root=/dev/xvde1
initrd /boot/initramfs-2.6.32-279.14.1.el6.x86_64.img

# reboot

# uname -a
Linux ip-10-120-7-217 2.6.32-279.14.1.el6.x86_64 #1 SMP Tue Nov 6 23:43:09 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux

# yum -y erase kernel-2.6.32-279.9.1.el6

"/boot/grub/menu.lst"を"grub.conf"からのシンボリックリンクに

"yum"でKernelをアップデートすると"grub.conf"も更新してくれるようなので...
# cd /boot/grub/
# mv menu.lst  grub.conf
# ln -s grub.conf menu.lst
# ll
合計 8
-rw-r--r-- 1 root root  186 11月 25 03:41 2012 grub.conf
lrwxrwxrwx 1 root root    9 11月 25 05:16 2012 menu.lst -> grub.conf
-rw-r--r-- 1 root root 1341 11月 15 03:01 2010 splash.xpm.gz
("純正 CentOS AMI"の調査中に知ったのは内緒です...)

AKI(Amazon Kernel Image)を"aki-44992845"に

今までは、下記のAKIを使っていたのですが、
aki-ee5df7ef on The Cloud Market

次の、バージョンの上がったAKIが、知らないうちにでていました。
aki-44992845 on The Cloud Market

("純正 CentOS AMI"の調査中に知ったのは内緒です...)

ということでAKIの入れ替えですが、AKI指定してEC2起動して、
そのEC2から再度AMIを取得すれば、デフォルトAKIが上記のものに変更されます。


NRPEをインストール

作業内容は下記のとおりです。
# yum -y install nagios-nrpe nagios-plugins-all

今まではZabbixなどの利用も考えて、「Nagiosロックイン」的にならないように、
あえてインストールしてませんでしたが、CentOS純正AMIも出たので、
もう少しcloudpackの業務に依存した形にしてもいいかな?といった判断です。
(以下も同じ判断でインストールしています)

Fluentdをインストール

作業内容は下記と同じです。
CentOS6にFluentdをインストール

"AWS SDK for PHP Version 2"をインストール

作業内容は下記と同じです。
"AWS SDK for PHP Version 2"をインストールしてみた(Composer)

最後に

いつものやつ(いろいろとクリア)を実行してAMI化します。
# echo "" > /root/.ssh/authorized_keys
# echo "" > /var/log/boot.log
# echo "" > /var/log/btmp
# echo "" > /var/log/cron
# echo "" > /var/log/dmesg
# echo "" > /var/log/dmesg.old
# echo "" > /var/log/dracut.log
# echo "" > /var/log/lastlog
# echo "" > /var/log/maillog
# echo "" > /var/log/messages
# echo "" > /var/log/secure
# echo "" > /var/log/spooler
# echo "" > /var/log/tallylog
# echo "" > /var/log/wtmp
# echo "" > /var/log/yum.log
# echo "" > /var/log/audit/audit.log
# history -c

Enjoy!
--------
http://www.suz-lab.com

CentOS6にFluentdをインストール

スズキです。

当然、Blog(Cache)化されてると思って調べてたのですが、何か、書いてないようで、
忘れないうちにBlog(Cache)化しておきます。(当時の俺は何をしてたんだ...)
Install from rpm Repository Fluentd rpm Installation | Fluentd


インストール

上記の通り、コマンド一発です!
# curl -OL http://toolbelt.treasure-data.com/sh/install-redhat.sh
# chmod 755 install-redhat.sh
# ./install-redhat.sh
# rm -f install-redhat.sh 

"yum"レポジトリの確認

やはり、"yum"リポジトリが登録されてました。
# cat /etc/yum.repos.d/td.repo 
[treasuredata]
name=TreasureData
baseurl=http://packages.treasure-data.com/redhat/$basearch
gpgcheck=0

サービス(td-agent)の確認


起動スクリプトもあります!
# ls -1 /etc/init.d/
...
td-agent
...
あとは、"/etc/td-agent/td-agent.conf"を調整して、上記の起動スクリプトで
"start"するだけです。

Blog(Cache)化しておかないと、また、調べ直しだし、引継ぎもできないのに...
--------
http://www.suz-lab.com

"AWS SDK for PHP Version 2"をインストールしてみた(Composer)

スズキです。

そういえば、下記がリリースされてたので、インストールしてみました。
AWS SDK for PHP Version 2 がリリースされました!

なんか、Guzzleとか、Symfony2とか、Composerとか、面白そうなキーワードが
所々に見受けられます。

そしてComposer経由のインストールがオススメ(recommended way)ということなので、
Composerデビューしてみました。
Installing via Composer | aws-sdk-php/README.md at master · aws/aws-sdk-php

そもそもComposerについては、以下の記事が参考になります。
PHPの外部ライブラリの管理にComposerを使う | Ryuzee.com

1. PHPの準備とディレクトリの作成

下記コマンドを実行するだけです。
# yum -y install php-cli
# mkdir /opt/aws/php
# cd /opt/aws/php/

2. "AWS SDK"の依存関係を設定

下記のように"composer.json"を用意(に追記)します。
# cat composer.json 
{
    "require": {
        "aws/aws-sdk-php": "2.*"
    }
}

3. "Composer"のダウンロードとインストール

下記コマンドでComposerのダウンロード&インストールを行います。
# curl -s "http://getcomposer.org/installer" | php
#!/usr/bin/env php
All settings correct for using Composer
Downloading...

Composer successfully installed to: /opt/aws/php/composer.phar
Use it: php composer.phar

4. "AWS SDK"と依存パッケージのインストール

下記コマンドで上記で作成した"composer.json"に従ってインストールします。
# php composer.phar install
Loading composer repositories with package information
Installing dependencies
  - Installing symfony/event-dispatcher (v2.1.3)

  - Installing guzzle/guzzle (v3.0.5)

  - Installing aws/aws-sdk-php (2.0.1)

symfony/event-dispatcher suggests installing symfony/dependency-injection (2.1.*)
symfony/event-dispatcher suggests installing symfony/http-kernel (2.1.*)
Writing lock file
Generating autoload files

5. インストールされたものを確認

Composerはもちろんのこと、上述されたGuzzleやSymfony2に関するものも
インストールされています。
# tree -L 3
.
├── composer.json
├── composer.lock
├── composer.phar
└── vendor
    ├── autoload.php
    ├── aws
    │   └── aws-sdk-php
    ├── composer
    │   ├── ClassLoader.php
    │   ├── autoload_classmap.php
    │   ├── autoload_namespaces.php
    │   ├── autoload_real.php
    │   └── installed.json
    ├── guzzle
    │   └── guzzle
    └── symfony
        └── event-dispatcher

8 directories, 9 files

まだ、S3、Glacier、DynamoDB、CloudFront、しか使えないのかなー?
--------
http://www.suz-lab.com

2012年11月23日金曜日

SUZ-LAB系 Advent Calendar 2012

スズキです。

こんな感じで参加します。(自分で作ったものもあるけれど...)

AWS Advent Calendar 2012

12/17(月)に記事を書きます。テーマは
Amazon Web Services に関することなら何でもOK!
です。

CDP Advent Calendar 2012

12/10(月)に記事を書きます。テーマは
AWS Cloud Design Pattern (CDP) に関することなら何でもOK!
です。


SUZ-LAB Advent Calendar 2012

最近、関係者の方々にブログの更新が少ないと注意されてしまったため、
気合を入れ直すために、作成しました。
suz-lab が好きそうなネタなら何でもOK!
で、どなたかが書いてくれればいいのですが、記事の予定がない日は
自動的に僕が技術ネタを書くことになります。(実質、僕が毎日書くことになるはずです)

cloudpack Advent Calendar 2012

昔cloudpackは、スタッフ全員で技術ブログを書いていたのですが、業務が忙しくなり、
書けなくなってしまいました。(それでも書けとは、この状況では言えない...)

しかし、これを機に、ちょっと復活させてみようと思います。テーマは
cloudpack に関係する技術ネタなら何でもOK!
です。人数も増えてきているので、そろそろ、みんな、書けるのでは!?
(僕は12/01に書きます!)

記事、使い回したら負けです...
--------
http://www.suz-lab.com

同一AZのEC2で"Public IP"と"Private IP"でのアクセスの違い

スズキです。

アクセス先のIPアドレスを固定したいため、同一AZのEC2への通信もEIPをつけて、
そのEIPの"Public IP"に対して行いたいと思うことはあると思います。

そもそも、同一AZのEC2間は"Private IP"に対しての通信なら無料ですが、EIPなどの
"Public IP"に対して場合、下記のように課金されてしまいます。

Amazon EC2 (仮想サーバー Amazon Elastic Compute Cloud) - 料金体系


Amazon Web Services Simple Monthly Calculator


つまり同一AZのEC2でもEIPにアクセスすると、データ転送料1GB(in/out)当たり
$0.01かかることになります。

また、ネットワークパフォーマンスに関しても確認してみました。

まずは"ping"です。

"Private IP"に対しては下記の通りです。
# ping 10.146.82.86
PING 10.146.82.86 (10.146.82.86) 56(84) bytes of data.
64 bytes from 10.146.82.86: icmp_seq=1 ttl=64 time=0.303 ms
64 bytes from 10.146.82.86: icmp_seq=2 ttl=64 time=0.492 ms
64 bytes from 10.146.82.86: icmp_seq=3 ttl=64 time=0.350 ms
64 bytes from 10.146.82.86: icmp_seq=4 ttl=64 time=0.493 ms
64 bytes from 10.146.82.86: icmp_seq=5 ttl=64 time=0.561 ms
^C
--- 10.146.82.86 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4459ms
rtt min/avg/max/mdev = 0.303/0.439/0.561/0.100 ms
"Public IP"に対しては下記の通りです。
# ping 54.248.226.255
PING 54.248.226.255 (54.248.226.255) 56(84) bytes of data.
64 bytes from 54.248.226.255: icmp_seq=1 ttl=59 time=0.993 ms
64 bytes from 54.248.226.255: icmp_seq=2 ttl=59 time=1.02 ms
64 bytes from 54.248.226.255: icmp_seq=3 ttl=59 time=0.973 ms
64 bytes from 54.248.226.255: icmp_seq=4 ttl=59 time=1.77 ms
64 bytes from 54.248.226.255: icmp_seq=5 ttl=59 time=1.21 ms
^C
--- 54.248.226.255 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4884ms
rtt min/avg/max/mdev = 0.973/1.196/1.777/0.305 ms
当然ですが"Private IP"へのアクセスのほうが、"Public IP"へのアクセスより速くなってます。

次は"traceroute"です。

"Private IP"に対しては下記の通りです。
# traceroute 10.146.82.86
traceroute to 10.146.82.86 (10.146.82.86), 30 hops max, 60 byte packets
 1  ip-10-146-82-86.ap-northeast-1.compute.internal (10.146.82.86)  2.023 ms  1.971 ms  1.910 ms
"Public IP"に対しては下記の通りです。
# traceroute 54.248.226.255
traceroute to 54.248.226.255 (54.248.226.255), 30 hops max, 60 byte packets
 1  ip-10-146-80-2.ap-northeast-1.compute.internal (10.146.80.2)  0.314 ms  0.383 ms  0.480 ms
 2  ip-10-1-24-1.ap-northeast-1.compute.internal (10.1.24.1)  0.447 ms ip-10-1-22-1.ap-northeast-1.compute.internal (10.1.22.1)  0.300 ms ip-10-1-24-1.ap-northeast-1.compute.internal (10.1.24.1)  0.428 ms
 3  ec2-175-41-192-21.ap-northeast-1.compute.amazonaws.com (175.41.192.21)  4.789 ms ec2-175-41-192-27.ap-northeast-1.compute.amazonaws.com (175.41.192.27)  0.472 ms  0.517 ms
 4  ec2-175-41-192-26.ap-northeast-1.compute.amazonaws.com (175.41.192.26)  1.115 ms ec2-175-41-192-20.ap-northeast-1.compute.amazonaws.com (175.41.192.20)  0.776 ms  0.963 ms
 5  * * *
 6  ec2-54-248-226-255.ap-northeast-1.compute.amazonaws.com (54.248.226.255)  1.015 ms  0.975 ms  0.978 ms
当然ですが"Private IP"へのアクセスのほうが、"Public IP"へのアクセスよりホップ数が少なくなってます。

最後に"tracepath"です。(まあ"traceroute"と同じですが)

"Private IP"に対しては下記の通りです。
# tracepath 10.146.82.86
 1:  ip-10-146-83-8.ap-northeast-1.compute.internal (10.146.83.8)   0.134ms pmtu 1500
 1:  ip-10-146-82-86.ap-northeast-1.compute.internal (10.146.82.86)   0.505ms reached
 1:  ip-10-146-82-86.ap-northeast-1.compute.internal (10.146.82.86)   0.285ms reached
     Resume: pmtu 1500 hops 1 back 64 
"Public IP"に対しては下記の通りです。
# tracepath 54.248.226.255
 1:  ip-10-146-83-8.ap-northeast-1.compute.internal (10.146.83.8)   0.132ms pmtu 1500
 1:  ip-10-146-80-2.ap-northeast-1.compute.internal (10.146.80.2)   8.652ms asymm  2 
 1:  ip-10-146-80-2.ap-northeast-1.compute.internal (10.146.80.2)   0.326ms asymm  2 
 2:  ip-10-1-24-1.ap-northeast-1.compute.internal (10.1.24.1)   0.402ms 
 3:  ec2-175-41-192-21.ap-northeast-1.compute.amazonaws.com (175.41.192.21)   0.549ms 
 4:  ec2-175-41-192-20.ap-northeast-1.compute.amazonaws.com (175.41.192.20)   1.158ms 
 5:  no reply
 6:  ec2-54-248-226-255.ap-northeast-1.compute.amazonaws.com (54.248.226.255)   1.121ms reached
     Resume: pmtu 1500 hops 6 back 59
当然"traceroute"と同様の結果になっています。

ということで"Public IP"にアクセスするか、"Private IP"にアクセスするかは、
IPアドレスの固定化(運用効率)を優先するか、コストとパフォーマンス優先するか、
ということでの判断になるのか、と思います。

同一AZのEC2は、"Private IP"宛にしかアクセスさせたこと無いけど...
--------
http:://www.suz-lab.com

2012年11月22日木曜日

SQSのロングポーリング機能を試してみた

スズキです。

先日、SQSに関して下記の機能がリリースしました。
Amazon SQSに新機能が追加! ロングポーリング、
リクエストバッチ処理/クライアントサイドでのバッファリング
ということで、さっそく、ロングポーリングに関して試してみました。

すでに、SQSに関しては、下記でいろいろと試しており、
そこでのスクリプトをブラッシュアップしたもの実験しています。
PHPでSQS
実際の実験用スクリプト(キューからメッセージを取得)は次のものです。
#!/usr/bin/php
<?php
require_once("../php/default/sdk.class.php");
$url = "https://sqs.ap-northeast-1.amazonaws.com/811118151095/suz-lab-queue";
$sqs = new AmazonSQS(array(
    "key"    => "ACCESS KEY",
    "secret" => "SECRET KEY"
));
$sqs->set_region(AmazonSQS::REGION_APAC_NE1);
$response = $sqs->receive_message($url);
$body = $response->body->ReceiveMessageResult->Message->Body;
if(isset($body)) {
    error_log("Body: " . $body);
} else {
    error_log("Empty");
}
$receipt_handle = $response->body->ReceiveMessageResult->Message->ReceiptHandle;
if(isset($receipt_handle)) {
    $response = $sqs->delete_message($url, $receipt_handle);
    error_log("Delete: " . $receipt_handle);
}
if(!$response->isOK()) {
    exit(1);
}
exit(0);
?>

まずは、下記のデフォルト状態で試してみます。


ちなみに設定されているパラメータは次のとおりです。
  • Default Visibility Timeout
    キューからメッセージが取得され、見えなくなっている期間のデフォルト値です。

  • Message Retention Period
    キューのメッセージを保持する期間です。
    1から14日間の間で指定できます。

  • Maximum Message Size
    キューに送れるメッセージのサイズの最大値です。
    1から64kBの間で指定できます。

  • Delivery Delay
    キューにメッセージを送った後、取得できるようになるまでの期間です。
    0から15秒で指定できます。

  • Receive Message Wait time
    キューからメッセージを取得するときにメッセージを待つ時間です。
    0から20秒で指定できます。
    ロングポーリングに関する設定です!

それではテストスクリプトを実行してみます。
$ ./long-polling.php 
Empty
当然ですが今までどおり、キューにメッセージが無ければ、すぐに"Empty"と返ってきます。

キューにメッセージ(test1)をおくると、


下記のように、スクリプトを実行した瞬間にメッセージ(test1)を取得します。
$ ./long-polling.php 
Body: test1
Delete: cOJv9qrD9XLVlpsfwYn3xQmb+PN7hPQPbkCIB97S3YoyAF+H02uR3CuLsjHxWnZJ3AfRM9/AEkwmrLllzyQfgmGr3NvOxZtxgEHdHG7hCuZj60xWB5TI4kPjjV/MUdapjateCyEm0z65WeuxAS4Ek1l0SjmE5N/xC2dpWOLbFUckMs8XBsfXik95Y8/lXq55xFElXroXRfYS7hFdiLJMxTywEwFPlmKnMV2rRGRzq58jxR9z5+ay3Ior+0gT987n3fSpC08KUC9WX1FKSacnxeivQMpOAV9+84TnrPxqcffMy2gO3IT0TA==

次にキューの設定で"Receive Message Wait Time"をMaxの20秒にしてみます。


そして、キューにメッセージ(test2)を送信して、


スクリプトを実行すると、当然、すぐにメッセージ(test2)が取得され、処理が終了します。
$ ./long-polling.php 
Body: test2
Delete: cOJv9qrD9XLVlpsfwYn3xQmb+PN7hPQP7rQDzfWJc5gwt93m4XHEeuFtIE6jhgu6v9ZaF3dmpwgmrLllzyQfgk8KvWkmEINZQVpyT9HSJN4aV7bWdWMuYN9gY5+w9hl+OOTuSnkHs4gU1WDoUVxdpOvnuzRSz8gIC2dpWOLbFUckMs8XBsfXik95Y8/lXq55xFElXroXRfYS7hFdiLJMxajR6XsXPNgEFWxNOhj2eev6AdZeLbZBInCZSlP4VsY9vvW6rzY9Gff4kzffCfO+f6Xq/3+NXJOMTtVxCUuPvGH19TAUVTfd7w==

キューにメッセージがない状態でスクリプトを実行してみると、
$ ./long-polling.php 
今度は、SQSからのレスポンス待ちの状態となり、
下記のようにメッセージ(test3)を送信すると、


その時点で、メッセージ(test3)が取得でき、処理が終了します。
$ ./long-polling.php 
Body: test3
Delete: cOJv9qrD9XLVlpsfwYn3xQmb+PN7hPQPPNwCZ7A4qpAuJRlSAxSID66Ud7UcK/WMoCbIzo57PIwmrLllzyQfgrstDjoj4ylbP9aayqfgia0MLPCcn2kF8rKnKj7ixVwgCAmy4ftW3AdNAIhG69NhjP5fZNpcqcLlC2dpWOLbFUckMs8XBsfXik95Y8/lXq55xFElXroXRfYS7hFdiLJMxQfc5tcttdCff/m2Eeh7/08FGEDrW8e38hsoKOlI7Py/IKq3rPL5nNB8i6cql6Z75zjNEaw+FUliN44ru1GUNYWBo0xBDlfHjA==

つまりメッセージが無い場合は、最大"Receive Message Wait TIme"で指定した時間だけ
処理が待たされ、キューにメッセージが送信された時点で、すぐにメッセージを取得し、
処理が終了する形となっています。

ちなみにメッセージを送信せずに、そのままにしておくと、20秒後に"Empty"で処理が返ってきます。
$ ./long-polling.php 
Empty

次は、Supervisor(d)の組み合わせを試してみよう。
--------
http://www.suz-lab.com

2012年11月16日金曜日

NginxのアクセスログにELBの"400 Bad Request"エラー(まとめ)

スズキです。

ELBの下のNginxで、下記のアクセスログが頻繁にみられました。
("x.x.x.x"はELBのIPアドレスです)
x.x.x.x - [16/Nov/2012:00:00:17 +0900] 0.000 "-" 400 0 "-" "-" 0 0
x.x.x.x - [16/Nov/2012:00:00:18 +0900] 0.000 "-" 400 0 "-" "-" 0 0
x.x.x.x - [16/Nov/2012:00:00:18 +0900] 0.000 "-" 400 0 "-" "-" 0 0

上記の減少は下記で非常に詳しく説明されていました。
Elastic Load Balancer にぶら下がってる時の access log
つまり、ELBが"second health check"と言われるコネクションを開いて閉じるだけの
チェックを行い、それがNginxのアクセスログで"400 Bad Request"で拾われてるようです。

上記で紹介した日本語の情報は、下記の記事をもとにしていると思います。
Random requests from ELB generating 400 errors in Nginx
ここには、問題のログ(400 Bad Request)を出力しない方法なども紹介されています。

そして、上記で紹介した英語情報には、"second health check"の情報もとも
記載されていました。
ELB making many connections

There is a second health check that we implemented in Oct/Nov 2011,
which behaves as you suggested -- it opens a connection and closes it.

"second health check"は2011/10-11に実装されており、そのヘルスチェックの
振る舞いは、コネクションを開いて閉じるのみのとなっています。

The reason for this second health check is that it provides protection
against instances being terminated without being de-registered.

"second health check"を行う理由は、ELBから取り外されず終了してしまう
EC2インスタンスに対しても、ELBがより問題なく動作できるようにするためです。
ということで、単にELBのヘルスチェック拾っているだけなので、そこまで問題視する
必要はないと思いますが、ログの解析などでうざったい場合は、この手のログは
出力しないようにコントロールした方がいいかもしれません。

Nginxもがんばろう...
--------
http://www.suz-lab.com

2012年11月12日月曜日

"ELB"と"512バイト問題"と"EDNS0"と"Route 53"

スズキです。

下記の記事を書いたら、
ELB(スケールサイズ)とDNS(返されるIPアドレス)の関係(予想)
Facebookで次のようなコメントをいただきました。


ということで、再調査です...

まずは最初のキーワードの「512byte問題」ですが、下記の記事の最初の部分を読むと
概要がわかると思います。
DNSのIPv6対応へのハードル「512バイト問題」とは?
つまり、「DNSでは512バイトを超えるデータをUDPで転送できない」ということで、
ELBのDNS名を名前解決するときに返すIPアドレスの最大数8は、この512バイトを
ギリギリ超えない数だと予想できます。

実際に下記のような"dig"コマンドを実行してみると、最終行が次のように出力されており
MSG SIZE  rcvd: 493
転送されたデータが512バイトにギリギリの493バイトであることがわかります。
$ dig suz-000000000.ap-northeast-1.elb.amazonaws.com +noall +answer +stats

; <<>> DiG 9.8.3-P1 <<>> suz-000000000.ap-northeast-1.elb.amazonaws.com +noall +answer +stats
;; global options: +cmd
suz-000000000.ap-northeast-1.elb.amazonaws.com. 60 IN A 176.34.61.xxx
suz-000000000.ap-northeast-1.elb.amazonaws.com. 60 IN A 176.34.62.xxx
suz-000000000.ap-northeast-1.elb.amazonaws.com. 60 IN A 46.51.249.xxx
suz-000000000.ap-northeast-1.elb.amazonaws.com. 60 IN A 54.248.76.xxx
suz-000000000.ap-northeast-1.elb.amazonaws.com. 60 IN A 54.248.111.xxx
suz-000000000.ap-northeast-1.elb.amazonaws.com. 60 IN A 54.248.120.xxx
suz-000000000.ap-northeast-1.elb.amazonaws.com. 60 IN A 176.34.29.xxx
suz-000000000.ap-northeast-1.elb.amazonaws.com. 60 IN A 176.34.60.xxx
;; Query time: 134 msec
;; SERVER: 192.168.11.1#53(192.168.11.1)
;; WHEN: Mon Nov 12 01:25:56 2012
;; MSG SIZE  rcvd: 493

そして次のキーワードである「EDNS0」ですが、恥ずかしながらこの言葉、
この時、初めて知りました...

で、いろいろ調べてみると、下記を読むことで、ある程度理解することができました。
DNS拡張EDNS0の解析
要は、上記の記事の言葉をかりると、
DNSの要求と応答に「転送可能バイト」を格納することで、
512バイト以上のデータをUDPでも送信できるようにする拡張。
といった感じになると思います。

おそらく、上記の拡張に対応していないDNSサーバ/クライアントのことも考え、
ELBのDNS名を名前解決したときに返ってくるIPアドレスは、
512バイトを超えない8個までにしているのでは、と予想できます。

で話は終わるはずだったのですが、"Route 53"のドキュメントにて
下記のような記述を見つけてしまいました...
DNS Constraints and Behaviors

Maximum Response Size

To comply with DNS standards, responses sent over UDP
are limited to 512 bytes in size. Responses exceeding 512 bytes
are truncated and the resolver must re-issue the request over TCP.
If the resolver supports EDNS0 (as defined in RFC 2671),
and advertises the EDNS0 option to Route 53, Route 53 permits responses
up to 4096 bytes over UDP, without truncation.

DNSの標準に従うためにUDPで送信される応答の大きさは512バイトに
限定される。応答が512バイトを超える場合は切り縮められて、クライアントは
名前解決のためにTCPにて再度リクエストしなければならない。もしクライアントが
EDNS0をサポートしている場合、EDNS0オプションを"Route 53"に送信することで
UDPでも切り縮められることなしに、4096バイトまで応答を送信することができる。
つまり、"Route 53"なら、EDNS0をサポートしているわけです。

ということで、"Route 53"上で"test.suz-lab.com"のAレコードを
"10.0.0.1 - 10.0.0.30"まで作成して実験してみます。

まず普通に名前解決してみると、下記の通り、最後が"MSG SIZE  rcvd: 514"と
512バイト以上になっていますが、先頭が"Truncated, retrying in TCP mode."なので、
UDPではなくTCPで応答が(ドキュメント通り)送信されていることがわかります。
$ dig @8.8.8.8 test.suz-lab.com +noall +answer +stats +comments
;; Truncated, retrying in TCP mode.

; <<>> DiG 9.8.3-P1 <<>> @8.8.8.8 test.suz-lab.com +noall +answer +stats +comments
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 2630
;; flags: qr rd ra; QUERY: 1, ANSWER: 30, AUTHORITY: 0, ADDITIONAL: 0

;; ANSWER SECTION:
test.suz-lab.com. 41 IN A 10.0.0.1
test.suz-lab.com. 41 IN A 10.0.0.22
test.suz-lab.com. 41 IN A 10.0.0.20
test.suz-lab.com. 41 IN A 10.0.0.12
test.suz-lab.com. 41 IN A 10.0.0.10
test.suz-lab.com. 41 IN A 10.0.0.19
test.suz-lab.com. 41 IN A 10.0.0.15
test.suz-lab.com. 41 IN A 10.0.0.23
test.suz-lab.com. 41 IN A 10.0.0.13
test.suz-lab.com. 41 IN A 10.0.0.6
test.suz-lab.com. 41 IN A 10.0.0.14
test.suz-lab.com. 41 IN A 10.0.0.26
test.suz-lab.com. 41 IN A 10.0.0.21
test.suz-lab.com. 41 IN A 10.0.0.2
test.suz-lab.com. 41 IN A 10.0.0.27
test.suz-lab.com. 41 IN A 10.0.0.24
test.suz-lab.com. 41 IN A 10.0.0.18
test.suz-lab.com. 41 IN A 10.0.0.8
test.suz-lab.com. 41 IN A 10.0.0.16
test.suz-lab.com. 41 IN A 10.0.0.3
test.suz-lab.com. 41 IN A 10.0.0.7
test.suz-lab.com. 41 IN A 10.0.0.9
test.suz-lab.com. 41 IN A 10.0.0.11
test.suz-lab.com. 41 IN A 10.0.0.29
test.suz-lab.com. 41 IN A 10.0.0.4
test.suz-lab.com. 41 IN A 10.0.0.25
test.suz-lab.com. 41 IN A 10.0.0.28
test.suz-lab.com. 41 IN A 10.0.0.5
test.suz-lab.com. 41 IN A 10.0.0.30
test.suz-lab.com. 41 IN A 10.0.0.17

;; Query time: 8 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Mon Nov 12 02:42:02 2012
;; MSG SIZE  rcvd: 514

そしてEDNS0で名前解決("+bufsize=4096"を付与)してみると、
今度は下記のように、"EDNS: version: 0, flags:; udp: 512"とEDNS0を利用して
UDPのまま応答を送信していることがわかります。
$ dig @8.8.8.8 test.suz-lab.com +noall +answer +stats +comments +bufsize=4096

; <<>> DiG 9.8.3-P1 <<>> @8.8.8.8 test.suz-lab.com +noall +answer +stats +comments +bufsize=4096
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 26095
;; flags: qr rd ra; QUERY: 1, ANSWER: 30, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; ANSWER SECTION:
test.suz-lab.com. 59 IN A 10.0.0.23
test.suz-lab.com. 59 IN A 10.0.0.26
test.suz-lab.com. 59 IN A 10.0.0.14
test.suz-lab.com. 59 IN A 10.0.0.20
test.suz-lab.com. 59 IN A 10.0.0.8
test.suz-lab.com. 59 IN A 10.0.0.4
test.suz-lab.com. 59 IN A 10.0.0.13
test.suz-lab.com. 59 IN A 10.0.0.18
test.suz-lab.com. 59 IN A 10.0.0.27
test.suz-lab.com. 59 IN A 10.0.0.6
test.suz-lab.com. 59 IN A 10.0.0.16
test.suz-lab.com. 59 IN A 10.0.0.28
test.suz-lab.com. 59 IN A 10.0.0.7
test.suz-lab.com. 59 IN A 10.0.0.1
test.suz-lab.com. 59 IN A 10.0.0.24
test.suz-lab.com. 59 IN A 10.0.0.29
test.suz-lab.com. 59 IN A 10.0.0.5
test.suz-lab.com. 59 IN A 10.0.0.30
test.suz-lab.com. 59 IN A 10.0.0.25
test.suz-lab.com. 59 IN A 10.0.0.10
test.suz-lab.com. 59 IN A 10.0.0.9
test.suz-lab.com. 59 IN A 10.0.0.17
test.suz-lab.com. 59 IN A 10.0.0.12
test.suz-lab.com. 59 IN A 10.0.0.3
test.suz-lab.com. 59 IN A 10.0.0.11
test.suz-lab.com. 59 IN A 10.0.0.22
test.suz-lab.com. 59 IN A 10.0.0.19
test.suz-lab.com. 59 IN A 10.0.0.2
test.suz-lab.com. 59 IN A 10.0.0.21
test.suz-lab.com. 59 IN A 10.0.0.15

;; Query time: 218 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Mon Nov 12 02:43:14 2012
;; MSG SIZE  rcvd: 525

ちなみにEDNS0のついでにDNSSECはどうかというと、
下記よりサポートされてないことがわかります。
Q. Does Amazon Route 53 support DNSSEC?
"Route 53"はDNSSECをサポートしていますか?

No. Amazon Route 53 does not support DNSSEC at this time.
いいえ、今の時点では"Route 53"はDNSSECをサポートしていません。
結構古い情報なのに、今まで知らなかった...
--------
http://www.suz-lab.com

2012年11月10日土曜日

ELB(スケールサイズ)とDNS(返されるIPアドレス)の関係(予想)

スズキです。

以前、下記の記事より、ELBのDNS名を名前解決して返ってくるIPアドレスは、
最大8個であることがわかりました。
【AWS発表】 Elastic Load Balancingが東京リージョンでIPv6をサポート、
新メトリクスもサポート、複数のIPアドレスを返すように

実際に、そこそこアクセス数の多いELBのDNS名を名前解決してみると、
下記のように8個(最大)のIPアドレスが帰ってきました。
$ nslookup suz-lab-000000000.ap-northeast-1.elb.amazonaws.com
...
Name: suz-lab-000000000.ap-northeast-1.elb.amazonaws.com
Address: 46.51.248.xxx
Name: suz-lab-000000000.ap-northeast-1.elb.amazonaws.com
Address: 54.248.111.xxx
Name: suz-lab-000000000.ap-northeast-1.elb.amazonaws.com
Address: 175.41.254.xxx
Name: suz-lab-000000000.ap-northeast-1.elb.amazonaws.com
Address: 176.34.27.xxx
Name: suz-lab-000000000.ap-northeast-1.elb.amazonaws.com
Address: 176.34.29.xxx
Name: suz-lab-000000000.ap-northeast-1.elb.amazonaws.com
Address: 176.34.61.xxx
Name: suz-lab-000000000.ap-northeast-1.elb.amazonaws.com
Address: 54.248.122.xxx
Name: suz-lab-000000000.ap-northeast-1.elb.amazonaws.com
Address: 54.248.108.xxx

と言うことは、スケールした数(ELBの実体の数)がDNS名を名前解決して返ってくる
IPアドレスと予想することはできますが、そうなると、ELBは8インスタンスしか
スケールしないことになってしまいます。

そして、VPCに関してですが、ドキュメントより下記のような情報を
見つけることもできます。
Deploying Elastic Load Balancing in Amazon VPC

In order to ensure that your load balancer can scale properly,
the subnet that you attach the load balancer to should be at least a /27 CIDR block
and should have at least 20 free IP addresses in the subnet
when you attach the load balancer.

ELBが適切にスケールするように、ELBが配置されているVPCのサブネットの
ネットワークアドアドレスの範囲は、少なくても"/27"のCIDRブロックの
範囲であり、ELBを配置するときには、少なくても20個のIPアドレスが
利用可能でなければならない。
つまり、8インスタンスどころか、20インスタンス以上はスケールする可能性が
確実にあるということになります。

ということで、もう一度、同一のELBに対して名前解決をしてみると、
下記のように、更に別のIPアドレスが返ってきました。
$ nslookup suz-lab-000000000.ap-northeast-1.elb.amazonaws.com
...
Name: suz-lab-000000000.ap-northeast-1.elb.amazonaws.com
Address: 54.248.120.xxx
Name: suz-lab-000000000.ap-northeast-1.elb.amazonaws.com
Address: 54.248.248.xxx
Name: suz-lab-000000000.ap-northeast-1.elb.amazonaws.com
Address: 46.51.248.xxx
Name: suz-lab-000000000.ap-northeast-1.elb.amazonaws.com
Address: 176.34.62.xxx
Name: suz-lab-000000000.ap-northeast-1.elb.amazonaws.com
Address: 46.51.249.xxx
Name: suz-lab-000000000.ap-northeast-1.elb.amazonaws.com
Address: 54.248.122.xxx
Name: suz-lab-000000000.ap-northeast-1.elb.amazonaws.com
Address: 176.34.61.xxx
Name: suz-lab-000000000.ap-northeast-1.elb.amazonaws.com
Address: 176.34.29.xxx

ちなみに、3つのAZに配置し、全くアクセスの無いELBのDNS名を同様に名前解決すると
下記のように、二回目も同じIPアドレスが返ってきました。
$ nslookup suz-lab2-000000000.ap-northeast-1.elb.amazonaws.com
Name: suz-lab2-000000000.ap-northeast-1.elb.amazonaws.com
Address: 54.248.85.xxx
Name: suz-lab2-000000000.ap-northeast-1.elb.amazonaws.com
Address: 54.248.85.xxx
Name: suz-lab2-000000000.ap-northeast-1.elb.amazonaws.com
Address: 54.248.252.xxx
$
$ nslookup app-test-365558714.ap-northeast-1.elb.amazonaws.com
...
Name: suz-lab2-000000000.ap-northeast-1.elb.amazonaws.com
Address: 54.248.252.xxx
Name: suz-lab2-000000000.ap-northeast-1.elb.amazonaws.com
Address: 54.248.85.xxx
Name: suz-lab2-000000000.ap-northeast-1.elb.amazonaws.com
Address: 54.248.85.xxx
※各AZに一つずつ、ELBの実体(インスタンス)があることも予想できます。

結論として、
ELBの実体(インスタンス)は8個以上スケールし、その場合は、その中から、
あるルールで選ばれた8個のIPアドレスが、DNS名の名前解決時に返される。
と予想できるのではないのでしょうか?

真実は、中の人のみぞ知る、ですね...
--------
http://www.suz-lab.com

2012年11月9日金曜日

NginxでELB対策(アクセスログにクライアントIP)

スズキです。

以前、下記のようにApacheでELB経由のアクセスログに、ELBのIPアドレスではなく
クライアントIPを出力する方法を紹介しました。
ApacheでREMOTE_ADDRをELB経由でも...(CentOS)
当然それは、Nginxでも同様なので、今回はNginxでの実現方法の紹介です。

といってもNginxにはHttpRealipModuleというモジュールが存在し、
それが利用できれば、すぐに実現できます。(Apache2.4なら"mod_remoteip"ですね)

ということで、まずは対象のNginxにHttpRealipModuleが組み込まれているか確認です。
(下記の出力で"--with-http_realip_module"があればOKです)
# nginx -V
nginx version: nginx/1.2.3
built by gcc 4.4.6 20120305 (Red Hat 4.4.6-4) (GCC)
TLS SNI support enabled
configure arguments:
--user=nginx
--group=nginx
--prefix=/usr/share/nginx
--sbin-path=/usr/sbin/nginx
--conf-path=/etc/nginx/nginx.conf
--error-log-path=/var/log/nginx/error.log
--http-log-path=/var/log/nginx/access.log
--http-client-body-temp-path=/var/lib/nginx/tmp/client_body
--http-proxy-temp-path=/var/lib/nginx/tmp/proxy
--http-fastcgi-temp-path=/var/lib/nginx/tmp/fastcgi
--http-uwsgi-temp-path=/var/lib/nginx/tmp/uwsgi
--http-scgi-temp-path=/var/lib/nginx/tmp/scgi
--pid-path=/var/run/nginx.pid
--lock-path=/var/lock/subsys/nginx
--with-http_ssl_module
--with-http_realip_module
--with-http_addition_module
--with-http_xslt_module
--with-http_image_filter_module
--with-http_geoip_module
--with-http_sub_module
--with-http_dav_module
--with-http_flv_module
--with-http_gzip_static_module
--with-http_random_index_module
--with-http_secure_link_module
--with-http_degradation_module
--with-http_stub_status_module
--with-http_perl_module
--with-mail
--with-file-aio
--with-mail_ssl_module
--with-ipv6
--with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic'
--with-ld-opt=-Wl,-E

組み込まれていることが確認できたら、下記のように設定ファイル(nginx.conf)に
追記します。
# For ELB
set_real_ip_from   10.0.0.0/8;
real_ip_header     X-Forwarded-For;

"ser_real_ip_from"はELBのIPアドレスです。普通のEC2なら"10.0.0.0/8"とし、
VPCなら、ELBが所属するサブネットのネットワークアドレスを指定します。

"real_ip_header"はクライアントIPが渡されるHTTPヘッダです。ELBの場合は、
X-Forwarded-Forを指定することになります。

最終的に"nginx.conf"は下記のようになるのでは、とおもいます。
http {
    ....
    # For ELB
    set_real_ip_from   10.0.0.0/8;
    real_ip_header     X-Forwarded-For;
    ...
}

最後にNginxを再起動してアクセスログを確認すると、リモートIPの部分が、ELBのもの
(10.0.0.0/8)から実際のクライアントのIPに変わっていることが確認できるはずです。

また、ブログ量が減ってる...
--------
http://www.suz-lab.com