diff --git a/eks.tf b/eks.tf index 1f1755c..a341a8c 100644 --- a/eks.tf +++ b/eks.tf @@ -2,6 +2,7 @@ module "eks" { source = "terraform-aws-modules/eks/aws" version = "20.11.0" + access_entries = var.eks_access_entries authentication_mode = "API_AND_CONFIG_MAP" cloudwatch_log_group_class = "STANDARD" cloudwatch_log_group_kms_key_id = module.cloudwatch_kms.key_arn @@ -13,7 +14,7 @@ module "eks" { cluster_security_group_name = "eks-${local.cluster_name}-cluster-sg" cluster_service_ipv4_cidr = "172.20.0.0/16" cluster_version = local.cluster_version - control_plane_subnet_ids = module.vpc.private_subnets + control_plane_subnet_ids = local.all_private_subnet_ids create_cloudwatch_log_group = true create_cluster_primary_security_group_tags = true create_cluster_security_group = true @@ -37,24 +38,9 @@ module "eks" { node_security_group_enable_recommended_rules = true node_security_group_name = "eks-${local.cluster_name}-node-sg" node_security_group_use_name_prefix = false - subnet_ids = module.vpc.private_subnets + subnet_ids = local.all_private_subnet_ids tags = merge(var.eks_cluster_tags, { Name = local.cluster_name }) - vpc_id = module.vpc.vpc_id - - access_entries = merge(var.eks_access_entries, { - main = { - principal_arn = "arn:${data.aws_caller_identity.current.provider}:iam::${data.aws_caller_identity.current.account_id}:role/ct-ado-batcave-application-admin" - type = "STANDARD" - policy_associations = { - admin = { - policy_arn = "arn:${data.aws_caller_identity.current.provider}:eks::aws:cluster-access-policy/AmazonEKSClusterAdminPolicy" - access_scope = { - type = "cluster" - } - } - } - } - }) + vpc_id = data.aws_vpc.vpc.id cluster_addons = { coredns = { @@ -102,7 +88,7 @@ module "main_nodes" { create_iam_role = false iam_role_additional_policies = { ssm = "arn:${data.aws_caller_identity.current.provider}:iam::aws:policy/AmazonSSMManagedInstanceCore" } iam_role_arn = module.eks.cluster_iam_role_arn - subnet_ids = module.vpc.private_subnets + subnet_ids = local.all_private_subnet_ids vpc_security_group_ids = [module.eks.node_security_group_id] desired_size = 3 @@ -156,9 +142,6 @@ module "eks_base" { enable_aws_load_balancer_controller = false enable_secrets_store_csi_driver_provider_aws = true - enable_aws_node_termination_handler = true - - aws_node_termination_handler_asg_arns = local.asg_arns secrets_store_csi_driver_provider_aws = { atomic = true @@ -177,21 +160,6 @@ module "eks_base" { ] } - -module "karpenter" { - source = "terraform-aws-modules/eks/aws//modules/karpenter" - - cluster_name = module.eks.cluster_name - create_access_entry = false - create_node_iam_role = false - enable_pod_identity = true - enable_spot_termination = true - node_iam_role_arn = module.eks.cluster_iam_role_arn - - - tags = var.karpenter_tags -} - # This installs the gp3 storage class and makes it the default resource "kubernetes_storage_class_v1" "gp3" { storage_provisioner = "kubernetes.io/aws-ebs" @@ -275,3 +243,31 @@ module "aws_lb_controller_pod_identity" { tags = var.lb_controller_tags } + +module "fluentbit_pod_identity" { + count = var.enable_eks_pod_identities ? 1 : 0 + source = "terraform-aws-modules/eks-pod-identity/aws" + depends_on = [helm_release.fluent-bit] + + name = "fluentbit" + use_name_prefix = false + description = "AWS EKS fluentbit role" + + + attach_custom_policy = true + source_policy_documents = [data.aws_iam_policy_document.fluent-bit.json] + + associations = { + default = { + cluster_name = local.cluster_name + namespace = "kube-system" + service_account = "fluentbit" + } + } + + tags = merge( + var.pod_identity_tags, + var.fb_tags + ) + +} diff --git a/fluentbit.tf b/fluentbit.tf new file mode 100644 index 0000000..5e53e5b --- /dev/null +++ b/fluentbit.tf @@ -0,0 +1,40 @@ +#Cloudwatch Log Group +resource "aws_cloudwatch_log_group" "fluent-bit" { + name = var.fb_log_group_name + retention_in_days = var.fb_log_retention + kms_key_id = var.fb_log_encryption ? var.fb_kms_key_id : "" + tags = var.fb_tags +} + +resource "aws_cloudwatch_log_group" "fluent-bit-system" { + count = var.fb_log_systemd ? 1 : 0 + name = var.fb_system_log_group_name + retention_in_days = var.fb_system_log_retention + kms_key_id = var.fb_log_encryption ? var.fb_kms_key_id : "" + tags = var.fb_tags +} + +#Fluentbit HELM +resource "helm_release" "fluent-bit" { + depends_on = [module.eks, module.main_nodes, module.eks_base] + name = "${local.cluster_name}-fluenbit" + repository = "https://fluent.github.io/helm-charts" + chart = "fluent-bit" + version = var.fb_chart_verison + namespace = "kube-system" + + values = [ + local.values + ] + + set { + name = "clusterName" + value = local.cluster_name + } + + set { + name = "serviceAccount.name" + value = "fluent-bit" + } + +} diff --git a/helm/fluentbit/values.yaml.tpl b/helm/fluentbit/values.yaml.tpl new file mode 100644 index 0000000..87dfab8 --- /dev/null +++ b/helm/fluentbit/values.yaml.tpl @@ -0,0 +1,81 @@ +config: + ## https://docs.fluentbit.io/manual/pipeline/inputs + inputs: | + [INPUT] + Name tail + Tag kube.* + Path /var/log/containers/*.log + Read_from_head true + multiline.parser docker, cri + Docker_Mode On + Parser docker + Mem_Buf_Limit 50MB + + [INPUT] + Name systemd + Tag host.* + Systemd_Filter _SYSTEMD_UNIT=kubelet.service + Read_From_Tail On + + ${indent(4, inputs)} + + ## https://docs.fluentbit.io/manual/pipeline/filters + filters: | + [FILTER] + Name kubernetes + Match kube.* + Merge_Log On + Keep_Log Off + K8S-Logging.Parser On + K8S-Logging.Exclude On + + [FILTER] + Name grep + Match kube.* + Exclude $log ${log_filters} + + [FILTER] + Name grep + Match kube.* + Exclude $log ${additional_log_filters} + +%{ for value in kube_namespaces } + [FILTER] + Name rewrite_tag + Match kube.* + Rule $kubernetes['namespace_name'] ^${value}$ system.$TAG false +%{ endfor ~} + + [FILTER] + Name grep + Match * + Exclude $kubernetes['namespace_name'] ${drop_namespaces} + + ${indent(4, filters)} + outputs: | + [OUTPUT] + Name cloudwatch_logs + Match kube.* + region ${region} + log_group_name ${log_group_name} + log_stream_prefix from-fluent-bit- + log_retention_days ${log_retention_days} + + [OUTPUT] + Name cloudwatch_logs + Match host.* + region ${region} + log_group_name ${system_log_group_name} + log_stream_prefix eks- + log_retention_days ${log_retention_days} + + [OUTPUT] + Name cloudwatch_logs + Match system.* + region ${region} + log_group_name ${system_log_group_name} + log_stream_prefix from-fluent-bit- + auto_create_group ${auto_create_group} + log_retention_days ${log_retention_days} + + ${indent(4, outputs)} \ No newline at end of file diff --git a/helm/karpenter-nodes/Chart.yaml b/helm/karpenter-nodes/Chart.yaml new file mode 100644 index 0000000..36dc753 --- /dev/null +++ b/helm/karpenter-nodes/Chart.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +description: A Helm chart for Karpenter Nodes +name: karpenter-nodes +version: 1.0.0 \ No newline at end of file diff --git a/helm/karpenter-nodes/templates/ec2NodeClass.yaml b/helm/karpenter-nodes/templates/ec2NodeClass.yaml new file mode 100644 index 0000000..ee7814b --- /dev/null +++ b/helm/karpenter-nodes/templates/ec2NodeClass.yaml @@ -0,0 +1,35 @@ +apiVersion: karpenter.k8s.aws/v1beta1 +kind: EC2NodeClass +metadata: + name: {{ .Values.nodeClass.metadata.name | default "default" | quote }} + annotations: +{{- range $key, $value := .Values.nodeClass.metadata.annotations }} + {{ $key }}: "{{ $value }}" +{{- end }} +spec: + amiFamily: {{ .Values.nodeClass.spec.amiFamily | default "AL2" | quote }} + blockDeviceMappings: +{{- range .Values.nodeClass.spec.blockDeviceMappings }} + - deviceName: {{ .deviceName | quote }} + ebs: + volumeType: {{ .ebs.volumeType | quote }} + volumeSize: {{ .ebs.volumeSize | quote }} + deleteOnTermination: {{ .ebs.deleteOnTermination | quote }} +{{- end }} + role: "{{ .Values.nodeClass.spec.role }}" + associatePublicIPAddress: {{ .Values.nodeClass.spec.associatePublicIPAddress | default false }} + subnetSelectorTerms: + - tags: + Name: "{{ .Values.nodeClass.spec.subnetTag }}" + securityGroupSelectorTerms: + - tags: + karpenter.sh/discovery: "{{ .Values.nodeClass.spec.clustername }}" + - id: "{{ .Values.nodeClass.spec.securityGroupID }}" + tags: +{{- range $key, $value := .Values.nodeClass.spec.tags }} + {{ $key }}: "{{ $value }}" +{{- end }} + userData: | + {{- if .Values.nodeClass.spec.userData }} + {{ .Values.nodeClass.spec.userData | indent 4 }} + {{- end }} diff --git a/helm/karpenter-nodes/templates/nodePool.yaml b/helm/karpenter-nodes/templates/nodePool.yaml new file mode 100644 index 0000000..1a9c9a7 --- /dev/null +++ b/helm/karpenter-nodes/templates/nodePool.yaml @@ -0,0 +1,21 @@ +apiVersion: karpenter.sh/v1beta1 +kind: NodePool +metadata: + name: {{ .Values.nodePool.metadata.name | default "default" | quote }} + annotations: +{{- range $key, $value := .Values.nodePool.metadata.annotations }} + {{ $key }}: "{{ $value }}" +{{- end }} +spec: + template: + spec: + requirements: +{{- range .Values.nodePool.spec.template.spec.requirements }} + - key: {{ .key | quote }} + operator: {{ .operator | quote }} + values: [{{ range $index, $value := .values }}{{ if $index }}, {{ end }}"{{ $value }}"{{ end }}] +{{- end }} + nodeClassRef: + apiVersion: {{ .Values.nodePool.spec.template.spec.nodeClassRef.apiVersion | default "karpenter.k8s.aws/v1beta1" | quote }} + kind: {{ .Values.nodePool.spec.template.spec.nodeClassRef.kind | default "EC2NodeClass" | quote }} + name: {{ .Values.nodePool.spec.template.spec.nodeClassRef.name | default "default" | quote }} \ No newline at end of file diff --git a/helm/karpenter-nodes/values.yaml.tpl b/helm/karpenter-nodes/values.yaml.tpl new file mode 100644 index 0000000..5f70c3c --- /dev/null +++ b/helm/karpenter-nodes/values.yaml.tpl @@ -0,0 +1,56 @@ +nodeClass: + metadata: + name: "default" + annotations: + description: "EC2NodeClass for running Amazon Linux 2 nodes with custom user data" + + spec: + amiFamily: ${amiFamily} + blockDeviceMappings: + - deviceName: "/dev/xvda" + ebs: + volumeType: "gp3" + volumeSize: 5 + deleteOnTermination: true + - deviceName: "/dev/xvdb" + ebs: + volumeType: "gp3" + volumeSize: 100 + deleteOnTermination: true + role: ${iamRole} + subnetTag: ${subnetTag} + securityGroupID: ${securityGroupID} + tags: + ${tags} + +nodePool: + metadata: + name: "default" + annotations: + kubernetes.io/description: "General purpose NodePool for generic workloads" + spec: + template: + spec: + requirements: + - key: "kubernetes.io/arch" + operator: "In" + values: ["amd64"] + - key: "kubernetes.io/os" + operator: "In" + values: ["linux"] + - key: "karpenter.sh/capacity-type" + operator: "In" + values: ["on-demand"] + - key: "karpenter.k8s.aws/instance-category" + operator: "In" + values: ["c", "m", "r"] + - key: "karpenter.k8s.aws/instance-generation" + operator: "Gt" + values: ["5"] + - key: "usage" + operator: "In" + values: ["application", "system"] + nodeClassRef: + apiVersion: "karpenter.k8s.aws/v1beta1" + kind: "EC2NodeClass" + name: "default" \ No newline at end of file diff --git a/helm/karpenter/values.yaml.tpl b/helm/karpenter/values.yaml.tpl new file mode 100644 index 0000000..344202d --- /dev/null +++ b/helm/karpenter/values.yaml.tpl @@ -0,0 +1,27 @@ +controller: + tolerations: + - key: "CriticalAddonsOnly" + operator: "Exists" + effect: "NoSchedule" + +webhook: + tolerations: + - key: "CriticalAddonsOnly" + operator: "Exists" + effect: "NoSchedule" + +affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: usage + operator: In + values: + - karpenter + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - topologyKey: "kubernetes.io/hostname" +settings: + clusterName: ${cluster_name} + interruptionQueue: "Karpenter-"${cluster_name} \ No newline at end of file diff --git a/iam_policies.tf b/iam_policies.tf index fdafb22..7a9392e 100644 --- a/iam_policies.tf +++ b/iam_policies.tf @@ -50,3 +50,32 @@ data "aws_iam_policy_document" "vpc" { ] } } + +data "aws_iam_policy_document" "fluent-bit" { + statement { + sid = "Fluentbit Cloudwatch" + effect = "Allow" + actions = [ + "cloudwatch:PutMetricData", + "ec2:DescribeVolumes", + "ec2:DescribeTags", + "logs:PutLogEvents", + "logs:DescribeLogStreams", + "logs:DescribeLogGroups", + "logs:CreateLogStream", + "logs:CreateLogGroup", + "logs:putRetentionPolicy" + ] + resources = ["*"] + } + statement { + sid = "Fluentbit SSM" + effect = "Allow" + actions = ["ssm:GetParameter"] + resources = [ + "arn:${data.aws_caller_identity.current.provider}:ssm:*:*:parameter/AmazonCloudWatch-*" + ] + } +} + + diff --git a/karpenter.tf b/karpenter.tf new file mode 100644 index 0000000..0eef2d7 --- /dev/null +++ b/karpenter.tf @@ -0,0 +1,46 @@ +#Karpenter Terraform +module "karpenter" { + source = "terraform-aws-modules/eks/aws//modules/karpenter" + depends_on = [module.eks, module.main_nodes, module.eks_base] + + cluster_name = module.eks.cluster_name + create_access_entry = false + create_node_iam_role = false + enable_pod_identity = true + enable_spot_termination = true + node_iam_role_arn = module.eks.cluster_iam_role_arn + + + tags = var.karpenter_tags +} + +#Karpenter HELM +resource "helm_release" "karpenter-crd" { + depends_on = [module.eks, module.main_nodes, module.eks_base, module.karpenter] + name = "${local.cluster_name}-karpenter" + repository = "oci://public.ecr.aws/karpenter" + chart = "karpenter" + version = var.kp_chart_verison + create_namespace = true + namespace = "karpenter" + + values = [ + local.kp_values + ] + +} + +#Karpenter Nodes HELM +resource "helm_release" "karpenter-nodes" { + depends_on = [helm_release.karpenter-crd] + name = "${local.cluster_name}-karpenter" + repository = "./helm/karpenter-nodes" + chart = "karpenter-nodes" + version = "1.0.0" + namespace = "karpenter" + + values = [ + local.kpn_values + ] + +} diff --git a/settings.tf b/settings.tf index 8173236..74fba2c 100644 --- a/settings.tf +++ b/settings.tf @@ -13,69 +13,52 @@ locals { cluster_name = var.cluster_custom_name == "" ? "main-test" : var.cluster_custom_name cluster_version = var.eks_version - ################################## VPC Settings ################################## - vpc_cidr = "10.10.0.0/16" - private_subnets = ["10.10.15.0/24", "10.10.25.0/24", "10.10.35.0/24"] - public_subnets = ["10.10.10.0/24"] - - endpoints = { - s3 = { - service = "s3" - tags = { Name = "S3" } - } - ssm = { - service = "ssm" - tags = { Name = "SSM" } - } - ssm-messages = { - service = "ssmmessages" - tags = { Name = "SSM Messages" } - } - ec2-messages = { - service = "ec2messages" - tags = { Name = "EC2 Messages" } - } + ################################## Fluentbit Settings ################################## + config_settings = { + log_group_name = var.fb_log_group_name + system_log_group_name = var.fb_system_log_group_name == "" ? "${var.fb_log_group_name}-kube" : var.fb_system_log_group_name + region = data.aws_region.current.name + log_retention_days = var.fb_log_retention + drop_namespaces = "(${join("|", var.drop_namespaces)})" + log_filters = "(${join("|", var.log_filters)})" + additional_log_filters = "(${join("|", var.additional_log_filters)})" + kube_namespaces = var.kube_namespaces } - ################################## Route Settings ################################## - public_route_table_routes = [ - for subnet_cidr in module.vpc.public_subnets_cidr_blocks : { - cidr_block = subnet_cidr, - gateway_id = module.vpc.igw_id - } - ] - private_route_table_routes = [ - for subnet_cidr in module.vpc.private_subnets_cidr_blocks : { - cidr_block = subnet_cidr, - gateway_id = module.vpc.natgw_ids[0] - } - ] + values = templatefile("${path.module}/helm/fluenbit/values.yaml.tpl", local.config_settings) - ################################## NACL Settings ################################## - public_nacl_ingress_rules = [ - { rule_number = 100, from_port = 53, to_port = 53, protocol = "udp", cidr_block = local.vpc_cidr, rule_action = "allow" }, - { rule_number = 101, from_port = 80, to_port = 80, protocol = "tcp", cidr_block = "0.0.0.0/0", rule_action = "allow" }, - { rule_number = 102, from_port = 443, to_port = 443, protocol = "tcp", cidr_block = "0.0.0.0/0", rule_action = "allow" }, - { rule_number = 103, from_port = 1024, to_port = 65535, protocol = "tcp", cidr_block = "0.0.0.0/0", rule_action = "allow" }, - { rule_number = 104, from_port = 22, to_port = 22, protocol = "tcp", cidr_block = "0.0.0.0/0", rule_action = "deny" }, - { rule_number = 105, from_port = 3389, to_port = 3389, protocol = "tcp", cidr_block = "0.0.0.0/0", rule_action = "deny" } - ] - private_nacl_ingress_rules = [ - { rule_number = 100, from_port = 22, to_port = 22, protocol = "tcp", cidr_block = local.vpc_cidr, rule_action = "allow" }, - { rule_number = 101, from_port = 53, to_port = 53, protocol = "tcp", cidr_block = local.vpc_cidr, rule_action = "allow" }, - { rule_number = 102, from_port = 53, to_port = 53, protocol = "udp", cidr_block = local.vpc_cidr, rule_action = "allow" }, - { rule_number = 103, from_port = 80, to_port = 80, protocol = "tcp", cidr_block = local.vpc_cidr, rule_action = "allow" }, - { rule_number = 104, from_port = 443, to_port = 443, protocol = "tcp", cidr_block = local.vpc_cidr, rule_action = "allow" }, - { rule_number = 105, from_port = 1024, to_port = 65535, protocol = "tcp", cidr_block = "0.0.0.0/0", rule_action = "allow" }, - { rule_number = 106, from_port = 1024, to_port = 65535, protocol = "udp", cidr_block = "0.0.0.0/0", rule_action = "allow" } - ] + ################################## Karpenter Settings ################################## + kp_config_settings = { + cluster_name = local.cluster_name + } + + kpn_config_settings = { + amiFamily = var.custom_ami_id != "" ? var.custom_ami_id : "BOTTLEROCKET_x86_64" + iamRole = module.eks.cluster_iam_role_arn + subnetTag = "${var.project}-*-${var.env}-private-*" + tags = var.karpenter_tags + securityGroupID = module.eks.node_security_group_id + } + + kp_values = templatefile("${path.module}/helm/karpenter/values.yaml.tpl", local.kp_config_settings) + kpn_values = templatefile("${path.module}/helm/karpenter/values.yaml.tpl", local.kpn_config_settings) + + ################################## VPC Settings ################################## + all_non_public_subnets = merge({ + "private" = data.aws_subnets.private + "container" = data.aws_subnets.container + }, + ) + + all_private_subnet_ids = flatten([for subnet in data.aws_subnets.private.ids : subnet]) + all_non_public_subnet_ids = flatten([for subnet_group in local.all_non_public_subnets : [for subnet in subnet_group : subnet.id]]) ################################## Security Group Settings ################################## eks_local = [ { description = "Allow all traffic from orchestrator nodes", from_port = 0, to_port = 0, protocol = "-1", self = true }, - { description = "Allow instances required to reach to the API server", from_port = 443, to_port = 443, protocol = "tcp", cidr_blocks = [local.vpc_cidr] }, - { description = "Allow necessary Kubelet and node communications", from_port = 10250, to_port = 10250, protocol = "tcp", cidr_blocks = [local.vpc_cidr] }, - { description = "Allow LB communication", from_port = 3000, to_port = 31237, protocol = "tcp", cidr_blocks = [local.vpc_cidr] } + { description = "Allow instances required to reach to the API server", from_port = 443, to_port = 443, protocol = "tcp", cidr_blocks = [data.aws_vpc.vpc.cidr_block] }, + { description = "Allow necessary Kubelet and node communications", from_port = 10250, to_port = 10250, protocol = "tcp", cidr_blocks = [data.aws_vpc.vpc.cidr_block] }, + { description = "Allow LB communication", from_port = 3000, to_port = 31237, protocol = "tcp", cidr_blocks = [data.aws_vpc.vpc.cidr_block] } ] ################################## Misc Config ################################## @@ -84,8 +67,6 @@ locals { var.use_bottlerocket ? "BOTTLEROCKET_x86_64" : "" ) ) - asg_names = module.main_nodes.node_group_autoscaling_group_names - asg_arns = [for name in local.asg_names : "arn:${data.aws_caller_identity.current.provider}:autoscaling:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:autoScalingGroupName/${name}"] } resource "random_string" "s3" { @@ -118,5 +99,6 @@ data "aws_ami" "gold_image" { name = "name" values = ["^amzn2-eks-${module.eks.cluster_version}-gi-${var.gold_image_date}"] } - owners = ["743302140042"] -} \ No newline at end of file + + owners = ["743302140042"] +} diff --git a/variables.tf b/variables.tf index 5644564..93d60bd 100644 --- a/variables.tf +++ b/variables.tf @@ -5,6 +5,40 @@ variable "custom_ami_id" { default = "" } +variable "env" { + default = "dev" +} + +variable "project" { + default = "batcave" +} + +################################# VPC Variables ################################# + +variable "subnet_lookup_overrides" { + description = "Some Subnets don't follow standard naming conventions. Use this map to override the query used for looking up Subnets. Ex: { private = \"foo-west-nonpublic-*\" }" + default = {} + type = map(string) +} + +variable "create_s3_vpc_endpoint" { + type = bool + description = "toggle on/off the creation of s3 vpc endpoint" + default = true +} + +variable "vpc_endpoint_lookup_overrides" { + description = "Some vpc endpoints don't follow standard naming conventions. Use this map to override the query used for looking up Subnets. Ex: { private = \"foo-west-nonpublic-*\" }" + default = "" + type = string +} + +variable "vpc_lookup_override" { + description = "Some VPCs don't follow standard naming conventions. Use this to override the query used to lookup VPC names. Accepts wildcard in form of '*'" + default = "" + type = string + +} variable "gold_image_date" { description = "Gold Image Date in YYYYMM format" type = string @@ -34,17 +68,22 @@ variable "cluster_custom_name" { variable "eks_access_entries" { description = "The access entries to apply to the EKS cluster" - type = map(object({ - principal_arn = string - type = string + type = map(object({ + principal_arn = string + type = string policy_associations = map(object({ - policy_arn = string + policy_arn = string access_scope = map(object({ type = string })) })) })) default = {} + + validation { + condition = !contains(keys(var.eks_access_entries), "cluster_creator") + error_message = "The access entry name 'cluster_creator' is not allowed" + } } variable "eks_cluster_tags" { @@ -114,9 +153,108 @@ variable "pod_identity_tags" { default = {} } +################################# Fluent-bit ################################# +variable "fb_chart_verison" { + description = "Fluent-bit helm chart version" + type = string + default = "0.30.3" +} + +variable "fb_log_group_name" { + description = "Fluent-bit log group name" + type = string + default = "Fluent-bit-cloudwatch" +} + +variable "fb_system_log_group_name" { + description = "Fluent-bit systemd log group name" + type = string + default = "Fluent-bit-cloudwatch" +} + +variable "fb_log_encryption" { + description = "Enable Fluent-bit log encryption" + type = bool + default = false +} + +variable "fb_log_systemd" { + description = "Enable Fluent-bit cloudwatch logging for systemd" + type = bool + default = true +} + +variable "fb_kms_key_id" { + description = "Fluent-bit log encryption KMS key ID" + type = string + default = "" +} + +variable "fb_tags" { + description = "The tags to apply to the fluent-bit deployment" + type = map(string) + default = {} +} + +variable "fb_log_retention" { + description = "Days to retain Fluent-bit logs" + type = number + default = 7 +} + +variable "fb_system_log_retention" { + description = "Days to retain Fluent-bit systemd logs" + type = number + default = 7 +} + +variable "drop_namespaces" { + type = list(string) + default = [ + "kube-system", + "cert-manager" + ] + description = "Fluent-bit doesn't send logs for these namespaces" +} + +variable "kube_namespaces" { + type = list(string) + default = [ + "kube.*", + "cert-manager.*" + ] + description = "Kubernates namespaces" +} + +variable "log_filters" { + type = list(string) + default = [ + "kube-probe", + "health", + "prometheus", + "liveness" + ] + description = "Fluent-bit doesn't send logs if message consists of these values" +} + +variable "additional_log_filters" { + type = list(string) + default = [ + "ELB-HealthChecker", + "Amazon-Route53-Health-Check-Service", + ] + description = "Fluent-bit doesn't send logs if message consists of these values" +} + ################################# Karpenter Variables ################################# +variable "kp_chart_verison" { + description = "Karpenter helm chart version" + type = string + default = "0.37.0" +} + variable "karpenter_tags" { - description = "The tags to apply to the Karpenter" + description = "The tags to apply to the Karpenter deployment" type = map(string) default = {} } diff --git a/vpc.tf b/vpc.tf index fa95758..a312833 100644 --- a/vpc.tf +++ b/vpc.tf @@ -1,76 +1,44 @@ -module "vpc" { - source = "terraform-aws-modules/vpc/aws" - version = "5.8.1" +# vpc id +data "aws_vpc" "vpc" { + tags = { + Name = coalesce(var.vpc_lookup_override, "${var.project}-*-${var.env}") + } +} + +# private subnets +data "aws_subnets" "private" { + filter { + name = "tag:Name" + values = [ + try(var.subnet_lookup_overrides.private, "${var.project}-*-${var.env}-private-*") + ] + } +} - azs = data.aws_availability_zones.available.names - cidr = local.vpc_cidr - create_flow_log_cloudwatch_iam_role = false - create_flow_log_cloudwatch_log_group = true - create_igw = true - create_vpc = true - default_network_acl_ingress = local.private_nacl_ingress_rules - default_network_acl_name = "${local.cluster_name}-private" - default_network_acl_tags = { Name = "${local.cluster_name}-private" } - default_route_table_name = "${local.cluster_name}-private" - default_route_table_routes = local.private_route_table_routes - default_route_table_tags = { Name = "${local.cluster_name}-private" } - default_security_group_ingress = [] - default_security_group_name = "${local.cluster_name}-private" - default_security_group_tags = { Name = "${local.cluster_name}-private" } - default_vpc_name = local.cluster_name - default_vpc_tags = { Name = local.cluster_name } - enable_dns_hostnames = true - enable_dns_support = true - enable_flow_log = true - enable_nat_gateway = true - flow_log_cloudwatch_iam_role_arn = aws_iam_role.vpc.arn - flow_log_cloudwatch_log_group_class = "STANDARD" - flow_log_cloudwatch_log_group_kms_key_id = module.cloudwatch_kms.key_arn - flow_log_cloudwatch_log_group_retention_in_days = 365 - flow_log_cloudwatch_log_group_skip_destroy = false - flow_log_destination_type = "cloud-watch-logs" - flow_log_file_format = "plain-text" - flow_log_traffic_type = "ALL" - igw_tags = { Name = "${local.cluster_name}-igw" } - manage_default_network_acl = false - manage_default_route_table = false - manage_default_security_group = false - manage_default_vpc = false - name = local.cluster_name - nat_eip_tags = { Name = "${local.cluster_name}-nat-eip" } - nat_gateway_tags = { Name = "${local.cluster_name}-ngw" } - private_acl_tags = { Name = "${local.cluster_name}-private" } - private_dedicated_network_acl = true - private_inbound_acl_rules = local.private_nacl_ingress_rules - private_route_table_tags = { Name = "${local.cluster_name}-private" } - private_subnet_enable_resource_name_dns_a_record_on_launch = true - private_subnet_private_dns_hostname_type_on_launch = "ip-name" - private_subnet_tags = { Name = "${local.cluster_name}-private" } - private_subnets = local.private_subnets - public_acl_tags = { Name = "${local.cluster_name}-public" } - public_dedicated_network_acl = true - public_inbound_acl_rules = local.public_nacl_ingress_rules - public_route_table_tags = { Name = "${local.cluster_name}-public" } - public_subnet_enable_resource_name_dns_a_record_on_launch = true - public_subnet_private_dns_hostname_type_on_launch = "ip-name" - public_subnet_tags = { Name = "${local.cluster_name}-public" } - public_subnets = local.public_subnets - single_nat_gateway = true - tags = { cluster = local.cluster_name } - vpc_flow_log_tags = { Name = "${local.cluster_name}-flow-log" } - vpc_tags = { Name = local.cluster_name } +# container subnets +data "aws_subnets" "container" { + filter { + name = "tag:Name" + values = [ + try(var.subnet_lookup_overrides.container, "${var.project}-*-${var.env}-unroutable-*") + ] + } } -module "endpoints" { - source = "terraform-aws-modules/vpc/aws//modules/vpc-endpoints" - version = "5.8.1" +#non-prod route table +data "aws_route_table" "all_non_public_route_tables" { + for_each = toset(local.all_non_public_subnet_ids) + subnet_id = each.key +} + +resource "aws_vpc_endpoint" "s3" { + count = var.create_s3_vpc_endpoint ? 1 : 0 + + vpc_id = data.aws_vpc.vpc.id + service_name = "com.amazonaws.${data.aws_region.current.name}.s3" + route_table_ids = [for route_table in data.aws_route_table.all_non_public_route_tables : route_table.id] - create = true - create_security_group = true - endpoints = local.endpoints - security_group_description = "Allow traffic to VPC endpoints" - security_group_name = "${local.cluster_name}-vpce" - subnet_ids = module.vpc.private_subnets - tags = { Name = "${local.cluster_name}-vpce" } - vpc_id = module.vpc.vpc_id + tags = { + Name = coalesce(var.vpc_endpoint_lookup_overrides, "${var.project}-${var.env}-s3-endpoint") + } }