Skip to content

Commit

Permalink
setup cloudwatch-agent
Browse files Browse the repository at this point in the history
  • Loading branch information
badra001 committed Aug 23, 2023
1 parent 4c99275 commit 6c45644
Show file tree
Hide file tree
Showing 11 changed files with 662 additions and 57 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# .tf-control
# allows for setting a specific command to be used for tf-* commands under this git repo
# see tf-control.sh help for more info

TFCONTROL_VERSION="1.0.5"

TFCOMMAND="terraform_latest"
# TF_CLI_CONFIG_FILE=PATH-TO-FILE/.tf-control.tfrc
# TFARGS=""
# TFNOLOG=""
# TFNOCOLOR=""

# use the following to force a specific version. An upgrade of an existing 0.12.31 to 1.x
# needs you to cycle through 0.13.17, 0.14.11, and then latest (0.15.5 not needed). Other
# steps in between. See https://github.e.it.census.gov/terraform/support/tree/master/docs/how-to/terraform-upgrade for details
#
#TFCOMMAND="terraform_0.12.31"
#TFCOMMAND="terraform_0.13.7"
#TFCOMMAND="terraform_0.14.11"
#TFCOMMAND="terraform_0.15.5"
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
TFCONTROL_VERSION="1.0.5"

# https://www.terraform.io/docs/cli/config/config-file.html
plugin_cache_dir = "/data/terraform/terraform.d/plugin-cache"
#disable_checkpoint = true

provider_installation {
# filesystem_mirror {
# path = "/apps/terraform/terraform.d/providers"
# include = [ "*/*/*" ]
# }
filesystem_mirror {
path = "/data/terraform/terraform.d/providers"
include = [ "*/*/*" ]
}
# filesystem_mirror {
# path = "/apps/terraform/terraform.d/providers"
# include = [ "external.terraform.census.gov/*/*" ]
# }
direct {
include = [ "*/*/*" ]
}
}

Original file line number Diff line number Diff line change
@@ -1,37 +1,4 @@
# https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Container-Insights-prerequisites.html
# https://registry.terraform.io/modules/bailey84j/cloudwatch-agent/kubernetes/latest
# cannot let this create the role, as it tries to attache a policy that does not exist
# we need this policy: arn:aws-us-gov:iam::aws:policy/CloudWatchAgentServerPolicy

# need to hack the module for now
# main.tf
## container {
## name = "${var.name}-agent"
## # image = "amazon/${var.image_name}:${var.image_version}"
## image = "${var.image_name}:${var.image_version}"
#
# want to replace this with var.image_repository
#
# also want to do the same for the role, to allow a different managed role(s) besides
# the appsync one to be used

module "cloudwatch-agent" {
source = "bailey84j/cloudwatch-agent/kubernetes"
version = "1.0.1"

eks_cluster_name = var.cluster_name
create_namespace = false
image_name = split(":", local.cloudwatch_agent_images_output["cloudwatch-agent"].dest_full_path)[0]
image_version = local.cloudwatch_agent_images_output["cloudwatch-agent"].tag
create_iam_role = false
iam_role_arn = module.role_cloudwatch-agent.iam_role_arn

tags = merge(
local.base_tags,
local.common_tags,
var.application_tags,
)
}

