Introduction
Kubernetes upgrades are rarely difficult because of the version change alone. The real challenge is discovering what the application, container image, deployment manifests, admission controllers, observability stack, and infrastructure integrations expect from the cluster.
For .NET applications, an upgrade should therefore be treated as a compatibility exercise, not simply a control-plane operation.
Kubernetes 1.34 was released in August 2025 and introduced 58 enhancements across stable, beta, and alpha stages. The 1.34 release series is scheduled to enter maintenance mode on August 27, 2026, with end of life on October 27, 2026.
That makes compatibility testing especially relevant for teams still running applications on Kubernetes 1.33 or earlier and planning their upgrade path.
The key question is not:
"Will my .NET container start on Kubernetes 1.34?"
It is:
"Will my complete .NET workload behave correctly after the cluster upgrade?"
This article presents a practical compatibility-testing strategy for .NET applications before moving to Kubernetes 1.34.
What Can Break During a Kubernetes Upgrade?
A .NET application does not communicate only with Kubernetes itself.
A typical production deployment looks more like this:
Kubernetes Cluster
|
+----------------+----------------+
| | |
Ingress Service Config
| | |
+----------------+----------------+
|
Pod
|
ASP.NET Core
|
+------------+------------+
| | |
.NET SDK Secrets ConfigMap
|
Container
Compatibility problems can therefore appear in several places:
The application may compile successfully and still fail after deployment.
Start With the Current Cluster Inventory
Before testing Kubernetes 1.34, document the current environment.
For example:
kubectl version
kubectl get nodes -o wide
kubectl get pods -A
kubectl get crd
kubectl get validatingwebhookconfigurations
kubectl get mutatingwebhookconfigurations
Also inspect the workloads:
kubectl get deployments -A
kubectl get statefulsets -A
kubectl get daemonsets -A
For a .NET application, record at least:
| Component | Current Value |
|---|
| Kubernetes version | Current production version |
| .NET runtime | 8/9/10/etc. |
| Container base image | Linux distribution + version |
| CPU request | Application-specific |
| Memory request | Application-specific |
| CPU limit | Application-specific |
| Memory limit | Application-specific |
| Ingress controller | Current version |
| CSI driver | Current version |
| Observability agent | Current version |
| Helm chart | Current version |
This inventory becomes the baseline for the compatibility test.
Understand Kubernetes Version Skew
Kubernetes does not require every component to change simultaneously.
The Kubernetes version-skew policy defines supported relationships between components. For example, kubelet must not be newer than kube-apiserver, while it can be several minor versions older within the documented limits. kubectl is supported within one minor version of the API server.
For an upgrade from Kubernetes 1.33 to 1.34, this means you should test the upgrade order rather than independently upgrading random components.
A simplified sequence is:
Current Cluster
|
v
Upgrade Control Plane
|
v
Validate API + Controllers
|
v
Upgrade Worker Nodes
|
v
Validate .NET Workloads
|
v
Production
The exact procedure depends on how the cluster is managed.
Build a Kubernetes 1.34 Test Environment
The safest approach is to create a representative non-production environment.
It should resemble production in the areas that affect application behavior:
Production
|
+-- .NET version
+-- Container image
+-- Kubernetes manifests
+-- Ingress
+-- Secrets
+-- ConfigMaps
+-- Storage
+-- Network policies
+-- Observability
+-- Autoscaling
Avoid creating a test cluster that contains only the basic Deployment and Service.
That may prove that the container starts, but it does not provide meaningful compatibility evidence.
Test the .NET Container Independently
Before testing Kubernetes behavior, verify the application image itself.
A simple Dockerfile might look like:
FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS base
WORKDIR /app
EXPOSE 8080
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
WORKDIR /src
COPY ["MyApi/MyApi.csproj", "MyApi/"]
RUN dotnet restore "MyApi/MyApi.csproj"
COPY . .
WORKDIR "/src/MyApi"
RUN dotnet publish \
"MyApi.csproj" \
-c Release \
-o /app/publish \
/p:UseAppHost=false
FROM base AS final
WORKDIR /app
COPY --from=build /app/publish .
ENTRYPOINT ["dotnet", "MyApi.dll"]
Test the image outside Kubernetes:
docker build -t myapi:test .
docker run --rm -p 8080:8080 myapi:test
Then verify:
curl http://localhost:8080/health
This separates container problems from Kubernetes problems.
Test the Kubernetes Deployment
A basic ASP.NET Core deployment could look like:
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapi
spec:
replicas: 3
selector:
matchLabels:
app: myapi
template:
metadata:
labels:
app: myapi
spec:
containers:
- name: myapi
image: myapi:test
ports:
- containerPort: 8080
resources:
requests:
cpu: "250m"
memory: "256Mi"
limits:
cpu: "1"
memory: "512Mi"
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 15
periodSeconds: 20
Apply it to the test cluster:
kubectl apply -f deployment.yaml
Then inspect:
kubectl get pods
kubectl describe pod <pod-name>
kubectl logs <pod-name>
The important point is to test the application exactly as production deploys it.
Validate Kubernetes API Usage
One of the most important upgrade checks is API compatibility.
Search deployment repositories for:
apiVersion:
For example:
apiVersion: apps/v1
kind: Deployment
Review:
Deployment
StatefulSet
DaemonSet
Ingress
CronJob
Role
RoleBinding
NetworkPolicy
PodDisruptionBudget
Custom resources
A .NET application may not directly use these APIs from C#, but its deployment infrastructure certainly does.
An API removal can therefore break deployment without changing a single line of C#.
Test Ingress Behavior
ASP.NET Core applications commonly sit behind an ingress layer.
Test:
Client
|
v
Ingress
|
v
Service
|
v
ASP.NET Core Pod
Validate:
HTTP routing
HTTPS termination
TLS certificates
Path rewriting
Headers
WebSocket connections
Request body limits
Timeouts
Client IP forwarding
For applications using authentication, specifically test:
Authorization header
Cookie
X-Forwarded-For
X-Forwarded-Proto
Host
A cluster upgrade can expose assumptions in proxy configuration that were not visible during normal application testing.
Validate ASP.NET Core Forwarded Headers
If your application relies on forwarded headers, make sure the configuration is explicitly tested.
For example:
using Microsoft.AspNetCore.HttpOverrides;
var builder = WebApplication.CreateBuilder(args);
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders =
ForwardedHeaders.XForwardedFor |
ForwardedHeaders.XForwardedProto;
});
var app = builder.Build();
app.UseForwardedHeaders();
app.UseHttpsRedirection();
app.MapControllers();
app.Run();
This matters when application behavior depends on whether the original request was HTTP or HTTPS.
Authentication redirects, generated URLs, logging, and security policies can all be affected.
Test Health Probes
Health checks are especially important during node and pod transitions.
A basic ASP.NET Core setup might expose:
app.MapHealthChecks("/health/live");
app.MapHealthChecks("/health/ready");
Treat the two endpoints differently.
Liveness
Liveness should answer:
Is this process fundamentally alive?
Readiness
Readiness should answer:
Can this instance currently receive application traffic?
A readiness check might include dependencies such as a database or message broker, while liveness generally should not fail merely because an external dependency is temporarily unavailable.
This distinction becomes important during rolling upgrades.
Test Rolling Deployments
Run an actual rolling deployment in the Kubernetes 1.34 environment.
For example:
kubectl rollout status deployment/myapi
Then monitor:
kubectl get pods -w
Validate that:
Old Pod
|
v
Traffic continues
|
v
New Pod becomes Ready
|
v
Traffic moves
|
v
Old Pod terminates
The test should verify that there is no unacceptable interruption.
Test Resource Behavior
Kubernetes upgrades can expose resource assumptions.
For a .NET application, test:
Inspect resource behavior with:
kubectl top pods
kubectl top nodes
Do not rely only on whether the application remains "Running."
A pod can be technically healthy while experiencing severe CPU throttling or memory pressure.
Test Autoscaling
If the application uses Horizontal Pod Autoscaling, reproduce a realistic workload.
For example:
kubectl get hpa
Then generate controlled traffic and observe:
Traffic
|
v
CPU / Memory / Custom Metric
|
v
HPA
|
v
Replica Count
Measure:
The application startup path matters because a slow .NET container can create a larger gap between scaling decisions and usable capacity.
Test Graceful Shutdown
Rolling upgrades depend on applications shutting down correctly.
ASP.NET Core supports graceful application shutdown, but your application code should also handle cancellation appropriately.
For example:
public sealed class Worker(
ILogger<Worker> logger) : BackgroundService
{
protected override async Task ExecuteAsync(
CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
await ProcessWorkAsync(stoppingToken);
await Task.Delay(
TimeSpan.FromSeconds(5),
stoppingToken);
}
}
}
The cancellation token should flow into long-running operations.
This becomes particularly important for:
Background workers
Queue consumers
Message processors
Scheduled jobs
Long-running HTTP calls
Test Persistent Storage
If your .NET application uses persistent volumes, include storage in the compatibility test.
Validate:
Pod
|
v
PVC
|
v
Storage Driver
|
v
Storage Backend
Test:
Do not treat storage as compatible merely because the PVC object still exists.
Test Observability
A Kubernetes upgrade can affect monitoring and logging even when the application works perfectly.
For a .NET application, validate:
Application logs
Structured logging
Metrics
Distributed tracing
OpenTelemetry exporters
Container metadata
Pod metadata
Node metadata
For example:
ASP.NET Core
|
+--> Logs
|
+--> Metrics
|
+--> Traces
|
v
Observability Stack
Confirm that telemetry still contains the identifiers your operations team relies on.
Test Security Contexts
Check workloads that use:
securityContext:
runAsNonRoot: true
allowPrivilegeEscalation: false
Also test:
A .NET application that writes temporary files to an unexpected filesystem location may behave differently when security restrictions are enforced.
Run Application-Level Regression Tests
Infrastructure compatibility is not enough.
Run the application's normal test suite:
dotnet test
Then run integration tests against the Kubernetes 1.34 environment.
For example:
Authentication
|
v
API Request
|
v
ASP.NET Core
|
+--> Database
|
+--> Cache
|
+--> Message Broker
Test the complete path.
Include:
Authentication
Authorization
CRUD operations
Database access
Cache access
Messaging
File operations
Background jobs
External APIs
Error handling
Benchmark Before and After the Upgrade
Compatibility testing should include performance measurements.
Record a baseline from the current cluster:
| Metric | Current Cluster | Kubernetes 1.34 |
|---|
| P50 latency | Baseline | Measure |
| P95 latency | Baseline | Measure |
| P99 latency | Baseline | Measure |
| Requests/sec | Baseline | Measure |
| CPU/request | Baseline | Measure |
| Memory/request | Baseline | Measure |
| Error rate | Baseline | Measure |
| Startup time | Baseline | Measure |
Do not declare compatibility solely because functional tests pass.
A workload that passes functional tests but has significantly worse P95 latency still needs investigation.
Test Failure Scenarios
A useful upgrade test intentionally creates failures.
For example:
Kill Pod
|
v
Does traffic continue?
Then:
Restart Node
|
v
Does workload recover?
And:
Database unavailable
|
v
Does readiness behave correctly?
Also test:
These tests reveal whether the application and Kubernetes configuration fail safely.
Validate Deployment Automation
The final test should include the actual deployment pipeline.
For example:
Git Commit
|
v
Build
|
v
Unit Tests
|
v
Container Build
|
v
Security Scan
|
v
Deploy to Kubernetes 1.34
|
v
Integration Tests
|
v
Smoke Tests
Do not manually deploy the application to the test cluster and consider the migration validated.
The deployment automation itself must be tested.
Build a Compatibility Matrix
A useful migration artifact is a compatibility matrix.
| Area | Test | Result | Risk |
|---|
| Container | Image starts | Pass | Low |
| Deployment | Pod rollout | Pass | Low |
| Ingress | HTTPS routing | Pass | Medium |
| Probes | Readiness/liveness | Pass | Low |
| HPA | Scaling | Pass | Medium |
| Storage | PVC operations | Pass | High |
| Messaging | Queue processing | Pass | Medium |
| Observability | Traces/logs | Pass | Medium |
| Security | Non-root execution | Pass | Low |
| Performance | P95 latency | Pass | Medium |
This gives the upgrade team something more useful than a generic statement that "testing passed."
Common Mistakes
Testing Only Pod Startup
A running container does not prove application compatibility.
Testing Only the .NET Application
Kubernetes manifests, ingress, storage, networking, and observability also need testing.
Ignoring Admission Webhooks
Admission components can affect whether workloads are accepted and how resources are mutated.
Skipping Performance Tests
Functional compatibility does not guarantee performance compatibility.
Testing Only Happy Paths
Upgrade testing should include node failure, pod termination, dependency failures, and rolling deployments.
Using a Different Container Image
If production uses a specific .NET runtime and base image, test that same image.
Ignoring CI/CD
A successful manual deployment does not validate the actual production deployment process.
Best Practices
Inventory the complete production workload before upgrading.
Test the exact .NET container image used in production.
Use a Kubernetes 1.34 environment that resembles production.
Review Kubernetes API versions in manifests and Helm charts.
Test ingress, services, probes, autoscaling, and storage.
Validate .NET graceful shutdown behavior.
Run application integration and regression tests.
Test observability pipelines, not just application functionality.
Include security-context and admission-policy testing.
Measure P50, P95, and P99 latency before and after the upgrade.
Test failure and recovery scenarios.
Run the real CI/CD deployment pipeline against the test cluster.
Document compatibility results in a migration matrix.
Upgrade to the latest patch release of the target minor version rather than testing against an arbitrary early patch.
The Kubernetes project itself recommends ensuring components are on the latest patch of the current minor version before upgrading, and then moving to the latest patch of the target minor version.
A Practical Pre-Upgrade Checklist
Before approving the production migration, verify:
[ ] Current cluster inventory completed
[ ] Kubernetes APIs reviewed
[ ] .NET container image tested
[ ] Deployment manifests validated
[ ] Ingress tested
[ ] Health probes tested
[ ] Rolling deployment tested
[ ] Graceful shutdown tested
[ ] HPA tested
[ ] Storage tested
[ ] Network policies tested
[ ] Secrets/configuration tested
[ ] Observability validated
[ ] Security context validated
[ ] Integration tests passed
[ ] Failure scenarios tested
[ ] Performance baseline compared
[ ] CI/CD pipeline tested
[ ] Rollback procedure tested
A rollback test is particularly important. The team should know not only how to upgrade, but also how to recover if the upgraded environment produces unacceptable behavior.
Frequently Asked Questions
Does Kubernetes 1.34 require .NET application code changes?
Not necessarily. Many .NET applications can continue running without source-code changes, but compatibility depends on the application's Kubernetes integrations, container image, deployment configuration, and surrounding infrastructure.
Should I upgrade .NET and Kubernetes at the same time?
For an infrastructure compatibility test, changing both simultaneously makes troubleshooting harder. Unless there is a specific reason to combine the upgrades, isolate variables where practical.
What should be tested first?
Start with container and deployment compatibility, then validate ingress, probes, scaling, dependencies, observability, security, and performance.
Is a successful kubectl apply enough?
No. A successful deployment only proves that Kubernetes accepted the resource definitions. It does not prove that the application behaves correctly.
Should performance testing be part of the upgrade?
Yes. At minimum, compare application latency, throughput, resource consumption, startup time, and error rates before and after the upgrade.
Is Kubernetes 1.34 still supported?
As of August 19, 2026, Kubernetes 1.34 remains actively supported. Its maintenance mode is scheduled to begin on August 27, 2026, and its end-of-life date is October 27, 2026.
Conclusion
A Kubernetes upgrade should be treated as a compatibility and reliability exercise rather than a simple infrastructure change.
For .NET applications, the most important validation happens across the boundary between the application and the platform: container startup, health probes, graceful shutdown, networking, ingress, storage, autoscaling, security policies, observability, and deployment automation.
Kubernetes 1.34 introduced substantial platform changes and remains supported until October 27, 2026, making a structured migration plan particularly important for teams approaching the end of its support window.
The safest approach is straightforward:
Build a representative Kubernetes 1.34 environment, deploy the real .NET workload, run functional and failure tests, compare performance with the existing cluster, and validate the complete CI/CD path before production migration.
That turns a Kubernetes upgrade from a high-risk event into a measurable engineering exercise.