-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Delete and redeploy object upon error 'field is immutable' #940
Conversation
As discussed in GoogleContainerTools#891, when running skaffold dev certain immutable Kubernetes objects (like Jobs) can't be redeployed. A 'field is immutable' error is returned when this happens. To fix this issue, we can check the error from kubectl apply for 'field is immutable'. If we find it, we can delete the object and try to deploy it again.
As discussed in GoogleContainerTools#891, when running skaffold dev certain immutable Kubernetes objects (like Jobs) can't be redeployed. A 'field is immutable' error is returned when this happens. To fix this issue, we can check the error from kubectl apply for 'field is immutable'. If we find it, we can delete the object and try to deploy it again.
Codecov Report
@@ Coverage Diff @@
## master #940 +/- ##
==========================================
- Coverage 42.57% 42.44% -0.14%
==========================================
Files 71 71
Lines 3239 3254 +15
==========================================
+ Hits 1379 1381 +2
- Misses 1727 1740 +13
Partials 133 133
Continue to review full report at Codecov.
|
/cc @lenlen |
pkg/skaffold/deploy/kubectl/cli.go
Outdated
} | ||
// If the output contains the string 'field is immutable', we want to delete the object and recreate it | ||
// See Issue #891 for more information | ||
if err := c.Detete(ctx, out, manifests); err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this will need a rebase on balint's PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we please write an integration test for this?
9744858
to
2e5ac25
Compare
I added an integration test to make sure a Job is deleted and redeployed upon changes when running via skaffold dev. The test sets up by creating a file foo. It runs skaffold dev and make sure the Job is created. It then changes foo so that skaffold redeploys, and makes sure the UID of the new Job is different from the UID of the old job.
@balopat for sure, I added one! |
@priyawadhwa should we switch to applying object one by one so that if only one can't be recreated, we don't force delete the others? |
pkg/skaffold/deploy/kubectl/cli.go
Outdated
for _, mfst := range manifests { | ||
buf := bytes.NewBuffer([]byte{}) | ||
writer := bufio.NewWriter(buf) | ||
ml := ManifestList{mfst} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need to convert this back to a manifest list, mfst is just a []byte at this point
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So I had to convert it because the Delete function takes in a ManifestList
func (c *CLI) Delete(ctx context.Context, out io.Writer, manifests ManifestList) error
Is applying one by one slower? How much? |
@dgageot I'm not sure what the best way to figure this out would be, is there benchmarking for skaffold set up? I would guess that it's probably faster to go one by one than it would be to (potentially) delete and recreate all objects. |
We can compare the integration test timings to the previous runs to get a rough idea |
Timings with this PR:
A previous run:
So it does take a few seconds more for all of the tests except for the bazel test. Since this change only applies to developing with certain objects (Jobs, CronJobs) maybe it would be better to delete all objects and recreate instead? |
Update: @r2d4 suggested we use the
Support for using this flag with the immutable error was added in this PR, which hasn't been released officially. As discussed offline, we'll wait for kubectl v1.12.0 to come out so that we can use this flag. |
One more comment: we should be careful about version support for kubectl and make it clear in the docs what works. Also we could print a warning for lower than supported kubectl versions. |
The --force flag will delete and redeploy a deployment if 'kubectl apply' doesn't work because a field is immutable. Updated the skaffold deploy Dockerfile to reflect this change, added a note in the docs that kubectl > 1.12.0 is recommended, and added a check in the kubectl deployer for the version.
kubectl v1.12.0 is out, this should be RFAL :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A couple nits, but otherwise this seems fine
@@ -28,6 +28,8 @@ tools for deployment, for example `kubectl` or `helm`. | |||
Each deployment type has parameters that allow you to | |||
define how you want your app to be installed and updated. | |||
|
|||
_Note: kubectl version 1.12.0 or greater is recommended for use with skaffold._ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
might be worth documenting the known issues for earlier kubectl versions for users
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for sure, would this be the right spot for that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah, sorry missed your reply on this. FWIW this is a fine place to do it :)
func (c *CLI) CheckVersion() error { | ||
m, err := strconv.Atoi(c.Version().Minor) | ||
if err != nil { | ||
return fmt.Errorf("couldn't get kubectl minor version: %v", err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: errors.Wrapf(err, "retrieving kubectl minor version")
return fmt.Errorf("couldn't get kubectl minor version: %v", err) | ||
} | ||
if m < 12 { | ||
return fmt.Errorf("kubectl version 1.12.0 or greater is recommended for use with skaffold") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: errors.New("...")
@priyawadhwa I wonder if we could use that feature only when kubectl is 1.12+ |
@dgageot so the flag exists in lower versions it just doesn't work as expected, so if a user has a lower version then the same bug from the issue will occur. |
Any ideas when this will get merged? |
I think your feedback was taken into account
Shouldn't it be the same for |
Ping, @priyawadhwa @dgageot , see the comment from last year: this is still broken |
hey @haf -- what version of kubectl are you using? This feature only works with kubectl >1.12; if you're already on that, would you mind opening an issue so this bug can be tracked? |
hi @haf - you can override the behavior for |
I’m using latest of everything. I never do force on almost anything. Only interested in happy path for the team. |
As discussed in #891, when running skaffold dev certain immutable Kubernetes
objects (like Jobs) can't be redeployed. A 'field is immutable' error is
returned when this happens.
To fix this issue, we can check the error from kubectl apply for 'field
is immutable'. If we find it, we can delete the object and try to deploy
it again.
Adds an integration test for skaffold dev (#441)