Securely exposing an application on a private ROSA cluser with an AWS Network Load Balancer
Overview
Red Hat strongly recommends creating a private ROSA cluster with no inbound Internet connectivity, isolating both the cluster API and hosted applications from external access. This configuration is a key part of a multi-layered security strategy to protect clusters and workloads from external threats.
However, some applications may require Internet access to support external users or partners. Even with a private cluster, you can securely expose these applications through various methods. For example, a TCP-based application like Kafka may need connectivity to allow partners on the Internet to send or receive data. This document provides guidance on one specific method to securely expose a TCP-based application while maintaining the security of a private cluster.
This approach ensures that the application remains accessible as needed while keeping your cluster’s core components safely isolated.
This guide describes how to setup the following:
- a Private ROSA Cluster
- a 2nd ingress controller ( AWS Network Load Balancer ) used for application(s) you want to expose to the Internet
- a custom domain configured for the 2nd ingress controller
- a 2nd ‘Public’ VPC peered with the ROSA VPC
- a ‘public’ network load balancer in the ‘public’ VPC
This is just one layer in securely exposing an application. Additional measures, such as a firewall, web application firewall (WAF), and other security controls, should also be considered to strengthen the overall security posture.

Pre-requisites
You will need a A Private ROSA Cluster (see Deploying ROSA HCP with Terraform if you need help creating one). Make sure to select the private option in Terraform.
Set environment variables. In the example we re-use the variables from the Terraform guide
For reference only, this is the expected output from the Terraform guide.
Set additional environment variables for a custom domain and additional ingress controller.
note: this tutorial will use AWS Route53, if you have a different DNS follow the same steps in creating DNS records in your DNS environment.
Create a public VPC or set your VPC Environment variables
If you already have a secondary public VPC you’d like to use, please set the following environment variables for that VPC.
If you’d like a guided walkthrough to create the secondary public VPC, follow these instructions . This guide will also set all the required environment variables needed.
(Optional) Launch an Jump Host EC2 instance in Public NLB VPC
This guide requires connectivity to the cluster, because we are using a private cluster you will need to ensure your workstation is connected to the AWS VPC which hosts the ROSA cluster. If you already have this connectivity through a VPN, Direct Link or other method you can skip this part.
If you do need to establish connectivity to the cluster these instructions will guide you through creating a jump host on the public subnet of the ROSA cluster.
Create a second ingress controller for public applications
To limit the blast radius, a second private ingress controller will be set up within the cluster, connected to by an additional public network load balancer.
(Optional) create certificates for your domain.
Note: Make sure if update your DNS with a text record as prompted. You can also use nslookup to make sure the record is set.
Create certficates
Add Domain certificates to OpenShift
Note: the following uses the certificate generation output from certbot. If you already have certificates, substitute the key and certificate location.
if using the jump host, you will need to copy the key and certificate to the jump host and run the oc command there
log into the Openshift cluster, if you need the ROSA API url you can find it with this command
Add Domain certificates to AWS ACM
When we create a listener for the public load balancer, we will add a certificate to the listener. Adding a certificate to an AWS Network Load Balancer listener enables encrypted, authenticated connections, enhancing security and compliance by protecting data in transit.
Create an additional IngressController
A fundamental aspect of this architecture is the creation of a second Ingress Controller to manage routing for applications exposed to the Internet. This Ingress Controller is configured as a private AWS Network Load Balancer. The decision to keep it private serves two primary purposes: first, it prevents direct access to the cluster and applications from the Internet; second, by directing traffic through a public ingress VPC initially, you can centralize Internet access control for your environment and implement your organizational security standards, including inspection, WAF, firewalls, and other security technologies.
if using a jump box run this command there
Get the newly created Network Load Balancer hostname and IP addresses
if using a jump host of ‘oc’ command run this command there.
Copy the output of the above command to a new environment variable on your workstation
Example:
Wait a few minutes for the load balancer to be provisioned and run these commands. If they don’t return with IP addresses, just wait a while and run then again.
Update DNS records
As described, this tutorial uses AWS Route53 to handle DNS records. If you use a different DNS system use the following as a reference.
Create and configure the public NLB
Start by creating a target group
Register the targets for the AWS Network Load Balancer that was created when we added the second IngressController
Create a security group for the public load balancer Create an additional Security Group for the jumphost
Grab the Security Group Id generated in the previous step
Create the public load balancer
Authorize TCP 443 access to the load balancer
Create a listener for the load balancer using the target group we just created
Get the DNS Hostname of the public load balancer
Get the NLB environment variables
Create an alias record json statement.
Update Route53 with the new record
Test an application.
Create a test applciation in a new namespace.
Expose the test application Service.
Let’s create a Route to expose the application from outside the cluster, and annotate the Route to give it a new Certificate.
Access the application Route.
Open your browser to hello.$DOMAIN and you will see a secured web page that displays Hello OpenShift.
