翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。
Step Functions でステートマシンバージョンの段階的なデプロイを実行する
ローリングデプロイとは、アプリケーションの以前のバージョンを新しいバージョンのアプリケーションに徐々に置き換えるデプロイ戦略です。ステートマシンバージョンのローリングデプロイを行うには、徐々に増加する実行トラフィックを新しいバージョンに送信します。トラフィックの量と増加率は、設定するパラメータです。
次のいずれかのオプションを使用して、バージョンのローリングデプロイを実行できます。
-
Step Functions コンソール
- 同じステートマシンの 2 つのバージョンを指すエイリアスを作成します。このエイリアスでは、2 つのバージョン間でトラフィックをシフトするようルーティングを設定します。コンソールを使用したバージョンのロールアウトに関する詳細については、「バージョン」および「エイリアス」を参照してください。 -
のスクリプト AWS CLI および SDK- を使用してシェルスクリプトを作成する AWS CLI または AWS SDK。詳細については、 の使用に関する以下のセクションを参照してください。 AWS CLI また、 AWS SDK.
-
AWS CloudFormation テンプレート –
AWS::StepFunctions::StateMachineVersion
およびAWS::StepFunctions::StateMachineAlias
リソースを使用して、複数のステートマシンバージョンを公開し、これらのバージョンの 1 つまたは 2 つを指すエイリアスを作成します。
このセクションのスクリプト例は、 AWS CLI は、トラフィックを以前のステートマシンバージョンから新しいステートマシンバージョンに徐々に移行します。このサンプルスクリプトを使用することも、必要に応じて更新することもできます。
このスクリプトは、エイリアスを使用して新しいステートマシンバージョンをデプロイするための Canary デプロイを示しています。以下の手順は、このスクリプトが実行するタスクの概要を示しています。
-
publish_revision
パラメータが true に設定されている場合は、最新の revision を、ステートマシンの次のバージョンとして公開します。デプロイが成功すると、このバージョンが新しいライブバージョンになります。publish_revision
パラメータを false に設定すると、スクリプトは、最後に公開されたバージョンのステートマシンをデプロイします。 -
エイリアスがまだ存在しない場合は作成します。エイリアスが存在しない場合は、このエイリアスへのトラフィックの 100% を新しいバージョンにルーティングして、スクリプトを終了します。
-
エイリアスのルーティング設定を更新して、トラフィックのごく一部を以前のバージョンから新しいバージョンにシフトします。canary のこの割合は
canary_percentage
パラメータで設定します。 -
デフォルトでは、設定可能な CloudWatch アラームを 60 秒ごとにモニタリングします。これらのアラームのいずれかが発せられたら、トラフィックの 100% を以前のバージョンにルーティングし、すぐにデプロイをロールバックしてください。
alarm_polling_interval
で定義した時間間隔 (秒単位) が経過したら、引き続きアラームをモニタリングします。canary_interval_seconds
で定義した時間間隔が経過するまでモニタリングを続けます。 -
canary_interval_seconds
の間にアラームが鳴らなかった場合は、トラフィックの 100% を新しいバージョンにシフトします。 -
新しいバージョンが正常にデプロイされたら、
history_max
パラメータで指定された番号より古いバージョンをすべて削除します。
#!/bin/bash # # AWS StepFunctions example showing how to create a canary deployment with a # State Machine Alias and versions. # # Requirements: AWS CLI installed and credentials configured. # # A canary deployment deploys the new version alongside the old version, while # routing only a small fraction of the overall traffic to the new version to # see if there are any errors. Only once the new version has cleared a testing # period will it start receiving 100% of traffic. # # For a Blue/Green or All at Once style deployment, you can set the # canary_percentage to 100. The script will immediately shift 100% of traffic # to the new version, but keep on monitoring the alarms (if any) during the # canary_interval_seconds time interval. If any alarms raise during this period, # the script will automatically rollback to the previous version. # # Step Functions allows you to keep a maximum of 1000 versions in version history # for a state machine. This script has a version history deletion mechanism at # the end, where it will delete any versions older than the limit specified. # # For an example that also demonstrates linear (or rolling) deployments, see the following: # https://github.com/aws-samples/aws-stepfunctions-examples/blob/main/gradual-deploy/sfndeploy.py set -euo pipefail # ****************************************************************************** # you can safely change the variables in this block to your values state_machine_name="my-state-machine" alias_name="alias-1" region="us-east-1" # array of cloudwatch alarms to poll during the test period. # to disable alarm checking, set alarm_names=() alarm_names=("alarm1" "alarm name with a space") # true to publish the current revision as the next version before deploy. # false to deploy the latest version from the state machine's version history. publish_revision=true # true to force routing configuration update even if the current routing # for the alias does not have a 100% routing config. # false will abandon deploy attempt if current routing config not 100% to a # single version. # Be careful when you combine this flag with publish_revision - if you just # rerun the script you might deploy the newly published revision from the # previous run. force=false # percentage of traffic to route to the new version during the test period canary_percentage=10 # how many seconds the canary deployment lasts before full deploy to 100% canary_interval_seconds=300 # how often to poll the alarms alarm_polling_interval=60 # how many versions to keep in history. delete versions prior to this. # set to 0 to disable old version history deletion. history_max=0 # ****************************************************************************** ####################################### # Update alias routing configuration. # # If you don't specify version 2 details, will only create 1 routing entry. In # this case the routing entry weight must be 100. # # Globals: # alias_arn # Arguments: # 1. version 1 arn # 2. version 1 weight # 3. version 2 arn (optional) # 4. version 2 weight (optional) ####################################### function update_routing() { if [[ $# -eq 2 ]]; then local routing_config="[{\"stateMachineVersionArn\": \"$1\", \"weight\":$2}]" elif [[ $# -eq 4 ]]; then local routing_config="[{\"stateMachineVersionArn\": \"$1\", \"weight\":$2}, {\"stateMachineVersionArn\": \"$3\", \"weight\":$4}]" else echo "You have to call update_routing with either 2 or 4 input arguments." >&2 exit 1 fi ${aws} update-state-machine-alias --state-machine-alias-arn ${alias_arn} --routing-configuration "${routing_config}" } # ****************************************************************************** # pre-run validation if [[ (("${#alarm_names[@]}" -gt 0)) ]]; then alarm_exists_count=$(aws cloudwatch describe-alarms --alarm-names "${alarm_names[@]}" --alarm-types "CompositeAlarm" "MetricAlarm" --query "length([MetricAlarms, CompositeAlarms][])" --output text) if [[ (("${#alarm_names[@]}" -ne "${alarm_exists_count}")) ]]; then echo All of the alarms to monitor do not exist in CloudWatch: $(IFS=,; echo "${alarm_names[*]}") >&2 echo Only the following alarm names exist in CloudWatch: aws cloudwatch describe-alarms --alarm-names "${alarm_names[@]}" --alarm-types "CompositeAlarm" "MetricAlarm" --query "join(', ', [MetricAlarms, CompositeAlarms][].AlarmName)" --output text exit 1 fi fi if [[ (("${history_max}" -gt 0)) && (("${history_max}" -lt 2)) ]]; then echo The minimum value for history_max is 2. This is the minimum number of older state machine versions to be able to rollback in the future. >&2 exit 1 fi # ****************************************************************************** # main block follows account_id=$(aws sts get-caller-identity --query Account --output text) sm_arn="arn:aws:states:${region}:${account_id}:stateMachine:${state_machine_name}" # the aws command we'll be invoking a lot throughout. aws="aws stepfunctions" # promote the latest revision to the next version if [[ "${publish_revision}" = true ]]; then new_version=$(${aws} publish-state-machine-version --state-machine-arn=$sm_arn --query stateMachineVersionArn --output text) echo Published the current revision of state machine as the next version with arn: ${new_version} else new_version=$(${aws} list-state-machine-versions --state-machine-arn ${sm_arn} --max-results 1 --query "stateMachineVersions[0].stateMachineVersionArn" --output text) echo "Since publish_revision is false, using the latest version from the state machine's version history: ${new_version}" fi # find the alias if it exists alias_arn_expected="${sm_arn}:${alias_name}" alias_arn=$(${aws} list-state-machine-aliases --state-machine-arn ${sm_arn} --query "stateMachineAliases[?stateMachineAliasArn==\`${alias_arn_expected}\`].stateMachineAliasArn" --output text) if [[ "${alias_arn_expected}" == "${alias_arn}" ]]; then echo Found alias ${alias_arn} echo Current routing configuration is: ${aws} describe-state-machine-alias --state-machine-alias-arn "${alias_arn}" --query routingConfiguration else echo Alias does not exist. Creating alias ${alias_arn_expected} and routing 100% traffic to new version ${new_version} ${aws} create-state-machine-alias --name "${alias_name}" --routing-configuration "[{\"stateMachineVersionArn\": \"${new_version}\", \"weight\":100}]" echo Done! exit 0 fi # find the version to which the alias currently points (the current live version) old_version=$(${aws} describe-state-machine-alias --state-machine-alias-arn $alias_arn --query "routingConfiguration[?weight==\`100\`].stateMachineVersionArn" --output text) if [[ -z "${old_version}" ]]; then if [[ "${force}" = true ]]; then echo Force setting is true. Will force update to routing config for alias to point 100% to new version. update_routing "${new_version}" 100 echo Alias ${alias_arn} now pointing 100% to ${new_version}. echo Done! exit 0 else echo Alias ${alias_arn} does not have a routing config entry with 100% of the traffic. This means there might be a deploy in progress, so not starting another deploy at this time. >&2 exit 1 fi fi if [[ "${old_version}" == "${new_version}" ]]; then echo The alias already points to this version. No update necessary. exit 0 fi echo Switching ${canary_percentage}% to new version ${new_version} (( old_weight = 100 - ${canary_percentage} )) update_routing "${new_version}" ${canary_percentage} "${old_version}" ${old_weight} echo New version receiving ${canary_percentage}% of traffic. echo Old version ${old_version} is still receiving ${old_weight}%. if [[ ${#alarm_names[@]} -eq 0 ]]; then echo No alarm_names set. Skipping cloudwatch monitoring. echo Will sleep for ${canary_interval_seconds} seconds before routing 100% to new version. sleep ${canary_interval_seconds} echo Canary period complete. Switching 100% of traffic to new version... else echo Checking if alarms fire for the next ${canary_interval_seconds} seconds. (( total_wait = canary_interval_seconds + $(date +%s) )) now=$(date +%s) while [[ ((${now} -lt ${total_wait})) ]]; do alarm_result=$(aws cloudwatch describe-alarms --alarm-names "${alarm_names[@]}" --state-value ALARM --alarm-types "CompositeAlarm" "MetricAlarm" --query "join(', ', [MetricAlarms, CompositeAlarms][].AlarmName)" --output text) if [[ ! -z "${alarm_result}" ]]; then echo The following alarms are in ALARM state: ${alarm_result}. Rolling back deploy. >&2 update_routing "${old_version}" 100 echo Rolled back to ${old_version} exit 1 fi echo Monitoring alarms...no alarms have triggered. sleep ${alarm_polling_interval} now=$(date +%s) done echo No alarms detected during canary period. Switching 100% of traffic to new version... fi update_routing "${new_version}" 100 echo Version ${new_version} is now receiving 100% of traffic. if [[ (("${history_max}" -eq 0 ))]]; then echo Version History deletion is disabled. Remember to prune your history, the default limit is 1000 versions. echo Done! exit 0 fi echo Keep the last ${history_max} versions. Deleting any versions older than that... # the results are sorted in descending order of the version creation time version_history=$(${aws} list-state-machine-versions --state-machine-arn ${sm_arn} --max-results 1000 --query "join(\`\"\\n\"\`, stateMachineVersions[].stateMachineVersionArn)" --output text) counter=0 while read line; do ((counter=${counter} + 1)) if [[ (( ${counter} -gt ${history_max})) ]]; then echo Deleting old version ${line} ${aws} delete-state-machine-version --state-machine-version-arn ${line} fi done <<< "${version_history}" echo Done!
のサンプルスクリプトaws-stepfunctions-examples
このスクリプトは、以下のデプロイ戦略を示しています。
-
Canary - トラフィックは 2 つの増分で移行されます。
1 回目の増分では、トラフィックのごく一部、例えば 10% が新しいバージョンにシフトされます。2 回目の増分では、指定した秒単位の時間間隔が経過する前に、残りのトラフィックが新しいバージョンにシフトされます。残りのトラフィックの新しいバージョンへの切り替えは、指定された時間間隔内に CloudWatch アラームがオフになっていない場合にのみ行われます。
-
リニアまたはローリング - トラフィックを同じ間隔で、各増分の間隔を同じ秒数空けて新しいバージョンにシフトします。
例えば、増加率を
600
秒のうちの--interval
の20
として指定すると、このデプロイでは、新しいバージョンがトラフィックの 100% を受信するまで、600 秒ごとに 20% ずつトラフィックが増加します。このデプロイでは、 CloudWatch アラームがオフになっている場合、新しいバージョンがすぐにロールバックされます。
-
All at Once または Blue/Green - トラフィックの 100% をただちに新しいバージョンに移行します。このデプロイでは、新しいバージョンをモニタリングし、 CloudWatch アラームがオフになっている場合は、自動的に以前のバージョンにロールバックします。
次の CloudFormation テンプレート例では、 という名前のステートマシンの 2 つのバージョンを公開しています
。両方のバージョンを指す MyStateMachine
というエイリアスを作成して、バージョン PROD
2
をデプロイします。
この例では、このバージョンがトラフィックの 100% を受信するまで、5 分ごとにトラフィックの 10% がバージョン 2
に移行されます。この例では、 を設定する方法も示しています。CloudWatch アラーム。設定したアラームのいずれかが ALARM
状態になると、デプロイは失敗し、すぐにロールバックされます。
MyStateMachine: Type: AWS::StepFunctions::StateMachine Properties: Type: STANDARD StateMachineName: MyStateMachine RoleArn: arn:aws:iam::123456789012:role/myIamRole Definition: StartAt: PassState States: PassState: Type: Pass Result: Result End: true MyStateMachineVersionA: Type: AWS::StepFunctions::StateMachineVersion Properties: Description: Version 1 StateMachineArn: !Ref MyStateMachine MyStateMachineVersionB: Type: AWS::StepFunctions::StateMachineVersion Properties: Description: Version 2 StateMachineArn: !Ref MyStateMachine PROD: Type: AWS::StepFunctions::StateMachineAlias Properties: Name: PROD Description: The PROD state machine alias taking production traffic. DeploymentPreference: StateMachineVersionArn: !Ref MyStateMachineVersionB Type: LINEAR Percentage: 10 Interval: 5 Alarms: # A list of alarms that you want to monitor. If any of these alarms trigger, rollback the deployment immediately by pointing 100 percent of traffic to the previous version. - !Ref CloudWatchAlarm1 - !Ref CloudWatchAlarm2