Skip to main content
Version: 2.12.X

Readying Terraform Modules

If your organization intends to use AWS, then it is recommended that you review the Terraform modules that Cogynt provides to guide the installation, and modify them if necessary. These modules define everything that is needed from AWS in order to run Cogynt. Terraform uses the files to build the required Cogynt infrastructure and set up guardrails for Cogynt's working clusters.

Note

Terraform modules are meant to facilitate AWS installation. They are not required for installing, deploying, or running Cogynt.

Cogynt provides a set of .tf files in the eksv2 and ia directories. The directory contents are described in greater detail under the corresponding topic headings.

eksv2 Directory Contents

The eksv2 directory contains the following files.

iam.tf

The iam.tf file defines the roles for every node and application type for the OID connection. It includes the following definitions by default.

Nodes

Master Node
Description

The master node monitors, manages, and controls the other nodes in the cluster. It accepts client requests, schedules containers, and runs control loops to guide the cluster toward the correct state and outcome.

Node Definition
resource "aws_iam_role" "master_role" {
name = var.master_node.role_name
description = var.master_node.role_description
assume_role_policy = jsonencode({
"Version" = "2012-10-17",
"Statement" = [
{
"Action" = "sts:AssumeRole",
"Principal" = {
"Service" = "eks.amazonaws.com"
},
"Effect" = "Allow",
"Sid" = ""
}
]
})

inline_policy {
name = var.master_node.inline_policy_name
policy = jsonencode({
"Version" = "2012-10-17",
"Statement" = [
{
"Effect" = "Allow",
"Action" = [
"ec2:DescribeAccountAttributes",
"ec2:DescribeInstances",
"ec2:DescribeInternetGateways",
"ec2:DescribeRegions",
"ec2:DescribeRouteTables",
"ec2:DescribeSecurityGroups",
"ec2:DescribeSubnets",
"ec2:DescribeVolumes"
],
"Resource" = [
"*"
]
},
{
"Effect" = "Allow",
"Action" = [
"ec2:CreateSecurityGroup",
"ec2:CreateTags",
"ec2:CreateVolume",
"ec2:DescribeVolumesModifications",
"ec2:ModifyInstanceAttribute",
"ec2:ModifyVolume"
],
"Resource" = [
"*"
]
},
{
"Effect" = "Allow",
"Action" = [
"ec2:AttachVolume",
"ec2:AuthorizeSecurityGroupIngress",
"ec2:CreateRoute",
"ec2:DeleteRoute",
"ec2:DeleteSecurityGroup",
"ec2:DeleteVolume",
"ec2:DetachVolume",
"ec2:RevokeSecurityGroupIngress"
],
"Resource" = [
"*"
],
"Condition" = {
"StringEquals" = {
"eks:cluster-name" = "${var.cluster.name}"
}
}
},
{
"Effect" = "Allow",
"Action" = [
"autoscaling:DescribeAutoScalingGroups",
"autoscaling:DescribeLaunchConfigurations",
"autoscaling:DescribeTags",
"ec2:DescribeLaunchTemplateVersions"
],
"Resource" = [
"*"
]
},
{
"Effect" = "Allow",
"Action" = [
"autoscaling:SetDesiredCapacity",
"autoscaling:TerminateInstanceInAutoScalingGroup",
"autoscaling:UpdateAutoScalingGroup"
],
"Resource" = [
"*"
],
"Condition" = {
"StringEquals" = {
"autoscaling:ResourceTag/KubernetesCluster" = "${var.cluster.name}"
}
}
},
{
"Effect" = "Allow",
"Action" = [
"elasticloadbalancing:AddTags",
"elasticloadbalancing:AttachLoadBalancerToSubnets",
"elasticloadbalancing:ApplySecurityGroupsToLoadBalancer",
"elasticloadbalancing:CreateLoadBalancer",
"elasticloadbalancing:CreateLoadBalancerPolicy",
"elasticloadbalancing:CreateLoadBalancerListeners",
"elasticloadbalancing:ConfigureHealthCheck",
"elasticloadbalancing:DeleteLoadBalancer",
"elasticloadbalancing:DeleteLoadBalancerListeners",
"elasticloadbalancing:DescribeLoadBalancers",
"elasticloadbalancing:DescribeLoadBalancerAttributes",
"elasticloadbalancing:DetachLoadBalancerFromSubnets",
"elasticloadbalancing:DeregisterInstancesFromLoadBalancer",
"elasticloadbalancing:ModifyLoadBalancerAttributes",
"elasticloadbalancing:RegisterInstancesWithLoadBalancer",
"elasticloadbalancing:SetLoadBalancerPoliciesForBackendServer"
],
"Resource" = [
"*"
]
},
{
"Effect" = "Allow",
"Action" = [
"ec2:DescribeVpcs",
"elasticloadbalancing:AddTags",
"elasticloadbalancing:CreateListener",
"elasticloadbalancing:CreateTargetGroup",
"elasticloadbalancing:DeleteListener",
"elasticloadbalancing:DeleteTargetGroup",
"elasticloadbalancing:DeregisterTargets",
"elasticloadbalancing:DescribeListeners",
"elasticloadbalancing:DescribeLoadBalancerPolicies",
"elasticloadbalancing:DescribeTargetGroups",
"elasticloadbalancing:DescribeTargetHealth",
"elasticloadbalancing:ModifyListener",
"elasticloadbalancing:ModifyTargetGroup",
"elasticloadbalancing:RegisterTargets",
"elasticloadbalancing:SetLoadBalancerPoliciesOfListener"
],
"Resource" = [
"*"
]
},
{
"Effect" = "Allow",
"Action" = [
"iam:ListServerCertificates",
"iam:GetServerCertificate"
],
"Resource" = [
"*"
]
},
{
"Effect" = "Allow",
"Action" = [
"ecr:GetAuthorizationToken",
"ecr:BatchCheckLayerAvailability",
"ecr:GetDownloadUrlForLayer",
"ecr:GetRepositoryPolicy",
"ecr:DescribeRepositories",
"ecr:ListImages",
"ecr:BatchGetImage"
],
"Resource" = [
"*"
]
}
]
})
}
}

