felixfbecker / PSKubectl

kubectl with the power of the object pipeline
MIT License
61 stars 9 forks source link

`Publish-KubeResource ./service.yml` throws resource not found if used with older Kubernetes version that doesn't support server-side-apply yet #49

Open TylerLeonhardt opened 5 years ago

TylerLeonhardt commented 5 years ago

here's my service config:

apiVersion: v1
kind: Service
metadata:
  name: ud-helloworld-service
spec:
  selector:
    app: ud-helloworld
  ports:
    - name: http
      protocol: TCP
      port: 80
      nodePort: 30001
      targetPort: 10001
  type: NodePort

I'm trying to run:

Publish-KubeResource ./service.yml

but get the following error:

Publish-KubeResource : Unable to patch v1/Service resource 'ud-helloworld-service' using server-side apply (resource not found).
At line:1 char:1
+ Publish-KubeResource ./service.yml -Force
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : NotSpecified: (:) [Publish-KubeResource], KubeClientException
+ FullyQualifiedErrorId : KubeClient.KubeClientException,Kubectl.Cmdlets.DeployKubeResourceCmdlet

Here's the stack trace:

$Error[0].Exception.StackTrace
   at KubeClient.ResourceClients.DynamicResourceClient.ApplyYaml(String name, String kind, String apiVersion, String yaml, String fieldManager, Boolean force, String kubeNamespace, CancellationToken cancellationToken)
   at Kubectl.Cmdlets.DeployKubeResourceCmdlet.updateResource(Object resource, String yaml, CancellationToken cancellationToken) in /home/travis/build/felixfbecker/PSKubectl/src/Cmdlets/PublishKubeResourceCmdlet.cs:line 98
   at Kubectl.Cmdlets.DeployKubeResourceCmdlet.ProcessRecordAsync(CancellationToken cancellationToken) in /home/travis/build/felixfbecker/PSKubectl/src/Cmdlets/PublishKubeResourceCmdlet.cs:line 51
   at Kubectl.ThreadAffinitiveSynchronizationContext.RunSynchronized(Func`1 asyncOperation) in /home/travis/build/felixfbecker/PSKubectl/src/ThreadAffinitiveSynchronizationContext.cs:line 174
   at Kubectl.AsyncCmdlet.ProcessRecord() in /home/travis/build/felixfbecker/PSKubectl/src/AsyncCmdlet.cs:line 150
   at System.Management.Automation.Cmdlet.DoProcessRecord()
   at System.Management.Automation.CommandProcessor.ProcessRecord()

I did switch my context recently so maybe that's related... but I also tried with:

kubectl apply -f ./service.yml

and it worked as expected.

let me know if there's any other info I can provide.

felixfbecker commented 5 years ago

Thanks for the report! Does the service exist already and you're trying to update it, or are you trying to create it? What does kubectl version show?

TylerLeonhardt commented 5 years ago

@felixfbecker

The service already existed when I ran it.

kubectl version

Client Version: version.Info{Major:"1", Minor:"14", GitVersion:"v1.14.6", GitCommit:"96fac5cd13a5dc064f7d9f4f23030a6aeface6cc", GitTreeState:"clean", BuildDate:"2019-08-19T11:13:49Z", GoVersion:"go1.12.9", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"14", GitVersion:"v1.14.6", GitCommit:"96fac5cd13a5dc064f7d9f4f23030a6aeface6cc", GitTreeState:"clean", BuildDate:"2019-08-19T11:05:16Z", GoVersion:"go1.12.9", Compiler:"gc", Platform:"linux/amd64"}
felixfbecker commented 5 years ago

Thanks for the info! I wonder if this is caused by server-side apply not being enabled. Did you run the server with --feature-gates=ServerSideApply=true? Does the same happen with 1.16 (where it should be enabled by default)? Could you run the command with -Verbose -LogPayloads and paste the output?

TylerLeonhardt commented 5 years ago

Ah that could be it. I'm just using the Kubernetes runtime that comes with docker for Mac which seems to be 1.14

felixfbecker commented 5 years ago

It is odd though that it reports a 404 (not found), so I'd still be curious to see the -Verbose -LogPayloads output

TylerLeonhardt commented 5 years ago

Publish-KubeResource ./service.yml -Verbose -LogPayloads

VERBOSE: Using endpoint https://kubernetes.docker.internal:6443/
VERBOSE: Reading object from YAML file /Users/tyleonha/Code/Docker/UniversalDashboard/service.yml
VERBOSE: Apply Service "ud-helloworld-service" in namespace ""
VERBOSE: KubeCmdlet: apiVersion v1
VERBOSE: KubeClient.KubeApiClient.Http: Performing PATCH request to 'https://kubernetes.docker.internal:6443/api/v1/services/ud-helloworld-service?fieldManager=kubectl'.
VERBOSE: KubeClient.KubeApiClient.Http: Send request body for PATCH request to 'https://kubernetes.docker.internal:6443/api/v1/services/ud-helloworld-service?fieldManager=kubectl':
apiVersion: v1
kind: Service
metadata:
  name: ud-helloworld-service
spec:
  selector:
    app: ud-helloworld
  ports:
    - name: http
      protocol: TCP
      port: 80
      nodePort: 30001
      targetPort: 10001
  type: NodePort

VERBOSE: KubeClient.KubeApiClient.Http: Receive response body for PATCH request to 'https://kubernetes.docker.internal:6443/api/v1/services/ud-helloworld-service?fieldManager=kubectl' (NotFound):
{"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"the server could not find the requested resource","reason":"NotFound","details":{},"code":404}

VERBOSE: KubeClient.KubeApiClient.Http: Completed PATCH request to 'https://kubernetes.docker.internal:6443/api/v1/services/ud-helloworld-service?fieldManager=kubectl' (NotFound).
Publish-KubeResource : Unable to patch v1/Service resource 'ud-helloworld-service' using server-side apply (resource not found).
At line:1 char:1
+ Publish-KubeResource ./service.yml -Verbose -LogPayloads
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : NotSpecified: (:) [Publish-KubeResource], KubeClientException
+ FullyQualifiedErrorId : KubeClient.KubeClientException,Kubectl.Cmdlets.DeployKubeResourceCmdlet

Also just to prove it does exist:

Get-KubeResource -Kind Service ud-helloworld-service

Spec       : KubeClient.Models.ServiceSpecV1
Status     : KubeClient.Models.ServiceStatusV1
Metadata   : KubeClient.Models.ObjectMetaV1
Kind       : Service
ApiVersion : v1
Name       : ud-helloworld-service
Namespace  : default
Age        : 10.03:42:02.3635020
felixfbecker commented 5 years ago

Interesting, it looks like Kubernetes sends an inappropriate HTTP status code (404) when it doesn't support the Content-Type of the request.

I would guess that kubectl apply with a server-side apply (don't remember the flag for that in v14) would return the same.

felixfbecker commented 5 years ago

If you want to play around with it, you could use minikube:

brew cask install minikube
minikube start