userData are not getting executed after launching the instance by cloudformation - json

I created a AWS cloudformation, which creates a launch configuration and an autoscaling group. In the user Data in the launch Config I have configured the file system mount target, and I installed the cloudwatch agent:
Code EDITED
"LaunchConfig":{
"Type":"AWS::AutoScaling::LaunchConfiguration",
"Metadata" : {
"AWS::CloudFormation::Init" : {
"config" : {
"files" : {
"/etc/cwlogs.cfg": {
"content": { "Fn::Join" : ["", [
"[general]",
"state_file = /var/awslogs/state/agent-state",
"[/var/log/syslog]",
"file = /tmp/",
"log_group_name = ecs-dataloader",
"log_stream_name = ECS-loader",
"datetime_format = %b %d %H:%M:%S"
]]},
"mode": "000755",
"owner": "root",
"group": "root"
},
"/etc/ecs/ecs.config": {
"content": { "Fn::Join" : ["", [
"ECS_CLUSTER=", { "Ref" : "ClusterName" }
]]},
"mode": "000755",
"owner": "root",
"group": "root"
}
},
"commands": {
"Update": {
"command": "yum -y update"
},
"InstallNfs":{
"command": "yum -y install nfs-utils"
},
"CreatFolder": {
"command": "mkdir -p /efs-mount-point/"
},
"EditPerms": {
"command": "chown ec2-user:ec2-user /efs-mount-point/"
},
"MountPoint": {
"command": { "Fn::Join" : ["", [
"AZ=$(curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone)\n",
"echo LABEL=cloudimg-rootfs / ext4 defaults,discard 0 0\n",
"$AZ.",{ "Fn::FindInMap" : [ "FileSystemMap", {"Ref" : "EnvParam"}, "FileSystemID"] },
".efs.",{ "Ref" : "AWS::Region" },".amazonaws.com:/ /efs-script-import-tmp nfs4 nfsvers=4.1 0 0 >> /etc/fstab"
]]}
},
"Mount": {
"command": "mount -a -t nfs4"
},
"CloudWatchAgent": {
"command": { "Fn::Join" : ["", [
"curl https://s3.amazonaws.com/aws-cloudwatch/downloads/latest/awslogs-agent-setup.py -O\n",
"python ./awslogs-agent-setup.py --region ",{"Ref" : "AWS::Region"},"\n",
"chmod +x ./awslogs-agent-setup.py ./awslogs-agent-setup.py -n -r",
{"Ref" : "AWS::Region"}," -c /etc/cwlogs.cfg"
]]}
}
},
"services" : {
"sysvinit" : {
"awslogs" : { "enabled" : "true", "ensureRunning" : "true" }
}
}
}
}
},
"Properties":{
"ImageId":{ "Fn::FindInMap":[ "AWSRegionToAMI", { "Ref":"AWS::Region" }, "AMIID" ] },
"SecurityGroups":[ { "Ref":"EcsSecurityGroup" } ],
"InstanceType": {"Ref":"InstanceType" },
"IamInstanceProfile":{ "Ref":"EC2InstanceProfile" },
"KeyName":{ "Fn::FindInMap" : [ "KeyPairMapping", {"Ref" : "EnvParam"}, "Key"] },
"UserData":{ "Fn::Base64" : {
"Fn::Join" : ["", [
"#!/bin/bash -xe\n",
"/opt/aws/bin/cfn-init -v ",
" --stack ", { "Ref": "AWS::StackName" },
" --resource LaunchConfig",
" --region ", { "Ref" : "AWS::Region" },"\n"
]]}
}
}
}
The image details : "eu-west-1": { "AMIID":"ami-ba346ec9" },
After running the template, the resources got created successfuly. So I connected to my instance that got created by the autoscaling group via SSH to see if the userData was properly run and set.
Unfortunately, After checking, this is what I found in the /etc/fstab file:
$ cat /etc/fstab
LABEL=cloudimg-rootfs / ext4 defaults,discard 0 0
$ cat /etc/ecs/ecs.config
cat: /etc/ecs/ecs.config: No such file or directory
The instance is not connected to the file system, the file that I tried to create in the cloudformation::init /etc/cwlogs.cfg does not exist either (it's the cloudwatch agent config file) . Can any one tell me what is wrong in the user data that it didn't get executed?
I tried to check the log files but :
$ cat /var/log/cfn-init.log
cat: /var/log/cfn-init.log: No such file or directory
What is the problem here ?
EDIT
$ cat /var/log/cloud-init-ouput.log
...
Cloud-init v. 0.7.6 running 'modules:final' at Fri, 17 Feb 2017 11:43:42 +0000. Up 44.66 seconds.
+ yum install -y aws-cfn-bootstrap/opt/aws/bin/cfn-init -v --stack Mystack --resource LaunchConfig --region eu-west-1
Loading "priorities" plugin
Loading "update-motd" plugin
Config time: 0.009
Command line error: no such option: --stack
Feb 17 11:43:43 cloud-init[2814]: util.py[WARNING]: Failed running /var/lib/cloud/instance/scripts/part-001 [1]
Feb 17 11:43:43 cloud-init[2814]: cc_scripts_user.py[WARNING]: Failed to run module scripts-user (scripts in /var/lib/cloud/instance/scripts)
Feb 17 11:43:43 cloud-init[2814]: util.py[WARNING]: Running module scripts-user (<module 'cloudinit.config.cc_scripts_user' from '/usr/lib/python2.7/dist-packages/cloudinit/config/cc_scripts_user.pyc'>) failed
Cloud-init v. 0.7.6 finished at Fri, 17 Feb 2017 11:43:43 +0000. Datasource DataSourceEc2. Up 45.18 seconds

User Data log files are located at:
Linux cloud-init: /var/log/cloud-init.log
Windows EC2Config: C:\cfn\log\cloud-init.log
Check to see whether anything is in the log file. If not, then something's wrong with passing the User Data script from the template. (Why do you have the initial empty quotes in the Join?)

cfn-init is only installed by default on Amazon Linux AMI, so if you're using any other Image ID to launch your EC2 instance you need to ensure that it's installed correctly before invoking it. See my previous answer to the question, "Installing packages using apt-get in CloudFormation file" for more info.

Here is how I resolved the problem: I Update the cloud-init in the user data before calling the meta-data and instead of installing the cloudwatch agent in the metadata, I did in the userdata.
"UserData":{ "Fn::Base64" : {
"Fn::Join" : ["", [
"#!/bin/bash -xe\n",
"yum -y install aws-cfn-bootstrap\n",
"/opt/aws/bin/cfn-init -v",
" --stack ", { "Ref": "AWS::StackName" },
" --resource LaunchConfig",
" --region ", { "Ref" : "AWS::Region" },"\n",
"# Get the CloudWatch Logs agent\n",
"wget https://s3.amazonaws.com/aws-cloudwatch/downloads/latest/awslogs-agent-setup.py\n",
"# Install the CloudWatch Logs agent\n",
"python ./awslogs-agent-setup.py -n -r ", { "Ref" : "AWS::Region" }, " -c /etc/cwlogs.cfg || error_exit 'Failed to run CloudWatch Logs agent setup'\n",
"service awslogs start"
]]}

Related

Using AWS CloudFormation to launch AutoScaling servers with latest Apache and PHP?

I would like to launch a LAMP stack with Autoscaled EC2 instances through CloudFormation template. Whenever I try it, stack is built successfully but when I go onto the website, it gives me a message that app does not support older versions of PHP.
Now, when I searched for this problem online, I found one answer that suggested installing newer versions of httpd and php through yum. I tried that directly on the EC2 linux terminal and it worked, I could now access the website successfully. The thing is, I want these updated versions to be installed directly in the template. For this purpose I replaced this code within AutoScaling::LaunchConfiguration:
"setup" : {
"packages" : {
"yum" : {
"nfs-utils" : [],
"httpd" : [],
"php" : [],
"mysql" : []
}
},
with:
"setup" : {
"packages" : {
"yum" : {
"nfs-utils" : [],
"httpd24" : [],
"php72" : [],
"mysql" : []
}
},
This causes the stack to fail to create AutoScalingGroup which has the LaunchConfiguration as param, with an error stating "Received 0 SUCCESS signal".
Here's my Properties of LaunchConfiguration:
"Properties": {
"AssociatePublicIpAddress" : true,
"ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" },
{ "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] },
"InstanceType" : { "Ref" : "InstanceType" },
"SecurityGroups" : [ {"Ref" : "WebServerSecurityGroup"} ],
"KeyName" : { "Ref" : "KeyName" },
"IamInstanceProfile" : { "Ref" : "CloudWatchPutMetricsInstanceProfile" },
"UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
"#!/bin/bash -xe\n",
"yum update -y aws-cfn-bootstrap\n",
"/opt/aws/bin/cfn-init -v ",
" --stack ", { "Ref" : "AWS::StackName" },
" --resource LaunchConfig ",
" --configsets app_install ",
" --region ", { "Ref" : "AWS::Region" }, "\n",
"/opt/aws/bin/cfn-signal -e $? ",
" --stack ", { "Ref" : "AWS::StackName" },
" --resource WebServerGroup ",
" --region ", { "Ref" : "AWS::Region" }, "\n"
]]}}
}
Any ideas why it doesn't work? Any suggestions what I can do to actually install newest httpd and php directly through the template? Should I remove packages section and just put script for installing httpd and php directly in the UserData?
I managed to sort it out myself. I used Ubuntu 18.04 AMI instead of Linux as it supports latest versions of PHP and Apache.
Also had to change the "UserData" a bit:
"UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
"#!/bin/bash -xe\n",
"apt-get update -y\n",
"apt-get install -y python-pip\n",
"mkdir -p /opt/aws/bin\n",
"python /usr/lib/python2.7/dist-packages/easy_install.py --script-dir /opt/aws/bin https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-latest.tar.gz\n",
"ln -s /usr/local/lib/python2.7/dist-packages/aws_cfn_bootstrap-1.4-py2.7.egg/init/ubuntu/cfn-hup /etc/init.d/cfn-hup \n",
"systemctl daemon-reload \n",
"chmod 700 /etc/init.d/cfn-hup \n",
"chown root:root /etc/init.d/cfn-hup \n",
"update-rc.d cfn-hup defaults \n",
"update-rc.d cfn-hup enable \n",
"/opt/aws/bin/cfn-init -v ",
" --stack ", { "Ref" : "AWS::StackName" },
" --resource LaunchConfig ",
" --configsets app_install ",
" --region ", { "Ref" : "AWS::Region" }, "\n",
"/opt/aws/bin/cfn-signal -e $? ",
" --stack ", { "Ref" : "AWS::StackName" },
" --resource WebServerGroup ",
" --region ", { "Ref" : "AWS::Region" }, "\n"
]]}}
and because Ubuntu uses apt instead of yum, this is how I included packages:
"setup" : {
"packages" : {
"apt" : {
"nfs-common" : [],
"apache2" : [],
"php" : [],
"php-mysql" : [],
"mysql-common" : []
}
},

CannotStartContainerError while submitting a AWS Batch Job

In AWS Batch I have a job definition and a job queue and a compute environment where to execute my AWS Batch jobs.
After submitting a job, I find it in the list of the failed ones with this error:
Status reason
Essential container in task exited
Container message
CannotStartContainerError: API error (404): oci runtime error: container_linux.go:247: starting container process caused "exec: \"/var/application/script.sh --file= --key=.
and in the cloudwatch logs I have:
container_linux.go:247: starting container process caused "exec: \"/var/application/script.sh --file=Toulouse.json --key=out\": stat /var/application/script.sh --file=Toulouse.json --key=out: no such file or directory"
I have specified a correct docker image that has all the scripts (we use it already and it works) and I don't know where the error is coming from.
Any suggestions are very appreciated.
The docker file is something like that:
# Pull base image.
FROM account-id.dkr.ecr.region.amazonaws.com/application-image.base-php7-image:latest
VOLUME /tmp
VOLUME /mount-point
RUN chown -R ubuntu:ubuntu /var/application
# Create the source directories
USER ubuntu
COPY application/ /var/application
# Register aws profile
COPY data/aws /home/ubuntu/.aws
WORKDIR /var/application/
ENV COMPOSER_CACHE_DIR /tmp
RUN composer update -o && \
rm -Rf /tmp/*
Here is the Job Definition:
{
"jobDefinitionName": "JobDefinition",
"jobDefinitionArn": "arn:aws:batch:region:accountid:job-definition/JobDefinition:25",
"revision": 21,
"status": "ACTIVE",
"type": "container",
"parameters": {},
"retryStrategy": {
"attempts": 1
},
"containerProperties": {
"image": "account-id.dkr.ecr.region.amazonaws.com/application-dev:latest",
"vcpus": 1,
"memory": 512,
"command": [
"/var/application/script.sh",
"--file=",
"Ref::file",
"--key=",
"Ref::key"
],
"volumes": [
{
"host": {
"sourcePath": "/mount-point"
},
"name": "logs"
},
{
"host": {
"sourcePath": "/var/log/php/errors.log"
},
"name": "php-errors-log"
},
{
"host": {
"sourcePath": "/tmp/"
},
"name": "tmp"
}
],
"environment": [
{
"name": "APP_ENV",
"value": "dev"
}
],
"mountPoints": [
{
"containerPath": "/tmp/",
"readOnly": false,
"sourceVolume": "tmp"
},
{
"containerPath": "/var/log/php/errors.log",
"readOnly": false,
"sourceVolume": "php-errors-log"
},
{
"containerPath": "/mount-point",
"readOnly": false,
"sourceVolume": "logs"
}
],
"ulimits": []
}
}
In Cloudwatch log stream /var/log/docker:
time="2017-06-09T12:23:21.014547063Z" level=error msg="Handler for GET /v1.17/containers/4150933a38d4f162ba402a3edd8b7763c6bbbd417fcce232964e4a79c2286f67/json returned error: No such container: 4150933a38d4f162ba402a3edd8b7763c6bbbd417fcce232964e4a79c2286f67"
This error was because the command was malformed. I was submitting the job by a lambda function (python 2.7) using boto3 and the syntax of the command should be something like this:
'command' : ['sudo','mkdir','directory']
Hope it helps somebody.

Can't mount EFS in the ECS instance

I have this UserData in the configurationConfig resource in my cloudformation template:
"UserData":{ "Fn::Base64" : {
"Fn::Join" : ["", [
"#!/bin/bash -xv\n",
"yum -y update\n",
"yum -y install aws-cfn-bootstrap\n",
"yum -y install awslogs jq\n",
"#Install NFS client\n",
"yum -y install nfs-utils\n",
"#Install pip\n",
"yum -y install python27 python27-pip\n",
"#Install awscli\n",
"pip install awscli\n",
"#Upgrade to the latest version of the awscli\n",
"#pip install --upgrade awscli\n",
"#Add support for EFS to the CLI configuration\n",
"aws configure set preview.efs true\n",
"#Get region of EC2 from instance metadata\n",
"EC2_AVAIL_ZONE=`curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone`\n",
"EC2_REGION=",{ "Ref": "AWS::Region"} ,"\n",
"mkdir /efs-tmp/\n",
"chown -R ec2-user:ec2-user /efs-tmp/\n",
"DIR_SRC=$EC2_AVAIL_ZONE.",{ "Fn::FindInMap" : [ "FileSystemMap", {"Ref" : "EnvParam"}, "FileSystemID"] },".efs.$EC2_REGION.amazonaws.com\n",
"DIR_TGT=/efs-tmp/\n",
"touch /home/ec2-user/echo.res\n",
"echo ",{ "Fn::FindInMap" : [ "FileSystemMap", {"Ref" : "EnvParam"}, "FileSystemID"] }," >> /home/ec2-user/echo.res\n",
"echo $EC2_AVAIL_ZONE >> /home/ec2-user/echo.res\n",
"echo $EC2_REGION >> /home/ec2-user/echo.res\n",
"echo $DIR_SRC >> /home/ec2-user/echo.res\n",
"echo $DIR_TGT >> /home/ec2-user/echo.res\n",
"#Mount EFS file system\n",
"mount -t nfs4 -o vers=4.1 $DIR_SRC:/ $DIR_TGT >> /home/ec2-user/echo.res\n",
"#Backup fstab\n",
"cp -p /etc/fstab /etc/fstab.back-$(date +%F)\n",
"echo -e \"$DIR_SRC:/ $DIR_TGT nfs4 nfsvers=4.1 0 0 | tee -a /etc/fstab\n",
"docker ps\n",
"service docker stop\n",
"service docker start\n",
"/opt/aws/bin/cfn-init -v",
" --stack ", { "Ref": "AWS::StackName" },
" --resource ContainerInstances",
" --region ", { "Ref" : "AWS::Region" },"\n",
"service awslogs start\n",
"chkconfig awslogs on\n"
]]}
Here is the security group of the ECS container:
"EcsSecurityGroup":{
"Type" : "AWS::EC2::SecurityGroup",
"Properties" : {
"GroupDescription" : "ECS SecurityGroup",
"SecurityGroupIngress" : [
{
"IpProtocol" : "tcp",
"FromPort" : "2049",
"ToPort" : "2049",
"CidrIp" : {"Ref" : "CIDRVPC"}
},
{
"IpProtocol" : "tcp",
"FromPort" : "22",
"ToPort" : "22",
"CidrIp" : "0.0.0.0/0"
}
],
"SecurityGroupEgress" : [
{
"IpProtocol" : "-1",
"FromPort" : "-1",
"ToPort" : "-1",
"CidrIp" : "0.0.0.0/0"
}
],
"VpcId":{ "Ref":"VpcId" }
}
},
After running the template, I ssh into the instance, waited for userdata to finish executing, then I found in /var/log/cloud-init-ouptut.log this error:
mount.nfs4: Connection timed out
Moreover, the /etc/fstab file does not contain the mount line.
And I can't access the File system, because the created folder for EFS is empty..
Please tell me where is the issue here?
Ensure you created EFS security group and allow your ec2 security in the ingress rules:
"EfsSecurityGroup": {
"Properties": {
"GroupDescription": "EFS security group",
"SecurityGroupIngress": [
{
"FromPort": 2049,
"IpProtocol": "tcp",
"SourceSecurityGroupId": {
"Ref": "YOUR_EC2_SECURITY_GROUP"
},
"ToPort": 2049
},
],
"Tags": [
{
"Key": "Application",
"Value": {
"Ref": "AWS::StackName"
}
},
{
"Key": "Name",
"Value": "efs-sg"
}
],
"VpcId": {
"Ref": "YOUR_VPC_ID"
}
},
"Type": "AWS::EC2::SecurityGroup"
}
Ensure EFS mountarget exist:
"EFSMountTargetYourAZ": {
"Properties": {
"FileSystemId": "EFS_id",
"SecurityGroups": [
{
"Ref": "EFS_SECURITY_GROUP"
}
],
"SubnetId": {
"Ref": "SUBNET_ID"
}
},
"Type": "AWS::EFS::MountTarget"
},
There's a typo (missing closing \") in this line in your script, which is causing the attempted write to /etc/fstab to fail:
echo -e \"$DIR_SRC:/ $DIR_TGT nfs4 nfsvers=4.1 0 0 | tee -a /etc/fstab\n",
This should read:
echo -e \"$DIR_SRC:/ $DIR_TGT nfs4 nfsvers=4.1 0 0\" | tee -a /etc/fstab\n",
You need to make sure that an AWS::EFS::MountTarget resource exists in the availability zone specified. Otherwise, the attempt to mount the filesystem using the DNS name will fail to resolve correctly. See Mounting File Systems and AWS::EFS::FileSystem for further documentation.

Packer hangs waiting for (inline) Shell script to be executed

being new to packer i am trying to build my first virtual box image with a packer file. But somehow it hangs on the inline shell provisioning. I cannot figure out what the issue is. Tried to debug and it hangs on.
virtualbox-iso: Provisioning with shell script: /var/folders/27/p5wvd4l164z3c56378y7pp940000gn/T/packer-shell450560231
My packer script is as follows:
{
"provisioners": [{
"type": "shell",
"inline": [
"sleep 30",
"sudo apt-get update"
]
}],
"builders": [
{
"type": "virtualbox-iso",
"boot_command": [
"<esc><wait>",
"<esc><wait>",
"<enter><wait>",
"/install/vmlinuz<wait>",
" auto<wait>",
" console-setup/ask_detect=false<wait>",
" console-setup/layoutcode=us<wait>",
" console-setup/modelcode=pc105<wait>",
" debian-installer=en_US<wait>",
" fb=false<wait>",
" initrd=/install/initrd.gz<wait>",
" kbd-chooser/method=us<wait>",
" keyboard-configuration/layout=USA<wait>",
" keyboard-configuration/variant=USA<wait>",
" locale=en_US<wait>",
" netcfg/get_hostname=ubuntu-1404<wait>",
" netcfg/get_domain=acme.com<wait>",
" noapic<wait>",
" preseed/url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/preseed.cfg<wait>",
" -- <wait>",
"<enter><wait>"
],
"boot_wait": "10s",
"disk_size": 40960,
"guest_os_type": "Ubuntu_64",
"http_directory": "http",
"iso_checksum": "9e5fecc94b3925bededed0fdca1bd417",
"iso_checksum_type": "md5",
"iso_url": "http://releases.ubuntu.com/14.04/ubuntu-14.04.3-server-amd64.iso",
"ssh_username": "packer",
"ssh_password": "packer",
"ssh_port": 22,
"ssh_pty" : "true",
"headless": "false",
"ssh_wait_timeout": "10000s",
"shutdown_command": "echo packer | sudo -S shutdown -P now",
"output_directory": "/Users/marco/Desktop/generated_images/ubuntu",
"vboxmanage": [
[ "modifyvm", "{{.Name}}", "--memory", "512" ],
[ "modifyvm", "{{.Name}}", "--cpus", "1" ]
]
}
]
}
You can get verbose output from Packer with PACKER_LOG=1 before the build command. That might help diagnose what's happening on particular scripts. Also packer has a --debug flag that will stop the build at breakpoints and enable you to login to the image.

Logstash Forwarder on AWS Elastic Beasntalk

what is best possible way to install the logstash forwarder on the Elastic Beanstalk application (Rails Application) to forward logs on the Logstash
Here what I did , create config file .ebextensions/02-logstash.config
files:
"/etc/yum.repos.d/logstash.repo":
mode: "000755"
owner: root
group: root
content: |
[logstash-forwarder]
name=logstash-forwarder repository
baseurl=http://packages.elasticsearch.org/logstashforwarder/centos
gpgcheck=1
gpgkey=http://packages.elasticsearch.org/GPG-KEY-elasticsearch
enabled=1
commands:
"100-rpm-key":
command: "rpm --import http://packages.elasticsearch.org/GPG-KEY-elasticsearch"
"200-install-logstash-forwarder":
command: "yum -y install logstash-forwarder"
"300-install-contrib-plugin":
command: "rm -rf /etc/logstash-forwarder.conf && cp /var/app/current/logstash-forwarder.conf /etc/ "
test: "[ ! -f /etc/logstash-forwarder.conf ]"
"400-copy-cert":
command: "cp /var/app/current/logstash-forwarder.crt /etc/pki/tls/certs/"
"500-install-logstash":
command: "service logstash-forwarder restart"
1: logstash-forwarder.conf
{
"network": {
"servers": [
"logstashIP:5000"
],
"timeout": 15,
"ssl ca": "/etc/pki/tls/certs/logstash-forwarder.crt"
},
"files": [
{
"paths": [
"/var/log/messages",
"/var/log/secure",
"/var/log/eb-version-deployment.log",
"/var/app/support/logs/passenger.log",
"/var/log/eb-activity.log",
"/var/log/eb-commandprocessor.log"
],
"fields": {
"type": "syslog"
}
}
]
}