resource "aws_iam_instance_profile" "master_profile" {
name = var.master_node.instance_profile_name
role = aws_iam_role.master_role.name
}
Worker Node
Description

Worker nodes execute containerized application workloads as dictated by the master node.

Node Definition
resource "aws_iam_role" "worker_role" {
name = var.worker_node.role_name
description = var.worker_node.role_description
assume_role_policy = jsonencode({
"Version" = "2012-10-17"
"Statement" = [
{
"Action" = "sts:AssumeRole"
"Principal" = {
"Service" = "ec2.amazonaws.com"
},
"Effect" = "Allow"
}
]
})

inline_policy {
name = var.worker_node.inline_policy_name
policy = jsonencode({
"Version" = "2012-10-17"
"Statement" = [
{
"Effect" = "Allow"
"Action" = [
"ec2:DescribeInstances",
"ec2:DescribeRegions"
],
"Resource" = [
"*"
]
},
{
"Effect" = "Allow",
"Action" = [
"ecr:GetAuthorizationToken",
"ecr:BatchCheckLayerAvailability",
"ecr:GetDownloadUrlForLayer",
"ecr:GetRepositoryPolicy",
"ecr:DescribeRepositories",
"ecr:ListImages",
"ecr:BatchGetImage"
],
"Resource" = [
"*"
]
},
{
"Effect" = "Allow",
"Action" = [
"autoscaling:DescribeTags",
"autoscaling:DescribeAutoScalingGroups",
"autoscaling:DescribeAutoScalingInstances",
"autoscaling:DescribeLaunchConfigurations",
"autoscaling:SetDesiredCapacity",
"autoscaling:TerminateInstanceInAutoScalingGroup",
"autoscaling:DescribeLaunchConfigurations",
"ec2:DescribeLaunchTemplateVersions"
],
"Resource" = [
"*"
]
}
]
})
}
}

resource "aws_iam_instance_profile" "worker_profile" {
name = var.worker_node.instance_profile_name
role = aws_iam_role.worker_role.name
}

resource "aws_iam_role_policy_attachment" "worker_s3_policy" {
role = aws_iam_role.worker_role.name
policy_arn = aws_iam_policy.s3_data.arn
}

resource "aws_iam_role_policy_attachment" "worker_additional_policies" {
for_each = var.worker_node.additional_policy_arn_attachments
role = aws_iam_role.worker_role.name
policy_arn = each.value
}
Storage Node
Description

Storage nodes provide long-term and temporary storage for the cluster.

