csharp: Connecting to api server fails with HTTP/2 handshake error
Describe the bug I’m getting the following exception while connecting to my K8s cluster:
System.Net.Http.HttpRequestException: 'An HTTP/2 connection could not be established because the server did not complete the HTTP/2 handshake.'
The code:
KubernetesClientConfiguration config = KubernetesClientConfiguration.BuildConfigFromConfigFile(kubeConfFilePath);
Console.WriteLine($"Connecting to {config.CurrentContext}, {config.Host}, {config.Namespace}, {config.Username}");
config.SkipTlsVerify = true; //does not change anything
using (IKubernetes client = new Kubernetes(config))
{
V1NamespaceList namespaces = client.CoreV1.ListNamespace(); //this fails
Whole stacktrace is:
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
at System.Threading.Tasks.TaskCompletionSourceWithCancellation`1.<WaitWithCancellationAsync>d__1.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Threading.Tasks.ValueTask`1.get_Result()
at System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable`1.ConfiguredValueTaskAwaiter.GetResult()
at System.Net.Http.HttpConnectionPool.<GetHttp2ConnectionAsync>d__79.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Threading.Tasks.ValueTask`1.get_Result()
at System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable`1.ConfiguredValueTaskAwaiter.GetResult()
at System.Net.Http.HttpConnectionPool.<SendWithVersionDetectionAndRetryAsync>d__83.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Threading.Tasks.ValueTask`1.get_Result()
at System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable`1.ConfiguredValueTaskAwaiter.GetResult()
at System.Net.Http.RedirectHandler.<SendAsync>d__4.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
at System.Net.Http.HttpClient.<<SendAsync>g__Core|83_0>d.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at k8s.Kubernetes.<SendRequestRaw>d__39.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at k8s.AbstractKubernetes.<k8s-ICoreV1Operations-ListNamespaceWithHttpMessagesAsync>d__21.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at k8s.CoreV1OperationsExtensions.<ListNamespaceAsync>d__15.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at k8s.CoreV1OperationsExtensions.ListNamespace(ICoreV1Operations operations, Nullable`1 allowWatchBookmarks, String continueParameter, String fieldSelector, String labelSelector, Nullable`1 limit, String resourceVersion, String resourceVersionMatch, Nullable`1 timeoutSeconds, Nullable`1 watch, Nullable`1 pretty)
at K8sApiTest.Program.Main(String[] args) in Z:\kube-test\src\K8sApiTest\Program.cs:line 18
Kubernetes C# SDK Client Version
9.0.38
Server Kubernetes Version
1.25.4
Dotnet Runtime Version net6
Expected behavior I expected to be able to connect to the api server
KubeConfig my kubeconf file looks like this:
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: LS0t...
server: https://<some_ip>:6443
name: kubernetes-test
contexts:
- context:
cluster: kubernetes-test
user: kubernetes-test-admin
name: kubernetes-test-admin@kubernetes-test
current-context: kubernetes-test-admin@kubernetes-test
kind: Config
preferences: {}
users:
- name: kubernetes-test-admin
user:
client-certificate-data: LS0...
client-key-data: LS0...
Where do you run your app with Kubernetes SDK (please complete the following information):
- OS: Windows 8.1 Prof
- Environment - just a plain app from MS VS
- Cloud - No
Additional context I doubt that there’s a problem with my kubeconf file, because both Lens and KubeNav have no problems connecting to the API server using the same file.
Here are screenshots from wireshark:
My app with the problem:

Kubenav with no problem:

(black rects mask my machine, green ones mask api server)
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Comments: 22 (10 by maintainers)
long discussion about
keep alivein #533the tcp keep alive is not easy to setup, thus, the sdk prefers https now
good catch will add an option to disable http2 the reason we force http2 is to have the connections
keep alive, otherwise loadbalancers might kick the watch connections.It seems that there’s a specific requirement in rfc7540 that says that in case of HTTP/2 over TLS1.2 there’s a list of additionally forbidden ciphers.
It looks that what I’m facing is that my client and server negotiate a cypher that is OK in general, but is not allowed for HTTP/2. So when client requests an HTTP/2 connection AFTER SSL handshake, api server rejects it because of inappropriate cipher used for the channel.
The part of a problem is that
SslClientAuthenticationOptions.CipherSuitesPolicyis not available on Windows platform so I cannot specify exact ciphers on the client side.So I’ll be checking the –tls-cipher-suites option of api-server, but for now I have no luck finding a proper ciphers subset.
Just for a reference, here’s a win 8.1 ciphers list.
https://kubernetes.io/docs/tasks/debug/debug-cluster/#control-plane-nodes
LMK if it helps, so we can do something to improve sdk’s compatibility