aws-quickstart / cdk-eks-blueprints

AWS Quick Start Team
Apache License 2.0
424 stars 188 forks source link

Add resource tags at a global/resource level to all resources deployed by CDK EKS Blueprints #984

Open JonVDB opened 1 month ago

JonVDB commented 1 month ago

Describe the feature

A way to define AWS resource tags on a per-resource level within a cluster template. These tags are then added to all resources (at least the ones that can have tags) that are deployed by CDK EKS Blueprints.

Use Case

To keep track of different resources from different apps, to monitor and manage them, customers want the ability to add custom tags to all resources that are part of a specific application. This is necessary when wanting to properly monitor and manage these resources. Not being able to do this makes it hard to work with monitoring software that depends on specific tags being applied to all resources in an AWS account.

This applies to resources that are defined by the user within the stack, as well as resources automatically generated by CDK EKS Blueprints to deploy the environment (ex: Lambda functions, Roles, ...).

Proposed Solution

The user gets to define their preferred tags on a per-resource level. This would basically mean that the "tags" argument is a valid argument that can be added to all applicable EKS Blueprints methods that generate resources. For example, if the user wants to add the LoadBalancer Controller AddOn, one would be able to define tags which are added to the related roles and other resources created by EKS Blueprints for this addon to function. Example:

new blueprints.addons.AwsLoadBalancerControllerAddOn( { "key1":"val1", ... } ),

In this example, to cover all resources that are implicitly created by EKS Blueprints (such as Lambda functions, SSM, etc... ), the user would also be able to define "blueprintGlobalTags" which add tags only to these implicit resources. Example

const stack = blueprints.EksBlueprint.builder()
    .blueprintGlobalTags( { "key2":"val2", "key3":"val3", ... } )
    .build(app, 'eks-blueprint');

Other Information

No response

Acknowledgements

CDK version used

2.133.0 (build dcc1e75)

EKS Blueprints Version

1.14.1

Node.js Version

v20.11.0

Environment details (OS name and version, etc.)

Win11Pro22H2

Feder1co5oave commented 2 weeks ago

This is very interesting and particularly useful in those cases where a cloud-migration-oriented discount agreement exists, where the customer needs to tag all resources with a specific tag value provided by AWS, in order to be eligible to the discount.

Thankfully CDK provides an easy way to tag all resources in a stack, via the Tags aspect. For example, to tagg ALL cloud resources of specific types:

import * as cdk from 'aws-cdk-lib';
const app = new cdk.App();
cdk.Tags.of(app).add(key, value, {
    includeResourceTypes: [
      'AWS::EC2::VPCEndpoint', 'AWS::EC2::NatGateway', 'AWS::EC2::InternetGateway',
      'AWS::KMS::Key',
      'AWS::Lambda::Function', 'AWS::StepFunctions::StateMachine',
      'AWS::SQS::Queue',
      'AWS::S3::Bucket',
      'AWS::SecretsManager::Secret', 'AWS::SSM::Parameter',
      'AWS::RDS::DBInstance'
    ]
  });

Furthermore, some cloud resources are indirectly created by Kubernetes controllers, instead of CDK/CloudFormation itself, and each controller/addon has a slightly different mechanism (when available) to specify tags for provisioned resources (e.g. EC2 instances, EBS volumes, and NLB load balancers).

For example, Karpenter allows to set tags on launched instances by setting the spec.tags field in the EC2NodeClass:

apiVersion: karpenter.k8s.aws/v1beta1
kind: EC2NodeClass
metadata:
  name: default
spec:
  amiFamily: AL2
  tags:
    key: value

EBS CSI drivers allows to propagate tags to provisioned EBS volumes, via parameters in the StorageClass:

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: ebs-sc
provisioner: ebs.csi.aws.com
parameters:
  tagSpecification_1: "key1=value1"
  tagSpecification_2: "key2=value2"

AWS Load Balancer Controller has a way to inject tags into ALB/ELB/NLB by setting defaultTags in its helm chart's Values:

# values.yaml
defaultTags:
  key: value

(see #968)