3.7 How to publish my application to the internet?

Last modified by Tomas Terälä on 2024/06/12 10:31

General

TIKE Openshift cluster has two Ingresses shared by all projects. This means that all projects receive user traffic through shared floating ip addresses. Note, outward traffic from the cluster does not go through these ip addresses, instead it comes from the ip addresses of the virtual machines in the cluster.

In OpenShift services (Service) are connected to a shared ingess with a  Route object. A project administrator can create Routes without the help of cluster administration. The Route also defines a DNS name, which also works as the hostname for http(s) service. The Ingress connects traffic to the right Route with the host header in http protocol.

From version 4.6 onward, Openshift creates Routes based on Ingress objects https://docs.openshift.com/container-platform/4.12/networking/routes/route-configuration.html#nw-ingress-creating-a-route-via-an-ingress_route-configuration

Both the test and production clusters have two ingresses. For one of them its (*.apps) ip address is limited to the University's internal and peripheral network, where as the other (*.ext) is open to everyone on the internet. The Route object defines which Ingress to use, and therefore who the application is visible.

Brief and Concise explanation

Assuming that both a Route and Service were created automatically for your application and that you do not use a custom hostname with its challenges.

Publishing to the external internet

Web console → Administrator perspective → Networking → Routes → Choose your Route → "Actions -> Edit Route"→ Make your changes-> Save -> Reload

metadata:
    labels:
        type: external

