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.
- Node Port
- Load Balancers
- Ingress
- 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.
The following diagrams explain how the traffic users routed to the service in the openshift.
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.
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.
5. You can click on the “Not secure” icon to know more about the certificate details.
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).
Leave a Reply