Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Limit external-dns to exactly one zone #82

Merged
merged 63 commits into from
Mar 22, 2022
Merged
Show file tree
Hide file tree
Changes from 60 commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
95671e8
fix: "type -p" is not available in /bin/sh
mogul Mar 2, 2022
dfb0a96
fix: -p is not the correct flag
nickumia-reisys Mar 2, 2022
c3f782f
undo: switch back to using bash, not sh
nickumia-reisys Mar 2, 2022
0d2dd40
update: use non-ancient external-dns Helm chart
mogul Mar 2, 2022
09ba6a3
fix: limit external-dns syncing to just zone IDs associated with this…
mogul Mar 2, 2022
43dfd6f
cleanup: remove redundant/unused external-dns configuration
mogul Mar 2, 2022
d96b883
update: switch to the official external-dns Helm chart
mogul Mar 2, 2022
450d3a6
doc: add providers/* to local iteration docs for modules
mogul Mar 2, 2022
4557eb2
fix: extraArgs is a list, not a map
nickumia-reisys Mar 2, 2022
189acb9
rework: convert heredoc to yamlencode
nickumia-reisys Mar 2, 2022
3bb9c59
fix: curly braces were not being properly escaped
nickumia-reisys Mar 2, 2022
2ab4c27
fix: pass AWS_DEFAULT_REGION as environment variable
nickumia-reisys Mar 2, 2022
30b0b67
new: default to using nginx ingress
nickumia-reisys Mar 2, 2022
386aedb
fix: nginx ingress helm chart is already creating the class
nickumia-reisys Mar 2, 2022
07ebb77
update: poll upto 10 mins for DNS to resolve
nickumia-reisys Mar 2, 2022
25af797
fix: don't over-escape the fqdnTemplate
mogul Mar 3, 2022
5b279c2
fix: wait for DNS resolution and ingress response separately
mogul Mar 3, 2022
8785604
cleanup: remove unnecessary flag
mogul Mar 3, 2022
bb7d728
fix: use a heredoc to specify a subdomain for the text fixture
mogul Mar 3, 2022
54452fe
fix: better test
mogul Mar 3, 2022
3d49e96
todo: fix this test in the future
nickumia-reisys Mar 3, 2022
95864b5
add encryption config to ebs
FuhuXia Feb 28, 2022
8549363
new: increase vpc cidr range
nickumia-reisys Mar 8, 2022
41abff5
fix: VPCs must be betwee 16/24 bits long for network
nickumia-reisys Mar 8, 2022
51c3ae5
fix: brush up on my cidr range math
nickumia-reisys Mar 8, 2022
a24431b
refactor: use the pre-existing k8s admin role for the namespace-admin
mogul Mar 9, 2022
0750828
refactor: logging code is split into AWS and k8s resources
mogul Mar 9, 2022
f77d57c
refactor: k8s admin account will be created in a separate module from…
mogul Mar 9, 2022
dfbb249
refactor: split external-dns into aws- and k8s-specific submodules
mogul Mar 9, 2022
884ff25
lint: remove stray comment
mogul Mar 9, 2022
a249d5f
refactor: rename modules to better indicate their purpose
mogul Mar 9, 2022
906748e
fix: add required_providers for provision-k8s
mogul Mar 9, 2022
abdefbd
refactor: sort variable inputs alphabetically
mogul Mar 9, 2022
3db20b7
refactor: rename module.provision -> module.provision-aws to match th…
mogul Mar 9, 2022
7e5a828
fix: connect provision-aws outputs to provision-k8s inputs
mogul Mar 9, 2022
7bf2395
refactor: persistent-storage.tf into provision-aws and provision-k8s …
mogul Mar 9, 2022
cbca20a
refactor: remove the need for the aws provider in the bind module
mogul Mar 10, 2022
a5a9faf
try: see if we can "reconnect" module.provision-aws to state by keepi…
mogul Mar 10, 2022
095d5ab
lint: remove unused resource
mogul Mar 10, 2022
4db3170
refactor: name the module for the directory it's using
mogul Mar 12, 2022
42847ac
doc: comment on where the subnets come from
mogul Mar 12, 2022
5a6eccc
refactor: abstract variable usage via locals
mogul Mar 15, 2022
8c115dc
refactor: rename files that will be linked into provision-aws
mogul Mar 15, 2022
5f70ebe
feat: add a provision-aws-local way to define the locals for provisio…
mogul Mar 15, 2022
db95a47
doc: adjust setup commands to allow for relative symlinks
mogul Mar 15, 2022
499cad9
fix: xlarge instances aren't available in us-west-2d, so skip that AZ
mogul Mar 16, 2022
4750d57
fix: the service-definition explicitly includes/excludes files based …
mogul Mar 16, 2022
cfa5ad7
cleanup: ran `terraform fmt`
mogul Mar 16, 2022
1f16d95
cleanup: indent to make scanning visually for filename/directory chan…
mogul Mar 16, 2022
ca81f25
fix: "admin" is a ClusterRole
mogul Mar 16, 2022
5ca6769
refactor: ran shellcheck on the file
mogul Mar 17, 2022
a4888ab
fix: add test that waits for DNS resolution of the expected domain to…
mogul Mar 17, 2022
e2e81e8
fix: turn off verbose output now that the test is working
mogul Mar 17, 2022
8b7c4fd
fix: increase the time to wait for DNS resolution to succeed
mogul Mar 17, 2022
440a12f
fix: leave terminals in a usable state after tests end
mogul Mar 18, 2022
b1be203
fix: cleanup stray output from the 60s socket closing test
mogul Mar 18, 2022
aa082e0
fix: no DNS provider is better than another; just wait longer
mogul Mar 18, 2022
db09ae1
fix: avoid naming collisions when you re-attempt a GitHub Action
mogul Mar 18, 2022
aad9c51
fix: ensure that domain names don't end with a '-'
mogul Mar 18, 2022
6acc307
fix: stty sane doesn't work in a pty
mogul Mar 18, 2022
88afd62
enh: clue people in to when they can play 2048 earlier
mogul Mar 18, 2022
6f41773
fix: wait up to 600 seconds for DNSSEC DS records to propagate
mogul Mar 18, 2022
b24aa0b
debt: disable flaky DNSSEC validation test
mogul Mar 22, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,11 @@ jobs:
# Docs for this method:
# https://docs.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-environment-variable
run: |
INSTANCE_NAME="$(echo ci-${{ github.event.pull_request.number }}-${GITHUB_RUN_ID})"
INSTANCE_NAME="$(echo ci-${{ github.event.pull_request.number }}-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT})"
if [[ "$(echo -n ${INSTANCE_NAME} | wc -c)" -lt "64" ]]; then
INSTANCE_NAME=${INSTANCE_NAME}-special-extra-long-padding-for-real-test-case-because-ssb-needs-it
INSTANCE_NAME=$(head -c 64 <<< $INSTANCE_NAME)
INSTANCE_NAME="${INSTANCE_NAME}-a-long-suffix-to-ensure-we-are-generating-ids-that-are-short-enough-for-underlying-identifiers"
INSTANCE_NAME="${INSTANCE_NAME//-}"
INSTANCE_NAME=$(head -c 64 <<< "$INSTANCE_NAME")
fi
echo "INSTANCE_NAME=${INSTANCE_NAME}" | tee -a $GITHUB_ENV

Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,5 @@ kubeconfig-*
*.swp
terraform.log
*.binding.json
terraform/modules/provision-aws/provider-*.tf
terraform/modules/provision-aws/k8s-*.tf
66 changes: 44 additions & 22 deletions eks-service-definition.yml
Original file line number Diff line number Diff line change
Expand Up @@ -117,23 +117,41 @@ provision:
details: The cluster token for authentication of the eks cluster user

template_refs:
admin-account: terraform/modules/provision/admin-account.tf
crds: terraform/modules/provision/crds.tf
clusterdns: terraform/modules/provision/cluster-dns.tf
data: terraform/modules/provision/data.tf
eks: terraform/modules/provision/eks.tf
external-dns: terraform/modules/provision/external-dns.tf
ingress: terraform/modules/provision/ingress.tf
logging: terraform/modules/provision/logging.tf
main: terraform/modules/provision/main.tf
outputs: terraform/modules/provision/outputs.tf
providers-aws: terraform/modules/provision/providers/aws.tf
providers-kubernetes: terraform/modules/provision/providers/kubernetes.tf
providers-helm: terraform/modules/provision/providers/helm.tf
rbac: terraform/modules/provision/rbac.tf
variables: terraform/modules/provision/variables.tf
vpc: terraform/modules/provision/vpc.tf
persistent-storage: terraform/modules/provision/persistent-storage.tf

# These files make up the provision module (AWS resources)
cluster-dns: terraform/modules/provision-aws/cluster-dns.tf
crds: terraform/modules/provision-aws/crds.tf
data: terraform/modules/provision-aws/data.tf
eks: terraform/modules/provision-aws/eks.tf
external-dns: terraform/modules/provision-aws/external-dns.tf
ingress: terraform/modules/provision-aws/ingress.tf
main: terraform/modules/provision-aws/main.tf
outputs: terraform/modules/provision-aws/outputs.tf
persistent-storage: terraform/modules/provision-aws/persistent-storage.tf
variables: terraform/modules/provision-aws/variables.tf
versions: terraform/modules/provision-aws/versions.tf
vpc: terraform/modules/provision-aws/vpc.tf

# Since these modules are being used as a root module in the brokerpak,
# these files add the necessary provider configuration.
provider-aws: terraform/modules/provision-aws/providers/provider-aws.tf
provider-kubernetes: terraform/modules/provision-aws/providers/provider-kubernetes.tf
provider-helm: terraform/modules/provision-aws/providers/provider-helm.tf

# This file sets provision-k8s locals based on internal/output values from provision-aws
k8s-locals: terraform/modules/provision-aws/locals/k8s-locals.tf

# These files make up the provision module (k8s/helm resources)
k8s-admin-account: terraform/modules/provision-k8s/k8s-admin-account.tf
k8s-external-dns: terraform/modules/provision-k8s/k8s-external-dns.tf
k8s-logging: terraform/modules/provision-k8s/k8s-logging.tf
k8s-outputs: terraform/modules/provision-k8s/k8s-outputs.tf
k8s-persistent-storage: terraform/modules/provision-k8s/k8s-persistent-storage.tf

# EXPLICITLY OMITTED; these are only useful for submodule usage
# terraform/modules/provision-aws/standalone-outputs.tf
# terraform/modules/provision-k8s/standalone-variables.tf
# terraform/modules/provision-k8s/standalone-versions.tf

bind:
plan_inputs: []
Expand Down Expand Up @@ -181,11 +199,15 @@ bind:
type: string
details: The CA data for the kubernetes endpoint
template_refs:
main: terraform/modules/bind/main.tf
data: terraform/modules/bind/data.tf
outputs: terraform/modules/bind/outputs.tf
providers: terraform/modules/bind/providers/kubernetes.tf
variables: terraform/modules/bind/variables.tf
data: terraform/modules/bind/data.tf
main: terraform/modules/bind/main.tf
outputs: terraform/modules/bind/outputs.tf
variables: terraform/modules/bind/variables.tf
versions: terraform/modules/bind/versions.tf

# Since this module is being used as a root module in the brokerpak, this file adds the necessary provider
provider-kubernetes: terraform/modules/bind/providers/provider-kubernetes.tf

examples:
- name: Demonstrate provisioning and binding the "raw" plan
description: |
Expand Down
6 changes: 3 additions & 3 deletions terraform/bind-providers.tf
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
provider "kubernetes" {
alias = "bind"
host = module.provision.server
cluster_ca_certificate = base64decode(module.provision.certificate_authority_data)
token = module.provision.token
host = data.aws_eks_cluster.cluster.endpoint
cluster_ca_certificate = base64decode(data.aws_eks_cluster.cluster.certificate_authority.0.data)
token = module.provision-k8s.token
}
29 changes: 23 additions & 6 deletions terraform/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ terraform {
# configuration pointing specifically at the us-east-1 region. We are
# required to set up KMS keys in that region in order for them to be usable
# for setting up a DNSSEC KSK in Route53.
# Documentation on using aliased providers in a module:
# https://www.terraform.io/language/modules/develop/providers#provider-aliases-within-modules
aws = {
source = "hashicorp/aws"
version = "~> 3.63"
Expand All @@ -15,7 +17,7 @@ terraform {
}

output "domain_name" {
value = module.provision.domain_name
value = module.provision-aws.domain_name
}

output "certificate_authority_data" {
Expand Down Expand Up @@ -87,13 +89,11 @@ variable "write_kubeconfig" {
default = false
}

module "provision" {
source = "./modules/provision"
module "provision-aws" {
source = "./modules/provision-aws"
providers = {
aws = aws
aws.dnssec-key-provider = aws.dnssec-key-provider
kubernetes = kubernetes.provision
helm = helm.provision
}
instance_name = var.instance_name
labels = var.labels
Expand All @@ -107,13 +107,30 @@ module "provision" {
zone = var.zone
}

module "provision-k8s" {
source = "./modules/provision-k8s"
providers = {
aws = aws
kubernetes = kubernetes.provision
helm = helm.provision
}
certificate_authority_data = module.provision-aws.certificate_authority_data
domain = module.provision-aws.domain_name
instance_name = var.instance_name
persistent_storage_key_id = module.provision-aws.persistent_storage_key_id
region = var.region
server = module.provision-aws.server
zone_id = module.provision-aws.zone_id
zone_role_arn = module.provision-aws.zone_role_arn
}

module "bind" {
source = "./modules/bind"
providers = {
kubernetes = kubernetes.bind
}
instance_name = var.instance_name
depends_on = [
module.provision
module.provision-k8s
]
}
5 changes: 0 additions & 5 deletions terraform/modules/bind/data.tf
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,6 @@ locals {
data "aws_eks_cluster" "main" {
name = local.cluster_name
}

data "aws_eks_cluster_auth" "main" {
name = local.cluster_name
}

# Read in the generated secret for the service account
data "kubernetes_secret" "secret" {
metadata {
Expand Down
7 changes: 4 additions & 3 deletions terraform/modules/bind/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ resource "kubernetes_service_account" "account" {
}
}

# Bind the namespace-admin role to the service account
# Make the service account an admin within the namespace. See
# https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles.
resource "kubernetes_role_binding" "binding" {
metadata {
name = "${kubernetes_service_account.account.metadata[0].name}-namespace-admin-role-binding"
Expand All @@ -20,8 +21,8 @@ resource "kubernetes_role_binding" "binding" {

role_ref {
api_group = "rbac.authorization.k8s.io"
kind = "Role"
name = "namespace-admin"
kind = "ClusterRole"
name = "admin"
}

subject {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,18 @@ the broker context here.
docker build -t eks-provision:latest .
```

1. Symlink the various files that make this module self-contained into this directory:

```bash
ln -s providers/* locals/* ../provision-k8s/k8s-* .
```

1. Then, start a shell inside a container based on this image. The parameters
here carry some of your environment variables into that shell, and ensure
that you'll have permission to remove any files that get created.

```bash
$ docker run -v `pwd`:`pwd` -w `pwd` -e HOME=`pwd` --user $(id -u):$(id -g) -e TERM -it --rm -e AWS_SECRET_ACCESS_KEY -e AWS_ACCESS_KEY_ID -e AWS_DEFAULT_REGION eks-provision:latest
$ docker run -v `pwd`/..:`pwd`/.. -w `pwd` -e HOME=`pwd` --user $(id -u):$(id -g) -e TERM -it --rm -e AWS_SECRET_ACCESS_KEY -e AWS_ACCESS_KEY_ID -e AWS_DEFAULT_REGION eks-provision:latest

[within the container]
terraform init
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
locals {
# Prevent provisioning if the necessary CLI binaries aren't present
cluster_name = "k8s-${substr(sha256(var.instance_name), 0, 16)}"
cluster_version = "1.21"
kubeconfig = "kubeconfig-${local.cluster_name}"
Expand Down Expand Up @@ -99,6 +98,18 @@ module "eks" {
max_size = var.mng_max_capacity
min_size = var.mng_min_capacity

block_device_mappings = {
xvda = {
device_name = "/dev/xvda"
ebs = {
volume_size = 20
encrypted = true
kms_key_id = aws_kms_key.ebs-key.arn
delete_on_termination = true
}
}
}

instance_types = var.mng_instance_types
capacity_type = "ON_DEMAND"
}
Expand Down Expand Up @@ -132,6 +143,28 @@ resource "aws_iam_role_policy_attachment" "ebs-usage" {
role = each.value.iam_role_name
}

# ---------------------------------------------
# Logging Policy for the pod execution IAM role
# ---------------------------------------------
resource "aws_iam_policy" "pod-logging" {
name = "${local.cluster_name}-pod-logging"
policy = <<-EOF
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": [
"logs:CreateLogStream",
"logs:CreateLogGroup",
"logs:DescribeLogStreams",
"logs:PutLogEvents"
],
"Resource": "*"
}]
}
EOF
}


# Generate a kubeconfig file for use in provisioners
data "template_file" "kubeconfig" {
Expand Down
59 changes: 59 additions & 0 deletions terraform/modules/provision-aws/external-dns.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Modeled after an example here:
# https://tech.polyconseil.fr/external-dns-helm-terraform.html

data "aws_caller_identity" "current" {}

resource "aws_iam_role" "external_dns" {
name = "${local.cluster_name}-external-dns"
tags = var.labels
assume_role_policy = <<-EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRoleWithWebIdentity",
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::${data.aws_caller_identity.current.account_id}:oidc-provider/${module.eks.oidc_provider}"
},
"Condition": {
"StringEquals": {
"${module.eks.oidc_provider}:sub": "system:serviceaccount:kube-system:external-dns"
}
}
}
]
}
EOF
}

resource "aws_iam_role_policy" "external_dns" {
name_prefix = "${local.cluster_name}-external-dns"
role = aws_iam_role.external_dns.name
policy = <<-EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"route53:ChangeResourceRecordSets"
],
"Resource": [
"arn:aws:route53:::hostedzone/${aws_route53_zone.cluster.zone_id}"
]
},
{
"Effect": "Allow",
"Action": [
"route53:ListHostedZones",
"route53:ListResourceRecordSets"
],
"Resource": [
"*"
]
}
]
}
EOF
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ resource "helm_release" "ingress_nginx" {

dynamic "set" {
for_each = {
"aws_iam_role_arn" = module.aws_load_balancer_controller.aws_iam_role_arn
"controller.ingressClassResource.default" = true
"controller.service.annotations.service\\.beta\\.kubernetes\\.io/aws-load-balancer-scheme" = "internet-facing",
"controller.service.annotations.service\\.beta\\.kubernetes\\.io/aws-load-balancer-ssl-ports" = "https",
"controller.service.annotations.service\\.beta\\.kubernetes\\.io/aws-load-balancer-ssl-cert" = aws_acm_certificate.cert.arn,
Expand Down Expand Up @@ -87,7 +89,6 @@ resource "helm_release" "ingress_nginx" {
"clusterName" = module.eks.cluster_id,
"region" = local.region,
"vpcId" = module.vpc.vpc_id,
"aws_iam_role_arn" = module.aws_load_balancer_controller.aws_iam_role_arn
}
content {
name = set.key
Expand Down
7 changes: 7 additions & 0 deletions terraform/modules/provision-aws/locals/k8s-locals.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
locals {
certificate_authority_data = data.aws_eks_cluster.main.certificate_authority[0].data
persistent_storage_key_id = aws_kms_key.ebs-key.key_id
server = data.aws_eks_cluster.main.endpoint
zone_id = aws_route53_zone.cluster.zone_id
zone_role_arn = aws_iam_role.external_dns.arn
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
# can to avoid that.
resource "null_resource" "prerequisite_binaries_present" {
provisioner "local-exec" {
interpreter = ["/bin/sh", "-c"]
command = "type -p aws-iam-authenticator git helm kubectl"
interpreter = ["/bin/bash", "-c"]
command = "type -a aws-iam-authenticator git helm kubectl"
}
}
4 changes: 4 additions & 0 deletions terraform/modules/provision-aws/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
output "domain_name" { value = local.domain }
output "server" { value = data.aws_eks_cluster.main.endpoint }
output "certificate_authority_data" { value = data.aws_eks_cluster.main.certificate_authority[0].data }
output "cluster-id" { value = data.aws_eks_cluster.main.id }
Loading