Unsere Anwendung erfordert die Verwendung von HAProxy zum Lastenausgleich und Routenverkehr (eine pro AZ), ALBs und ELBs sind nicht konfigurierbar genug für unsere Zwecke. Bei der Bereitstellung von neuem Code über AWS CodeDeploy möchten wir, dass die gepatchten Instanzen in den Wartungsmodus versetzt werden (aus dem Lastenausgleich entfernt, Verbindungen abgebaut). Wir haben die standardmäßigen CodeDeploy-Lebenszyklus-Bash-Skripts so geändert, dass sie die Instanzen aus ihren jeweiligen HAProxy-Instanzen entfernen, indem sie einen SSM-Ausführungsbefehl von den betreffenden Instanzen an HAProxy senden. Derzeit funktioniert diese Änderung nicht und der Grund für den Fehler ist unbekannt. Das Skript funktioniert bei der manuellen Ausführung Schritt für Schritt (zumindest bis zum aktuellen Fehlerpunkt). Der Teil, der fehlschlägt, ist entweder der Test, der "$ INSTANCE_ID scheint nicht in einem AZ mit einer HAProxy-Instanz zu sein, die Deregistrierung überspringt.", Oder die Einstellung von $ HAPROXY_ID, von der der vorher erwähnte Test abhängt. Das Skript läuft bis zu diesem Punkt einwandfrei, wird aber an diesem Punkt beendet, da die HAProxy-Instanz-ID nicht gefunden werden kann.Entfernen von Instanzen von HAProxy während AWS CodeDeploy
Ich habe IAM Rollenberechtigungen/Berechtigungsnachweise, Umgebungsvariablen und Dateiberechtigungen überprüft, die alle korrekt zu sein scheinen. Normalerweise würde ich mehr Logging in das Skript legen, um zu debuggen, aber die Implementierungen sind zu wenig und weit genug, um das praktisch zu machen.
Meine Frage: Gibt es einen besseren Weg, dies zu tun? Ich kann nur raten, dass wir nicht die einzigen sind, die HAProxy mit CodeDeploy verwenden, und dazu muss es eine zuverlässige Methode geben. Im Folgenden wird der aktuelle Code verwendet, der nicht funktioniert.
#!/bin/bash
#
# Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License").
# You may not use this file except in compliance with the License.
# A copy of the License is located at
#
# http://aws.amazon.com/apache2.0
#
# or in the "license" file accompanying this file. This file is distributed
# on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
# express or implied. See the License for the specific language governing
# permissions and limitations under the License.
. $(dirname $0)/common_functions.sh
if [[ "$DEPLOYMENT_GROUP_NAME" != "redacted" ]]; then
msg "ELB Deregistration doesn't need to happen when not on redacted."
exit
fi
msg "Running AWS CLI with region: $(get_instance_region)"
# get this instance's ID
INSTANCE_ID=$(get_instance_id)
if [ $? != 0 -o -z "$INSTANCE_ID" ]; then
error_exit "Unable to get this instance's ID; cannot continue."
fi
# Get current time
msg "Started $(basename $0) at $(/bin/date "+%F %T")"
start_sec=$(/bin/date +%s.%N)
msg "Checking if instance $INSTANCE_ID is part of an AutoScaling group"
asg=$(autoscaling_group_name $INSTANCE_ID)
if [ $? == 0 -a -n "${asg}" ]; then
msg "Found AutoScaling group for instance $INSTANCE_ID: ${asg}"
msg "Checking that installed CLI version is at least at version required for AutoScaling Standby"
check_cli_version
if [ $? != 0 ]; then
error_exit "CLI must be at least version ${MIN_CLI_X}.${MIN_CLI_Y}.${MIN_CLI_Z} to work with AutoScaling Standby"
fi
msg "Attempting to put instance into Standby"
autoscaling_enter_standby $INSTANCE_ID "${asg}"
if [ $? != 0 ]; then
error_exit "Failed to move instance into standby"
else
msg "Instance is in standby"
fi
fi
msg "Instance is not part of an ASG, continuing..."
## Get the instanceID of the HAProxy instance in this AZ and ENVIRONMENT - Will there ever be more than one???
HAPROXY_ID=$(/usr/local/bin/aws ec2 describe-instances --region us-east-1 --filters "Name=availability-zone,Values=$(/usr/bin/curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone)" "Name=tag:deployment_group,Values=haproxy.$ENVIRONMENT" --output text | \
grep INSTANCES | \
awk '{print $8}')
HAPROXY_IP=$(/usr/local/bin/aws ec2 describe-instances --region us-east-1 --filters "Name=availability-zone,Values=$(/usr/bin/curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone)" "Name=tag:deployment_group,Values=haproxy.$ENVIRONMENT" --output text | \
grep INSTANCES | \
awk '{print $13}')
if test -z "$HAPROXY_ID"; then
msg "$INSTANCE_ID doesn't seem to be in an AZ with a HAProxy instance, skipping deregistration."
exit
fi
## Put the current instance into MAINT mode with the HAProxy instance via SSM
msg "Deregistering $INSTANCE_ID from HAProxy $HAPROXY_ID"
DEREGCMD="{\"commands\":[\"haproxyctl disable server bk_app_servers/$INSTANCEID\"],\"executionTimeout\":[\"3600\"]}"
/usr/local/bin/aws ssm send-command \
--document-name "AWS-RunShellScript" \
--instance-ids "$HAPROXY_ID" \
--parameters "$DEREGCMD" \
--timeout-seconds 600 \
--output-s3-bucket-name "redacted" \
--output-s3-key-prefix "haproxy-codedeploy/deregister" \
--region us-east-1
if [ $? != 0 ]; then
error_exit "Failed to send SSM command to deregister instance $INSTANCE_ID from HAProxy $HAPROXY_ID"
fi
## Wait for all connections to drain from instance
SESS_COUNT=$(/usr/bin/curl -s "http://$HAPROXY_IP:<portredacted>/<urlredacted>" | grep $INSTANCEID | awk -F "," '{print $5}')
DRAIN_TIME=60
msg "Initial session count: $SESS_COUNT"
while [[ "$SESS_COUNT" -gt 0 ]]; do
if [[ "$COUNTER" -gt "$DRAIN_TIME" ]]; then
msg "Instance failed to drain all connections within $DRAIN_TIME seconds. Continuing to deploy anyway."
break
fi
msg $SESS_COUNT
sleep 1
COUNTER=$(($COUNTER + 1))
SESS_COUNT=$(/usr/bin/curl -s "http://$HAPROXY_IP:<portredacted>/<urlredacted>" | grep $INSTANCEID | awk -F "," '{print $5}')
done
msg "Finished $(basename $0) at $(/bin/date "+%F %T")"
end_sec=$(/bin/date +%s.%N)
elapsed_seconds=$(echo "$end_sec - $start_sec" | /usr/bin/bc)
msg "Elapsed time: $elapsed_seconds"