ElasticLoadbalancer(ApplicationLoadBalancer)によるロードバランシング

alb-ec2.yml (EC2)

ネットワークはマルチAZPublicSubnetAPublicSubnetBのサブネットを持つVPCとして作成。
各サブネットにそれぞれEC2インスタンスを配置する。

インスタンスに対するSSHによる管理アクセスは許可するが、WebコンテンツへのアクセスはALBからのみしか許可しない。
ただし、ALBのIPアドレスを明示できないので、同一VPCからのアクセスを許可する。
WebSecurityGroupSecurityGroupIngresのみNLB編と異なる。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# ------------------------------------------------------------ #
# EC2
# ------------------------------------------------------------ #
ManagementSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Enable SSH access via port 22
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub "${AWS::StackName}-management-sg"
SecurityGroupIngress:
- CidrIp: !Ref AllowSshFrom
IpProtocol: tcp
FromPort: '22'
ToPort: '22'

WebSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Enable HTTP(S) access via port 80+443
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub "${AWS::StackName}-web-sg"
SecurityGroupIngress:
- CidrIp: !Ref VpcCidrBlock
IpProtocol: tcp
FromPort: '80'
ToPort: '80'
- CidrIp: !Ref VpcCidrBlock
IpProtocol: tcp
FromPort: '443'
ToPort: '443'

PublicSubetAInstance:
Type: AWS::EC2::Instance
Properties:
ImageId: !Ref ImageID
InstanceType: t2.micro
SecurityGroupIds:
- Fn::GetAtt: [ ManagementSecurityGroup, GroupId ]
- Fn::GetAtt: [ WebSecurityGroup, GroupId ]
KeyName: !Ref KeyName
SubnetId: !Ref PublicSubnetA
Tags:
- Key: Name
Value: !Sub "${AWS::StackName}-PublicSubnetA-Instance"
UserData: !Base64
Fn::Sub: |
#!/bin/bash
apt-get update
apt-get install -y apache2
echo "<HTML>PUBLIC SUBNET A</HTML>" > /var/www/html/index.html

PublicSubetBInstance:
Type: AWS::EC2::Instance
Properties:
ImageId: !Ref ImageID
InstanceType: t2.micro
SecurityGroupIds:
- Fn::GetAtt: [ ManagementSecurityGroup, GroupId ]
- Fn::GetAtt: [ WebSecurityGroup, GroupId ]
KeyName: !Ref KeyName
SubnetId: !Ref PublicSubnetB
Tags:
- Key: Name
Value: !Sub "${AWS::StackName}-PublicSubnetB-Instance"
UserData: !Base64
Fn::Sub: |
#!/bin/bash
apt-get update
apt-get install -y apache2
echo "<HTML>PUBLIC SUBNET B</HTML>" > /var/www/html/index.html

alb-ec2.yml (ALB)

  • セキュリティグループを適用する
  • ヘルスチェックはHTTPによるステータスコードのチェック
  • スティッキーの設定は無効化(ロードバランシングの様子を見たい)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# ------------------------------------------------------------ #
# ElasticLoadBalancer
# ------------------------------------------------------------ #
InternetALBSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Enable HTTP(S) access via port 80+443
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub "${AWS::StackName}-lb-sg"
SecurityGroupIngress:
- CidrIp: 0.0.0.0/0
FromPort: '80'
IpProtocol: tcp
ToPort: '80'
- CidrIp: 0.0.0.0/0
FromPort: '443'
IpProtocol: tcp
ToPort: '443'

InternetALBTargetGroup:
Type: "AWS::ElasticLoadBalancingV2::TargetGroup"
Properties:
VpcId: !Ref VPC
Name: !Sub "${AWS::StackName}-tg"
Protocol: HTTP
Port: 80
HealthCheckProtocol: HTTP
HealthCheckPath: "/"
HealthCheckPort: "traffic-port"
HealthyThresholdCount: 2
UnhealthyThresholdCount: 2
HealthCheckTimeoutSeconds: 5
HealthCheckIntervalSeconds: 10
Matcher:
HttpCode: 200
Tags:
- Key: Name
Value: !Sub "${AWS::StackName}-tg"
TargetGroupAttributes:
- Key: "deregistration_delay.timeout_seconds"
Value: 300
- Key: "stickiness.enabled"
Value: false
- Key: "stickiness.type"
Value: lb_cookie
- Key: "stickiness.lb_cookie.duration_seconds"
Value: 86400
Targets:
- Id: !Ref PublicSubetAInstance
Port: 80
- Id: !Ref PublicSubetBInstance
Port: 80

InternetALB:
Type: "AWS::ElasticLoadBalancingV2::LoadBalancer"
Properties:
Name: !Sub "${AWS::StackName}-alb"
Tags:
- Key: Name
Value: !Sub "${AWS::StackName}-alb"
# ロードバランサーのタイプ (default: application)
Type: application
Scheme: "internet-facing"
LoadBalancerAttributes:
- Key: "deletion_protection.enabled"
Value: false
- Key: "idle_timeout.timeout_seconds"
Value: 60
SecurityGroups:
- !Ref InternetALBSecurityGroup
Subnets:
- !Ref PublicSubnetA
- !Ref PublicSubnetB