Node Definition
resource "aws_iam_role" "storage_role" {
name = var.storage_node.role_name
description = var.storage_node.role_description
assume_role_policy = jsonencode({
"Version" = "2012-10-17",
"Statement" = [
{
"Action" = "sts:AssumeRole",
"Principal" = {
"Service" = "ec2.amazonaws.com"
},
"Effect" = "Allow",
"Sid" = ""
}
]
})

inline_policy {
name = var.storage_node.inline_policy_name
policy = jsonencode({
"Version" = "2012-10-17"
"Statement" = [
{
"Effect" = "Allow"
"Action" = [
"ec2:DescribeInstances",
"ec2:DescribeRegions"
],
"Resource" = [
"*"
]
},
{
"Effect" = "Allow",
"Action" = [
"ecr:GetAuthorizationToken",
"ecr:BatchCheckLayerAvailability",
"ecr:GetDownloadUrlForLayer",
"ecr:GetRepositoryPolicy",
"ecr:DescribeRepositories",
"ecr:ListImages",
"ecr:BatchGetImage"
],
"Resource" = [
"*"
]
},
{
"Effect" = "Allow",
"Action" = [
"autoscaling:DescribeTags",
"autoscaling:DescribeAutoScalingGroups",
"autoscaling:DescribeAutoScalingInstances",
"autoscaling:DescribeLaunchConfigurations",
"autoscaling:SetDesiredCapacity",
"autoscaling:TerminateInstanceInAutoScalingGroup",
"autoscaling:DescribeLaunchConfigurations",
"ec2:DescribeLaunchTemplateVersions"
],
"Resource" = [
"*"
]
}
]
})
}

inline_policy {
name = var.storage_node.portworx_inline_policy_name
policy = jsonencode({
"Version" = "2012-10-17",
"Statement" = [
{
"Effect" = "Allow",
"Action" = [
"ec2:AttachVolume",
"ec2:ModifyVolume",
"ec2:DetachVolume",
"ec2:CreateTags",
"ec2:CreateVolume",
"ec2:DeleteTags",
"ec2:DeleteVolume",
"ec2:DescribeTags",
"ec2:DescribeVolumeAttribute",
"ec2:DescribeVolumesModifications",
"ec2:DescribeVolumeStatus",
"ec2:DescribeVolumes",
"ec2:DescribeInstances",
"autoscaling:DescribeAutoScalingGroups"
],
"Resource" = [
"*"
]
},
{
"Effect" = "Allow",
"Action" = [
"autoscaling:DescribeTags",
"autoscaling:DescribeAutoScalingGroups",
"autoscaling:DescribeAutoScalingInstances",
"autoscaling:DescribeLaunchConfigurations",
"autoscaling:SetDesiredCapacity",
"autoscaling:TerminateInstanceInAutoScalingGroup",
"autoscaling:DescribeLaunchConfigurations",
"ec2:DescribeLaunchTemplateVersions"
],
"Resource" = ["*"]
}
]
})
}
}

resource "aws_iam_instance_profile" "storage_profile" {
name = var.storage_node.instance_profile_name
role = aws_iam_role.storage_role.name
}

resource "aws_iam_role_policy_attachment" "storage_s3_policy" {
role = aws_iam_role.storage_role.name
policy_arn = aws_iam_policy.s3_data.arn
}

resource "aws_iam_role_policy_attachment" "master-AmazonEKSClusterPolicy" {
policy_arn = "arn:${var.aws_partition}:iam::aws:policy/AmazonEKSClusterPolicy"
role = aws_iam_role.master_role.name
}

resource "aws_iam_role_policy_attachment" "master-AmazonEKSVPCResourceController" {
policy_arn = "arn:${var.aws_partition}:iam::aws:policy/AmazonEKSVPCResourceController"
role = aws_iam_role.master_role.name
}

resource "aws_iam_role_policy_attachment" "worker-AmazonEKSWorkerNodePolicy" {
policy_arn = "arn:${var.aws_partition}:iam::aws:policy/AmazonEKSWorkerNodePolicy"
role = aws_iam_role.worker_role.name
}

resource "aws_iam_role_policy_attachment" "worker-AmazonEKS_CNI_Policy" {
policy_arn = "arn:${var.aws_partition}:iam::aws:policy/AmazonEKS_CNI_Policy"
role = aws_iam_role.worker_role.name
}

resource "aws_iam_role_policy_attachment" "worker-AmazonEC2ContainerRegistryReadOnly" {
policy_arn = "arn:${var.aws_partition}:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly"
role = aws_iam_role.worker_role.name
}

resource "aws_iam_role_policy_attachment" "worker-AmazonSSMManagedInstanceCore" {
policy_arn = "arn:${var.aws_partition}:iam::aws:policy/AmazonSSMManagedInstanceCore"
role = aws_iam_role.worker_role.name
}

resource "aws_iam_role_policy_attachment" "storage-AmazonEKSWorkerNodePolicy" {
policy_arn = "arn:${var.aws_partition}:iam::aws:policy/AmazonEKSWorkerNodePolicy"
role = aws_iam_role.storage_role.name
}

resource "aws_iam_role_policy_attachment" "storage-AmazonEKS_CNI_Policy" {
policy_arn = "arn:${var.aws_partition}:iam::aws:policy/AmazonEKS_CNI_Policy"
role = aws_iam_role.storage_role.name
}

resource "aws_iam_role_policy_attachment" "storage-AmazonEC2ContainerRegistryReadOnly" {
policy_arn = "arn:${var.aws_partition}:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly"
role = aws_iam_role.storage_role.name
}

