From caf2a1b961433120a4620675c06f179cec431fda Mon Sep 17 00:00:00 2001 From: Michael Thamm Date: Mon, 16 Jun 2025 11:00:36 -0400 Subject: [PATCH] chore: remove TF modules due to migration to observability-stack repo --- .gitignore | 41 -- README.md | 4 + terraform/modules/aws-infra/README.md | 131 ---- terraform/modules/aws-infra/justfile | 39 -- terraform/modules/aws-infra/main.tf | 621 ------------------ terraform/modules/aws-infra/outputs.tf | 29 - terraform/modules/aws-infra/variables.tf | 23 - terraform/modules/aws-infra/versions.tf | 13 - terraform/modules/cos-lite/README.md | 46 -- terraform/modules/cos-lite/main.tf | 384 ----------- terraform/modules/cos-lite/outputs.tf | 27 - terraform/modules/cos-lite/variables.tf | 16 - terraform/modules/cos-lite/versions.tf | 9 - terraform/modules/cos/README.md | 510 -------------- terraform/modules/cos/main.tf | 607 ----------------- terraform/modules/cos/outputs.tf | 26 - terraform/modules/cos/variables.tf | 266 -------- terraform/modules/cos/versions.tf | 9 - terraform/modules/loki/README.md | 59 -- terraform/modules/loki/main.tf | 151 ----- terraform/modules/loki/outputs.tf | 30 - terraform/modules/loki/variables.tf | 128 ---- terraform/modules/loki/versions.tf | 9 - terraform/modules/mimir/README.md | 60 -- terraform/modules/mimir/main.tf | 152 ----- terraform/modules/mimir/outputs.tf | 31 - terraform/modules/mimir/variables.tf | 129 ---- terraform/modules/mimir/versions.tf | 9 - terraform/modules/minio/main.tf | 43 -- terraform/modules/minio/outputs.tf | 4 - .../modules/minio/scripts/s3management.sh | 112 ---- terraform/modules/minio/variables.tf | 47 -- terraform/modules/minio/version.tf | 9 - terraform/modules/tempo/README.md | 63 -- terraform/modules/tempo/main.tf | 247 ------- terraform/modules/tempo/outputs.tf | 33 - terraform/modules/tempo/variables.tf | 176 ----- terraform/modules/tempo/versions.tf | 9 - terraform/scripts/generate_integrations.py | 67 -- .../hcl-generator/generate_integrations.py | 116 ---- 40 files changed, 4 insertions(+), 4481 deletions(-) delete mode 100644 terraform/modules/aws-infra/README.md delete mode 100644 terraform/modules/aws-infra/justfile delete mode 100644 terraform/modules/aws-infra/main.tf delete mode 100644 terraform/modules/aws-infra/outputs.tf delete mode 100644 terraform/modules/aws-infra/variables.tf delete mode 100644 terraform/modules/aws-infra/versions.tf delete mode 100644 terraform/modules/cos-lite/README.md delete mode 100644 terraform/modules/cos-lite/main.tf delete mode 100644 terraform/modules/cos-lite/outputs.tf delete mode 100644 terraform/modules/cos-lite/variables.tf delete mode 100644 terraform/modules/cos-lite/versions.tf delete mode 100644 terraform/modules/cos/README.md delete mode 100644 terraform/modules/cos/main.tf delete mode 100644 terraform/modules/cos/outputs.tf delete mode 100644 terraform/modules/cos/variables.tf delete mode 100644 terraform/modules/cos/versions.tf delete mode 100644 terraform/modules/loki/README.md delete mode 100644 terraform/modules/loki/main.tf delete mode 100644 terraform/modules/loki/outputs.tf delete mode 100644 terraform/modules/loki/variables.tf delete mode 100644 terraform/modules/loki/versions.tf delete mode 100644 terraform/modules/mimir/README.md delete mode 100644 terraform/modules/mimir/main.tf delete mode 100644 terraform/modules/mimir/outputs.tf delete mode 100644 terraform/modules/mimir/variables.tf delete mode 100644 terraform/modules/mimir/versions.tf delete mode 100644 terraform/modules/minio/main.tf delete mode 100644 terraform/modules/minio/outputs.tf delete mode 100755 terraform/modules/minio/scripts/s3management.sh delete mode 100644 terraform/modules/minio/variables.tf delete mode 100644 terraform/modules/minio/version.tf delete mode 100644 terraform/modules/tempo/README.md delete mode 100644 terraform/modules/tempo/main.tf delete mode 100644 terraform/modules/tempo/outputs.tf delete mode 100644 terraform/modules/tempo/variables.tf delete mode 100644 terraform/modules/tempo/versions.tf delete mode 100644 terraform/scripts/generate_integrations.py delete mode 100644 terraform/scripts/hcl-generator/generate_integrations.py diff --git a/.gitignore b/.gitignore index 3f9d7ae5..7edbc9ed 100644 --- a/.gitignore +++ b/.gitignore @@ -1,43 +1,2 @@ **/dist/** - -# Terraform -**/.terraform/* -*.tfstate -*.tfstate.* -*.tfplan -.terraform.lock.hcl -crash.log -.terraform/ -terraform.tfvars -terraform.tfvars.json -*.backup -*.bak -crash.log -crash.*.log - -# Exclude all .tfvars files, which are likely to contain sensitive data, such as -# password, private keys, and other secrets. These should not be part of version -# control as they are data points which are potentially sensitive and subject -# to change depending on the environment. -*.tfvars -*.tfvars.json - -# Ignore override files as they are usually used to override resources locally and so -# are not checked in -override.tf -override.tf.json -*_override.tf -*_override.tf.json - -# Include override files you do wish to add to version control using negated pattern -# !example_override.tf - -# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan -# example: *tfplan* - -# Ignore CLI configuration files -.terraformrc -terraform.rc -.terraform.lock.hcl - venv diff --git a/README.md b/README.md index 87aefc34..fae655c8 100644 --- a/README.md +++ b/README.md @@ -136,6 +136,10 @@ Issues are synced by the [gh-jira-sync-bot](https://github.com/canonical/gh-jira The bot configuration lives in [.github/.jira_sync_config.yaml](https://github.com/canonical/observability/blob/main/.github/.jira_sync_config.yaml); *carefully* read the README to configure it. This takes care of most things, except the Jira labels, which are added by the *Jira automation*. +## Terraform + +The COS product Terraform modules exist in [observability-stack/terraform](https://github.com/canonical/observability-stack/tree/main/terraform/), where you can find references to all the other Observability charm Terraform modules. + ## Scripts This repository contains a `scripts` directory for helper scripts of various nature as `pip-installables`. diff --git a/terraform/modules/aws-infra/README.md b/terraform/modules/aws-infra/README.md deleted file mode 100644 index c36c58af..00000000 --- a/terraform/modules/aws-infra/README.md +++ /dev/null @@ -1,131 +0,0 @@ -# From Zero to COS: AWS Provisioning & Deployment - -This directory contains Terraform modules for automating the process of bootstrapping a fresh AWS account to a fully running instance of COS deployed on a 3-node EKS cluster. - - -## Prerequisites - -Make sure you have the following installed: - -- [Terraform](https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli) >= v1.10.4 -- [AWS CLI](https://github.com/aws/aws-cli) >= 2.26.7 -- [Juju](https://snapcraft.io/juju) >= 3.0.3 -- [Just](https://github.com/casey/just) >= 1.40.0 - -### AWS Credentials Setup - -Before running any commands, ensure your AWS credentials are configured on the host: - -You can do this using one of the following methods: - -- [Environment variables](https://docs.aws.amazon.com/cli/v1/userguide/cli-configure-envvars.html) -- [Credentials file](https://docs.aws.amazon.com/cli/v1/userguide/cli-configure-files.html) - ---- - - -## Usage - -### Bootstrap AWS infrastructure + Juju controller: -In order to provision the AWS infrastructure required for COS, create a `main.tf` file with the following content. - -```hcl -module "aws_infra" { - source = "git::https://github.com/canonical/observability//terraform/modules/aws-infra" - region = var.region - cos_cloud_name = var.cos_cloud_name - cos_controller_name = var.cos_controller_name - cos_model_name = var.cos_model_name -} - -variable "region" { - description = "The AWS region where the resources will be provisioned." - type = string -} - -variable "cos_cloud_name" { - description = "The name to assign to the Kubernetes cloud when running 'juju add-k8s'." - type = string - default = "cos-cloud" -} - -variable "cos_controller_name" { - description = "The name to assign to the Juju controller that will manage COS." - type = string - default = "cos-controller" -} - -variable "cos_model_name" { - description = "The name of the Juju model where COS will be deployed." - type = string - default = "cos" -} - -``` -Then, create a `terraform.tfvars` file with the following content: - -```hcl -region = "" -cos_cloud_name = "" -cos_controller_name = "" -cos_model_name = "" -``` -Then, use terraform to deploy the module: -```bash -terraform init -terraform apply -var-file=terraform.tfvars -``` -### Full bootstrap: go from zero to COS: - -You can fully bootstrap AWS infra and COS in one of two ways: -#### Option 1: Manual 2-Step Process -1. [Bootstrap AWS infra](#bootstrap-aws-infrastructure--juju-controller) - -Set up the necessary infrastructure and Juju controller on AWS using the `aws-infra` module. - -2. [Deploy COS on the freshly created infra](../cos/README.md#deploy-cos-on-aws-eks) - -Use the output from step 1 to deploy COS on top of your provisioned infrastructure using the `cos` module. - -#### Option 2: Automated via `just` - -Clone this repository and run the appropriate `just` command to fully automate the bootstrap process. -This command handles: - -1. Bootstrapping the AWS infrastructure -2. Piping all required input to deploy COS on top - - -Create a `terraform.tfvars` file with the following content: -```hcl -region = "" -# Add other optional variables below -cos_cloud_name = "" -cos_controller_name = "" -cos_model_name = "" -``` -Then, run `just apply` - ---- - - -## Inputs - -| Variable Name | Description | -|----------|-------------------------| -| region | AWS region to provision resources in | -| cos_cloud_name | The name to assign to the Kubernetes cloud when running 'juju add-k8s' | -| cos_controller_name | The name to assign to the Juju controller that will manage COS | -| cos_model_name | The name of the Juju model where COS will be deployed | - ---- - -## Available Commands (via `just`) - -- `just init` – Initialize Terraform for AWS infra and COS -- `just apply` – Provision AWS infrastructure, then pipe the necessary outputs to provision COS on top -- `just destroy` – Tear down everything (COS + infra) - ---- - - diff --git a/terraform/modules/aws-infra/justfile b/terraform/modules/aws-infra/justfile deleted file mode 100644 index a7fe6021..00000000 --- a/terraform/modules/aws-infra/justfile +++ /dev/null @@ -1,39 +0,0 @@ -set quiet # Recipes are silent by default - -init: - terraform init - terraform -chdir=../cos init - -apply: init apply_infra apply_cos - -destroy: destroy_cos destroy_infra - -apply_infra: - terraform apply - -apply_cos: - terraform -chdir=../cos apply \ - -var="loki_bucket=$(terraform output -raw loki_bucket)" \ - -var="tempo_bucket=$(terraform output -raw tempo_bucket)" \ - -var="mimir_bucket=$(terraform output -raw mimir_bucket)" \ - -var="s3_endpoint=$(terraform output -raw s3_endpoint)" \ - -var="s3_user=$(terraform output -raw s3_user)" \ - -var="s3_password=$(terraform output -raw s3_password)" \ - -var="model_name=$(terraform output -raw cos_model)" \ - -var="ssc_channel=1/edge" \ - -var="cloud=aws" \ - -destroy_infra: - terraform destroy - -destroy_cos: - terraform -chdir=../cos destroy \ - -var="loki_bucket=$(terraform output -raw loki_bucket)" \ - -var="tempo_bucket=$(terraform output -raw tempo_bucket)" \ - -var="mimir_bucket=$(terraform output -raw mimir_bucket)" \ - -var="s3_endpoint=$(terraform output -raw s3_endpoint)" \ - -var="s3_user=$(terraform output -raw s3_user)" \ - -var="s3_password=$(terraform output -raw s3_password)" \ - -var="model_name=$(terraform output -raw cos_model)" \ - -var="ssc_channel=1/edge" \ - -var="cloud=aws" \ diff --git a/terraform/modules/aws-infra/main.tf b/terraform/modules/aws-infra/main.tf deleted file mode 100644 index 85350df0..00000000 --- a/terraform/modules/aws-infra/main.tf +++ /dev/null @@ -1,621 +0,0 @@ -provider "aws" { - region = var.region -} - -data "aws_availability_zones" "available" { - state = "available" -} -locals { - cos-cluster-name = "cos-cluster" -} - -## ==================================================== -## Network infra -## ==================================================== -resource "aws_vpc" "main" { - cidr_block = "10.0.0.0/16" - enable_dns_hostnames = true - enable_dns_support = true -} - -# To allow workloads running on ec2 nodes to access the public internet (e.g: to pull OCI images) -resource "aws_internet_gateway" "internet_gateway" { - vpc_id = aws_vpc.main.id -} - -# To deploy a 3-node eks cluster, it's recommended to spread them across at least 2 subnets in different AZs. -resource "aws_subnet" "public_subnet_1" { - vpc_id = aws_vpc.main.id - cidr_block = cidrsubnet(aws_vpc.main.cidr_block, 8, 1) - availability_zone = element(data.aws_availability_zones.available.names, 0) - map_public_ip_on_launch = true - tags = { - "kubernetes.io/role/elb" = "1" - } -} - -resource "aws_subnet" "public_subnet_2" { - vpc_id = aws_vpc.main.id - cidr_block = cidrsubnet(aws_vpc.main.cidr_block, 8, 2) - availability_zone = element(data.aws_availability_zones.available.names, 1) - map_public_ip_on_launch = true - tags = { - "kubernetes.io/role/elb" = "1" - } -} - -resource "aws_route_table" "public_rt" { - vpc_id = aws_vpc.main.id - route { - cidr_block = "0.0.0.0/0" - gateway_id = aws_internet_gateway.internet_gateway.id - } -} - - -resource "aws_route_table_association" "public_rta_1" { - subnet_id = aws_subnet.public_subnet_1.id - route_table_id = aws_route_table.public_rt.id -} - -resource "aws_route_table_association" "public_rta_2" { - subnet_id = aws_subnet.public_subnet_2.id - route_table_id = aws_route_table.public_rt.id -} - -## ==================================================== -## Kubernetes infra -## ==================================================== - -# a role that eks cluster can assume -resource "aws_iam_role" "cos_cluster_role" { - name = "cos-cluster-role" - assume_role_policy = jsonencode({ - Version = "2012-10-17" - Statement = [ - { - Effect = "Allow" - Principal = { - Service = ["eks.amazonaws.com"] - } - Action = [ - "sts:AssumeRole", - "sts:TagSession" - ] - } - ] - }) -} - -# eks role needs the below permissions -resource "aws_iam_role_policy_attachment" "cos_cluster_policy" { - role = aws_iam_role.cos_cluster_role.name - policy_arn = "arn:aws:iam::aws:policy/AmazonEKSClusterPolicy" -} -resource "aws_iam_role_policy_attachment" "cos_cluster_network_policy" { - role = aws_iam_role.cos_cluster_role.name - policy_arn = "arn:aws:iam::aws:policy/AmazonEKSNetworkingPolicy" -} -resource "aws_iam_role_policy_attachment" "cos_cluster_lb_policy" { - role = aws_iam_role.cos_cluster_role.name - policy_arn = "arn:aws:iam::aws:policy/AmazonEKSLoadBalancingPolicy" -} -resource "aws_iam_role_policy_attachment" "cos_cluster_storage_policy" { - role = aws_iam_role.cos_cluster_role.name - policy_arn = "arn:aws:iam::aws:policy/AmazonEKSBlockStoragePolicy" -} -resource "aws_iam_role_policy_attachment" "cos_cluster_compute_policy" { - role = aws_iam_role.cos_cluster_role.name - policy_arn = "arn:aws:iam::aws:policy/AmazonEKSComputePolicy" -} - -resource "aws_eks_cluster" "cos_cluster" { - name = local.cos-cluster-name - bootstrap_self_managed_addons = false - access_config { - authentication_mode = "API" - } - role_arn = aws_iam_role.cos_cluster_role.arn - compute_config { - enabled = true - } - - kubernetes_network_config { - elastic_load_balancing { - enabled = true - } - } - - storage_config { - block_storage { - enabled = true - } - } - - vpc_config { - subnet_ids = [ - aws_subnet.public_subnet_1.id, - aws_subnet.public_subnet_2.id, - ] - } - - depends_on = [ - aws_iam_role_policy_attachment.cos_cluster_policy, - aws_iam_role_policy_attachment.cos_cluster_network_policy, - aws_iam_role_policy_attachment.cos_cluster_lb_policy, - aws_iam_role_policy_attachment.cos_cluster_storage_policy, - aws_iam_role_policy_attachment.cos_cluster_compute_policy, - aws_route_table.public_rt, - aws_internet_gateway.internet_gateway, - ] -} - -# enable network communication -resource "aws_eks_addon" "eks_kube_proxy_addon" { - cluster_name = aws_eks_cluster.cos_cluster.name - addon_name = "kube-proxy" -} - -# enable name resolution for all pods -resource "aws_eks_addon" "eks_core_dns_addon" { - cluster_name = aws_eks_cluster.cos_cluster.name - addon_name = "coredns" - depends_on = [aws_eks_node_group.cos_workers] -} - -# enables assigning a private IPv4 from your VPC to each pod. -resource "aws_eks_addon" "eks_vpc_cni_addon" { - cluster_name = aws_eks_cluster.cos_cluster.name - addon_name = "vpc-cni" -} - -# provides the ability to manage credentials for your application -# needed for EBS CSI driver -resource "aws_eks_addon" "eks_pod_identity_addon" { - cluster_name = aws_eks_cluster.cos_cluster.name - addon_name = "eks-pod-identity-agent" -} - -resource "aws_iam_role" "eks_ebs_role" { - name = "eks-ebs-csi-driver-role" - - assume_role_policy = jsonencode({ - Version = "2012-10-17" - Statement = [ - { - Effect = "Allow" - Principal = { - Service = "pods.eks.amazonaws.com" - } - Action = ["sts:AssumeRole", "sts:TagSession"] - } - ] - }) -} -resource "aws_iam_role_policy_attachment" "eks_ebs_policy" { - role = aws_iam_role.eks_ebs_role.name - policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonEBSCSIDriverPolicy" -} - - -# enable Amazon EBS CSI driver. -# Give access to "ebs-csi-controller-sa" SA to provision and manage Amazon EBS volumes. -resource "aws_eks_addon" "eks_ebs_addon" { - cluster_name = aws_eks_cluster.cos_cluster.name - addon_name = "aws-ebs-csi-driver" - pod_identity_association { - role_arn = aws_iam_role.eks_ebs_role.arn - service_account = "ebs-csi-controller-sa" - } - depends_on = [aws_eks_node_group.cos_workers] -} - -# Worker nodes need the below permissions -resource "aws_iam_role" "workers_role" { - name = "workers-role" - assume_role_policy = jsonencode({ - Version = "2012-10-17" - Statement = [ - { - Effect = "Allow" - Principal = { - Service = "ec2.amazonaws.com" - } - Action = "sts:AssumeRole" - } - ] - }) -} - -resource "aws_iam_role_policy_attachment" "workers_nodes_policy" { - role = aws_iam_role.workers_role.name - policy_arn = "arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy" -} - -resource "aws_iam_role_policy_attachment" "workers_cni_policy" { - role = aws_iam_role.workers_role.name - policy_arn = "arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy" -} - -resource "aws_iam_role_policy_attachment" "workers_registry_policy" { - role = aws_iam_role.workers_role.name - policy_arn = "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" -} - -# create 3 AWS-managed worker nodes -resource "aws_eks_node_group" "cos_workers" { - cluster_name = aws_eks_cluster.cos_cluster.name - node_group_name = "cos-workers" - node_role_arn = aws_iam_role.workers_role.arn - subnet_ids = [ - aws_subnet.public_subnet_1.id, - aws_subnet.public_subnet_2.id, - ] - scaling_config { - min_size = 3 - max_size = 3 - desired_size = 3 - } - disk_size = 50 - instance_types = [ - "t3.xlarge" - ] - ami_type = "AL2_x86_64" - - depends_on = [ - aws_iam_role_policy_attachment.workers_nodes_policy, - aws_iam_role_policy_attachment.workers_registry_policy, - aws_iam_role_policy_attachment.workers_cni_policy, - aws_eks_cluster.cos_cluster, - ] -} - -## ==================================================== -## Bootstrap Juju -## ==================================================== - -# Authorise the current user to access the K8s cluster resources (i.e K8s RBAC) -# needed for a later step (i.e juju add-k8s) -data "aws_caller_identity" "admin" {} - -data "aws_iam_session_context" "admin_iam" { - arn = data.aws_caller_identity.admin.arn -} - -resource "aws_eks_access_policy_association" "admin_eks_admin_policy" { - cluster_name = aws_eks_cluster.cos_cluster.name - policy_arn = "arn:aws:eks::aws:cluster-access-policy/AmazonEKSAdminPolicy" - principal_arn = data.aws_iam_session_context.admin_iam.issuer_arn - access_scope { - type = "cluster" - } -} - -resource "aws_eks_access_policy_association" "admin_eks_cluster_admin_policy" { - cluster_name = aws_eks_cluster.cos_cluster.name - policy_arn = "arn:aws:eks::aws:cluster-access-policy/AmazonEKSClusterAdminPolicy" - principal_arn = data.aws_iam_session_context.admin_iam.issuer_arn - access_scope { - type = "cluster" - } -} - -resource "aws_eks_access_entry" "admin_access_entry" { - cluster_name = aws_eks_cluster.cos_cluster.name - principal_arn = data.aws_iam_session_context.admin_iam.issuer_arn -} - -# create a role for the juju controller (i.e an ec2 instance) -# with the necessary permissions to manage juju resources that interact with AWS resources. -resource "aws_iam_role" "juju_controller_role" { - name = "juju-controller-role" - assume_role_policy = jsonencode({ - Version = "2012-10-17" - Statement = [ - { - Effect = "Allow" - Principal = { - Service = ["ec2.amazonaws.com"] - } - Action = [ - "sts:AssumeRole", - ] - } - ] - }) - -} - -# permissions needed: https://discourse.charmhub.io/t/juju-aws-permissions/5307 -resource "aws_iam_policy" "juju_controller_policy" { - name = "juju-controller-policy" - - policy = jsonencode({ - Version = "2012-10-17" - Statement = [ - { - "Sid" : "JujuEC2Actions", - Action = [ - "ec2:AssociateIamInstanceProfile", - "ec2:AttachVolume", - "ec2:AuthoriseSecurityGroupIngress", - "ec2:CreateSecurityGroup", - "ec2:CreateTags", - "ec2:CreateVolume", - "ec2:DeleteSecurityGroup", - "ec2:DeleteVolume", - "ec2:DescribeAccountAttributes", - "ec2:DescribeAvailabilityZones", - "ec2:DescribeIamInstanceProfileAssociations", - "ec2:DescribeInstances", - "ec2:DescribeInstanceTypeOfferings", - "ec2:DescribeInstanceTypes", - "ec2:DescribeInternetGateways", - "ec2:DescribeNetworkInterfaces", - "ec2:DescribeRouteTables", - "ec2:DescribeSecurityGroups", - "ec2:DescribeSpotPriceHistory", - "ec2:DescribeSubnets", - "ec2:DescribeVolumes", - "ec2:DescribeVpcs", - "ec2:DetachVolume", - "ec2:RevokeSecurityGroupIngress", - "ec2:RunInstances", - "ec2:TerminateInstances" - ] - Effect = "Allow" - Resource = "*" - }, - { - "Sid" : "JujuIAMActions", - "Effect" : "Allow", - "Action" : [ - "iam:AddRoleToInstanceProfile", - "iam:CreateInstanceProfile", - "iam:CreateRole", - "iam:DeleteInstanceProfile", - "iam:DeleteRole", - "iam:DeleteRolePolicy", - "iam:GetInstanceProfile", - "iam:GetRole", - "iam:ListInstanceProfiles", - "iam:ListRolePolicies", - "iam:ListRoles", - "iam:PassRole", - "iam:PutRolePolicy", - "iam:RemoveRoleFromInstanceProfile" - ], - "Resource" : "*" - }, - { - "Sid" : "JujuSSMActions", - "Effect" : "Allow", - "Action" : [ - "ssm:ListInstanceAssociations", - "ssm:UpdateInstanceInformation" - ], - "Resource" : "*" - } - - ] - }) -} - -resource "aws_iam_role_policy_attachment" "juju_controller_policy_attach" { - role = aws_iam_role.juju_controller_role.name - policy_arn = aws_iam_policy.juju_controller_policy.arn -} - -resource "aws_iam_instance_profile" "juju_ctrl_instance_profile" { - name = "juju-ctrl-instance-profile" - role = aws_iam_role.juju_controller_role.name -} - -# Authorise the juju controller to access the K8s cluster resources (i.e K8s RBAC) -resource "aws_eks_access_policy_association" "ctrl_access_eks_admin" { - cluster_name = aws_eks_cluster.cos_cluster.name - policy_arn = "arn:aws:eks::aws:cluster-access-policy/AmazonEKSAdminPolicy" - principal_arn = aws_iam_role.juju_controller_role.arn - - access_scope { - type = "cluster" - } -} - -resource "aws_eks_access_policy_association" "ctrl_access_eks_cluster_admin" { - cluster_name = aws_eks_cluster.cos_cluster.name - policy_arn = "arn:aws:eks::aws:cluster-access-policy/AmazonEKSClusterAdminPolicy" - principal_arn = aws_iam_role.juju_controller_role.arn - - access_scope { - type = "cluster" - } -} - -resource "aws_eks_access_entry" "juju_controller_access_entry" { - cluster_name = aws_eks_cluster.cos_cluster.name - principal_arn = aws_iam_role.juju_controller_role.arn -} - - -# create an IAM user with permissions that can bootstrap a juju controller on aws. -# The managed role used to run this terraform doesn't work for some reason. -resource "aws_iam_user" "juju_bootstrap_user" { - name = "juju-bootstrap" -} - -resource "aws_iam_user_policy" "juju_bootstrap_policy" { - name = "juju-bootstrap-policy" - user = aws_iam_user.juju_bootstrap_user.name - policy = jsonencode({ - Version = "2012-10-17" - Statement = [ - { - Action = [ - "ec2:*", - ] - Effect = "Allow" - Resource = "*" - }, - { - "Effect" : "Allow", - "Action" : [ - "iam:AddRoleToInstanceProfile", - "iam:CreateInstanceProfile", - "iam:CreateRole", - "iam:DeleteInstanceProfile", - "iam:DeleteRole", - "iam:DeleteRolePolicy", - "iam:GetInstanceProfile", - "iam:GetRole", - "iam:ListInstanceProfiles", - "iam:ListRolePolicies", - "iam:ListRoles", - "iam:PassRole", - "iam:PutRolePolicy", - "iam:RemoveRoleFromInstanceProfile" - ], - "Resource" : "*" - }, - ] - }) - -} - -resource "aws_iam_access_key" "juju_bootstrap_access_key" { - user = aws_iam_user.juju_bootstrap_user.name -} - -# to bootstrap a controller on aws, we need to provide the aws credentials -# through a credentials.yaml file -resource "local_sensitive_file" "aws_credentials" { - depends_on = [aws_iam_access_key.juju_bootstrap_access_key] - - content = yamlencode({ - credentials : { - aws : { - bootstrap-juju : { - auth-type : "access-key", - access-key : aws_iam_access_key.juju_bootstrap_access_key.id, - secret-key : aws_iam_access_key.juju_bootstrap_access_key.secret, - } } - } - }) - filename = "${path.root}/.terraform/tmp/credentials.yaml" -} - - -# run local juju commands to bootstrap a juju controller using aws_iam_user.juju_bootstrap_user credentials -# then, when the controller is running, it will use the aws_iam_instance_profile.juju_ctrl_instance_profile -# to give the controller access to manage AWS resources -resource "null_resource" "bootstrap_juju" { - - triggers = { - # uncomment if you need to force destroy then create - # once = timestamp() - cos-controller = var.cos_controller_name - } - - depends_on = [local_sensitive_file.aws_credentials, - aws_eks_node_group.cos_workers, - aws_eks_addon.eks_ebs_addon, - aws_eks_access_entry.juju_controller_access_entry, - aws_eks_access_entry.admin_access_entry, - aws_eks_addon.eks_vpc_cni_addon, - aws_eks_addon.eks_kube_proxy_addon, - aws_eks_addon.eks_core_dns_addon, - aws_eks_addon.eks_pod_identity_addon, - aws_iam_policy.juju_controller_policy, - aws_route_table_association.public_rta_1, - aws_route_table_association.public_rta_2, - aws_eks_access_policy_association.ctrl_access_eks_cluster_admin, - aws_eks_access_policy_association.admin_eks_admin_policy, - aws_iam_role.juju_controller_role, - aws_iam_instance_profile.juju_ctrl_instance_profile, - aws_iam_role_policy_attachment.juju_controller_policy_attach, - aws_iam_role_policy_attachment.eks_ebs_policy, - aws_eks_access_policy_association.ctrl_access_eks_admin, - aws_iam_user_policy.juju_bootstrap_policy, - aws_eks_access_policy_association.admin_eks_cluster_admin_policy, - ] - - provisioner "local-exec" { - when = create - command = <<-EOT - juju remove-credential aws bootstrap-juju --client - juju add-credential aws --client -f ${local_sensitive_file.aws_credentials.filename} - - if ! juju controllers | grep -q '^${var.cos_controller_name}'; then - juju bootstrap --bootstrap-constraints="instance-role=${aws_iam_instance_profile.juju_ctrl_instance_profile.name}" aws/${var.region} ${var.cos_controller_name} --config vpc-id=${aws_vpc.main.id} --config vpc-id-force=true --credential bootstrap-juju - else - echo "controller already exists, skipping bootstrap." - fi - aws eks --region ${var.region} update-kubeconfig --name ${local.cos-cluster-name} - /snap/juju/current/bin/juju add-k8s ${var.cos_cloud_name} --controller ${var.cos_controller_name} - juju add-model ${var.cos_model_name} ${var.cos_cloud_name}/${var.region} - EOT - } - - provisioner "local-exec" { - when = destroy - command = <<-EOT - - if juju controllers | grep -q '^${self.triggers.cos-controller}'; then - juju kill-controller ${self.triggers.cos-controller} --timeout 0 --no-prompt - else - echo "Skipping controller deletion." - fi - EOT - } -} - - -## ==================================================== -## Create S3 buckets -## ==================================================== - -resource "aws_s3_bucket" "tempo_s3" { - bucket = "cos-tempo-bucket" - force_destroy = true -} - -resource "aws_s3_bucket" "loki_s3" { - bucket = "cos-loki-bucket" - force_destroy = true -} - -resource "aws_s3_bucket" "mimir_s3" { - bucket = "cos-mimir-bucket" - force_destroy = true -} - -# currently, our charms require the existence of an S3 access key and secret key -# and we can only obtain them through an IAM user. -# create an IAM user to access the buckets. -# TODO: create 3 IAM users, one for each bucket access -resource "aws_iam_user" "s3_access" { - name = "s3-access" -} - -resource "aws_iam_user_policy" "s3_access_policy" { - name = "s3-access-policy" - user = aws_iam_user.s3_access.name - - policy = jsonencode({ - Version = "2012-10-17" - Statement = [ - { - Action = [ - "s3:*", - ] - Effect = "Allow" - Resource = "*" - }, - ] - }) -} - -resource "aws_iam_access_key" "s3_access_key" { - user = aws_iam_user.s3_access.name -} - diff --git a/terraform/modules/aws-infra/outputs.tf b/terraform/modules/aws-infra/outputs.tf deleted file mode 100644 index c70d423d..00000000 --- a/terraform/modules/aws-infra/outputs.tf +++ /dev/null @@ -1,29 +0,0 @@ - - -output "loki_bucket" { - value = aws_s3_bucket.loki_s3.bucket -} - -output "mimir_bucket" { - value = aws_s3_bucket.mimir_s3.bucket -} -output "tempo_bucket" { - value = aws_s3_bucket.tempo_s3.bucket -} - -output "s3_endpoint" { - value = "https://s3.${var.region}.amazonaws.com" -} - -output "s3_user" { - value = aws_iam_access_key.s3_access_key.id -} - -output "s3_password" { - value = aws_iam_access_key.s3_access_key.secret - sensitive = true -} - -output "cos_model" { - value = var.cos_model_name -} diff --git a/terraform/modules/aws-infra/variables.tf b/terraform/modules/aws-infra/variables.tf deleted file mode 100644 index 0ac2558a..00000000 --- a/terraform/modules/aws-infra/variables.tf +++ /dev/null @@ -1,23 +0,0 @@ - -variable "region" { - description = "The AWS region where the resources will be provisioned." - type = string -} - -variable "cos_cloud_name" { - description = "The name to assign to the Kubernetes cloud when running 'juju add-k8s'." - type = string - default = "cos-cloud" -} - -variable "cos_controller_name" { - description = "The name to assign to the Juju controller that will manage COS." - type = string - default = "cos-controller" -} - -variable "cos_model_name" { - description = "The name of the Juju model where COS will be deployed." - type = string - default = "cos" -} diff --git a/terraform/modules/aws-infra/versions.tf b/terraform/modules/aws-infra/versions.tf deleted file mode 100644 index ccb1e344..00000000 --- a/terraform/modules/aws-infra/versions.tf +++ /dev/null @@ -1,13 +0,0 @@ -terraform { - required_version = ">= 1.5" - required_providers { - aws = { - source = "hashicorp/aws" - version = "~> 5.0" - } - null = { - source = "hashicorp/null" - version = "~> 3.0" - } - } -} diff --git a/terraform/modules/cos-lite/README.md b/terraform/modules/cos-lite/README.md deleted file mode 100644 index c99645ae..00000000 --- a/terraform/modules/cos-lite/README.md +++ /dev/null @@ -1,46 +0,0 @@ -Terraform module for COS solution - -This is a Terraform module facilitating the deployment of COS solution, using the [Terraform juju provider](https://github.com/juju/terraform-provider-juju/). For more information, refer to the provider [documentation](https://registry.terraform.io/providers/juju/juju/latest/docs). - -The COS Lite solution consists of the following Terraform modules: -- [grafana-k8s](https://github.com/canonical/grafana-k8s-operator): Visualization, monitoring, and dashboards. -- [alertmanager-k8s](https://github.com/canonical/alertmanager-k8s-operator): Handles alerts sent by clients applications. -- [prometheus-k8s](https://github.com/canonical/prometheus-k8s-operator/tree/main/terraform/): Backend for metrics -- [loki-k8s](https://github.com/canonical/loki-k8s-operator/tree/main/terraform): Backend for logs -- [self-signed-certificates](https://github.com/canonical/self-signed-certificates-operator): certificates operator to secure traffic with TLS. - -## Requirements - -This module requires a `juju` model to be available. Refer to the [usage section](#usage) below for more details. - -## API - -### Inputs - -The module offers the following configurable inputs: - -| Name | Type | Description | Required | -|--------------|--------|------------------------------------------------------------------------|-------------| -| `channel` | string | Channel that the charms are deployed from | latest/edge | -| `model_name` | string | Name of the model that the charm is deployed on | | -| `use_tls` | bool | Specify whether to use TLS or not for coordinator-worker communication | | - -### Outputs - -Upon application, the module exports the following outputs: - -| Name | Description | -|------------|-----------------------------| -| `app_name` | Application name | -| `provides` | Map of `provides` endpoints | -| `requires` | Map of `requires` endpoints | - -## Usage - - -### Basic usage - -Users should ensure that Terraform is aware of the `juju_model` dependency of the charm module. - -To deploy this module with its needed dependency, you can run `terraform apply -var="model_name=" -auto-approve`. This would deploy all COS HA solution modules in the same model. - diff --git a/terraform/modules/cos-lite/main.tf b/terraform/modules/cos-lite/main.tf deleted file mode 100644 index 9126107d..00000000 --- a/terraform/modules/cos-lite/main.tf +++ /dev/null @@ -1,384 +0,0 @@ -# -------------- # Applications -------------- - -module "ssc" { - count = var.use_tls ? 1 : 0 - source = "git::https://github.com/canonical/self-signed-certificates-operator//terraform" - model = var.model - channel = var.channel -} - -module "alertmanager" { - source = "git::https://github.com/canonical/alertmanager-k8s-operator//terraform" - app_name = "alertmanager" - model = var.model - channel = var.channel -} - -module "catalogue" { - source = "git::https://github.com/canonical/catalogue-k8s-operator//terraform" - app_name = "catalogue" - model = var.model - channel = var.channel -} - -module "prometheus" { - source = "git::https://github.com/canonical/prometheus-k8s-operator//terraform" - app_name = "prometheus" - model_name = var.model - channel = var.channel -} - -module "loki" { - source = "git::https://github.com/canonical/loki-k8s-operator//terraform" - app_name = "loki" - model_name = var.model - channel = var.channel -} - -module "grafana" { - source = "git::https://github.com/canonical/grafana-k8s-operator//terraform" - app_name = "grafana" - model = var.model - channel = var.channel -} - -module "traefik" { - source = "git::https://github.com/canonical/traefik-k8s-operator//terraform" - app_name = "traefik" - model = var.model - channel = var.channel -} - - -# -------------- # Integrations -------------- - - -# Provided by Alertmanager - -resource "juju_integration" "alertmanager_grafana_dashboards" { - model = var.model - - application { - name = module.alertmanager.app_name - endpoint = module.alertmanager.endpoints.grafana_dashboard - } - - application { - name = module.grafana.app_name - endpoint = module.grafana.endpoints.grafana_dashboard - } -} - -resource "juju_integration" "alertmanager_prometheus" { - model = var.model - - application { - name = module.prometheus.app_name - endpoint = module.prometheus.endpoints.alertmanager - } - - application { - name = module.alertmanager.app_name - endpoint = module.alertmanager.endpoints.alerting - } -} - -resource "juju_integration" "alertmanager_self_monitoring_prometheus" { - model = var.model - - application { - name = module.prometheus.app_name - endpoint = module.prometheus.endpoints.metrics_endpoint - } - - application { - name = module.alertmanager.app_name - endpoint = module.alertmanager.endpoints.self_metrics_endpoint - } -} - -resource "juju_integration" "alertmanager_loki" { - model = var.model - - application { - name = module.loki.app_name - endpoint = module.loki.endpoints.alertmanager - } - - application { - name = module.alertmanager.app_name - endpoint = module.alertmanager.endpoints.alerting - } -} - - -resource "juju_integration" "grafana_source_alertmanager" { - model = var.model - - application { - name = module.alertmanager.app_name - endpoint = module.alertmanager.endpoints.grafana_source - } - - application { - name = module.grafana.app_name - endpoint = module.grafana.endpoints.grafana_source - } -} - -# Provided by Grafana - -resource "juju_integration" "grafana_self_monitoring_prometheus" { - model = var.model - - application { - name = module.prometheus.app_name - endpoint = module.prometheus.endpoints.metrics_endpoint - } - - application { - name = module.grafana.app_name - endpoint = module.grafana.endpoints.metrics_endpoint - } -} - - -# Provided by Prometheus - -resource "juju_integration" "prometheus_grafana_dashboards_provider" { - model = var.model - - application { - name = module.prometheus.app_name - endpoint = module.prometheus.endpoints.grafana_dashboard - } - - application { - name = module.grafana.app_name - endpoint = module.grafana.endpoints.grafana_dashboard - } -} - -resource "juju_integration" "prometheus_grafana_source" { - model = var.model - - application { - name = module.prometheus.app_name - endpoint = module.prometheus.endpoints.grafana_source - } - - application { - name = module.grafana.app_name - endpoint = module.grafana.endpoints.grafana_source - } -} - - - - -# Provided by Loki - -resource "juju_integration" "loki_grafana_dashboards_provider" { - model = var.model - - application { - name = module.loki.app_name - endpoint = module.loki.endpoints.grafana_dashboard - } - - application { - name = module.grafana.app_name - endpoint = module.grafana.endpoints.grafana_dashboard - } -} - -resource "juju_integration" "loki_grafana_source" { - model = var.model - - application { - name = module.loki.app_name - endpoint = module.loki.endpoints.grafana_source - } - - application { - name = module.grafana.app_name - endpoint = module.grafana.endpoints.grafana_source - } -} - -resource "juju_integration" "loki_self_monitoring_prometheus" { - model = var.model - - application { - name = module.prometheus.app_name - endpoint = module.prometheus.endpoints.metrics_endpoint - } - - application { - name = module.loki.app_name - endpoint = module.loki.endpoints.metrics_endpoint - } -} - - -# Provided by Catalogue - -resource "juju_integration" "catalogue_alertmanager" { - model = var.model - - application { - name = module.catalogue.app_name - endpoint = module.catalogue.endpoints.catalogue - } - - application { - name = module.alertmanager.app_name - endpoint = module.alertmanager.endpoints.catalogue - } -} - -resource "juju_integration" "catalogue_grafana" { - model = var.model - - application { - name = module.catalogue.app_name - endpoint = module.catalogue.endpoints.catalogue - } - - application { - name = module.grafana.app_name - endpoint = module.grafana.endpoints.catalogue - } -} - -resource "juju_integration" "catalogue_prometheus" { - model = var.model - - application { - name = module.catalogue.app_name - endpoint = module.catalogue.endpoints.catalogue - } - - application { - name = module.prometheus.app_name - endpoint = module.prometheus.endpoints.catalogue - } -} - - -# Provided by Traefik - -resource "juju_integration" "alertmanager_ingress" { - model = var.model - - application { - name = module.traefik.app_name - endpoint = module.traefik.endpoints.ingress - } - - application { - name = module.alertmanager.app_name - endpoint = module.alertmanager.endpoints.ingress - } -} - - -resource "juju_integration" "catalogue_ingress" { - model = var.model - - application { - name = module.traefik.app_name - endpoint = module.traefik.endpoints.ingress - } - - application { - name = module.catalogue.app_name - endpoint = module.catalogue.endpoints.ingress - } -} - -resource "juju_integration" "grafana_ingress" { - model = var.model - - application { - name = module.traefik.app_name - endpoint = module.traefik.endpoints.traefik_route - } - - application { - name = module.grafana.app_name - endpoint = module.grafana.endpoints.ingress - } -} - -resource "juju_integration" "prometheus_ingress" { - model = var.model - - application { - name = module.traefik.app_name - endpoint = module.traefik.endpoints.ingress_per_unit - } - - application { - name = module.prometheus.app_name - endpoint = module.prometheus.endpoints.ingress - } -} - -resource "juju_integration" "loki_ingress" { - model = var.model - - application { - name = module.traefik.app_name - endpoint = module.traefik.endpoints.ingress_per_unit - } - - application { - name = module.loki.app_name - endpoint = module.loki.endpoints.ingress - } -} - -resource "juju_integration" "traefik_self_monitoring_prometheus" { - model = var.model - - application { - name = module.prometheus.app_name - endpoint = module.prometheus.endpoints.metrics_endpoint - } - - application { - name = module.traefik.app_name - endpoint = module.traefik.endpoints.metrics_endpoint - } -} - -# -------------- # Offers -------------- - -resource "juju_offer" "alertmanager-karma-dashboard" { - name = "alertmanager-karma-dashboard" - model = var.model - application_name = module.alertmanager.app_name - endpoint = "karma-dashboard" -} - -resource "juju_offer" "grafana-dashboards" { - name = "grafana-dashboards" - model = var.model - application_name = module.grafana.app_name - endpoint = "grafana-dashboard" -} - -resource "juju_offer" "loki-logging" { - name = "loki-logging" - model = var.model - application_name = module.loki.app_name - endpoint = "logging" -} - -resource "juju_offer" "prometheus-receive-remote-write" { - name = "prometheus-receive-remote-write" - model = var.model - application_name = module.prometheus.app_name - endpoint = "receive-remote-write" -} diff --git a/terraform/modules/cos-lite/outputs.tf b/terraform/modules/cos-lite/outputs.tf deleted file mode 100644 index 06e50fc7..00000000 --- a/terraform/modules/cos-lite/outputs.tf +++ /dev/null @@ -1,27 +0,0 @@ -output "app_names" { - value = merge( - { - alertmanager = module.alertmanager.app_name, - catalogue = module.catalogue.app_name, - grafana = module.grafana.app_name, - loki = module.loki.app_name, - prometheus = module.prometheus.app_name, - traefik = module.traefik.app_name, - } - ) -} - -output "grafana" { - description = "Outputs from the Grafana module" - value = module.grafana -} - -output "prometheus" { - description = "Outputs from the prometheus module" - value = module.prometheus -} - -output "loki" { - description = "Outputs from the Loki module" - value = module.loki -} diff --git a/terraform/modules/cos-lite/variables.tf b/terraform/modules/cos-lite/variables.tf deleted file mode 100644 index fd74d96a..00000000 --- a/terraform/modules/cos-lite/variables.tf +++ /dev/null @@ -1,16 +0,0 @@ -variable "channel" { - description = "Charms channel" - type = string - default = "latest/edge" -} - -variable "model" { - description = "Model name" - type = string -} - -variable "use_tls" { - description = "Specify whether to use TLS or not for coordinator-worker communication. By default, TLS is enabled through self-signed-certificates" - type = bool - default = true -} diff --git a/terraform/modules/cos-lite/versions.tf b/terraform/modules/cos-lite/versions.tf deleted file mode 100644 index 77b64403..00000000 --- a/terraform/modules/cos-lite/versions.tf +++ /dev/null @@ -1,9 +0,0 @@ -terraform { - required_version = ">= 1.5" - required_providers { - juju = { - source = "juju/juju" - version = "~> 0.14" - } - } -} \ No newline at end of file diff --git a/terraform/modules/cos/README.md b/terraform/modules/cos/README.md deleted file mode 100644 index e0387019..00000000 --- a/terraform/modules/cos/README.md +++ /dev/null @@ -1,510 +0,0 @@ -# Terraform module for COS solution - -This is a Terraform module facilitating the deployment of COS solution, using the [Terraform juju provider](https://github.com/juju/terraform-provider-juju/). For more information, refer to the provider [documentation](https://registry.terraform.io/providers/juju/juju/latest/docs). - -The HA solution consists of the following Terraform modules: -- [alertmanager-k8s](https://github.com/canonical/alertmanager-k8s-operator/tree/main/terraform): Handles alerts sent by clients applications. -- [grafana-k8s](https://github.com/canonical/grafana-k8s-operator/tree/main/terraform): Visualization, monitoring, and dashboards. -- [grafana-agent-k8s](https://github.com/canonical/grafana-agent-k8s-operator/tree/main/terraform): Aggregate and send telemetry data. -- [loki](https://github.com/canonical/observability/tree/main/terraform/modules/loki): Backend for logs. -- [mimir](https://github.com/canonical/observability/tree/main/terraform/modules/mimir): Backend for metrics. -- [tempo](https://github.com/canonical/observability/tree/main/terraform/modules/tempo): Backend for traces. -- [s3-integrator](https://github.com/canonical/s3-integrator): facade for S3 storage configurations. -- [self-signed-certificates](https://github.com/canonical/self-signed-certificates-operator/tree/main/terraform): certificates operator to secure traffic with TLS. -- [traefik](https://github.com/canonical/traefik-k8s-operator/tree/main/terraform): ingress. - -This Terraform module deploys COS with Mimir, Tempo and Loki in their microservices modes, and other charms in monolithic mode. - -> [!NOTE] -> `s3-integrator` itself doesn't act as an S3 object storage system. For the HA solution to be functional, `s3-integrator` needs to point to an S3-like storage. See [this guide](https://discourse.charmhub.io/t/cos-lite-docs-set-up-minio/15211) to learn how to connect to an S3-like storage for traces. - -## Requirements -This module requires a `juju` model to be available. Refer to the [usage section](#usage) below for more details. - -## API - -### Inputs -The module offers the following configurable inputs: - -| Name | Type | Description | Default | -| - | - |----------------------------------------------------------------| - | -| `channel` | string | Channel that all the charms (unless overwritten) are deployed from | -| `ssc_channel` | string | Channel that the self-signed certificates charm is deployed from | latest/edge | -| `traefik_channel` | string | Channel that the traefik charm is deployed from | latest/edge | -| `model` | string | Reference to an existing model resource or data source for the model to deploy to | -| `use_tls` | bool | Specify whether to use TLS or not for in-cluster communication | -| `cloud` | string | Kubernetes cloud or environment where this COS module will be deployed | self-managed | -| `loki_coordinator_units` | number | Number of Loki coordinator units | -| `loki_backend_units` | number | Number of Loki worker units with `backend` role | -| `loki_read_units` | number | Number of Loki worker units with `read` role | -| `loki_write_units` | number | Number of Loki worker units with `write` role | -| `mimir_coordinator_units` | number | Number of Mimir coordinator units | -| `mimir_backend_units` | number | Number of Mimir worker units with `backend` role | -| `mimir_read_units` | number | Number of Mimir worker units with `read` role | -| `mimir_write_units` | number | Number of Mimir worker units with `write` role | -| `tempo_coordinator_units` | number | Number of Tempo coordinator units | -| `tempo_compactor_units` | number | Number of Tempo worker units with `compactor` role | -| `tempo_distributor_units` | number | Number of Tempo worker units with `distributor` role | -| `tempo_ingester_units` | number | Number of Tempo worker units with `ingester` role | -| `tempo_metrics_generator_units` | number | Number of Tempo worker units with `metrics_generator` role | -| `tempo_querier_units` | number | Number of Tempo worker units with `querier` role | -| `tempo_query_frontend_units` | number | Number of Tempo worker units with `query_frontend` role | -| `s3_access_key` | string | Access key credential to connect to the S3 provider | 1 | -| `s3_secret_key` | string | Secret key credential to connect to the S3 provider | 1 | -| `s3_endpoint` | string | S3 provider endpoint | 1 | -| `loki_bucket` | string | Name of the bucket in which Loki should store its logs | 1 | -| `mimir_bucket` | string | Name of the bucket in which Mimir should store its metrics | 1 | -| `tempo_bucket` | string | Name of the bucket in which Tempo should store its traces | 1 | -| `alertmanager_revision` | number | Revision number of the charm | null | -| `catalogue_revision` | number | Revision number of the charm | null | -| `grafana_revision` | number | Revision number of the charm | null | -| `grafana_agent_revision` | number | Revision number of the charm | null | -| `loki_coordinator_revision` | number | Revision number of the charm | null | -| `loki_worker_revision` | number | Revision number of the charm | null | -| `mimir_coordinator_revision` | number | Revision number of the charm | null | -| `mimir_worker_revision` | number | Revision number of the charm | null | -| `ssc_revision` | number | Revision number of the charm | null | -| `s3_integrator_revision` | number | Revision number of the charm | null | -| `tempo_coordinator_revision` | number | Revision number of the charm | null | -| `tempo_worker_revision` | number | Revision number of the charm | null | -| `traefik_revision` | number | Revision number of the charm | null | - -### Outputs -Upon application, the module exports the following outputs: - -| Name | Type | Description | -| - | - | - | -| `alertmanager`| module | Alertmanager module | -| `catalogue`| module | Catalogue module | -| `grafana`| module | Grafana module | -| `grafana_agent`| module | Grafana agent module | -| `loki`| module | Loki module | -| `mimir`| module | Mimir module | -| `ssc`| module | Self-signed certificates module | -| `tempo`| module | Tempo module | -| `traefik`| module | Traefik module | - - -## Usage - - -### Basic usage - -Users should ensure that Terraform is aware of the `juju_model` dependency of the charm module. - -To deploy this module with its needed dependency, you can run `terraform apply -var="model=" -auto-approve`. This would deploy all COS HA solution modules in the same model. - -### High Availability - -By default, this Terraform module will deploy each worker with `3` unit. If you want to scale each Loki, Mimir or Tempo worker unit please check the variables available for that purpose in `variables.tf`. - -### Minimal sample deployment. - -In order to deploy COS with just one unit per worker charm create a `main.tf` file with the following content: - -```hcl -terraform { - required_version = ">= 1.5" - required_providers { - aws = { - source = "hashicorp/aws" - version = "~> 5.0" - } - null = { - source = "hashicorp/null" - version = "~> 3.0" - } - } -} - -# COS module that deploy the whole Canonical Observability Stack -module "cos" { - source = "git::https://github.com/canonical/observability//terraform/modules/cos" - model = "cos" - channel = "2/edge" - s3_integrator_channel = "2/edge" - ssc_channel = "1/edge" - traefik_channel = "latest/edge" - cloud = "self-managed" - use_tls = true - s3_endpoint = "http://S3_HOST_IP:8080" - s3_secret_key = "secret-key" - s3_access_key = "access-key" - loki_bucket = "loki" - mimir_bucket = "mimir" - tempo_bucket = "tempo" - loki_coordinator_units = 3 - loki_backend_units = 3 - loki_read_units = 3 - loki_write_units = 3 - mimir_coordinator_units = 3 - mimir_backend_units = 3 - mimir_read_units = 3 - mimir_write_units = 3 - tempo_coordinator_units = 3 - tempo_compactor_units = 3 - tempo_distributor_units = 3 - tempo_ingester_units = 3 - tempo_metrics_generator_units = 3 - tempo_querier_units = 3 - tempo_query_frontend_units = 3 - alertmanager_revision = null - catalogue_revision = null - grafana_revision = null - grafana_agent_revision = null - loki_coordinator_revision = null - loki_worker_revision = null - mimir_coordinator_revision = null - mimir_worker_revision = null - ssc_revision = null - s3_integrator_revision = 157 # FIXME: This is a temporary fix until the spec for the s3-integrator is stable. - tempo_coordinator_revision = null - tempo_worker_revision = null - traefik_revision = null -} -``` - -Then, use terraform to deploy the module: - -```shell -terraform init -terraform apply -``` - -Some minutes after running these two commands, we have a distributed COS deployment! - -```shell -$ juju status --relations -Model Controller Cloud/Region Version SLA Timestamp -cos microk8s microk8s/localhost 3.6.2 unsupported 20:16:42-03:00 - -App Version Status Scale Charm Channel Rev Address Exposed Message -alertmanager 0.27.0 active 1 alertmanager-k8s latest/edge 156 10.152.183.57 no -catalogue active 1 catalogue-k8s latest/edge 81 10.152.183.88 no -grafana 9.5.3 active 1 grafana-k8s latest/edge 141 10.152.183.138 no -grafana-agent 0.40.4 active 1 grafana-agent-k8s latest/edge 112 10.152.183.37 no grafana-dashboards-provider: off -loki active 3 loki-coordinator-k8s latest/edge 20 10.152.183.201 no -loki-backend 3.0.0 active 3 loki-worker-k8s latest/edge 34 10.152.183.112 no backend ready. -loki-read 3.0.0 active 3 loki-worker-k8s latest/edge 34 10.152.183.87 no read ready. -loki-s3-integrator active 1 s3-integrator latest/edge 139 10.152.183.20 no -loki-write 3.0.0 active 3 loki-worker-k8s latest/edge 34 10.152.183.167 no write ready. -mimir active 3 mimir-coordinator-k8s latest/edge 38 10.152.183.207 no -mimir-backend 2.13.0 active 3 mimir-worker-k8s latest/edge 45 10.152.183.45 no backend ready. -mimir-read 2.13.0 active 3 mimir-worker-k8s latest/edge 45 10.152.183.160 no read ready. -mimir-s3-integrator active 1 s3-integrator latest/edge 139 10.152.183.85 no -mimir-write 2.13.0 active 3 mimir-worker-k8s latest/edge 45 10.152.183.125 no write ready. -self-signed-certificates active 1 self-signed-certificates 1/edge 268 10.152.183.34 no -tempo active 3 tempo-coordinator-k8s latest/edge 70 10.152.183.72 no -tempo-compactor 2.7.1 active 3 tempo-worker-k8s latest/edge 52 10.152.183.99 no compactor ready. -tempo-distributor 2.7.1 active 3 tempo-worker-k8s latest/edge 52 10.152.183.162 no distributor ready. -tempo-ingester 2.7.1 active 3 tempo-worker-k8s latest/edge 52 10.152.183.195 no ingester ready. -tempo-metrics-generator 2.7.1 active 3 tempo-worker-k8s latest/edge 52 10.152.183.122 no metrics-generator ready. -tempo-querier 2.7.1 active 3 tempo-worker-k8s latest/edge 52 10.152.183.136 no querier ready. -tempo-query-frontend 2.7.1 active 3 tempo-worker-k8s latest/edge 52 10.152.183.105 no query-frontend ready. -tempo-s3-integrator active 1 s3-integrator latest/edge 139 10.152.183.121 no -traefik 2.11.0 active 1 traefik-k8s latest/edge 234 10.152.183.110 no Serving at 192.168.1.244 - -Unit Workload Agent Address Ports Message -alertmanager/0* active idle 10.1.167.134 -catalogue/0* active idle 10.1.167.150 -grafana-agent/0* active idle 10.1.167.149 grafana-dashboards-provider: off -grafana/0* active idle 10.1.167.173 -loki-backend/0* active idle 10.1.167.148 backend ready. -loki-backend/1 active idle 10.1.167.171 backend ready. -loki-backend/2 active idle 10.1.167.188 backend ready. -loki-read/0 active idle 10.1.167.153 read ready. -loki-read/1 active idle 10.1.167.180 read ready. -loki-read/2* active idle 10.1.167.183 read ready. -loki-s3-integrator/0* active idle 10.1.167.169 -loki-write/0* active idle 10.1.167.144 write ready. -loki-write/1 active idle 10.1.167.142 write ready. -loki-write/2 active idle 10.1.167.187 write ready. -loki/0* active idle 10.1.167.174 -mimir-backend/0* active idle 10.1.167.139 backend ready. -mimir-backend/1 active idle 10.1.167.128 backend ready. -mimir-backend/2 active idle 10.1.167.177 backend ready. -mimir-read/0* active idle 10.1.167.151 read ready. -mimir-read/1 active idle 10.1.167.163 read ready. -mimir-read/2 active idle 10.1.167.132 read ready. -mimir-s3-integrator/0* active idle 10.1.167.137 -mimir-write/0* active idle 10.1.167.152 write ready. -mimir-write/1 active idle 10.1.167.167 write ready. -mimir-write/2 active idle 10.1.167.143 write ready. -mimir/0* active idle 10.1.167.135 -self-signed-certificates/0* active idle 10.1.167.166 -tempo-compactor/0 active idle 10.1.167.181 compactor ready. -tempo-compactor/1* active idle 10.1.167.168 compactor ready. -tempo-compactor/2 active idle 10.1.167.129 compactor ready. -tempo-distributor/0* active idle 10.1.167.157 distributor ready. -tempo-distributor/1 active idle 10.1.167.131 distributor ready. -tempo-distributor/2 active idle 10.1.167.186 distributor ready. -tempo-ingester/0* active idle 10.1.167.191 ingester ready. -tempo-ingester/1 active idle 10.1.167.133 ingester ready. -tempo-ingester/2 active idle 10.1.167.179 ingester ready. -tempo-metrics-generator/0* active idle 10.1.167.147 metrics-generator ready. -tempo-metrics-generator/1 active idle 10.1.167.159 metrics-generator ready. -tempo-metrics-generator/2 active idle 10.1.167.146 metrics-generator ready. -tempo-querier/0 active idle 10.1.167.170 querier ready. -tempo-querier/1 active idle 10.1.167.140 querier ready. -tempo-querier/2* active idle 10.1.167.165 querier ready. -tempo-query-frontend/0* active idle 10.1.167.162 query-frontend ready. -tempo-query-frontend/1 active idle 10.1.167.190 query-frontend ready. -tempo-query-frontend/2 active idle 10.1.167.184 query-frontend ready. -tempo-s3-integrator/0* active idle 10.1.167.172 -tempo/0* active idle 10.1.167.189 -traefik/0* active idle 10.1.167.182 Serving at 192.168.1.244 - -Integration provider Requirer Interface Type Message -alertmanager:alerting loki:alertmanager alertmanager_dispatch regular -alertmanager:alerting mimir:alertmanager alertmanager_dispatch regular -alertmanager:grafana-dashboard grafana:grafana-dashboard grafana_dashboard regular -alertmanager:grafana-source grafana:grafana-source grafana_datasource regular -alertmanager:replicas alertmanager:replicas alertmanager_replica peer -alertmanager:self-metrics-endpoint grafana-agent:metrics-endpoint prometheus_scrape regular -catalogue:catalogue alertmanager:catalogue catalogue regular -catalogue:catalogue grafana:catalogue catalogue regular -catalogue:catalogue mimir:catalogue catalogue regular -catalogue:catalogue tempo:catalogue catalogue regular -catalogue:replicas catalogue:replicas catalogue_replica peer -grafana-agent:logging-provider loki:logging-consumer loki_push_api regular -grafana-agent:logging-provider tempo:logging loki_push_api regular -grafana-agent:peers grafana-agent:peers grafana_agent_replica peer -grafana-agent:tracing-provider grafana:charm-tracing tracing regular -grafana-agent:tracing-provider loki:charm-tracing tracing regular -grafana-agent:tracing-provider mimir:charm-tracing tracing regular -grafana:grafana grafana:grafana grafana_peers peer -grafana:replicas grafana:replicas grafana_replicas peer -loki-s3-integrator:s3-credentials loki:s3 s3 regular -loki-s3-integrator:s3-integrator-peers loki-s3-integrator:s3-integrator-peers s3-integrator-peers peer -loki:grafana-dashboards-provider grafana:grafana-dashboard grafana_dashboard regular -loki:grafana-source grafana:grafana-source grafana_datasource regular -loki:logging grafana-agent:logging-consumer loki_push_api regular -loki:loki-cluster loki-backend:loki-cluster loki_cluster regular -loki:loki-cluster loki-read:loki-cluster loki_cluster regular -loki:loki-cluster loki-write:loki-cluster loki_cluster regular -loki:self-metrics-endpoint grafana-agent:metrics-endpoint prometheus_scrape regular -mimir-s3-integrator:s3-credentials mimir:s3 s3 regular -mimir-s3-integrator:s3-integrator-peers mimir-s3-integrator:s3-integrator-peers s3-integrator-peers peer -mimir:grafana-dashboards-provider grafana:grafana-dashboard grafana_dashboard regular -mimir:grafana-source grafana:grafana-source grafana_datasource regular -mimir:mimir-cluster mimir-backend:mimir-cluster mimir_cluster regular -mimir:mimir-cluster mimir-read:mimir-cluster mimir_cluster regular -mimir:mimir-cluster mimir-write:mimir-cluster mimir_cluster regular -mimir:receive-remote-write grafana-agent:send-remote-write prometheus_remote_write regular -mimir:receive-remote-write tempo:send-remote-write prometheus_remote_write regular -mimir:self-metrics-endpoint grafana-agent:metrics-endpoint prometheus_scrape regular -tempo-s3-integrator:s3-credentials tempo:s3 s3 regular -tempo-s3-integrator:s3-integrator-peers tempo-s3-integrator:s3-integrator-peers s3-integrator-peers peer -tempo:grafana-source grafana:grafana-source grafana_datasource regular -tempo:metrics-endpoint grafana-agent:metrics-endpoint prometheus_scrape regular -tempo:peers tempo:peers tempo_peers peer -tempo:tempo-cluster tempo-compactor:tempo-cluster tempo_cluster regular -tempo:tempo-cluster tempo-distributor:tempo-cluster tempo_cluster regular -tempo:tempo-cluster tempo-ingester:tempo-cluster tempo_cluster regular -tempo:tempo-cluster tempo-metrics-generator:tempo-cluster tempo_cluster regular -tempo:tempo-cluster tempo-querier:tempo-cluster tempo_cluster regular -tempo:tempo-cluster tempo-query-frontend:tempo-cluster tempo_cluster regular -tempo:tracing grafana-agent:tracing tracing regular -traefik:ingress alertmanager:ingress ingress regular -traefik:ingress catalogue:ingress ingress regular -traefik:ingress loki:ingress ingress regular -traefik:ingress mimir:ingress ingress regular -traefik:peers traefik:peers traefik_peers peer -traefik:traefik-route grafana:ingress traefik_route regular -traefik:traefik-route tempo:ingress traefik_route regular -``` - -### Deploy COS on AWS EKS - -> **Note:** This deployment assumes that the required AWS infrastructure is already provisioned and that a Juju controller has been bootstrapped. -> Additionally, a Juju model must be ready in advance. -> -> See [provision AWS infrastructure](../aws-infra/README.md) - -In order to deploy COS on AWS, create a `main.tf` file with the following content. - -```hcl -# COS module that deploy the whole Canonical Observability Stack -module "cos" { - source = "git::https://github.com/canonical/observability//terraform/modules/cos" - model_name = var.model_name - channel = var.channel - s3_endpoint = var.s3_endpoint - s3_access_key = var.s3_access_key - s3_secret_key = var.s3_secret_key - loki_bucket = var.loki_bucket - mimir_bucket = var.mimir_bucket - tempo_bucket = var.tempo_bucket - loki_backend_units = var.loki_backend_units - loki_read_units = var.loki_read_units - loki_write_units = var.loki_write_units - mimir_backend_units = var.mimir_backend_units - mimir_read_units = var.mimir_read_units - mimir_write_units = var.mimir_write_units - tempo_compactor_units = var.tempo_compactor_units - tempo_distributor_units = var.tempo_distributor_units - tempo_ingester_units = var.tempo_ingester_units - tempo_metrics_generator_units = var.tempo_metrics_generator_units - tempo_querier_units = var.tempo_querier_units - tempo_query_frontend_units = var.tempo_query_frontend_units - cloud = var.cloud - ssc_channel = var.ssc_channel -} - -variable "channel" { - description = "Charms channel" - type = string - default = "latest/edge" -} - -variable "model_name" { - description = "Model name" - type = string -} - -variable "use_tls" { - description = "Specify whether to use TLS or not for coordinator-worker communication. By default, TLS is enabled through self-signed-certificates" - type = bool - default = true -} - -variable "s3_endpoint" { - description = "S3 endpoint" - type = string -} - -variable "s3_access_key" { - description = "S3 access key" - type = string - sensitive = true -} - -variable "s3_secret_key" { - description = "S3 secret key" - type = string - sensitive = true -} - -variable "loki_bucket" { - description = "Loki bucket name" - type = string - sensitive = true -} - -variable "mimir_bucket" { - description = "Mimir bucket name" - type = string - sensitive = true -} - -variable "tempo_bucket" { - description = "Tempo bucket name" - type = string - sensitive = true -} - -variable "loki_backend_units" { - description = "Number of Loki worker units with backend role" - type = number - default = 3 -} - -variable "loki_read_units" { - description = "Number of Loki worker units with read role" - type = number - default = 3 -} - -variable "loki_write_units" { - description = "Number of Loki worker units with write roles" - type = number - default = 3 -} - -variable "mimir_backend_units" { - description = "Number of Mimir worker units with backend role" - type = number - default = 3 -} - -variable "mimir_read_units" { - description = "Number of Mimir worker units with read role" - type = number - default = 3 -} - -variable "mimir_write_units" { - description = "Number of Mimir worker units with write role" - type = number - default = 3 -} - -variable "tempo_compactor_units" { - description = "Number of Tempo worker units with compactor role" - type = number - default = 3 -} - -variable "tempo_distributor_units" { - description = "Number of Tempo worker units with distributor role" - type = number - default = 3 -} - -variable "tempo_ingester_units" { - description = "Number of Tempo worker units with ingester role" - type = number - default = 3 -} - -variable "tempo_metrics_generator_units" { - description = "Number of Tempo worker units with metrics-generator role" - type = number - default = 3 -} - -variable "tempo_querier_units" { - description = "Number of Tempo worker units with querier role" - type = number - default = 3 -} -variable "tempo_query_frontend_units" { - description = "Number of Tempo worker units with query-frontend role" - type = number - default = 3 -} - -variable "cloud" { - description = "Kubernetes cloud or environment where this COS module will be deployed (e.g self-managed, aws)" - type = string - default = "self-managed" -} - -# ssc doesn't have a "latest" track for ubuntu@24.04 base. -variable "ssc_channel" { - description = "self-signed certificates charm channel." - type = string - default = "latest/edge" -} - -``` -Then, create a `aws.tfvars` file with the following content: - -```hcl -cloud = "aws" -# If you're deploying on an ubuntu@24.04 base -ssc_channel = "1/edge" -model = "" -s3_endpoint = "" -s3_access_key = "" -s3_secret_key = "" -loki_bucket = "" -mimir_bucket = "" -tempo_bucket = "" -``` - -Then, use terraform to deploy the module: -```bash -terraform init -terraform apply -var-file=aws.tfvars -``` diff --git a/terraform/modules/cos/main.tf b/terraform/modules/cos/main.tf deleted file mode 100644 index e9859ee8..00000000 --- a/terraform/modules/cos/main.tf +++ /dev/null @@ -1,607 +0,0 @@ -# -------------- # Applications -------------- - -module "alertmanager" { - source = "git::https://github.com/canonical/alertmanager-k8s-operator//terraform" - app_name = "alertmanager" - model = var.model - channel = var.channel - revision = var.alertmanager_revision -} - -module "catalogue" { - source = "git::https://github.com/canonical/catalogue-k8s-operator//terraform" - app_name = "catalogue" - model = var.model - channel = var.channel - revision = var.catalogue_revision -} - -module "grafana" { - source = "git::https://github.com/canonical/grafana-k8s-operator//terraform" - app_name = "grafana" - model = var.model - channel = var.channel - revision = var.grafana_revision -} - -module "grafana_agent" { - source = "git::https://github.com/canonical/grafana-agent-k8s-operator//terraform" - app_name = "grafana-agent" - model = var.model - channel = var.channel - revision = var.grafana_agent_revision -} - -module "loki" { - source = "git::https://github.com/canonical/observability//terraform/modules/loki" - model = var.model - channel = var.channel - s3_integrator_channel = var.s3_integrator_channel - s3_integrator_revision = var.s3_integrator_revision - coordinator_revision = var.loki_coordinator_revision - worker_revision = var.loki_worker_revision - coordinator_units = var.loki_coordinator_units - backend_units = var.loki_backend_units - read_units = var.loki_read_units - write_units = var.loki_write_units - s3_bucket = var.loki_bucket - s3_endpoint = var.s3_endpoint - s3_secret_key = var.s3_secret_key - s3_access_key = var.s3_access_key - anti_affinity = var.anti_affinity -} - -module "mimir" { - source = "git::https://github.com/canonical/observability//terraform/modules/mimir" - model = var.model - channel = var.channel - s3_integrator_channel = var.s3_integrator_channel - s3_integrator_revision = var.s3_integrator_revision - coordinator_revision = var.mimir_coordinator_revision - worker_revision = var.mimir_worker_revision - coordinator_units = var.mimir_coordinator_units - backend_units = var.mimir_backend_units - read_units = var.mimir_read_units - write_units = var.mimir_write_units - s3_bucket = var.mimir_bucket - s3_endpoint = var.s3_endpoint - s3_secret_key = var.s3_secret_key - s3_access_key = var.s3_access_key - anti_affinity = var.anti_affinity -} - -module "ssc" { - count = var.use_tls ? 1 : 0 - source = "git::https://github.com/canonical/self-signed-certificates-operator//terraform" - model = var.model - channel = var.ssc_channel - revision = var.ssc_revision -} - -module "tempo" { - source = "git::https://github.com/canonical/observability//terraform/modules/tempo" - model = var.model - channel = var.channel - s3_integrator_channel = var.s3_integrator_channel - s3_integrator_revision = var.s3_integrator_revision - coordinator_revision = var.tempo_coordinator_revision - worker_revision = var.tempo_worker_revision - coordinator_units = var.tempo_coordinator_units - compactor_units = var.tempo_compactor_units - distributor_units = var.tempo_distributor_units - ingester_units = var.tempo_ingester_units - metrics_generator_units = var.tempo_metrics_generator_units - querier_units = var.tempo_querier_units - query_frontend_units = var.tempo_query_frontend_units - s3_bucket = var.tempo_bucket - s3_endpoint = var.s3_endpoint - s3_access_key = var.s3_access_key - s3_secret_key = var.s3_secret_key - anti_affinity = var.anti_affinity -} - -module "traefik" { - source = "git::https://github.com/canonical/traefik-k8s-operator//terraform" - app_name = "traefik" - model = var.model - channel = var.traefik_channel - config = var.cloud == "aws" ? { "loadbalancer_annotations" = "service.beta.kubernetes.io/aws-load-balancer-scheme=internet-facing" } : {} - revision = var.traefik_revision -} - -# -------------- # Integrations -------------- - -# Provided by Alertmanager - -resource "juju_integration" "alertmanager_grafana_dashboards" { - model = var.model - - application { - name = module.alertmanager.app_name - endpoint = module.alertmanager.endpoints.grafana_dashboard - } - - application { - name = module.grafana.app_name - endpoint = module.grafana.endpoints.grafana_dashboard - } -} - -resource "juju_integration" "mimir_alertmanager" { - model = var.model - - application { - name = module.mimir.app_names.mimir_coordinator - endpoint = module.mimir.endpoints.alertmanager - } - - application { - name = module.alertmanager.app_name - endpoint = module.alertmanager.endpoints.alerting - } -} - -resource "juju_integration" "loki_alertmanager" { - model = var.model - - application { - name = module.loki.app_names.loki_coordinator - endpoint = module.loki.endpoints.alertmanager - } - - application { - name = module.alertmanager.app_name - endpoint = module.alertmanager.endpoints.alerting - } -} - -resource "juju_integration" "agent_alertmanager_metrics" { - model = var.model - - application { - name = module.alertmanager.app_name - endpoint = module.alertmanager.endpoints.self_metrics_endpoint - } - - application { - name = module.grafana_agent.app_name - endpoint = module.grafana_agent.endpoints.metrics_endpoint - } -} - -resource "juju_integration" "grafana_source_alertmanager" { - model = var.model - - application { - name = module.alertmanager.app_name - endpoint = module.alertmanager.endpoints.grafana_source - } - - application { - name = module.grafana.app_name - endpoint = module.grafana.endpoints.grafana_source - } -} - -# Provided by Mimir - -resource "juju_integration" "mimir_grafana_dashboards_provider" { - model = var.model - - application { - name = module.mimir.app_names.mimir_coordinator - endpoint = module.mimir.endpoints.grafana_dashboards_provider - } - - application { - name = module.grafana.app_name - endpoint = module.grafana.endpoints.grafana_dashboard - } -} - -resource "juju_integration" "mimir_grafana_source" { - model = var.model - - application { - name = module.mimir.app_names.mimir_coordinator - endpoint = module.mimir.endpoints.grafana_source - } - - application { - name = module.grafana.app_name - endpoint = module.grafana.endpoints.grafana_source - } -} - -resource "juju_integration" "mimir_tracing_grafana_agent_traicing_provider" { - model = var.model - - application { - name = module.mimir.app_names.mimir_coordinator - endpoint = module.mimir.endpoints.charm_tracing - } - - application { - name = module.grafana_agent.app_name - endpoint = module.grafana_agent.endpoints.tracing_provider - } -} - - -resource "juju_integration" "mimir_self_metrics_endpoint_grafana_agent_metrics_endpoint" { - model = var.model - - application { - name = module.mimir.app_names.mimir_coordinator - endpoint = module.mimir.endpoints.self_metrics_endpoint - } - - application { - name = module.grafana_agent.app_name - endpoint = module.grafana_agent.endpoints.metrics_endpoint - } -} - - -# Provided by Loki - -resource "juju_integration" "loki_grafana_dashboards_provider" { - model = var.model - - application { - name = module.loki.app_names.loki_coordinator - endpoint = module.loki.endpoints.grafana_dashboards_provider - } - - application { - name = module.grafana.app_name - endpoint = module.grafana.endpoints.grafana_dashboard - } -} - -resource "juju_integration" "loki_grafana_source" { - model = var.model - - application { - name = module.loki.app_names.loki_coordinator - endpoint = module.loki.endpoints.grafana_source - } - - application { - name = module.grafana.app_name - endpoint = module.grafana.endpoints.grafana_source - } -} - -resource "juju_integration" "loki_logging_consumer_grafana_agent_logging_provider" { - model = var.model - - application { - name = module.loki.app_names.loki_coordinator - endpoint = module.loki.endpoints.logging_consumer - } - - application { - name = module.grafana_agent.app_name - endpoint = module.grafana_agent.endpoints.logging_provider - } -} - -resource "juju_integration" "loki_logging_grafana_agent_logging_consumer" { - model = var.model - - application { - name = module.loki.app_names.loki_coordinator - endpoint = module.loki.endpoints.logging - } - - application { - name = module.grafana_agent.app_name - endpoint = module.grafana_agent.endpoints.logging_consumer - } -} - -resource "juju_integration" "loki_tracing_grafana_agent_traicing_provider" { - model = var.model - - application { - name = module.loki.app_names.loki_coordinator - endpoint = module.loki.endpoints.charm_tracing - } - - application { - name = module.grafana_agent.app_name - endpoint = module.grafana_agent.endpoints.tracing_provider - } -} - -# Provided by Tempo -resource "juju_integration" "tempo_grafana_source" { - model = var.model - - application { - name = module.tempo.app_names.tempo_coordinator - endpoint = module.tempo.endpoints.grafana_source - } - - application { - name = module.grafana.app_name - endpoint = module.grafana.endpoints.grafana_source - } -} - -resource "juju_integration" "tempo_tracing_grafana_agent_tracing" { - model = var.model - - application { - name = module.tempo.app_names.tempo_coordinator - endpoint = module.tempo.endpoints.tracing - } - - application { - name = module.grafana_agent.app_name - endpoint = module.grafana_agent.endpoints.tracing - } -} - -resource "juju_integration" "tempo_metrics_endpoint_grafana_agent_metrics_endpoint" { - model = var.model - - application { - name = module.tempo.app_names.tempo_coordinator - endpoint = module.tempo.endpoints.metrics_endpoint - } - - application { - name = module.grafana_agent.app_name - endpoint = module.grafana_agent.endpoints.metrics_endpoint - } -} - -resource "juju_integration" "tempo_logging_grafana_agent_logging_provider" { - model = var.model - - application { - name = module.tempo.app_names.tempo_coordinator - endpoint = module.tempo.endpoints.logging - } - - application { - name = module.grafana_agent.app_name - endpoint = module.grafana_agent.endpoints.logging_provider - } -} - -resource "juju_integration" "tempo_send_remote_write_mimir_receive_remote_write" { - model = var.model - - application { - name = module.tempo.app_names.tempo_coordinator - endpoint = module.tempo.endpoints.send-remote-write - } - - application { - name = module.mimir.app_names.mimir_coordinator - endpoint = module.mimir.endpoints.receive_remote_write - } -} - -# Provided by Catalogue - -resource "juju_integration" "alertmanager_catalogue" { - model = var.model - - application { - name = module.catalogue.app_name - endpoint = module.catalogue.endpoints.catalogue - } - - application { - name = module.alertmanager.app_name - endpoint = module.alertmanager.endpoints.catalogue - } -} - -resource "juju_integration" "grafana_catalogue" { - model = var.model - - application { - name = module.catalogue.app_name - endpoint = module.catalogue.endpoints.catalogue - } - - application { - name = module.grafana.app_name - endpoint = module.grafana.endpoints.catalogue - } -} - -resource "juju_integration" "tempo_catalogue" { - model = var.model - - application { - name = module.catalogue.app_name - endpoint = module.catalogue.endpoints.catalogue - } - - application { - name = module.tempo.app_names.tempo_coordinator - endpoint = module.tempo.endpoints.catalogue - } -} - -resource "juju_integration" "mimir_catalogue" { - model = var.model - - application { - name = module.catalogue.app_name - endpoint = module.catalogue.endpoints.catalogue - } - - application { - name = module.mimir.app_names.mimir_coordinator - endpoint = module.mimir.endpoints.catalogue - } -} - -# Provided by Traefik - -resource "juju_integration" "alertmanager_ingress" { - model = var.model - - application { - name = module.traefik.app_name - endpoint = module.traefik.endpoints.ingress - } - - application { - name = module.alertmanager.app_name - endpoint = module.alertmanager.endpoints.ingress - } -} - -resource "juju_integration" "catalogue_ingress" { - model = var.model - - application { - name = module.traefik.app_name - endpoint = module.traefik.endpoints.ingress - } - - application { - name = module.catalogue.app_name - endpoint = module.catalogue.endpoints.ingress - } -} - -resource "juju_integration" "grafana_ingress" { - model = var.model - - application { - name = module.traefik.app_name - endpoint = module.traefik.endpoints.traefik_route - } - - application { - name = module.grafana.app_name - endpoint = module.grafana.endpoints.ingress - } -} - -resource "juju_integration" "mimir_ingress" { - model = var.model - - application { - name = module.traefik.app_name - endpoint = module.traefik.endpoints.ingress - } - - application { - name = module.mimir.app_names.mimir_coordinator - endpoint = module.mimir.endpoints.ingress - } -} - -resource "juju_integration" "loki_ingress" { - model = var.model - - application { - name = module.traefik.app_name - endpoint = module.traefik.endpoints.ingress - } - - application { - name = module.loki.app_names.loki_coordinator - endpoint = module.loki.endpoints.ingress - } -} - -resource "juju_integration" "tempo_ingress" { - model = var.model - - application { - name = module.traefik.app_name - endpoint = module.traefik.endpoints.traefik_route - } - - application { - name = module.tempo.app_names.tempo_coordinator - endpoint = module.tempo.endpoints.ingress - } -} - -# Grafana agent - -resource "juju_integration" "agent_loki_metrics" { - model = var.model - - application { - name = module.loki.app_names.loki_coordinator - endpoint = module.loki.endpoints.self_metrics_endpoint - } - - application { - name = module.grafana_agent.app_name - endpoint = module.grafana_agent.endpoints.metrics_endpoint - } -} - -resource "juju_integration" "agent_mimir_metrics" { - model = var.model - - application { - name = module.mimir.app_names.mimir_coordinator - endpoint = module.mimir.endpoints.receive_remote_write - } - - application { - name = module.grafana_agent.app_name - endpoint = module.grafana_agent.endpoints.send_remote_write - } -} - -# Provided by Grafana - -resource "juju_integration" "grafana_tracing_grafana_agent_traicing_provider" { - model = var.model - - application { - name = module.grafana.app_name - endpoint = module.grafana.endpoints.charm_tracing - } - - application { - name = module.grafana_agent.app_name - endpoint = module.grafana_agent.endpoints.tracing_provider - } -} - -# -------------- # Offers -------------- - -resource "juju_offer" "alertmanager-karma-dashboard" { - name = "alertmanager-karma-dashboard" - model = var.model - application_name = module.alertmanager.app_name - endpoint = "karma-dashboard" -} - -resource "juju_offer" "grafana-dashboards" { - name = "grafana-dashboards" - model = var.model - application_name = module.grafana.app_name - endpoint = "grafana-dashboard" -} - -resource "juju_offer" "loki-logging" { - name = "loki-logging" - model = var.model - application_name = module.loki.app_names.loki_coordinator - endpoint = "logging" -} - -resource "juju_offer" "mimir-receive-remote-write" { - name = "mimir-receive-remote-write" - model = var.model - application_name = module.mimir.app_names.mimir_coordinator - endpoint = "receive-remote-write" -} diff --git a/terraform/modules/cos/outputs.tf b/terraform/modules/cos/outputs.tf deleted file mode 100644 index 0de44f9b..00000000 --- a/terraform/modules/cos/outputs.tf +++ /dev/null @@ -1,26 +0,0 @@ -# -------------- # Integration offers -------------- # - -output "offers" { - value = { - alertmanager_karma_dashboard = juju_offer.alertmanager-karma-dashboard - grafana_dashboards = juju_offer.grafana-dashboards - loki_logging = juju_offer.loki-logging - mimir_receive_remote_write = juju_offer.mimir-receive-remote-write - } -} - -# -------------- # Sub-modules -------------- # - -output "components" { - value = { - alertmanager = module.alertmanager - catalogue = module.catalogue - grafana = module.grafana - grafana_agent = module.grafana_agent - loki = module.loki - mimir = module.mimir - ssc = module.ssc - tempo = module.tempo - traefik = module.traefik - } -} diff --git a/terraform/modules/cos/variables.tf b/terraform/modules/cos/variables.tf deleted file mode 100644 index a100b5d7..00000000 --- a/terraform/modules/cos/variables.tf +++ /dev/null @@ -1,266 +0,0 @@ - -# the list of kubernetes clouds where this COS module can be deployed. -locals { - clouds = ["aws", "self-managed"] -} - -variable "channel" { - description = "Channel that the charms are (unless overwritten by external_channels) deployed from" - type = string -} - -variable "model" { - description = "Reference to an existing model resource or data source for the model to deploy to" - type = string -} - -variable "use_tls" { - description = "Specify whether to use TLS or not for coordinator-worker communication. By default, TLS is enabled through self-signed-certificates" - type = bool - default = true -} - -variable "cloud" { - description = "Kubernetes cloud or environment where this COS module will be deployed (e.g self-managed, aws)" - type = string - default = "self-managed" - validation { - condition = contains(local.clouds, var.cloud) - error_message = "Allowed values are: ${join(", ", local.clouds)}." - } -} - -variable "anti_affinity" { - description = "Enable anti-affinity constraints across all HA modules (Mimir, Loki, Tempo)" - type = bool - default = true -} - -# -------------- # External channels -------------- -# O11y does not own these charms, so we allow users to specify their channels directly. - -variable "ssc_channel" { - description = "Channel that the self-signed certificates charm is deployed from" - type = string - default = "1/stable" -} - -variable "s3_integrator_channel" { - description = "Channel that the s3-integrator charm is deployed from" - type = string - default = "2/edge" -} - -variable "traefik_channel" { - description = "Channel that the Traefik charm is deployed from" - type = string - default = "latest/stable" -} - -# -------------- # S3 storage configuration -------------- - -variable "s3_endpoint" { - description = "S3 endpoint" - type = string -} - -variable "s3_access_key" { - description = "S3 access-key credential" - type = string -} - -variable "s3_secret_key" { - description = "S3 secret-key credential" - type = string - sensitive = true -} - -variable "loki_bucket" { - description = "Loki bucket name" - type = string - sensitive = true -} - -variable "mimir_bucket" { - description = "Mimir bucket name" - type = string - sensitive = true -} - -variable "tempo_bucket" { - description = "Tempo bucket name" - type = string - sensitive = true -} - -# -------------- # Charm revisions -------------- - -variable "alertmanager_revision" { - description = "Revision number of the Alertmanager charm" - type = number - default = null -} - -variable "catalogue_revision" { - description = "Revision number of the Catalogue charm" - type = number - default = null -} - -variable "grafana_revision" { - description = "Revision number of the Grafana charm" - type = number - default = null -} - -variable "grafana_agent_revision" { - description = "Revision number of the Grafana agent charm" - type = number - default = null -} - -variable "loki_coordinator_revision" { - description = "Revision number of the Loki coordinator charm" - type = number - default = null -} - -variable "loki_worker_revision" { - description = "Revision number of the Loki worker charm" - type = number - default = null -} - -variable "mimir_coordinator_revision" { - description = "Revision number of the Mimir coordinator charm" - type = number - default = null -} - -variable "mimir_worker_revision" { - description = "Revision number of the Mimir worker charm" - type = number - default = null -} - -variable "ssc_revision" { - description = "Revision number of the self-signed certificates charm" - type = number - default = null -} - -variable "s3_integrator_revision" { - description = "Revision number of the s3-integrator charm" - type = number - default = 157 # FIXME: https://github.com/canonical/observability/issues/342 -} - -variable "tempo_coordinator_revision" { - description = "Revision number of the Tempo coordinator charm" - type = number - default = null -} - -variable "tempo_worker_revision" { - description = "Revision number of the Tempo worker charm" - type = number - default = null -} - -variable "traefik_revision" { - description = "Revision number of the Traefik charm" - type = number - default = null -} - -# -------------- # Charm unit counts -------------- - -variable "loki_backend_units" { - description = "Number of Loki worker units with backend role" - type = number - default = 3 -} - -variable "loki_read_units" { - description = "Number of Loki worker units with read role" - type = number - default = 3 -} - -variable "loki_write_units" { - description = "Number of Loki worker units with write roles" - type = number - default = 3 -} - -variable "loki_coordinator_units" { - description = "Number of Loki coordinator units" - type = number - default = 3 -} - -variable "mimir_backend_units" { - description = "Number of Mimir worker units with backend role" - type = number - default = 3 -} - -variable "mimir_read_units" { - description = "Number of Mimir worker units with read role" - type = number - default = 3 -} - -variable "mimir_write_units" { - description = "Number of Mimir worker units with write role" - type = number - default = 3 -} - -variable "mimir_coordinator_units" { - description = "Number of Mimir coordinator units" - type = number - default = 3 -} - -variable "tempo_compactor_units" { - description = "Number of Tempo worker units with compactor role" - type = number - default = 3 -} - -variable "tempo_distributor_units" { - description = "Number of Tempo worker units with distributor role" - type = number - default = 3 -} - -variable "tempo_ingester_units" { - description = "Number of Tempo worker units with ingester role" - type = number - default = 3 -} - -variable "tempo_metrics_generator_units" { - description = "Number of Tempo worker units with metrics-generator role" - type = number - default = 3 -} - -variable "tempo_querier_units" { - description = "Number of Tempo worker units with querier role" - type = number - default = 3 -} - -variable "tempo_query_frontend_units" { - description = "Number of Tempo worker units with query-frontend role" - type = number - default = 3 -} - -variable "tempo_coordinator_units" { - description = "Number of Tempo coordinator units" - type = number - default = 3 -} diff --git a/terraform/modules/cos/versions.tf b/terraform/modules/cos/versions.tf deleted file mode 100644 index cde98c1a..00000000 --- a/terraform/modules/cos/versions.tf +++ /dev/null @@ -1,9 +0,0 @@ -terraform { - required_version = ">= 1.5" - required_providers { - juju = { - source = "juju/juju" - version = ">= 0.14.0" - } - } -} \ No newline at end of file diff --git a/terraform/modules/loki/README.md b/terraform/modules/loki/README.md deleted file mode 100644 index d13e1b0b..00000000 --- a/terraform/modules/loki/README.md +++ /dev/null @@ -1,59 +0,0 @@ -# Terraform module for Loki solution - -This is a Terraform module facilitating the deployment of Loki solution, using the [Terraform juju provider](https://github.com/juju/terraform-provider-juju/). For more information, refer to the provider [documentation](https://registry.terraform.io/providers/juju/juju/latest/docs). - -The solution consists of the following Terraform modules: -- [loki-coordinator-k8s](https://github.com/canonical/loki-coordinator-k8s-operator): ingress, cluster coordination, single integration facade. -- [loki-worker-k8s](https://github.com/canonical/loki-worker-k8s-operator): run one or more Loki application components. -- [s3-integrator](https://github.com/canonical/s3-integrator): facade for S3 storage configurations. -- [self-signed-certificates](https://github.com/canonical/self-signed-certificates-operator): certificates operator to secure traffic with TLS. - -This Terraform module deploys Loki in its [microservices mode](https://grafana.com/docs/enterprise-logs/latest/get-started/deployment-modes/#microservices-mode), which runs each one of the required roles in distinct processes. - - -> [!NOTE] -> `s3-integrator` itself doesn't act as an S3 object storage system. For the HA solution to be functional, `s3-integrator` needs to point to an S3-like storage. See [this guide](https://discourse.charmhub.io/t/cos-lite-docs-set-up-minio/15211) to learn how to connect to an S3-like storage for traces. - -## Requirements -This module requires a `juju` model to be available. Refer to the [usage section](#usage) below for more details. - -## API - -### Inputs -The module offers the following configurable inputs: - -| Name | Type | Description | Default | -| - | - | - | - | -| `backend_units`| number | Number of Loki worker units with the backend role | 1 | -| `channel`| string | Channel that the charms are deployed from | | -| `model`| string | Name of the model that the charm is deployed on | | -| `read_units`| number | Number of Loki worker units with the read role | 1 | -| `write_units`| number | Number of Loki worker units with the write role | 1 | -| `coordinator_units`| number | Number of Loki coordinator units | 1 | -| `s3_integrator_name` | string | Name of the s3-integrator app | 1 | -| `s3_bucket` | string | Name of the bucke in which Loki stores logs | 1 | -| `s3_access_key` | string | Access key credential to connect to the S3 provider | 1 | -| `s3_secret_key` | string | Secret key credential to connect to the S3 provider | 1 | -| `s3_endpoint` | string | Endpoint of the S3 provider | 1 | - -### Outputs -Upon application, the module exports the following outputs: - -| Name | Type | Description | -| - | - | - | -| `app_names`| map(string) | Names of the deployed applications | -| `endpoints`| map(string) | Map of all `provides` and `requires` endpoints | - -## Usage - - -### Basic usage - -Users should ensure that Terraform is aware of the `juju_model` dependency of the charm module. - -To deploy this module with its needed dependency, you can run `terraform apply -var="model_name=" -auto-approve`. This would deploy all Loki HA solution modules in the same model. - -### Microservice deployment - -By default, this Terraform module will deploy each Loki worker with `1` unit. To configure the module to run `x` units of any worker role, you can run `terraform apply -var="model_name=" -var="_units=" -auto-approve`. -See [Loki worker roles](https://discourse.charmhub.io/t/loki-worker-roles/15484) for the recommended scale for each role. diff --git a/terraform/modules/loki/main.tf b/terraform/modules/loki/main.tf deleted file mode 100644 index 9977eafe..00000000 --- a/terraform/modules/loki/main.tf +++ /dev/null @@ -1,151 +0,0 @@ -resource "juju_secret" "loki_s3_credentials_secret" { - model = var.model - name = "loki_s3_credentials" - value = { - access-key = var.s3_access_key - secret-key = var.s3_secret_key - } - info = "Credentials for the S3 endpoint" -} - -resource "juju_access_secret" "loki_s3_secret_access" { - model = var.model - applications = [ - juju_application.s3_integrator.name - ] - secret_id = juju_secret.loki_s3_credentials_secret.secret_id -} - -# TODO: Replace s3_integrator resource to use its remote terraform module once available -resource "juju_application" "s3_integrator" { - name = var.s3_integrator_name - model = var.model - trust = true - - charm { - name = "s3-integrator" - channel = var.s3_integrator_channel - revision = var.s3_integrator_revision - } - config = { - endpoint = var.s3_endpoint - bucket = var.s3_bucket - credentials = "secret:${juju_secret.loki_s3_credentials_secret.secret_id}" - } - units = 1 -} - -module "loki_coordinator" { - source = "git::https://github.com/canonical/loki-coordinator-k8s-operator//terraform" - app_name = "loki" - model = var.model - channel = var.channel - revision = var.coordinator_revision - units = var.coordinator_units - constraints = var.anti_affinity ? "arch=amd64 tags=anti-pod.app.kubernetes.io/name=loki,anti-pod.topology-key=kubernetes.io/hostname" : null -} - -module "loki_backend" { - source = "git::https://github.com/canonical/loki-worker-k8s-operator//terraform" - app_name = var.backend_name - model = var.model - channel = var.channel - constraints = var.anti_affinity ? "arch=amd64 tags=anti-pod.app.kubernetes.io/name=${var.backend_name},anti-pod.topology-key=kubernetes.io/hostname" : null - config = { - role-backend = true - } - revision = var.worker_revision - units = var.backend_units - depends_on = [ - module.loki_coordinator - ] -} - -module "loki_read" { - source = "git::https://github.com/canonical/loki-worker-k8s-operator//terraform" - app_name = var.read_name - model = var.model - channel = var.channel - constraints = var.anti_affinity ? "arch=amd64 tags=anti-pod.app.kubernetes.io/name=${var.read_name},anti-pod.topology-key=kubernetes.io/hostname" : null - config = { - role-read = true - } - revision = var.worker_revision - units = var.read_units - depends_on = [ - module.loki_coordinator - ] -} - -module "loki_write" { - source = "git::https://github.com/canonical/loki-worker-k8s-operator//terraform" - app_name = var.write_name - model = var.model - channel = var.channel - constraints = var.anti_affinity ? "arch=amd64 tags=anti-pod.app.kubernetes.io/name=${var.write_name},anti-pod.topology-key=kubernetes.io/hostname" : null - config = { - role-write = true - } - revision = var.worker_revision - units = var.write_units - depends_on = [ - module.loki_coordinator - ] -} - -# -------------- # Integrations -------------- - -resource "juju_integration" "coordinator_to_s3_integrator" { - model = var.model - application { - name = juju_application.s3_integrator.name - endpoint = "s3-credentials" - } - - application { - name = module.loki_coordinator.app_name - endpoint = "s3" - } -} - -resource "juju_integration" "coordinator_to_backend" { - model = var.model - - application { - name = module.loki_coordinator.app_name - endpoint = "loki-cluster" - } - - application { - name = module.loki_backend.app_name - endpoint = "loki-cluster" - } -} - -resource "juju_integration" "coordinator_to_read" { - model = var.model - - application { - name = module.loki_coordinator.app_name - endpoint = "loki-cluster" - } - - application { - name = module.loki_read.app_name - endpoint = "loki-cluster" - } -} - -resource "juju_integration" "coordinator_to_write" { - model = var.model - - application { - name = module.loki_coordinator.app_name - endpoint = "loki-cluster" - } - - application { - name = module.loki_write.app_name - endpoint = "loki-cluster" - } -} diff --git a/terraform/modules/loki/outputs.tf b/terraform/modules/loki/outputs.tf deleted file mode 100644 index 27921bed..00000000 --- a/terraform/modules/loki/outputs.tf +++ /dev/null @@ -1,30 +0,0 @@ -output "app_names" { - value = merge( - { - loki_s3_integrator = juju_application.s3_integrator.name, - loki_coordinator = module.loki_coordinator.app_name, - loki_backend = module.loki_backend.app_name, - loki_read = module.loki_read.app_name, - loki_write = module.loki_write.app_name, - } - ) -} - -output "endpoints" { - value = { - # Requires - alertmanager = "alertmanager", - certificates = "certificates", - ingress = "ingress", - logging_consumer = "logging-consumer", - s3 = "s3", - charm_tracing = "charm-tracing", - # Provides - grafana_dashboards_provider = "grafana-dashboards-provider", - grafana_source = "grafana-source", - logging = "logging", - loki_cluster = "loki-cluster", - receive_remote_write = "receive-remote-write", - self_metrics_endpoint = "self-metrics-endpoint", - } -} diff --git a/terraform/modules/loki/variables.tf b/terraform/modules/loki/variables.tf deleted file mode 100644 index 5a55e11f..00000000 --- a/terraform/modules/loki/variables.tf +++ /dev/null @@ -1,128 +0,0 @@ -variable "model" { - description = "Reference to an existing model resource or data source for the model to deploy to" - type = string -} - -variable "channel" { - description = "Channel that the charms are deployed from" - type = string -} - -variable "s3_integrator_channel" { - description = "Channel that the s3-integrator charm is deployed from" - type = string - default = "2/edge" -} - -variable "coordinator_revision" { - description = "Revision number of the coordinator charm" - type = number - default = null -} - -variable "worker_revision" { - description = "Revision number of the worker charm" - type = number - default = null -} - -variable "s3_integrator_revision" { - description = "Revision number of the s3-integrator charm" - type = number - default = 157 # FIXME: https://github.com/canonical/observability/issues/342 -} - -variable "s3_bucket" { - description = "Bucket name" - type = string - default = "loki" -} - -variable "s3_access_key" { - description = "S3 access-key credential" - type = string -} - -variable "s3_secret_key" { - description = "S3 secret-key credential" - type = string - sensitive = true -} - -variable "s3_endpoint" { - description = "S3 endpoint" - type = string -} - -variable "anti_affinity" { - description = "Enable anti-affinity constraints." - type = bool - default = true -} - -# -------------- # App Names -------------- - -variable "backend_name" { - description = "Name of the Loki app with the backend role" - type = string - default = "loki-backend" -} - -variable "read_name" { - description = "Name of the Loki app with the read role" - type = string - default = "loki-read" -} - -variable "write_name" { - description = "Name of the Loki app with the write role" - type = string - default = "loki-write" -} - -variable "s3_integrator_name" { - description = "Name of the s3-integrator app" - type = string - default = "loki-s3-integrator" -} -# -------------- # Units Per App -------------- - -variable "backend_units" { - description = "Number of Loki worker units with the backend role" - type = number - default = 1 - validation { - condition = var.backend_units >= 1 - error_message = "The number of units must be greater than or equal to 1." - } -} - -variable "read_units" { - description = "Number of Loki worker units with the read role" - type = number - default = 1 - validation { - condition = var.read_units >= 1 - error_message = "The number of units must be greater than or equal to 1." - } -} - -variable "write_units" { - description = "Number of Loki worker units with the write role" - type = number - default = 1 - validation { - condition = var.write_units >= 1 - error_message = "The number of units must be greater than or equal to 1." - } -} - -variable "coordinator_units" { - description = "Number of Loki coordinator units" - type = number - default = 1 - validation { - condition = var.coordinator_units >= 1 - error_message = "The number of units must be greater than or equal to 1." - } -} diff --git a/terraform/modules/loki/versions.tf b/terraform/modules/loki/versions.tf deleted file mode 100644 index cde98c1a..00000000 --- a/terraform/modules/loki/versions.tf +++ /dev/null @@ -1,9 +0,0 @@ -terraform { - required_version = ">= 1.5" - required_providers { - juju = { - source = "juju/juju" - version = ">= 0.14.0" - } - } -} \ No newline at end of file diff --git a/terraform/modules/mimir/README.md b/terraform/modules/mimir/README.md deleted file mode 100644 index 99390bcf..00000000 --- a/terraform/modules/mimir/README.md +++ /dev/null @@ -1,60 +0,0 @@ -# Terraform module for Mimir solution - -This is a Terraform module facilitating the deployment of Mimir solution, using the [Terraform juju provider](https://github.com/juju/terraform-provider-juju/). For more information, refer to the provider [documentation](https://registry.terraform.io/providers/juju/juju/latest/docs). - -The solution consists of the following Terraform modules: -- [mimir-coordinator-k8s](https://github.com/canonical/mimir-coordinator-k8s-operator): ingress, cluster coordination, single integration facade. -- [mimir-worker-k8s](https://github.com/canonical/mimir-worker-k8s-operator): run one or more mimir application components. -- [s3-integrator](https://github.com/canonical/s3-integrator): facade for S3 storage configurations. -- [self-signed-certificates](https://github.com/canonical/self-signed-certificates-operator): certificates operator to secure traffic with TLS. - -This Terraform module deploys Mimir in its [microservices mode](https://grafana.com/docs/mimir/latest/references/architecture/deployment-modes/#microservices-mode), which runs each one of the required roles in distinct processes. - - -> [!NOTE] -> `s3-integrator` itself doesn't act as an S3 object storage system. For the HA solution to be functional, `s3-integrator` needs to point to an S3-like storage. See [this guide](https://discourse.charmhub.io/t/cos-lite-docs-set-up-minio/15211) to learn how to connect to an S3-like storage for traces. - -## Requirements -This module requires a `juju` model to be available. Refer to the [usage section](#usage) below for more details. - -## API - -### Inputs -The module offers the following configurable inputs: - -| Name | Type | Description | Default | -| - | - | - | - | -| `channel`| string | Channel that the charms are deployed from | | -| `model`| string | Name of the model that the charm is deployed on | | -| `coordinator_units`| number | Number of Mimir coordinator units | 1 | -| `read_units`| number | Number of Mimir worker units with the read role | 1 | -| `write_units`| number | Number of Mimir worker units with the write role | 1 | -| `backend_units`| number | Number of Mimir worker units with the backend role | 1 | -| `s3_integrator_name` | string | Name of the s3-integrator app | 1 | -| `s3_bucket` | string | Name of the bucke in which Mimir stores metrics | 1 | -| `s3_access_key` | string | Access key credential to connect to the S3 provider | 1 | -| `s3_secret_key` | string | Secret key credential to connect to the S3 provider | 1 | -| `s3_endpoint` | string | Endpoint of the S3 provider | 1 | - - -### Outputs -Upon application, the module exports the following outputs: - -| Name | Type | Description | -| - | - | - | -| `app_names`| map(string) | Names of the deployed applications | -| `endpoints`| map(string) | Map of all `provides` and `requires` endpoints | - -## Usage - - -### Basic usage - -Users should ensure that Terraform is aware of the `juju_model` dependency of the charm module. - -To deploy this module with its needed dependency, you can run `terraform apply -var="model_name=" -auto-approve`. This would deploy all Mimir HA solution modules in the same model. - -### Microservice deployment - -By default, this Terraform module will deploy each Mimir worker with `1` unit. To configure the module to run `x` units of any worker role, you can run `terraform apply -var="model_name=" -var="_units=" -auto-approve`. -See [Mimir worker roles](https://discourse.charmhub.io/t/mimir-worker-roles/15484) for the recommended scale for each role. diff --git a/terraform/modules/mimir/main.tf b/terraform/modules/mimir/main.tf deleted file mode 100644 index f1284846..00000000 --- a/terraform/modules/mimir/main.tf +++ /dev/null @@ -1,152 +0,0 @@ -resource "juju_secret" "mimir_s3_credentials_secret" { - model = var.model - name = "mimir_s3_credentials" - value = { - access-key = var.s3_access_key - secret-key = var.s3_secret_key - } - info = "Credentials for the S3 endpoint" -} - -resource "juju_access_secret" "mimir_s3_secret_access" { - model = var.model - applications = [ - juju_application.s3_integrator.name - ] - secret_id = juju_secret.mimir_s3_credentials_secret.secret_id -} - -# TODO: Replace s3_integrator resource to use its remote terraform module once available -resource "juju_application" "s3_integrator" { - name = var.s3_integrator_name - model = var.model - trust = true - - charm { - name = "s3-integrator" - channel = var.s3_integrator_channel - revision = var.s3_integrator_revision - } - config = { - endpoint = var.s3_endpoint - bucket = var.s3_bucket - credentials = "secret:${juju_secret.mimir_s3_credentials_secret.secret_id}" - } - units = 1 - -} - -module "mimir_coordinator" { - source = "git::https://github.com/canonical/mimir-coordinator-k8s-operator//terraform" - app_name = "mimir" - model = var.model - channel = var.channel - revision = var.coordinator_revision - units = var.coordinator_units - constraints = var.anti_affinity ? "arch=amd64 tags=anti-pod.app.kubernetes.io/name=mimir,anti-pod.topology-key=kubernetes.io/hostname" : null -} - -module "mimir_read" { - source = "git::https://github.com/canonical/mimir-worker-k8s-operator//terraform" - app_name = var.read_name - model = var.model - channel = var.channel - revision = var.worker_revision - constraints = var.anti_affinity ? "arch=amd64 tags=anti-pod.app.kubernetes.io/name=${var.read_name},anti-pod.topology-key=kubernetes.io/hostname" : null - config = { - role-read = true - } - units = var.read_units - depends_on = [ - module.mimir_coordinator - ] -} - -module "mimir_write" { - source = "git::https://github.com/canonical/mimir-worker-k8s-operator//terraform" - app_name = var.write_name - model = var.model - channel = var.channel - revision = var.worker_revision - constraints = var.anti_affinity ? "arch=amd64 tags=anti-pod.app.kubernetes.io/name=${var.write_name},anti-pod.topology-key=kubernetes.io/hostname" : null - config = { - role-write = true - } - units = var.write_units - depends_on = [ - module.mimir_coordinator - ] -} - -module "mimir_backend" { - source = "git::https://github.com/canonical/mimir-worker-k8s-operator//terraform" - app_name = var.backend_name - model = var.model - channel = var.channel - revision = var.worker_revision - constraints = var.anti_affinity ? "arch=amd64 tags=anti-pod.app.kubernetes.io/name=${var.backend_name},anti-pod.topology-key=kubernetes.io/hostname" : null - config = { - role-backend = true - } - units = var.backend_units - depends_on = [ - module.mimir_coordinator - ] -} - -# -------------- # Integrations -------------- - -resource "juju_integration" "coordinator_to_s3_integrator" { - model = var.model - application { - name = juju_application.s3_integrator.name - endpoint = "s3-credentials" - } - - application { - name = module.mimir_coordinator.app_name - endpoint = "s3" - } -} - -resource "juju_integration" "coordinator_to_read" { - model = var.model - - application { - name = module.mimir_coordinator.app_name - endpoint = "mimir-cluster" - } - - application { - name = module.mimir_read.app_name - endpoint = "mimir-cluster" - } -} - -resource "juju_integration" "coordinator_to_write" { - model = var.model - - application { - name = module.mimir_coordinator.app_name - endpoint = "mimir-cluster" - } - - application { - name = module.mimir_write.app_name - endpoint = "mimir-cluster" - } -} - -resource "juju_integration" "coordinator_to_backend" { - model = var.model - - application { - name = module.mimir_coordinator.app_name - endpoint = "mimir-cluster" - } - - application { - name = module.mimir_backend.app_name - endpoint = "mimir-cluster" - } -} diff --git a/terraform/modules/mimir/outputs.tf b/terraform/modules/mimir/outputs.tf deleted file mode 100644 index d3603364..00000000 --- a/terraform/modules/mimir/outputs.tf +++ /dev/null @@ -1,31 +0,0 @@ -output "app_names" { - value = merge( - { - mimir_s3_integrator = juju_application.s3_integrator.name, - mimir_coordinator = module.mimir_coordinator.app_name, - mimir_read = module.mimir_read.app_name, - mimir_write = module.mimir_write.app_name, - mimir_backend = module.mimir_backend.app_name, - } - ) -} - -output "endpoints" { - value = { - # Requires - alertmanager = "alertmanager", - certificates = "certificates", - ingress = "ingress", - logging_consumer = "logging-consumer", - s3 = "s3", - charm_tracing = "charm-tracing", - catalogue = "catalogue", - - # Provides - grafana_dashboards_provider = "grafana-dashboards-provider", - grafana_source = "grafana-source", - mimir_cluster = "mimir-cluster", - receive_remote_write = "receive-remote-write", - self_metrics_endpoint = "self-metrics-endpoint", - } -} diff --git a/terraform/modules/mimir/variables.tf b/terraform/modules/mimir/variables.tf deleted file mode 100644 index c6d35842..00000000 --- a/terraform/modules/mimir/variables.tf +++ /dev/null @@ -1,129 +0,0 @@ -variable "model" { - description = "Reference to an existing model resource or data source for the model to deploy to" - type = string -} - -variable "channel" { - description = "Channel that the charms are deployed from" - type = string -} - -variable "s3_integrator_channel" { - description = "Channel that the s3-integrator charm is deployed from" - type = string - default = "2/edge" -} - -variable "coordinator_revision" { - description = "Revision number of the coordinator charm" - type = number - default = null -} - -variable "worker_revision" { - description = "Revision number of the worker charm" - type = number - default = null -} - -variable "s3_integrator_revision" { - description = "Revision number of the s3-integrator charm" - type = number - default = 157 # FIXME: https://github.com/canonical/observability/issues/342 -} - -variable "s3_bucket" { - description = "Bucket name" - type = string - default = "mimir" -} - -variable "s3_access_key" { - description = "S3 access-key credential" - type = string -} - -variable "s3_secret_key" { - description = "S3 secret-key credential" - type = string - sensitive = true -} - -variable "s3_endpoint" { - description = "S3 endpoint" - type = string -} - -variable "anti_affinity" { - description = "Enable anti-affinity constraints." - type = bool - default = true -} - -# -------------- # App Names -------------- - -variable "read_name" { - description = "Name of the Mimir read (meta role) app" - type = string - default = "mimir-read" -} - -variable "write_name" { - description = "Name of the Mimir write (meta role) app" - type = string - default = "mimir-write" -} - -variable "backend_name" { - description = "Name of the Mimir backend (meta role) app" - type = string - default = "mimir-backend" -} - -variable "s3_integrator_name" { - description = "Name of the s3-integrator app" - type = string - default = "mimir-s3-integrator" -} - -# -------------- # Units Per App -------------- - -variable "read_units" { - description = "Number of Mimir worker units with the read meta role" - type = number - default = 1 - validation { - condition = var.read_units >= 1 - error_message = "The number of units must be greater than or equal to 1." - } -} - -variable "write_units" { - description = "Number of Mimir worker units with the write meta role" - type = number - default = 1 - validation { - condition = var.write_units >= 1 - error_message = "The number of units must be greater than or equal to 1." - } -} - -variable "backend_units" { - description = "Number of Mimir worker units with the backend meta role" - type = number - default = 1 - validation { - condition = var.backend_units >= 1 - error_message = "The number of units must be greater than or equal to 1." - } -} - -variable "coordinator_units" { - description = "Number of Mimir coordinator units" - type = number - default = 1 - validation { - condition = var.coordinator_units >= 1 - error_message = "The number of units must be greater than or equal to 1." - } -} diff --git a/terraform/modules/mimir/versions.tf b/terraform/modules/mimir/versions.tf deleted file mode 100644 index cde98c1a..00000000 --- a/terraform/modules/mimir/versions.tf +++ /dev/null @@ -1,9 +0,0 @@ -terraform { - required_version = ">= 1.5" - required_providers { - juju = { - source = "juju/juju" - version = ">= 0.14.0" - } - } -} \ No newline at end of file diff --git a/terraform/modules/minio/main.tf b/terraform/modules/minio/main.tf deleted file mode 100644 index f8edccb5..00000000 --- a/terraform/modules/minio/main.tf +++ /dev/null @@ -1,43 +0,0 @@ -resource "juju_application" "minio" { - # Coordinator requires s3 - name = var.minio_app - model = var.model_name - trust = true - - charm { - name = var.minio_app - channel = var.channel - } - units = 1 - - config = { - access-key = var.minio_user - secret-key = var.minio_password - } -} - -resource "null_resource" "s3management" { - triggers = { - # model_name = var.model_name - always_run = timestamp() - } - provisioner "local-exec" { - environment = { - MINIO_USER = var.minio_user - MINIO_PASSWORD = var.minio_password - } - command = <<-EOT - bash "${path.module}/scripts/s3management.sh" \ - --model-name ${var.model_name} \ - --minio-app ${var.minio_app} \ - --mc-binary-url ${var.mc_binary_url} \ - --minio-url "http://${var.minio_app}-0.${var.minio_app}-endpoints.${var.model_name}.svc.cluster.local:9000" \ - --loki-bucket ${var.loki.bucket_name} \ - --mimir-bucket ${var.mimir.bucket_name} \ - --tempo-bucket ${var.tempo.bucket_name} \ - --loki-integrator ${var.loki.s3_integrator_name} \ - --mimir-integrator ${var.mimir.s3_integrator_name} \ - --tempo-integrator ${var.tempo.s3_integrator_name} - EOT - } -} \ No newline at end of file diff --git a/terraform/modules/minio/outputs.tf b/terraform/modules/minio/outputs.tf deleted file mode 100644 index 7d42f35f..00000000 --- a/terraform/modules/minio/outputs.tf +++ /dev/null @@ -1,4 +0,0 @@ -output "minio_name" { - value = var.minio_app - description = "The application name for Minio" -} diff --git a/terraform/modules/minio/scripts/s3management.sh b/terraform/modules/minio/scripts/s3management.sh deleted file mode 100755 index ffc0a4d1..00000000 --- a/terraform/modules/minio/scripts/s3management.sh +++ /dev/null @@ -1,112 +0,0 @@ -#!/bin/bash - -set -euo pipefail - -# Variables -MODEL_NAME="" -MINIO_APP="" -MC_BINARY_URL="" -MINIO_URL="" -MINIO_USER="${MINIO_USER:-}" -MINIO_PASSWORD="${MINIO_PASSWORD:-}" -LOKI_BUCKET="" -MIMIR_BUCKET="" -TEMPO_BUCKET="" -LOKI_INTEGRATOR="" -MIMIR_INTEGRATOR="" -TEMPO_INTEGRATOR="" - -MC_BINARY="/root/minio/mc" - -# Parse arguments -while [[ "$#" -gt 0 ]]; do - case $1 in - --model-name) MODEL_NAME="$2"; shift ;; - --minio-app) MINIO_APP="$2"; shift ;; - --mc-binary-url) MC_BINARY_URL="$2"; shift ;; - --minio-url) MINIO_URL="$2"; shift ;; - --minio-user) MINIO_USER="$2"; shift ;; - --minio-password) MINIO_PASSWORD="$2"; shift ;; - --loki-bucket) LOKI_BUCKET="$2"; shift ;; - --mimir-bucket) MIMIR_BUCKET="$2"; shift ;; - --tempo-bucket) TEMPO_BUCKET="$2"; shift ;; - --loki-integrator) LOKI_INTEGRATOR="$2"; shift ;; - --mimir-integrator) MIMIR_INTEGRATOR="$2"; shift ;; - --tempo-integrator) TEMPO_INTEGRATOR="$2"; shift ;; - *) echo "Unknown parameter passed: $1"; exit 1 ;; - esac - shift -done - -# Credentials validation -if [[ -z "$MINIO_USER" || -z "$MINIO_PASSWORD" ]]; then - echo "Error: MINIO_USER and MINIO_PASSWORD must be set either as arguments or environment variables." - exit 1 -fi - - -# Functions -wait_for_app() { - local app="$1" - local status="${2:-active}" - - echo "Waiting for application $app in model $MODEL_NAME..." - juju wait-for application "$app" -m "$MODEL_NAME" --query="status=='$status'" --timeout 20m -} - -bucket_exists() { - local bucket_name="$1" - juju ssh -m "$MODEL_NAME" "$MINIO_APP/leader" "$MC_BINARY" ls local/ | grep -q "$bucket_name" -} - -mc_exists() { - echo "Checking if mc is already downlaoded..." - juju ssh -m "$MODEL_NAME" "$MINIO_APP/leader" ls "$MC_BINARY" -} - -configure_s3() { - local bucket_name="$1" - local integrator="$2" - - - echo "Checking if bucket $bucket_name exists..." - if bucket_exists "$bucket_name"; then - echo "Bucket $bucket_name already exists. Skipping creation." - else - echo "Creating bucket $bucket_name..." - juju ssh -m "$MODEL_NAME" "$MINIO_APP/leader" "$MC_BINARY" mb local/"$bucket_name" - fi - - wait_for_app "$integrator" "blocked" - - echo "Configuring $integrator..." - juju config "$integrator" endpoint="$MINIO_URL" bucket="$bucket_name" - - echo "Syncing S3 credentials for $integrator..." - juju run -m "$MODEL_NAME" "$integrator/leader" sync-s3-credentials access-key="$MINIO_USER" secret-key="$MINIO_PASSWORD" -} - -configure_minio() { - # Wait for MinIO app - wait_for_app "$MINIO_APP" - - if mc_exists; then - echo "MinIO client is already downloaded. Skipping download." - else - echo "Downloading MinIO client..." - juju ssh -m "$MODEL_NAME" "$MINIO_APP/leader" curl "$MC_BINARY_URL" --create-dirs -o "$MC_BINARY" - fi - - juju ssh -m "$MODEL_NAME" "$MINIO_APP/leader" chmod +x "$MC_BINARY" - juju ssh -m "$MODEL_NAME" "$MINIO_APP/leader" "$MC_BINARY" alias set local "$MINIO_URL" "$MINIO_USER" "$MINIO_PASSWORD" -} - -# Configure MinIO -configure_minio - -# Configure buckets and sync credentials -configure_s3 "$LOKI_BUCKET" "$LOKI_INTEGRATOR" -configure_s3 "$MIMIR_BUCKET" "$MIMIR_INTEGRATOR" -configure_s3 "$TEMPO_BUCKET" "$TEMPO_INTEGRATOR" - -echo "S3 configuration complete!" diff --git a/terraform/modules/minio/variables.tf b/terraform/modules/minio/variables.tf deleted file mode 100644 index 8649e8d2..00000000 --- a/terraform/modules/minio/variables.tf +++ /dev/null @@ -1,47 +0,0 @@ -variable "channel" { - description = "Charms channel" - type = string - default = "latest/edge" -} - -variable "model_name" { - description = "Model name" - type = string -} - -variable "minio_app" { - description = "Minio user" - type = string - default = "minio" -} - -variable "minio_user" { - description = "Minio user" - type = string -} - -variable "minio_password" { - description = "Minio Password" - type = string -} - -variable "mc_binary_url" { - description = "mc binary URL" - type = string - default = "https://dl.min.io/client/mc/release/linux-amd64/mc" -} - -variable "loki" { - description = "Configuration outputs from the Loki module, including bucket and integrator details." - type = any -} - -variable "mimir" { - description = "Configuration outputs from the Mimir module, including bucket and integrator details." - type = any -} - -variable "tempo" { - description = "Configuration outputs from the Tempo module, including bucket and integrator details." - type = any -} diff --git a/terraform/modules/minio/version.tf b/terraform/modules/minio/version.tf deleted file mode 100644 index 77b64403..00000000 --- a/terraform/modules/minio/version.tf +++ /dev/null @@ -1,9 +0,0 @@ -terraform { - required_version = ">= 1.5" - required_providers { - juju = { - source = "juju/juju" - version = "~> 0.14" - } - } -} \ No newline at end of file diff --git a/terraform/modules/tempo/README.md b/terraform/modules/tempo/README.md deleted file mode 100644 index 47ad1aee..00000000 --- a/terraform/modules/tempo/README.md +++ /dev/null @@ -1,63 +0,0 @@ -# Terraform module for Tempo solution - -This is a Terraform module facilitating the deployment of Tempo solution, using the [Terraform juju provider](https://github.com/juju/terraform-provider-juju/). For more information, refer to the provider [documentation](https://registry.terraform.io/providers/juju/juju/latest/docs). - -The solution consists of the following Terraform modules: -- [tempo-coordinator-k8s](https://github.com/canonical/tempo-coordinator-k8s-operator): ingress, cluster coordination, single integration facade. -- [tempo-worker-k8s](https://github.com/canonical/tempo-worker-k8s-operator): run one or more tempo application components. -- [s3-integrator](https://github.com/canonical/s3-integrator): facade for S3 storage configurations. -- [self-signed-certificates](https://github.com/canonical/self-signed-certificates-operator): certificates operator to secure traffic with TLS. - -This Terraform module deploys Tempo in its [microservices mode](https://grafana.com/docs/tempo/latest/setup/deployment/#microservices-mode), which runs each one of the required roles in distinct processes. [See](https://discourse.charmhub.io/t/topic/15484) to understand more about Tempo roles. - - -> [!NOTE] -> `s3-integrator` itself doesn't act as an S3 object storage system. For the solution to be functional, `s3-integrator` needs to point to an S3-like storage. See [this guide](https://discourse.charmhub.io/t/cos-lite-docs-set-up-minio/15211) to learn how to connect to an S3-like storage for traces. - -## Requirements -This module requires a `juju` model to be available. Refer to the [usage section](#usage) below for more details. - -## API - -### Inputs -The module offers the following configurable inputs: - -| Name | Type | Description | Default | -| - | - | - | - | -| `channel`| string | Channel that the charms are deployed from | | -| `compactor_units`| number | Number of Tempo worker units with compactor role | 1 | -| `distributor_units`| number | Number of Tempo worker units with distributor role | 1 | -| `ingester_units`| number | Number of Tempo worker units with ingester role | 1 | -| `metrics_generator_units`| number | Number of Tempo worker units with metrics-generator role | 1 | -| `model`| string | Name of the model that the charm is deployed on | | -| `querier_units`| number | Number of Tempo worker units with querier role | 1 | -| `query_frontend_units`| number | Number of Tempo worker units with query-frontend role | 1 | -| `coordinator_units`| number | Number of Tempo coordinator units | 1 | -| `s3_integrator_name` | string | Name of the s3-integrator app | 1 | -| `s3_bucket` | string | Name of the bucke in which Tempo stores traces | 1 | -| `s3_access_key` | string | Access key credential to connect to the S3 provider | 1 | -| `s3_secret_key` | string | Secret key credential to connect to the S3 provider | 1 | -| `s3_endpoint` | string | Endpoint of the S3 provider | 1 | - - -### Outputs -Upon application, the module exports the following outputs: - -| Name | Type | Description | -| - | - | - | -| `app_names`| map(string) | Names of the deployed applications | -| `endpoints`| map(string) | Map of all `provides` and `requires` endpoints | - -## Usage - - -### Basic usage - -Users should ensure that Terraform is aware of the `juju_model` dependency of the charm module. - -To deploy this module with its needed dependency, you can run `terraform apply -var="model_name=" -auto-approve`. This would deploy all Tempo components in the same model. - -### Microservice deployment - -By default, this Terraform module will deploy each Tempo worker with `1` unit. To configure the module to run `x` units of any worker role, you can run `terraform apply -var="model_name=" -var="_units=" -auto-approve`. -See [Tempo worker roles](https://discourse.charmhub.io/t/tempo-worker-roles/15484) for the recommended scale for each role. diff --git a/terraform/modules/tempo/main.tf b/terraform/modules/tempo/main.tf deleted file mode 100644 index db82bac9..00000000 --- a/terraform/modules/tempo/main.tf +++ /dev/null @@ -1,247 +0,0 @@ -resource "juju_secret" "tempo_s3_credentials_secret" { - model = var.model - name = "tempo_s3_credentials" - value = { - access-key = var.s3_access_key - secret-key = var.s3_secret_key - } - info = "Credentials for the S3 endpoint" -} - -resource "juju_access_secret" "tempo_s3_secret_access" { - model = var.model - applications = [ - juju_application.s3_integrator.name - ] - secret_id = juju_secret.tempo_s3_credentials_secret.secret_id -} - -# TODO: Replace s3_integrator resource to use its remote terraform module once available -resource "juju_application" "s3_integrator" { - name = var.s3_integrator_name - model = var.model - trust = true - - charm { - name = "s3-integrator" - channel = var.s3_integrator_channel - revision = var.s3_integrator_revision - } - config = { - endpoint = var.s3_endpoint - bucket = var.s3_bucket - credentials = "secret:${juju_secret.tempo_s3_credentials_secret.secret_id}" - } - units = 1 -} - -module "tempo_coordinator" { - source = "git::https://github.com/canonical/tempo-coordinator-k8s-operator//terraform" - model = var.model - channel = var.channel - revision = var.coordinator_revision - units = var.coordinator_units - constraints = var.anti_affinity ? "arch=amd64 tags=anti-pod.app.kubernetes.io/name=tempo,anti-pod.topology-key=kubernetes.io/hostname" : null -} - -module "tempo_querier" { - source = "git::https://github.com/canonical/tempo-worker-k8s-operator//terraform" - app_name = var.querier_name - model = var.model - channel = var.channel - constraints = var.anti_affinity ? "arch=amd64 tags=anti-pod.app.kubernetes.io/name=${var.querier_name},anti-pod.topology-key=kubernetes.io/hostname" : null - config = { - role-all = false - role-querier = true - } - revision = var.worker_revision - units = var.querier_units - depends_on = [ - module.tempo_coordinator - ] -} - -module "tempo_query_frontend" { - source = "git::https://github.com/canonical/tempo-worker-k8s-operator//terraform" - app_name = var.query_frontend_name - model = var.model - channel = var.channel - constraints = var.anti_affinity ? "arch=amd64 tags=anti-pod.app.kubernetes.io/name=${var.query_frontend_name},anti-pod.topology-key=kubernetes.io/hostname" : null - config = { - role-all = false - role-query-frontend = true - } - revision = var.worker_revision - units = var.query_frontend_units - depends_on = [ - module.tempo_coordinator - ] -} - -module "tempo_ingester" { - source = "git::https://github.com/canonical/tempo-worker-k8s-operator//terraform" - app_name = var.ingester_name - model = var.model - channel = var.channel - constraints = var.anti_affinity ? "arch=amd64 tags=anti-pod.app.kubernetes.io/name=${var.ingester_name},anti-pod.topology-key=kubernetes.io/hostname" : null - config = { - role-all = false - role-ingester = true - } - revision = var.worker_revision - units = var.ingester_units - depends_on = [ - module.tempo_coordinator - ] -} - -module "tempo_distributor" { - source = "git::https://github.com/canonical/tempo-worker-k8s-operator//terraform" - app_name = var.distributor_name - model = var.model - channel = var.channel - constraints = var.anti_affinity ? "arch=amd64 tags=anti-pod.app.kubernetes.io/name=${var.distributor_name},anti-pod.topology-key=kubernetes.io/hostname" : null - config = { - role-all = false - role-distributor = true - } - revision = var.worker_revision - units = var.distributor_units - depends_on = [ - module.tempo_coordinator - ] -} - -module "tempo_compactor" { - source = "git::https://github.com/canonical/tempo-worker-k8s-operator//terraform" - app_name = var.compactor_name - model = var.model - channel = var.channel - constraints = var.anti_affinity ? "arch=amd64 tags=anti-pod.app.kubernetes.io/name=${var.compactor_name},anti-pod.topology-key=kubernetes.io/hostname" : null - config = { - role-all = false - role-compactor = true - } - revision = var.worker_revision - units = var.compactor_units - depends_on = [ - module.tempo_coordinator - ] -} - -module "tempo_metrics_generator" { - source = "git::https://github.com/canonical/tempo-worker-k8s-operator//terraform" - app_name = var.metrics_generator_name - model = var.model - channel = var.channel - constraints = var.anti_affinity ? "arch=amd64 tags=anti-pod.app.kubernetes.io/name=${var.metrics_generator_name},anti-pod.topology-key=kubernetes.io/hostname" : null - config = { - role-all = false - role-metrics-generator = true - } - revision = var.worker_revision - units = var.metrics_generator_units - depends_on = [ - module.tempo_coordinator - ] -} - -#Integrations - -resource "juju_integration" "coordinator_to_s3_integrator" { - model = var.model - - application { - name = juju_application.s3_integrator.name - endpoint = "s3-credentials" - } - - application { - name = module.tempo_coordinator.app_name - endpoint = "s3" - } -} - -resource "juju_integration" "coordinator_to_querier" { - model = var.model - - application { - name = module.tempo_coordinator.app_name - endpoint = "tempo-cluster" - } - - application { - name = module.tempo_querier.app_name - endpoint = "tempo-cluster" - } -} - -resource "juju_integration" "coordinator_to_query_frontend" { - model = var.model - - application { - name = module.tempo_coordinator.app_name - endpoint = "tempo-cluster" - } - - application { - name = module.tempo_query_frontend.app_name - endpoint = "tempo-cluster" - } -} - -resource "juju_integration" "coordinator_to_ingester" { - model = var.model - - application { - name = module.tempo_coordinator.app_name - endpoint = "tempo-cluster" - } - - application { - name = module.tempo_ingester.app_name - endpoint = "tempo-cluster" - } -} - -resource "juju_integration" "coordinator_to_distributor" { - model = var.model - - application { - name = module.tempo_coordinator.app_name - endpoint = "tempo-cluster" - } - - application { - name = module.tempo_distributor.app_name - endpoint = "tempo-cluster" - } -} - -resource "juju_integration" "coordinator_to_compactor" { - model = var.model - - application { - name = module.tempo_coordinator.app_name - endpoint = "tempo-cluster" - } - - application { - name = module.tempo_compactor.app_name - endpoint = "tempo-cluster" - } -} - -resource "juju_integration" "coordinator_to_metrics_generator" { - model = var.model - - application { - name = module.tempo_coordinator.app_name - endpoint = "tempo-cluster" - } - - application { - name = module.tempo_metrics_generator.app_name - endpoint = "tempo-cluster" - } -} diff --git a/terraform/modules/tempo/outputs.tf b/terraform/modules/tempo/outputs.tf deleted file mode 100644 index a4579bec..00000000 --- a/terraform/modules/tempo/outputs.tf +++ /dev/null @@ -1,33 +0,0 @@ -output "app_names" { - value = merge( - { - tempo_s3_integrator = juju_application.s3_integrator.name, - tempo_coordinator = module.tempo_coordinator.app_name, - tempo_querier = module.tempo_querier.app_name, - tempo_query_frontend = module.tempo_query_frontend.app_name, - tempo_ingester = module.tempo_ingester.app_name, - tempo_distributor = module.tempo_distributor.app_name, - tempo_compactor = module.tempo_compactor.app_name, - tempo_metrics_generator = module.tempo_metrics_generator.app_name, - } - ) -} - -output "endpoints" { - value = { - # Requires - logging = "logging", - ingress = "ingress", - certificates = "certificates", - send-remote-write = "send-remote-write", - receive_datasource = "receive-datasource" - catalogue = "catalogue", - - # Provides - tempo_cluster = "tempo-cluster" - grafana_dashboard = "grafana-dashboard", - grafana_source = "grafana-source", - metrics_endpoint = "metrics-endpoint", - tracing = "tracing", - } -} diff --git a/terraform/modules/tempo/variables.tf b/terraform/modules/tempo/variables.tf deleted file mode 100644 index 42db6db6..00000000 --- a/terraform/modules/tempo/variables.tf +++ /dev/null @@ -1,176 +0,0 @@ -variable "model" { - description = "Reference to an existing model resource or data source for the model to deploy to" - type = string -} - -variable "channel" { - description = "Channel that the charms are deployed from" - type = string -} - -variable "s3_integrator_channel" { - description = "Channel that the s3-integrator charm is deployed from" - type = string - default = "2/edge" -} - -variable "coordinator_revision" { - description = "Revision number of the coordinator charm" - type = number - default = null -} - -variable "worker_revision" { - description = "Revision number of the worker charm" - type = number - default = null -} - -variable "s3_integrator_revision" { - description = "Revision number of the s3-integrator charm" - type = number - default = 157 # FIXME: https://github.com/canonical/observability/issues/342 -} - -variable "s3_bucket" { - description = "Bucket name" - type = string - default = "tempo" -} - -variable "s3_access_key" { - description = "S3 access-key credential" - type = string -} - -variable "s3_secret_key" { - description = "S3 secret-key credential" - type = string - sensitive = true -} - -variable "s3_endpoint" { - description = "S3 endpoint" - type = string -} - -variable "anti_affinity" { - description = "Enable anti-affinity constraints" - type = bool - default = true -} - -# -------------- # App Names -------------- - -variable "querier_name" { - description = "Name of the Tempo querier app" - type = string - default = "tempo-querier" -} - -variable "query_frontend_name" { - description = "Name of the Tempo query-frontend app" - type = string - default = "tempo-query-frontend" -} - -variable "ingester_name" { - description = "Name of the Tempo ingester app" - type = string - default = "tempo-ingester" -} - -variable "distributor_name" { - description = "Name of the Tempo distributor app" - type = string - default = "tempo-distributor" -} - -variable "compactor_name" { - description = "Name of the Tempo compactor app" - type = string - default = "tempo-compactor" -} - -variable "metrics_generator_name" { - description = "Name of the Tempo metrics-generator app" - type = string - default = "tempo-metrics-generator" -} - -variable "s3_integrator_name" { - description = "Name of the s3-integrator app" - type = string - default = "tempo-s3-integrator" -} - -# -------------- # Units Per App -------------- - -variable "compactor_units" { - description = "Number of Tempo worker units with compactor role" - type = number - default = 1 - validation { - condition = var.compactor_units >= 1 - error_message = "The number of units must be greater than or equal to 1." - } -} - -variable "distributor_units" { - description = "Number of Tempo worker units with distributor role" - type = number - default = 1 - validation { - condition = var.distributor_units >= 1 - error_message = "The number of units must be greater than or equal to 1." - } -} - -variable "ingester_units" { - description = "Number of Tempo worker units with ingester role" - type = number - default = 1 - validation { - condition = var.ingester_units >= 1 - error_message = "The number of units must be greater than or equal to 1." - } -} - -variable "metrics_generator_units" { - description = "Number of Tempo worker units with metrics-generator role" - type = number - default = 1 - validation { - condition = var.metrics_generator_units >= 1 - error_message = "The number of units must be greater than or equal to 1." - } -} - -variable "coordinator_units" { - description = "Number of Tempo coordinator units" - type = number - default = 1 - validation { - condition = var.coordinator_units >= 1 - error_message = "The number of units must be greater than or equal to 1." - } -} - -variable "querier_units" { - description = "Number of Tempo worker units with querier role" - type = number - default = 1 - validation { - condition = var.querier_units >= 1 - error_message = "The number of units must be greater than or equal to 1." - } -} -variable "query_frontend_units" { - description = "Number of Tempo worker units with query-frontend role" - type = number - default = 1 - validation { - condition = var.query_frontend_units >= 1 - error_message = "The number of units must be greater than or equal to 1." - } -} diff --git a/terraform/modules/tempo/versions.tf b/terraform/modules/tempo/versions.tf deleted file mode 100644 index cde98c1a..00000000 --- a/terraform/modules/tempo/versions.tf +++ /dev/null @@ -1,9 +0,0 @@ -terraform { - required_version = ">= 1.5" - required_providers { - juju = { - source = "juju/juju" - version = ">= 0.14.0" - } - } -} \ No newline at end of file diff --git a/terraform/scripts/generate_integrations.py b/terraform/scripts/generate_integrations.py deleted file mode 100644 index ad63f3cd..00000000 --- a/terraform/scripts/generate_integrations.py +++ /dev/null @@ -1,67 +0,0 @@ -import yaml -import sys - - -def parse_yaml(file_path): - """Parse the YAML file and return the data""" - with open(file_path, "r") as file: - return yaml.safe_load(file) - - -def format_keys(section): - """ - Format the keys by replacing hyphens with underscores - Although HCL allows dashes in keys, this does not allow for dot notation - """ - return {key.replace("-", "_"): key for key in section} - - -def generate_output(data): - """Generate the output string based on the parsed YAML data""" - requires = data.get("requires", {}) - provides = data.get("provides", {}) - - # Format the keys in the 'requires' and 'provides' sections - requires_formatted = format_keys(requires) - provides_formatted = format_keys(provides) - - # Prepare the output string - output = 'output "endpoints" {\n value = {\n' - - # Add requires - output += " # Requires\n" - for key, value in requires_formatted.items(): - output += f' {key:<20} = "{value}",\n' - - # Add provides - output += " # Provides\n" - for key, value in provides_formatted.items(): - output += f' {key:<20} = "{value}",\n' - - output += " }\n}" - # TODO: Create a function for `terraform format` of the output - return output - - -def main(): - """Main function to handle script execution""" - if len(sys.argv) < 2: - print("Usage: python script.py ") - sys.exit(1) - - yaml_file_path = sys.argv[1] - - # Parse the YAML file - try: - data = parse_yaml(yaml_file_path) - except Exception as e: - print(f"Error reading YAML file: {e}") - sys.exit(1) - - # Generate the output and print it - output = generate_output(data) - print(output) - - -if __name__ == "__main__": - main() diff --git a/terraform/scripts/hcl-generator/generate_integrations.py b/terraform/scripts/hcl-generator/generate_integrations.py deleted file mode 100644 index 28d5dee1..00000000 --- a/terraform/scripts/hcl-generator/generate_integrations.py +++ /dev/null @@ -1,116 +0,0 @@ -import yaml -import sys -import hcl2 -import os -import argparse -from pathlib import Path - -OUTPUTS_TF_FILE = "outputs.tf" - - -def build_parser(): - """Create and configure the argument parser for the script.""" - - parser = argparse.ArgumentParser(description="Process YAML and generate Terraform output.") - - parser.add_argument( - '--input-yaml', - required=True, - help='Path to the input YAML file (charmcraft.yaml or metadata.yaml)' - ) - - parser.add_argument( - '--outputs-tf', - default=OUTPUTS_TF_FILE, - help=f'Path to the output Terraform file (default: {OUTPUTS_TF_FILE})' - ) - - return parser - - -class HCLGenerator(object): - def __init__(self, input_yaml: str, outputs_tf: str): - self.input_yaml = Path(input_yaml) - if outputs_tf == OUTPUTS_TF_FILE: - self.outputs_tf = Path(os.getcwd()) / outputs_tf - else: - self.outputs_tf = Path(outputs_tf) - - def parse_yaml(self): - """Parse the YAML file and return the data""" - try: - with open(self.input_yaml, "r") as file: - return yaml.safe_load(file) - except Exception as e: - print(f"Error reading YAML file: {e}") - sys.exit(1) - - @staticmethod - def format_keys(section): - """ - Format the keys by replacing hyphens with underscores - Although HCL allows dashes in keys, this does not allow for dot notation - """ - return {key.replace("-", "_"): key for key in section} - - def create_file_with_parents(self): - """Create the file and parent directories if they don't exist""" - self.outputs_tf.parent.mkdir(parents=True, exist_ok=True) - self.outputs_tf.touch(exist_ok=True) - - def generate_output(self, data): - """Generate the output string based on the parsed YAML data""" - requires = data.get("requires", {}) - provides = data.get("provides", {}) - - # Format the keys in the 'requires' and 'provides' sections - requires_formatted = self.format_keys(requires) - provides_formatted = self.format_keys(provides) - - # Prepare the output string - output = 'output "endpoints" {\n value = {\n' - - # Add requires - output += " # Requires\n" - for key, value in requires_formatted.items(): - output += f' {key:<20} = "{value}",\n' - - # Add provides - output += " # Provides\n" - for key, value in provides_formatted.items(): - output += f' {key:<20} = "{value}",\n' - - output += " }\n}" - # TODO: Create a function for `terraform format` of the output - return output - - def write_hcl_file(self, hcl_content): - """Parse the YAML file and return the data""" - - self.create_file_with_parents() - - with open(self.outputs_tf, "r") as file: - read_obj = hcl2.load(file) - - if read_obj: - print("WE HAD CONTENTS") - - with open(self.outputs_tf, "w") as file: - file.write(hcl_content) - - -def main(): - """Main function to handle script execution""" - - parser = build_parser() - args = parser.parse_args() - - gen = HCLGenerator(args.input_yaml, args.outputs_tf) - data = gen.parse_yaml() - output_raw = gen.generate_output(data) - print(output_raw) - gen.write_hcl_file(output_raw) - - -if __name__ == "__main__": - main()