Skip to content

Commit ef6f013

Browse files
authored
Merge pull request #46 from aws-observability/feature/existingClusterOpenSourcePattern
Existing Cluster Open Source Observability Pattern
2 parents e2e9345 + c8bf852 commit ef6f013

File tree

11 files changed

+228
-24
lines changed

11 files changed

+228
-24
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import ExistingEksOpenSourceobservabilityConstruct from '../lib/existing-eks-opensource-observability-construct';
2+
import { configureApp, errorHandler } from '../lib/common/construct-utils';
3+
4+
const app = configureApp();
5+
6+
new ExistingEksOpenSourceobservabilityConstruct().buildAsync(app, 'existing-eks-opensource').catch((error) => {
7+
errorHandler(app, "Existing Cluster Pattern is missing information of existing cluster: " + error);
8+
});

cdk.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
"namespaceworkloads.dashboard.url": "https://raw.githubusercontent.com/aws-observability/aws-observability-accelerator/main/artifacts/grafana-dashboards/eks/infrastructure/namespace-workloads.json",
2323
"nodeexporter.dashboard.url": "https://raw.githubusercontent.com/aws-observability/aws-observability-accelerator/main/artifacts/grafana-dashboards/eks/infrastructure/nodeexporter-nodes.json",
2424
"nodes.dashboard.url": "https://raw.githubusercontent.com/aws-observability/aws-observability-accelerator/main/artifacts/grafana-dashboards/eks/infrastructure/nodes.json",
25-
"workloads.dashboard.url": "https://raw.githubusercontent.com/aws-observability/aws-observability-accelerator/main/artifacts/grafana-dashboards/eks/infrastructure/workloads.json"
25+
"workloads.dashboard.url": "https://raw.githubusercontent.com/aws-observability/aws-observability-accelerator/main/artifacts/grafana-dashboards/eks/infrastructure/workloads.json",
26+
"existing.cluster.name": "single-new-eks-observability-accelerator",
27+
"existing.kubectl.rolename": "YOUR_KUBECTL_ROLE"
2628
}
2729
}

lib/common/observability-builder.ts

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,31 @@ import * as utils from '@aws-quickstart/eks-blueprints/dist/utils';
33
import { NestedStack, NestedStackProps } from 'aws-cdk-lib';
44
import { Construct } from 'constructs';
55