resource "aws_iam_role_policy_attachment" "storage-AmazonSSMManagedInstanceCore" {
policy_arn = "arn:${var.aws_partition}:iam::aws:policy/AmazonSSMManagedInstanceCore"
role = aws_iam_role.storage_role.name
}

Applications

OIDC Provider
Description

In Cogynt, the OIDC provider establishes a trust relationship between Cogynt's external identity provider and the hosting AWS account.

For more information about OIDC providers, refer to the official AWS documentation.

Sample Code
data "tls_certificate" "eks" {
url = aws_eks_cluster.cluster.identity[0].oidc[0].issuer
}

resource "aws_iam_openid_connect_provider" "eks" {
client_id_list = ["sts.amazonaws.com"]
thumbprint_list = [data.tls_certificate.eks.certificates[0].sha1_fingerprint]
url = aws_eks_cluster.cluster.identity[0].oidc[0].issuer
}
External DNS
Description

The external DNS makes Kubernetes resources discoverable via public DNS servers. This allows configuring external DNS servers (such as AWS) for Kubernetes services.

Sample Code
resource "aws_iam_policy" "externaldns" {
count = var.hosted_zone.name != "" ? 1 : 0
name = var.externaldns.policy_name
path = "/"
description = var.externaldns.policy_description

policy = jsonencode({
Version = "2012-10-17"
"Statement" = [
{
"Effect" = "Allow",
"Action" = [
"route53:ChangeResourceRecordSets"
],
"Resource" = [
"arn:${var.aws_partition}:route53:::hostedzone/${data.aws_route53_zone.this[count.index].id}"
]
},
{
"Effect" = "Allow",
"Action" = [
"route53:ListHostedZones",
"route53:ListResourceRecordSets"
],
"Resource" = [
"*"
]
}
]
})
}

module "externaldns_role" {
count = var.hosted_zone.name != "" ? 1 : 0
source = "terraform-aws-modules/iam/aws//modules/iam-assumable-role-with-oidc"
version = "~> 3.0"

create_role = true

role_name = var.externaldns.role_name

provider_url = aws_eks_cluster.cluster.identity[0].oidc[0].issuer

role_policy_arns = [
aws_iam_policy.externaldns[count.index].arn
]
number_of_role_policy_arns = 1
}
Project Istio
Description

The project Istio is an infrastructure layer that adds observability, traffic management, and security capabilities.

For more information about Istio, refer to the official Istio documentation.

Sample Code
resource "aws_iam_policy" "istio" {
name = var.istio.policy_name
path = "/"
description = var.istio.policy_description

policy = jsonencode({
Version = "2012-10-17"
"Statement" = [
{
"Effect" = "Allow",
"Action" = [
"elasticloadbalancing:AddTags",
"elasticloadbalancing:AttachLoadBalancerToSubnets",
"elasticloadbalancing:ApplySecurityGroupsToLoadBalancer",
"elasticloadbalancing:CreateLoadBalancer",
"elasticloadbalancing:CreateLoadBalancerPolicy",
"elasticloadbalancing:CreateLoadBalancerListeners",
"elasticloadbalancing:ConfigureHealthCheck",
"elasticloadbalancing:DeleteLoadBalancer",
"elasticloadbalancing:DeleteLoadBalancerListeners",
"elasticloadbalancing:DescribeLoadBalancers",
"elasticloadbalancing:DescribeLoadBalancerAttributes",
"elasticloadbalancing:DetachLoadBalancerFromSubnets",
"elasticloadbalancing:DeregisterInstancesFromLoadBalancer",
"elasticloadbalancing:ModifyLoadBalancerAttributes",
"elasticloadbalancing:RegisterInstancesWithLoadBalancer",
"elasticloadbalancing:SetLoadBalancerPoliciesForBackendServer"
],
"Resource" = [
"*"
]
},
{
"Effect" = "Allow",
"Action" = [
"ec2:DescribeVpcs",
"elasticloadbalancing:AddTags",
"elasticloadbalancing:CreateListener",
"elasticloadbalancing:CreateTargetGroup",
"elasticloadbalancing:DeleteListener",
"elasticloadbalancing:DeleteTargetGroup",
"elasticloadbalancing:DeregisterTargets",
"elasticloadbalancing:DescribeListeners",
"elasticloadbalancing:DescribeLoadBalancerPolicies",
"elasticloadbalancing:DescribeTargetGroups",
"elasticloadbalancing:DescribeTargetHealth",
"elasticloadbalancing:ModifyListener",
"elasticloadbalancing:ModifyTargetGroup",
"elasticloadbalancing:RegisterTargets",
"elasticloadbalancing:SetLoadBalancerPoliciesOfListener"
],
"Resource" = [
"*"
]
},
{
"Effect" = "Allow",
"Action" = [
"iam:ListServerCertificates",
"iam:GetServerCertificate"
],
"Resource" = [
"*"
]
}
]
})
}

