How to get pem file for AWS Autoscaling launched instance - amazon-web-services

I have a Terraform script that launches VPC, subnets, database, autoscaling and some other stuff. Autoscaling uses default Windows Server 2012 R2 images to launch new instances (including the initial ones). Every instance is executing Chef install after launch. I need to log into the instance so i can confirm that Chef is installed but i dont have any .pem keys. How do i launch an instance with Autoscaling and launch_configuration and output .pem file so i can login afterwards?
Here is my autoscaling part of the script:
resource "aws_autoscaling_group" "asgPrimary" {
depends_on = ["aws_launch_configuration.primary"]
availability_zones = ["${data.aws_availability_zones.available.names[0]}"]
name = "TerraformASGPrimary"
max_size = 1
min_size = 1
wait_for_capacity_timeout = "0"
health_check_grace_period = 300
health_check_type = "ELB"
desired_capacity = 1
force_delete = false
wait_for_capacity_timeout = "0"
vpc_zone_identifier = ["${aws_subnet.private_primary.id}"]
#placement_group = "${aws_placement_group.test.id}"
launch_configuration = "${aws_launch_configuration.primary.name}"
load_balancers = ["${aws_elb.elb.name}"]
}
and this is my launch configuration:
resource "aws_launch_configuration" "primary" {
depends_on = ["aws_subnet.primary"]
name = "web_config_primary"
image_id = "${data.aws_ami.amazon_windows_2012R2.id}"
instance_type = "${var.ami_type}"
security_groups = ["${aws_security_group.primary.id}"]
user_data = "${template_file.user_data.rendered}"
}
I need to avoid using Amazon CLI or the webpage itself - the point is all that to be automated for reusing in all my other solutions.

The .pem files used to RDS/SSH into an EC2 instance are not generated during launch of an EC2 instance. It may appear like this when using the AWS Management Console, but in actuality, the Key Pair is generated first, and then that Key Pair is assigned to the EC2 instance during launch.
To get your .pem file, first:
Generate a new Key Pair. See Amazon EC2 Key Pairs. When you do this, you will be able to download the .pem file.
Assign that Key Pair to your Auto Scaling Group's launch configuration using the key_name argument.
Here's an example:
resource "aws_launch_configuration" "primary" {
depends_on = ["aws_subnet.primary"]
name = "web_config_primary"
image_id = "${data.aws_ami.amazon_windows_2012R2.id}"
instance_type = "${var.ami_type}"
security_groups = ["${aws_security_group.primary.id}"]
user_data = "${template_file.user_data.rendered}",
key_name = "my-key-pair"
}
See: https://www.terraform.io/docs/providers/aws/r/launch_configuration.html#key_name

Related

Get Private IP from ASG

I need to output private IP from Auto Scaling Group of EC2 instance that configuration by Terraform. How can i get private IP from ASG?
# Launch config for ASG
resource "aws_launch_configuration" "asg_conf" {
name = "ASG-Conf-${var.env}"
image_id = data.aws_ami.ubuntu.id # Get image from data
instance_type = var.instance_type # use t2.micro ad default
security_groups = [var.sg_app.id, var.sg_alb.id] # SG for APP
key_name = var.ssh_key # SSH key for connection to EC2
user_data = file("./modules/ec2/shell/apache.sh") # install apache
lifecycle {
create_before_destroy = true
}
}
# Auto Scaling Group
resource "aws_autoscaling_group" "asg" {
count = length(var.private_subnet_id) # count numbers of private subnets
name = "ASG-${var.env}-${count.index + 1}"
vpc_zone_identifier = [var.private_subnet_id[count.index]]
launch_configuration = aws_launch_configuration.asg_conf.name
target_group_arns = [var.alb_target.arn]
min_size = 1 # Min size of creating EC2
max_size = 1 # Max size of creating EC2
health_check_grace_period = 120
health_check_type = "ELB"
force_delete = true
lifecycle {
create_before_destroy = true
}
tag {
key = "Name"
value = "Webserver-ec2-${count.index + 1}"
propagate_at_launch = true
}
}
output {
# How can i get this???
value = aws_autoscaling_group.asg.private_ip
}
My infrastructure create 1 EC2 instance in 2 private AZ by ASG and i need output IP from this ASG
You need custom data source to get the IPs. But this really does not make much sense as instances in ASG can be changed by AWS at any time, thus making your IPs obsolete.

