By Daniel Du
As a practice of DevOps, I have been investigating the auto-deployment mechanism, and the AWS CodeDeploy service draws my attention, it supports deploying from GitHub repository as well. In this post and following I will sharing what I learned.
Create an IAM Role for CodeDeploy
Firstly, I need to create an IAM role for CodeDeploy, and launch my EC2 instances as well. I am going to using AWS command line interface(AWS CLI) which is easy to track what I did and I can repeat the process easily. I installed AWS CLI on my local Mac, so I am doing following on my local MacBook.
To create an IAM role, I need to prepare a JSON file for assume-role-policy-document:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": [
"codedeploy.us-west-2.amazonaws.com",
"codedeploy.us-east-1.amazonaws.com",
"ec2.amazonaws.com",
"s3.amazonaws.com"
]
},
"Action": "sts:AssumeRole"
}
]
}
Here I need this role can access to CodeDeploy service, EC2 service and S3 service. Although I just want to deploy from Github instead of S3, but I still need to access S3 to install the CodeDeploy Agent on my EC2 instance. Now I am going to create my role:
$ aws iam create-role \
> --role-name ADN-Viewer-CodeDeploy-Role \
> --assume-role-policy-document file://ADN-Viewer-CodeDeploy-Trust.json
Once my role is created, I need to assign it a policy with another JSON file:
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"autoscaling:PutLifecycleHook",
"autoscaling:DeleteLifecycleHook",
"autoscaling:RecordLifecycleActionHeartbeat",
"autoscaling:CompleteLifecycleAction",
"autoscaling:DescribeAutoscalingGroups",
"autoscaling:PutInstanceInStandby",
"autoscaling:PutInstanceInService",
"ec2:Describe*",
"s3:Get*",
"s3:List*",
"Tag:get*"
],
"Effect": "Allow",
"Resource": "*"
}
]
}
$ aws iam put-role-policy \
> --role-name ADN-Viewer-CodeDeploy-Role \
> --policy-name ADN-Viewer-CodeDeploy-Permissions \
> --policy-document file://ADN-Viewer-CodeDeploy-Permissions.json
Since I am creating IAM role with AWS CLI, I have to create an instance profile for EC2. here is the explanation about instance profile from AWS document:
Amazon EC2 uses an instance profile as a container for an IAM role. When you create an IAM role using the console, the console creates an instance profile automatically and gives it the same name as the role it corresponds to. If you use the AWS CLI, API, or an AWS SDK to create a role, you create the role and instance profile as separate actions, and you might give them different names. To launch an instance with an IAM role, you specify the name of its instance profile. When you launch an instance using the Amazon EC2 console, you can select a role to associate with the instance; however, the list that's displayed is actually a list of instance profile names. For more information, see Instance Profiles in the Using IAM.
$ aws iam create-instance-profile \
> --instance-profile-name ADN-Viewer-CodeDeploy-Role-Profile
$ aws iam add-role-to-instance-profile \
> --instance-profile-name ADN-Viewer-CodeDeploy-Role-Profile \
> --role-name ADN-Viewer-CodeDeploy-Role
Now my role is created.
Launch EC2 Instances
Now I am ready to create my EC2 instances, with AWS CLI, I can launch multiple instances at one time. With following command line, I am creating 2 Linux t2.micro instances from Amazon Linux AMI 2015.03 (HVM), SSD Volume Type - ami-1ecae776. I’ve already created a security group named as “web server”.
$ aws ec2 run-instances \
> --image-id ami-1ecae776 \
> --count 2 \
> --instance-type t2.micro \
> --iam-instance-profile Name="ADN-Viewer-CodeDeploy-Role-Profile" \
> --key-name aws-devtech-us-east1 \
> --security-groups "web server"
To find these instances easily when deploying the code with CodeDeploy service, I need to assign tags for these instances. Please note that I have to input the correct instance ID when creating tags.
$ aws ec2 create-tags \
> --resources i-5f0e2fa3 \
> --tags Key=Name,Value=Production
$ aws ec2 create-tags \
> --resources i-47e3c2bb i-44e3c2b8 \
> --tags Key=Name,Value=Staging
A better way is to create it automatically in one command, here is the sample, for your information.
Install AWS CodeDeploy Agent
To use AWS CodeDeploy service deploy application to these EC2 instances, AWS CodeDeploy Agent has to be running it them. How do I know whether CodeDeploy Agent is running or not? I will logon to the EC2 instance and check with following command:
$ sudo service codedeploy-agent stat
codedeploy-agent: unrecognized service
Seems CodeDeoply agent is not installed, now I logged in to one of EC2 instances with SSH from Mac, or Putty if you are using Windows. Please note that following commands are running from EC2 linux instance. AWS CodeDeploy Agent is not installed by default, so I will go ahead to install CodeDeploy Agent.yum update
yum install aws-cli
aws s3 cp s3://aws-codedeploy-us-east-1/latest/install . --region us-east-1
chmod +x ./install
./install auto
sudo service codedeploy-agent start
Please note that I am using AWS CLI from Linux instance to get the CodeDeploy installation file from S3, that why I need to assign S3 access permission to my IAM role in first step, otherwise, I will get error message like below:
$ sudo aws s3 cp s3://aws-codedeploy-us-east-1/latest/install . --region us-east-1
A client error (403) occurred when calling the HeadObject operation: Forbidden
Completed 1 part(s) with ... file(s) remaining
OK, with that, I have one instance ready to deploy my application. But as you can see, I launched multiple instances but I only installed CodeDeploy agent on one instance, what about others? Do I have to repeat myself and login to them and install them separately? It is OK since I just have 2 or 3. But what if I have handers or even thousand of instances? Actually there are different solutions for this. One of them is, I setup all environment on one instances and create an AMI from it. When I launch my working instance, I will create instance from the one I’ve already configured instead of the AWS default ones. Some other solutions are available, for example to setup the environment with user data when the instance is launched. Anyway, a lot of solutions and a lot of fun. :)
Next, I will to to the deployment part soon. I will do it in another post.
Comments
You can follow this conversation by subscribing to the comment feed for this post.