Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

kubectl update -f not very usable #10202

Closed
j3ffml opened this issue Jun 22, 2015 · 22 comments
Closed

kubectl update -f not very usable #10202

j3ffml opened this issue Jun 22, 2015 · 22 comments
Assignees
Labels
area/kubectl priority/important-soon Must be staffed and worked on either currently, or very soon, ideally in time for the next release. sig/api-machinery Categorizes an issue or PR as relevant to SIG API Machinery.
Milestone

Comments

@j3ffml
Copy link
Contributor

j3ffml commented Jun 22, 2015

$ kubectl stop   -f examples/guestbook-go/redis-master-service.json
services/redis-master
$ kubectl create -f examples/guestbook-go/redis-master-service.json
services/redis-master
$ kubectl update -f examples/guestbook-go/redis-master-service.json
Error from server: service "redis-master" is invalid: spec.clusterIP: invalid value '': field is immutable

Instead of ignoring absent omitempty values from the spec, it appears to be providing a "default" value.

@j3ffml j3ffml added area/kubectl sig/api-machinery Categorizes an issue or PR as relevant to SIG API Machinery. labels Jun 22, 2015
@j3ffml j3ffml added this to the v1.0-candidate milestone Jun 22, 2015
@mikedanese
Copy link
Member

This is the correct semantic of a PUT according to our api-convention. https://github.com/GoogleCloudPlatform/kubernetes/blob/master/docs/api-conventions.md#verbs-on-resources. PUT is meant to be a replace all with the provided object including setting unprovided fields to default values. Other than status, PUT expects the whole object to be specified. The alternative is for update to use PATCH by default. It would also be a more consistent kubectl experience if patch was a bool flag rather than a string flag and the patch was passed in by file or stdin. Semi related issue: #3112
cc @bgrant0607

@j3ffml
Copy link
Contributor Author

j3ffml commented Jun 22, 2015

Making patch a bool flag would make sense to me. That way the command from above

kubectl update --patch -f examples/guestbook-go/redis-master-service.json

Would work (no-op) as expected. I would vote yes on making --patch the default in that case as well.

@bgrant0607
Copy link
Member

In order to use update, one either needs to use patch or get, modify, update.

Declarative update from config is #1702. It's trickier than one might think, and just patching the provided config won't have the desired behavior, either. I'd love for someone to work on it, but it's late in the game.

@bgrant0607 bgrant0607 modified the milestones: v1.0-post, v1.0-candidate Jun 23, 2015
@bgrant0607 bgrant0607 added the priority/important-soon Must be staffed and worked on either currently, or very soon, ideally in time for the next release. label Jun 23, 2015
@mikedanese
Copy link
Member

What about patch being passed with -f for kubectl consistency? That's an easy change. If it makes sense, it might be worth getting into v1.

@bgrant0607
Copy link
Member

@mikedanese Yes, I like that.

@bgrant0607 bgrant0607 modified the milestones: v1.0, v1.0-post Jun 23, 2015
@bgrant0607
Copy link
Member

We could also do something similar to what we've discussed doing with mirror pods: delete and re-create if the config changes #8683. I'd like to share the implementation if at all possible. This behavior could be flag-controlled in kubectl.

@caesarxuchao
Copy link
Member

Based on in-person discussion with @bgrant0607, here are what we decide to do:

  1. Add a --force flag to kubectl update. When this flag is set, kubectl update will delete and re-create the object.
  2. Modify the documentation, make it clear that kubectl update expect a full specification; also tell people to use cmdline tricks like pipeline and jq if they want to use kubectl update to make a partial update.
  3. Create a new command kubectl patch which uses the PATCH verb, and use the server-side patch. The command should have flags to allow users to specify which PATCH operations to use. Then we can deprecate kubectl update --patch.
  4. Create a new command, maybe called kubectl up. This command first diff the new config with the old config stored as annotation in the object, then submit a stategic-merge patch to update the object. See Configuration reconciliation (aka kubectl apply) #1702. (Adds a diff command #8662 is a PR for diff)

1 and 2 should go in v1, as they makes kubectl update work as expected. 3 and 4 are bonus points.

@bgrant0607 please correct me if I'm wrong.

@bgrant0607
Copy link
Member

Sounds right.

We should also determine whether create via PUT works: #7047, #2114

@bgrant0607
Copy link
Member

We could also (in a separate PR) make update --force smart enough to determine whether re-creation is necessary using the hash comparison described above.

@mikedanese
Copy link
Member