module "istio_role" {
source = "terraform-aws-modules/iam/aws//modules/iam-assumable-role-with-oidc"
version = "~> 3.0"

create_role = true

role_name = var.istio.role_name

provider_url = aws_eks_cluster.cluster.identity[0].oidc[0].issuer

role_policy_arns = [
aws_iam_policy.istio.arn
]
number_of_role_policy_arns = 1
}
AWS S3 Data
Description

The Amazon S3 data contains the necessary code to make use of Amazon S3 object storage.

Sample Code
resource "aws_iam_policy" "s3_data" {
name = var.s3_data.policy_name
path = "/"
description = var.s3_data.policy_description

policy = jsonencode({
"Version" : "2012-10-17",
"Statement" : [
{
"Effect" : "Allow",
"Action" : [
"s3:PutAnalyticsConfiguration",
"s3:GetObjectVersionTagging",
"s3:CreateBucket",
"s3:ReplicateObject",
"s3:GetObjectAcl",
"s3:GetBucketObjectLockConfiguration",
"s3:DeleteBucketWebsite",
"s3:PutLifecycleConfiguration",
"s3:GetObjectVersionAcl",
"s3:DeleteObject",
"s3:GetBucketPolicyStatus",
"s3:GetObjectRetention",
"s3:GetBucketWebsite",
"s3:PutReplicationConfiguration",
"s3:PutObjectLegalHold",
"s3:GetObjectLegalHold",
"s3:GetBucketNotification",
"s3:PutBucketCORS",
"s3:GetReplicationConfiguration",
"s3:ListMultipartUploadParts",
"s3:PutObject",
"s3:GetObject",
"s3:PutBucketNotification",
"s3:PutBucketLogging",
"s3:GetAnalyticsConfiguration",
"s3:PutBucketObjectLockConfiguration",
"s3:GetObjectVersionForReplication",
"s3:GetLifecycleConfiguration",
"s3:GetInventoryConfiguration",
"s3:GetBucketTagging",
"s3:PutAccelerateConfiguration",
"s3:DeleteObjectVersion",
"s3:GetBucketLogging",
"s3:ListBucketVersions",
"s3:RestoreObject",
"s3:ListBucket",
"s3:GetAccelerateConfiguration",
"s3:GetBucketPolicy",
"s3:PutEncryptionConfiguration",
"s3:GetEncryptionConfiguration",
"s3:GetObjectVersionTorrent",
"s3:AbortMultipartUpload",
"s3:GetBucketRequestPayment",
"s3:GetObjectTagging",
"s3:GetMetricsConfiguration",
"s3:DeleteBucket",
"s3:PutBucketVersioning",
"s3:GetBucketPublicAccessBlock",
"s3:ListBucketMultipartUploads",
"s3:PutIntelligentTieringConfiguration",
"s3:PutMetricsConfiguration",
"s3:PutBucketOwnershipControls",
"s3:GetBucketVersioning",
"s3:GetBucketAcl",
"s3:PutInventoryConfiguration",
"s3:GetObjectTorrent",
"s3:PutBucketWebsite",
"s3:PutBucketRequestPayment",
"s3:PutObjectRetention",
"s3:GetBucketCORS",
"s3:GetBucketLocation",
"s3:ReplicateDelete",
"s3:GetObjectVersion"
],
"Resource" : [
"arn:${var.aws_partition}:s3:::${var.s3_data.bucket}/*",
"arn:${var.aws_partition}:s3:::${var.s3_data.bucket}"
]
},
{
"Effect" : "Allow",
"Action" : [
"s3:PutStorageLensConfiguration",
"s3:CreateJob"
],
"Resource" : "*"
}
]
})
}

module "s3_role" {
source = "terraform-aws-modules/iam/aws//modules/iam-assumable-role-with-oidc"
version = "~> 3.0"

create_role = true

role_name = var.s3_data.role_name

provider_url = aws_eks_cluster.cluster.identity[0].oidc[0].issuer

role_policy_arns = concat([aws_iam_policy.s3_data.arn], tolist(var.worker_node.additional_policy_arn_attachments))

number_of_role_policy_arns = length(concat([aws_iam_policy.s3_data.arn], tolist(var.worker_node.additional_policy_arn_attachments)))
}
HashiCorp Vault
Description

This file defines Cogynt's secret and encryption policies for HashiCorp Vault.

For more information about HashiCorp Vault, refer to the official HashiCorp Vault documentation.

Sample Code
resource "aws_iam_policy" "hcvault" {
name = var.hcvault.policy_name
path = "/"
description = var.hcvault.policy_description

policy = jsonencode({
"Version" : "2012-10-17",
"Statement" : [
{
"Effect" : "Allow",
"Action" : [
"kms:DescribeKey",
"kms:Encrypt",
"kms:Decrypt"
],
"Resource" : [
"${aws_kms_key.hcvault.arn}"
]
}
]
})
}

module "hcvault_role" {
source = "terraform-aws-modules/iam/aws//modules/iam-assumable-role-with-oidc"
version = "~> 3.0"

create_role = true

role_name = var.hcvault.role_name

provider_url = aws_eks_cluster.cluster.identity[0].oidc[0].issuer

role_policy_arns = [
aws_iam_policy.hcvault.arn
]
number_of_role_policy_arns = 1
}

kms.tf

Description

The kms.tf file contains data for the key management system. It unseals the HashiCorp Vault in configuration.

Definition

The file's default configuration is as follows:

# Create KMS CMK for this cluster
resource "aws_kms_key" "hcvault" {
description = var.hcvault.kms_key_description
tags = {
name = var.hcvault.kms_key_name
}
}

# Add an alias to the key
resource "aws_kms_alias" "hcvault" {
name = "alias/${var.hcvault.kms_alias_name}"
target_key_id = aws_kms_key.hcvault.key_id
}

locals.tf

The locals.tf puts credentials for Cogility repos in an EC2 boot script.

Note

Contact Cogility for a default version of the file.

main.tf

Description

The main.tf file defines the AWS EKS cluster composition, along with launch templates for nodes, groups, and add-ons.

Sample Code

resource "aws_eks_cluster" "cluster" {
name = var.cluster.name
version = var.cluster.version
role_arn = aws_iam_role.master_role.arn

vpc_config {
subnet_ids = var.network.subnet_ids
endpoint_private_access = true
endpoint_public_access = var.cluster.endpoint_public_access
security_group_ids = [aws_security_group.sg.id]
}

enabled_cluster_log_types = [
"api",
"audit",
"authenticator",
"controllerManager",
"scheduler",
]
tags = var.tags
}

###############
## Workers
###############
resource "aws_launch_template" "worker" {
name = local.worker_node.launch_template_name
tags = var.tags
image_id = local.ami_image_id
user_data = base64encode(local.userdata)
vpc_security_group_ids = [aws_security_group.sg.id]
ebs_optimized = true

block_device_mappings {
device_name = local.worker_node.block_device_name

ebs {
volume_type = local.worker_node.ephemeral_volume_type
volume_size = local.worker_node.ephemeral_volume_size
throughput = local.worker_node.ephemeral_volume_throughput
iops = local.worker_node.ephemeral_volume_iops
}
}

tag_specifications {
resource_type = "instance"
tags = {
Name = local.worker_node.launch_template_name
}
}
lifecycle {
create_before_destroy = true
}
}

resource "aws_eks_node_group" "worker" {
cluster_name = aws_eks_cluster.cluster.name
node_group_name = local.worker_node.node_group_name
node_role_arn = aws_iam_role.worker_role.arn
subnet_ids = var.network.single_az == true ? split(",", var.network.subnet_ids[0]) : var.network.subnet_ids
instance_types = [local.worker_node.instance_type]
tags = var.tags

scaling_config {
desired_size = local.worker_node.scaling_min_size
max_size = local.worker_node.scaling_max_size
min_size = local.worker_node.scaling_min_size
}

labels = {
"px/enabled" = "false"
"k8s.cogynt.io/node" = "worker"
}

launch_template {
name = aws_launch_template.worker.name
version = aws_launch_template.worker.latest_version
}

lifecycle {
ignore_changes = [scaling_config[0].desired_size]
}

timeouts {}

depends_on = [
aws_iam_role_policy_attachment.worker-AmazonEKSWorkerNodePolicy,
aws_iam_role_policy_attachment.worker-AmazonEKS_CNI_Policy,
aws_iam_role_policy_attachment.worker-AmazonEC2ContainerRegistryReadOnly,
]
}

###############
## Storage
###############
resource "aws_launch_template" "storage" {
name = local.storage_node.launch_template_name
tags = var.tags
image_id = local.ami_image_id
user_data = base64encode(local.userdata)
vpc_security_group_ids = [aws_security_group.sg.id]

block_device_mappings {
device_name = local.storage_node.block_device_name

ebs {
volume_type = local.storage_node.ephemeral_volume_type
volume_size = local.storage_node.ephemeral_volume_size
throughput = local.storage_node.ephemeral_volume_throughput
iops = local.storage_node.ephemeral_volume_iops

}
}

tag_specifications {
resource_type = "instance"
tags = {
Name = local.storage_node.launch_template_name
}
}

lifecycle {
create_before_destroy = true
}
}

