この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
超おはようございます。最近パンケーキを昼食にできるようになった城内です。 今回は、Auto Scalingのアップデートにより、AWSでのBlue-Green Deploymentの方式に新たな選択肢が増えたことを喜びたいと思います。
Auto Scalingのアップデート
先日のAuto Scalingのアップデートにより、Auto Scalingグループに対するELBの付け外しができるようになりました。
- Attach or Detach Load Balancers in Your Auto Scaling Group (What's New)
- Attach and Detach Elastic Load Balancers from Auto Scaling Groups (AWS Official Blog)
何が嬉しいのか?
従来、Auto Scalingに紐づくELBは変更することができず、AWS上でBlue-Green Deploymentの切替を行おうと思ったときには、DNSベース(Route53)の切替しかできませんでした。しかし、今回のAuto Scalingのアップデートにより、ELBでの切替が可能になりました。
切替方法
では、実際の切替方法ですが、いたって簡単です。今回はCLIベースでいきたいと思います。
環境構成
まず、構成は以下のような簡素な構成を前提に実施します。
CLIで確認すると、以下のような感じです。
# aws elb describe-load-balancers | jq '.LoadBalancerDescriptions[] | {LoadBalancerName, DNSName}'
{
"LoadBalancerName": "ELB-A",
"DNSName": "ELB-A-87373750.ap-northeast-1.elb.amazonaws.com"
}
{
"LoadBalancerName": "ELB-B",
"DNSName": "ELB-B-55201029.ap-northeast-1.elb.amazonaws.com"
}
# aws autoscaling describe-auto-scaling-groups | jq '.AutoScalingGroups[] | {AutoScalingGroupName, LoadBalancerNames, Instances}'
{
"AutoScalingGroupName": "AutoScalingGroup-A",
"LoadBalancerNames": [
"ELB-A"
],
"Instances": [
{
"InstanceId": "i-0d21ceff",
"AvailabilityZone": "ap-northeast-1a",
"HealthStatus": "Healthy",
"LifecycleState": "InService",
"LaunchConfigurationName": "webserver-20150618-01"
}
]
}
{
"AutoScalingGroupName": "AutoScalingGroup-B",
"LoadBalancerNames": [
"ELB-B"
],
"Instances": [
{
"InstanceId": "i-8f21ce7d",
"AvailabilityZone": "ap-northeast-1a",
"HealthStatus": "Healthy",
"LifecycleState": "InService",
"LaunchConfigurationName": "webserver-20150618-01"
}
]
}
Green環境の本番組み込み
上記の構成から、本番アクセスがGreen環境(AutoScalingGroup-B)へも流れるようにします。Blue環境(AutoScalingGroup-A)に紐づいているELB-AをGreen環境にも取り付けます。
# aws autoscaling attach-load-balancers --auto-scaling-group-name 'AutoScalingGroup-B' --load-balancer-names 'ELB-A'
# aws autoscaling describe-auto-scaling-groups | jq '.AutoScalingGroups[] | {AutoScalingGroupName, LoadBalancerNames, Instances}'
{
"AutoScalingGroupName": "AutoScalingGroup-A",
"LoadBalancerNames": [
"ELB-A"
],
"Instances": [
{
"InstanceId": "i-0d21ceff",
"AvailabilityZone": "ap-northeast-1a",
"HealthStatus": "Healthy",
"LifecycleState": "InService",
"LaunchConfigurationName": "webserver-20150618-01"
}
]
}
{
"AutoScalingGroupName": "AutoScalingGroup-B",
"LoadBalancerNames": [
"ELB-A",
"ELB-B"
],
"Instances": [
{
"InstanceId": "i-8f21ce7d",
"AvailabilityZone": "ap-northeast-1a",
"HealthStatus": "Healthy",
"LifecycleState": "InService",
"LaunchConfigurationName": "webserver-20150618-01"
}
]
}
ここでは以下のような状態です。
Green環境への本番切替
上記では、Blue環境とGreen環境が両方本番環境として動作しています。ここから、Blue環境を切り離し、本番アクセスをGreen環境に完全に切り替えます。 オペレーションとしては、Blue環境からELB-Aを取り外し、Green環境からELB-Bを取り外します。
# aws autoscaling detach-load-balancers --auto-scaling-group-name 'AutoScalingGroup-A' --load-balancer-names 'ELB-A'
# aws autoscaling detach-load-balancers --auto-scaling-group-name 'AutoScalingGroup-B' --load-balancer-names 'ELB-B'
# aws autoscaling describe-auto-scaling-groups | jq '.AutoScalingGroups[] | {AutoScalingGroupName, LoadBalancerNames, Instances}'
{
"AutoScalingGroupName": "AutoScalingGroup-A",
"LoadBalancerNames": [],
"Instances": [
{
"InstanceId": "i-0d21ceff",
"AvailabilityZone": "ap-northeast-1a",
"HealthStatus": "Healthy",
"LifecycleState": "InService",
"LaunchConfigurationName": "webserver-20150618-01"
}
]
}
{
"AutoScalingGroupName": "AutoScalingGroup-B",
"LoadBalancerNames": [
"ELB-A"
],
"Instances": [
{
"InstanceId": "i-8f21ce7d",
"AvailabilityZone": "ap-northeast-1a",
"HealthStatus": "Healthy",
"LifecycleState": "InService",
"LaunchConfigurationName": "webserver-20150618-01"
}
]
}
最終的な状態は以下の通りです。
動作確認
上記作業の動作確認は、以下のようなPHPを作って確認してみました。
index.php
<?php
require '/usr/local/aws/sdk-php/vendor/autoload.php';
$url = "http://169.254.169.254/latest/meta-data/instance-id/";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$instid = curl_exec($ch);
curl_close($ch);
use Aws\AutoScaling\AutoScalingClient;
$client = AutoScalingClient::factory(array(
'region' => 'ap-northeast-1'
));
$result = $client->describeAutoScalingInstances(array(
'InstanceIds' => array($instid)
));
$asg = $result['AutoScalingInstances'][0]['AutoScalingGroupName'];
if ($asg) {
$msg = 'This instance (<strong>'.$instid.'</strong>) is attached to \'<strong>'.$asg.'</strong>\' AutoScalingGroup.';
} else {
$msg = 'This instance is not attached to AutoScalingGroup.';
}
echo <<<EOT
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Test Page</title>
</head>
<body>
<p>$msg</p>
</body>
</html>
EOT;
ブラウザでアクセスすると、どちらのAuto Scalingグループにアクセスしているのかが分かります。 切替がうまくいけば、以下のようにELB-AへのアクセスがBlue環境(AutoScalingGroup-A)からGreen環境(AutoScalingGroup-B)に切り替わります。
まとめ
うーん、いい感じに切り替えられますね!今回はあえて段階を踏んで切替を行いましたが、ほぼ一瞬で切替が可能です。DNSベースでの切替でもダウンタイムは発生しませんでしたが、DNSのキャッシュを考慮する必要がありました。今回の方法では、そんなことも気にせずにスパッと切り替えられて、とても気持ちいいですね。