terraform to launch and configure EC2 AD

I have 2 windows server AMIs :
the first one acts as a client (since as per my research, there is no windows 10 enterprise AMIs in AWS) and the second AMI has an AD.
I would like to create a terraform script that automatically creates EC2 instances from the AMIs, the script should also configure AD with domain and then make the windows member of domain.
Is that possible? if not, would that be possible to achieve using a user data script?
It's not very clear what exactly you need but the 2 resources you will need for sure are:
1.The ec2 resource is aws_instance and is configured like:
resource "aws_instance" "my-ec2" {
ami = "ami-058b1b7fe545997ae"
instance_type = "t2.micro"
subnet_id = "your-subnet-id"
availability_zone = "your-availability_zone"
vpc_security_group_ids = "your-security-group"
tags = {
Name = "me"
Environment = "dev"
}
}
The AD resource is aws_directory_service_directory
resource "aws_directory_service_directory" "my-ad" {
name = "corp.notexample.com"
password = "SuperSecretPassw0rd"
size = "Small"
vpc_settings {
vpc_id = "my-vpc-id"
subnet_ids = [aws_subnet.foo.id, aws_subnet.bar.id]
}
connect_settings {
customer_dns_ips = ["A.B.C.D"]
customer_username = "Admin"
subnet_ids = [aws_subnet.foo.id, aws_subnet.bar.id]
vpc_id = "my-vpc-id"
}
tags = {
Name = "me"
Environment = "dev"
}
}

How do I launch a Beanstalk environment with HealthChecks as "EC2 and ELB" and health_check_grace_time as 1500 using terraform?

I have started learning about terraform recently and wanted to create an environment using the above stated settings. When I run the below code I get 2 resources deployed one is beanstalk and other is Auto Scaling group(ASG) the ASG has the desired settings but is not linked with the beanstalk . Hence I am trying to Connect these two.
(I copy the beanstalk Id form the Tags section then head over to ASG under EC2 and search for the same and look at the health Check section)
resource "aws_autoscaling_group" "example" {
launch_configuration = aws_launch_configuration.as_conf.id
min_size = 2
max_size = 10
availability_zones = [ "us-east-1a" ]
health_check_type = "ELB"
health_check_grace_period = 1500
tag {
key = "Name"
value = "terraform-asg-example"
propagate_at_launch = true
}
}
provider "aws" {
region = "us-east-1"
}
resource "aws_elastic_beanstalk_application" "application" {
name = "Test-app"
}
resource "aws_elastic_beanstalk_environment" "environment" {
name = "Test-app"
application = aws_elastic_beanstalk_application.application.name
solution_stack_name = "64bit Windows Server Core 2019 v2.5.6 running IIS 10.0"
setting {
namespace = "aws:autoscaling:launchconfiguration"
name = "IamInstanceProfile"
value = "aws-elasticbeanstalk-ec2-role"
}
setting {
namespace = "aws:autscaling"
}
}
resource "aws_launch_configuration" "as_conf" {
name = "web_config_shivanshu"
image_id = "ami-2757f631"
instance_type = "t2.micro"
lifecycle {
create_before_destroy = true
}
}
You do not create an ASG or launch config/template outside of the Elastic Beanstalk environment and join them together. As there are config options which are not available. For example GP3 SSD is available as part of a launch template, but not available as part of elastic beanstalk yet
What you want to do is remove the resources of
resource "aws_launch_configuration" "as_conf"
resource "aws_autoscaling_group" "example"
Then utilise the setting {} block a lot more within resource "aws_elastic_beanstalk_environment" "environment"
Here is a list of all the settings you can describe in the settings block (https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/command-options-general.html)
So I got it how we can change the Auto-scaling group(ASG) of the beanstalk we have created using terraform. First of all,create the beanstalk according to your setting. we use the Setting block in beanstalk resource and Namespace for configuring it according to our need.
Step-1
Create a beanstalk using terraform
resource "aws_elastic_beanstalk_environment" "test"
{ ...
...
}
Step-2
After you have created the beanstalk.Create autoscaling resource skeleton. the ASG associated with the beanstalk will be handled by terraform under this resource block.Import using the id of ASG that you can get from either terraform plan/show
terraform import aws_autoscaling_group.<Name that you give> asg-id
Step-3
After you have done that Change the beanstalk according to your need
then make sure you have added these to tags.Because sometimes I have noticed that the mapping of this ASG to the beanstalk is is lost.
tag {
key = "elasticbeanstalk:environment-id"
propagate_at_launch = true
value = aws_elastic_beanstalk_environment.<Name of your beanstalk>.id
}
tag {
key = "elasticbeanstalk:environment-name"
propagate_at_launch = true
value = aws_elastic_beanstalk_environment.<Name of your beanstalk>.name
}

