Skip to content

Commit

Permalink
simplify and combine terraform repo
Browse files Browse the repository at this point in the history
  • Loading branch information
nllarson committed Aug 20, 2024
1 parent aa5eea4 commit c2594a0
Show file tree
Hide file tree
Showing 25 changed files with 302 additions and 952 deletions.
121 changes: 55 additions & 66 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,26 +11,13 @@ This repository contains a Terraform template to provision Confluent Cloud envir

## Environment Overview

![env-overview](./assets/demo-env.png)

> Image Source: [./assets/demo-env.excalidraw](./assets/demo-env.excalidraw)
![env-overview](./assets/bwc_customer360.png)

## Prerequisites

1. [Sign up for Confluent Cloud](https://confluent.cloud/home) with your email.

> NOTE: Each trial is only good for 30 days, so if you've done this before you can add a +1, +2, etc suffix to the email to create "unique" accounts
> * ex) `[email protected]`
> * ex) `[email protected]`
- [ ] Verify email
- [ ] Boost free trial credits to $750 with additional promo codes (_codes subject to change_)
- $400 is given by default
- $50 -> `C50INTEG`
- $200 -> `DEVOPS200`
- $100 -> `CLOUD100`

> ⚠️️ Although you're now rolling in $750 of lush credits, be sure to tear your environment(s) down after each use.
> ⚠️️ Although you're now rolling in $400 of lush credits, be sure to tear your environment(s) down after each use.
2. [Create a Confluent Cloud API Key](https://registry.terraform.io/providers/confluentinc/confluent/latest/docs/guides/sample-project#create-a-cloud-api-key)

Expand All @@ -54,20 +41,14 @@ The `./template` folder contains a few key subfolders - in a real env, these wou

```txt
./template
├── kafka-ops-team
├── kafka-environment
│ └── main.tf # environment resources
├── kafka-product-team-{domain}
│ ├── development
│ │ ├── flink-statements
│ │ │ └── ... flink .sql files
│ │ ├── schemas
│ │ │ └── ... schema files
│ │ ├── main.tf # environment data sources
│ │ └── cluster-{name}.tf # provision cluster ${name} & cluster resources
│ ├── staging
│ │ └── ... mirrors development
│ └── production
│ │ └── ... mirrors staging
│ └── topics.tf # topics
│ └── flink.tf # flink statements
│ ├── flink-statements
│ │ └── ... flink .sql files
│ ├── schemas
│ │ └── ... schema files
├── modules
│ ├── confluent_cloud_environment # shared module to provision environments
│ ├── product_team_avro_topic # shared module to provision topics tied to an Avro schema
Expand All @@ -82,26 +63,20 @@ The `./template` folder contains a few key subfolders - in a real env, these wou
└── start-kafka.sh # script to run shadowtraffic, producing results to Kafka (configs required)
```

### kafka-ops-team

This repo (folder) holds the shared [Environment](https://docs.confluent.io/cloud/current/access-management/hierarchy/cloud-environments.html#environments-on-ccloud) configurations (think `development`, `staging`, `production`). All environments should be configured within this central ops-team space.

> A Confluent Cloud environment contains Kafka clusters and deployed components, such as Connect, ksqlDB, and Schema Registry. You can define multiple environments in an organization, and there is no charge for creating or using additional environments. Different departments or teams can use separate environments to avoid interfering with each other.
### kafka-product-team-{domain}
### kafka-environment

In organizations with domain-aligned teams, each team would have their own repo that manages their resources.
This repo (folder) holds the Confluent Cloud infrastructure and resources required for this demo. We leverage [Terraform](https://developer.hashicorp.com/terraform) to deploy all of these resources with [Confluent provider](https://registry.terraform.io/providers/confluentinc/confluent/1.83.0)

Product Team Resources (things they can create) Include -
The following resources will automatically created to give you a fully featured environment:

* Clusters
* Topics
* Schemas
* Flink Compute Pools
* Service Accounts / ACLs
* ... and more
* Environment
* Clusters
* Topics
* Schemas
* Flink Compute Pools
* Service Accounts / ACLs
* ... and more

With an Environment in place, Product Teams are empowered to create their own systems.

### modules

Expand Down Expand Up @@ -147,53 +122,67 @@ export TF_VAR_confluent_cloud_api_secret="<cloud_api_secret>"

### Provisioning Confluent Cloud **Environments**

First, provision your environments from the `kafka-ops-team` repo (folder).
First, provision your environments from the `kafka-environment` repo (folder).

1. `cd template/kafka-ops-team`
1. `cd template/kafka-environment`
2. `terraform init`
3. `terraform apply` # approve after review, this may take a few minutes to complete
- As of V1.80.0 of the Confluent Provider, you will receive a "Warning: Deprecated Resource" around Schema Registry. Ignore this.
- As of V2.0.0 of the Confluent Provider, this Warning should be gone.
4. Confirm the Environments are created in your [Confluent Cloud](https://confluent.cloud/home) account

If needed, the `kafka-ops-team/outputs.tf/staging-resource-ids` will emit a variety of useful identifiers, keys, & urls.
If needed, the `kafka-environment/outputs.tf/resource-ids` will emit a variety of useful identifiers, keys, & urls.

```bash
> terraform output staging-resource-ids
> terraform output resource-ids

<<EOT
====
Staging Environment ID: env-123456
Staging Schema Registry ID: lsrc-123456
Staging Schema Registry Rest Endpoint: https://psrc-123456.us-east1.gcp.confluent.cloud
Staging Environment ID: env-kkv293
Staging Schema Registry ID: def-3drm1o
Staging Schema Registry Rest Endpoint: https://eiw-23932.us-east1.gcp.confluent.cloud
Staging MetricsViewer API Key: xxxxx:xxxxxxxx
Staging EnvironmentAdmin/AccountAdmin API Key: xxxxx:xxxxxxxx
```
Staging EnvironmentAdmin/AccountAdmin API Key: Txxxxx:xxxxxxxx
### Provisioning Product Team Resources (Staging Environment)
Customer Cluster ID: xyz-g5n70n
Customer Flink Compute Pool ID: abc-1232ms
Customer Cluster Admin: xxxxx:xxxxxxxx
Next, provision your clusters, Flink compute pools, topics, and more via the product team repo (folder).
****************************
Metrics Scrape Job Configs
****************************
Flink Scrape Job URL: https://api.telemetry.confluent.cloud/v2/metrics/cloud/export?resource.compute_pool.id=abc-1232ms
Cluster Scrape Job URL: https://api.telemetry.confluent.cloud/v2/metrics/cloud/export?resource.kafka.id=xyz-g5n70n
> ⚠️ This is a 2-step process due to the use of a cluster-specific [aliased `provider`](https://developer.hashicorp.com/terraform/language/providers/configuration#alias-multiple-provider-configurations) to simplify the configuration of resources for the cluster. With the cluster-specific provider, you can just pass the entire aliased `provider` on the resources rather than repeating all the configurations.
**************
Client Configs
**************
Provision the cluster, Flink compute pool (optional), and cluster API Keys -
"bootstrap.servers": "SASL_SSL://pkc-619z3.us-east1.gcp.confluent.cloud:9092",
> Note: Make sure the aliased provider and kafka topic resources are commented out.
# Customer-Cluster-Developer-Write sasl jaas config
"sasl.jaas.config": "org.apache.kafka.common.security.plain.PlainLoginModule required username='xxxxx' password='xxxxxxxxxx';",
1. `cd template/kafka-product-team-customer/staging`
2. `terraform init`
3. `terraform apply` # approve after review
# Customer-Cluster-Developer-Read sasl jaas config
"sasl.jaas.config": "org.apache.kafka.common.security.plain.PlainLoginModule required username='xxxxx' password='xxxxxxxxxx';",
# schema registry
"schema.registry.url": "https://psrc-571gzn.us-east1.gcp.confluent.cloud",
"basic.auth.credentials.source": "USER_INFO",
"basic.auth.user.info": "xxxxx:xxxxxxxx",
The cluster-specific [aliased `provider`](https://developer.hashicorp.com/terraform/language/providers/configuration#alias-multiple-provider-configurations) can't be created until the cluster exists.
**************
**************
4. Uncomment the aliased provider as well as all other resources that leverage the provider (topics, flink statements, etc).
5. Run `terraform apply` # approve after review
Getting Started with Flink:
⚠️ There is no data in the cluster in this point. The following section will get data into the cluster via ShadowTraffic.
> confluent flink shell --compute-pool abc-1232ms --environment env-kkv293
> Copy `/staging` into `/production` and repeat the above steps if you'd like to provision a cluster in another environment. Modify the `display_name` value on the `/main.tf/confluent_environment` data source.
EOT
```

### Producing Data with ShadowTraffic

Expand Down
26 changes: 26 additions & 0 deletions template/kafka-environment/.terraform.lock.hcl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ terraform {
required_providers {
confluent = {
source = "confluentinc/confluent"
version = "1.80.0"
version = "1.83.0"
}
}
}
Expand Down Expand Up @@ -30,12 +30,16 @@ module "staging_environment" {
}
}

//module "production_environment" {
// source = "../modules/confluent_cloud_environment"
//
// environment_display_name = "production"
//
// providers = {
// confluent = confluent
// }
//}
module "customer_cluster" {
source = "../modules/product_team_standard_cluster"

cluster_display_name = "customer"
environment_id = module.staging_environment.id
enable_flink_workspace = true

providers = {
confluent = confluent
}

depends_on = [ module.staging_environment ]
}
Original file line number Diff line number Diff line change
@@ -1,55 +1,38 @@
output "shadowtraffic-config" {
output "resource-ids" {
value = <<-EOT
# Replace the value in `/shadowtraffic/orders/config/connections/staging-kafka.json` with the value below
====
{
"bootstrap.servers": "${module.customer_cluster.confluent_kafka_cluster.bootstrap_endpoint}",
"sasl.jaas.config": "org.apache.kafka.common.security.plain.PlainLoginModule required username='${module.customer_cluster.developer_write_api_key.id}' password='${module.customer_cluster.developer_write_api_key.secret}';",
"schema.registry.url": "${data.confluent_schema_registry_cluster.this.rest_endpoint}",
"basic.auth.user.info": "${module.customer_cluster.data_steward_api_key.id}:${module.customer_cluster.data_steward_api_key.secret}",
${title(module.staging_environment.confluent_environment.display_name)} Environment ID: ${module.staging_environment.id}
${title(module.staging_environment.confluent_environment.display_name)} Schema Registry ID: ${module.staging_environment.schema_registry_cluster.id}
${title(module.staging_environment.confluent_environment.display_name)} Schema Registry Rest Endpoint: ${module.staging_environment.schema_registry_cluster.rest_endpoint}
${title(module.staging_environment.confluent_environment.display_name)} MetricsViewer API Key: ${module.staging_environment.env_metrics_viewer_api_key.id}:${module.staging_environment.env_metrics_viewer_api_key.secret}
${title(module.staging_environment.confluent_environment.display_name)} EnvironmentAdmin/AccountAdmin API Key: ${module.staging_environment.env_admin_api_key.id}:${module.staging_environment.env_admin_api_key.secret}
"key.serializer": "org.apache.kafka.common.serialization.StringSerializer",
"value.serializer": "io.confluent.kafka.serializers.KafkaAvroSerializer",
"basic.auth.credentials.source": "USER_INFO",
"sasl.mechanism": "PLAIN",
"security.protocol": "SASL_SSL",
"client.dns.lookup": "use_all_dns_ips"
}
EOT

sensitive = true
}

output "resource-ids" {
value = <<-EOT
'${data.confluent_environment.this.display_name}' Environment ID: ${data.confluent_environment.this.id}
'${module.customer_cluster.confluent_kafka_cluster.display_name}' Cluster ID: ${module.customer_cluster.id}
'${module.customer_cluster.confluent_kafka_cluster.display_name}' Flink Compute Pool ID: ${module.customer_cluster.flink_compute_pool_id}
'${module.customer_cluster.confluent_kafka_cluster.display_name}' Cluster Admin: "${module.customer_cluster.cluster_admin_api_key.id}:${module.customer_cluster.cluster_admin_api_key.secret}"
${title(module.customer_cluster.confluent_kafka_cluster.display_name)} Cluster ID: ${module.customer_cluster.id}
${title(module.customer_cluster.confluent_kafka_cluster.display_name)} Flink Compute Pool ID: ${module.customer_cluster.flink_compute_pool_id}
${title(module.customer_cluster.confluent_kafka_cluster.display_name)} Cluster Admin: "${module.customer_cluster.cluster_admin_api_key.id}:${module.customer_cluster.cluster_admin_api_key.secret}"
****************************
Metrics Scrape Job Configs
****************************
Flink Scrape Job URL: https://api.telemetry.confluent.cloud/v2/metrics/cloud/export?resource.compute_pool.id=${module.customer_cluster.flink_compute_pool_id}
Cluster Scrape Job URL: https://api.telemetry.confluent.cloud/v2/metrics/cloud/export?resource.kafka.id=${module.customer_cluster.id}
Metrics API Username/Password - RUN `/kafka-ops-team > terraform output staging-resource-ids`
**************
Client Configs
**************
"bootstrap.servers": "${module.customer_cluster.confluent_kafka_cluster.bootstrap_endpoint}",
# '${module.customer_cluster.developer_write_service_account.display_name}' sasl jaas config
# ${title(module.customer_cluster.developer_write_service_account.display_name)} sasl jaas config
"sasl.jaas.config": "org.apache.kafka.common.security.plain.PlainLoginModule required username='${module.customer_cluster.developer_write_api_key.id}' password='${module.customer_cluster.developer_write_api_key.secret}';",
# '${module.customer_cluster.developer_read_service_account.display_name}' sasl jaas config
# ${title(module.customer_cluster.developer_read_service_account.display_name)} sasl jaas config
"sasl.jaas.config": "org.apache.kafka.common.security.plain.PlainLoginModule required username='${module.customer_cluster.developer_read_api_key.id}' password='${module.customer_cluster.developer_read_api_key.secret}';",
# schema registry
"schema.registry.url": "${data.confluent_schema_registry_cluster.this.rest_endpoint}",
"schema.registry.url": "${module.staging_environment.schema_registry_cluster.rest_endpoint}",
"basic.auth.credentials.source": "USER_INFO",
"basic.auth.user.info": "${module.customer_cluster.data_steward_api_key.id}:${module.customer_cluster.data_steward_api_key.secret}",
Expand All @@ -58,9 +41,33 @@ output "resource-ids" {
Getting Started with Flink:
> confluent flink shell --compute-pool ${module.customer_cluster.flink_compute_pool_id} --environment ${data.confluent_environment.this.id}
> confluent flink shell --compute-pool ${module.customer_cluster.flink_compute_pool_id} --environment ${module.staging_environment.id}
EOT

sensitive = true
}

output "shadowtraffic-config" {
value = <<-EOT
# Replace the value in `/shadowtraffic/orders/config/connections/staging-kafka.json` with the value below
{
"bootstrap.servers": "${module.customer_cluster.confluent_kafka_cluster.bootstrap_endpoint}",
"sasl.jaas.config": "org.apache.kafka.common.security.plain.PlainLoginModule required username='${module.customer_cluster.developer_write_api_key.id}' password='${module.customer_cluster.developer_write_api_key.secret}';",
"schema.registry.url": "${module.staging_environment.schema_registry_cluster.rest_endpoint}",
"basic.auth.user.info": "${module.customer_cluster.data_steward_api_key.id}:${module.customer_cluster.data_steward_api_key.secret}",
"key.serializer": "org.apache.kafka.common.serialization.StringSerializer",
"value.serializer": "io.confluent.kafka.serializers.KafkaAvroSerializer",
"basic.auth.credentials.source": "USER_INFO",
"sasl.mechanism": "PLAIN",
"security.protocol": "SASL_SSL",
"client.dns.lookup": "use_all_dns_ips"
}
EOT

sensitive = true
}

Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@
{ "name": "email", "type": "string" },
{ "name": "phone", "type": "string" },
{ "name": "address", "type": "string" },
{"name": "last_modified_date","type": "string" } // ISO 8601 date format
{ "name": "last_modified_date", "type": "string" }, // ISO 8601 date format
{
"name": "stores",
"name": "customer_info",
"type": {
"type": "array",
"items": {
"type": "record",
"name": "StoreInfo",
"name": "CustomerInfo",
"fields": [
{ "name": "store_id", "type": "string" },
{ "name": "customer_id", "type": "string" },
Expand Down
Loading

0 comments on commit c2594a0

Please sign in to comment.