次の通りNLBをCloudformationで作成し、Codepipelineで実行していたとします。
AWSTemplateFormatVersion: "2010-09-09"
Resources:
ElasticLoadBalancingV2LoadBalancer:
Type: "AWS::ElasticLoadBalancingV2::LoadBalancer"
Properties:
Name: "import-nlb"
Scheme: "internal"
Type: "network"
Subnets:
- "subnet-XXX"
- "subnet-XXX"
IpAddressType: "ipv4"
LoadBalancerAttributes:
-
Key: "access_logs.s3.enabled"
Value: "false"
-
Key: "deletion_protection.enabled"
Value: "false"
-
Key: "load_balancing.cross_zone.enabled"
Value: "false"
ElasticLoadBalancingV2Listener:
Type: "AWS::ElasticLoadBalancingV2::Listener"
Properties:
LoadBalancerArn: !Ref ElasticLoadBalancingV2LoadBalancer
Port: 80
Protocol: "TCP"
DefaultActions:
-
Order: 1
TargetGroupArn: !Ref ElasticLoadBalancingV2TargetGroup
Type: "forward"
ElasticLoadBalancingV2TargetGroup:
Type: "AWS::ElasticLoadBalancingV2::TargetGroup"
Properties:
HealthCheckIntervalSeconds: 30
Port: 80
Protocol: "TCP"
HealthCheckPort: "traffic-port"
HealthCheckProtocol: "TCP"
HealthCheckTimeoutSeconds: 10
UnhealthyThresholdCount: 3
TargetType: "ip"
HealthyThresholdCount: 3
VpcId: "vpc-XXX"
Name: "import-tg"
HealthCheckEnabled: true
TargetGroupAttributes:
-
Key: "proxy_protocol_v2.enabled"
Value: "false"
-
Key: "preserve_client_ip.enabled"
Value: "false"
-
Key: "stickiness.enabled"
Value: "false"
-
Key: "deregistration_delay.timeout_seconds"
Value: "300"
-
Key: "stickiness.type"
Value: "source_ip"
-
Key: "deregistration_delay.connection_termination.enabled"
Value: "false"
次に、コンソールからNLBリスナーをわざと削除してから、コンソールで再作成します。
この場合、Cloudformationテンプレートとコンソールから再作成したものに差が出ることとなります。
次にCloudformationテンプレートのNLBリスナーのリソースをコメントアウトし、Codepipelineを実行してみます。
# ElasticLoadBalancingV2Listener:
# Type: "AWS::ElasticLoadBalancingV2::Listener"
# Properties:
# LoadBalancerArn: !Ref ElasticLoadBalancingV2LoadBalancer
# Port: 80
# Protocol: "TCP"
# DefaultActions:
# -
# Order: 1
# TargetGroupArn: !Ref ElasticLoadBalancingV2TargetGroup
# Type: "forward"
NLBリスナーはコンソールから再作成しているため、当然消えません。
では、ここからが本題です。
コンソールから再作成したNLBリスナーをCloudformationのインポート機能を利用して、テンプレート化します。
なお、Cloudformationのインポートにリソースがサポートしている必要があるので注意しましょう。
Cloudformationのコンソールから作業します。
先程コメントアウトした箇所を解除したものと、DeletionPolicy: Retain
を追加したCloudformationテンプレートを準備しておきます。
「スタックアクション」から、「スタックへのリソースのインポート」をクリック。
「cloudformation.yml」をアップロードし、「次へ」をクリック。
コンソールから再作成したNLBリスナーのarnを入力し、「次へ」。
コンソールから再作成したNLBリスナーのarnが指定されていることを確認し、「リソースをインポート」。
「ドリフトの検出」後「ドリフト結果を表示」からCloudformationテンプレートに差がないか確認してみましょう。
NLBリスナーのリソースを確認し、「IN_SYNC」と差がないことが確認できました。
次に、コメントアウトした箇所を解除したCloudformationテンプレートをCodepipelineから実行してみます。
ハマりどころ。。。
Cloudformationのイベントを確認すると、「IMPORT_COMPLETE」から変化しません。
Codepipelineを停止して中止後、Cloudformationから直接スタックを更新してみます。
この時同じCloudformationテンプレートでは、次のようなエラーが表示されてしまうため、DeletionPolicy: Retain
を外した状態でスタックを更新してみます。
この変更セットの作成中にエラーが発生しました The submitted information didn't contain changes. Submit different information to create a change set.
Cloudformationスタックのステータスが、「UPDATE_COMPLETE」となったことを確認します。
この状態で、Codepipelineを再度実行してみます。今度はCodepipelineが最後まで完了したみたいです。
Cloudformationスタックのステータスが「IMPORT_COMPLETE」では、Codepipelineから実行すると、変化しないということでしょうか?