A Kubernetes upgrade is rarely just a matter of changing a version number.
For a production .NET application, the cluster version sits underneath the application runtime, networking, storage, ingress, observability stack, admission controllers, deployment tooling, and platform integrations. A change that looks safe at the cluster level can still expose an incompatibility somewhere in that chain.
Kubernetes 1.34 is particularly relevant for upgrade planning because its current support timeline is approaching a transition point. The official Kubernetes release information lists 1.34.9 as the latest patch release and shows maintenance mode beginning on August 27, 2026, with end of life scheduled for October 27, 2026.
That does not mean every application running Kubernetes 1.34 must immediately upgrade. It does mean platform teams should have a repeatable way to determine whether their .NET workloads are ready for the next supported Kubernetes version.
This article presents a practical upgrade-readiness methodology focused on production .NET applications.
Why Kubernetes Upgrade Testing Matters
A typical .NET application deployed to Kubernetes has more dependencies than its container image suggests.
A simplified architecture might look like this:
Kubernetes Cluster
|
+-------------+-------------+
| |
Control Plane Worker Nodes
| |
| +------+------+
| | |
| .NET API Worker
| | |
+-------------+------+-------------+
|
Ingress / Service
|
Database / Cache
The application itself may not need to change at all during a Kubernetes upgrade.
The surrounding platform can still affect:
Pod scheduling
Container startup
Service discovery
Networking
Readiness and liveness probes
Resource enforcement
Ingress behavior
Storage
Autoscaling
Deployment behavior
Admission policies
The purpose of upgrade testing is therefore to verify the complete application path, not just whether a Pod reaches Running.
Define an Upgrade Readiness Baseline
Before changing anything, record the current environment.
Start with:
kubectl version
kubectl get nodes -o wide
kubectl get pods -A
kubectl get deployments -A
kubectl get statefulsets -A
Also capture important workload configuration:
kubectl get deployment my-api -o yaml
Do not treat the resulting YAML as something to blindly restore later. It is primarily a baseline for understanding what is deployed.
Record:
| Area | Baseline |
|---|---|
| Kubernetes version | Current cluster version |
| .NET runtime | Application runtime |
| Container image | Current application image |
| Node OS | Current node image |
| CPU requests/limits | Current configuration |
| Memory requests/limits | Current configuration |
| Replica count | Current deployment |
| HPA | Current scaling configuration |
| Ingress | Current controller/configuration |
| Storage | PVC/storage configuration |
| Observability | Metrics/logging/tracing |
| Admission policies | Current policies |
This makes comparison much easier after the upgrade.
Check Kubernetes Version Skew
One of the first things to understand is that Kubernetes components do not all have unlimited version compatibility.
The official version-skew policy defines supported relationships between components such as kube-apiserver, kubelet, kube-proxy, controllers, and kubectl. For example, kubelet must not be newer than kube-apiserver, while supported older versions are allowed within documented limits. kubectl is supported within one minor version of the API server.
This matters during rolling upgrades because a cluster is temporarily running mixed component versions.
The upgrade should therefore follow the supported component order rather than upgrading arbitrary components independently.
The Kubernetes project also recommends moving from the latest patch version of the current minor release to the latest patch version of the target minor release when preparing an upgrade.
Test the .NET Application Before the Upgrade
The application should have a known-good baseline before the cluster changes.
For an ASP.NET Core application, verify the health endpoints.
For example:
builder.Services.AddHealthChecks()
.AddCheck("application", () => HealthCheckResult.Healthy());
var app = builder.Build();
app.MapHealthChecks("/health/live");
app.MapHealthChecks("/health/ready");
A production application should distinguish between liveness and readiness when appropriate.
A liveness probe answers:
Is this process alive?
A readiness probe answers:
Can this instance currently receive traffic?
Those questions become especially important during rolling upgrades.
Review Kubernetes Probes
A typical Deployment might define:
apiVersion: apps/v1
kind: Deployment
metadata:
name: orders-api
spec:
replicas: 3
template:
spec:
containers:
- name: orders-api
image: orders-api:1.0
ports:
- containerPort: 8080
startupProbe:
httpGet:
path: /health/live
port: 8080
failureThreshold: 30
periodSeconds: 5
readinessProbe:
httpGet:
path: /health/ready
port: 8080
periodSeconds: 10
livenessProbe:
httpGet:
path: /health/live
port: 8080
periodSeconds: 20
The exact values should be based on application startup and recovery behavior.
Do not copy probe timings from another service simply because they appear to work there.
Test Graceful Shutdown
A Kubernetes upgrade can cause Pods to be terminated and recreated.
The .NET application should handle termination cleanly.
ASP.NET Core applications participate in the host's graceful shutdown process, but your application should still be tested under actual termination conditions.
For example, if the service consumes background work, verify that shutdown does not result in:
Lost messages
Partially completed operations
Duplicate processing
Abandoned database transactions
Unflushed telemetry
A simple application test can terminate a Pod deliberately:
kubectl delete pod <pod-name>
Then observe:
kubectl get pods -w
The goal is not merely to confirm that Kubernetes creates a replacement.
You want to verify that the application exits and recovers correctly.
Validate Resource Requests and Limits
Kubernetes scheduling and resource management are closely connected to application stability.
A .NET deployment should define appropriate resource requests and, where appropriate, limits:
resources:
requests:
cpu: "250m"
memory: "256Mi"
limits:
cpu: "1"
memory: "1Gi"
These numbers are examples, not recommended defaults.
During upgrade testing, compare actual utilization against configured resources.
Useful commands include:
kubectl top pods
kubectl top nodes
Look for:
CPU throttling
Memory pressure
OOM kills
Pods becoming unschedulable
Node capacity changes
Unexpected changes in application latency
A Kubernetes upgrade should not be considered successful if the cluster is technically healthy but the application has degraded resource behavior.
Test Autoscaling
If the .NET application uses an HPA, test scaling before and after the upgrade.
Inspect the configuration:
kubectl get hpa orders-api
kubectl describe hpa orders-api
A typical HPA might look like:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: orders-api
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: orders-api
minReplicas: 3
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
Run a controlled load test and verify:
Traffic increases
|
v
CPU increases
|
v
HPA detects utilization
|
v
Replica count increases
|
v
Traffic is distributed
The important measurement is not simply whether replicas increase.
Check whether scaling happens quickly enough for the application's traffic profile and whether newly created Pods become ready successfully.
Validate Service and Ingress Networking
A .NET API can be healthy while external traffic is broken.
Test the entire path:
Client
|
v
Load Balancer
|
v
Ingress
|
v
Service
|
v
Pod
|
v
ASP.NET Core
Validate:
kubectl get ingress
kubectl get svc
kubectl get endpoints
Then perform real HTTP requests.
For example:
curl -i https://api.example.com/health/ready
Test both normal traffic and failure scenarios.
Terminate one Pod while sending requests and verify that traffic continues through the remaining replicas.
Test Database Connectivity
Many .NET applications depend on PostgreSQL, SQL Server, Redis, or another external service.
Kubernetes upgrades should not be tested with only an application health endpoint.
A health check that says "process is alive" does not prove that database operations are working.
For a controlled integration test:
builder.Services.AddHealthChecks()
.AddDbContextCheck<AppDbContext>();
Be careful with dependency-heavy readiness checks. If the database is temporarily unavailable, you want Kubernetes to stop sending traffic to an unhealthy instance, but you also do not want an unhealthy dependency to create an uncontrolled cascading restart loop.
The appropriate behavior depends on the application architecture.
Test Deployment Behavior
Perform a normal rolling deployment before and after the cluster upgrade.
Inspect the Deployment:
kubectl rollout status deployment/orders-api
Then verify:
kubectl get pods
kubectl get rs
kubectl describe deployment orders-api
A successful rollout should preserve the application's availability expectations.
Test:
Rolling updates
Rollback
Pod replacement
Readiness transitions
Replica availability
Configuration changes
Secret changes
Image pull behavior
Rollback should be tested deliberately, not assumed.
kubectl rollout undo deployment/orders-api
Test Disruption Scenarios
Upgrade readiness is more meaningful when the application is tested under controlled failure.
Useful scenarios include:
| Scenario | What to Verify |
|---|---|
| Delete one Pod | Traffic continues |
| Restart a node | Workloads reschedule |
| Increase traffic | HPA responds |
| Database temporarily unavailable | Correct application behavior |
| Ingress restart | Traffic recovers |
| Rolling deployment | Availability maintained |
| Pod startup delay | Probes behave correctly |
| Application crash | Replacement Pod becomes ready |
Do not run destructive tests against production unless they are part of an approved resilience program.
Use a staging or dedicated upgrade environment wherever possible.
Compare Application Metrics
Before and after the upgrade, compare application-level telemetry.
Useful metrics include:
Request rate
Error rate
p50 latency
p95 latency
p99 latency
Pod restart count
CPU usage
Memory usage
HPA replica count
Startup time
Readiness failures
For an ASP.NET Core API, OpenTelemetry or another observability system can provide the application-side view while Kubernetes metrics provide the platform-side view.
The objective is to correlate changes.
For example:
Kubernetes Upgrade
|
v
Pod startup time increases
|
v
Readiness delayed
|
v
Available replicas decrease
|
v
Request latency increases
That tells a much more useful story than simply reporting that "the upgrade caused higher latency."
Build a Production Readiness Matrix
Before approving the upgrade, create a simple readiness matrix.
| Test | Expected Result | Actual Result | Status |
|---|---|---|---|
| Application startup | Successful | Record result | Pass/Fail |
| Readiness probe | Healthy | Record result | Pass/Fail |
| Liveness probe | Healthy | Record result | Pass/Fail |
| Rolling deployment | No unacceptable outage | Record result | Pass/Fail |
| Rollback | Successful | Record result | Pass/Fail |
| HPA | Scales correctly | Record result | Pass/Fail |
| Service networking | Healthy | Record result | Pass/Fail |
| Ingress | Healthy | Record result | Pass/Fail |
| Database access | Healthy | Record result | Pass/Fail |
| Pod disruption | Recovers | Record result | Pass/Fail |
| Resource usage | Within limits | Record result | Pass/Fail |
| Application latency | Within baseline | Record result | Pass/Fail |
This creates an auditable decision instead of relying on a manual "looks good" assessment.
Common Upgrade Mistakes
Testing Only kubectl get pods
A Running Pod does not prove that the application is serving correct traffic.
Skipping Version-Skew Checks
Mixed-version components during upgrades must remain within Kubernetes' supported skew rules.
Testing Without Production-Like Load
A cluster can appear healthy at idle while showing latency or autoscaling problems under realistic traffic.
Ignoring Admission Controllers
Admission policies, webhooks, and security controls can affect workload creation during an upgrade.
Test actual deployment operations rather than only existing Pods.
Forgetting Rollback
A successful forward upgrade is only half the operational story.
Verify that the team can recover if a problem appears after the upgrade.
Changing Application Code at the Same Time
If possible, do not combine a Kubernetes upgrade with unrelated application, runtime, database, or infrastructure changes.
Fewer variables make failures easier to diagnose.
Troubleshooting Failed Upgrade Tests
When something fails, first determine which layer changed.
Use this model:
Application
|
ASP.NET Core
|
Container
|
Pod
|
Service
|
Node
|
Kubernetes Control Plane
For application failures, inspect:
kubectl logs deployment/orders-api
For Pod-level issues:
kubectl describe pod <pod-name>
For scheduling problems:
kubectl describe node <node-name>
For Deployment behavior:
kubectl describe deployment orders-api
For cluster-wide events:
kubectl get events --sort-by=.lastTimestamp
Do not immediately roll back because a single test failed. First determine whether the failure is deterministic, environment-specific, or unrelated to the upgrade.
Kubernetes 1.34 Upgrade Timing
Kubernetes' official release schedule currently lists 1.34.9 as the latest patch release and October 27, 2026 as its end-of-life date. The branch enters maintenance mode on August 27, 2026.
That creates a useful planning window for teams still running 1.34.
The correct response is not to rush an untested upgrade simply because a date is approaching. Instead:
Inventory affected clusters.
Identify workloads still running 1.34.
Establish a baseline.
Test the target Kubernetes version.
Run application and infrastructure validation.
Perform a controlled rollout.
Monitor the upgraded environment.
Keep a tested rollback path.
The exact target version should be selected according to the organization's support policy and the Kubernetes versions supported by its managed Kubernetes provider or platform.
Frequently Asked Questions
Does a Kubernetes upgrade require changes to a .NET application?
Not necessarily. Many applications can run without code changes, but application behavior should still be validated because the surrounding platform can affect networking, scheduling, probes, resources, and deployment behavior.
Is a Pod being Running enough to declare the upgrade successful?
No. Running only describes one part of Pod state. Application readiness, traffic handling, dependencies, scaling, latency, and recovery should also be tested.
Should the .NET runtime be upgraded at the same time?
Preferably not unless there is a specific reason to combine the changes. Separating infrastructure and application-runtime upgrades makes troubleshooting easier.
How much load should be used during testing?
Use a workload representative of the application's expected production behavior. A single universal load level would not be appropriate for every service.
Should upgrade testing happen in production?
Use a dedicated or staging environment that closely resembles production whenever possible. Production testing should follow an approved operational and resilience-testing process.
Best Practices Checklist
Record the current Kubernetes and application baseline.
Verify Kubernetes version-skew requirements.
Use the latest supported patch releases appropriate to the upgrade path.
Test .NET startup and shutdown behavior.
Validate readiness and liveness probes.
Test Service and Ingress traffic.
Test database and external-service connectivity.
Exercise HPA behavior under representative load.
Test rolling deployments and rollback.
Run controlled disruption scenarios.
Compare application latency and error metrics.
Document every failed test and its remediation.
Keep application and infrastructure changes separated when practical.
Maintain a tested rollback procedure.
Conclusion
Kubernetes upgrade readiness is ultimately an application-platform compatibility problem, not simply a cluster-version problem.
For .NET applications, the most valuable testing covers the complete path from container startup to readiness, service discovery, ingress, database connectivity, autoscaling, deployment, observability, and recovery.
Kubernetes 1.34's approaching maintenance and end-of-life milestones make upgrade planning particularly relevant right now. The official Kubernetes documentation should remain the source of truth for supported versions, patch releases, and version-skew rules.
A good upgrade is not one where the control plane reports healthy. It is one where the application continues to meet its operational requirements before, during, and after the platform change.
The safest approach is therefore straightforward: establish a baseline, test the real workload, measure the important behaviors, document the results, and only then approve the production rollout.

Join the conversation! Your thoughts help the community grow.