首页 > 解决方案 > Cloudformation 蓝/绿部署 HealthCheckGracePeriodSeconds

问题描述

我正在尝试使用 Cloudformation Codedeploy Blue/Green 部署功能,因此有一个如下所示的任务集。

TaskSet:
  Type: AWS::ECS::TaskSet
  Properties:
    Cluster: 
      Fn::ImportValue: !Sub "${ClusterStackName}-ClusterID"
    LaunchType: FARGATE
    NetworkConfiguration:
      AwsVpcConfiguration:
        AssignPublicIp: ENABLED
        SecurityGroups: 
          - !Ref FargateSecurityGroup
        Subnets: 
          - Fn::ImportValue: !Sub "${ClusterStackName}-SUBNET1ID"
          - Fn::ImportValue: !Sub "${ClusterStackName}-SUBNET2ID"
    PlatformVersion: 1.3.0
    Scale:
      Unit: PERCENT
      Value: 1
    Service: !Ref ECSService
    TaskDefinition: !Ref TaskDefinition
    LoadBalancers: 
      - ContainerName: !Ref ServiceName
        ContainerPort: !Ref ContainerPort
        TargetGroupArn: !Ref TargetGroup

我的 ECS 服务定义如下所示

ECSService:
  Type: AWS::ECS::Service
  DependsOn: HTTPSListener
  Properties: 
    ServiceName: !Sub "${ServiceName}-service"
    Cluster: 
      Fn::ImportValue: !Sub "${ClusterStackName}-ClusterID"
    DeploymentController: 
      Type: EXTERNAL
    DesiredCount: 4
    EnableECSManagedTags: true
    HealthCheckGracePeriodSeconds: 30
    SchedulingStrategy: REPLICA

这会导致 Cloudformation 出现以下错误

Invalid request provided: CreateService error: Health check grace period is only valid for services configured to use load balancers 

但是,省略HealthCheckGracePeriodSeconds会导致我的任务在启动时无法通过运行状况检查。我检查了文档,似乎没有添加HealthCheckGracePeriodSecondsTaskSet定义中的选项。

如何使用具有运行状况检查宽限期的 ECS 的 Cloudformation 蓝/绿部署?

完整示例

这是一个完整的模板,我希望它可以工作,但不能。

AWSTemplateFormatVersion: 2010-09-09
Parameters: 
  Image: 
    Type: String
  Vpc:
    Type: 'AWS::EC2::VPC::Id'
  Subnet1:
    Type: 'AWS::EC2::Subnet::Id'
  Subnet2:
    Type: 'AWS::EC2::Subnet::Id'

Transform:
  - AWS::CodeDeployBlueGreen

Hooks:
  CodeDeployBlueGreenHook:
    Type: AWS::CodeDeploy::BlueGreen
    Properties:
      TrafficRoutingConfig:
        Type: AllAtOnce
      Applications:
        - Target:
            Type: AWS::ECS::Service
            LogicalID: ECSService
          ECSAttributes:
            TaskDefinitions:
              - TaskDefinition
              - GreenTaskDefinition
            TaskSets:
              - TaskSet
              - GreenTaskSet
            TrafficRouting:
              ProdTrafficRoute:
                Type: AWS::ElasticLoadBalancingV2::Listener
                LogicalID: HTTPListener
              TargetGroups:
                - TargetGroup
                - TargetGroupGreen
    
