Is there a way to create default AWS VPC using terraform?
aws_vpc resource doesn't have any attribute to mark VPC as default.
I know I can use aws-cli aws ec2 create-default-vpc, but that's outside of the terraform.
No it looks like you can't via TF, you can adopt an existing default VPC but not create it:
https://www.terraform.io/docs/providers/aws/r/default_vpc.html.
So use the AWS cli to recreate it (if you can) and then use this new provider to adopt it.
A default VPC comes with a public subnet in each Availability Zone, an internet gateway, and settings to enable DNS resolution.
As 17-August-2022, it is possible to create a default VPC through Terraform on AWS in the current region.
It is as simple as:
resource "aws_default_vpc" "default" {
tags = {
Name = "Default VPC"
}
}
Some important points to note: (As mentioned here)
The aws_default_vpc resource behaves differently from normal resources in that if a default VPC exists, Terraform does not create this resource, but instead "adopts" it into management. If no default VPC exists, Terraform creates a new default VPC, which leads to the implicit creation of other resources (e.g. Subnets, Internet Gateway etc.).
By default, terraform destroy does not delete the default VPC but does remove the resource from Terraform state. Set the force_destroy argument to true to delete the default VPC.
Related
I have been trying to set up my Terragrunt EC2 environment in a no/very limited internet setting.
Current Setup:
AWS network firewall that whitelists domains to allow traffic, and most internet traffic is blocked excepted a few domains.
EC2 instance where I run the terragrunt code, it has an instance profile that can assume the role in providers
VPC endpoints set up for sts, s3, dynamodb, codeartifact etc
All credentials (assumed role etc) work and have been verified
Remote State and Providers File
remote_state {
backend = "s3"
generate = {
path = "backend.tf"
if_exists = "overwrite_terragrunt"
}
config = {
bucket = "***"
key = "${path_relative_to_include()}/terraform.tfstate"
region = "ap-southeast-1"
encrypt = true
dynamodb_table = "***"
}
}
# Dynamically changes the role depending on which account is being modified
generate "providers" {
path = "providers.tf"
if_exists = "overwrite"
contents = <<EOF
provider "aws" {
region = "${local.env_vars.locals.aws_region}"
assume_role {
role_arn = "arn:aws:iam::$***"
endpoints {
sts = "https://sts.ap-southeast-1.amazonaws.com"
s3 = "https://s3.ap-southeast-1.amazonaws.com"
dynamodb = "https://dynamodb.ap-southeast-1.amazonaws.com"
}
}
EOF
}
With Internet (Turning off the firewall):
I am able to run all the terragrunt commands
Without Internet
I only allow "registry.terraform.io" to pass the firewall
I am able to assume the role listed in providers via aws sts assume-role, and I can list the tables in dynamodb and files in the s3 bucket
I am able to run terragrunt init on my EC2 instance with the instance profile, I assume terragrunt does use the correct sts_endpoint
However when I run terragrunt apply, it hangs at the stage `DEBU[0022] Running command: terraform plan prefix=[***]
In my CloudTrail I do see that Terragrunt has assumed the username aws-go-sdk-1660077597688447480 for the event GetCallerIdentity, so I think the provider is able to assume the role that was declared in the providers block
I tried adding custom endpoints for sts, s3, and dynamodb, but it still hangs.
I suspect that terraform is still trying to use the internet when making the AWS SDK calls, which leads to terragrunt apply being stuck.
Is there a comprehensive list of endpoints I need to custom add, or a list of domains I should whitelist to be able to run terragrunt apply?
I set the environment variable TF_LOG to debug, and besides the registry.terraform.io domain, I was able to gather these ones:
github.com
2022-08-18T15:33:03.106-0600 [DEBUG] using github.com/hashicorp/go-tfe v1.0.0
2022-08-18T15:33:03.106-0600 [DEBUG] using github.com/hashicorp/hcl/v2 v2.12.0
2022-08-18T15:33:03.106-0600 [DEBUG] using github.com/hashicorp/terraform-config-inspect v0.0.0-20210209133302-4fd17a0faac2
2022-08-18T15:33:03.106-0600 [DEBUG] using github.com/hashicorp/terraform-svchost v0.0.0-20200729002733-f050f53b9734
sts.region.amazonaws.com
resource.region.amazonaws.com
You'll want to add those domains to your whitelist in the firewall settings, something like *.region.amazonaws.com should do the trick, of course, you can be more restrictive, and rather than use a wildcard, you can specify the exact resource.
For reference: https://docs.aws.amazon.com/general/latest/gr/rande.html
I am using Terraform to create EKS cluster. The traffic is routed through AWS Application Load Balancer (ALB) - Ingress controller.
I can get the host name through following output
kubernetes_ingress.app.status.0.load_balancer.0.ingress.0.hostname
However, the problem is Ingress and ALB automatically create one security group, which I needed to create AWS API Gateway & VPC Link, how to get that security group's id?
I think the link below might help you, but in case it's unavailable, you can sort of hack an LB object via the name.
You first get your LB hostname (as you already have, except split on the hyphen), then make an 'aws_lb' data type using that name, which should then populate 'aws_lb' as if you had deployed an LB. Or at least enough to be able to query that type of object to get the bits you need.
locals {
lb_name_parts = split("-", split(".", kubernetes_ingress.alb_nginx_primary_ingress.status.0.load_balancer.0.ingress.0.hostname).0)
}
data "aws_lb" "alb_primary_ingress" {
name = join("-", slice(local.lb_name_parts, 0, length(local.lb_name_parts) - 1))
}
(my variable for the hostname is slightly different to yours but you should get the idea)
The clever person who figured it out:
https://github.com/hashicorp/terraform-provider-kubernetes/issues/942
I have terraform managing my infrastructure in Azure. However, there are cases where the state can get out of sync when other services are changing the infrastructure as well.
For example, I have terraform create an Application Gateway. But I also have an AKS cluster with AGIC enabled, which dynamically updates/changes rules, listeners, etc. inside of Application Gateway. So if terraform is re-run after AGIC makes some changes, terraform doesn't know and wants to reset to the default config it knows about.
Maybe this isn't possible, but is there an automated way to sync the two? It's kind of unfeasible to have to go into the terraform config and manually add the changes AGIC makes every time it does so. At this point, is it even worth managing Application Gateway with terraform?
If you really want to create the Application Gateway with Terraform, you should probably use the Lifecycle Meta-Argument ignore_changes on the attributes that will be modified by AKS. It is not perfect, but at least they can share their responsibilities without overwriting each other.
The ignore_changes feature is intended to be used when a resource is
created with references to data that may change in the future, but
should not affect said resource after its creation. In some rare
cases, settings of a remote object are modified by processes outside
of Terraform, which Terraform would then attempt to "fix" on the next
run. In order to make Terraform share management responsibilities of a
single object with a separate process, the ignore_changes
meta-argument specifies resource attributes that Terraform should
ignore when planning updates to the associated remote object.
For example :
resource "azurerm_application_gateway" "example" {
...
lifecycle {
ignore_changes = [
http_listener,
request_routing_rule,
backend_http_settings
]
}
...
}
My use-case is multiple AppService apps with different lifecycles sitting behind a single Application Gateway. I'd like to add a new listener, new multi-site routing rules, and a new backend pool whenever I add a new app without tearing down and re-creating the gateway.
Initially, my plan was to have a Terraform config for shared infra that creates a skeleton Application Gateway and then have separate application-specific Terraform configs to add listeners, backend address pools, and routing rules to this gateway for each app. It seems to be impossible to accomplish with TF though.
I can clearly add listeners, routing rules and backend pools to an exiting gateway using Azure CLI or Portal. Is there a way to do it with Terraform?
It seems that this is not currently possible due to the fact that the Application Gateway must be initialised with at least one of each of these configuration blocks.
While it is possible to add further definitions using the Azure CLI, that behaviour isn't currently compatible with the way Terraform works. Consider what would happen if backend address pools were initially defined inline as part of the azurerm_application_gateway block and then further definitions of azurerm_application_gateway_backend_address_pool (hypothetical resource block) were also specified.
It would be nice if Terraform could deal with this situation with a union of those two definitions but unfortunately it doesn't play nicely with both inline and standalone resource blocks. Hence the warning on azurerm_subnet resources explaining that inline subnets on azurerm_virtual_network would conflict.
NOTE on Virtual Networks and Subnet's:
Terraform currently provides both a standalone Subnet resource, and allows for Subnets to be defined in-line within the Virtual Network resource. At this time you cannot use a Virtual Network with in-line Subnets in conjunction with any Subnet resources. Doing so will cause a conflict of Subnet configurations and will overwrite Subnet's.
Logically it wouldn't be possible to have a similar warning for Application Gateway since it's inline resource blocks are mandatory (not so for Azure Virtual Networks)
For now, the options here would seem to be
Manage all application-specific aspects of the Application Gateway in the same place with native Terraform.
Create the skeleton definition of the Application Gateway and run local-exec provisioner CLI commands for application-specific configuration
provisioner "local-exec" {
command = <<EOT
az network application-gateway address-pool create `
--resource-group MyResourceGroup `
--gateway-name MyAppGateway `
--name MyAddressPool `
--servers 10.0.0.4 10.0.0.5 `
EOT
interpreter = ["PowerShell", "-command"]
}
Here is the reference doc from Terraform for managing Azure Application Gateway.
You can refer this sample code for adding new listeners,routing rules as well as backend pools to the existing application gateway. This template carries all the required arguments like,
http_listener - (Required) One or more http_listener blocks.
http_listener {
name = "https-listener-1"
frontend_ip_configuration_name = "feip"
frontend_port_name = "http-port"
protocol = "Http"
}
request_routing_rule - (Required) One or more request_routing_rule blocks.
request_routing_rule {
name = "${local.request_routing_rule_name}"
rule_type = "Basic"
http_listener_name = "${local.listener_name}"
backend_address_pool_name = "${local.backend_address_pool_name}"
backend_http_settings_name = "${local.http_setting_name}"
}
}
backend_address_pool - (Required) One or more backend_address_pool blocks as defined below.
backend_address_pool {
name = "${local.backend_address_pool_name}"
}
I heavily use ECS Attributes on our containerized infrastructure. I couldn't find terraform docs to achieve this. Do I need to execute aws cli commands manually to apply those attributes after creating the infrastructure?
I'd recommend having the ECS agent set the ECS attributes if you need these.
You can do this by adding ECS_INSTANCE_ATTRIBUTES to the /etc/ecs/ecs.config file or passing them as an environment variable directly to the ECS agent on startup.
If you have a "base" ECS AMI (either one you rolled your own or the Amazon Linux AMI) then you probably just want to use user data to dynamically set this from Terraform.
You can use "aws_ecs_service" resource and add attributes. For example:
placement_constraints {
type = "memberOf"
expression = "attribute:ecs.availability-zone in [us-west-2a, us-west-2b]"}