resource "aws_eks_node_group" "storage" {
cluster_name = aws_eks_cluster.cluster.name
node_group_name = local.storage_node.node_group_name
node_role_arn = aws_iam_role.storage_role.arn
subnet_ids = var.network.single_az == true ? split(",", var.network.subnet_ids[0]) : var.network.subnet_ids
instance_types = [local.storage_node.instance_type]
tags = merge({"k8s.io/cluster-autoscaler/enabled" : "false"},var.tags)

scaling_config {
desired_size = local.storage_node.scaling_size
max_size = local.storage_node.scaling_size
min_size = local.storage_node.scaling_size
}

labels = {
"px/enabled" = "true",
"k8s.cogynt.io/node" = "storage"
}

launch_template {
name = aws_launch_template.storage.name
version = aws_launch_template.storage.latest_version
}

lifecycle {
ignore_changes = [scaling_config[0].desired_size]
}

timeouts {}

depends_on = [
aws_iam_role_policy_attachment.storage-AmazonEKSWorkerNodePolicy,
aws_iam_role_policy_attachment.storage-AmazonEKS_CNI_Policy,
aws_iam_role_policy_attachment.storage-AmazonEC2ContainerRegistryReadOnly,
]
}

resource "aws_eks_addon" "vpc-cni" {
depends_on = [aws_eks_node_group.storage]
cluster_name = data.aws_eks_cluster.cluster.name
addon_name = "vpc-cni"
}

resource "aws_eks_addon" "kube-proxy" {
depends_on = [aws_eks_node_group.storage]
cluster_name = data.aws_eks_cluster.cluster.name
addon_name = "kube-proxy"
}

resource "aws_eks_addon" "coredns" {
depends_on = [aws_eks_node_group.storage]
cluster_name = data.aws_eks_cluster.cluster.name
addon_name = "coredns"
}

s3.tf

Description

The s3.tf file creates directories in a bucket that Cogility scripts externally establish.

Sample Code

resource "aws_s3_object" "s3_cluster_folder" {
bucket = var.s3_data.bucket
key = "${var.cluster.name}/"
content = ""
}

resource "aws_s3_object" "s3_cluster_folder_druid" {
bucket = var.s3_data.bucket
key = "${var.cluster.name}/druid/"
content = ""
}

resource "aws_s3_object" "s3_cluster_folder_flink" {
bucket = var.s3_data.bucket
key = "${var.cluster.name}/flink/"
content = ""
}

resource "aws_s3_object" "s3_cluster_folder_kafka" {
bucket = var.s3_data.bucket
key = "${var.cluster.name}/kafka/"
content = ""
}

resource "aws_s3_object" "s3_cluster_folder_workstation" {
bucket = var.s3_data.bucket
key = "${var.cluster.name}/workstation/"
content = ""
}

sg.tf

Description

The sg.tf file defines the security group rules.

Sample Code

resource "aws_security_group" "sg" {
name = var.network.security_group_name
description = var.network.security_group_description
vpc_id = var.network.vpc_id

ingress = [
{
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = var.network.vpc_cidr_blocks
description = "EKS cluster VPC cidr"
ipv6_cidr_blocks = null
prefix_list_ids = null
self = null
security_groups = null
},
{
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["172.20.0.0/16"]
description = "EKS cluster internal cidr"
ipv6_cidr_blocks = null
prefix_list_ids = null
self = null
security_groups = null
},
{
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = [var.network.vpn_cidr_block]
description = "VPN CIDR block"
ipv6_cidr_blocks = null
prefix_list_ids = null
self = null
security_groups = null
},
]

egress = [
{
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
description = null
ipv6_cidr_blocks = null
prefix_list_ids = null
self = null
security_groups = null
}
]
}

variables.tf

Description

The variables.tf file is a Terraform-specific item that helps navigate the other Terraform files in the repository. It contains the definitions of variables to use in other scripts.

Sample Code

data "aws_caller_identity" "current" {}

data "aws_route53_zone" "this" {
count = var.hosted_zone.name != "" ? 1 : 0
name = var.hosted_zone.name
private_zone = var.hosted_zone.type == "Private" ? true : false
}

data "aws_eks_cluster" "cluster" {
name = aws_eks_cluster.cluster.name
}

data "aws_ami" "eks" {
owners = ["amazon"]
most_recent = true
name_regex = "^amazon-eks-node-${var.cluster.version}-v\\d{8}$"

filter {
name = "name"
values = ["amazon-eks-node-${var.cluster.version}-*"]
}
}

variable "ami_image_id" {
type = string
description = "ID for the AMI"
default = ""
}

variable "aws_partition" {
type = string
description = "The AWS partition in which the resource is located."
default = "aws"
}

variable "user_data" {
type = string
description = "User Data to include in the nodes"
default = ""
}

variable "cluster" {
type = object({
name = string
version = optional(string)
endpoint_public_access = optional(bool)
})
description = "EKS cluster details"
}

variable "hosted_zone" {
type = object({
name = string
type = string
})
validation {
condition = var.hosted_zone.type == "Private" || var.hosted_zone.type == "Public"
error_message = "DNS Hosted Zone type can only be either Private or Public."
}
}

variable "network" {
type = object({
vpc_id = string
vpc_cidr_blocks = list(string)
single_az = optional(bool)
subnet_ids = list(string)
security_group_name = optional(string)
security_group_description = optional(string)
vpn_cidr_block = optional(string)
egress_cidr_block = optional(string)
})
description = "EKS cluster network details."
}

variable "master_node" {
type = object({
role_name = optional(string)
role_description = optional(string)
inline_policy_name = optional(string)
instance_profile_name = optional(string)
})
description = "Master EKS Node details for roles & policies."
}

variable "worker_node" {
type = object({
instance_type = optional(string)
launch_template_name = optional(string)
node_group_name = optional(string)
scaling_min_size = optional(number)
scaling_max_size = optional(number)
block_device_name = optional(string)
ephemeral_volume_type = optional(string)
ephemeral_volume_size = optional(number)
ephemeral_volume_iops = optional(number)
ephemeral_volume_throughput = optional(number)
role_name = optional(string)
role_description = optional(string)
inline_policy_name = optional(string)
instance_profile_name = optional(string)
additional_policy_arn_attachments = optional(set(string))
})
description = "Worker EKS Node details for launch template, role, policy, & EKS node groups."
}

variable "storage_node" {
type = object({
instance_type = optional(string)
launch_template_name = optional(string)
node_group_name = optional(string)
scaling_size = optional(number)
block_device_name = optional(string)
ephemeral_volume_type = optional(string)
ephemeral_volume_size = optional(number)
ephemeral_volume_iops = optional(number)
ephemeral_volume_throughput = optional(number)
role_name = optional(string)
role_description = optional(string)
inline_policy_name = optional(string)
portworx_inline_policy_name = optional(string)
instance_profile_name = optional(string)
})
description = "Storage EKS Node details for launch template, role, policy, & EKS node groups."
}

variable "externaldns" {
type = object({
role_name = string
policy_name = string
policy_description = string
})
description = "Name and descriptions of the role & policy used for ExternalDNS."
}

variable "istio" {
type = object({
role_name = string
policy_name = string
policy_description = string
})
description = "Name and descriptions of the role & policy used for Istio."
}

variable "s3_data" {
type = object({
bucket = string
role_name = string
policy_name = string
policy_description = string
})
description = "Name and descriptions of the bucket, role, & policy used for S3 data."
}

variable "hcvault" {
type = object({
role_name = string
policy_name = string
policy_description = string
kms_key_name = string
kms_key_description = string
kms_alias_name = string
})
description = "Name and descriptions of the kms, role, & policy used for Hashicorp Vault."
}

variable "tags" {
type = map(string)
description = "Tags to use globally on resources."
}

versions.tf

Description

The versions.tf file is a Terraform-specific item that helps navigate the other Terraform files in the repository. It contains some of the base-level configuration needed for the rest of the scripts to work. The backend and list of required providers are contained in this file.

Sample Code

terraform {
required_version = ">= 1.0"
experiments = [module_variable_optional_attrs]

required_providers {
aws = {
source = "hashicorp/aws"
version = "4.19.0"
}
tls = {
source = "hashicorp/tls"
version = "3.4.0"
}
}
}

ia Directory Contents

The ia directory contains the following files.

ia.env.yaml

The ia.env.yaml file is not a Terraform file. It defines the configuration for the Cogynt Delivery Tool.

For more information, see Configuring the Cogynt Delivery Tool.

main.tf

The main.tf file creates modules using abstractions from other files. Common variables are abstracted in this file to make editing configurations easier.

outputs.tf

The outputs.tf file contains the variables that should display their values at the end of a Terraform apply in the terminal.

variables.tf

The variables.tf file is a Terraform-specific item that helps navigate the other Terraform files in the repository. It contains the definitions of variables to use in other scripts.

vars.auto.tfvars

The vars.auto.tfvars file contains the values of the variables to use in other scripts.

Customers may want to review this file if they want to use values other than the Cogility defaults.

versions.tf

The versions.tf file is a Terraform-specific item that helps navigate the other Terraform files in the repository. It contains some of the base-level configuration needed for the rest of the scripts to work. The backend and list of required providers are contained in this file.

Customers may want to review this file, as it determines where Terraform stores its state.