Resources: 
  ALBSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Allow HTTP to load balancer
      VpcId: !Ref Vpc
      SecurityGroupIngress:
      - IpProtocol: tcp
        FromPort: 80
        ToPort: 80
        CidrIp: 0.0.0.0/0
      SecurityGroupEgress:
      - IpProtocol: -1
        CidrIp: 0.0.0.0/0

  FargateSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Allow port 80 to service
      VpcId: !Ref Vpc
      SecurityGroupIngress:
      - IpProtocol: tcp
        FromPort: 80
        ToPort: 80
        SourceSecurityGroupId: !Ref ALBSecurityGroup
      SecurityGroupEgress:
      - IpProtocol: -1
        CidrIp: 0.0.0.0/0

  LoadBalancer:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Properties:
      Name: load-balancer
      Type: application
      IpAddressType: ipv4
      Scheme: internet-facing
      SecurityGroups: [!Ref ALBSecurityGroup]
      Subnets: [!Ref Subnet1, !Ref Subnet2]

  HTTPListener:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      DefaultActions:
        - TargetGroupArn: !Ref TargetGroup
          Type: forward
      LoadBalancerArn: !Ref LoadBalancer
      Port: 80
      Protocol: HTTP

  TargetGroup:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Properties:
      HealthCheckEnabled: true
      HealthCheckIntervalSeconds: 30
      HealthCheckPath: "/"
      HealthCheckTimeoutSeconds: 10
      HealthyThresholdCount: 5
      Name: targetgroup-blue
      Port: 80
      Protocol: HTTP
      TargetType: ip
      UnhealthyThresholdCount: 10
      VpcId: !Ref Vpc

  TargetGroupGreen:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Properties:
      HealthCheckEnabled: true
      HealthCheckIntervalSeconds: 30
      HealthCheckPath: "/"
      HealthCheckTimeoutSeconds: 10
      HealthyThresholdCount: 5
      Name: targetgroup-green
      Port: 80
      Protocol: HTTP
      TargetType: ip
      UnhealthyThresholdCount: 10
      VpcId: !Ref Vpc
      
  TaskDefinition:
    Type: AWS::ECS::TaskDefinition
    Properties:
      Family: "task-family-name"
      NetworkMode: awsvpc
      RequiresCompatibilities: [FARGATE]
      Cpu: 512
      Memory: 1024
      ContainerDefinitions:
        - Name: Container
          Essential: true
          Image: !Ref Image
          PortMappings:
            - ContainerPort: 80

  TaskSet:
    Type: AWS::ECS::TaskSet
    Properties:
      Cluster: !Ref ECSCluster
      LaunchType: FARGATE
      NetworkConfiguration:
        AwsVpcConfiguration:
          AssignPublicIp: ENABLED
          SecurityGroups: [!Ref FargateSecurityGroup]
          Subnets: [!Ref Subnet1, !Ref Subnet2]
      Scale:
        Unit: PERCENT
        Value: 100
      Service: !Ref ECSService
      TaskDefinition: !Ref TaskDefinition
      PlatformVersion: LATEST
      LoadBalancers: 
        - ContainerName: Container
          ContainerPort: 80
          TargetGroupArn: !Ref TargetGroup

  ECSService:
    Type: AWS::ECS::Service
    DependsOn: HTTPListener
    Properties: 
      ServiceName: "service"
      Cluster: !Ref ECSCluster
      DeploymentController: 
        Type: EXTERNAL
      DesiredCount: 4
      EnableECSManagedTags: true
      HealthCheckGracePeriodSeconds: 30
      SchedulingStrategy: REPLICA
    
  PrimaryTaskSet:
    Type: 'AWS::ECS::PrimaryTaskSet'
    Properties:
      Cluster: !Ref ECSCluster
      Service: !Ref ECSService
      TaskSetId: !GetAtt 'TaskSet.Id'

  ECSCluster:
    Type: AWS::ECS::Cluster
    Properties:
      ClusterName: Cluster
      CapacityProviders:
        - FARGATE
      DefaultCapacityProviderStrategy:
        - CapacityProvider: FARGATE
          Weight: 1

标签: amazon-web-servicesamazon-cloudformationamazon-ecsaws-code-deploy

解决方案


错误是正确的,级别的健康检查Service,将需要一个Load Balancer. 但是,您可以在任务级别定义运行状况检查:

  EscTaskDef:
    Type: 'AWS::ECS::TaskDefinition'
    Properties:
...
      ContainerDefinitions:
        - Name: !Ref AWS::StackName
          Image: !Ref Image
          PortMappings:
            - ContainerPort: 80

          HealthCheck:
            Command: [ "CMD-SHELL", "curl -f http://localhost:80/api/healthcheck/ping || exit 1" ]
            StartPeriod: 200

以下是使用此类健康检查的回滚示例Cloudformation


推荐阅读