delivered for clients · names withheldmodernization Applications

Legacy web apps to containers on Kubernetes or OpenShift

Cohash containerizes legacy web applications and runs them on Kubernetes, EKS, AKS or OpenShift. We pick the apps that fit. Then we externalize configuration and secrets, move session state and file storage off the server, build minimal images in CI and deploy through GitOps with health checks and autoscaling. An app that would need a rewrite to containerize gets a different plan.

  1. 01Fit assessment
  2. 02Twelve-factor clean-up
  3. 03Images and pipeline
  4. 04Platform onboarding
  5. 05Cut-over and VM retirement
case-study / legacy-app-to-containers delivered
beforeWeb apps on hand-patched VMs afterContainers on Kubernetes or OpenShift
01 · BUILD AND DEPLOY 02 · PLATFORM 03 · BACKING SERVICES CI pipeline: scan · sign · non-root images CI pipeline scan · sign · non-rootimages Private registry Private registry Argo CD or OpenShift GitOps: cluster state matches the repo Argo CD or OpenShiftGitOps cluster state matchesthe repo Ingress and probes: health checks · autoscaling Ingress and probes health checks ·autoscaling Kubernetes or OpenShift: namespaces · quotas · network policy Kubernetes orOpenShift namespaces · quotas ·network policy HashiCorp Vault: secrets HashiCorp Vault secrets Redis or a database: session state Redis or a database session state Object storage: uploaded files Object storage uploaded files
case file

The story

Told without the client's name or anything that could identify them.

what happened

A manufacturer's application team ran its Java, .NET and PHP web apps on servers built by hand, and a deployment meant RDP or SSH, copying files and restarting services in a maintenance window. A platform team already ran Kubernetes, but most business apps sat on VMs beside it, and OS upgrades were stuck because nobody knew what each server had installed. We scored each app for fit, moved config, secrets, sessions and uploads off the servers, and built signed, non-root images in CI. Apps that fit moved onto the cluster through GitOps with traffic shifted gradually at the load balancer, and their VMs and patching schedules were retired.

why it was urgent

Extended support for Windows Server 2016 ends on 12 January 2027, and Microsoft says its container images end on the same dates. Moving an old IIS app into a 2016-based container doesn't buy you anything. The platforms keep moving too: EKS supports each Kubernetes minor for 14 months as standard, and OpenShift 4.22 came out on 9 June 2026.

problem statement
  • openApp servers built by hand, and the only person who can rebuild one is on holiday.
  • recurringReleasing still means an RDP or SSH session, copying files across and restarting services in a maintenance window.
  • blockedA platform team runs Kubernetes, but most business apps still live on VMs beside it.
  • openOS upgrades are stuck because nobody is sure what each server has installed.
architecture

The estate, before and after

before
before

Before: hand-built VMs with state on the server

Engineers deployed by RDP or SSH onto servers built by hand, and the load balancer pinned users to one server for their session. Uploads, logs, config and secrets all lived on the server's own disk.

Before: hand-built VMs with state on the server Engineers deployed by RDP or SSH onto servers built by hand, and the load balancer pinned users to one server for their session. Uploads, logs, config and secrets all lived on the server's own disk. 01 · DEPLOYS AND TRAFFIC 02 · APP SERVERS 03 · STATE ON THE SERVER manual deploy manual deploy sticky traffic sticky traffic writes files reads secrets session state Engineers over RDP or SSH copy files · restartservices Load balancer sticky sessions Java app VM hand-built · hand-patched IIS .NET app VM OS upgrade stuck PHP app VM Local disk uploads · logs · caches Config files secrets in plain text In-memory sessions tied to one server
Read the diagram as text
  1. Engineers over RDP or SSH → Java app VM: manual deploy
  2. Engineers over RDP or SSH → IIS .NET app VM: manual deploy
  3. Load balancer → Java app VM: sticky traffic
  4. Load balancer → PHP app VM: sticky traffic
  5. Java app VM → Local disk: writes files
  6. IIS .NET app VM → Config files: reads secrets
  7. PHP app VM → In-memory sessions: session state
after
after

After: signed images deployed by GitOps, with state moved off the server

Images come out of CI signed and non-root, into a private registry. GitOps keeps the cluster matched to the repo. Secrets are read from Vault. Sessions and files live in shared services, so any pod can serve any user.

After: signed images deployed by GitOps, with state moved off the server Images come out of CI signed and non-root, into a private registry. GitOps keeps the cluster matched to the repo. Secrets are read from Vault. Sessions and files live in shared services, so any pod can serve any user. 01 · BUILD AND DEPLOY 02 · PLATFORM 03 · BACKING SERVICES signed image image pull sync from repo traffic secrets sessions file storage CI pipeline scan · sign · non-rootimages Private registry Argo CD or OpenShiftGitOps cluster state matches therepo Ingress and probes health checks · autoscaling OP Kubernetes orOpenShift namespaces · quotas ·network policy HashiCorp Vault secrets Redis or a database session state Object storage uploaded files
Read the diagram as text
  1. CI pipeline → Private registry: signed image
  2. Private registry → Kubernetes or OpenShift: image pull
  3. Argo CD or OpenShift GitOps → Kubernetes or OpenShift: sync from repo
  4. Ingress and probes → Kubernetes or OpenShift: traffic
  5. Kubernetes or OpenShift → HashiCorp Vault: secrets
  6. Kubernetes or OpenShift → Redis or a database: sessions
  7. Kubernetes or OpenShift → Object storage: file storage
