-
Notifications
You must be signed in to change notification settings - Fork 4.7k
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
Add support for Containerd container runtime #7986
Conversation
Hi @hakman. Thanks for your PR. I'm waiting for a kubernetes member to verify that this patch is reasonable to test. If it is, they should reply with Once the patch is verified, the new status will be reflected by the I understand the commands that are listed here. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
/ok-to-test |
77d284c
to
ef23b9b
Compare
ef23b9b
to
b8d8ce4
Compare
b8d8ce4
to
dbebbfc
Compare
eb97bb3
to
0aa01f8
Compare
I think this is ready for a few more pair of eyes. It works reliably in all my tests. /assign @granular-ryanbonham |
root: | ||
description: Directory for persistent data (default "/var/lib/containerd") | ||
type: string | ||
skipInstall: |
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.
Naming nit... What about managed: false
or external: true
? It's more than just install (I believe?); e.g. if we specify configFile + skipInstall, do we write the config file?
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.
I was confused also in the beginning. Current implementation is to not touch it at all, so no config, no managed service, just expect it to be running. The problem is that this is the current behaviour for Docker:
https://github.com/kubernetes/kops/blob/release-1.17/nodeup/pkg/model/docker.go#L1079
We may have to use 'managed: falseand
install: falseand deprecate
skipInstall: true` completely.
nodeup/pkg/model/containerd.go
Outdated
package model | ||
|
||
import ( | ||
// "encoding/json" |
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: we should probably not have these in new code. But I imagine staticcheck or similar will pick it up!
nodeup/pkg/model/containerd.go
Outdated
|
||
// DefaultContainerdVersion is the (legacy) containerd version we use if one is not specified in the manifest. | ||
// We don't change this with each version of kops, we expect newer versions of kops to populate the field. | ||
const DefaultContainerdVersion = "1.2.10" |
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 just require this version? I think this was an accommodation for a mistake I made previously when doing docker, but if we don't have to carry it forward, that feels better to me...
const DefaultContainerdVersion = "1.2.10" | ||
|
||
var containerdVersions = []packageVersion{ | ||
// 1.2.10 - Debian Stretch |
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.
I would love to try using the tar.gz packages in general for containerd, but I agree that this approach lets us have the best of both worlds :-)
Reasons for using the tar.gz:
- In theory, supports more OSes.
- Should be easier to package.. easier to specify just a URL to a tar.gz file (but the problems of architecture were pointed out previously!)
- Easier to deal with if we have to hotfix... building a tar.gz is much easier than building a package.
But I agree we should start here!
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.
I had exactly the same thought. I would love to continue on this path and same with Docker. Also, would like to include at some point the custom version tar.gz along the lines of what is done in #7719.
Btw, not sure if #7719 takes into account that containerd needs to be managed also in newer Docker versions.
switch b.Distribution { | ||
case distros.DistributionCoreOS: | ||
klog.Infof("Detected CoreOS; won't install containerd") | ||
if err := b.buildContainerOSConfigurationDropIn(c); 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.
Idea for future: We probably could flatten these three into a single switch
(or even if
statement). If there are differences in the drop-in, we could switch on b.Distribution in that function.
@@ -140,6 +142,7 @@ type ClusterSpec struct { | |||
// EtcdClusters stores the configuration for each cluster | |||
EtcdClusters []*EtcdClusterSpec `json:"etcdClusters,omitempty"` | |||
// Component configurations | |||
Containerd *ContainerdConfig `json:"containerd,omitempty"` |
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.
We did discuss in office hours whether this should be top-level; I think it's fine to leave it here.
- Docker is already at top-level, so we can move both at the same time when/if we ever refactor these.
- I think we want to put them on the InstanceGroup. When we do that maybe we can refactor. But this suggests something...
- Perhaps the configuration should be external, like other addons. Previously we've used a size argument to motivate that (keep each type manageable and understandable), but now's a DRY argument - multiple instancegroups might refer to the same shared containerd configuration.
- In that light, I imagine ContainerRuntime actually being a ref to the CRI configuration
- I don't think we should actually make it a full apimachinery ref (with a kind), that feels like overkill
- I think there's a path from where we are to that world. Specifying the
containerd
field in Cluster would be equivalent to create akind: ContainerdConfiguration
(or whatever) withname: containerd
So I think this is more intuitive today, and gives us a reasonable path to the future.
cc @geojaz ... I think it was you that brought this up in office hours?
return fmt.Errorf("Kubernetes version is required") | ||
} | ||
|
||
sv, err := KubernetesVersion(clusterSpec) |
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.
Tip (for the future): We do have the IsKubernetesGTE
helper in a bunch of places, not sure if it's available here.
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.
I tried to keep this as close as possible to the Docker version to make it easier to review.
The IsKubernetesGTE function family is quite nice. Thanks.
dockerVersion := fi.StringValue(clusterSpec.Docker.Version) | ||
switch dockerVersion { | ||
case "19.03.4": | ||
containerdVersion = "1.2.10" |
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.
Oh! So we are always installing containerd for these docker versions! Now I get it!
This is really clever, in that now we have a consistent way of configuring containerd underneath docker! I like it!
The downside is that we need to be super-careful that we haven't broken docker. I will ponder - this is great, but it's also a little risky, and maybe we should just do it for versions of docker we haven't yet introduced...
We could also leave docker as-is, and encourage people to go to containerd.
@@ -133,6 +133,12 @@ Resources.AWSAutoScalingLaunchConfigurationmasterustest1bmastersadditionalcidrex | |||
|
|||
cat > cluster_spec.yaml << '__EOF_CLUSTER_SPEC' | |||
cloudConfig: null | |||
containerRuntime: docker | |||
containerd: |
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.
I wonder if seeing docker
and containerd
is going to cause user confusion
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.
Depends a lot on users and how we present this in the release notes and docs.
My guess is that most users either know that Kubernetes runs on Docker + containerd, or think Kops does something magic and Kubernetes just runs. Those confused will ask in #kops-users
and we should direct them to the release notes and docs.
if err != nil { | ||
return err | ||
} | ||
defer writer.Close() |
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.
Not to self: So there are some edge cases here; e.g. if writer.Close() fails the output will likely be missing its last chunk or something. This is absolutely fine for how you are using it (with a tempdir), but we probably should be careful about making it a utils function. I'll add some paranoid error handling :-)
This is really great, thank you @hakman I would classify my comments into 3 types:
The "should docker install containerd" question is really tricky and the one that I think we should figure out. It is really clever, and I didn't get it at first, but it does make sense. I think there are a few challenges:
Thank you so much for this though - I think if we can figure out the right answer for "should docker install containerd" we should get this merged and iterate on it. I might also write a test for the protokube manifest generation, just to satisfy my own paranoia! |
Thanks so much @hakman for all the great comments! You've persuaded me on the idea that docker can now install docker + containerd - the idea that it will encourage users to go to containerd is a good one. (And looking at the docker additional features you cited over containerd, those do feel like client-side features which we probably don't want on servers!) The challenge is that we generally have a policy that you can update kops and we won't change configurations (except for bug / security fixes). We do that by keying most of our changes off the kubernetes version, not the kops version. This in turn lets us avoid having to maintain too many versions of kops, because in theory you can run k8s 1.14 with kops 1.14, 1.15, 1.16, 1.17 and should have the same behaviour.... So if we change the configuration of the docker version used for 1.16 or 1.17, based on that we should backport it. I don't think we want to do that, because then we don't have the time to stabilize containerd support on master. (I wasn't able to find which comment you were referring to when you mentioned it, so forgive me if this duplicates something you said) I think there are a few options: 1(a) Just accept that the docker behaviour will change for k8s 1.16 / 1.17 in kops 1.18 - it's not something we've done in the past and it might impact the upgrade story for kops. My view is that the best options here are 1(b) and 3 - and that 3 is easier. Do you have a view @hakman ? (Perhaps you've already pursued 1(b) in this PR? ) |
That's great @justinsb! :) My comment was this: Pretty much on the same lines as your conclusion:
I would add that we should maybe try the e2e tests soon. |
@justinsb would it be ok to merge this to master as is and continue with 1.b) and 3) as separate PRs? |
So I'm generally very much in favor of that @hakman ... but are we going to have to put back the containerd packages into docker.go? I may have the wrong end of the stick here, but I was interpreting the conclusion as being that we would not change the existing versions of docker, but we would split out containerd for some future version of docker. Is that right? If so, I was imagining it would be a pain to re-add containerd, but I'm ready to be corrected :-) |
@justinsb Re-adding containerd to existing Docker versions in docker.go shouldn't be that hard if we really want. We can also keep them in containerd.go and skip all the other tasks except installing the package (may be easier). The management in containerd.go is limited to creating a service file and a config file that's almost empty. These 2 are also created on install in a similar way. The containerd part will remain the same in both cases, independent, so anyone can select |
So you've persuaded me generally, and I'm OK with basically taking on a bit more validation work, except that we're changing the containerd version for older docker versions (we're essentially upgrading everyone to containerd 1.2.10). OK - let's get this in! A few things I want to do in follow-up:
Thanks for all your hard work on this @hakman - great stuff! /approve |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: hakman, justinsb The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
/lgtm |
Wonderful, @justinsb ! Thanks! Regarding your concern about the containerd upgrade to 1.2.10 for everyone, I assumed no one will mind. Someone that would install Docker 18.09.3 would get 1.2.10 as a dependency, even though the validated version was 1.2.4 at the release time: Containerd has a very strict policy regarding parch releases, I guess that's why Docker is so relaxed in regards to the dependency:
I don't mind changing, but will need to apply the change in branches for 1.15, 1.16 and 1.17. The versions I added there last month use 1.2.10 as a dependency. Please let me know if you want to change 18.09.3 dependency to 1.2.4 and I will send the PRs your way in a few days. PS: I now see that you meant the case of 18.09.3 here, not 18.09.9. Will take care of it: kops/pkg/model/components/containerd.go Lines 77 to 78 in 0b52b99
|
Docker and containerd are separate packages now. One could run Kubernetes with Docker + containerd or just with containerd with very little effort.
At the same time, Docker can run with newer versions of containerd have a more stable cluster.
This change brings new user facing changes with 2 new ClusterSpec options:
All new options have defaults and they default to the same values as without this change:
To use containerd as the container runtime, one would have to edit the cluster and change containerRuntime to containerd: