Skip to content

This AWS Partner Solution uses Terraform to deploy a Mendix infrastructure in the AWS Cloud.

License

Notifications You must be signed in to change notification settings

aws-ia/terraform-aws-mendix-private-cloud

Repository files navigation

Mendix Partner Solution for Amazon EKS—Terraform module

This Amazon Web Services (AWS) Partner Solution uses a Terraform module to deploy an infrastructure that meets the requirements of Mendix for Private Cloud. You deploy this solution in an automated way using Amazon Elastic Kubernetes Service (Amazon EKS). The infrastructure is for users of the Mendix application-development platform who want to deploy and manage Mendix apps in the AWS Cloud.

For more information, refer to the Mendix documentation. If you have questions, feedback, or ideas, you can post them in the Mendix Forum about AWS.

This Partner Solution was developed by Siemens in collaboration with AWS. Siemens is an AWS Partner. Mendix is a wholly owned subsidiary of Siemens.

Costs and licenses

To use Mendix, you must have an operator license. For more information, refer to Licensing Mendix for Private Cloud.

There is no cost to use this Partner Solution, but you'll be billed for any AWS services or resources that this Partner Solution deploys. For more information, refer to the AWS Partner Solution General Information Guide.

Architecture

This Partner Solution deploys into a new virtual private cloud (VPC).

Architecture for Mendix on Amazon EKS

As shown in the diagram, this solution sets up the following:

  • A highly available architecture that spans three Availability Zones.
  • A VPC configured with public and private subnets, according to AWS best practices, to provide you with your own virtual network on AWS.
  • An Amazon Route 53 public hosted zone that routes incoming internet traffic.
  • In the public subnets, managed NAT gateways to allow outbound internet access for resources in the private subnet.
  • In the private subnets, Amazon EKS clusters—each with three Kubernetes nodes—inside an Auto Scaling group. Each node is an Amazon Elastic Compute Cloud (Amazon EC2) instance. Each cluster contains the following (not shown):
    • Mendix apps and components.
    • Cert-manager.
    • An open-source logging and monitoring solution with Grafana, AWS managed Prometheus, OpenTelemetry, CloudWatch, and Fluent Bit.
    • ExternalDNS, which synchronizes exposed Kubernetes services and ingresses with Route 53.
  • A Network Load Balancer to distribute traffic across the Kubernetes nodes.
  • Amazon Simple Storage Service (Amazon S3) to store the files.
  • Amazon Elastic Block Store (Amazon EBS) to provide storage for Grafana.
  • Amazon Relational Database Service (Amazon RDS) for PostgreSQL to store Mendix application data.
  • Amazon Elastic Container Registry (Amazon ECR) to provide a private registry.
  • AWS Key Management Service (AWS KMS) to provide an encryption key for Amazon RDS, Amazon EBS, and AWS Secrets Manager.
  • Secrets Manager to replace hardcoded credentials, including passwords, with an API call.

Prerequisites

Before you can provision your Mendix environments on Amazon EKS, you must install and configure the required tools, configure Mendix Private Cloud, and configure Terraform.

Install and configure the required tools

  1. Install the latest version of Terraform.

  2. Configure an IAM user with programmatic access and at least the following IAM permissions.

  3. Install the latest version of AWS CLI.

  4. Run aws configure to configure AWS CLI with the ACCESS_KEY_ID, SECRET_ACCESS_KEY, and REGION corresponding to your IAM user.

  5. Install the latest version of AWS IAM Authenticator.

  6. Install the latest version of kubectl.

  7. Download GNU Wget (required for the Terraform EKS module).

Configure Mendix Private Cloud

  1. Confirm that your Mendix Runtime version is 9.21 or newer.
  2. Create your Mendix app. For more information, refer to Deploying a Mendix App to a Private Cloud Cluster.
  3. Register a new EKS cluster. For more information, refer to Creating a Cluster and Namespace.
  4. Add a new connected namespace called mendix.
  5. Retrieve the cluster ID and the cluster secret in the Installation tab for your namespace.

Configure Terraform

  1. Provision an S3 bucket with your desired name and an Amazon DynamoDB table with the partition key LockID (string type) to store the state file and have a locking mechanism, respectively.

  2. Edit providers.tf, filling in your information, as in the following example:

    terraform {
      backend "s3" {
        region         = "eu-central-1"
        bucket         = "state-bucket-state"
        key            = "terraform.tfstate"
        dynamodb_table = "dynamodb-table-state"
        encrypt        = true
      }
    
  3. Edit terraform.tfvars, filling in your information, as in the following example:

    aws_region                   = ""
    domain_name                  = "project-name-example.com"
    certificate_expiration_email = "example@example.com"
    s3_bucket_name               = "project-name"
    namespace_id                 = ""
    namespace_secret             = ""
    environments_internal_names  = ["app1", "app2", "app3"]
    

The number of applications deployed is handled by the environments_internal_names variable. Internal names are used during the environment creation, as shown here:

Customizing the environment name

The internal name must match the name that you specify in the environments_internal_names variable when you create your Mendix app.

Provision a new environment

  1. Run the following commands:

    terraform init
    terraform apply
    
  2. After everything has been provisioned, run the following command to retrieve the access credentials for your new cluster and automatically configure kubectl:

    aws eks --region $(terraform output -raw region) update-kubeconfig --name $(terraform output -raw cluster_name)
    
  3. Retrieve the aws_route53_zone_name_servers that were generated using the AWS Console. To do so, either choose Route53 > Hosted Zone or run the following command:

    terraform output aws_route53_zone_name_servers
    
  4. Depending on your provider, update External Domain Name Registrar or Route53 registered domain with the aws_route53_zone_name_servers values. For more information, refer to Configuring Amazon Route 53 as your DNS service.

  5. If you're deploying more than three apps, change the default instance type of the eks_node_instance_type variable. By default, the instance type for the Kubernetes nodes is optimized to support up to three apps. Deploying more than three apps with the default instance type may affect the performance of your applications. For more information, refer to Choosing an Amazon EC2 instance type in the Amazon EKS User Guide.

Security

Cluster endpoint

Kubernetes API requests within your cluster's VPC (such as node to control plane communication) use the private VPC endpoint.

Your cluster API server is accessible from the internet. If required, you can limit the CIDR blocks that can access the public endpoint by configuring the allowed_ips variable. For more information, refer to Amazon EKS cluster endpoint access control.

Encryption

All the EBS volumes, the RDS PostgreSQL database, and the S3 storage bucket are encrypted at rest. The end-to-end TLS encryption is handled at the Ingress NGINX Controller level. A certificate is generated for each app by cert-manager, configured with a Let’s Encrypt certificate issuer.

Automatic scaling

While all the Amazon EKS nodes are placed in an Auto Scaling group, the Kubernetes Cluster Autoscaler is not installed by default. The Cluster Autoscaler automatically scales up and down by allowing Kubernetes to modify the Amazon EC2 Auto Scaling groups.

Logging and monitoring

A basic logging and monitoring stack containing Grafana, AWS managed Prometheus, OpenTelemetry, CloudWatch, and Fluent Bit is available at the following URL: https://monitoring.{domain_name}

To retrieve the Grafana administrative credentials (with admin username), run the following command:

terraform output -json grafana_admin_password

Troubleshooting

If you encounter any issues while provisioning your Mendix environments on AWS, use the following troubleshooting tips.

The Terraform Registry does not have a package available (Mac)

When initializing Terraform, Apple M1 users may encounter the following error:

│ Provider Terraform Registry 38 v2.2.0 does not have a
│ package available for your current platform, darwin_arm64

Solution: Install m1-terraform-provider-helper:

brew install kreuzwerker/taps/m1-terraform-provider-helper
m1-terraform-provider-helper activate
m1-terraform-provider-helper install hashicorp/template -v v2.2.0

My cluster never connects

In the Mendix Private Cloud portal, in the Cluster Manager, the status of your cluster is shown as Waiting for Connection, but the cluster never connects.

Cause: The Mendix Agent or the Mendix Operator may not be configured correctly or may not be connected.

Solution: Perform the following steps:

  1. Retrieve the logs of the installer job by running the following command:

    kubectl logs job.batch/mxpc-cli-installer -n mendix
    

    You should receive the following output:

    -- Done-- Applying Kubernetes Secrets... Done!
    -- Applying Service Accounts... Done!
    -- Applying Storage Plans... Done!
    -- Applying Operator Patches... Done!
    -- Successfully applied all the configuration!
    operatorconfiguration.privatecloud.mendix.com/mendix-operator-configuration patched
    operatorconfiguration.privatecloud.mendix.com/mendix-operator-configuration patched
    operatorconfiguration.privatecloud.mendix.com/mendix-operator-configuration patched
    
  2. Reinstall the installer by running the following command:

    terraform destroy -target=helm_release.mendix_installer
    terraform plan; terraform apply --auto-approve
    

Cleanup

Before cleaning up, make sure that you have deleted Mendix App environments. Otherwise, you will need to manually remove some finalizers in the namespace and detach some roles from policies in AWS IAM.

To clean up your environment, run the following commands:

terraform destroy -target="module.eks_blueprints_kubernetes_addons.module.ingress_nginx.helm_release.this[0]" -auto-approve
terraform destroy -target="module.eks_blueprints_kubernetes_addons.module.kube_prometheus_stack.helm_release.this[0]" -auto-approve
terraform destroy -target="module.eks_blueprints_kubernetes_addons.module.aws_load_balancer_controller.helm_release.this[0]" -auto-approve
terraform destroy -target="module.eks_blueprints_kubernetes_addons" -auto-approve
terraform destroy -auto-approve

License

License

Customer responsibility

After you deploy this Partner Solution, confirm that your resources and services are updated and configured—including any required patches—to meet your security and other needs. For more information, refer to the AWS Shared Responsibility Model.

Requirements

Name Version
terraform >= 0.14
aws >= 5.10
helm >= 2.7.1
kubectl >= 1.14
kubernetes >= 2.16.1
random >= 3.4.3
template >= 2.2.0

Providers

Name Version
aws >= 5.10
helm >= 2.7.1
kubernetes >= 2.16.1
random >= 3.4.3

Modules

Name Source Version
container_registry ./modules/container-registry n/a
databases ./modules/databases n/a
ebs_csi_driver_irsa terraform-aws-modules/iam/aws//modules/iam-role-for-service-accounts-eks ~> 5.20
eks_blueprints terraform-aws-modules/eks/aws ~> 19.13
eks_blueprints_kubernetes_addons aws-ia/eks-blueprints-addons/aws ~> 1.8.0
file_storage ./modules/file-storage n/a
monitoring ./modules/monitoring n/a
vpc ./modules/vpc n/a

Resources

Name Type
aws_cloudwatch_log_group.aws_for_fluentbit resource
aws_ebs_encryption_by_default.ebs_encryption resource
aws_eks_addon.adot_addon resource
aws_iam_policy.environment_policy resource
aws_iam_policy.provisioner_policy resource
aws_iam_role.storage_provisioner_role resource
aws_route53_zone.cluster_dns resource
helm_release.mendix_installer resource
kubernetes_namespace.mendix resource
random_string.random_eks_suffix resource
aws_caller_identity.current data source
aws_eks_cluster_auth.this data source

Inputs

Name Description Type Default Required
aws_region AWS Region name string n/a yes
certificate_expiration_email Let's Encrypt certificate expiration email string n/a yes
domain_name Domain name string n/a yes
namespace_id Mendix Private Cloud Namespace ID string n/a yes
namespace_secret Mendix Private Cloud Namespace Secret string n/a yes
s3_bucket_name S3 bucket name string n/a yes
allowed_ips List of IP adresses allowed to access EKS cluster endpoint list(string)
[
"0.0.0.0/0"
]
no
eks_cluster_name_prefix EKS name prefix for the new cluster string "mendix-eks" no
eks_node_instance_type EKS instance type string "t3.medium" no
environments_internal_names List of internal environments names list(string)
[
"app1"
]
no
mendix_operator_version Mendix Private Cloud Operator version string "2.13.0" no
postgres_version The version of Postgres that terraform would create. string "14.8" no

Outputs

Name Description
aws_route53_zone Route 53 hosted zone ID
aws_route53_zone_name_servers Route 53 hosted zone nameservers
cluster_name Kubernetes cluster name
cluster_vpc_id VPC ID
container_irsa_role_arn Elatic Container Registry IAM Role ARN
container_registry_name Elatic Container Registry name
container_registry_url Elatic Container Registry URL
database_name RDS database name
database_password RDS database password
database_server_address RDS database address
database_username RDS database username
filestorage_endpoint S3 endpoint
filestorage_regional_endpoint S3 regional endpoint
grafana_admin_password Grafana admin password
region AWS Region where the cluster is provisioned
vpc_private_subnets VPC private subnets
vpc_public_subnets VPC public subnets