ocp

Deploying a Dot Net Core Apps into Openshift 4

The goal of this article is to display a simple hello-world apps build on top of a .net core 7 that can be use to test a deployment to Openshift 4 platform. And we can start it by using a git clone command

$ git clone https://github.com/edwin/hello-world-dot-net-core

Go to the corresponding folder,

$ cd hello-world-dot-net-core

Create a namespace for this app,

$ oc new-project dot-net-ns

And run this command within the sourcecode folder,

$ oc new-app dotnet:7.0-ubi8~.

It will generate logs like this,

warning: Cannot check if git requires authentication.
--> Found image 4466483 (2 months old) in image stream "openshift/dotnet" under tag "7.0-ubi8" for "dotnet:7.0-ubi8"

    .NET 7
    ------
    Platform for building and running .NET 7 applications

    Tags: builder, .net, dotnet, dotnetcore, dotnet-70

    * A source build using source code from https://github.com/edwin/hello-world-dot-net-core#master will be created
      * The resulting image will be pushed to image stream tag "hello-world-dot-net-core:latest"
      * Use 'oc start-build' to trigger a new build

--> Creating resources ...
    imagestream.image.openshift.io "hello-world-dot-net-core" created
    buildconfig.build.openshift.io "hello-world-dot-net-core" created
    deployment.apps "hello-world-dot-net-core" created
    service "hello-world-dot-net-core" created
--> Success
    Build scheduled, use 'oc logs -f buildconfig/hello-world-dot-net-core' to track its progress.
    Application is not exposed. You can expose services to the outside world by executing one or more of the commands below:
     'oc expose service/hello-world-dot-net-core'
    Run 'oc status' to view your app.

And finally we can create a route for this service,

$ oc create route edge --service=hello-world-dot-net-core

We can try to do some changes on Index.cshtml file,

@{
    ViewData["Title"] = "Home Page";
}

<div class="text-center">
    <h1 class="display-4">Welcome</h1>
    <p>Learn about <a href="https://redhat.com">Red Hat loves dotnet</a>.</p>
</div>

Save and redeploy it by running below command in the root sourcecode folder,

$ oc start-build hello-world-dot-net-core --from-dir=.

The result would be something like this,

Lets do some more changes, and deploy it to Openshift

@{
    ViewData["Title"] = "Home Page";
}

<div class="text-center">
    <h1 class="display-4">Welcome</h1>
    <p>Learn about <a href="https://redhat.com">Red Hat loves alot of programming language but we loves dotnet more</a>.</p>
</div>

And we instantly can see changes within the web page,

Code can be seen here,

https://github.com/edwin/hello-world-dot-net-core

How to Expose Openshift Route into a Secure Endpoint

We can do below command to expose a specific Openshift Service into a route or URL

$ oc expose svc <service-name>

but it would create a regular not-secure http endpoint, which sometimes not sufficient enough to fulfil our requirements. Therefore we need to find a way to create a secure route endpoint, and we can achieve that condition by using below command

$ oc create route edge --service <service-name>

It would create a route with an edge TLS termination.

Importing a Custom SPI into Keycloak Operator in Openshift

Keycloak Operator provide a convenient method for uploading a custom SPI into Keycloak instances, and that is by using an extensions inside Keycloak YAML operator.

apiVersion: keycloak.org/v1alpha1
kind: Keycloak
metadata: 
  namespace: my-redhat-sso
  labels:
    app: sso
spec:
  extensions:
    - >-
      https://url/custom-sso-spi-1.0.0.jar
  externalAccess:
    enabled: true
  externalDatabase:
    enabled: true
  instances: 1

Rollout your Keycloak pod, and you can see that Keycloak instance is now having a custom SPI embedded within it.

Java, SecureRandom, and Openshift

Had one unique case where generating a SecureRandom in Java is very very slow, the thing is that this never happens on a regular VM deployment, and only happens in a Pod deployment in Openshift 4.

This is original sample code that is slow,

    @GetMapping(path = "/secure-random")
    public HashMap secureRandom() {
        SecureRandom secureRandom = new SecureRandom();
        secureRandom.setSeed(secureRandom.generateSeed(24));
        return new HashMap(){{
            put("random-value", String.format("%06d", secureRandom.nextInt(1000000)));
        }};
    }

The reason why it is slow is because SecureRandom is relying on the OS random generator which is relying on noise. And it seems that for our case, we are lacking of noise to make a good entropy therefore we arent able to generate a SecureRandom at all.

Our workaround for this is by using a Pseudo Random Number Generator (PRNG) from Java, and not relying on the OS at all. For this example, im using “SHA1PRNG”.

    @GetMapping(path = "/secure-random-new")
    public HashMap secureRandomNew() throws Exception {
        SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
        secureRandom.setSeed(secureRandom.generateSeed(24));
        return new HashMap(){{
            put("random-value", String.format("%06d", secureRandom.nextInt(1000000)));
        }};
    }

Hope it helps.

Fail Fast Architecture using Openshift Container Platform

This week ive met an application that are being deployed as Pod in OCP but having a very unique behaviour, it keeps giving below error every one and a while.

[5585.146s][warning][os,thread] Failed to start thread "Unknown thread" 
         - pthread_create failed (EAGAIN) for attributes: stacksize: 1024k, guardsize: 0k, detached.
[5585.147s][warning][os,thread] Failed to start the native thread for java.lang.Thread "HandshakeCompletedNotify-Thread"
[5586.153s][warning][os,thread] Failed to start thread "Unknown thread" 
         - pthread_create failed (EAGAIN) for attributes: stacksize: 1024k, guardsize: 0k, detached.
[5586.154s][warning][os,thread] Failed to start the native thread for java.lang.Thread "HandshakeCompletedNotify-Thread"
[5589.672s][warning][os,thread] Failed to start thread "Unknown thread" 
         - pthread_create failed (EAGAIN) for attributes: stacksize: 1024k, guardsize: 0k, detached.
[5589.673s][warning][os,thread] Failed to start the native thread for java.lang.Thread "pool-4944-thread-1"
06:57:23,949 
         ERROR [io.undertow.request] (default task-34) UT005023: Exception handling request to /actuator/health: java.lang.OutOfMemoryError: 
         unable to create native thread: possibly out of memory or process/resource limits reached	

It seems that once this error happens, Pod will never recover from this condition. So Openshift need to find a way to handle this situation.

One workaround which i found is by utilizing Kubernetes Liveness Probe, which will detect application’s healthness.

      livenessProbe:
        httpGet:
          path: /actuator/health
          port: 8080
          scheme: HTTP
        initialDelaySeconds: 60
        timeoutSeconds: 3
        periodSeconds: 4
        successThreshold: 1
        failureThreshold: 2

For this configuration I am setting a 4 seconds delay between request and will wait for 3 seconds for reply from the corresponding Pod. And if Pod are unable to response to Openshift’s request for two times, Openshift will force terminate the Pod assuming that the Pod is in an unhealthy state.

This strategy makes applications restart quite often in a day, but at least it will be healthy again after being restarted forcefully.