AWS日記28 (Amazon VPC)

# はじめに
今回は Amazon VPC を試します。
VPC, Subnet 生成して Lambda 上で参照します。
今回作成した Lambda関数・SAMテンプレートは[Github](https://github.com/tanaka-takurou/serverless-vpc-page-go)に。



# 準備
[AWS SAM の準備をします](https://qiita.com/tanaka_takurou/items/cae7c19fc3aaf0031abb)

[Amazon VPCの資料]
[Amazon VPC](https://aws.amazon.com/jp/vpc/)


# AWS SAM テンプレート作成

AWS SAM テンプレートで API-Gateway , Lambda, Amazon VPC の設定をします。

[参考資料]
[AWS SAM テンプレートを作成する](https://docs.aws.amazon.com/ja_jp/codedeploy/latest/userguide/tutorial-lambda-sam-template.html)

### Amazon VPCの設定は以下の部分
```yaml
  SampleVPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: !Ref VpcCidrBlock
      EnableDnsHostnames: true
      EnableDnsSupport: true
      InstanceTenancy: default
      Tags:
        - Key: Name
          Value: !Ref VpcName

  SamplePublicSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: !Ref AZ
      CidrBlock: !Ref PublicSubnetCidrBlock
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: !Ref PublicSubnetName
      VpcId: !Ref SampleVPC
```


# Lambda関数作成

※ Lambda関数は aws-lambda-go を利用しました。
Amazon VPC の操作は aws-sdk-go-v2/service/ec2 を利用しました。


### VPC のデータを取得するには DescribeVpcs を使う
```golang
func getVpcs(ctx context.Context)(string, error) {
	if ec2Client == nil {
		ec2Client = ec2.NewFromConfig(getConfig(ctx))
	}
	input := &ec2.DescribeVpcsInput{
		VpcIds: []string{os.Getenv("VPC_ID")},
	}

	result, err := ec2Client.DescribeVpcs(ctx, input)
	if err != nil {
		log.Print(err)
		return "", err
	}
	if len(result.Vpcs) < 1 {
		err := fmt.Errorf("No Vpcs")
		log.Print(err)
		return "", err
	}
	resultJson, err := json.Marshal(VpcData{
		VpcId: aws.ToString(result.Vpcs[0].VpcId),
		CidrBlock: aws.ToString(result.Vpcs[0].CidrBlock),
	})
	if err != nil {
		log.Print(err)
		return "", err
	}
	return string(resultJson), nil
}
```


### Subnet のデータを取得するには DescribeSubnets を使う
```golang
func getSubnets(ctx context.Context)(string, error) {
	if ec2Client == nil {
		ec2Client = ec2.NewFromConfig(getConfig(ctx))
	}
	input := &ec2.DescribeSubnetsInput{
		SubnetIds: []string{os.Getenv("SUBNET_ID")},
	}

	result, err := ec2Client.DescribeSubnets(ctx, input)
	if err != nil {
		log.Print(err)
		return "", err
	}
	if len(result.Subnets) < 1 {
		err := fmt.Errorf("No Subnets")
		log.Print(err)
		return "", err
	}
	resultJson, err := json.Marshal(SubnetData{
		SubnetId: aws.ToString(result.Subnets[0].SubnetId),
		CidrBlock: aws.ToString(result.Subnets[0].CidrBlock),
		AvailabilityZone: aws.ToString(result.Subnets[0].AvailabilityZone),
	})
	if err != nil {
		log.Print(err)
		return "", err
	}
	return string(resultJson), nil
}
```


# 終わりに
VPC, Subnet 生成し、Lambda上で参照出来るようにしました。
EC2や[Fargate](https://qiita.com/tanaka_takurou/items/19a54600cda97ac95dc8)や[ElastiCache](https://qiita.com/tanaka_takurou/items/ae93ef976a63614c02f8)などを使用する際に利用できます。



<details><summary>参考資料</summary><div>

[CloudFormationを使ってVPCを構築する](https://qiita.com/okubot55/items/b18a5dd5166f1ec2696c)

[AWS::EC2::VPC](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpc.html)

[【初心者向け】VPC+PublicSubnetをCloudFormationを使って構築する 前編](https://blog.serverworks.co.jp/build-vpc-and-pubsub-by-cfn)