I see code that seems to imply that PUT is intended to create https://github.com/GoogleCloudPlatform/kubernetes/blob/master/pkg/apiserver/resthandler.go#L510-L512

@nikhiljindal
Copy link
Contributor

@j3ffml
Copy link
Contributor Author

j3ffml commented Jun 25, 2015

  1. Add a --force flag to kubectl update. When this flag is set, kubectl update will delete and re-create the object.
  2. Modify the documentation, make it clear that kubectl update expect a full specification; also tell people to use cmdline tricks like pipeline and jq if they want to use kubectl update to make a partial update.

This approach requires more special knowledge on the user's part than seems necessary. Why not make kubectl update -f always default to using patch? That way users can make incremental changes to local files and update will work as expected. The defaults should be simple; update requiring a full object specification as a default is not simple.

@j3ffml
Copy link
Contributor Author

j3ffml commented Jun 25, 2015

cc @brendandburns

@caesarxuchao
Copy link
Member

@jlowdermilk, the 4th point, kubectl up, does what you suggest, doesn't it?

@j3ffml
Copy link
Contributor Author

j3ffml commented Jun 25, 2015

@caesarxuchao, it does, but I am suggesting that behavior be made the default for kubectl update -f, since that would be the least surprising behavior. Consider:

kubectl create -f mypod.yaml  # works as expected
kubectl delete -f mypod.yaml  # works as expected
kubectl update -f mypod.yaml  # always fails???

Adding kubectl --force seems useful, but I think we should still make it easy for users to update running resources based on incremental changes to local config.

@bgrant0607
Copy link
Member

Part of the problem is that "update" is too generic of a term. I propose we rename it to "replace".

We shouldn't make patch the default behavior for "update". We should just create a "patch" command to make it obvious that that's what it does.

There is nothing short of #1702 that actually does what we want, which is a proper declarative update.

cc @ghodss

@bgrant0607
Copy link
Member

We'll see if we can get diff+patch in.
cc @jackgr

@ghodss
Copy link
Contributor

ghodss commented Jun 25, 2015

I like changing kubectl update to kubectl replace, and changing kubectl update to do a PATCH instead of a PUT. Advantage of update is that it's much more natural and expected, and as far as the user's concerned, I don't think there's a distinction between what the user would think that update does and what patch actually does. I dislike removing update altogether as I think it would decrease usability.

@ghodss
Copy link
Contributor

ghodss commented Jun 25, 2015

Actually I thought of one issue, that has to do with what we were planning for kubectl reconcile - if you delete a field in your config file, and you run kubectl update -f and it has patch semantics, by default that field is not updated. That's the whole design of patch to prevent clobbering already-set fields. The plan for solving this (in #1702) is to maintain annotations that describe what was previously set by kubectl so we can track what to remove (and correspondingly, what to leave alone) when a patch doesn't have all the fields of the object it's patching.

So, that might be one distinction that someone may not expect from kubectl update but may expect from kubectl patch.

We can either roll reconcile functionality into update and make patching with annotations a first class activity, but that might be hard for v1. The alternative would be to change kubectl update to kubectl replace, add kubectl patch, and add kubectl update which patches with annotations when we get to it.

@caesarxuchao
Copy link
Member

Here's what we plan to do after in-person discussion with @bgrant0607

  1. move kubectl update --patch to a separate verb kubectl patch
  2. let kubectl update do diff+patch (@jackgr is going to do this)
  3. move the current PUT behavior of kubectl update to a new verb kubectl replace (we will make "update" as an alias of "replace" until 2 is in.)

Please correct me if I'm wrong.

@bgrant0607
Copy link
Member

We'll leave "update" as an alias for "replace" for now, and eventually just remove "update". "replace" and "patch" are more specific.

If pflags/cobra supported it, we could also create a "change" command that would support changing frequently used properties via patch, but specified via command-line flags. We could also create specific commands for changing common properties.

I think we should call diff+patch (aka reconcile) "apply".

@ghodss Yes, the case of deleting a field from the config file is exactly why we should not just change update to patch. Imagine, for instance, removing or renaming a container in a pod/podTemplate.

It's a good point that imperative updates should update config annotations, if any. I don't think we need to do that initially, however.

@bgrant0607
Copy link
Member

We now have kubectl patch and kubectl replace --force.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/kubectl priority/important-soon Must be staffed and worked on either currently, or very soon, ideally in time for the next release. sig/api-machinery Categorizes an issue or PR as relevant to SIG API Machinery.
Projects
None yet
Development

No branches or pull requests

6 participants