(the host is of form ("application"-"project"."apps or ext".ocp-"test or prod"-0.k8s.it.helsinki.fi)

spec:
  host: application-container.ext.ocp-clustername-0.k8s.it.helsinki.fi

NOTE!! you must change apps → ext in the Route. If editing the Route using the webconsole is not possible, you can download the Route.yaml file and edit it locally. Then delete the old Route and create a new Route by going to Administrator perspective → Networking → Routes → Create Route → Edit YAML → Drag your local file to the window and click save.

Adding a certificate

Add the following lines to Route.yaml.

spec:
  tls:
    termination: edge
    insecureEdgeTerminationPolicy: Redirect

The application url should be visible in the Route. You can also find it from Developer perspective → Topology → Pick your deployment→ Scroll to the bottom of the page.

More precise instructions

Creating a RouteIf you added your application from the web-console, check if both the Service and Route were created automatically.

Before creating a Route an application needs both a Service and one or more Pods linked to the Service.

Terminal command: oc expose :

$ oc expose svc servicename --name routename -n projectname

The command above creates a Route visible to University internal network. This means that the application would be visible to: 

  • only internal and peripheral network (this essentially means vpn, eduroam, university servers + workstations and lab computers)
  • at the address routename-servicename-projectname.apps.clustername.k8s.it.helsinki.fi
  • only as unencrypted http

By default the Route is opened to the container platform default Ingress, which is accessible only from the internal and peripheral networks of the University. The default Ingressin address is appsk8s.it.helsinki.fi*..<clustername>..

Making the application visible to everyone

If your service needs to be accessible from the entire internet,  use the external Ingress in your Route object.  Its address is ext*..<clustername>.k8s.it.helsinki.fi.

Add the label ja hostname to your Route as seen below:

metadata:
   labels:
       type: external
spec:
   host: <service>.ext.<clustername>.k8s.it.helsinki.fi

The same Route with the optional oc expose command:

oc expose svc servicename  -n projectname  --name routename  --labels type=external  --hostname <service>.ext.<clustername>.k8s.it.helsinki.fi

The UoH external firewall (pm-register) works as is, you do not need to ask for and you will not be given openings in the firewall.

If necessary, your service can filter client IP-addresses more accurately with the Route object configuration ("haproxy.router.openshift.io/ip_whitelist") or with a Forwarded-For header. (Not a lot of testing has gone to this so make sure everything works as it should.)

Standard names offered by the cluster

In the Route.yaml definitions the row spec.host can be basically anything. All the Routes will be serviced using a shared IP address, which has a wildcard DNS configuration of  k8s.it.helsinki.fi*.(apps|ext).<clustername>..

An example:

apps.ocp-prod-0.k8s.it.helsinki.fi
apps.ocp-prod-0.k8s.it.helsinki.fi



ext.ocp-prod-0.k8s.it.helsinki.fi
ext.ocp-prod-0.k8s.it.helsinki.fi



apps.ocp-test-0.k8s.it.helsinki.fi
apps.ocp-test-0.k8s.it.helsinki.fi



ext.ocp-test-0.k8s.it.helsinki.fi
ext.ocp-test-0.k8s.it.helsinki.fi

# Ingress visible to both internal and peripheral traffic in the production cluster
$ nslookup *.Name: *.Address: 128.214.137.96

# Ingress visible to external traffic in the production cluster
$ nslookup *.Name: *.Address: 128.214.137.97

# Ingress visible to both internal and peripheral traffic in the testing cluster
$ nslookup *.Name: *.Address: 128.214.137.152

# Ingress visible to external traffic in the testing cluster
$ nslookup *.Name: *.Address: 128.214.137.153

The project can generate a service address without adding a CNAME or certificates. In this case the service address must conform to the form of the wildcard above. A service address such as this one can be https encrypted without getting your own certificate, more informations later on this page. URL addresses of form service.apps.ocp-prod-0.k8s.it.helsinki.fi can also be useful for background addresses for interfaces offered in the API-gateway service.

Note, the wildcard part of the name can also be anything! In the example above using the oc expose command the "routename-servicename-projectname" is just the default form. As long as the name is something that matches with the wildcard, the Route works. If the name already exists, the Route's creation fails.

  • Warning: it is technically possible to create a Route that on a name level resembles the Route of another project's Route. Within Tike OpenShift container platform using a Route with a hostname that resembles another project is strictly forbidden.

If you wish to use a better url address for your application, read on.

Using a custom hostname

You can change your service address to any DNS name whose CNAME points to any name matching the wildcard *.(apps|ext).clustername.k8s.it.helsinki.fi. When using such a name you need your own TLS certificate that must be defined in the Route object. More below.

For example, host.apps works like this:

  • Service for public internet:
    • Production: servicename.helsinki.fihost.ext.ocp-prod-0.k8s.it.helsinki.fi
    • Testing: servicename-testi.helsinki.fihost.ext.ocp-test-0.8s.it.helsinki.fi
  • Service for internal and peripheral network:
    • Tuotanto: servicename.helsinki.fi → host.ext.ocp-prod-0.k8s.it.helsinki.fi
    • Testi: servicename-testi.helsinki.fi → host.apps.ocp-test-0.8s.it.helsinki.fi

Example of a CNAME service address

Let us publish 4 different Routes for the project:

  • production version in the production cluster to public internet as tahtitaivas.helsinki.fi
  • staging version in the production cluster for internal and peripheral network as tahtitaivas-stage.helsinki.fi
  • development version in the test cluster for internal and peripheral network as tahtitaivas-dev.helsinki.fi ja
  • test version in the test cluster for internal and peripheral network as tahtitaivas-test.helsinki.fi.
  1. Make sure that you have successfully created the Routes for the right clusters, whose spec.host defines your servicename in its entirety.
    1. Production cluster names:
      1. hostname: tahtitaivas.helsinki.fi
        ingress: external
      2. hostname: tahtitaivas-stage.helsinki.fi
        ingress: default
    2. Test cluster names:
      1. hostname: tahtitaivas-dev.helsinki.fi
        ingress: default
      2. hostname: tahtitaivas-test.helsinki.fi
        ingress: default
  2. Choose a method of operation below (in order of recommendation):
    1. If you have access to the IP-Reg system, make the CNAME there as self-service.
    2. If you do not have access to the IP-Reg system, send a free-form email to atk-verkko@helsinki.fi. Ask for the following CNAMEs:
      - tahtitaivas.helsinki.fi →  host.ext.ocp-prod-0.k8s.it.helsinki.fi,
      - tahtitaivas-stage.helsinki.fi → host.apps.ocp-prod-0.k8s.it.helsinki.fi
      - tahtitaivas-dev.helsinki.fi → host.apps.ocp-test-0.k8s.it.helsinki.fi ja
      - tahtitaivas-test.helsinki.fi →  host.apps.ocp-test-0.k8s.it.helsinki.fi
    1. Ask the container platform administration to fix the CNAMEs. Contact grp-openshift-owner@helsinki.fi.
  1.  Done!

Route and HTTPS

Using the default address

By default Routes get a subdomain of form routename-servicename-projectname.(apps|ext).clustername.k8s.it.helsinki.fi 

The Ingress wildcard domains have cluster wide certificates. You can add this certificate to your Route by adding the following lines to the Route.yaml:

spec:
 tls:
   termination: edge
   insecureEdgeTerminationPolicy: Redirect

or with the command:

oc patch route routename \
  -n projectname \
  --type=merge -p '{"spec":{"tls": {"termination": "edge", "insecureEdgeTerminationPolicy": "Redirect" }}}'

NOTE! The certificate could be applied correctly and your browser could still show the website as insecure if the page is cached. Try using incognito mode or another device to be sure.

Using your own service address

If you wish to use a custom service name, define it in the Route object and create the appropriate CNAME as seen above. Also acquire a signed certificate, for example by asking one from (ca@helsinki.fi) and place the certificate chain with their keys in the Route.yaml's  spec.tls -section.

RedHat documentation:  https://docs.openshift.com/container-platform/4.12/networking/routes/secured-routes.html

Asking for a certificate

  • Make sure that all CNAME address forwarding have been asked for.
  • Install OpenSSL
  • Login to the correct cluster in Openshiftin using the terminal. Instructions
  • If you want a certificate for both test and production clusters, email them separately or have both req.pem files in clearly labeled folders. The certificate will fail if you mix up the files.
  • Run the following command
Ssl sertifikaatin luominen
openssl req -newkey rsa:4096 -keyout key.pem -nodes -out req.pem.

varmennepyynto.png

From the picture above:

  • <Jätä tyhjäksi> = leave this line empty
  • Organizational unit name = e.g. Department of Computer Science or IT Center
  • Common Name: The url/service address for your application
  • Email address: can be left empty if no permanent maintainer exists

Deliver the certificate request (req.pem) to ca@helsinki.fi. NOTE! Never share your key.pem file.  The email response contains the necessary files. Store these (including both the req.pem and key.pem) somewhere safe in case you need them later.

More detailed instructions can be found in this PDF-file (Finnish only):Varmennepyynto_ja_varmenteen_tilaus_Helsingin_yliopistolla_v01.pdf

After this, place the certificates in the Route.yaml (make sure to indent the rows correctly).

An example Route with custom name and certificates:

apiVersion: v1
kind: Route
metadata:
 name: my_service
spec:
  host:www.example.com # the same service address/url/CNAME as above
 to:
   kind: Service
   name: my_service
 tls:
   termination: edge
   insecureEdgeTerminationPolicy: Redirect
   key:
      |------BEGIN PRIVATE KEY----- # your keys, certificates and CA certificates[...] The contents of the key.pem
     -----END PRIVATE KEY-----
   certificate:
      |------BEGIN CERTIFICATE-----[...] from the email: as Certificate only, PEM encoded:
     -----END CERTIFICATE-----
   caCertificate:
      |------BEGIN CERTIFICATE-----[...] from the email: as Intermediate(s)/Root only, PEM encoded:
     -----END CERTIFICATE-----

If a file has more than one certificate inside it, add them one-after-another, so that each has its own begin and end certificate rows.

If you are using nginx as a reverse-proxy, the certificates do not need to be placed in the Route.yaml. 

Still does not work! No Pod or Service error

Check the following things:

  1. The pod is actually working.  Port forward directly to the port serving the pod:
    1. oc port-forward <pod-name> <local-port>:<pod-port>
    2. and in another terminal: curl localhost:<local-port>
  2. Your Service has correct endpoints. Optionally the selectorLabel in your Service is not matching to the correct pods. The command "oc get endpoints" should list all Services and their endpoints. At least one endpoint resembling 10.12.*:<pod-port> should exist.

 

Contact information

The recommended contact for questions is:

https://helsinkifi.slack.com #kontit 

All changes related to resources for the project/namespace should be emailed to:

grp-openshift-owner@helsinki.fi (platform administration and development)tike-ohjelmistotuotanto@helsinki.fi (program development)