diff --git a/kubernetes/aws/eks/README.md b/kubernetes/aws/eks/README.md index 9675e9067..40b526baf 100644 --- a/kubernetes/aws/eks/README.md +++ b/kubernetes/aws/eks/README.md @@ -6,6 +6,7 @@ | [terraform](#requirement\_terraform) | >= 1.0 | | [aws](#requirement\_aws) | >= 5.3.0 | | [helm](#requirement\_helm) | >= 2.10.1 | +| [kubernetes](#requirement\_kubernetes) | >= 2.13.0 | | [null](#requirement\_null) | >= 3.2.1 | | [random](#requirement\_random) | >= 3.5.1 | @@ -15,6 +16,7 @@ |------|---------| | [aws](#provider\_aws) | >= 5.3.0 | | [helm](#provider\_helm) | >= 2.10.1 | +| [kubernetes](#provider\_kubernetes) | >= 2.13.0 | | [null](#provider\_null) | >= 3.2.1 | | [random](#provider\_random) | >= 3.5.1 | @@ -34,11 +36,17 @@ | [aws_cloudwatch_event_rule.aws_node_termination_handler_asg](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_rule) | resource | | [aws_cloudwatch_event_rule.aws_node_termination_handler_spot](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_rule) | resource | | [aws_iam_policy.aws_node_termination_handler](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | +| [aws_iam_policy.efs_csi_driver](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | | [aws_iam_policy.worker_autoscaling](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | | [aws_iam_policy_attachment.workers_autoscaling](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy_attachment) | resource | +| [aws_iam_role.efs_csi_driver](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_iam_role_policy_attachment.efs_csi_driver](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | [helm_release.aws_node_termination_handler](https://registry.terraform.io/providers/hashicorp/helm/latest/docs/resources/release) | resource | | [helm_release.cluster_autoscaler](https://registry.terraform.io/providers/hashicorp/helm/latest/docs/resources/release) | resource | +| [helm_release.efs_csi](https://registry.terraform.io/providers/hashicorp/helm/latest/docs/resources/release) | resource | | [helm_release.eni_config](https://registry.terraform.io/providers/hashicorp/helm/latest/docs/resources/release) | resource | +| [kubernetes_service_account.efs_csi_driver_controller](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/service_account) | resource | +| [kubernetes_service_account.efs_csi_driver_node](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/service_account) | resource | | [null_resource.change_cni_label](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) | resource | | [null_resource.patch_coredns](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) | resource | | [null_resource.update_kubeconfig](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) | resource | @@ -47,6 +55,7 @@ | [aws_availability_zones.available](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones) | data source | | [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | | [aws_iam_policy_document.aws_node_termination_handler](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.efs_csi_driver](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.worker_autoscaling](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source | @@ -83,6 +92,19 @@ | [cluster\_log\_retention\_in\_days](#input\_cluster\_log\_retention\_in\_days) | Logs retention in days | `number` | n/a | yes | | [cluster\_version](#input\_cluster\_version) | Kubernetes version to use for the EKS cluster | `string` | n/a | yes | | [ebs\_kms\_key\_id](#input\_ebs\_kms\_key\_id) | KMS key id to encrypt/decrypt EBS | `string` | n/a | yes | +| [efs\_csi\_external\_provisioner\_image](#input\_efs\_csi\_external\_provisioner\_image) | EFS CSI external provisioner image name | `string` | n/a | yes | +| [efs\_csi\_external\_provisioner\_tag](#input\_efs\_csi\_external\_provisioner\_tag) | EFS CSI external provisioner image tag | `string` | n/a | yes | +| [efs\_csi\_image](#input\_efs\_csi\_image) | EFS CSI image name | `string` | n/a | yes | +| [efs\_csi\_image\_pull\_secrets](#input\_efs\_csi\_image\_pull\_secrets) | Image pull secret used to pull EFS CSI images | `string` | `null` | no | +| [efs\_csi\_liveness\_probe\_image](#input\_efs\_csi\_liveness\_probe\_image) | EFS CSI liveness probe image name | `string` | n/a | yes | +| [efs\_csi\_liveness\_probe\_tag](#input\_efs\_csi\_liveness\_probe\_tag) | EFS CSI liveness probe image tag | `string` | n/a | yes | +| [efs\_csi\_name](#input\_efs\_csi\_name) | EFS CSI name | `string` | `null` | no | +| [efs\_csi\_namespace](#input\_efs\_csi\_namespace) | EFS CSI namespace | `string` | `null` | no | +| [efs\_csi\_node\_driver\_registrar\_image](#input\_efs\_csi\_node\_driver\_registrar\_image) | EFS CSI node driver registrar image name | `string` | n/a | yes | +| [efs\_csi\_node\_driver\_registrar\_tag](#input\_efs\_csi\_node\_driver\_registrar\_tag) | EFS CSI node driver registrar image tag | `string` | n/a | yes | +| [efs\_csi\_repository](#input\_efs\_csi\_repository) | EFS CSI helm repository | `string` | n/a | yes | +| [efs\_csi\_tag](#input\_efs\_csi\_tag) | EFS CSI image tag | `string` | n/a | yes | +| [efs\_csi\_version](#input\_efs\_csi\_version) | EFS CSI helm version | `string` | n/a | yes | | [eks\_managed\_node\_groups](#input\_eks\_managed\_node\_groups) | List of EKS managed node groups | `any` | `null` | no | | [fargate\_profiles](#input\_fargate\_profiles) | List of fargate profiles | `any` | `null` | no | | [instance\_refresh\_image](#input\_instance\_refresh\_image) | Instance refresh image name | `string` | n/a | yes | diff --git a/kubernetes/aws/eks/efs-csi.tf b/kubernetes/aws/eks/efs-csi.tf new file mode 100644 index 000000000..4e60634fb --- /dev/null +++ b/kubernetes/aws/eks/efs-csi.tf @@ -0,0 +1,224 @@ +locals { + # EFS CSI + efs_csi_name = coalesce(var.efs_csi_name, "efs-csi-driver") + oidc_arn = module.eks.oidc_provider_arn + oidc_url = trimprefix(module.eks.cluster_oidc_issuer_url, "https://") + efs_csi_namespace = coalesce(var.efs_csi_namespace, "kube-system") + kubernetes_service_account_controller = "efs-csi-controller-sa" + kubernetes_service_account_node = "efs-csi-node-sa" + efs_csi_tolerations = [ + for index in range(0, length(local.node_selector_keys)) : { + key = local.node_selector_keys[index] + operator = "Equal" + value = local.node_selector_values[index] + effect = "NoSchedule" + } + ] + controller = { + controller = { + create = true + logLevel = 2 + extraCreateMetadata = true + tags = {} + deleteAccessPointRootDir = false + volMetricsOptIn = false + podAnnotations = {} + resources = {} + nodeSelector = var.node_selector + tolerations = local.efs_csi_tolerations + affinity = {} + serviceAccount = { + create = false + name = kubernetes_service_account.efs_csi_driver_controller.metadata[0].name + annotations = {} + } + healthPort = 9909 + regionalStsEndpoints = false + } + } +} + +# Allow EKS and the driver to interact with EFS +data "aws_iam_policy_document" "efs_csi_driver" { + statement { + sid = "Describe" + actions = [ + "elasticfilesystem:DescribeAccessPoints", + "elasticfilesystem:DescribeFileSystems", + "elasticfilesystem:DescribeMountTargets", + "ec2:DescribeAvailabilityZones" + ] + effect = "Allow" + resources = ["*"] + } + statement { + sid = "Create" + actions = [ + "elasticfilesystem:CreateAccessPoint" + ] + effect = "Allow" + resources = ["*"] + condition { + test = "StringLike" + values = [true] + variable = "aws:RequestTag/efs.csi.aws.com/cluster" + } + } + statement { + sid = "Delete" + actions = [ + "elasticfilesystem:DeleteAccessPoint" + ] + effect = "Allow" + resources = ["*"] + condition { + test = "StringEquals" + values = [true] + variable = "aws:ResourceTag/efs.csi.aws.com/cluster" + } + } + statement { + sid = "TagResource" + actions = [ + "elasticfilesystem:TagResource" + ] + effect = "Allow" + resources = ["*"] + condition { + test = "StringLike" + values = [true] + variable = "aws:ResourceTag/efs.csi.aws.com/cluster" + } + } + statement { + sid = "Mount" + actions = [ + "elasticfilesystem:ClientRootAccess", + "elasticfilesystem:ClientWrite", + "elasticfilesystem:ClientMount" + ] + effect = "Allow" + resources = ["*"] + } +} + +resource "aws_iam_policy" "efs_csi_driver" { + name_prefix = local.efs_csi_name + description = "Policy to allow EKS and the driver to interact with EFS" + policy = data.aws_iam_policy_document.efs_csi_driver.json + tags = local.tags +} + +resource "aws_iam_role" "efs_csi_driver" { + name = local.efs_csi_name + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Effect = "Allow" + Principal = { + Federated = local.oidc_arn + } + Action = "sts:AssumeRoleWithWebIdentity" + Condition = { + StringEquals = { + "${local.oidc_url}:aud" = "sts.amazonaws.com" + "${local.oidc_url}:sub" = [ + "system:serviceaccount:${local.efs_csi_namespace}:${local.kubernetes_service_account_controller}", + "system:serviceaccount:${local.efs_csi_namespace}:${local.kubernetes_service_account_node}" + ] + } + } + } + ] + }) + tags = local.tags +} + +resource "aws_iam_role_policy_attachment" "efs_csi_driver" { + policy_arn = aws_iam_policy.efs_csi_driver.arn + role = aws_iam_role.efs_csi_driver.name +} + +resource "kubernetes_service_account" "efs_csi_driver_controller" { + metadata { + name = local.kubernetes_service_account_controller + annotations = { + "eks.amazonaws.com/role-arn" = aws_iam_role.efs_csi_driver.arn + } + namespace = local.efs_csi_namespace + } +} + +resource "kubernetes_service_account" "efs_csi_driver_node" { + metadata { + name = local.kubernetes_service_account_node + annotations = { + "eks.amazonaws.com/role-arn" = aws_iam_role.efs_csi_driver.arn + } + namespace = local.efs_csi_namespace + } +} + +resource "helm_release" "efs_csi" { + name = "efs-csi" + namespace = kubernetes_service_account.efs_csi_driver_controller.metadata[0].namespace + chart = "aws-efs-csi-driver" + repository = var.efs_csi_repository + version = var.efs_csi_version + + set { + name = "image.repository" + value = var.efs_csi_image + } + set { + name = "image.tag" + value = var.efs_csi_tag + } + set { + name = "sidecars.livenessProbe.image.repository" + value = var.efs_csi_liveness_probe_image + } + set { + name = "sidecars.livenessProbe.image.tag" + value = var.efs_csi_liveness_probe_tag + } + set { + name = "sidecars.nodeDriverRegistrar.image.repository" + value = var.efs_csi_node_driver_registrar_image + } + set { + name = "sidecars.nodeDriverRegistrar.image.tag" + value = var.efs_csi_node_driver_registrar_tag + } + set { + name = "sidecars.csiProvisioner.image.repository" + value = var.efs_csi_external_provisioner_image + } + set { + name = "sidecars.csiProvisioner.image.tag" + value = var.efs_csi_external_provisioner_tag + } + dynamic "set" { + for_each = toset(compact([var.efs_csi_image_pull_secrets])) + content { + name = "imagePullSecrets" + value = each.key + } + } + set { + name = "node.serviceAccount.create" + value = false + } + set { + name = "node.serviceAccount.name" + value = kubernetes_service_account.efs_csi_driver_node.metadata[0].name + } + values = [ + yamlencode(local.controller) + ] + depends_on = [ + kubernetes_service_account.efs_csi_driver_controller, + kubernetes_service_account.efs_csi_driver_node + ] +} diff --git a/kubernetes/aws/eks/examples/complete/main.tf b/kubernetes/aws/eks/examples/complete/main.tf index 5af058343..8620c8e7d 100644 --- a/kubernetes/aws/eks/examples/complete/main.tf +++ b/kubernetes/aws/eks/examples/complete/main.tf @@ -68,6 +68,18 @@ module "eks" { vpc_id = data.aws_vpc.default.id vpc_pods_subnet_ids = data.aws_subnets.subnets.ids vpc_private_subnet_ids = data.aws_subnets.subnets.ids + + efs_csi_image = "amazon/aws-efs-csi-driver" + efs_csi_tag = "v1.5.1" + efs_csi_liveness_probe_image = "public.ecr.aws/eks-distro/kubernetes-csi/livenessprobe" + efs_csi_liveness_probe_tag = "v2.9.0-eks-1-22-19" + efs_csi_node_driver_registrar_image = "public.ecr.aws/eks-distro/kubernetes-csi/node-driver-registrar" + efs_csi_node_driver_registrar_tag = "v2.7.0-eks-1-22-19" + efs_csi_external_provisioner_image = "public.ecr.aws/eks-distro/kubernetes-csi/external-provisioner" + efs_csi_external_provisioner_tag = "v3.4.0-eks-1-22-19" + efs_csi_repository = "https://kubernetes-sigs.github.io/aws-efs-csi-driver/" + efs_csi_version = "2.3.0" + eks_managed_node_groups = { test = { name = "workers" diff --git a/kubernetes/aws/eks/examples/simple/main.tf b/kubernetes/aws/eks/examples/simple/main.tf index bd58fa11b..7681f1cb2 100644 --- a/kubernetes/aws/eks/examples/simple/main.tf +++ b/kubernetes/aws/eks/examples/simple/main.tf @@ -69,6 +69,17 @@ module "eks" { vpc_pods_subnet_ids = data.aws_subnets.subnets.ids vpc_private_subnet_ids = data.aws_subnets.subnets.ids + efs_csi_image = "amazon/aws-efs-csi-driver" + efs_csi_tag = "v1.5.1" + efs_csi_liveness_probe_image = "public.ecr.aws/eks-distro/kubernetes-csi/livenessprobe" + efs_csi_liveness_probe_tag = "v2.9.0-eks-1-22-19" + efs_csi_node_driver_registrar_image = "public.ecr.aws/eks-distro/kubernetes-csi/node-driver-registrar" + efs_csi_node_driver_registrar_tag = "v2.7.0-eks-1-22-19" + efs_csi_external_provisioner_image = "public.ecr.aws/eks-distro/kubernetes-csi/external-provisioner" + efs_csi_external_provisioner_tag = "v3.4.0-eks-1-22-19" + efs_csi_repository = "https://kubernetes-sigs.github.io/aws-efs-csi-driver/" + efs_csi_version = "2.3.0" + eks_managed_node_groups = { test = { name = "workers" diff --git a/kubernetes/aws/eks/variables.tf b/kubernetes/aws/eks/variables.tf index 7e5dc395d..efcffd11b 100644 --- a/kubernetes/aws/eks/variables.tf +++ b/kubernetes/aws/eks/variables.tf @@ -235,6 +235,64 @@ variable "eks_managed_node_groups" { default = null } +# EFS +variable "efs_csi_image" { + description = "EFS CSI image name" + type = string +} +variable "efs_csi_tag" { + description = "EFS CSI image tag" + type = string +} +variable "efs_csi_liveness_probe_image" { + description = "EFS CSI liveness probe image name" + type = string +} +variable "efs_csi_liveness_probe_tag" { + description = "EFS CSI liveness probe image tag" + type = string +} +variable "efs_csi_node_driver_registrar_image" { + description = "EFS CSI node driver registrar image name" + type = string +} +variable "efs_csi_node_driver_registrar_tag" { + description = "EFS CSI node driver registrar image tag" + type = string +} +variable "efs_csi_external_provisioner_image" { + description = "EFS CSI external provisioner image name" + type = string +} +variable "efs_csi_external_provisioner_tag" { + description = "EFS CSI external provisioner image tag" + type = string +} + +variable "efs_csi_name" { + description = "EFS CSI name" + type = string + default = null +} +variable "efs_csi_namespace" { + description = "EFS CSI namespace" + type = string + default = null +} +variable "efs_csi_image_pull_secrets" { + description = "Image pull secret used to pull EFS CSI images" + type = string + default = null +} +variable "efs_csi_repository" { + description = "EFS CSI helm repository" + type = string +} +variable "efs_csi_version" { + description = "EFS CSI helm version" + type = string +} + # Encryption keys variable "cluster_log_kms_key_id" { description = "KMS id to encrypt/decrypt the cluster's logs" diff --git a/kubernetes/aws/eks/versions.tf b/kubernetes/aws/eks/versions.tf index a4c552a21..1f1a61933 100644 --- a/kubernetes/aws/eks/versions.tf +++ b/kubernetes/aws/eks/versions.tf @@ -5,6 +5,10 @@ terraform { source = "hashicorp/aws" version = ">= 5.3.0" } + kubernetes = { + source = "hashicorp/kubernetes" + version = ">= 2.13.0" + } helm = { source = "hashicorp/helm" version = ">= 2.10.1" diff --git a/monitoring/onpremise/grafana/README.md b/monitoring/onpremise/grafana/README.md index 5751dfa2e..079fa935f 100644 --- a/monitoring/onpremise/grafana/README.md +++ b/monitoring/onpremise/grafana/README.md @@ -27,7 +27,9 @@ No modules. | [kubernetes_config_map.datasources_config](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/config_map) | resource | | [kubernetes_config_map.grafana_ini](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/config_map) | resource | | [kubernetes_deployment.grafana](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/deployment) | resource | +| [kubernetes_persistent_volume_claim.grafana](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/persistent_volume_claim) | resource | | [kubernetes_service.grafana](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/service) | resource | +| [kubernetes_storage_class.grafana](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/storage_class) | resource | | [local_file.dashboards_config_file](https://registry.terraform.io/providers/hashicorp/local/latest/docs/resources/file) | resource | | [local_file.datasources_config_file](https://registry.terraform.io/providers/hashicorp/local/latest/docs/resources/file) | resource | @@ -39,8 +41,10 @@ No modules. | [docker\_image](#input\_docker\_image) | Docker image for Grafana |
object({| n/a | yes | | [namespace](#input\_namespace) | Namespace of ArmoniK monitoring | `string` | n/a | yes | | [node\_selector](#input\_node\_selector) | Node selector for Grafana | `any` | `{}` | no | +| [persistent\_volume](#input\_persistent\_volume) | Persistent volume info |
image = string
tag = string
image_pull_secrets = string
})
object({| `null` | no | | [port](#input\_port) | Port for Grafana service | `string` | n/a | yes | | [prometheus\_url](#input\_prometheus\_url) | Prometheus URL | `string` | n/a | yes | +| [security\_context](#input\_security\_context) | security context for Grafana pods |
storage_provisioner = string
volume_binding_mode = string
parameters = map(string)
# Resources for PVC
resources = object({
limits = object({
storage = string
})
requests = object({
storage = string
})
})
})
object({|
run_as_user = number
fs_group = number
})
{| no | | [service\_type](#input\_service\_type) | Service type which can be: ClusterIP, NodePort or LoadBalancer | `string` | n/a | yes | ## Outputs diff --git a/monitoring/onpremise/grafana/main.tf b/monitoring/onpremise/grafana/main.tf index b7b13fb85..dfd950908 100644 --- a/monitoring/onpremise/grafana/main.tf +++ b/monitoring/onpremise/grafana/main.tf @@ -50,6 +50,12 @@ resource "kubernetes_deployment" "grafana" { name = var.docker_image.image_pull_secrets } } + security_context { + run_as_user = var.security_context.run_as_user + run_as_non_root = true + run_as_group = var.security_context.fs_group + fs_group = var.security_context.fs_group + } container { name = "grafana" image = "${var.docker_image.image}:${var.docker_image.tag}" @@ -80,7 +86,15 @@ resource "kubernetes_deployment" "grafana" { } volume_mount { name = "dashboards-json-configmap" - mount_path = "/var/lib/grafana/dashboards/" + mount_path = "/var/lib/grafana/dashboards/dashboard-armonik.json" + sub_path = "dashboard-armonik.json" + } + dynamic "volume_mount" { + for_each = length(kubernetes_persistent_volume_claim.grafana) > 0 ? [1] : [] + content { + name = "database" + mount_path = "/var/lib/grafana" + } } } volume { @@ -111,6 +125,15 @@ resource "kubernetes_deployment" "grafana" { optional = false } } + dynamic "volume" { + for_each = length(kubernetes_persistent_volume_claim.grafana) > 0 ? [1] : [] + content { + name = "database" + persistent_volume_claim { + claim_name = kubernetes_persistent_volume_claim.grafana[0].metadata[0].name + } + } + } } } } diff --git a/monitoring/onpremise/grafana/persistent-volume.tf b/monitoring/onpremise/grafana/persistent-volume.tf new file mode 100644 index 000000000..6d3ba607d --- /dev/null +++ b/monitoring/onpremise/grafana/persistent-volume.tf @@ -0,0 +1,36 @@ +resource "kubernetes_storage_class" "grafana" { + count = var.persistent_volume != null ? 1 : 0 + metadata { + name = "grafana" + labels = { + app = "grafana" + type = "storage-class" + service = "persistent-volume" + } + } + mount_options = ["tls"] + storage_provisioner = var.persistent_volume.storage_provisioner + volume_binding_mode = var.persistent_volume.volume_binding_mode + parameters = var.persistent_volume.parameters +} + +resource "kubernetes_persistent_volume_claim" "grafana" { + count = length(kubernetes_storage_class.grafana) > 0 ? 1 : 0 + metadata { + name = "grafana" + namespace = var.namespace + labels = { + app = "grafana" + type = "persistent-volume-claim" + service = "persistent-volume" + } + } + spec { + access_modes = ["ReadWriteMany"] + storage_class_name = kubernetes_storage_class.grafana[0].metadata[0].name + resources { + requests = var.persistent_volume.resources.requests + limits = var.persistent_volume.resources.limits + } + } +} diff --git a/monitoring/onpremise/grafana/variables.tf b/monitoring/onpremise/grafana/variables.tf index b7ec96f7b..12f793284 100644 --- a/monitoring/onpremise/grafana/variables.tf +++ b/monitoring/onpremise/grafana/variables.tf @@ -45,3 +45,35 @@ variable "authentication" { type = bool default = false } + +variable "security_context" { + description = "security context for Grafana pods" + type = object({ + run_as_user = number + fs_group = number + }) + default = { + run_as_user = 999 + fs_group = 999 + } +} + +# Persistent volume +variable "persistent_volume" { + description = "Persistent volume info" + type = object({ + storage_provisioner = string + volume_binding_mode = string + parameters = map(string) + # Resources for PVC + resources = object({ + limits = object({ + storage = string + }) + requests = object({ + storage = string + }) + }) + }) + default = null +} diff --git a/monitoring/onpremise/prometheus/README.md b/monitoring/onpremise/prometheus/README.md index 4a9723749..637715d98 100644 --- a/monitoring/onpremise/prometheus/README.md +++ b/monitoring/onpremise/prometheus/README.md @@ -29,7 +29,9 @@ No modules. | [kubernetes_cluster_role_binding.prometheus_ns_armonik](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/cluster_role_binding) | resource | | [kubernetes_config_map.prometheus_config](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/config_map) | resource | | [kubernetes_deployment.prometheus](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/deployment) | resource | +| [kubernetes_persistent_volume_claim.prometheus](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/persistent_volume_claim) | resource | | [kubernetes_service.prometheus](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/service) | resource | +| [kubernetes_storage_class.prometheus](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/storage_class) | resource | | [local_file.prometheus_config_file](https://registry.terraform.io/providers/hashicorp/local/latest/docs/resources/file) | resource | | [random_string.random_resources](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/string) | resource | @@ -41,6 +43,8 @@ No modules. | [metrics\_exporter\_url](#input\_metrics\_exporter\_url) | URL of metrics exporter | `string` | n/a | yes | | [namespace](#input\_namespace) | Namespace of ArmoniK monitoring | `string` | n/a | yes | | [node\_selector](#input\_node\_selector) | Node selector for Prometheus | `any` | `{}` | no | +| [persistent\_volume](#input\_persistent\_volume) | Persistent volume info |
"fs_group": 999,
"run_as_user": 999
}
object({| `null` | no | +| [security\_context](#input\_security\_context) | security context for Prometheus pods |
storage_provisioner = string
volume_binding_mode = string
parameters = map(string)
# Resources for PVC
resources = object({
limits = object({
storage = string
})
requests = object({
storage = string
})
})
})
object({|
run_as_user = number
fs_group = number
})
{| no | | [service\_type](#input\_service\_type) | Service type which can be: ClusterIP, NodePort or LoadBalancer | `string` | n/a | yes | ## Outputs diff --git a/monitoring/onpremise/prometheus/main.tf b/monitoring/onpremise/prometheus/main.tf index ebc1112ca..e35d76293 100644 --- a/monitoring/onpremise/prometheus/main.tf +++ b/monitoring/onpremise/prometheus/main.tf @@ -50,6 +50,12 @@ resource "kubernetes_deployment" "prometheus" { name = var.docker_image.image_pull_secrets } } + security_context { + run_as_user = var.security_context.run_as_user + run_as_non_root = true + run_as_group = var.security_context.fs_group + fs_group = var.security_context.fs_group + } container { name = "prometheus" image = "${var.docker_image.image}:${var.docker_image.tag}" @@ -68,6 +74,13 @@ resource "kubernetes_deployment" "prometheus" { mount_path = "/etc/prometheus/prometheus.yml" sub_path = "prometheus.yml" } + dynamic "volume_mount" { + for_each = length(kubernetes_persistent_volume_claim.prometheus) > 0 ? [1] : [] + content { + name = "database" + mount_path = "/prometheus" + } + } } volume { name = "prometheus-configmap" @@ -76,6 +89,15 @@ resource "kubernetes_deployment" "prometheus" { optional = false } } + dynamic "volume" { + for_each = length(kubernetes_persistent_volume_claim.prometheus) > 0 ? [1] : [] + content { + name = "database" + persistent_volume_claim { + claim_name = kubernetes_persistent_volume_claim.prometheus[0].metadata[0].name + } + } + } } } } diff --git a/monitoring/onpremise/prometheus/persistent-volume.tf b/monitoring/onpremise/prometheus/persistent-volume.tf new file mode 100644 index 000000000..0d88f0ef4 --- /dev/null +++ b/monitoring/onpremise/prometheus/persistent-volume.tf @@ -0,0 +1,36 @@ +resource "kubernetes_storage_class" "prometheus" { + count = var.persistent_volume != null ? 1 : 0 + metadata { + name = "prometheus" + labels = { + app = "prometheus" + type = "storage-class" + service = "persistent-volume" + } + } + mount_options = ["tls"] + storage_provisioner = var.persistent_volume.storage_provisioner + volume_binding_mode = var.persistent_volume.volume_binding_mode + parameters = var.persistent_volume.parameters +} + +resource "kubernetes_persistent_volume_claim" "prometheus" { + count = length(kubernetes_storage_class.prometheus) > 0 ? 1 : 0 + metadata { + name = "prometheus" + namespace = var.namespace + labels = { + app = "prometheus" + type = "persistent-volume-claim" + service = "persistent-volume" + } + } + spec { + access_modes = ["ReadWriteMany"] + storage_class_name = kubernetes_storage_class.prometheus[0].metadata[0].name + resources { + requests = var.persistent_volume.resources.requests + limits = var.persistent_volume.resources.limits + } + } +} diff --git a/monitoring/onpremise/prometheus/variables.tf b/monitoring/onpremise/prometheus/variables.tf index cc0618edb..0c7fbb99d 100644 --- a/monitoring/onpremise/prometheus/variables.tf +++ b/monitoring/onpremise/prometheus/variables.tf @@ -32,3 +32,35 @@ variable "metrics_exporter_url" { description = "URL of metrics exporter" type = string } + +variable "security_context" { + description = "security context for Prometheus pods" + type = object({ + run_as_user = number + fs_group = number + }) + default = { + run_as_user = 65534 + fs_group = 65534 + } +} + +# Persistent volume +variable "persistent_volume" { + description = "Persistent volume info" + type = object({ + storage_provisioner = string + volume_binding_mode = string + parameters = map(string) + # Resources for PVC + resources = object({ + limits = object({ + storage = string + }) + requests = object({ + storage = string + }) + }) + }) + default = null +} diff --git a/storage/aws/efs/README.md b/storage/aws/efs/README.md index f05156000..510a99a6b 100644 --- a/storage/aws/efs/README.md +++ b/storage/aws/efs/README.md @@ -39,7 +39,7 @@ No modules. | [provisioned\_throughput\_in\_mibps](#input\_provisioned\_throughput\_in\_mibps) | The throughput, measured in MiB/s, that you want to provision for the file system. Only applicable with throughput\_mode set to provisioned | `number` | `null` | no | | [tags](#input\_tags) | Tags for resource | `any` | `{}` | no | | [throughput\_mode](#input\_throughput\_mode) | Throughput mode for the file system. Defaults to bursting. Valid values: bursting, elastic, and provisioned. When using provisioned, also set provisioned\_throughput\_in\_mibps | `string` | `"bursting"` | no | -| [transition\_to\_ia](#input\_transition\_to\_ia) | Describes the period of time that a file is not accessed, after which it transitions to IA storage | `string` | `"AFTER_7_DAYS"` | no | +| [transition\_to\_ia](#input\_transition\_to\_ia) | Describes the period of time that a file is not accessed, after which it transitions to IA storage | `string` | `null` | no | | [vpc\_cidr\_block\_private](#input\_vpc\_cidr\_block\_private) | AWS VPC private cidr block | `set(string)` | n/a | yes | | [vpc\_cidr\_blocks](#input\_vpc\_cidr\_blocks) | AWS VPC cidr block | `set(string)` | n/a | yes | | [vpc\_id](#input\_vpc\_id) | AWS VPC id | `string` | n/a | yes | diff --git a/storage/aws/efs/main.tf b/storage/aws/efs/main.tf index fed9a5799..b60b14f74 100644 --- a/storage/aws/efs/main.tf +++ b/storage/aws/efs/main.tf @@ -19,9 +19,14 @@ resource "aws_efs_file_system" "efs" { performance_mode = var.performance_mode throughput_mode = var.throughput_mode provisioned_throughput_in_mibps = var.provisioned_throughput_in_mibps - lifecycle_policy { - transition_to_ia = var.transition_to_ia + + dynamic "lifecycle_policy" { + for_each = toset(compact([var.transition_to_ia])) + content { + transition_to_ia = each.key + } } + tags = local.tags } diff --git a/storage/aws/efs/outputs.tf b/storage/aws/efs/outputs.tf index 8cd856326..f843bff56 100644 --- a/storage/aws/efs/outputs.tf +++ b/storage/aws/efs/outputs.tf @@ -1,9 +1,11 @@ output "id" { description = "EFS id" value = aws_efs_file_system.efs.id + depends_on = [aws_efs_mount_target.efs, aws_efs_access_point.efs] } output "kms_key_id" { description = "KMS used to encrypt EFS" value = aws_efs_file_system.efs.kms_key_id + depends_on = [aws_efs_mount_target.efs, aws_efs_access_point.efs] } diff --git a/storage/aws/efs/variables.tf b/storage/aws/efs/variables.tf index a7098b020..6b632b2d1 100644 --- a/storage/aws/efs/variables.tf +++ b/storage/aws/efs/variables.tf @@ -68,15 +68,15 @@ variable "provisioned_throughput_in_mibps" { variable "transition_to_ia" { description = "Describes the period of time that a file is not accessed, after which it transitions to IA storage" type = string - default = "AFTER_7_DAYS" + default = null validation { - condition = contains([ + condition = var.transition_to_ia != null ? contains([ "AFTER_7_DAYS", "AFTER_14_DAYS", "AFTER_30_DAYS", "AFTER_60_DAYS", "AFTER_90_DAYS" - ], var.transition_to_ia) + ], var.transition_to_ia) : true error_message = "Possible values for the parameter transition_to_ia are \"AFTER_7_DAYS\" | \"AFTER_14_DAYS\" | \"AFTER_30_DAYS\", \"AFTER_60_DAYS\" | \"AFTER_90_DAYS\"." } } diff --git a/storage/onpremise/mongodb/README.md b/storage/onpremise/mongodb/README.md index eb890d6fd..00e047dbc 100644 --- a/storage/onpremise/mongodb/README.md +++ b/storage/onpremise/mongodb/README.md @@ -58,7 +58,8 @@ No modules. |------|-------------|------|---------|:--------:| | [mongodb](#input\_mongodb) | Parameters of MongoDB |
"fs_group": 65534,
"run_as_user": 65534
}
object({| n/a | yes | | [namespace](#input\_namespace) | Namespace of ArmoniK resources | `string` | n/a | yes | -| [persistent\_volume](#input\_persistent\_volume) | Persistent volume info |
image = string
tag = string
node_selector = any
image_pull_secrets = string
replicas_number = number
})
object({| n/a | yes | +| [persistent\_volume](#input\_persistent\_volume) | Persistent volume info |
storage_provisioner = string
parameters = map(string)
# Resources for PVC
resources = object({
limits = object({
storage = string
})
requests = object({
storage = string
})
})
})
object({| `null` | no | +| [security\_context](#input\_security\_context) | security context for MongoDB pods |
storage_provisioner = string
volume_binding_mode = string
parameters = map(string)
# Resources for PVC
resources = object({
limits = object({
storage = string
})
requests = object({
storage = string
})
})
})
object({|
run_as_user = number
fs_group = number
})
{| no | | [validity\_period\_hours](#input\_validity\_period\_hours) | Validity period of the certificate in hours | `string` | `"8760"` | no | ## Outputs diff --git a/storage/onpremise/mongodb/main.tf b/storage/onpremise/mongodb/main.tf index 7268098df..108fa465c 100644 --- a/storage/onpremise/mongodb/main.tf +++ b/storage/onpremise/mongodb/main.tf @@ -51,8 +51,10 @@ resource "kubernetes_deployment" "mongodb" { } } security_context { - run_as_user = 999 - fs_group = 999 + run_as_user = var.security_context.run_as_user + run_as_non_root = true + run_as_group = var.security_context.fs_group + fs_group = var.security_context.fs_group } container { name = "mongodb" @@ -91,7 +93,7 @@ resource "kubernetes_deployment" "mongodb" { mount_path = "/start/" } dynamic "volume_mount" { - for_each = (var.persistent_volume != null && var.persistent_volume != "" ? [1] : []) + for_each = length(kubernetes_persistent_volume_claim.mongodb) > 0 ? [1] : [] content { name = "database" mount_path = "/data/db" @@ -127,7 +129,7 @@ resource "kubernetes_deployment" "mongodb" { } } dynamic "volume" { - for_each = (var.persistent_volume != null && var.persistent_volume != "" ? [1] : []) + for_each = length(kubernetes_persistent_volume_claim.mongodb) > 0 ? [1] : [] content { name = "database" persistent_volume_claim { diff --git a/storage/onpremise/mongodb/persistent-volume.tf b/storage/onpremise/mongodb/persistent-volume.tf index caa0cbfdc..0a0dca6f4 100644 --- a/storage/onpremise/mongodb/persistent-volume.tf +++ b/storage/onpremise/mongodb/persistent-volume.tf @@ -1,5 +1,5 @@ resource "kubernetes_storage_class" "mongodb" { - count = (var.persistent_volume != null && var.persistent_volume != "" ? 1 : 0) + count = var.persistent_volume != null ? 1 : 0 metadata { name = "mongodb" labels = { @@ -10,11 +10,12 @@ resource "kubernetes_storage_class" "mongodb" { } mount_options = ["tls"] storage_provisioner = var.persistent_volume.storage_provisioner + volume_binding_mode = var.persistent_volume.volume_binding_mode parameters = var.persistent_volume.parameters } resource "kubernetes_persistent_volume_claim" "mongodb" { - count = length(kubernetes_storage_class.mongodb) + count = length(kubernetes_storage_class.mongodb) > 0 ? 1 : 0 metadata { name = "mongodb" namespace = var.namespace diff --git a/storage/onpremise/mongodb/variables.tf b/storage/onpremise/mongodb/variables.tf index 866bed432..efa21204d 100644 --- a/storage/onpremise/mongodb/variables.tf +++ b/storage/onpremise/mongodb/variables.tf @@ -16,11 +16,24 @@ variable "mongodb" { }) } +variable "security_context" { + description = "security context for MongoDB pods" + type = object({ + run_as_user = number + fs_group = number + }) + default = { + run_as_user = 999 + fs_group = 999 + } +} + # Persistent volume variable "persistent_volume" { description = "Persistent volume info" type = object({ storage_provisioner = string + volume_binding_mode = string parameters = map(string) # Resources for PVC resources = object({ @@ -32,6 +45,7 @@ variable "persistent_volume" { }) }) }) + default = null } variable "validity_period_hours" {
"fs_group": 999,
"run_as_user": 999
}