Site icon UnixArena

How to expose service on the Openshift? Enable TLS secure route?

Openshift provides multiple options to expose the application to external traffic. When you deploy a pod in openshift, kubernetes allocates the internal IP address for each pod. If you are deploying an nginx container to serve the webpage, the nginx pod will have a unique internal IP address but it can’t be accessed outside the cluster. To access the container, outside the cluster, you need to expose the pod to external traffic. When you expose the pod to external traffic, a pod will be treated like an actual server in terms of port allocation, load balancing, naming, service discovery, etc.. Here is the list of options to expose the application to external traffic.

  1. Node Port
  2. Load Balancers
  3. Ingress
  4. Route

In this article, we will expose the service using the route method and secure the route using a TLS certificate. Route objects are not allowed to read the secrets directly. This means you need to update the certificate and private key on the route manifest.

Let’s start from scratch

Download nginx helm chart from the repo:

1. Add the known helm repo to pull the sample helm chart for the nginx service.

[lingesh@okd4 ~]$ helm repo add bitnami https://charts.bitnami.com/bitnami
"bitnami" has been added to your repositories
[lingesh@okd4 ~]$ 

2. Download the helm chart from the repo using the pull command.

[lingesh@okd4 ~]$ helm pull bitnami/nginx
[lingesh@okd4 ~]$
[lingesh@okd4 ~]$ ls -lrt nginx*
-rw-r--r--. 1 lingesh lingesh 39771 Nov 13 17:53 nginx-13.2.13.tgz

3. Extract the chart using the tar command.

[lingesh@okd4 ~]$ tar -xf nginx-13.2.13.tgz
[lingesh@okd4 ~]$
[lingesh@okd4 ~]$ cd nginx/
[lingesh@okd4 nginx]$ ls -lrt
total 100
-rw-r--r--. 1 lingesh lingesh 36079 Nov  2 20:00 values.yaml
-rw-r--r--. 1 lingesh lingesh  2489 Nov  2 20:00 values.schema.json
-rw-r--r--. 1 lingesh lingesh 48312 Nov  2 20:00 README.md
-rw-r--r--. 1 lingesh lingesh   790 Nov  2 20:00 Chart.yaml
-rw-r--r--. 1 lingesh lingesh   218 Nov  2 20:00 Chart.lock
drwxrwxr-x. 2 lingesh lingesh  4096 Nov 13 17:54 templates
drwxrwxr-x. 3 lingesh lingesh    20 Nov 13 17:54 charts
[lingesh@okd4 nginx]$ 

Deploy nginx using helm chart:

1. Create a new namespace for the test deployment. Switched to the newly created namespace.

[lingesh@okd4 nginx]$ oc create ns ua-nginx
namespace/ua-nginx created
[lingesh@okd4 nginx]$ oc project ua-nginx
Now using project "ua-nginx" on server "https://api.crc.testing:6443".
[lingesh@okd4 nginx]$

2. Deploy the service using the helm command.

[lingesh@okd4 ~]$ helm install ua-nginx nginx
NAME: ua-nginx
LAST DEPLOYED: Sun Nov 13 18:32:34 2022
NAMESPACE: ua-nginx
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
CHART NAME: nginx
CHART VERSION: 13.2.13
APP VERSION: 1.23.2

** Please be patient while the chart is being deployed **
NGINX can be accessed through the following DNS name from within your cluster:

    ua-nginx.ua-nginx.svc.cluster.local (port 80)

To access NGINX from outside the cluster, follow the steps below:

1. Get the NGINX URL by running these commands:

  NOTE: It may take a few minutes for the LoadBalancer IP to be available.
        Watch the status with: 'kubectl get svc --namespace ua-nginx -w ua-nginx'

    export SERVICE_PORT=$(kubectl get --namespace ua-nginx -o jsonpath="{.spec.ports[0].port}" services ua-nginx)
    export SERVICE_IP=$(kubectl get svc --namespace ua-nginx ua-nginx -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
    echo "http://${SERVICE_IP}:${SERVICE_PORT}"
[lingesh@okd4 ~]$

3. List the deployed resources.

[lingesh@okd4 ~]$ oc get all
NAME                            READY   STATUS    RESTARTS   AGE
pod/ua-nginx-7bd5c655bb-s9wb8   1/1     Running   0          5m42s

NAME               TYPE           CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGE
service/ua-nginx   LoadBalancer   10.217.4.20   <pending>     80:31541/TCP   5m43s

NAME                       READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/ua-nginx   1/1     1            1           5m43s

NAME                                  DESIRED   CURRENT   READY   AGE
replicaset.apps/ua-nginx-7bd5c655bb   1         1         1       5m42s
[lingesh@okd4 ~]$

4. Let me change the service type from LoadBalancer to ClusterIP since we will be exploring the route option.

[lingesh@okd4 ~]$ oc patch service/ua-nginx  -p '{"spec": {"type": "ClusterIP"}}'
service/ua-nginx patched
[lingesh@okd4 ~]$ oc get all
NAME                            READY   STATUS    RESTARTS   AGE
pod/ua-nginx-7bd5c655bb-s9wb8   1/1     Running   0          7m36s

NAME               TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)   AGE
service/ua-nginx   ClusterIP   10.217.4.20   <none>        80/TCP    7m37s