data "aws_iam_policy" "policy_cloudwatch-agent" {
name = "CloudWatchAgentServerPolicy"
Expand All @@ -41,7 +8,7 @@ module "role_cloudwatch-agent" {
source = "terraform-aws-modules/iam/aws//modules/iam-role-for-service-accounts-eks"

role_description = "EKS IAM Role for ${var.cluster_name} for service account ${var.cloudwatch_agent_namespace}:${var.cloudwatch_agent_name}"
role_name = format("%v%v-irsa__%v", local._prefixes["eks"], var.cluster_name, var.cloudwatch_agent_name)
role_name = format("%v%v-irsa__%v", local._prefixes["eks-role"], var.cluster_name, var.cloudwatch_agent_name)

role_policy_arns = {
policy = data.aws_iam_policy.policy_cloudwatch-agent.arn
Expand All @@ -65,28 +32,6 @@ module "role_cloudwatch-agent" {
)
}

## module "role_cloudwatch-agent" {
## source = "git@github.e.it.census.gov:terraform-modules/aws-iam-role.git?ref=tf-upgrade"
##
## role_description = "EKS IAM Role for ${var.cluster_name} for service account ${var.cloudwatch_agent_namespace}:${var.cloudwatch_agent_name}"
## role_name = format("%v%v-irsa__%v", local._prefixes["eks"], var.cluster_name, var.cloudwatch_agent_name)
## enable_ldap_creation = false
## assume_policy_document = data.aws_iam_policy_document.assume_role_cloudwatch-agent.json
## attached_policies = [aws_iam_policy.policy_cloudwatch-agent.arn]
##
## tags = merge(
## local.base_tags,
## local.common_tags,
## var.tags,
## var.application_tags,
## {
## "eks:namespace" = var.namespace
## "eks:user" = var.name
## }
## )
## }


locals {
cloudwatch_agent_images_output = { for k, v in module.images_cloudwatch-agent.images : v.name => v }
}
Expand All @@ -104,3 +49,75 @@ module "images_cloudwatch-agent" {
var.application_tags,
)
}

resource "aws_cloudwatch_log_group" "cloudwatch_agent_logs" {
for_each = toset(var.cloudwatch_agent_log_names)
name = format("/aws/containerinsights/%v/%v", var.cluster_name, each.key)
retention_in_days = var.cloudwatch_agent_log_retention_days
tags = merge(
local.base_tags,
local.common_tags,
var.application_tags,
)
}

resource "kubernetes_namespace" "cloudwatch-agent" {
metadata {
name = var.cloudwatch_agent_namespace
}
}

# chart
# https://github.com/aws/eks-charts/tree/master/stable/aws-cloudwatch-metrics
resource "helm_release" "cloudwatch-agent" {
chart = "aws-cloudwatch-metrics"
name = "aws-cloudwatch-metrics"
namespace = var.cloudwatch_agent_namespace
repository = var.cloudwatch_agent_charts["cloudwatch-agent"].use_remote ? var.cloudwatch_agent_charts["cloudwatch-agent"].repository : "${path.module}/charts"
version = var.cloudwatch_agent_charts["cloudwatch-agent"].use_remote ? var.cloudwatch_agent_charts["cloudwatch-agent"].version : null
depends_on = [kubernetes_namespace.cloudwatch-agent,module.images_cloudwatch-agent]
set {
name = "image.repository"
value = split(":", local.cloudwatch_agent_images_output["cloudwatch-agent"].dest_full_path)[0]
}
set {
name = "image.tag"
value = local.cloudwatch_agent_images_output["cloudwatch-agent"].tag
}
set {
name = "clusterName"
value = var.cluster_name
}
set {
name = "serviceAccount.name"
value = var.cloudwatch_agent_name
}
set {
name = "serviceAccount.create"
value = "true"
}
set {
name = "serviceAccount.annotations.eks\\.amazonaws\\.com/role-arn"
value = module.role_cloudwatch-agent.iam_role_arn
}
timeout = 300
}
data "aws_iam_policy_document" "cloudwatch_agent_policy_extra" {
statement {
sid = "DescribeVolumes"
effect = "Allow"
actions = [ "ec2:DescribeVolumes" ]
resources = [ "*" ]
}
}

resource "aws_iam_role_policy" "cloudwatch_agent_policy_extra" {
name = "extra"
role = module.role_cloudwatch-agent.iam_role_name

policy = data.aws_iam_policy_document.cloudwatch_agent_policy_extra.json
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
# https://github.com/aws/aws-for-fluent-bit

## % tf-aws ssm get-parameters-by-path --path /aws/service/aws-for-fluent-bit/ --query 'Parameters[*].Name'|grep 2.31.12
## "/aws/service/aws-for-fluent-bit/2.31.12-windowsservercore",
## "/aws/service/aws-for-fluent-bit/init-2.31.12.20230629",
## "/aws/service/aws-for-fluent-bit/2.31.12.20230727",
## "/aws/service/aws-for-fluent-bit/2.31.12.20230629",
## "/aws/service/aws-for-fluent-bit/2.31.12",
## "/aws/service/aws-for-fluent-bit/init-2.31.12",
## "/aws/service/aws-for-fluent-bit/init-2.31.12.20230727"
##
## % tf-aws ssm get-parameter --name /aws/service/aws-for-fluent-bit/2.31.12.20230629
## {
## "Parameter": {
## "Name": "/aws/service/aws-for-fluent-bit/2.31.12.20230629",
## "Type": "String",
## "Value": "161423150738.dkr.ecr.us-gov-west-1.amazonaws.com/aws-for-fluent-bit:2.31.12.20230629",
## "Version": 1,
## "LastModifiedDate": "2023-06-29T20:54:07.770000-04:00",
## "ARN": "arn:aws-us-gov:ssm:us-gov-west-1::parameter/aws/service/aws-for-fluent-bit/2.31.12.20230629",
## "DataType": "text"
## }
## }


data "aws_ssm_parameter" "fluentbit_image" {
name = format("/aws/service/aws-for-fluent-bit/%v", var.fluentbit_tag)

lifecycle {
precondition {
condition = var.fluentbit_tag != null && var.fluentbit_tag != ""
error_message = "var.fluentbit_tag must be provided and not null or empty."
}
}
}


module "role_fluentbit" {
source = "terraform-aws-modules/iam/aws//modules/iam-role-for-service-accounts-eks"

role_description = "EKS IAM Role for ${var.cluster_name} for service account ${var.fluentbit_namespace}:${var.fluentbit_name}"
role_name = format("%v%v-irsa__%v", local._prefixes["eks-role"], var.cluster_name, var.fluentbit_name)

role_policy_arns = {
policy = aws_iam_policy.policy_fluentbit.arn
}

oidc_providers = {
main = {
provider_arn = local.oidc_provider_arn
namespace_service_accounts = [format("%v:%v", var.fluentbit_namespace, var.fluentbit_name)]
}
}

tags = merge(
local.base_tags,
local.common_tags,
var.application_tags,
{
"eks:namespace" = var.fluentbit_namespace
"eks:user" = var.fluentbit_name
}
)
}

resource "aws_iam_policy" "policy_fluentbit" {
name = format("%v%v-irsa__%v", local._prefixes["eks-policy"], var.cluster_name, var.fluentbit_name)
description = "EKS IAM Policy for ${var.cluster_name} for service account ${var.fluentbit_namespace}:${var.fluentbit_name}"
path = "/"
policy = data.aws_iam_policy_document.policy_fluentbit.json

tags = merge(
local.base_tags,
local.common_tags,
var.application_tags,
{
"Name" = format("%v%v-irsa__%v", local._prefixes["eks-policy"], var.cluster_name, var.fluentbit_name)
"eks:namespace" = var.fluentbit_namespace
"eks:user" = var.fluentbit_name
}
)
}


# https://aws.amazon.com/blogs/opensource/centralized-container-logging-fluent-bit/
data "aws_iam_policy_document" "policy_fluentbit" {
statement {
sid = "AllowFirehose"
effect = "Allow"
actions = [
"firehose:PutRecordBatch"
]
resources = ["*"]
}
## statement {
## sid = "PutLogEvents"
## effect = "Allow"
## actions = [
## "logs:PutLogEvents"
## ]
## resources = [ format("arn:%v:logs:*:*:log-group:*:*:*",data.aws_arn.current.partition) ]
## }
statement {
sid = "CreateStreams"
effect = "Allow"
actions = [
"logs:CreateLogStream",
"logs:DescribeLogStreams",
"logs:PutLogEvents"
]
# resources = [ format("arn:%v:logs:*:*:log-group:*",data.aws_arn.current.partition) ]
resources = [for k, v in aws_cloudwatch_log_group.fluentbit_logs : format("%v:*", v.arn)]
}
## statement {
## sid = "CreateLogGroup"
## effect = "Allow"
## actions = [
## "logs:CreateLogGroup"
## ]
## resources = [ "*" ]
## }
}

resource "aws_cloudwatch_log_group" "fluentbit_logs" {
for_each = toset(var.fluentbit_log_names)
name = format("/aws/containerinsights/%v/%v", var.cluster_name, each.key)
retention_in_days = var.fluentbit_log_retention_days
tags = merge(
local.base_tags,
local.common_tags,
var.application_tags,
)
}

## helm, reference ssm image
# https://github.com/aws/eks-charts/tree/master/stable/aws-for-fluent-bit

resource "helm_release" "fluentbit" {
chart = "aws-for-fluent-bit"
name = var.fluentbit_name
namespace = var.fluentbit_namespace
repository = var.fluentbit_charts["fluent-bit"].use_remote ? var.fluentbit_charts["fluent-bit"].repository : "${path.module}/charts"
version = var.fluentbit_charts["fluent-bit"].use_remote ? var.fluentbit_charts["fluent-bit"].version : null
values = [
file("fluentbit.values.yml"),
templatefile("${path.root}/templates/fluentbit.env.yml.tpl",{
region = local.region
cluster_name = var.cluster_name
})
]

set {
name = "cluster.name"
value = var.cluster_name
}
set {
name = "logs.region"
value = var.region
}
set {
name = "image.repository"
value = split(":", data.aws_ssm_parameter.fluentbit_image.value)[0]
}
set {
name = "image.tag"
value = var.fluentbit_tag
}
set {
name = "cloudWatchLogs.enabled"
value = "false"
}
set {
name = "serviceAccount.name"
value = var.fluentbit_name
}
set {
name = "serviceAccount.create"
value = "true"
}
set {
name = "serviceAccount.annotations.eks\\.amazonaws\\.com/role-arn"
value = module.role_fluentbit.iam_role_arn
}
timeout = 300
}
Loading

0 comments on commit 6c45644

Please sign in to comment.