6+
export class ObservabilityBuilder extends blueprints.BlueprintBuilder {
7+
8+
public addNewClusterObservabilityBuilderAddOns(): ObservabilityBuilder {
9+
return this.addOns(
10+
new blueprints.addons.VpcCniAddOn(),
11+
new blueprints.addons.CoreDnsAddOn(),
12+
new blueprints.addons.MetricsServerAddOn(),
13+
new blueprints.addons.PrometheusNodeExporterAddOn(),
14+
new blueprints.addons.KubeStateMetricsAddOn());
15+
}
616

17+
public addExistingClusterObservabilityBuilderAddOns(): ObservabilityBuilder {
18+
return this.addOns(
19+
new blueprints.addons.AwsLoadBalancerControllerAddOn(),
20+
new blueprints.addons.CertManagerAddOn());
21+
}
722

8-
export class ObservabilityBuilder {
9-
10-
public static builder(): blueprints.BlueprintBuilder {
11-
return new blueprints.BlueprintBuilder()
12-
.addOns(
13-
new blueprints.NestedStackAddOn({
14-
id: "usage-tracking-addon",
15-
builder: UsageTrackingAddOn.builder(),
16-
}),
17-
new blueprints.addons.AwsLoadBalancerControllerAddOn(),
18-
new blueprints.addons.VpcCniAddOn(),
19-
new blueprints.addons.CoreDnsAddOn(),
20-
new blueprints.addons.MetricsServerAddOn(),
21-
new blueprints.addons.ExternalsSecretsAddOn(),
22-
new blueprints.addons.CertManagerAddOn(),
23-
new blueprints.addons.PrometheusNodeExporterAddOn(),
24-
new blueprints.addons.KubeStateMetricsAddOn());
23+
public static builder(): ObservabilityBuilder {
24+
const builder = new ObservabilityBuilder();
25+
builder.addOns(
26+
new blueprints.NestedStackAddOn({
27+
id: "usage-tracking-addon",
28+
builder: UsageTrackingAddOn.builder(),
29+
}));
30+
return builder;
2531
}
2632
}
2733

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import 'source-map-support/register';
2+
import * as blueprints from '@aws-quickstart/eks-blueprints';
3+
import * as eks from "aws-cdk-lib/aws-eks";
4+
import { Construct } from 'constructs';
5+
import { dependable } from '@aws-quickstart/eks-blueprints/dist/utils';
6+
7+
export class GrafanaOperatorSecretAddon implements blueprints.ClusterAddOn {
8+
id?: string | undefined;
9+
@dependable(blueprints.addons.ExternalsSecretsAddOn.name, blueprints.addons.GrafanaOperatorAddon.name)
10+
deploy(clusterInfo: blueprints.ClusterInfo): void | Promise<Construct> {
11+
const cluster = clusterInfo.cluster;
12+
const secretStore = new eks.KubernetesManifest(clusterInfo.cluster.stack, "ClusterSecretStore", {
13+
cluster: cluster,
14+
manifest: [
15+
{
16+
apiVersion: "external-secrets.io/v1beta1",
17+
kind: "ClusterSecretStore",
18+
metadata: {
19+
name: "ssm-parameter-store",
20+
namespace: "default"
21+
},
22+
spec: {
23+
provider: {
24+
aws: {
25+
service: "ParameterStore",
26+
region: clusterInfo.cluster.stack.region,
27+
auth: {
28+
jwt: {
29+
serviceAccountRef: {
30+
name: "external-secrets-sa",
31+
namespace: "external-secrets",
32+
},
33+
},
34+
},
35+
},
36+
},
37+
},
38+
},
39+
],
40+
});
41+
42+
const externalSecret = new eks.KubernetesManifest(clusterInfo.cluster.stack, "ExternalSecret", {
43+
cluster: cluster,
44+
manifest: [
45+
{
46+
apiVersion: "external-secrets.io/v1beta1",
47+
kind: "ExternalSecret",
48+
metadata: {
49+
name: "external-grafana-admin-credentials",
50+
namespace: "grafana-operator"
51+
},
52+
spec: {
53+
secretStoreRef: {
54+
name: "ssm-parameter-store",
55+
kind: "ClusterSecretStore",
56+
},
57+
target: {
58+
name: "grafana-admin-credentials"
59+
},
60+
data: [
61+
{
62+
secretKey: "GF_SECURITY_ADMIN_APIKEY",
63+
remoteRef: {
64+
key: "/cdk-accelerator/grafana-api-key"
65+
},
66+
},
67+
],
68+
},
69+
},
70+
],
71+
});
72+
externalSecret.node.addDependency(secretStore);
73+
return Promise.resolve(secretStore);
74+
}
75+
}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
// import { Construct } from 'constructs';
2+
import { ImportClusterProvider, utils } from '@aws-quickstart/eks-blueprints';
3+
import * as blueprints from '@aws-quickstart/eks-blueprints';
4+
import { GrafanaOperatorSecretAddon } from './grafanaoperatorsecretaddon';
5+
import * as amp from 'aws-cdk-lib/aws-aps';
6+
import { ObservabilityBuilder } from '../common/observability-builder';
7+
import * as cdk from "aws-cdk-lib";
8+
import * as eks from 'aws-cdk-lib/aws-eks';
9+
10+
export default class ExistingEksOpenSourceobservabilityConstruct {
11+
async buildAsync(scope: cdk.App, id: string) {
12+
// AddOns for the cluster
13+
const stackId = `${id}-observability-accelerator`;
14+
const clusterName = utils.valueFromContext(scope, "existing.cluster.name", undefined);
15+
const kubectlRoleName = utils.valueFromContext(scope, "existing.kubectl.rolename", undefined);
16+
17+
const account = process.env.COA_ACCOUNT_ID! || process.env.CDK_DEFAULT_ACCOUNT!;
18+
const region = process.env.COA_AWS_REGION! || process.env.CDK_DEFAULT_REGION!;
19+
const ampWorkspaceName = process.env.COA_AMP_WORKSPACE_NAME! || 'observability-amp-Workspace';
20+
const ampPrometheusEndpoint = (blueprints.getNamedResource(ampWorkspaceName) as unknown as amp.CfnWorkspace).attrPrometheusEndpoint;
21+
22+
const amgEndpointUrl = process.env.COA_AMG_ENDPOINT_URL;
23+
const sdkCluster = await blueprints.describeCluster(clusterName, region); // get cluster information using EKS APIs
24+
const vpcId = sdkCluster.resourcesVpcConfig?.vpcId;
25+
26+
/**
27+
* Assumes the supplied role is registered in the target cluster for kubectl access.
28+
*/
29+
30+
const importClusterProvider = new ImportClusterProvider({
31+
clusterName: sdkCluster.name!,
32+
version: eks.KubernetesVersion.of(sdkCluster.version!),
33+
clusterEndpoint: sdkCluster.endpoint,
34+
openIdConnectProvider: blueprints.getResource(context =>
35+
new blueprints.LookupOpenIdConnectProvider(sdkCluster.identity!.oidc!.issuer!).provide(context)),
36+
clusterCertificateAuthorityData: sdkCluster.certificateAuthority?.data,
37+
kubectlRoleArn: blueprints.getResource(context => new blueprints.LookupRoleProvider(kubectlRoleName).provide(context)).roleArn,
38+
clusterSecurityGroupId: sdkCluster.resourcesVpcConfig?.clusterSecurityGroupId
39+
});
40+
41+
// All Grafana Dashboard URLs from `cdk.json` if presentgi
42+
const clusterDashUrl: string = utils.valueFromContext(scope, "cluster.dashboard.url", undefined);
43+
const kubeletDashUrl: string = utils.valueFromContext(scope, "kubelet.dashboard.url", undefined);
44+
const namespaceWorkloadsDashUrl: string = utils.valueFromContext(scope, "namespaceworkloads.dashboard.url", undefined);
45+
const nodeExporterDashUrl: string = utils.valueFromContext(scope, "nodeexporter.dashboard.url", undefined);
46+
const nodesDashUrl: string = utils.valueFromContext(scope, "nodes.dashboard.url", undefined);
47+
const workloadsDashUrl: string = utils.valueFromContext(scope, "workloads.dashboard.url", undefined);
48+
49+
Reflect.defineMetadata("ordered", true, blueprints.addons.GrafanaOperatorAddon);
50+
const addOns: Array<blueprints.ClusterAddOn> = [
51+
new blueprints.addons.CloudWatchLogsAddon({
52+
logGroupPrefix: `/aws/eks/${stackId}`,
53+
logRetentionDays: 30
54+
}),
55+
new blueprints.addons.AdotCollectorAddOn(),
56+
new blueprints.addons.AmpAddOn({
57+
ampPrometheusEndpoint: ampPrometheusEndpoint,
58+
}),
59+
new blueprints.addons.XrayAdotAddOn(),
60+
new blueprints.addons.ExternalsSecretsAddOn(),
61+
new blueprints.addons.GrafanaOperatorAddon({
62+
version: 'v5.0.0-rc3'
63+
}),
64+
new blueprints.addons.FluxCDAddOn({
65+
bootstrapRepo: {
66+
repoUrl: 'https://github.com/aws-observability/aws-observability-accelerator',
67+
name: "grafana-dashboards",
68+
targetRevision: "main",
69+
path: "./artifacts/grafana-operator-manifests/eks/infrastructure"
70+
},
71+
fluxTargetNamespace: "grafana-operator",
72+
bootstrapValues: {
73+
"AMG_AWS_REGION": region,
74+
"AMP_ENDPOINT_URL": ampPrometheusEndpoint,
75+
"AMG_ENDPOINT_URL": amgEndpointUrl,
76+
"GRAFANA_CLUSTER_DASH_URL" : clusterDashUrl,
77+
"GRAFANA_KUBELET_DASH_URL" : kubeletDashUrl,
78+
"GRAFANA_NSWRKLDS_DASH_URL" : namespaceWorkloadsDashUrl,
79+
"GRAFANA_NODEEXP_DASH_URL" : nodeExporterDashUrl,
80+
"GRAFANA_NODES_DASH_URL" : nodesDashUrl,
81+
"GRAFANA_WORKLOADS_DASH_URL" : workloadsDashUrl
82+
},
83+
}),
84+
new GrafanaOperatorSecretAddon(),
85+
];
86+
87+
ObservabilityBuilder.builder()
88+
.account(account)
89+
.region(region)
90+
.addExistingClusterObservabilityBuilderAddOns()
91+
.clusterProvider(importClusterProvider)
92+
.resourceProvider(blueprints.GlobalResources.Vpc, new blueprints.VpcProvider(vpcId)) // this is required with import cluster provider
93+
.resourceProvider(ampWorkspaceName, new blueprints.CreateAmpProvider(ampWorkspaceName, ampWorkspaceName))
94+
.addOns(...addOns)
95+
.build(scope, stackId);
96+
}
97+
}

lib/single-new-eks-awsnative-observability-construct/index.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,20 @@ export default class SingleNewEksClusterAWSNativeobservabilityConstruct {
1212

1313
const addOns: Array<blueprints.ClusterAddOn> = [
1414
new blueprints.addons.KubeProxyAddOn(),
15+
new blueprints.addons.AwsLoadBalancerControllerAddOn(),
16+
new blueprints.addons.CertManagerAddOn(),
1517
new blueprints.addons.CloudWatchLogsAddon({
1618
logGroupPrefix: `/aws/eks/${stackId}`,
1719
logRetentionDays: 30
1820
}),
1921
new blueprints.addons.ContainerInsightsAddOn(),
20-
// new blueprints.addons.XrayAddOn()
22+
new blueprints.addons.XrayAddOn()
2123
];
2224

2325
ObservabilityBuilder.builder()
2426
.account(account)
2527
.region(region)
28+
.addNewClusterObservabilityBuilderAddOns()
2629
.addOns(...addOns)
2730
.build(scope, stackId);
2831
}

lib/single-new-eks-cluster-construct/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,13 @@ export default class SingleNewEksConstruct {
1111

1212
const addOns: Array<blueprints.ClusterAddOn> = [
1313
new blueprints.addons.KubeProxyAddOn(),
14+
new blueprints.addons.ClusterAutoScalerAddOn()
1415
];
1516

1617
ObservabilityBuilder.builder()
1718
.account(account)
1819
.region(region)
20+
.addNewClusterObservabilityBuilderAddOns()
1921
.addOns(...addOns)
2022
.build(scope, stackId);
2123
}

lib/single-new-eks-mixed-observability-construct/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ export default class SingleNewEksMixedobservabilityConstruct {
2020

2121
const addOns: Array<blueprints.ClusterAddOn> = [
2222
new blueprints.addons.KubeProxyAddOn(),
23+
new blueprints.addons.AwsLoadBalancerControllerAddOn(),
24+
new blueprints.addons.CertManagerAddOn(),
2325
new blueprints.addons.CloudWatchLogsAddon({
2426
logGroupPrefix: `/aws/eks/${stackId}`,
2527
logRetentionDays: 30
@@ -32,6 +34,7 @@ export default class SingleNewEksMixedobservabilityConstruct {
3234
ObservabilityBuilder.builder()
3335
.account(account)
3436
.region(region)
37+
.addNewClusterObservabilityBuilderAddOns()
3538
.addOns(...addOns)
3639
.build(scope, stackId);
3740
}

lib/single-new-eks-opensource-observability-construct/graviton-index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ export default class SingleNewEksGravitonOpenSourceObservabilityConstruct {
3030
Reflect.defineMetadata("ordered", true, blueprints.addons.GrafanaOperatorAddon);
3131
const addOns: Array<blueprints.ClusterAddOn> = [
3232
new blueprints.addons.KubeProxyAddOn("v1.27.1-eksbuild.1"),
33+
new blueprints.addons.AwsLoadBalancerControllerAddOn(),
34+
new blueprints.addons.CertManagerAddOn(),
3335
new blueprints.addons.CloudWatchLogsAddon({
3436
logGroupPrefix: `/aws/eks/${stackId}`,
3537
logRetentionDays: 30
@@ -39,6 +41,7 @@ export default class SingleNewEksGravitonOpenSourceObservabilityConstruct {
3941
ampPrometheusEndpoint: ampPrometheusEndpoint,
4042
}),
4143
new blueprints.addons.XrayAdotAddOn(),
44+
new blueprints.addons.ExternalsSecretsAddOn(),
4245
new blueprints.addons.GrafanaOperatorAddon({
4346
version: 'v5.0.0-rc3'
4447
}),
@@ -74,6 +77,7 @@ export default class SingleNewEksGravitonOpenSourceObservabilityConstruct {
7477
ObservabilityBuilder.builder()
7578
.account(account)
7679
.region(region)
80+
.addNewClusterObservabilityBuilderAddOns()
7781
.resourceProvider(ampWorkspaceName, new blueprints.CreateAmpProvider(ampWorkspaceName, ampWorkspaceName))
7882
.clusterProvider(new blueprints.MngClusterProvider(mngProps))
7983
.addOns(...addOns)

lib/single-new-eks-opensource-observability-construct/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ export default class SingleNewEksOpenSourceobservabilityConstruct {
3232
Reflect.defineMetadata("ordered", true, blueprints.addons.GrafanaOperatorAddon);
3333
const addOns: Array<blueprints.ClusterAddOn> = [
3434
new blueprints.addons.KubeProxyAddOn(),
35+
new blueprints.addons.AwsLoadBalancerControllerAddOn(),
36+
new blueprints.addons.CertManagerAddOn(),
3537
new blueprints.addons.CloudWatchLogsAddon({
3638
logGroupPrefix: `/aws/eks/${stackId}`,
3739
logRetentionDays: 30
@@ -41,6 +43,7 @@ export default class SingleNewEksOpenSourceobservabilityConstruct {
4143
ampPrometheusEndpoint: ampPrometheusEndpoint,
4244
}),
4345
new blueprints.addons.XrayAdotAddOn(),
46+
new blueprints.addons.ExternalsSecretsAddOn(),
4447
new blueprints.addons.GrafanaOperatorAddon({
4548
version: 'v5.0.0-rc3'
4649
}),
@@ -70,6 +73,7 @@ export default class SingleNewEksOpenSourceobservabilityConstruct {
7073
ObservabilityBuilder.builder()
7174
.account(account)
7275
.region(region)
76+
.addNewClusterObservabilityBuilderAddOns()
7377
.resourceProvider(ampWorkspaceName, new blueprints.CreateAmpProvider(ampWorkspaceName, ampWorkspaceName))
7478
.addOns(...addOns)
7579
.build(scope, stackId);

0 commit comments

Comments
 (0)