Skip to content

Ignore Apiversion, use Kind and Name only to search for original resource on update/delete#2976

Merged
bacongobbler merged 1 commit intohelm:masterfrom
HotelsDotCom:respect-apiversion-change
Oct 4, 2017
Merged

Ignore Apiversion, use Kind and Name only to search for original resource on update/delete#2976
bacongobbler merged 1 commit intohelm:masterfrom
HotelsDotCom:respect-apiversion-change

Conversation

@redbaron
Copy link
Contributor

Kind can change it's APIVersion with time, such as "Deployment" which was
"extensions/v1beta1" and then migrated to "apps/v1beta1" in Kube 1.6.

Name, Kind and optinally Namespace are used to find relevant Info
object for a original resource which is being upgraded, it safe enough,
as it is uniquely identifies an object.

Fixes: #2885

…n, use Kind and Name only

Kind can change it's APIVersion with time, such as "Deployment" which was
"extensions/v1beta1" and then migrated to "apps/v1beta1" in Kube 1.6.

Name, Kind and optinally Namespace are used to find relevant Info
object for a original resource which is being upgraded, it safe enough,
as it is uniquely identifies an object.
@k8s-ci-robot k8s-ci-robot added size/XS Denotes a PR that changes 0-9 lines, ignoring generated files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. labels Sep 27, 2017
@thomastaylor312 thomastaylor312 self-requested a review September 28, 2017 03:57
@thomastaylor312
Copy link
Contributor

I think this should work. I do want to run it by @adamreese though to make sure that this wouldn't have unintended side effects I haven't taken into account.

@thomastaylor312 thomastaylor312 added this to the 2.6.2 - Fixes milestone Sep 28, 2017
@bacongobbler
Copy link
Member

tentatively scheduling this for the v2.6.2 release.

// isMatchingInfo returns true if infos match on Name and GroupVersionKind.
func isMatchingInfo(a, b *resource.Info) bool {
return a.Name == b.Name && a.Mapping.GroupVersionKind == b.Mapping.GroupVersionKind
return a.Name == b.Name && a.Mapping.GroupVersionKind.Kind == b.Mapping.GroupVersionKind.Kind
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we change this to a.Mapping.GroupVersionKind.GroupKind() == b.Mapping.GroupVersionKind.GroupKind() then? We still want to ensure that two resources that are the same "Kind" (e.g. "Deployment") come from the same "Group" (e.g. "k8s.io"). For example, aggregated APIs like OpenShift could come up with their own Deployment object that acts differently from Kubernetes' Deployment object.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, we can't. Otherwise Deployment in ‘extensions/v1beta1’ won't be matching Deployment in ‘apps/v1beta1’, which is the whole point of this PR

@bacongobbler
Copy link
Member

bacongobbler commented Oct 4, 2017

I'm going to say that I do not agree with this patch. There is a movement towards aggregated APIs in Kubernetes where resources are uniquely identified by group/kind, so only checking the resource by Kind will not be unique enough in the future. Network policies coming from networking.k8s.io and network policies coming from openshift.io should not be directly comparable/upgradable. Similarly speaking, Deployments with version v1beta1, v1 and v2 (and in your case, shifting from extensions to apps) should not be allowed to upgrade without the user running --force. Non-v1 resources in Kubernetes were always expected to break in backwards-incompatible ways should the group, version OR kind ever change.

For example, let's assume in a future Kubernetes release, Pods now has released a v2 resource, so old manifests look like this:

apiVersion: v1
kind: Pod

And new manifests look like this:

apiVersion: v2
kind: Pod

Should these two types match? No. They are not directly translatable and should not be able to upgrade from one to another without a helm upgrade --force.

Now that all being said, we should absolutely display a more informational error and explain to the user why the upgrade failed (and how to fix it moving forward using --force), but I don't think this patch is the right way forward in general.

@bacongobbler
Copy link
Member

Given that this is not a regression that was introduced in v2.6, I'm going to remove this from the v2.6.2 milestone. If a future patch comes up then we can triage it into a future release.

@bacongobbler bacongobbler removed this from the 2.6.2 - Fixes milestone Oct 4, 2017
@redbaron
Copy link
Contributor Author

redbaron commented Oct 4, 2017

Ultimately, it is up to APIServer to say if resource is upgradable or not. Should there be no in-kube conversion supported between v2/pod and v1/Pod, helm would receive an authoritative APIServer error. All helm needs to do is not not stand in the way.

kubectl apply copes with extensions/v1beta1 and app/v1beta1 update just fine. Kube 1.8 highlight is promotion of various workloads to an app/v1beta2 , people will be updating their charts, it would be sad if helm falls short.

Please reconsider.

@bacongobbler
Copy link
Member

I'm agreeing with you, but I don't believe this specific change (changing isMatchingInfo's behaviour) is the right approach. I believe changing .Get to match kubectl's .GetOriginalConfiguration would be the correct approach here.

@redbaron
Copy link
Contributor Author

redbaron commented Oct 4, 2017

kubectl apply case is easier, they went with annotation, therefore they made their life so much easier on many levels. For this particular case, they know exactly that they are upgrading this specific object, there is no ambiguity.

Helm on the other hand stores known state as a separate .Release entity (encoded in configmap), therefore there is a need to find a match between every resource in a new Release and a resource in previously stored Release (create or delete is attempted if no match found). This search have no option, but to tolerate apiVersion changes to have a chance to find a match.

Unless Helm changes it's storage layout to uniquely track individual resources, lets say by their UIDs, I can see no way around it, but to relax matching condition.

@bacongobbler
Copy link
Member

bacongobbler commented Oct 4, 2017

Now I understand... So ultimately this is a limitation of tiller being unable to track the deployed resources in kubernetes as described in #2070. Thank you for clarifying. I should've known better.

I've already gone and cut v2.6.2 (release notes are coming soon) so this'll have to go into v2.7. Kubernetes 1.8 is out now so it shouldn't be much longer before we have it out.

@bacongobbler bacongobbler merged commit d7a81c9 into helm:master Oct 4, 2017
@redbaron redbaron deleted the respect-apiversion-change branch October 4, 2017 23:42
@redbaron
Copy link
Contributor Author

redbaron commented Oct 5, 2017

It just occurred to me, that even if Helm changes storage layout and starts to track individual resources it created in the past, it would still be needed to find a match between resources created in the past and resource definitions user provided in a new .Release.

In other words this:

Unless Helm changes it's storage layout to uniquely track individual resources, lets say by their UIDs, I can see no way around it, but to relax matching condition.Unless Helm changes it's storage layout to uniquely track individual resources, lets say by their UIDs, I can see no way around it, but to relax matching condition.

is not true, I don't know what I was thinking about :) It should say "Even if Helm changes it's storage layout..."

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

awaiting review cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. size/XS Denotes a PR that changes 0-9 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants