Skip to content

Commit ba620d6

Browse files
Build Kubelet without Docker
A KEP proposing supporting building a Kubelet without docker, via the use of build tags.
1 parent 8f238f5 commit ba620d6

File tree

1 file changed

+289
-0
lines changed

1 file changed

+289
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,289 @@
1+
---
2+
title: Building a Dockerless Kubelet
3+
authors:
4+
- "@mattjmcnaughton"
5+
owning-sig: sig-node
6+
participating-sigs:
7+
- sig-testing
8+
- sig-release
9+
reviewers:
10+
- "@dims"
11+
- "@BenTheElder"
12+
- TBD
13+
approvers:
14+
- TBD
15+
editor: TBD
16+
creation-date: 2020-02-05
17+
last-updated: 2020-02-09
18+
status: provisional
19+
see-also:
20+
- "/keps/sig-cloud-provider/20190729-building-without-in-tree-providers.md"
21+
---
22+
23+
# Building a Dockerless Kubelet
24+
25+
## Table of Contents
26+
27+
<!-- toc -->
28+
- [Release Signoff Checklist](#release-signoff-checklist)
29+
- [Summary](#summary)
30+
- [Motivation](#motivation)
31+
- [History](#history)
32+
- [Returning to Motivation](#returning-to-motivation)
33+
- [Goals](#goals)
34+
- [Non-Goals](#non-goals)
35+
- [Proposal](#proposal)
36+
- [User Stories](#user-stories)
37+
- [Story 1](#story-1)
38+
- [Story 2](#story-2)
39+
- [Implementation Details/Notes/Constraints](#implementation-detailsnotesconstraints)
40+
- [Risks and Mitigations](#risks-and-mitigations)
41+
- [Design Details](#design-details)
42+
- [Test Plan](#test-plan)
43+
- [Graduation Criteria](#graduation-criteria)
44+
- [Upgrade / Downgrade Strategy](#upgrade--downgrade-strategy)
45+
- [Version Skew Strategy](#version-skew-strategy)
46+
- [Implementation History](#implementation-history)
47+
- [Drawbacks](#drawbacks)
48+
- [Alternatives](#alternatives)
49+
<!-- /toc -->
50+
51+
## Release Signoff Checklist
52+
53+
- [ ] kubernetes/enhancements issue in release milestone, which links to KEP (this should be a link to the KEP location in kubernetes/enhancements, not the initial KEP PR)
54+
- [ ] KEP approvers have set the KEP status to `implementable`
55+
- [ ] Design details are appropriately documented
56+
- [ ] Test plan is in place, giving consideration to SIG Architecture and SIG Testing input
57+
- [ ] Graduation criteria is in place
58+
- [ ] "Implementation History" section is up-to-date for milestone
59+
- [ ] User-facing documentation has been created in [kubernetes/website], for publication to [kubernetes.io]
60+
- [ ] Supporting documentation e.g., additional design documents, links to mailing list discussions/SIG meetings, relevant PRs/issues, release notes
61+
62+
## Summary
63+
64+
This proposal outlines a plan to enable building a dockerless Kubelet. We
65+
define a dockerless Kubelet as a Kubelet with no "Docker-specific" code and
66+
no dependency on the `docker/docker` Golang package. We define "Docker-specific"
67+
code as code which only serves a purpose when Docker is the container runtime.
68+
"Docker-specific" code is never executed when the Kubelet uses a remote
69+
container runtime (i.e. containerd or CRI-O).
70+
71+
Supporting building a dockerless Kubelet is a precursor to moving all
72+
"Docker-specific" Kubelet code out-of-tree, in the name of treating Docker like
73+
any other container runtime.
74+
75+
At a high level, this undertaking is similar to the efforts of
76+
sig-cloud-provider to support [Building Kubernetes Without In-Tree Cloud Providers](/keps/sig-cloud-provider/20190729-building-without-in-tree-providers.md).
77+
A big thanks to them for their leadership; much of this KEP is based off their great work :)
78+
79+
## Motivation
80+
81+
For this KEP to be worthwhile, we must believe the following two statements.
82+
83+
First, we must see a benefit to a dockerless Kubelet.
84+
Second, we must believe supporting the ability to compile a dockerless Kubelet is
85+
a useful first step towards a truly dockerless Kubelet.
86+
87+
A quick review of recent Kubernetes history provides context when considering
88+
whether we agree with the statements in question.
89+
90+
### History
91+
92+
With 1.5, Kubernetes introduced the [Container Runtime Interface](https://kubernetes.io/blog/2016/12/container-runtime-interface-cri-in-kubernetes/)
93+
(CRI). The CRI defines a standard interface for the Kubelet to communicate with container
94+
runtimes. At the time of the CRI's release, Kubernetes supported only the Docker
95+
and rkt container runtimes. Kubernetes introduced the CRI to avoid needing
96+
provider specific code for each new container runtime.
97+
98+
Since the CRI's release, the Kubelet only interacts with container runtimes via
99+
the CRI. For increasingly popular CRI implementations like containerd or CRI-O,
100+
the singular focus on the CRI poses no obstacles, as these container runtimes
101+
supported the CRI from the start. However, the Kubelet still needed a solution for
102+
Docker and rkt, in-tree runtimes which did not support the CRI. In-tree support
103+
for Rkt was deprecated, leaving only Docker as an issue.
104+
105+
Ultimately, the Kubelet introduced the `dockershim` to address Docker's lack of
106+
CRI support. When a cluster operator chooses to use Docker as the container
107+
runtime, the Kubelet will start the `dockershim`. The `dockershim` supports the
108+
CRI, so the Kubelet communicates with `dockershim` as if it was any other remote
109+
container runtime implementing the CRI. The `dockershim` makes the appropriate
110+
calls to the Docker daemon via a heavy dependence on the `docker/docker` client library.
111+
112+
The `docker/docker` client library is a particularly painful dependency because
113+
its pulls in code from many different open source libraries. For those managing
114+
k8s dependencies, it can be extremely difficult to keep up with the changes to
115+
all these dependencies. Additionally, all the open source libraries required by
116+
`docker/docker` bloat the Kubelet binary.
117+
118+
## Returning to Motivation
119+
120+
We can anticipate the following benefits from the Kubelet having no in-tree
121+
"Docker-specific" code and no dependency on the `docker/docker` Golang package.
122+
123+
First, a dockerless Kubelet would truly treat all container runtimes the same.
124+
Second, the Kubelet's scope of responsibility would decrease: it would no longer
125+
be responsible for making Docker conform to the CRI. Finally, the painful
126+
`docker/docker` dependency would be gone.
127+
128+
While the aforementioned benefits are desirable, they do not outweigh the cons
129+
of completely dropping support for Docker as a container runtime, as
130+
Docker remains popular. In order for Kubernetes
131+
to both support Docker as a container runtime, and for the Kubelet do have no
132+
in-tree "Docker-specific" code and no dependency on `docker/docker`, one of two
133+
following paths must be followed: either Docker must begin implementing the CRI natively
134+
or the `dockershim` must be moved out-of-tree into a standalone component.
135+
136+
Clearly, both of these paths forward require significant work. Either effort would
137+
require finding an owner, making non-trivial code changes, and updating patterns
138+
of cluster management/operation.
139+
140+
Faced with a hefty chunk of work, we naturally try to break it up into smaller
141+
components. This desire leads us to our second question: is supporting
142+
compiling a dockerless Kubelet an appropriate first step?
143+
144+
We argue yes. First, the work to support compiling a dockerless Kubelet will
145+
be useful regardless of which path forward we chose. First, to compile a dockerless
146+
Kubelet we must consolidate all "Docker-specific" Kubelet code into specific
147+
locations, which are easier to move out-of-tree or delete entirely when the time comes. Furthermore,
148+
after this initial consolidation, we can create tooling to impose limitations on
149+
where "Docker-specific" code can/cannot live. Second, allowing developers to
150+
compile a dockerless Kubelet assists in testing either proposed solution.
151+
Finally, allowing compiling a dockerless Kubelet allows projects/cluster
152+
operators which already do not depend on Docker to obtain the dockerless
153+
Kubelet's benefits (i.e. smaller binaries) without waiting for the
154+
completion of the longer term projects to make Docker support the CRI or
155+
move `dockershim` out-of-tree.
156+
157+
### Goals
158+
159+
Our goals follow from our motivation:
160+
161+
1. Support building Kubelet, from the `master` branch, without any "Docker-specific" code and without any
162+
dependency on `docker/docker`. As mentioned
163+
previously, we imagine the resulting binaries to be used to test the
164+
different paths for deleting/moving out-of-tree all "Docker-specific" code.
165+
2. Draw clear delineations, with CI support, for what code in Kubelet can and
166+
cannot be "Docker-specific" and depend on `docker/docker`.
167+
168+
### Non-Goals
169+
170+
Our non-goals also follow from our motivation:
171+
172+
1. Either making Docker support the CRI or moving `dockershim` out-of-tree.
173+
2. Removing uses of the `docker/docker` Golang library outside of the Kubelet.
174+
3. Changing the official Kubernetes release builds.
175+
176+
## Proposal
177+
178+
We will undertake the following steps to obtain our goals. First, we will ensure
179+
that all "Docker-specific" code in the Kubelet lives in `dockershim`. Then, we
180+
will add a [build constraint](https://golang.org/pkg/go/build/#hdr-Build_Constraints)
181+
to the Kubelet for a pseudo "build tag" specifying not to include
182+
any in-tree "Docker-specific" code. If builds do not specify this build tag, the Go
183+
compiler will compile the Kubelet as normal. If we do, the Go compiler will
184+
compile the Kubelet without the "Docker-specific" code, and as a result, without
185+
the dependency on `docker/docker`. In other words, it will simulate the aforementioned
186+
code/dependency's removal.
187+
188+
A prototype is available in [kubernetes/kubernetes#87746](https://github.com/kubernetes/kubernetes/pull/87746).
189+
190+
To ensure that this dockerless Kubelet continues to function we will add CI building in this mode,
191+
and CI running end to end tests against it (to be elaborated on in the test plan). Additionally, to
192+
ensure the Kubelet doesn't introduce new dependencies on the `docker/docker`
193+
Golang library, we will add automated tooling enforcing that only the
194+
`dockershim` can depend on `docker/docker`.
195+
196+
One quick additional note - currently `cadvisor` also depends on the
197+
`docker/docker` client library. Since `kubelet` depends on `cadvisor`, the
198+
`kubelet` can not truly be rid of the `docker/docker` client library until `cadvisor` no
199+
longer depends on `docker/docker`. Work to remove the `docker/docker` dependency
200+
from `cadvisor` is being dealt with in separate workstreams.
201+
202+
This proposal follows the previous patterns for similar work, namely the efforts
203+
of sig-cloud-provider to support [Building Without In-Tree Cloud Providers](/keps/sig-cloud-provider/20190729-building-without-in-tree-providers.md).
204+
205+
### User Stories
206+
207+
#### Story 1
208+
209+
As a developer working to make Docker function like any other remote container
210+
runtime, I am attempting to validate that my proposed solution
211+
functions correctly. Using this dockerless build ensures the Kubelet contains no
212+
"Docker-specific" code, and any success/failures can be attributed to my
213+
implementation.
214+
215+
#### Story 2
216+
217+
As a Kubernetes developer/user, for example a maintainer of [kind](https://github.com/kubernetes-sigs/kind),
218+
I want to use Kubelet binaries which only contain the code I need. Since kind does not use
219+
Docker as its container runtime, compiling a dockerless Kubelet gives me a
220+
smaller binary.
221+
222+
### Implementation Details/Notes/Constraints
223+
224+
A couple high level notes (to be extended over time):
225+
226+
- We implement this functionality using a synthetic `dockerless` tag in go build
227+
constraints on relevant sources. If `GOFLAGS=-tags=dockerless` during build,
228+
then "Docker-specific" code will be excluded from the Kubelet build. With no
229+
"Docker-specific" code, we should also be excluding the dependency on
230+
`docker/docker`.
231+
232+
### Risks and Mitigations
233+
234+
This feature is only developer facing, which removes a large class of risks.
235+
236+
The largest remaining risk is that the build tags fall out of date, or are
237+
burdensome to continue updating, which leads to the dockerless Kubelet build
238+
breaking and/or being costly to maintain. This risk grows the longer the
239+
dockerless Kubelet exists (i.e. the longer it takes to move `dockershim` out of
240+
tree/have Docker support the CRI). Fortunately, these risks can be mitigated via
241+
the CI tooling discussed earlier.
242+
243+
## Design Details
244+
245+
### Test Plan
246+
247+
**Note:** *Section not required until targeted at a release.*
248+
249+
TBD
250+
251+
### Graduation Criteria
252+
253+
**Note:** *Section not required until targeted at a release.*
254+
255+
TBD
256+
257+
### Upgrade / Downgrade Strategy
258+
259+
N/A
260+
261+
### Version Skew Strategy
262+
263+
N/A
264+
265+
## Implementation History
266+
267+
- original prototype [kubernetes/kubernetes#87746](https://github.com/kubernetes/kubernetes/pull/87746)
268+
- original KEP PR [TBD]
269+
270+
## Drawbacks
271+
272+
One drawback is the opportunity cost of pursuing this workstream as opposed to
273+
other possible workstreams.
274+
275+
Another drawback is the slight additional cost of the CI tooling we propose
276+
adding.
277+
278+
## Alternatives
279+
280+
One alternative would be to do nothing.
281+
282+
Another alternative could be waiting to address "Docker-specific" code in the
283+
Kubelet until we have more momentum around one of the longer-term solutions
284+
discussed above. If we waited, we could delete "Docker-specific" code entirely,
285+
instead of just compiling without it.
286+
287+
Finally, we could attempt to have a long-running branch in which all
288+
"Docker-specific" code has been deleted, instead of attempting to support
289+
compiling a dockerless Kubelet from master.

0 commit comments

Comments
 (0)