Strategies for exposing applications in IBM Cloud Satellite

Tyler Lisowski
6 min readDec 9, 2022

By default: Satellite ROKS clusters come with an ingress domain that points to the IPs of the worker nodes in the ROKS cluster. These IPs are typically in a private network and consumers will often want to expose the applications running on these ROKS clusters to outside networks like the Internet. A few common patterns for that are discussed below:

Exposing the default router through a NAT Gateway

In this pattern: an IP is set to NAT to a worker node in the ROKS cluster (direct port forwarding). A domain is created that points to the NAT IP to provide a DNS mapping to the NAT IP address (the TLS certificates associated with the domain are automatically created and managed as part of the domain as well). From there routes can be created to publish the route through the NAT IP. In our example: the NAT IP will be utilized to expose the sample application to the Internet.

We will illustrate this process by exposing a sample cli download application in a Satellite Red Hat Openshift cluster. We first start out with a ROKS cluster inside an existing private network:

ibmcloud ks cluster get --cluster cbqg0h3w0scd7l9mc6gg
Retrieving cluster cbqg0h3w0scd7l9mc6gg...
OK

Name: tyler-loc-useast-d-1
ID: cbqg0h3w0scd7l9mc6gg
State: normal
Status: All Workers Normal
Created: 2022-08-11 08:12:36 -0500 (3 months ago)
Resource Group ID: f4bf7759b43c4d1a859e328dc363e478
Resource Group Name: default
Pod Subnet: 172.30.0.0/16
Service Subnet: 172.21.0.0/16
Workers: 2
Worker Zones: us-east-1
Ingress Subdomain: tyler-loc-useast-d-1-80d128fecd199542426020c17e5e9430-0000.us-east.containers.appdomain.cloud
Ingress Secret: tyler-loc-useast-d-1-80d128fecd199542426020c17e5e9430-0000
Ingress Status: healthy
Ingress Message: All Ingress components are healthy.
Public Service Endpoint URL: https://c-01.private.us-east.link.satellite.cloud.ibm.com:32915
Private Service Endpoint URL: https://t80bc734cb074c8b16595-6b64a6ccc9c596bf59a86625d8fa2202-ce00.us-east.satellite.appdomain.cloud:30617
Pull Secrets: enabled in the default namespace
VPCs: -
Pod network interface selection method: kubernetes=NodeInternalIP

Master
Status: Ready (3 weeks ago)
State: deployed
Health: normal
Version: 4.11.12_1532_openshift
Location: tyler-loc-useast
URL: https://t80bc734cb074c8b16595-6b64a6ccc9c596bf59a86625d8fa2202-ce00.us-east.satellite.appdomain.cloud:30617


ibmcloud ks workers --cluster cbqg0h3w0scd7l9mc6gg
OK
ID Primary IP Flavor State Status Zone Version
sat-tylertestt-6b232b18eb144361d0f27011b7f2eec52e43b802 10.240.0.19 upi normal Ready us-east-1 4.11.13_1533_openshift
sat-tylertestt-c50eabbf3519e3bed71206765a1a4784ac3c2d2e 10.240.0.20 upi normal Ready us-east-1 4.11.13_1533_openshift

ibmcloud ks nlb-dns ls --cluster cbqg0h3w0scd7l9mc6gg
OK
Hostname IP(s) Health Monitor SSL Cert Status SSL Cert Secret Name Secret Namespace Status
tyler-loc-useast-d-1-80d128fecd199542426020c17e5e9430-0000.us-east.containers.appdomain.cloud 10.240.0.19,10.240.0.20 disabled created tyler-loc-useast-d-1-80d128fecd199542426020c17e5e9430-0000 openshift-ingress OK

The ROKS on Satellite cluster has worker nodes with private IPs and the default ingress domain is setup to point to those IPs. In the infrastructure provider: we are going to setup a NAT IP 150.239.82.80 that will point to the IP of sat-tylertestt-6b232b18eb144361d0f27011b7f2eec52e43b802: 10.240.0.19 . Next we are going to create a new domain that will point to the NAT IP:

ibmcloud ks nlb-dns create classic --cluster cbqg0h3w0scd7l9mc6gg --ip 150.239.82.80 --secret-namespace openshift-ingress
OK
NLB hostname was created as tyler-loc-useast-d-1-80d128fecd199542426020c17e5e9430-0001.us-east.containers.appdomain.cloud and registered in public DNS
Note: It might take a few minutes for your changes to be applied.

nslookup tyler-loc-useast-d-1-80d128fecd199542426020c17e5e9430-0001.us-east.containers.appdomain.cloud 8.8.8.8
Server: 8.8.8.8
Address: 8.8.8.8#53

Non-authoritative answer:
Name: tyler-loc-useast-d-1-80d128fecd199542426020c17e5e9430-0001.us-east.containers.appdomain.cloud
Address: 150.239.82.80



ibmcloud ks nlb-dns ls --cluster cbqg0h3w0scd7l9mc6gg
OK
Hostname IP(s) Health Monitor SSL Cert Status SSL Cert Secret Name Secret Namespace Status
tyler-loc-useast-d-1-80d128fecd199542426020c17e5e9430-0000.us-east.containers.appdomain.cloud 10.240.0.19,10.240.0.20 disabled created tyler-loc-useast-d-1-80d128fecd199542426020c17e5e9430-0000 openshift-ingress OK
tyler-loc-useast-d-1-80d128fecd199542426020c17e5e9430-0001.us-east.containers.appdomain.cloud 150.239.82.80 None created tyler-loc-useast-d-1-80d128fecd199542426020c17e5e9430-0001 openshift-ingress OK

Once that domain is created: we can now create a route that is configured for that subdomain and then send traffic to the sample application

