blob: 589040c55d6f9f23f2de8768141698ef9756ddae [file] [log] [blame]
AWSTemplateFormatVersion: '2010-09-09'
Description: Gerrit primary launch configuration and autoscaling group
Parameters:
TemplateBucketName:
Description: S3 bucket containing cloudformation templates
Type: String
EC2AMI:
Description: AMI ID for the EC2 instance hosting gerrit primaries
Type: String
InstanceType:
Description: EC2 instance type
Type: String
AllowedValues: [t2.micro, t2.small, t2.medium, t2.large, m3.medium, m3.large,
m3.xlarge, m3.2xlarge, m4.large, m4.xlarge, m4.2xlarge, m4.4xlarge, m4.10xlarge,
c4.large, c4.xlarge, c4.2xlarge, c4.4xlarge, c4.8xlarge, c3.large, c3.xlarge,
c3.2xlarge, c3.4xlarge, c3.8xlarge, r3.large, r3.xlarge, r3.2xlarge, r3.4xlarge,
r3.8xlarge, i2.xlarge, i2.2xlarge, i2.4xlarge, i2.8xlarge]
ConstraintDescription: Please choose a valid instance type.
ECSKeyName:
Type: String
Description: EC2 key pair name the cluter's instances
EnvironmentName:
Description: An environment name used to build the log stream names
Type: String
ECSCluster:
Description: The ECSCluster reference name to register gerrit primaries to
Type: String
EC2SecurityGroup:
Description: security groups to assign to the instances in the Auto Scaling group hosting gerrit primaries
Type: String
EC2InstanceProfile:
Description: The Amazon Resource Name (ARN) of the instance profile associated with the IAM role for the EC2 instances running gerrit primaries
Type: String
GerritInstanceNumber:
Description: Whether this is primary1 or primary2
Type: Number
AllowedValues: [1,2]
FileSystem:
Description: The ID of the filesystem to share git data between gerrit primary instances
Type: String
SubnetId:
Description: The subnet ID where gerrit primary in the Auto Scaling group can be created
Type: String
AvailabilityZone:
Description: The Availability Zone in which to create the volume from a snapshot
Type: String
LogGroupName:
Description: The log group name
Type: String
PrimaryMaxCount:
Description: The maximum number of EC2 instances in the primary autoscaling group
Type: Number
GerritVolumeSnapshotId:
Description: Id of the EBS snapshot for Gerrit volume
Type: String
GerritVolumeAttachMaxRetries:
Description: Maximum number of retries when attaching Gerrit Volume
Type: Number
GerritVolumeAttachRetryDelay:
Description: The delay in seconds between Gerrit Volume attach attempts
Type: Number
GerritVolumeSizeInGiB:
Description: Gerrit volume size in GiB
Type: Number
Resources:
PrimaryECSAutoScalingGroup:
Type: AWS::AutoScaling::AutoScalingGroup
Properties:
VPCZoneIdentifier:
- !Ref SubnetId
LaunchTemplate:
LaunchTemplateId: !Ref 'PrimaryLaunchTemplate'
Version: !GetAtt PrimaryLaunchTemplate.DefaultVersionNumber
MinSize: '1'
MaxSize: !Ref PrimaryMaxCount
DesiredCapacity: '1'
CreationPolicy:
ResourceSignal:
Timeout: PT15M
UpdatePolicy:
AutoScalingReplacingUpdate:
WillReplace: 'true'
PrimaryLaunchTemplate:
Type: AWS::EC2::LaunchTemplate
Properties:
LaunchTemplateName: !Sub ${AWS::StackName}-lt-primary${GerritInstanceNumber}
LaunchTemplateData:
ImageId: !Ref 'EC2AMI'
SecurityGroupIds:
- !Ref EC2SecurityGroup
InstanceType: !Ref 'InstanceType'
IamInstanceProfile:
Arn: !Ref 'EC2InstanceProfile'
KeyName: !Ref ECSKeyName
UserData:
Fn::Base64: !Sub |
#!/bin/bash -xe
export PRIMARY_ID=primary-${GerritInstanceNumber}
echo ECS_CLUSTER=${ECSCluster} >> /etc/ecs/ecs.config
echo ECS_INSTANCE_ATTRIBUTES={\"target_group\":\"$PRIMARY_ID\"} >> /etc/ecs/ecs.config
yum install -y aws-cfn-bootstrap nfs-utils wget aws-cli xfsprogs
EC2_INSTANCE_ID=`curl -s http://169.254.169.254/latest/meta-data/instance-id`
VOLUME_ID=${GerritVolumeStack.Outputs.GerritVolumeRef}
echo "Volume Id: $VOLUME_ID"
aws ec2 attach-volume --region ${AWS::Region} --volume-id $VOLUME_ID --instance-id $EC2_INSTANCE_ID --device /dev/xvdg
for i in $(seq 1 ${GerritVolumeAttachMaxRetries}); do
echo "Waiting for volume $VOLUME_ID to be attached to the instace $EC2_INSTANCE_ID ($i/${GerritVolumeAttachMaxRetries})"
volumeStatus=`aws ec2 describe-volumes --region ${AWS::Region} --volume-ids $VOLUME_ID`
if [[ $volumeStatus =~ "\"State\": \"attached\"" ]]; then
echo "Volume $VOLUME_ID attached to the instace $EC2_INSTANCE_ID"
break
elif [[ "$i" -eq "${GerritVolumeAttachMaxRetries}" ]]; then
echo "Could not attach the volume $VOLUME_ID to the instace $EC2_INSTANCE_ID after ${GerritVolumeAttachMaxRetries} attempts"
exit 1
fi
sleep ${GerritVolumeAttachRetryDelay}
done
if [[ "${GerritVolumeSnapshotId}" = "" ]]; then
echo "Create file system for Gerrit volume"
mkfs -t xfs /dev/xvdg
fi
mkdir /gerrit-mount-point
mount /dev/xvdg /gerrit-mount-point
if [[ "${GerritVolumeSnapshotId}" = "" ]]; then
echo "Create Gerrit directories"
mkdir -p /gerrit-mount-point/gerrit-logs \
/gerrit-mount-point/gerrit-cache \
/gerrit-mount-point/gerrit-data \
/gerrit-mount-point/gerrit-git \
/gerrit-mount-point/gerrit-index \
/gerrit-mount-point/gerrit-db
fi
chown 1000:1000 -R /gerrit-mount-point
# EFS setting
DIR_TGT=/mnt/efs/gerrit-shared
mkdir -p $DIR_TGT
EC2_REGION=${AWS::Region}
# 169.254.169.254 link-local address, valid only from the instance, to retrieve meta-data information.
EC2_AVAIL_ZONE=`curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone`
EFS_FILE_SYSTEM_ID=${FileSystem}
DIR_SRC=$EC2_AVAIL_ZONE.$EFS_FILE_SYSTEM_ID.efs.$EC2_REGION.amazonaws.com
touch /home/ec2-user/echo.res
echo $PRIMARY_ID >> /home/ec2-user/echo.res
echo $EFS_FILE_SYSTEM_ID >> /home/ec2-user/echo.res
echo $EC2_AVAIL_ZONE >> /home/ec2-user/echo.res
echo $EC2_REGION >> /home/ec2-user/echo.res
echo $DIR_SRC >> /home/ec2-user/echo.res
echo $DIR_TGT >> /home/ec2-user/echo.res
MAX_RETRIES=20
for i in $(seq 1 $MAX_RETRIES); do
echo "Mounting EFS volume ($i/$MAX_RETRIES)..."
`mount -t nfs4 -o nfsvers=4.1,hard,timeo=600,retrans=2 $DIR_SRC:/ $DIR_TGT >> /home/ec2-user/echo.res` \
&& s=0 && break || s=$? && sleep 5;
done; (exit $s)
mkdir -p $DIR_TGT/git
mkdir -p $DIR_TGT/high-availability
chown -R 1000:1000 $DIR_TGT
cp -p /etc/fstab /etc/fstab.back-$(date +%F)
echo -e "$DIR_SRC:/ \t\t $DIR_TGT \t\t nfs \t\t defaults \t\t 0 \t\t 0" | tee -a /etc/fstab
# Get the CloudWatch Logs agent
echo -e "
{\"logs\":
{\"logs_collected\":
{\"files\":
{\"collect_list\":
[
{\"file_path\": \"/gerrit-mount-point/gerrit-logs/replication_log\",
\"log_group_name\": \"${LogGroupName}\",
\"log_stream_name\": \"${EnvironmentName}/{instance_id}/$PRIMARY_ID/replication_log\",
\"timezone\": \"UTC\"
},
{\"file_path\": \"/gerrit-mount-point/gerrit-logs/httpd_log\",
\"log_group_name\": \"${LogGroupName}\",
\"log_stream_name\": \"${EnvironmentName}/{instance_id}/$PRIMARY_ID/httpd_log\",
\"timezone\": \"UTC\"
},
{\"file_path\": \"/gerrit-mount-point/gerrit-logs/error_log\",
\"log_group_name\": \"${LogGroupName}\",
\"log_stream_name\": \"${EnvironmentName}/{instance_id}/$PRIMARY_ID/error_log\",
\"timezone\": \"UTC\"
},
{\"file_path\": \"/gerrit-mount-point/gerrit-logs/sshd_log\",
\"log_group_name\": \"${LogGroupName}\",
\"log_stream_name\": \"${EnvironmentName}/{instance_id}/$PRIMARY_ID/sshd_log\",
\"timezone\": \"UTC\"
},
{\"file_path\": \"/gerrit-mount-point/gerrit-logs/gc_log\",
\"log_group_name\": \"${LogGroupName}\",
\"log_stream_name\": \"${EnvironmentName}/{instance_id}/$PRIMARY_ID/gc_log\",
\"timezone\": \"UTC\"
},
{\"file_path\": \"/gerrit-mount-point/gerrit-logs/sharedref_log\",
\"log_group_name\": \"${LogGroupName}\",
\"log_stream_name\": \"${EnvironmentName}/{instance_id}/$PRIMARY_ID/sharedref_log\",
\"timezone\": \"UTC\"
},
{\"file_path\": \"/gerrit-mount-point/gerrit-logs/message_log\",
\"log_group_name\": \"${LogGroupName}\",
\"log_stream_name\": \"${EnvironmentName}/{instance_id}/$PRIMARY_ID/message_log\",
\"timezone\": \"UTC\"
},
{\"file_path\": \"/gerrit-mount-point/gerrit-logs/websession_log\",
\"log_group_name\": \"${LogGroupName}\",
\"log_stream_name\": \"${EnvironmentName}/{instance_id}/$PRIMARY_ID/websession_log\",
\"timezone\": \"UTC\"
},
{\"file_path\": \"/gerrit-mount-point/gerrit-logs/audit_log\",
\"log_group_name\": \"${LogGroupName}\",
\"log_stream_name\": \"${EnvironmentName}/{instance_id}/$PRIMARY_ID/audit_log\",
\"timezone\": \"UTC\"
}
]
}
}
}
}" >> /home/ec2-user/gerritlogsaccess.json
# Install the CloudWatch Logs agent
wget https://s3.amazonaws.com/amazoncloudwatch-agent/centos/amd64/latest/amazon-cloudwatch-agent.rpm
rpm -U ./amazon-cloudwatch-agent.rpm
/opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -c file:/home/ec2-user/gerritlogsaccess.json -s
# Signal to CloudFormation aws-cfn-bootstrap has been correctly updated
/opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource PrimaryECSAutoScalingGroup --region ${AWS::Region}
GerritVolumeStack:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: !Join [ '', ['https://', !Ref TemplateBucketName, '.s3.amazonaws.com/cf-gerrit-volume.yml'] ]
TimeoutInMinutes: '25'
Parameters:
GerritVolumeId: ""
GerritVolumeSnapshotId: !Ref GerritVolumeSnapshotId
GerritVolumeSizeInGiB: !Ref GerritVolumeSizeInGiB
AvailabilityZone: !Ref AvailabilityZone
Outputs:
PrimaryLaunchTemplate:
Value: !Ref PrimaryLaunchTemplate
Export:
Name: !Join [ '-', [ !Ref 'AWS::StackName', 'PrimaryLaunchTemplate', !Ref GerritInstanceNumber ] ]
PrimaryECSAutoScalingGroup:
Value: !Ref PrimaryECSAutoScalingGroup
Export:
Name: !Join [ '-', [ !Ref 'AWS::StackName', 'PrimaryECSAutoScalingGroup', !Ref GerritInstanceNumber ] ]