results

What the client got

What changed for the client once the work was done. Described, not scored: we don't publish client figures.

  1. result 01

    Each app has a recorded fit decision

    Every application was scored on runtime, OS dependencies, local writes, sessions, licensing and startup, and poor fits got a managed-service or stay-on-VM plan instead of a forced container.

  2. result 02

    Deployments are pull requests, not remote sessions

    Releases go through Argo CD or OpenShift GitOps now. The cluster matches the repo, and nobody copies files onto a server anymore.

  3. result 03

    Pods can restart without losing state

    We moved config into environment variables or config maps and secrets into Vault or the cloud secret store. Sessions sit in Redis or a database now, and uploads in object storage.

  4. result 04

    Images follow one standard from the first app

    Images are minimal and run as non-root. We scan them for dependencies and vulnerabilities, sign them in CI and pull them from a private registry.

  5. result 05

    Retired VMs left the patching schedule

    Once traffic had moved and errors and latency held steady, we shut down each app's VM and took it off the patching schedule.

what can go wrong

Risks we plan for

  1. Apps that write to local disk

    Anything an app writes to the server's disk, logs, uploads, caches, vanishes when a pod restarts. We find those in the assessment, not in production.

  2. Licensing tied to hosts

    Some commercial app servers and libraries are licensed per host or per core, and that changes on a shared cluster. We check the licences before building images.

  3. Containers as a new place for old problems

    An image built on an old base, running as root, with secrets baked in, isn't progress. Image standards and scanning apply from the first app.

ai in this move

Where AI helps, and where it needs guardrails

AI coding assistants are good at drafting Dockerfiles, Helm charts and probes from an existing app's config, and Microsoft's GitHub Copilot modernization agent handles parts of .NET upgrades. We review every generated manifest against platform policy. Agents that deploy to clusters work through GitOps pull requests, not direct cluster credentials.

forward deployed engineers →
you keep

What you're left with

We write these for your setup, and they're working documents. Your team should be able to keep things running from them long after we've gone.

  • report01

    Container fit assessment per application

    yours to keep
  • code02

    Hardened base images and CI pipeline with scanning and signing

    yours to keep
  • document03

    Helm charts or Kustomize overlays per app

    yours to keep
  • guide04

    Namespace, quota and network policy setup per team

    yours to keep
  • runbook05

    Cut-over plan and VM retirement record

    yours to keep
talent and delivery · containers on kubernetes or openshift

Certified engineers, wherever you need them.

Some clients want a project team, some want a couple of engineers on theirs. Either works. Onsite, nearshore or offshore, with handovers across time zones that keep things moving.

Onsite

Engineers at your sites in the US

Nearshore

Overlapping hours with US teams

Offshore

Overnight progress on your backlog

All time zones

Coverage handed over across time zones

24-hour coverage · US Central time
OnsiteUS business hours
Nearshoreoverlapping US hours
Offshoreovernight progress
Combinedhandover, not hand-off
01Kubernetes or OpenShift?

That depends on how you want support to work and what's already in place. OpenShift comes with a registry, GitOps, monitoring and Red Hat support, so teams wanting one vendor tend to pick it. Managed Kubernetes like EKS or AKS fits teams happy to assemble those parts.

02Can .NET Framework apps run in containers?

Yes, as Windows containers on Windows nodes. A lot of teams do that first and port to modern .NET later, at which point Linux containers become an option.

03How many apps should we move first?

Pick a few apps that fit well and whose owners actually care. They'll set the image standards and pipeline patterns everything after them reuses.

04Do you run the clusters too?

Either we keep running platform upgrades, add-ons and capacity, or your platform team takes over with our runbooks.

sources 4 sources linked last checked 2026-10-20 content fingerprint 5696a23c
  1. 01Microsoft Lifecycle: Windows Server 2016 (containers follow the same dates)learn.microsoft.com ↗
  2. 02AWS: Kubernetes version lifecycle on EKSdocs.aws.amazon.com ↗
  3. 03Red Hat: OpenShift 4.22 release notesdocs.redhat.com ↗
  4. 04Microsoft Learn: .NET Upgrade Assistant overview (Copilot modernization agent)learn.microsoft.com ↗
Reviewed by the Cohash team Product names are trademarks of their owners. how we handle facts and data →
next step

Planning this move?

A 30-minute working session with a senior engineer. No slides.

useful to bring
  • The platform and the version you're on
  • Where you need to get to, and by when
  • What's custom: rules, plugins, integrations
  • Any audit finding or deadline driving it