diff --git a/terraform-modules/aws/eks-efs-csi-driver/README.md b/terraform-modules/aws/eks-efs-csi-driver/README.md new file mode 100644 index 000000000..3169bda26 --- /dev/null +++ b/terraform-modules/aws/eks-efs-csi-driver/README.md @@ -0,0 +1,8 @@ +# EKS EFS CSI Driver + +source: https://github.com/kubernetes-sigs/aws-efs-csi-driver + + +Creates: +* AWS IAM policies for the efs-csi-driver to access EFS +* Deploys the aws-efs-csi-driver helm chart into an EKS cluster diff --git a/terraform-modules/aws/eks-efs-csi-driver/efs-policy.json b/terraform-modules/aws/eks-efs-csi-driver/efs-policy.json new file mode 100644 index 000000000..32ee8d5a3 --- /dev/null +++ b/terraform-modules/aws/eks-efs-csi-driver/efs-policy.json @@ -0,0 +1,36 @@ +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "elasticfilesystem:DescribeAccessPoints", + "elasticfilesystem:DescribeFileSystems" + ], + "Resource": "*" + }, + { + "Effect": "Allow", + "Action": [ + "elasticfilesystem:CreateAccessPoint" + ], + "Resource": "*", + "Condition": { + "StringLike": { + "aws:RequestTag/efs.csi.aws.com/cluster": "true" + } + } + }, + { + "Effect": "Allow", + "Action": "elasticfilesystem:DeleteAccessPoint", + "Resource": "*", + "Condition": { + "StringEquals": { + "aws:ResourceTag/efs.csi.aws.com/cluster": "true" + } + } + } + ] + } + \ No newline at end of file diff --git a/terraform-modules/aws/eks-efs-csi-driver/helm_values.tpl.yaml b/terraform-modules/aws/eks-efs-csi-driver/helm_values.tpl.yaml new file mode 100644 index 000000000..ed97d539c --- /dev/null +++ b/terraform-modules/aws/eks-efs-csi-driver/helm_values.tpl.yaml @@ -0,0 +1 @@ +--- diff --git a/terraform-modules/aws/eks-efs-csi-driver/main.tf b/terraform-modules/aws/eks-efs-csi-driver/main.tf new file mode 100644 index 000000000..5275768e7 --- /dev/null +++ b/terraform-modules/aws/eks-efs-csi-driver/main.tf @@ -0,0 +1,47 @@ +module "iam_assumable_role_admin" { + source = "terraform-aws-modules/iam/aws//modules/iam-assumable-role-with-oidc" + version = "3.6.0" + create_role = true + role_name = "efs-csi-driver-${var.cluster_name}" + provider_url = replace(var.eks_cluster_oidc_issuer_url, "https://", "") + role_policy_arns = [aws_iam_policy.cluster_autoscaler.arn] + oidc_fully_qualified_subjects = ["system:serviceaccount:${var.k8s_service_account_namespace}:${var.k8s_service_account_name}"] +} + +# Policy doc: https://github.com/kubernetes-sigs/aws-efs-csi-driver/blob/master/docs/iam-policy-example.json +resource "aws_iam_policy" "cluster_autoscaler" { + name_prefix = "efs-csi-driver-${var.cluster_name}" + description = "EKS efs-csi-driver policy for cluster ${var.eks_cluster_id}" + policy = file("${path.module}/efs-policy.json") +} + +data "aws_caller_identity" "current" {} + +# +# Helm - efs-csi-driver +# +# Docs: https://github.com/kubernetes-sigs/aws-efs-csi-driver/tree/master/charts/aws-efs-csi-driver +data "template_file" "helm_values" { + template = file("${path.module}/helm_values.tpl.yaml") + vars = { + awsAccountID = data.aws_caller_identity.current.account_id + awsRegion = var.aws_region + clusterName = var.cluster_name + serviceAccountName = var.k8s_service_account_name + } +} + +module "eks-efs-csi-driver" { + source = "github.com/ManagedKube/kubernetes-ops//terraform-modules/aws/helm/helm_generic?ref=v1.0.9" + + repository = "https://kubernetes-sigs.github.io/aws-efs-csi-driver" + official_chart_name = "aws-efs-csi-driver" + user_chart_name = "aws-efs-csi-driver" + helm_version = "1.2.4" + namespace = "kube-system" + helm_values = data.template_file.helm_values.rendered + + depends_on = [ + module.iam_assumable_role_admin + ] +} diff --git a/terraform-modules/aws/eks-efs-csi-driver/outputs.tf b/terraform-modules/aws/eks-efs-csi-driver/outputs.tf new file mode 100644 index 000000000..0ff7df1b0 --- /dev/null +++ b/terraform-modules/aws/eks-efs-csi-driver/outputs.tf @@ -0,0 +1,11 @@ +# output "arn" { +# value = module.eks-efs-csi-driver.arn +# } + +# output "id" { +# value = module.eks-efs-csi-driver.id +# } + +# output "dns_name" { +# value = module.eks-efs-csi-driver.dns_name +# } diff --git a/terraform-modules/aws/eks-efs-csi-driver/variables.tf b/terraform-modules/aws/eks-efs-csi-driver/variables.tf new file mode 100644 index 000000000..b1cfac077 --- /dev/null +++ b/terraform-modules/aws/eks-efs-csi-driver/variables.tf @@ -0,0 +1,41 @@ +variable "aws_region" { + type = string + default = "us-east-1" + description = "AWS region" +} + +variable "cluster_name" { + type = string + default = "cluster" + description = "EKS cluster name" +} + + +variable "eks_cluster_id" { + type = string + default = "" + description = "EKS cluster ID" +} + +variable "eks_cluster_oidc_issuer_url" { + type = string + default = "" + description = "EKS cluster oidc issuer url" +} + +variable "k8s_service_account_namespace" { + type = string + default = "kube-system" + description = "Namespace to place the service account into" +} + +variable "k8s_service_account_name" { + type = string + default = "cluster-autoscaler-aws-cluster-autoscaler" + description = "Service account name" +} + +variable "tags" { + type = map(any) + default = {} +} diff --git a/terraform-modules/aws/kubernetes-efs-volume/README.md b/terraform-modules/aws/kubernetes-efs-volume/README.md new file mode 100644 index 000000000..11585f6e0 --- /dev/null +++ b/terraform-modules/aws/kubernetes-efs-volume/README.md @@ -0,0 +1,10 @@ +# kubernetes-efs-volume + +Depends on the `eks-efs-csi-driver` module to be instantiated in the cluster first. + +This module will: +* Create an AWS EFS resource with the appropriate security group and IAM permisisons +* Create a persistent volume (pv) pointing to this EFS endpoint +* Create a persistent volume claim (pvc) pointing to the `pv` + +You can then readily use the `pvc` to mount to any resources in Kubernetes. diff --git a/terraform-modules/aws/kubernetes-efs-volume/main.tf b/terraform-modules/aws/kubernetes-efs-volume/main.tf new file mode 100644 index 000000000..9438bb193 --- /dev/null +++ b/terraform-modules/aws/kubernetes-efs-volume/main.tf @@ -0,0 +1,98 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 3.37.0" + } + kubernetes = { + source = "hashicorp/kubernetes" + version = ">= 2.1.0" + } + } +} + + +module "efs" { + source = "cloudposse/efs/aws" + version = "0.30.1" + + namespace = var.efs_namespace + stage = var.environment_name + name = var.efs_name + region = var.aws_region + vpc_id = var.vpc_id + subnets = var.subnets + security_groups = var.security_groups + + tags = var.tags +} + +resource "kubernetes_storage_class" "storage_class" { + metadata { + name = "${var.efs_name}-sc" + } + storage_provisioner = "efs.csi.aws.com" + reclaim_policy = var.reclaim_policy + # https://github.com/kubernetes-sigs/aws-efs-csi-driver/tree/master/examples/kubernetes/dynamic_provisioning#dynamic-provisioning + parameters = { + provisioningMode = var.storage_class_parameters_provisioningMode + directoryPerms = var.storage_class_parameters_directoryPerms + gidRangeStart = var.storage_class_parameters_gidRangeStart + gidRangeEnd = var.storage_class_parameters_gidRangeEnd + basePath = var.storage_class_parameters_basePath + } + mount_options = ["tls"] + + depends_on = [ + module.efs + ] +} + +resource "kubernetes_persistent_volume" "pv" { + metadata { + name = var.efs_name + } + spec { + storage_class_name = "${var.efs_name}-sc" + persistent_volume_reclaim_policy = var.persistent_volume_reclaim_policy + capacity = { + storage = var.storage_capacity + } + access_modes = var.access_modes + mount_options = ["tls"] + persistent_volume_source { + csi { + driver = "efs.csi.aws.com" + volume_handle = module.efs.id + volume_attributes = { + encryptInTransit = true + } + } + } + } + + depends_on = [ + kubernetes_storage_class.storage_class + ] +} + +resource "kubernetes_persistent_volume_claim" "pvc" { + metadata { + name = var.efs_name + namespace = var.kubernetes_namespace + } + spec { + access_modes = var.access_modes + resources { + requests = { + storage = var.storage_capacity + } + } + volume_name = kubernetes_persistent_volume.pv.metadata.0.name + storage_class_name = "${var.efs_name}-sc" + } + + depends_on = [ + kubernetes_persistent_volume.pv + ] +} diff --git a/terraform-modules/aws/kubernetes-efs-volume/outputs.tf b/terraform-modules/aws/kubernetes-efs-volume/outputs.tf new file mode 100644 index 000000000..7293a5e18 --- /dev/null +++ b/terraform-modules/aws/kubernetes-efs-volume/outputs.tf @@ -0,0 +1,8 @@ +output "kubernetes_persistent_volume_claim_name" { + value = var.efs_name + description = "Name of the pvc claim" +} + +output "kubernetes_persistent_volume_name" { + value = var.efs_name +} \ No newline at end of file diff --git a/terraform-modules/aws/kubernetes-efs-volume/variables.tf b/terraform-modules/aws/kubernetes-efs-volume/variables.tf new file mode 100644 index 000000000..9ea4743ff --- /dev/null +++ b/terraform-modules/aws/kubernetes-efs-volume/variables.tf @@ -0,0 +1,107 @@ +variable "efs_namespace" { + type = string + default = "kubernetes-ops" + description = "Delimiter for EFS naming" +} + +variable "environment_name" { + type = string + default = "env" + description = "A name for this environment" +} + +variable "efs_name" { + type = string + default = "efs" + description = "A name for the EFS volume" +} + +variable "aws_region" { + type = string + default = "us-east-1" + description = "AWS region this EFS will go into" +} + +variable "vpc_id" { + type = string + default = "vcp-xxx" + description = "VPC ID that this EFS will go into" +} + +variable "subnets" { + type = list(string) + default = [] + description = "A list of subnets to place the EFS mount points at (can not have multiple subnets in the same availability zone" +} + +variable "security_groups" { + type = list(string) + default = [] + description = "A list of security groups to allow access to this EFS resource" +} + +variable "kubernetes_namespace" { + type = string + default = "kubernetes-ops" + description = "The namespaces the pvc should be deployed into" +} + + +variable "tags" { + type = map(any) + default = {} +} + +variable "reclaim_policy" { + type = string + default = "Retain" + description = "Storage class reclaim policy" +} + +variable "storage_class_parameters_provisioningMode" { + type = string + default = "efs-ap" + description = "description" +} + +variable "storage_class_parameters_directoryPerms" { + type = string + default = "700" + description = "description" +} + +variable "storage_class_parameters_gidRangeStart" { + type = string + default = "1000" + description = "description" +} + +variable "storage_class_parameters_gidRangeEnd" { + type = string + default = "2000" + description = "description" +} + +variable "storage_class_parameters_basePath" { + type = string + default = "/" + description = "description" +} + +variable "persistent_volume_reclaim_policy" { + type = string + default = "Retain" + description = "persistent_volume_reclaim_policy" +} + +variable "storage_capacity" { + type = string + default = "2Gi" + description = "Size of the nfs disk" +} + +variable "access_modes" { + type = list(any) + default = ["ReadWriteMany"] + description = "access_modes" +} diff --git a/terraform-modules/aws/vpc/main.tf b/terraform-modules/aws/vpc/main.tf index b1562fb46..69f21de0d 100644 --- a/terraform-modules/aws/vpc/main.tf +++ b/terraform-modules/aws/vpc/main.tf @@ -12,6 +12,9 @@ module "vpc" { enable_nat_gateway = var.enable_nat_gateway enable_vpn_gateway = var.enable_vpn_gateway + enable_dns_hostnames = var.enable_dns_hostnames + enable_dns_support = var.enable_dns_support + public_subnet_tags = { "kubernetes.io/cluster/${var.cluster_name}" = "shared" "kubernetes.io/role/elb" = "1" diff --git a/terraform-modules/aws/vpc/variables.tf b/terraform-modules/aws/vpc/variables.tf index c4ce1b9d2..2193be554 100644 --- a/terraform-modules/aws/vpc/variables.tf +++ b/terraform-modules/aws/vpc/variables.tf @@ -38,3 +38,15 @@ variable "cluster_name" { default = "none" description = "The cluster name for the Kubernetes tags on the subnets" } + +variable "enable_dns_hostnames" { + type = bool + default = true + description = "Enable dns hostname resolution" +} + +variable "enable_dns_support" { + type = bool + default = true + description = "Enable dns support" +}