InternetALBListener:
Type: "AWS::ElasticLoadBalancingV2::Listener"
Properties:
DefaultActions:
- TargetGroupArn: !Ref InternetALBTargetGroup
Type: forward
LoadBalancerArn: !Ref InternetALB
Port: 80
Protocol: HTTP

# ------------------------------------------------------------ #
# Output Parameters
# ------------------------------------------------------------ #
Outputs:
PublicSubnetAInstanceIP:
Description: "Management Public IP"
Value: !GetAtt PublicSubetAInstance.PublicIp
PublicSubnetBInstanceIP:
Description: "Management Public IP"
Value: !GetAtt PublicSubetBInstance.PublicIp
InternetALBPublicDomainName:
Description: "Public access Domain Name"
Value: !GetAtt InternetALB.DNSName

システムの構築する

1
2
3
4
$ aws cloudformation update-stack --stack-name tutorial-alb-ec2 --template-body "file://./alb-ec2.yml" --parameters "file://./parameters.json"
{
"StackId": "arn:aws:cloudformation:ap-northeast-1:XXXXXXXXXXX:stack/tutorial-alb-ec2/XXXXXXXXXXXXXXXXXXX"
}

作成が完了したら、ロードバランサーに付与されたDNSNameでアクセスする。

1
2
$ aws elbv2 describe-load-balancers | jq -r '.LoadBalancers[] | select (.LoadBalancerName == "tutorial-alb-ec2-alb") | .DNSName'
tutorial-alb-ec2-alb-XXXXXXXXXX.ap-northeast-1.elb.amazonaws.com

ALBロードバランシング width=640

ALBロードバランシング width=640

接続できないときに

ヘルスチェックの状況を確認する

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
$aws elbv2 describe-target-groups | jq -r '.TargetGroups[] | select (.TargetGroupName == "tutorial-alb-ec2-tg")'
{
"TargetGroupArn": "arn:aws:elasticloadbalancing:ap-northeast-1:XXXXXXXXXXX:targetgroup/tutorial-alb-ec2-tg/XXXXXXXXXXXXXX",
"TargetGroupName": "tutorial-alb-ec2-tg",
"Protocol": "HTTP",
"Port": 80,
"VpcId": "vpc-XXXXXXXXXXXXXXXXXXX",
"HealthCheckProtocol": "HTTP",
"HealthCheckPort": "traffic-port",
"HealthCheckEnabled": true,
"HealthCheckIntervalSeconds": 10,
"HealthCheckTimeoutSeconds": 5,
"HealthyThresholdCount": 2,
"UnhealthyThresholdCount": 2,
"HealthCheckPath": "/",
"Matcher": {
"HttpCode": "200"
},
"LoadBalancerArns": [
"arn:aws:elasticloadbalancing:ap-northeast-1:XXXXXXXXXXX:loadbalancer/app/tutorial-alb-ec2-alb/XXXXXXXXXXXXXXXXXXX"
],
"TargetType": "instance"
}

$aws elbv2 describe-target-groups | jq -r '.TargetGroups[] | select (.TargetGroupName == "tutorial-alb-ec2-tg") | .TargetGroupArn'
arn:aws:elasticloadbalancing:ap-northeast-1:XXXXXXXXXXX:targetgroup/tutorial-alb-ec2-tg/XXXXXXXXXXXXXX

$aws elbv2 describe-target-health --target-group-arn arn:aws:elasticloadbalancing:ap-northeast-1:XXXXXXXXXXX:targetgroup/tutorial-alb-ec2-tg/XXXXXXXXXXXXXX
{
"TargetHealthDescriptions": [
{
"Target": {
"Id": "i-XXXXXXXXXXXXXXXXXXX",
"Port": 80
},
"HealthCheckPort": "80",
"TargetHealth": {
"State": "unhealthy",
"Reason": "Target.ResponseCodeMismatch",
"Description": "Health checks failed with these codes: [502]"
}
},
{
"Target": {
"Id": "i-XXXXXXXXXXXXXXXXXXX",
"Port": 80
},
"HealthCheckPort": "80",
"TargetHealth": {
"State": "unhealthy",
"Reason": "Target.ResponseCodeMismatch",
"Description": "Health checks failed with these codes: [502]"
}
}
]
}

$aws elbv2 describe-target-health --target-group-arn arn:aws:elasticloadbalancing:ap-northeast-1:XXXXXXXXXXX:targetgroup/tutorial-alb-ec2-tg/XXXXXXXXXXXXXX
{
"TargetHealthDescriptions": [
{
"Target": {
"Id": "i-XXXXXXXXXXXXXXXXXXX",
"Port": 80
},
"HealthCheckPort": "80",
"TargetHealth": {
"State": "healthy"
}
},
{
"Target": {
"Id": "i-XXXXXXXXXXXXXXXXXXX",
"Port": 80
},
"HealthCheckPort": "80",
"TargetHealth": {
"State": "healthy"
}
}
]
}