K8s中Bitnami Jenkins Agent执行任务时WebSocket 403错误排查求助
我在Kubernetes上运行Bitnami Jenkins Pod,Agent已成功调度至同一Namespace。任务执行时Git代码拉取正常,Pod启动后,在Jenkins构建阶段出现如下异常:
commit message: "Update deployment.yaml" > git rev-list --no-walk ffba5471c965178f7f2f036076239ad1df692475 # timeout=10 [Pipeline] sh + git rev-parse ffba5471c965178f7f2f036076239ad1df692475~ [Pipeline] stage [Pipeline] { (Prepare) [Pipeline] container [Pipeline] { [Pipeline] sh io.fabric8.kubernetes.client.http.WebSocketHandshakeException at io.fabric8.kubernetes.client.okhttp.OkHttpWebSocketImpl$1.onFailure(OkHttpWebSocketImpl.java:83) at okhttp3.internal.ws.RealWebSocket.failWebSocket(RealWebSocket.kt:592) at okhttp3.internal.ws.RealWebSocket$connect$1.onResponse(RealWebSocket.kt:174) at okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:519) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) at java.base/java.lang.Thread.run(Thread.java:829) Caused by: java.net.ProtocolException: Expected HTTP 101 response but was '403 Forbidden' at okhttp3.internal.ws.RealWebSocket.checkUpgradeSuccess$okhttp(RealWebSocket.kt:224) at okhttp3.internal.ws.RealWebSocket$connect$1.onResponse(RealWebSocket.kt:170) ... 4 more Failed to start websocket connection: io.fabric8.kubernetes.client.KubernetesClientException: An error has occurred. at io.fabric8.kubernetes.client.KubernetesClientException.launderThrowable(KubernetesClientException.java:129) at io.fabric8.kubernetes.client.KubernetesClientException.launderThrowable(KubernetesClientException.java:122) at io.fabric8.kubernetes.client.utils.Utils.waitUntilReady(Utils.java:174) at io.fabric8.kubernetes.client.utils.Utils.waitUntilReadyOrFail(Utils.java:184) at io.fabric8.kubernetes.client.dsl.internal.core.v1.PodOperationsImpl.setupConnectionToPod(PodOperationsImpl.java:365) at io.fabric8.kubernetes.client.dsl.internal.core.v1.PodOperationsImpl.exec(PodOperationsImpl.java:286) at org.csanchez.jenkins.plugins.kubernetes.pipeline.ContainerExecDecorator$1.doLaunch(ContainerExecDecorator.java:448) at org.csanchez.jenkins.plugins.kubernetes.pipeline.ContainerExecDecorator$1.launch(ContainerExecDecorator.java:335) at hudson.Launcher$ProcStarter.start(Launcher.java:509) at org.jenkinsci.plugins.durabletask.BourneShellScript.launchWithCookie(BourneShellScript.java:176) at org.jenkinsci.plugins.durabletask.FileMonitoringTask.launch(FileMonitoringTask.java:132) at org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep$Execution.start(DurableTaskStep.java:326) at org.jenkinsci.plugins.workflow.cps.DSL.invokeStep(DSL.java:322) at org.jenkinsci.plugins.workflow.cps.DSL.invokeMethod(DSL.java:196) at org.jenkinsci.plugins.workflow.cps.CpsScript.invokeMethod(CpsScript.java:124) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:566) at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:98) at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325) at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1225) at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1034) at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:41) at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116) at org.kohsuke.groovy.sandbox.impl.Checker$1.call(Checker.java:180) at org.kohsuke.groovy.sandbox.GroovyInterceptor.onMethodCall(GroovyInterceptor.java:23) at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onMethodCall(SandboxInterceptor.java:163) at org.kohsuke.groovy.sandbox.impl.Checker$1.call(Checker.java:178) at org.kohsuke.groovy.sandbox.impl.Checker.checkedCall(Checker.java:182) at org.kohsuke.groovy.sandbox.impl.Checker.checkedCall(Checker.java:152) at org.kohsuke.groovy.sandbox.impl.Checker.checkedCall(Checker.java:152) at org.kohsuke.groovy.sandbox.impl.Checker.checkedCall(Checker.java:152) at org.kohsuke.groovy.sandbox.impl.Checker.checkedCall(Checker.java:152) at com.cloudbees.groovy.cps.sandbox.SandboxInvoker.methodCall(SandboxInvoker.java:17) at com.cloudbees.groovy.cps.impl.ContinuationGroup.methodCall(ContinuationGroup.java:90) at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.dispatchOrArg(FunctionCallBlock.java:116) at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.fixArg(FunctionCallBlock.java:85) at jdk.internal.reflect.GeneratedMethodAccessor586.invoke(Unknown Source) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:566) at com.cloudbees.groovy.cps.impl.ContinuationPtr$ContinuationImpl.receive(ContinuationPtr.java:72) at com.cloudbees.groovy.cps.impl.ConstantBlock.eval(ConstantBlock.java:21) at com.cloudbees.groovy.cps.Next.step(Next.java:83) at com.cloudbees.groovy.cps.Continuable$1.call(Continuable.java:152) at com.cloudbees.groovy.cps.Continuable$1.call(Continuable.java:146) at org.codehaus.groovy.runtime.GroovyCategorySupport$ThreadCategoryInfo.use(GroovyCategorySupport.java:136) at org.codehaus.groovy.runtime.GroovyCategorySupport.use(GroovyCategorySupport.java:275) at com.cloudbees.groovy.cps.Continuable.run0(Continuable.java:146) at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.access$001(SandboxContinuable.java:18) at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.run0(SandboxContinuable.java:51) at org.jenkinsci.plugins.workflow.cps.CpsThread.runNextChunk(CpsThread.java:187) at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.run(CpsThreadGroup.java:420) at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:330) at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:294) at org.jenkinsci.plugins.workflow.cps.CpsVmExecutorService$2.call(CpsVmExecutorService.java:67) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) at hudson.remoting.SingleLaneExecutorService$1.run(SingleLaneExecutorService.java:139) at jenkins.util.ContextResettingExecutorService$1.run(ContextResettingExecutorService.java:28) at jenkins.security.ImpersonatingExecutorService$1.run(ImpersonatingExecutorService.java:68) at jenkins.util.ErrorLoggingExecutorService.lambda$wrap$0(ErrorLoggingExecutorService.java:51) at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) at java.base/java.lang.Thread.run(Thread.java:829) Caused by: io.fabric8.kubernetes.client.http.WebSocketHandshakeException at io.fabric8.kubernetes.client.okhttp.OkHttpWebSocketImpl$1.onFailure(OkHttpWebSocketImpl.java:83) at okhttp3.internal.ws.RealWebSocket.failWebSocket(RealWebSocket.kt:592) at okhttp3.internal.ws.RealWebSocket$connect$1.onResponse(RealWebSocket.kt:174) at okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:519) ... 3 more Suppressed: java.lang.Throwable: waiting here
核心错误:Expected HTTP 101 response but was '403 Forbidden'
目前已确认Pod、Jenkins服务及Git均正常,以下是调试排查建议:
检查Jenkins ServiceAccount权限:Jenkins主Pod使用的ServiceAccount需要具备对Agent Pod的
exec权限,确认对应的Role/RoleBinding是否包含pods/exec资源的操作权限。执行命令查看:kubectl describe role <jenkins-role> -n <your-namespace>确保规则中包含verbs为
create、get、list、watch、exec的配置。验证Kubernetes API Server的WebSocket配置:部分集群的反向代理或Ingress可能拦截WebSocket请求,若使用Nginx Ingress,确认配置中是否添加了:
proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade";检查Agent Pod的网络策略:如果集群启用了NetworkPolicy,确保Jenkins主Pod所在的Pod可以和Agent Pod建立WebSocket连接,NetworkPolicy需允许TCP流量到Agent Pod的相关端口,以及WebSocket升级请求。
查看Jenkins Kubernetes插件配置:在Jenkins系统配置中,确认插件是否正确配置Kubernetes API地址,是否使用了正确的ServiceAccount令牌,尝试测试集群连接,查看是否有明确的权限错误提示。
手动测试Pod exec连接:进入Jenkins主Pod内部,执行命令测试连接Agent Pod:
kubectl exec -it <agent-pod-name> -n <your-namespace> -- /bin/sh若连接失败,会返回更具体的权限错误,帮助定位问题根源。
调整Bitnami Jenkins默认权限:Bitnami Jenkins部署时默认ServiceAccount权限可能不足,需手动添加
pods/exec权限,可通过更新RoleBinding来补充相关规则。
内容的提问来源于stack exchange,提问作者Fabiansc