generate user_data including "IP Address" while creating ec2 instance using terraform

I am trying to spin 2 ec2 instances using terraform. Something like this
resource "aws_instance" "example" {
count = "${var.number_of_instances}"
ami = "${var.ami_name}"
associate_public_ip_address = "${var.associate_public_ip_address}"
instance_type = "${var.instance_type}"
key_name = "${var.keyname}"
subnet_id = "${element(var.subnet_ids, count.index)}"
user_data = "${element(data.template_file.example.*.rendered, count.index)}"
vpc_security_group_ids = ["${aws_security_group.example.id}","${var.extra_security_group_id}"]
root_block_device {
volume_size = "${var.root_volume_size}"
volume_type = "${var.root_volume_type}"
iops = "${var.root_volume_iops}"
}
tags {
Name = "${var.prefix}${var.name}${format("%02d", count.index + 1)}"
}
}
In template_file all I am trying to do is to generate a config file with IP Address of both the instances using user_data but this fails saying Cycle Error.
Is there any way to get the file to generate with IP Address while the ec2 instances are coming up
Make use of the AWS Instance Metadata endpoint in your userdata script to get each instance's IP address and put it into a config file. Here is a Powershell example of a userdata script:
<powershell>
$HostIp = (Invoke-RestMethod -URI 'http://169.254.169.254/latest/meta-data/local-ipv4' -UseBasicParsing)
Add-Content "C:\installer\config.txt" "HostIp:$HostIp"
</powershell>
You can also get the instance's public-ipv4 in this manner if that's desired instead.
By combining the various information, you can use user_data argument of the resource "aws_launch_template" block, to call a shell, itself may call in return a typical special metadata endpoint. For the private IP, it would be:
curl http://169.254.169.254/latest/meta-data/local-ipv4

How to remove an AWS Instance volume using Terraform

I deploy a CentOS 7 using an AMI that automatically creates a volume on AWS, so when I remove the platform using the next Terraform commands:
terraform plan -destroy -var-file terraform.tfvars -out terraform.tfplan
terraform apply terraform.tfplan
The volume doesn't remove because it was created automatically with the AMI and terraform doesn't create it. Is it possible to remove with terraform?
My AWS instance is created with the next terraform code:
resource "aws_instance" "DCOS-master1" {
ami = "${var.aws_centos_ami}"
availability_zone = "eu-west-1b"
instance_type = "t2.medium"
key_name = "${var.aws_key_name}"
security_groups = ["${aws_security_group.bastion.id}"]
associate_public_ip_address = true
private_ip = "10.0.0.11"
source_dest_check = false
subnet_id = "${aws_subnet.eu-west-1b-public.id}"
tags {
Name = "master1"
}
}
I add the next code to get information about the EBS volume and to take its ID:
data "aws_ebs_volume" "ebs_volume" {
most_recent = true
filter {
name = "attachment.instance-id"
values = ["${aws_instance.DCOS-master1.id}"]
}
}
output "ebs_volume_id" {
value = "${data.aws_ebs_volume.ebs_volume.id}"
}
Then having the EBS volume ID I import to the terraform plan using:
terraform import aws_ebs_volume.data volume-ID
Finally when I run terraform destroy all the instances and volumes are destroyed.
if the EBS is protected you need to manually remove the termination protection first on the console then you can destroy it