IMPORTANT NOTE: This site is not official Red Hat documentation and is provided for informational purposes only. These guides may be experimental, proof of concept, or early adoption. Officially supported documentation is available at docs.openshift.com and access.redhat.com.

Adding a Public Ingress endpoint to a ROSA Private-Link Cluster

The is an example guide for creating a public ingress endpoint for a ROSA Private-Link cluster. Be aware of the security implications of creating a public subnet in your ROSA VPC this way.

architecture diagram showing privatelink with public ingress

Prerequisites

Getting Started

Set some environment variables

  1. Set the following environment variables, changing them to suit your cluster.

    export ROSA_CLUSTER_NAME=private-link
    # this should be a free CIDR inside your VPC
    export PUBLIC_CIDR=10.0.2.0/24
    export AWS_PAGER=""
    export EMAIL=username.taken@gmail.com
    export DOMAIN=public.aws.mobb.ninja
    export SCRATCH_DIR=/tmp/scratch
    mkdir -p $SCRATCH_DIR
    

Create a public subnet

If you followed the above instructions to create the ROSA Private-Link cluster, you should already have a public subnet in your VPC and can skip to tagging the subnet.

  1. Get a Private Subnet ID from the cluster.

    PRIVATE_SUBNET_ID=$(rosa describe cluster -c $ROSA_CLUSTER_NAME -o json \
       | jq -r '.aws.subnet_ids[0]')
    echo $PRIVATE_SUBNET_ID
    
  2. Get the VPC ID from the subnet ID.

     VPC_ID=$(aws ec2 describe-subnets --subnet-ids $PRIVATE_SUBNET_ID \
       --query 'Subnets[0].VpcId' --output text)
     echo $VPC_ID
    
  3. Get the Cluster Tag from the subnet

    TAG=$(aws ec2 describe-subnets --subnet-ids $PRIVATE_SUBNET_ID \
       --query 'Subnets[0].Tags[?Value == `shared`]' | jq -r '.[0].Key')
    echo $TAG
    
  4. Create a public subnet

    PUBLIC_SUBNET=`aws ec2 create-subnet --vpc-id $VPC_ID --cidr-block $PUBLIC_CIDR \
      --query 'Subnet.SubnetId' --output text`
    echo $PUBLIC_SUBNET
    
  5. Tag the public subnet for the cluster

    aws ec2 create-tags --resources $PUBLIC_SUBNET \
       --tags Key=Name,Value=$ROSA_CLUSTER_NAME-public \
       Key=$TAG,Value="shared" Key=kubernetes.io/role/elb,Value="true"
    

Create a Custom Domain

  1. Create TLS Key Pair for custom domain using certbot:

    Skip this if you already have a key pair.

    certbot certonly --manual \
      --preferred-challenges=dns \
      --email $EMAIL \
      --server https://acme-v02.api.letsencrypt.org/directory \
      --agree-tos \
      --config-dir "$SCRATCH_DIR/config" \
      --work-dir "$SCRATCH_DIR/work" \
      --logs-dir "$SCRATCH_DIR/logs" \
      -d "*.$DOMAIN"
    
  2. Create TLS secret for custom domain:

    Note use your own keypair paths if not using certbot.

    CERTS=/tmp/scratch/config/live/$DOMAIN
    oc new-project my-custom-route
    oc create secret tls acme-tls --cert=$CERTS/fullchain.pem --key=$CERTS/privkey.pem
    
  3. Create Custom Domain resource:

    cat << EOF | oc apply -f -
    apiVersion: managed.openshift.io/v1alpha1
    kind: CustomDomain
    metadata:
      name: acme
    spec:
      domain: $DOMAIN
      certificate:
        name: acme-tls
        namespace: my-custom-route
    EOF
    
  4. Wait for the domain to be ready:

    watch oc get customdomains
    
  5. Once its ready grab the CLB name:

    CDO_NAME=acme
    CLB_NAME=$(oc get svc -n openshift-ingress -o jsonpath='{range .items[?(@.metadata.labels.ingresscontroller\.operator\.openshift\.io\/owning-ingresscontroller=="'$CDO_NAME'")]}{.status.loadBalancer.ingress[].hostname}{"\n"}{end}')
    echo $CLB_NAME
    
  6. Create a CNAME in your DNS provider for *.<$DOMAIN> that points at the CLB NAME from the above command.

Deploy a public application

  1. Create a new project

    oc new-project my-public-app
    
  2. Create a new application

    oc new-app --docker-image=docker.io/openshift/hello-openshift
    
  3. Create a route for the application

    oc create route edge --service=hello-openshift hello-openshift-tls \
      --hostname hello.$DOMAIN
    
  4. Check that you can access the application:

    curl https://hello.$DOMAIN
    
  5. You should see the output

    Hello OpenShift!