Openshift is a cloud-based Kubernetes service by RedHat. OpenShift routes enable access to pods (one or more containers deployed in a cluster) from external resources. In most cases, applications deployed on OpenShift expose external endpoints to the outside of the cluster through a router.
For example, if your Kubernetes workload is a web API (or any other interface external users need to access), you need to provide a route to the particular service or pod within OpenShift to access the required application or service. Each route consists of a name (limited to 63 characters), a service selector, and an optional security configuration.
To help you better understand the topic, we’ll take a closer look at the types of OpenShift routes and different methods for configuration and troubleshooting.
There are two types of OpenShift routes:
Let’s start by looking at an unsecured route example.
Unsecured Routes in OpenShift use plaintext HTTP communication. You can create OpenShift routes through GUI/web console or CLI (command line interface). Below, we’ll walk through both methods
To create a route using the Web Console, navigate to the “Routes” page under the “Application” section. Select the "Create Route" option to configure and create the route.
Use the following command to create an unsecured route
$oc expose svc/service --hostname=www.example.com
This command exposes the service against the URL www.example.com
. External users will be redirected to
the service named service
when accessing the URL www.example.com
.
Below is the YAML definition for Unsecured Route Object:
apiVersion: route.openshift.io/v1
kind: Route
metadata:
name: route-unsecured
spec:
host: www.example.com
to:
kind: Service
name: service-name
Unsecured routes are much easier to maintain because they do not require a key or certificate.
Path-Based routes allow for a path to be specified within the route. It is then compared against a URL to either allow or disallow the traffic. Traffic for a Path-Based route should be HTTP-based (unsecured). The same hostname can be used to configure multiple routes, each with its path. The URL is compared to the routes, and the most specific route (best match) is chosen. In the case of multiple routes, the comparison will move to the following route until the best match is found. This is all configurable, and the comparison criteria can be configured in the router. The hostname and paths are sent back to the server for it to respond to its requests successfully.
For example, if the route www.example.com/test
is compared to the URL www.example.com/test
it will allow the traffic. However, it will not allow traffic compared to a URL of www.example.com
.
On the other hand, if the route www.example.com is compared to the URL www.example.com/test, it will allow traffic based on the comparison match with the host and not the route.
Here is the YAML for an unsecured route with a path:
apiVersion: route.openshift.io/v1
kind: Route
metadata:
name: route-unsecured
spec:
host: www.example.com
path: "/test" (1)
to:
kind: Service
name: service-name
📝 Note: defining a route is the only additional attribute in path-based routing. Path-based routing is not secured and does not support TLS termination.
For more examples, visit the OpenShift Path-based Routing documentation.
As the name suggests, Secured Routes are secured with TLS by providing a key and certificate. Secure routes offer various TLS terminations to serve certificates to the client. A TLS termination is the process of decrypting encrypted traffic. In OpenShift, TLS termination means terminating TLS encryption before passing the traffic to the required service or pod. Routers support edge, passthrough, and re-encryption termination.
TLS Termination in OpenShift uses SNI (Server Name Indication). SNI is an extension of the Transport Layer Security (TLS) network protocol. The client indicates which hostname it is trying to connect to at the beginning of the TLS handshake.
Non-SNI traffic routed to the secure port (default 443) is assigned a default certificate that most likely will not match the hostname, resulting in an authentication error.
You can learn more about secured routes in the OpenShift Route documentation.
Below is an overview of an SNI communication flow:
Secured routes can use one of three types of secure TLS termination. The type of termination is determined by where the encryption is being terminated. The three termination types are:
In the sections below, we’ll take a closer look at each type of termination.
Edge termination terminates the encryption at the router. All communication till the router is secured, and any communication from the router to the endpoints is not. Since the encryption in edge termination is terminated at the router, the TLS certificate must be added to the route. If no certificate is specified, the router's default certificate is used and will likely result in an authentication error.
The screenshot below shows how edge termination is configured using a GUI. Note that there is an option in the screenshot below to deal with "Insecure traffic". Edge termination allows three different ways to treat insecure traffic. It can either be blocked, allowed, or redirected.
The following command is used to create a Secure Route with Edge Termination
$oc create route edge --service=route-edge-secured --cert=tls.crt --key=tls.key --ca-cert=ca.crt --hostname=www.example.com
Note: Certificate/Key pair must be created in PEM-encoded format and should exist in the path folder before running the above command.
Below is the YAML for a Secured Route using Edge Termination:
apiVersion: route.openshift.io/v1
kind: Route
metadata:
name: route-edge-secured (1)
spec:
host: www.example.com
to:
kind: Service
name: route-edge-secured
tls:
termination: edge (2)
key: |- (3)
-----BEGIN PRIVATE KEY-----
[...]
-----END PRIVATE KEY-----
certificate: |- (4)
-----BEGIN CERTIFICATE-----
[...]
-----END CERTIFICATE-----
caCertificate: |- (5)
-----BEGIN CERTIFICATE-----
[...]
-----END CERTIFICATE-----
name
field is used for naming the object and has a limit of 63 characters.termination
field is edge
for edge termination.key
field is where the contents of the PEM key are entered.certificate
field is for the contents of the certificate in PEM format.caCertificate
is optional but it may be required to enter the CA (Certificate Authority) cert for successful authentication.insecureEdgeTerminationPolicy
is the attribute used to configure what happens
with this type of traffic. The three values representing the goal discussed above are None
or empty, Allow
or Redirect.
Below is the YAML for A Secured Route using Edge Termination allowing HTTP Traffic:
apiVersion: route.openshift.io/v1
kind: Route
metadata:
name: route-edge-secured-allow-insecure (1)
spec:
host: www.example.com
to:
kind: Service
name: service-name
tls:
termination: edge (2)
insecureEdgeTerminationPolicy: Allow (3)
[ ... ]
name
field is used for naming the object and has a limit of 63 characters.termination
field is edge
for Edge Termination.insecureEdgeTerminationPolicy
field is used to configure what happens with the insecure traffic.
In the example YAML file above, insecure traffic is allowed.Below is the YAML for a Secured Route Using Edge Termination redirecting HTTP traffic to HTTPS:
apiVersion: route.openshift.io/v1
kind: Route
metadata:
name: route-edge-secured-redirect-insecure (1)
spec:
host: www.example.com
to:
kind: Service
name: service-name
tls:
Termination: edge (2)
insecureEdgeTerminationPolicy: Redirect (3)
[ ... ]
name
field is used for naming the object and has a limit of 63 characters.termination
field is edge
for Edge Termination.insecureEdgeTerminationPolicy
field is used to configure what happens with the insecure traffic.
In the example YAML file above, insecure traffic is Redirected to HTTPS.In Passthrough Termination, the termination is passed on from the router straight to the pod. The pod is then responsible for providing the certificate and decrypting the traffic. Since termination is not happening on the router, certificates are not part of the route.
Passthrough Termination provides end-to-end encryption. This is the only type of termination that requires the client to have a certificate. It is also known as "two-way authentication”. The screenshot below shows how to configure Passthrough Termination using GUI.
Even though Passthrough Termination is being used, there is still an option for “Insecure traffic”. The only options available for “Insecure traffic” when using Passthrough termination are “empty” or “redirect”. There is no option to add the certificate because the Pod provides the certificate for Passthrough Termination.
The following command is used to create passthrough termination:
$oc create route passthrough route-passthrough --service=service-name --port=1234
Below is the YAML for a Secured Route using Passthrough Termination:
apiVersion: route.openshift.io/v1
kind: Route
metadata:
name: route-passthrough (1)
spec:
host: www.example.com
Port:
targetPort: 1234
to:
kind: Service
name: service-name
tls:
termination: passthrough (2)
name
field is used for naming the object and has a limit of 63 characters.termination
field is passthrough
for Passthrough Termination.Re-encryption is Edge Termination with encapsulation. The termination happens at the
router the same way it does in Edge Termination. However, instead of forwarding the
insecure traffic to the Pod, blocking it, or redirecting it (which can be specified
using insecureEdgeTerminationPolicy
field), the router re-encrypts the traffic before
sending it off to the destination.
The re-encryption certificate can use a different certificate depending on the endpoint requirement. This secures the entire path, even the internal communication
The screenshot below shows how Re-encryption Termination is configured using the OpenShift GUI.
The following command can be used to create a Secured Re-encrypt route
$oc create route reencrypt --service=route-pt-secured --cert=tls.crt --key=tls.key --dest-ca-cert=destca.crt --ca-cert=ca.crt --hostname=www.example.com
Note: Certificate/Key pair must be created in PEM-encoded format and should exist in the path folder before running the above command.
Below is the YAML for a Secured Route using Re-Encrypt Termination:
apiVersion: v1
kind: Route
metadata:
name: route-pt-secured
spec:
host: www.example.com
to:
kind: Service
name: route-pt-secured (1)
tls:
termination: reencrypt (2)
key: [as in edge termination]
certificate: [as in edge termination]
caCertificate: [as in edge termination]
destinationCACertificate: |- (3)
-----BEGIN CERTIFICATE-----
[...]
-----END CERTIFICATE-----
name
field is used for naming the object and has a limit of 63 characters.termination
field is set to reencrypt
for Re-encryption Termination.destinationCACertificate
field specifies the certificate for re-encryption, which
will encrypt the traffic leaving the router to the Pod after the initial TLS termination on the router.
If this field is left empty, the router will automatically use the certificate generated by the
Certificate Authority configured to provide a certificate for this service. This saves the need
for adding a certificate for every new path or router.Since Re-encryption Termination is the same as Edge Termination for the initial TLS termination, its routes will have insecureEdgeTerminationPolicy with all the same values as Edge-Terminated routes.
To help you get started with basic troubleshooting for OpenShift routes and applications, let's assume you have a service configured in a cluster and a user is trying to access this service from outside the cluster. They can’t access the service and you need to figure out why. Below, we’ll walk through some steps to help troubleshoot.
You know there needs to be a process configured to listen on a public IP for any external user attempting to access the service for this to work. A route is also required for the traffic inside the cluster if an attempt to reach the service has been made externally.
The command given below is run on the machine where the issue occurs to determine if the service is running. This is used if the HTTP service is unavailable from outside the cluster.
curl -kv http://link.example.com:8000/bar
Next, you should check if DNS is working. Only do this if the previous command returns output suggesting that the service is running internally, but there may b an issue with DNS.
dig +short link.example.com
The command above should resolve the given URL to an IP address. This shows that the URL can be resolved externally. If it doesn't resolve, there is an issue with the DNS.
However, if the URL resolves or it starts to resolve after fixing the DNS issue, and the service is still not accessible externally, you should continue troubleshooting. The next step is to telnet to the resolved IP address against the port your service is running on.
telnet10.20.30.40 8000
The command should result in this output.
Trying 10.20.30.40...
Connected to 10.20.30.40
If the router is not listening on the specified port, it will return the following error.
Trying 10.20.30.40...
telnet: connect to address 10.20.30.40: Connection refused
Or the following error if there is no service listening on the IP address.
Trying 10.20.30.40...
telnet: connect to address 10.20.30.40: Connection timed out
In either case, we will then need to troubleshoot the router. You can find information on OpenShift network troubleshooting here.
To check if the application route is working, run the oc get route
command. This command lists the running
routes in the current namespace. If it gives the output and shows that the route is working,
there is no issue in the route.
If the oc get route
command shows that the route is not working, then run the command oc describe route
"route name"
to get a detailed description of the issue. This will help to identify and fix the issue.
That covers the basics of OpenShift route and application troubleshooting. For a deeper dive, see the Troubleshooting section of the OpenShift admin guide.
OpenShift allows different types of routes to be configured depending on the use case. With the ever-growing security challenges, the focus on the Zero Trust security principle is the way forward for organizations. Even though OpenShift allows certain route types to be configured without end-to-end encryption, it is best to keep the environment as secure as possible and use Passthrough and Re-encryption Termination whenever possible.