From 38d1de7846ff12cc15f4b708f08b68c145b6c521 Mon Sep 17 00:00:00 2001 From: Andrej Kislovskij Date: Wed, 13 Nov 2024 09:42:30 +0200 Subject: [PATCH] NOJIRA: Add IPv6 enabled EKS cluster to the examples --- examples/eks/eks_cluster_ipv6/README.MD | 27 ++++++ examples/eks/eks_cluster_ipv6/castai.tf | 85 +++++++++++++++++++ examples/eks/eks_cluster_ipv6/eks.tf | 68 +++++++++++++++ examples/eks/eks_cluster_ipv6/providers.tf | 16 ++++ examples/eks/eks_cluster_ipv6/tf.vars.example | 6 ++ examples/eks/eks_cluster_ipv6/variables.tf | 46 ++++++++++ examples/eks/eks_cluster_ipv6/versions.tf | 17 ++++ examples/eks/eks_cluster_ipv6/vpc.tf | 41 +++++++++ 8 files changed, 306 insertions(+) create mode 100644 examples/eks/eks_cluster_ipv6/README.MD create mode 100644 examples/eks/eks_cluster_ipv6/castai.tf create mode 100644 examples/eks/eks_cluster_ipv6/eks.tf create mode 100644 examples/eks/eks_cluster_ipv6/providers.tf create mode 100644 examples/eks/eks_cluster_ipv6/tf.vars.example create mode 100644 examples/eks/eks_cluster_ipv6/variables.tf create mode 100644 examples/eks/eks_cluster_ipv6/versions.tf create mode 100644 examples/eks/eks_cluster_ipv6/vpc.tf diff --git a/examples/eks/eks_cluster_ipv6/README.MD b/examples/eks/eks_cluster_ipv6/README.MD new file mode 100644 index 00000000..2831a072 --- /dev/null +++ b/examples/eks/eks_cluster_ipv6/README.MD @@ -0,0 +1,27 @@ +## EKS and CAST AI example for onboarding IPv6 enabled cluster + +Following this example shows how to onboard an IPv6 enabled EKS cluster to CAST AI platform. + +# Usage +1. Rename `tf.vars.example` to `tf.vars` +2. Update `tf.vars` file with your cluster name, cluster region and CAST AI API token, etc. + +| Variable | Description | +| --- | --- | +| cluster_name = "" | Name of cluster | +| cluster_region = "" | Name of region of cluster | +| castai_api_token = "" | Cast api token | + + +3. Initialize Terraform. Under example root folder run: +``` +terraform init +``` +4. Run Terraform apply: +``` +terraform apply -var-file=tf.vars +``` +5. To destroy resources created by this example: +``` +terraform destroy -var-file=tf.vars +``` diff --git a/examples/eks/eks_cluster_ipv6/castai.tf b/examples/eks/eks_cluster_ipv6/castai.tf new file mode 100644 index 00000000..e8e45cc9 --- /dev/null +++ b/examples/eks/eks_cluster_ipv6/castai.tf @@ -0,0 +1,85 @@ +# # 3. Connect EKS cluster to CAST AI. +# +locals { + role_name = "castai-eks-role" +} + +# Configure Data sources and providers required for CAST AI connection. +data "aws_caller_identity" "current" {} + +resource "castai_eks_user_arn" "castai_user_arn" { + cluster_id = castai_eks_clusterid.cluster_id.id +} + +provider "castai" { + api_url = var.castai_api_url + api_token = var.castai_api_token +} + +provider "helm" { + kubernetes { + host = module.eks.cluster_endpoint + cluster_ca_certificate = base64decode(module.eks.cluster_certificate_authority_data) + exec { + api_version = "client.authentication.k8s.io/v1beta1" + command = "aws" + # This requires the awscli to be installed locally where Terraform is executed. + args = ["eks", "get-token", "--cluster-name", module.eks.cluster_name, "--region", var.cluster_region] + } + } +} + +# Create AWS IAM policies and a user to connect to CAST AI. +module "castai-eks-role-iam" { + source = "castai/eks-role-iam/castai" + + aws_account_id = data.aws_caller_identity.current.account_id + aws_cluster_region = var.cluster_region + aws_cluster_name = var.cluster_name + aws_cluster_vpc_id = module.vpc.vpc_id + + castai_user_arn = castai_eks_user_arn.castai_user_arn.arn + + create_iam_resources_per_cluster = true +} + +# Configure EKS cluster connection using CAST AI eks-cluster module. +resource "castai_eks_clusterid" "cluster_id" { + account_id = data.aws_caller_identity.current.account_id + region = var.cluster_region + cluster_name = var.cluster_name +} + +module "castai-eks-cluster" { + source = "castai/eks-cluster/castai" + api_url = var.castai_api_url + castai_api_token = var.castai_api_token + grpc_url = var.castai_grpc_url + wait_for_cluster_ready = true + + aws_account_id = data.aws_caller_identity.current.account_id + aws_cluster_region = var.cluster_region + aws_cluster_name = module.eks.cluster_name + + aws_assume_role_arn = module.castai-eks-role-iam.role_arn + delete_nodes_on_disconnect = var.delete_nodes_on_disconnect + + default_node_configuration = module.castai-eks-cluster.castai_node_configurations["default"] + + node_configurations = { + default = { + subnets = module.vpc.private_subnets + tags = var.tags + security_groups = [ + module.eks.cluster_security_group_id, + module.eks.node_security_group_id, + aws_security_group.additional.id, + ] + instance_profile_arn = module.castai-eks-role-iam.instance_profile_arn + } + } + + // depends_on helps Terraform with creating proper dependencies graph in case of resource creation and in this case destroy. + // module "castai-eks-cluster" has to be destroyed before module "castai-eks-role-iam". + depends_on = [module.castai-eks-role-iam, module.eks] +} diff --git a/examples/eks/eks_cluster_ipv6/eks.tf b/examples/eks/eks_cluster_ipv6/eks.tf new file mode 100644 index 00000000..9bc4f59b --- /dev/null +++ b/examples/eks/eks_cluster_ipv6/eks.tf @@ -0,0 +1,68 @@ +# 2. Create EKS cluster. +module "eks" { + source = "terraform-aws-modules/eks/aws" + version = "19.4.2" + putin_khuylo = true + + cluster_name = var.cluster_name + cluster_version = var.cluster_version + cluster_endpoint_public_access = true + + cluster_ip_family = "ipv6" + create_cni_ipv6_iam_policy = true + + cluster_addons = { + coredns = { + most_recent = true + } + kube-proxy = { + most_recent = true + } + vpc-cni = { + most_recent = true + } + } + + vpc_id = module.vpc.vpc_id + subnet_ids = module.vpc.private_subnets + + manage_aws_auth_configmap = true + + aws_auth_roles = [ + # Add the CAST AI IAM role which required for CAST AI nodes to join the cluster. + { + rolearn = module.castai-eks-role-iam.instance_profile_role_arn + username = "system:node:{{EC2PrivateDNSName}}" + groups = [ + "system:bootstrappers", + "system:nodes", + ] + }, + ] + + eks_managed_node_groups = { + initial = { + name = "${var.cluster_name}-ng-2" + instance_types = ["m5.large"] + + max_size = 3 + min_size = 2 + desired_size = 2 + } + } +} + +# Example additional security group. +resource "aws_security_group" "additional" { + name_prefix = "${var.cluster_name}-additional" + vpc_id = module.vpc.vpc_id + + ingress { + from_port = 22 + to_port = 22 + protocol = "tcp" + cidr_blocks = [ + "10.0.0.0/8", + ] + } +} diff --git a/examples/eks/eks_cluster_ipv6/providers.tf b/examples/eks/eks_cluster_ipv6/providers.tf new file mode 100644 index 00000000..d3ee622b --- /dev/null +++ b/examples/eks/eks_cluster_ipv6/providers.tf @@ -0,0 +1,16 @@ +# Following providers required by EKS and VPC modules. +provider "aws" { + region = var.cluster_region +} + +provider "kubernetes" { + host = module.eks.cluster_endpoint + cluster_ca_certificate = base64decode(module.eks.cluster_certificate_authority_data) + + # Make sure awscli is installed locally where Terraform is executed. + exec { + api_version = "client.authentication.k8s.io/v1beta1" + command = "aws" + args = ["eks", "get-token", "--cluster-name", module.eks.cluster_name, "--region", var.cluster_region] + } +} diff --git a/examples/eks/eks_cluster_ipv6/tf.vars.example b/examples/eks/eks_cluster_ipv6/tf.vars.example new file mode 100644 index 00000000..16f1af0e --- /dev/null +++ b/examples/eks/eks_cluster_ipv6/tf.vars.example @@ -0,0 +1,6 @@ +castai_api_url = "" +castai_grpc_url = "" +castai_api_token = "" + +cluster_region = "" +cluster_name = "" diff --git a/examples/eks/eks_cluster_ipv6/variables.tf b/examples/eks/eks_cluster_ipv6/variables.tf new file mode 100644 index 00000000..6ac27651 --- /dev/null +++ b/examples/eks/eks_cluster_ipv6/variables.tf @@ -0,0 +1,46 @@ +# EKS module variables. +variable "cluster_name" { + type = string + description = "EKS cluster name in AWS account." +} + +variable "cluster_version" { + type = string + description = "EKS cluster name version." + default = "1.28" +} + +variable "cluster_region" { + type = string + description = "AWS Region in which EKS cluster and supporting resources will be created." +} + +variable "castai_api_url" { + type = string + description = "URL of alternative CAST AI API to be used during development or testing" + default = "https://api.cast.ai" +} + +# Variables required for connecting EKS cluster to CAST AI. +variable "castai_api_token" { + type = string + description = "CAST AI API token created in console.cast.ai API Access keys section" +} + +variable "castai_grpc_url" { + type = string + description = "CAST AI gRPC URL" + default = "grpc.cast.ai:443" +} + +variable "delete_nodes_on_disconnect" { + type = bool + description = "Optional parameter, if set to true - CAST AI provisioned nodes will be deleted from cloud on cluster disconnection. For production use it is recommended to set it to false." + default = true +} + +variable "tags" { + type = map(any) + description = "Optional tags for new cluster nodes. This parameter applies only to new nodes - tags for old nodes are not reconciled." + default = {} +} diff --git a/examples/eks/eks_cluster_ipv6/versions.tf b/examples/eks/eks_cluster_ipv6/versions.tf new file mode 100644 index 00000000..70ee4499 --- /dev/null +++ b/examples/eks/eks_cluster_ipv6/versions.tf @@ -0,0 +1,17 @@ +terraform { + required_providers { + castai = { + source = "castai/castai" + } + kubernetes = { + source = "hashicorp/kubernetes" + } + helm = { + source = "hashicorp/helm" + } + aws = { + source = "hashicorp/aws" + } + } + required_version = ">= 0.13" +} diff --git a/examples/eks/eks_cluster_ipv6/vpc.tf b/examples/eks/eks_cluster_ipv6/vpc.tf new file mode 100644 index 00000000..590c2eb3 --- /dev/null +++ b/examples/eks/eks_cluster_ipv6/vpc.tf @@ -0,0 +1,41 @@ +# 1. Create VPC. +data "aws_availability_zones" "available" {} + +locals { + name = var.cluster_name + region = var.cluster_region + + vpc_cidr = "10.0.0.0/16" + azs = slice(data.aws_availability_zones.available.names, 0, 3) + + tags = { + Example = local.name + GithubRepo = "terraform-aws-vpc" + GithubOrg = "terraform-aws-modules" + } +} + +################################################################################ +# VPC Module +################################################################################ + +module "vpc" { + source = "terraform-aws-modules/vpc/aws" + + name = local.name + cidr = local.vpc_cidr + + azs = local.azs + private_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k)] + public_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 4)] + + enable_nat_gateway = true + enable_ipv6 = true + public_subnet_assign_ipv6_address_on_creation = true + private_subnet_assign_ipv6_address_on_creation = true + + public_subnet_ipv6_prefixes = [0, 1, 2] + private_subnet_ipv6_prefixes = [3, 4, 5] + + tags = local.tags +}