ibmcloud cs cluster config --cluster cbqg0h3w0scd7l9mc6gg --admin
cat <<EOF >/tmp/route.yaml
apiVersion: route.openshift.io/v1
kind: Route
metadata:
name: route-passthrough-downloads
namespace: openshift-console
spec:
host: downloads.tyler-loc-useast-d-1-80d128fecd199542426020c17e5e9430-0001.us-east.containers.appdomain.cloud
port:
targetPort: http
to:
kind: Service
name: downloads
EOF
oc apply -f /tmp/route.yaml

With this configured: we can now access the service locally over the Internet through the NAT IP:

Accessing downloads application through NAT

Route Sharding with a Load Balancer + Dedicated Router

Sometimes: a user only wants to expose a subset of routes over a given network. In this case: we can use route sharding with dedicated router instances to accomplish the goal.

In this example: we assume we have a load balancer that has a IP of 150.239.83.52 and can load balance traffic across worker nodes associated with the ROKS on Satellite cluster. First: we are going to create a new ingress subdomain that we will point to the load balancer IP:

ibmcloud ks nlb-dns create classic --cluster cbqg0h3w0scd7l9mc6gg --ip 150.239.83.52 --secret-namespace openshift-ingress
OK
NLB hostname was created as tyler-loc-useast-d-1-80d128fecd199542426020c17e5e9430-0002.us-east.containers.appdomain.cloud and registered in public DNS
Note: It might take a few minutes for your changes to be applied.

nslookup tyler-loc-useast-d-1-80d128fecd199542426020c17e5e9430-0002.us-east.containers.appdomain.cloud 8.8.8.8
Server: 8.8.8.8
Address: 8.8.8.8#53

Non-authoritative answer:
Name: tyler-loc-useast-d-1-80d128fecd199542426020c17e5e9430-0002.us-east.containers.appdomain.cloud
Address: 150.239.83.52

ks nlb-dns ls --cluster cbqg0h3w0scd7l9mc6gg
OK
Hostname IP(s) Health Monitor SSL Cert Status SSL Cert Secret Name Secret Namespace Status
tyler-loc-useast-d-1-80d128fecd199542426020c17e5e9430-0000.us-east.containers.appdomain.cloud 10.240.0.19,10.240.0.20 disabled created tyler-loc-useast-d-1-80d128fecd199542426020c17e5e9430-0000 openshift-ingress OK
tyler-loc-useast-d-1-80d128fecd199542426020c17e5e9430-0001.us-east.containers.appdomain.cloud 150.239.82.80 None created tyler-loc-useast-d-1-80d128fecd199542426020c17e5e9430-0001 openshift-ingress OK
tyler-loc-useast-d-1-80d128fecd199542426020c17e5e9430-0002.us-east.containers.appdomain.cloud 150.239.83.52 None created tyler-loc-useast-d-1-80d128fecd199542426020c17e5e9430-0002 openshift-ingress OK

Then we are going to create a dedicated router instance that will only serve routes with a specific label of type=lb-ingress . We will also apply the route that will match with that

ibmcloud cs cluster config --cluster cbqg0h3w0scd7l9mc6gg --admin
cat <<EOF >/tmp/ingctr.yaml
apiVersion: operator.openshift.io/v1
kind: IngressController
metadata:
name: lb-ingress
namespace: openshift-ingress-operator
spec:
domain: tyler-loc-useast-d-1-80d128fecd199542426020c17e5e9430-0002.us-east.containers.appdomain.cloud
defaultCertificate:
name: tyler-loc-useast-d-1-80d128fecd199542426020c17e5e9430-0002
endpointPublishingStrategy:
type: NodePortService
replicas: 2
routeSelector:
matchLabels:
type: lb-ingress
EOF
oc apply -f /tmp/ingctr.yaml
cat <<EOF >/tmp/route.yaml
apiVersion: route.openshift.io/v1
kind: Route
metadata:
name: downloads-lb
namespace: openshift-console
labels:
type: lb-ingress
spec:
host: downloads.tyler-loc-useast-d-1-80d128fecd199542426020c17e5e9430-0002.us-east.containers.appdomain.cloud
port:
targetPort: http
tls:
insecureEdgeTerminationPolicy: Redirect
termination: edge
to:
kind: Service
name: downloads
weight: 100
EOF
oc apply -f /tmp/route.yaml

Once applied: we will now gather at the backend node port configuration for the router to configure the backend of the load balancer for:

kubectl get service -n openshift-ingress  router-nodeport-lb-ingress
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
router-nodeport-lb-ingress NodePort 172.21.14.104 <none> 80:32106/TCP,443:32527/TCP,1936:30282/TCP 63m

In our example: port 32106 on the two worker node IPs will be the backend for the front end load balancer listener on port 80 for HTTP. For HTTPS: the front end load balancer will listen on port 443 and forward to port 32527 on the two worker node IPs (use TCP forwarding). Once this is configured in the load balancer: the downloads service can be accessed over the load balancer.

Accessing downloads application through Load Balancer

Expose through local floating IP with Metal-LB

If the hybrid cloud environment has floating IPs available: then Metal-LB can be utilized to provision load balancer services natively in Openshift that hook into those floating IPs. Metal-LB will manage the floating IP in a highly available fashion with it’s member list protocol and using L2 gratuitous ARPs: failing over the floating IP to healthy machines in the cluster. IBM Cloud has a great existing guide of that workflow: https://cloud.ibm.com/docs/openshift?topic=openshift-sat-expose-apps#sat-expose-metallb.

--

--

Tyler Lisowski

IBM Cloud Satellite Lead Architect. Proud member of Bills Mafia.