NAME                       READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/ua-nginx   1/1     1            1           7m37s

NAME                                  DESIRED   CURRENT   READY   AGE
replicaset.apps/ua-nginx-7bd5c655bb   1         1         1       7m36s
[lingesh@okd4 ~]$

How to expose service to external IP in OCP?

1. Service can be easily exposed to external networks in Openshift using the route. Use “oc expose svc service_name” to populate the route automatically.

[lingesh@okd4 ~]$ oc expose service/ua-nginx
route.route.openshift.io/ua-nginx exposed
[lingesh@okd4 ~]$ oc get route
NAME       HOST/PORT                            PATH   SERVICES   PORT   TERMINATION   WILDCARD
ua-nginx   ua-nginx-ua-nginx.apps-crc.testing          ua-nginx   http                 None
[lingesh@okd4 ~]$ 

2. View the route manifest.

[lingesh@okd4 ~]$ oc get route ua-nginx -o yaml
apiVersion: route.openshift.io/v1
kind: Route
metadata:
  annotations:
    openshift.io/host.generated: "true"
  creationTimestamp: "2022-11-09T05:35:56Z"
  labels:
    app.kubernetes.io/instance: ua-nginx
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/name: nginx
    helm.sh/chart: nginx-13.2.13
  name: ua-nginx
  namespace: ua-nginx
  resourceVersion: "221333"
  uid: c9194dd1-2a3f-4c52-bd50-87df3251b09b
spec:
  host: ua-nginx-ua-nginx.apps-crc.testing
  port:
    targetPort: http
  to:
    kind: Service
    name: ua-nginx
    weight: 100
  wildcardPolicy: None
status:
  ingress:
  - conditions:
    - lastTransitionTime: "2022-11-09T05:35:56Z"
      status: "True"
      type: Admitted
    host: ua-nginx-ua-nginx.apps-crc.testing
    routerCanonicalHostname: router-default.apps-crc.testing
    routerName: default
    wildcardPolicy: None
[lingesh@okd4 ~]$ 

3. Test our work. We are able to access the route URL from our host.

[lingesh@okd4 ~]$ curl ua-nginx-ua-nginx.apps-crc.testing
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
[lingesh@okd4 ~]$ 

4. You can also browse the webpage from the browser.

nginx – webpage

The following diagrams explain how the traffic users routed to the service in the openshift.

OpenShift route

Enable TLS termination to Secure route in Openshift:

1. Generate a self-signed certificate and private key using the OpenSSL command.

[lingesh@okd4 ua-cert]$ openssl req -new -newkey rsa:4096 -x509 -sha256 -days 365 -nodes -out MyCertificate.crt -keyout MyKey.key
Generating a RSA private key
........++++
..............................++++
writing new private key to 'MyKey.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:IN
State or Province Name (full name) []:KA
Locality Name (eg, city) [Default City]:Bangalore
Organization Name (eg, company) [Default Company Ltd]:UA
Organizational Unit Name (eg, section) []:IT
Common Name (eg, your name or your server's hostname) []:apps-crc.testing
Email Address []:

[lingesh@okd4 ua-cert]$ ls -lrt
total 8
-rw-------. 1 lingesh lingesh 3268 Nov 13 22:08 MyKey.key
-rw-rw-r--. 1 lingesh lingesh 2021 Nov 13 22:09 MyCertificate.crt
[lingesh@okd4 ua-cert]$

2. Once the certificate is generated, you can edit the route and enable the TLS termination by updating the certificate and key like below.

TLS certificate update on OCP route – Termination edge

Example:

apiVersion: route.openshift.io/v1
kind: Route
metadata:
  name: frontend
spec:
  host: www.example.com
  to:
    kind: Service
    name: frontend
  tls:
    termination: edge
    key: |-
      -----BEGIN PRIVATE KEY-----
      [...]
      -----END PRIVATE KEY-----
    certificate: |-
      -----BEGIN CERTIFICATE-----
      [...]
      -----END CERTIFICATE-----

3. Get the FQDN for the route

[lingesh@okd4 certs]$ oc get route
NAME       HOST/PORT                            PATH   SERVICES   PORT   TERMINATION   WILDCARD
ua-nginx   ua-nginx-ua-nginx.apps-crc.testing          ua-nginx   http   edge          None
[lingesh@okd4 certs]$

4. Try to access the FQDN/Host with HTTPS. You should get the nginx webpage like below.

Secure route enabled using self-sign certificate – OCP

5. You can click on the “Not secure” icon to know more about the certificate details.

Certificate details – UA

Conclusion:

We have successfully deployed the nginx web service using the helm chart on the OCP cluster. Once the deployment was successful, we exposed the service which creates the OCP routes by default. Later. we have created the self-signed certificate and enabled TLS termination for the route (secure route).

Exit mobile version