scholzj / terraform-aws-kubernetes

Terraform module for Kubernetes setup on AWS
Apache License 2.0
200 stars 129 forks source link

Added AWS Account Role ARN support #5

Open guilhermeblanco opened 6 years ago

guilhermeblanco commented 6 years ago

Fixes #2

scholzj commented 6 years ago

My understanding is that you should be able to override the provider from the root module. Can't you simply do something like this? It should keep my module unchanged while letting you configure your role.

provider "aws" {
  region = "${var.aws_region}"

  assume_role {
    session_name = "Terraform"
    role_arn     = "arn:aws:iam::12345678900:role/terraform"
  }
}

module "kubernetes" {
  source = "../"

  aws_region    = "eu-central-1"
  cluster_name  = "aws-kubernetes"
  master_instance_type = "t2.medium"
  worker_instance_type = "t2.medium"
  ssh_public_key = "~/.ssh/id_rsa.pub"
  ssh_access_cidr = ["0.0.0.0/0"]
  api_access_cidr = ["0.0.0.0/0"]
  min_worker_count = 3
  max_worker_count = 6
  hosted_zone = "my-domain.com"
  hosted_zone_private = false

  master_subnet_id = "subnet-8a3517f8"
  worker_subnet_ids = [     
      "subnet-8a3517f8",
      "subnet-9b7853f7",
      "subnet-8g9sdfv8"
  ]

  # Tags
  tags = {
    Application = "AWS-Kubernetes"
  }

  # Tags in a different format for Auto Scaling Group
  tags2 = [
    {
      key                 = "Application"
      value               = "AWS-Kubernetes"
      propagate_at_launch = true
    }
  ]

  addons = [
    "https://raw.githubusercontent.com/scholzj/terraform-aws-kubernetes/master/addons/storage-class.yaml",
    "https://raw.githubusercontent.com/scholzj/terraform-aws-kubernetes/master/addons/heapster.yaml",
    "https://raw.githubusercontent.com/scholzj/terraform-aws-kubernetes/master/addons/dashboard.yaml",
    "https://raw.githubusercontent.com/scholzj/terraform-aws-kubernetes/master/addons/external-dns.yaml",
    "https://raw.githubusercontent.com/scholzj/terraform-aws-kubernetes/master/addons/autoscaler.yaml"
  ]
}
guilhermeblanco commented 6 years ago

@scholzj not really. Inside of the module you're redeclaring the provider, which means the external one is "useless" in this case. Unless you call every resource with a provider and also make sure you're assuming the specific role, it wouldn't work.

The reason why it works nicely is because you don't have setup multiple accounts. It reads the file ~/.aws/credentials and ~/.aws/config which likely only have "default" in your case.

In cases where you handle multiple accounts, you need to assume specific profiles over different accounts, which leads to the need of specifying the provider for every resource.

scholzj commented 6 years ago

The reason why it works nicely is because you don't have setup multiple accounts. It reads the file ~/.aws/credentials and ~/.aws/config which likely only have "default" in your case.

Well, what I tired is to configure the credentials only in the outside provider and not in the inside. That seemed to work fine and use the root module provider correctly. But that is a bit artificial, so maybe it doesn't work on your use case. I saw there are some issues open in Terraform around the way the provider is inherited.

Inside of the module you're redeclaring the provider, which means the external one is "useless" in this case.

Ok. What if we delete the provider which is inside the module? I checked the registry and there seem to be some module which actually don't seem to define the provider inside the module and expect the user to define it in the root module. Would that help to take your provider from the root module? Can you try that locally?

I'm also still not sure how you plan to use the alias with multiple accounts. Is it because you main project includes also other modules which need to use the different AWS accounts and that is why you need the alias? Because if it is just about this module how will you change the accounts / aliases without modifying the module? TBH I don't see any harm in the alias, I'm just trying to understand how it helps.

guilhermeblanco commented 6 years ago

Well, what I tired is to configure the credentials only in the outside provider and not in the inside. That seemed to work fine and use the root module provider correctly. But that is a bit artificial, so maybe it doesn't work on your use case. I saw there are some issues open in Terraform around the way the provider is inherited.

That would not work. Your credentials would work fine for the organization, but not for the individual accounts. You'd end up creating resources at the organization level. People are complaining on Terraform because they want to declare the provider only once, and currently this is not possible.

Ok. What if we delete the provider which is inside the module? I checked the registry and there seem to be some module which actually don't seem to define the provider inside the module and expect the user to define it in the root module. Would that help to take your provider from the root module? Can you try that locally?

That was the first thing I did. Whenever you define an un-aliased provider, your resources will reuse that definition. That works fine for a single account, but it doesn't work for multiple accounts.

I'm also still not sure how you plan to use the alias with multiple accounts. Is it because you main project includes also other modules which need to use the different AWS accounts and that is why you need the alias? Because if it is just about this module how will you change the accounts / aliases without modifying the module? TBH I don't see any harm in the alias, I'm just trying to understand how it helps.

In my case, I have 3 accounts that will define my environment: management, development and production. They're actually 3 AWS accounts that are children of a 4th one converted to an organization. This means only global services can be declared at the organization level (ie. Route53). These accounts then have VPC peering for management <-> production and management <-> development.

In my Terraform scripts, I require to declare all 4 accounts in order to orchestrate my environment creation. This means I have at least 4 declarations like:

provider "aws" {
    alias = "management"
    # ...
}

provider "aws" {
    alias = "development"
    # ...
}

provider "aws" {
    alias = "production"
    # ...
}

provider "aws" {
    alias = "organization"
    # ...
}

Depending of the account I'm looking to perform orchestration, I require to setup provider = "<provider_alias_here>" on every resource (or data) that is executed against AWS. If I don't specify a provider, it'll attempt to run against the organization account, and the execution will fail, since it won't go to your desired account.

scholzj commented 6 years ago

That was the first thing I did. Whenever you define an un-aliased provider, your resources will reuse that definition. That works fine for a single account, but it doesn't work for multiple accounts.

Ok, but what if we add the alias to the resources and remove the provider and let you define the provider in your root project? Because the alias is fine with me. It should not break anything for me and other users. We will need to set the alias in our providers, but that should be fine. But the part with the role

assume_role {
   session_name = "Terraform"
   role_arn     = "${var.aws_role_arn}"
}

is a breaking the module for me and some other users I know about. So I cannot really merge that part.