From 967454d5b72988e279ad49d0127d96ec1047372b Mon Sep 17 00:00:00 2001 From: Anca Lita <27920906+ancalita@users.noreply.github.com> Date: Thu, 25 Sep 2025 07:20:06 +0100 Subject: [PATCH 1/4] add changes for Bedrock usage --- aws/deploy/main.tf.template | 35 ++++++++++++++++++++++--- aws/rasa/assistant/values.template.yaml | 12 +++++++++ 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/aws/deploy/main.tf.template b/aws/deploy/main.tf.template index 773f9ef..f7df385 100644 --- a/aws/deploy/main.tf.template +++ b/aws/deploy/main.tf.template @@ -586,6 +586,34 @@ module "iam_role_rds_database" { } } +# Bedrock IAM Access Policy +resource "aws_iam_policy" "bedrock_access" { + name = "${NAME}_bedrock_access" + path = "/" + description = "Rasa ${NAME} Bedrock model access for inference and logging" + + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Effect = "Allow" + Action = [ + "bedrock:InvokeModel", + "bedrock:InvokeModelWithResponseStream" + ] + Resource = "*" + }, + { + Effect = "Allow" + Action = [ + "bedrock:GetModelInvocationLoggingConfiguration", + ] + Resource = "*" + }, + ] + }) +} + module "iam_role_assistant" { source = "terraform-aws-modules/iam/aws//modules/iam-role-for-service-accounts-eks" @@ -594,9 +622,10 @@ module "iam_role_assistant" { role_name = "${NAME}-assistant" role_policy_arns = { - s3 = aws_iam_policy.s3_access.arn - redis = aws_iam_policy.redis_access.arn - rds = aws_iam_policy.rds_database_access.arn + s3_policy = aws_iam_policy.assistant.arn + redis_policy = aws_iam_policy.redis_access.arn + rds_policy = aws_iam_policy.rds_database_access.arn + bedrock_policy = aws_iam_policy.bedrock_access.arn } oidc_providers = { diff --git a/aws/rasa/assistant/values.template.yaml b/aws/rasa/assistant/values.template.yaml index 77919c7..ed8bfa2 100644 --- a/aws/rasa/assistant/values.template.yaml +++ b/aws/rasa/assistant/values.template.yaml @@ -30,6 +30,14 @@ rasa: models: - model: text-embedding-3-small provider: openai + - id: anca-bedrock + models: + - provider: bedrock + model: anthropic.claude-3-7-sonnet-20250219-v1:0 + model_id: arn:aws:bedrock:us-east-1:536697270625:inference-profile/us.anthropic.claude-3-7-sonnet-20250219-v1:0 + aws_region_name: us-east-1 + request_timeout: 7 + max_tokens: 256 models: enabled: false # Configure the assistant to use our PostgreSQL instance as the Tracker Store, which records the assistant's conversations. @@ -66,6 +74,10 @@ rasa: additionalArgs: - --remote-storage - aws + - --model + - 20250924-160621-succulent-ravelin.tar.gz + - --debug + - --enable-api # Define the environment variables that Rasa needs to function and interact with the above services. # Note here that some of the values are plaintext environment variables and some are configured to be pulled from the Kubernetes Secret we created earlier. additionalEnv: From b50514acd149650a47c760bc782bab9bffb06240 Mon Sep 17 00:00:00 2001 From: Anca Lita <27920906+ancalita@users.noreply.github.com> Date: Thu, 25 Sep 2025 09:44:43 +0100 Subject: [PATCH 2/4] add changes for elasticache cluster mode --- aws/configure/get-infra-values.sh | 2 +- aws/deploy/main.tf.template | 15 ++++++++++----- aws/rasa/assistant/values.template.yaml | 1 + 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/aws/configure/get-infra-values.sh b/aws/configure/get-infra-values.sh index 691d8da..6e56c14 100644 --- a/aws/configure/get-infra-values.sh +++ b/aws/configure/get-infra-values.sh @@ -25,7 +25,7 @@ export DB_PORT=$($TF_CMD -chdir=$TARGET_DIR_ABSOLUTE output -raw db_port) export DB_HOST=$($TF_CMD -chdir=$TARGET_DIR_ABSOLUTE output -raw db_host) export DB_HOST="${DB_HOST%:$DB_PORT}" -export REDIS_HOST=$($TF_CMD -chdir=$TARGET_DIR_ABSOLUTE output -raw elasticache_primary_endpoint) +export REDIS_HOST=$($TF_CMD -chdir=$TARGET_DIR_ABSOLUTE output -raw elasticache_cfg_endpoint) export REDIS_CLUSTER_NAME=$($TF_CMD -chdir=$TARGET_DIR_ABSOLUTE output -raw elasticache_cluster_name) export SERVICE_ACCOUNT_DNS=$($TF_CMD -chdir=$TARGET_DIR_ABSOLUTE output -raw service_account_dns) diff --git a/aws/deploy/main.tf.template b/aws/deploy/main.tf.template index f7df385..14a9976 100644 --- a/aws/deploy/main.tf.template +++ b/aws/deploy/main.tf.template @@ -392,6 +392,11 @@ resource "aws_elasticache_parameter_group" "default" { name = "maxmemory-policy" value = "volatile-lru" } + + parameter { + name = "cluster-enabled" + value = "yes" + } } @@ -434,12 +439,12 @@ resource "aws_elasticache_user_group" "iam_user_group" { resource "aws_elasticache_replication_group" "group1" { automatic_failover_enabled = true - multi_az_enabled = true - preferred_cache_cluster_azs = slice(var.zones, 0, 2) replication_group_id = "${local.elasticache_id}-group1" description = "Rasa ${NAME} Redis Elasticache group 1" node_type = "cache.m5.xlarge" - num_cache_clusters = 2 + num_node_groups = 2 + replicas_per_node_group = 1 + cluster_mode = "enabled" parameter_group_name = aws_elasticache_parameter_group.default.name engine = "redis" @@ -455,8 +460,8 @@ resource "aws_elasticache_replication_group" "group1" { security_group_ids = [module.elasticache_security_group.security_group_id] } -output "elasticache_primary_endpoint" { - value = aws_elasticache_replication_group.group1.primary_endpoint_address +output "elasticache_cfg_endpoint" { + value = aws_elasticache_replication_group.group1.configuration_endpoint_address } output "redis_iam_user" { diff --git a/aws/rasa/assistant/values.template.yaml b/aws/rasa/assistant/values.template.yaml index ed8bfa2..1db4d8e 100644 --- a/aws/rasa/assistant/values.template.yaml +++ b/aws/rasa/assistant/values.template.yaml @@ -59,6 +59,7 @@ rasa: username: ${REDIS_USER} use_ssl: true key_prefix: ${NAME} + deployment_mode: "cluster" # Configure the assistant to use the Kafka broker. This allows us to perform further processing on the messages, like using the Rasa Studio Conversation View or Rasa Pro Analytics. eventBroker: enabled: true From ba0c6aa2fa39a15ef2a7eb136cfbb31ba2ec15b5 Mon Sep 17 00:00:00 2001 From: Anca Lita <27920906+ancalita@users.noreply.github.com> Date: Tue, 30 Sep 2025 08:55:33 +0100 Subject: [PATCH 3/4] update model path env var --- aws/setup/environment-variables.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/aws/setup/environment-variables.sh b/aws/setup/environment-variables.sh index 7642421..eb377e2 100644 --- a/aws/setup/environment-variables.sh +++ b/aws/setup/environment-variables.sh @@ -23,6 +23,8 @@ export DB_STUDIO_PASSWORD="your-studio-db-password" export RASA_PRO_LICENSE="Your Rasa Pro license string here" # Your OpenAI API Key. export OPENAI_API_KEY="Your OpenAI API Key here" +# The name of the model that will be uploaded to the model bucket as an initial model. +export MODEL_PATH="20250924-160621-succulent-ravelin.tar.gz" #-------------------------------- # You can optionally change the following environment variables if you have specific requirements From a645e36daa2c41e778ffe8e5f9938a80a2099bb9 Mon Sep 17 00:00:00 2001 From: Anca Lita <27920906+ancalita@users.noreply.github.com> Date: Fri, 10 Oct 2025 08:41:41 +0100 Subject: [PATCH 4/4] Update AWS playbook to include changes for rasa-pro-services & AWS MSK IAM auth enabled (#5) * add changes for kafka msk * fix path in endpoints * fix volume mount specification * add new iam enabled env vars per AWS service to rasa-pro values * [PF-489] Update AWS playbook to include rasa-pro-services deployment (#6) * update playbook to include rasa-pro-services deployment * fix values.template.yaml for rasa-pro-services to use a new helm chart release, add analytics db username to the rds policy * define analytics specific service account * make updates to rasa-pro-services values to use 1.3.0-rc.2 rasa helm chart --- .gitignore | 3 +- aws/configure/db-init.template.yaml | 7 + aws/configure/get-infra-values.sh | 5 + aws/deploy/main.tf.template | 165 +++++++++++++++++++++++- aws/permissions/policy.json | 4 +- aws/rasa/assistant/setup-assistant.sh | 10 +- aws/rasa/assistant/values.template.yaml | 93 +++++++++++-- aws/rasa/kafka/install-kafka.sh | 118 ++++++++--------- aws/setup/environment-variables.sh | 11 +- 9 files changed, 329 insertions(+), 87 deletions(-) diff --git a/.gitignore b/.gitignore index 07dd58a..461b46d 100644 --- a/.gitignore +++ b/.gitignore @@ -44,4 +44,5 @@ aws/studio/certificate.yaml secret_db.json # Dev -aws/setup/environment-variables-dev.sh \ No newline at end of file +aws/setup/environment-variables-dev.sh +AmazonRootCA1.pem \ No newline at end of file diff --git a/aws/configure/db-init.template.yaml b/aws/configure/db-init.template.yaml index f874d39..9d0d17a 100644 --- a/aws/configure/db-init.template.yaml +++ b/aws/configure/db-init.template.yaml @@ -35,6 +35,13 @@ spec: echo "GRANT ALL PRIVILEGES ON SCHEMA public TO $DB_STUDIO_USERNAME;" | psql -qtAX --set=sslmode=require echo "granted schema public to keycloak" + echo "create analytics database and user" + echo "CREATE USER $DB_ANALYTICS_USERNAME;" | psql -qtAX --set=sslmode=require + echo "GRANT rds_iam TO $DB_ANALYTICS_USERNAME;" | psql -qtAX --set=sslmode=require + echo "CREATE DATABASE $DB_ANALYTICS_DATABASE WITH ENCODING = 'UTF8';" | psql -qtAX --set=sslmode=require + echo "GRANT ALL PRIVILEGES ON DATABASE $DB_ANALYTICS_DATABASE TO $DB_ANALYTICS_USERNAME;" | psql -qtAX --set=sslmode=require + echo "ALTER DATABASE $DB_ANALYTICS_DATABASE OWNER TO $DB_ANALYTICS_USERNAME;" | psql -qtAX --set=sslmode=require + sleep 10 echo "done" env: diff --git a/aws/configure/get-infra-values.sh b/aws/configure/get-infra-values.sh index 6e56c14..e9f0e8a 100644 --- a/aws/configure/get-infra-values.sh +++ b/aws/configure/get-infra-values.sh @@ -28,8 +28,11 @@ export DB_HOST="${DB_HOST%:$DB_PORT}" export REDIS_HOST=$($TF_CMD -chdir=$TARGET_DIR_ABSOLUTE output -raw elasticache_cfg_endpoint) export REDIS_CLUSTER_NAME=$($TF_CMD -chdir=$TARGET_DIR_ABSOLUTE output -raw elasticache_cluster_name) +export KAFKA_BOOTSTRAP_SERVER=$($TF_CMD -chdir=$TARGET_DIR_ABSOLUTE output -raw msk_bootstrap_brokers | awk -F',' '{print $1}') + export SERVICE_ACCOUNT_DNS=$($TF_CMD -chdir=$TARGET_DIR_ABSOLUTE output -raw service_account_dns) export SERVICE_ACCOUNT_ASSISTANT=$($TF_CMD -chdir=$TARGET_DIR_ABSOLUTE output -raw service_account_assistant) +export SERVICE_ACCOUNT_ANALYTICS=$($TF_CMD -chdir=$TARGET_DIR_ABSOLUTE output -raw service_account_analytics) export SERVICE_ACCOUNT_STUDIO=$($TF_CMD -chdir=$TARGET_DIR_ABSOLUTE output -raw service_account_studio) echo "Infrastructure values fetched successfully:" @@ -42,4 +45,6 @@ echo "REDIS_HOST=$REDIS_HOST" echo "REDIS_CLUSTER_NAME=$REDIS_CLUSTER_NAME" echo "SERVICE_ACCOUNT_DNS=$SERVICE_ACCOUNT_DNS" echo "SERVICE_ACCOUNT_ASSISTANT=$SERVICE_ACCOUNT_ASSISTANT" +echo "SERVICE_ACCOUNT_ANALYTICS=$SERVICE_ACCOUNT_ANALYTICS" echo "SERVICE_ACCOUNT_STUDIO=$SERVICE_ACCOUNT_STUDIO" +echo "KAFKA_BOOTSTRAP_SERVER=$KAFKA_BOOTSTRAP_SERVER" diff --git a/aws/deploy/main.tf.template b/aws/deploy/main.tf.template index 14a9976..44de258 100644 --- a/aws/deploy/main.tf.template +++ b/aws/deploy/main.tf.template @@ -27,6 +27,10 @@ variable "elasticache_subnets" { default = ["$CIDR_ELASTICACHE_A", "$CIDR_ELASTICACHE_B", "$CIDR_ELASTICACHE_C"] } +variable "msk_subnets" { + default = ["$CIDR_MSK_A", "$CIDR_MSK_B", "$CIDR_MSK_C"] +} + terraform { required_providers { aws = { @@ -101,6 +105,20 @@ module "vpc" { } } +# MSK Subnets ========================================= + +resource "aws_subnet" "msk_subnets" { + count = length(var.msk_subnets) + + vpc_id = module.vpc.vpc_id + cidr_block = var.msk_subnets[count.index] + availability_zone = var.zones[count.index] + + tags = { + Name = "${NAME}-msk-${count.index + 1}" + "kubernetes.io/cluster/${NAME}" = "shared" + } +} # Kubernetes cluster EKS ========================================= @@ -477,6 +495,74 @@ output "elasticache_cluster_name" { } +# MSK Kafka Cluster ========================================= + +locals { + msk_cluster_id = "rasa-${NAME}-kafka" +} + +module "msk_security_group" { + source = "terraform-aws-modules/security-group/aws" + version = "~> 5.3" + + name = "rasa-${NAME}-msk" + description = "Security group for MSK ${NAME}" + vpc_id = module.vpc.vpc_id + + ingress_cidr_blocks = module.vpc.private_subnets_cidr_blocks + ingress_rules = ["kafka-broker-tcp", "kafka-broker-tls-tcp"] + + egress_cidr_blocks = [module.vpc.vpc_cidr_block] + egress_rules = ["all-all"] + + tags = { + Name = "rasa-${NAME}-msk" + } +} + +resource "aws_msk_cluster" "kafka_cluster" { + cluster_name = local.msk_cluster_id + kafka_version = "3.8.x" + number_of_broker_nodes = 3 + + broker_node_group_info { + instance_type = "kafka.m5.large" + client_subnets = aws_subnet.msk_subnets[*].id + security_groups = [module.msk_security_group.security_group_id] + + storage_info { + ebs_storage_info { + volume_size = 100 + } + } + } + + client_authentication { + sasl { + iam = true + } + } + + encryption_info { + encryption_in_transit { + client_broker = "TLS" + in_cluster = true + } + } + + tags = { + Name = local.msk_cluster_id + } +} + +output "msk_cluster_arn" { + value = aws_msk_cluster.kafka_cluster.arn +} + +output "msk_bootstrap_brokers" { + value = aws_msk_cluster.kafka_cluster.bootstrap_brokers_sasl_iam +} + # DNS Identity ========================================= module "iam_role_dns" { @@ -505,7 +591,7 @@ output "service_account_dns" { } -# Rasa Assistent Identity ========================================= +# Rasa Assistant Identity ========================================= # S3 IAM Access Policy @@ -566,7 +652,8 @@ resource "aws_iam_policy" "rds_database_access" { "rds-db:connect" ] Resource = [ - "arn:aws:rds-db:${REGION}:${data.aws_caller_identity.current.account_id}:dbuser:${module.rds_main.db_instance_resource_id}/${DB_ASSISTANT_USERNAME}" + "arn:aws:rds-db:${REGION}:${data.aws_caller_identity.current.account_id}:dbuser:${module.rds_main.db_instance_resource_id}/${DB_ASSISTANT_USERNAME}", + "arn:aws:rds-db:${REGION}:${data.aws_caller_identity.current.account_id}:dbuser:${module.rds_main.db_instance_resource_id}/${DB_ANALYTICS_USERNAME}" ] }, ] @@ -619,6 +706,44 @@ resource "aws_iam_policy" "bedrock_access" { }) } +# MSK IAM Access Policy +resource "aws_iam_policy" "msk_access" { + name = "${NAME}_msk_access" + path = "/" + description = "Rasa ${NAME} MSK Kafka access" + + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Effect = "Allow" + Action = [ + "kafka-cluster:Connect", + "kafka-cluster:DescribeCluster" + ] + Resource = "*" + }, + { + Effect = "Allow" + Action = [ + "kafka-cluster:*Topic*", + "kafka-cluster:WriteData", + "kafka-cluster:ReadData" + ] + Resource = "*" + }, + { + "Effect": "Allow", + "Action": [ + "kafka-cluster:AlterGroup", + "kafka-cluster:DescribeGroup" + ], + "Resource": "*" + } + ] + }) +} + module "iam_role_assistant" { source = "terraform-aws-modules/iam/aws//modules/iam-role-for-service-accounts-eks" @@ -627,10 +752,11 @@ module "iam_role_assistant" { role_name = "${NAME}-assistant" role_policy_arns = { - s3_policy = aws_iam_policy.assistant.arn - redis_policy = aws_iam_policy.redis_access.arn - rds_policy = aws_iam_policy.rds_database_access.arn - bedrock_policy = aws_iam_policy.bedrock_access.arn + s3 = aws_iam_policy.s3_access.arn + redis = aws_iam_policy.redis_access.arn + rds = aws_iam_policy.rds_database_access.arn + bedrock = aws_iam_policy.bedrock_access.arn + msk = aws_iam_policy.msk_access.arn } oidc_providers = { @@ -649,6 +775,33 @@ output "service_account_assistant" { value = local.service_account_assistant } +module "iam_role_analytics" { + source = "terraform-aws-modules/iam/aws//modules/iam-role-for-service-accounts-eks" + version = "~> 5.59" + + role_name = "${NAME}-analytics" + + role_policy_arns = { + rds = aws_iam_policy.rds_database_access.arn + msk = aws_iam_policy.msk_access.arn + } + + oidc_providers = { + rasa = { + provider_arn = module.eks.oidc_provider_arn + namespace_service_accounts = ["${NAMESPACE}:rasa-analytics"] + } + } +} + +locals { + service_account_analytics = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/${module.iam_role_analytics.iam_role_name}" +} + +output "service_account_analytics" { + value = local.service_account_analytics +} + # Rasa Studio Identity ========================================= diff --git a/aws/permissions/policy.json b/aws/permissions/policy.json index b3c2bea..8d08cea 100644 --- a/aws/permissions/policy.json +++ b/aws/permissions/policy.json @@ -8,7 +8,8 @@ "arn:aws:iam::*:role/aws-service-role/eks.amazonaws.com/AWSServiceRoleForAmazonEKS", "arn:aws:iam::*:role/aws-service-role/eks-nodegroup.amazonaws.com/AWSServiceRoleForAmazonEKSNodegroup", "arn:aws:iam::*:role/aws-service-role/elasticache.amazonaws.com/AWSServiceRoleForElastiCache", - "arn:aws:iam::*:role/aws-service-role/rds.amazonaws.com/AWSServiceRoleForRDS" + "arn:aws:iam::*:role/aws-service-role/rds.amazonaws.com/AWSServiceRoleForRDS", + "arn:aws:iam::*:role/aws-service-role/kafka.amazonaws.com/AWSServiceRoleForKafka" ] }, { @@ -100,6 +101,7 @@ "elasticache:ModifyUser", "elasticache:ModifyUserGroup", "elasticache:Connect", + "kafka:*", "iam:AttachRolePolicy", "iam:CreateOpenIDConnectProvider", "iam:CreatePolicy", diff --git a/aws/rasa/assistant/setup-assistant.sh b/aws/rasa/assistant/setup-assistant.sh index 76c9118..0709710 100755 --- a/aws/rasa/assistant/setup-assistant.sh +++ b/aws/rasa/assistant/setup-assistant.sh @@ -22,20 +22,18 @@ kubectl get ns # This Helm chart contains instructions for setting up the Rasa bot and Analytics components. print_info "Pulling Rasa Helm chart..." mkdir $SCRIPT_DIR/repos -helm pull oci://europe-west3-docker.pkg.dev/rasa-releases/helm-charts/rasa --version 1.2.5 --untar --destination $SCRIPT_DIR/repos/rasa-helm +helm pull oci://europe-west3-docker.pkg.dev/rasa-releases/helm-charts/rasa --version 1.3.0-rc.2 --untar --destination $SCRIPT_DIR/repos/rasa-helm # Next, we'll ensure that other passwords and secret values that Rasa requires are set, before creating a Kubernetes Secret to securely store them in a way that we can reference later on: print_info "Creating secrets for the Rasa assistant to use..." export AUTH_TOKEN=$(openssl rand -hex 8 | base64) export JWT_SECRET=$(openssl rand -hex 8 | base64) -export KAFKA_CLIENT_PASSWORD=$(kubectl get secret kafka-user-passwords -n $NAMESPACE -o jsonpath='{.data.client-passwords}' | base64 -d | cut -d ',' -f 1) export RASA_PRO_LICENSE=${RASA_PRO_LICENSE:-'Rasa License is not set! Set it manually with `export RASA_PRO_LICENSE=yourlicense`'} export OPENAI_API_KEY=${OPENAI_API_KEY:-'OpenAI API Key is not set! Set it manually with `export OPENAI_API_KEY=yourkey`'} print_info "Secret values retrieved. If any of the values below are not set, be sure to set them manually and re-run this script." print_info "AUTH_TOKEN: $AUTH_TOKEN" print_info "JWT_SECRET: $JWT_SECRET" -print_info "KAFKA_CLIENT_PASSWORD: $KAFKA_CLIENT_PASSWORD" print_info "RASA_PRO_LICENSE: $RASA_PRO_LICENSE" print_info "OPENAI_API_KEY: $OPENAI_API_KEY" @@ -45,5 +43,7 @@ create secret generic rasa-secrets \ --from-literal=rasaProLicense="$(echo $RASA_PRO_LICENSE )" \ --from-literal=authToken="$(echo $AUTH_TOKEN )" \ --from-literal=jwtSecret="$(echo $JWT_SECRET)" \ ---from-literal=kafkaSslPassword="$(echo $KAFKA_CLIENT_PASSWORD)" \ ---from-literal=openaiApiKey="$(echo $OPENAI_API_KEY)" \ No newline at end of file +--from-literal=openaiApiKey="$(echo $OPENAI_API_KEY)" + +kubectl --namespace $NAMESPACE create secret generic msk-ssl-ca --from-file=$SCRIPT_DIR/AmazonRootCA1.pem +print_info "Kubernetes secret created successfully!" \ No newline at end of file diff --git a/aws/rasa/assistant/values.template.yaml b/aws/rasa/assistant/values.template.yaml index 1db4d8e..a38fffa 100644 --- a/aws/rasa/assistant/values.template.yaml +++ b/aws/rasa/assistant/values.template.yaml @@ -1,5 +1,18 @@ rasa: enabled: true + image: + repository: "europe-west3-docker.pkg.dev/rasa-releases/rasa-pro/rasa-pro" + pullPolicy: IfNotPresent + tag: "3.14.0rc2" + volumeMounts: + - name: amazon-root-ca + mountPath: /app/AmazonRootCA1.pem + subPath: AmazonRootCA1.pem + readOnly: true + volumes: + - name: amazon-root-ca + secret: + secretName: msk-ssl-ca # Configure the service account which allows Rasa to interact with AWS resources like reading data from Cloud Storage buckets. serviceAccountName: rasa-assistant serviceAccount: @@ -64,13 +77,13 @@ rasa: eventBroker: enabled: true type: kafka - security_protocol: SASL_PLAINTEXT - sasl_mechanism: PLAIN + security_protocol: SASL_SSL + sasl_mechanism: OAUTHBEARER topic: rasa - url: kafka-controller-headless.${NAMESPACE}.svc.cluster.local:9092 - sasl_username: ${KAFKA_USER} - sasl_password: ${KAFKA_PASSWORD} - ssl_check_hostname: false + url: ${KAFKA_BOOTSTRAP_SERVER} + ssl_check_hostname: true + ssl_cafile: AmazonRootCA1.pem + partition_by_sender: true # We'll configure Rasa to use Google Cloud Storage for remote storage, so we can load models from the buckets we created earlier. additionalArgs: - --remote-storage @@ -88,6 +101,8 @@ rasa: value: "true" - name: RDS_SQL_DB_AWS_IAM_ENABLED value: "true" + - name: KAFKA_MSK_AWS_IAM_ENABLED + value: "true" - name: AWS_DEFAULT_REGION value: ${AWS_REGION} - name: SQL_TRACKER_STORE_SSL_MODE @@ -96,25 +111,22 @@ rasa: value: production - name: BUCKET_NAME value: ${MODEL_BUCKET} + - name: MODEL_PATH + value: ${MODEL_PATH} - name: DB_HOST value: ${DB_HOST} - name: DB_DATABASE value: ${DB_ASSISTANT_DATABASE} - name: DB_USER value: assistant - - name: KAFKA_PASSWORD - valueFrom: - secretKeyRef: - name: rasa-secrets - key: kafkaSslPassword - - name: KAFKA_USER - value: kafka - name: REDIS_HOST value: ${REDIS_HOST} - name: REDIS_USER value: ${REDIS_USER} - name: AWS_ELASTICACHE_CLUSTER_NAME value: ${REDIS_CLUSTER_NAME} + - name: KAFKA_BOOTSTRAP_SERVER + value: ${KAFKA_BOOTSTRAP_SERVER} - name: RASA_PRO_LICENSE valueFrom: secretKeyRef: @@ -128,7 +140,60 @@ rasa: # Disable other Rasa components for now. # https://rasa.com/docs/reference/integrations/analytics/ rasaProServices: - enabled: false + enabled: true + replicaCount: 1 + image: + repository: "europe-west3-docker.pkg.dev/rasa-releases/rasa-pro/rasa-pro-services" + pullPolicy: IfNotPresent + tag: "3.6.0rc1" + volumeMounts: + - name: amazon-root-ca + mountPath: /app/AmazonRootCA1.pem + subPath: AmazonRootCA1.pem + readOnly: true + volumes: + - name: amazon-root-ca + secret: + secretName: msk-ssl-ca + service: + type: ClusterIP + port: 8732 + targetPort: 8732 + serviceAccountName: rasa-analytics + serviceAccount: + create: true + name: rasa-analytics + annotations: + eks.amazonaws.com/role-arn: ${SERVICE_ACCOUNT_ANALYTICS} + loggingLevel: "DEBUG" + useCloudProviderIam: + enabled: true + provider: "aws" + region: "${AWS_REGION}" + database: + enableAwsRdsIam: true + username: ${DB_ANALYTICS_USERNAME} + hostname: ${DB_HOST} + port: ${DB_PORT} + databaseName: ${DB_ANALYTICS_DATABASE} + sslMode: "require" + kafka: + enableAwsMskIam: true + brokerAddress: ${KAFKA_BOOTSTRAP_SERVER} + topic: "rasa" + dlqTopic: "rasa-events-dlq" + saslMechanism: "OAUTHBEARER" + securityProtocol: "SASL_SSL" + sslCaLocation: "AmazonRootCA1.pem" + additionalEnv: + - name: RASA_PRO_LICENSE + valueFrom: + secretKeyRef: + name: rasa-secrets + key: rasaProLicense + - name: PORT + value: "8732" + # https://rasa.com/docs/action-server actionServer: enabled: false diff --git a/aws/rasa/kafka/install-kafka.sh b/aws/rasa/kafka/install-kafka.sh index ebc68cf..2a3f15e 100755 --- a/aws/rasa/kafka/install-kafka.sh +++ b/aws/rasa/kafka/install-kafka.sh @@ -24,66 +24,66 @@ kubectl create namespace $NAMESPACE kubectl label namespace $NAMESPACE istio-injection=enabled # Create a storage class for the Kafka cluster -kubectl apply -f $SCRIPT_DIR/storage-class.yaml +#kubectl apply -f $SCRIPT_DIR/storage-class.yaml # Create a random 16 character password for Kafka to use for authentication and then inject it into the Kafka configuration file. -print_info "Generating a random 16 character password for Kafka to use for authentication..." -export KAFKA_PASSWORD=$(openssl rand -hex 16) -envsubst < $SCRIPT_DIR/kafka.template.yaml > $SCRIPT_DIR/kafka.yaml -print_info "Kafka password: $KAFKA_PASSWORD" -print_info "Kafka configuration file generated successfully!" +#print_info "Generating a random 16 character password for Kafka to use for authentication..." +#export KAFKA_PASSWORD=$(openssl rand -hex 16) +#envsubst < $SCRIPT_DIR/kafka.template.yaml > $SCRIPT_DIR/kafka.yaml +#print_info "Kafka password: $KAFKA_PASSWORD" +#print_info "Kafka configuration file generated successfully!" # We'll fetch the automatically generated password from the previous step, and then use it to create a couple of configuration files locally that act as configuration for Rasa to be able to connect to Kafka -print_info "Installing Kafka to the cluster..." -helm repo add bitnami https://charts.bitnami.com/bitnami -print_info "First, uninstalling existing Kafka from the cluster..." -# We ignore an error when there is no existing Kafka installation -helm uninstall kafka -n $NAMESPACE || true -helm upgrade --install -n $NAMESPACE kafka bitnami/kafka -f $SCRIPT_DIR/kafka.yaml --version 32.3.2 -print_info "Kafka installed successfully!" - -print_info "Generating client configuration for Rasa to use to connect to Kafka..." -envsubst < $SCRIPT_DIR/client.properties.template > $SCRIPT_DIR/client.properties -envsubst < $SCRIPT_DIR/kafka_jaas.conf.template > $SCRIPT_DIR/kafka_jaas.conf -print_info "Client configuration for Rasa to use to connect to Kafka generated successfully!" - -# Next, we need to create Kafka topics that Rasa will use to send data through. We'll use the configuration files we've just generated which will also confirm that all the authentication is working properly. -print_info "Starting a Kafka client to test authentication and create topics..." -kubectl run kafka-client --restart='Never' --image bitnamilegacy/kafka:3.4.0-debian-11-r15 --namespace $NAMESPACE \ ---env="KAFKA_OPTS=-Djava.security.auth.login.config=/tmp/kafka_jaas.conf" \ ---env="NAMESPACE=$NAMESPACE" \ ---command -- sleep infinity - -print_info "Waiting for the Kafka client pod to be ready..." -kubectl wait --for=condition=Ready pod/kafka-client --namespace $NAMESPACE --timeout=60s - -print_info "Ready! Copying configuration files into the pod so we can authenticate..." -kubectl cp --namespace $NAMESPACE $SCRIPT_DIR/client.properties kafka-client:/tmp/client.properties -kubectl cp --namespace $NAMESPACE $SCRIPT_DIR/kafka_jaas.conf kafka-client:/tmp/kafka_jaas.conf - -print_info "Checking Kafka service is running..." -kubectl get svc -n $NAMESPACE | grep kafka - -print_info "Kafka service is running! Creating Kafka topics..." -print_info "It's normal to see connection errors here, as the client is not yet connected to the Kafka cluster. You should eventually see the topics created." - -kubectl exec kafka-client --namespace $NAMESPACE -- kafka-topics.sh \ - --bootstrap-server kafka.$NAMESPACE.svc.cluster.local:9092 \ - --command-config /tmp/client.properties \ - --create --topic rasa --if-not-exists - -kubectl exec kafka-client --namespace $NAMESPACE -- kafka-topics.sh \ - --bootstrap-server kafka.$NAMESPACE.svc.cluster.local:9092 \ - --command-config /tmp/client.properties \ - --create --topic rasa-events-dlq --if-not-exists - -print_info "Listing all topics:" -kubectl exec kafka-client --namespace $NAMESPACE -- kafka-topics.sh \ - --bootstrap-server kafka.$NAMESPACE.svc.cluster.local:9092 \ - --command-config /tmp/client.properties \ - --list - -print_info "Cleaning up..." -kubectl delete pod kafka-client --namespace $NAMESPACE - -print_info "Topic creation completed and temporary pod cleaned up." \ No newline at end of file +#print_info "Installing Kafka to the cluster..." +#helm repo add bitnami https://charts.bitnami.com/bitnami +#print_info "First, uninstalling existing Kafka from the cluster..." +## We ignore an error when there is no existing Kafka installation +#helm uninstall kafka -n $NAMESPACE || true +#helm upgrade --install -n $NAMESPACE kafka bitnami/kafka -f $SCRIPT_DIR/kafka.yaml --version 32.3.2 +#print_info "Kafka installed successfully!" + +#print_info "Generating client configuration for Rasa to use to connect to Kafka..." +#envsubst < $SCRIPT_DIR/client.properties.template > $SCRIPT_DIR/client.properties +#envsubst < $SCRIPT_DIR/kafka_jaas.conf.template > $SCRIPT_DIR/kafka_jaas.conf +#print_info "Client configuration for Rasa to use to connect to Kafka generated successfully!" +# +## Next, we need to create Kafka topics that Rasa will use to send data through. We'll use the configuration files we've just generated which will also confirm that all the authentication is working properly. +#print_info "Starting a Kafka client to test authentication and create topics..." +#kubectl run kafka-client --restart='Never' --image bitnamilegacy/kafka:3.4.0-debian-11-r15 --namespace $NAMESPACE \ +#--env="KAFKA_OPTS=-Djava.security.auth.login.config=/tmp/kafka_jaas.conf" \ +#--env="NAMESPACE=$NAMESPACE" \ +#--command -- sleep infinity +# +#print_info "Waiting for the Kafka client pod to be ready..." +#kubectl wait --for=condition=Ready pod/kafka-client --namespace $NAMESPACE --timeout=60s +# +#print_info "Ready! Copying configuration files into the pod so we can authenticate..." +#kubectl cp --namespace $NAMESPACE $SCRIPT_DIR/client.properties kafka-client:/tmp/client.properties +#kubectl cp --namespace $NAMESPACE $SCRIPT_DIR/kafka_jaas.conf kafka-client:/tmp/kafka_jaas.conf +# +#print_info "Checking Kafka service is running..." +#kubectl get svc -n $NAMESPACE | grep kafka +# +#print_info "Kafka service is running! Creating Kafka topics..." +#print_info "It's normal to see connection errors here, as the client is not yet connected to the Kafka cluster. You should eventually see the topics created." +# +#kubectl exec kafka-client --namespace $NAMESPACE -- kafka-topics.sh \ +# --bootstrap-server kafka.$NAMESPACE.svc.cluster.local:9092 \ +# --command-config /tmp/client.properties \ +# --create --topic rasa --if-not-exists +# +#kubectl exec kafka-client --namespace $NAMESPACE -- kafka-topics.sh \ +# --bootstrap-server kafka.$NAMESPACE.svc.cluster.local:9092 \ +# --command-config /tmp/client.properties \ +# --create --topic rasa-events-dlq --if-not-exists +# +#print_info "Listing all topics:" +#kubectl exec kafka-client --namespace $NAMESPACE -- kafka-topics.sh \ +# --bootstrap-server kafka.$NAMESPACE.svc.cluster.local:9092 \ +# --command-config /tmp/client.properties \ +# --list +# +#print_info "Cleaning up..." +#kubectl delete pod kafka-client --namespace $NAMESPACE +# +#print_info "Topic creation completed and temporary pod cleaned up." \ No newline at end of file diff --git a/aws/setup/environment-variables.sh b/aws/setup/environment-variables.sh index eb377e2..f5d7b1e 100644 --- a/aws/setup/environment-variables.sh +++ b/aws/setup/environment-variables.sh @@ -51,6 +51,10 @@ export DB_STUDIO_DATABASE="studio" export DB_STUDIO_USERNAME="studio" # The database name for Keycloak. export DB_KEYCLOAK_DATABASE="keycloak" +# The database name for analytics. +export DB_ANALYTICS_DATABASE="analytics" +# The username for the analytics database. +export DB_ANALYTICS_USERNAME="analytics" # The version of PostgreSQL Container to use for applying some configuration to the database. export PG_VERSION=17 # The username for the ElastiCache Redis IAM role. @@ -67,16 +71,19 @@ export CIDR_PUBLIC_A=10.100.4.0/22 export CIDR_PRIVATE_A=10.100.8.0/21 export CIDR_DB_A=10.100.16.0/21 export CIDR_ELASTICACHE_A=10.100.24.0/21 +export CIDR_MSK_A=10.100.96.0/21 export CIDR_PUBLIC_B=10.100.36.0/22 export CIDR_PRIVATE_B=10.100.40.0/21 export CIDR_DB_B=10.100.48.0/21 export CIDR_ELASTICACHE_B=10.100.56.0/21 +export CIDR_MSK_B=10.100.104.0/21 export CIDR_PUBLIC_C=10.100.68.0/22 export CIDR_PRIVATE_C=10.100.72.0/21 export CIDR_DB_C=10.100.80.0/21 export CIDR_ELASTICACHE_C=10.100.88.0/21 +export CIDR_MSK_C=10.100.112.0/21 #-------------------------------- # Print the environment variables so you can see they're all set correctly. @@ -99,7 +106,9 @@ echo "DB assistant username: $DB_ASSISTANT_USERNAME" echo "DB studio database: $DB_STUDIO_DATABASE" echo "DB studio username: $DB_STUDIO_USERNAME" echo "DB keycloak database: $DB_KEYCLOAK_DATABASE" -echo "Redis user: $REDIS_USER" +echo "DB analytics database: $DB_ANALYTICS_DATABASE" +echo "DB analytics username: $DB_ANALYTICS_USERNAME" echo "PostgreSQL version: $PG_VERSION" +echo "Redis user: $REDIS_USER" echo "--------------------------------" echo "If any of the above values are incorrect or blank, please update the file and re-run."