Skip to content

Commit 3737a61

Browse files
committed
KEP-1731: Extend the KEP with the OBS implementation
Signed-off-by: Marko Mudrinić <[email protected]>
1 parent 2be5509 commit 3737a61

File tree

2 files changed

+232
-57
lines changed

2 files changed

+232
-57
lines changed

keps/sig-release/1731-publishing-packages/README.md

Lines changed: 230 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Publishing kubernetes packages
1+
# Publishing kubernetes packages <!-- omit in toc -->
22

33
<!-- toc -->
44

@@ -11,6 +11,15 @@
1111
- [User Stories](#user-stories)
1212
- [User Roles](#user-roles)
1313
- [Implementation Details/Notes/Constraints](#implementation-detailsnotesconstraints)
14+
- [Using OBS instead of manually building and hosting packages](#using-obs-instead-of-manually-building-and-hosting-packages)
15+
- [How Open Build Service works?](#how-open-build-service-works)
16+
- [OBS configuration and packages layout](#obs-configuration-and-packages-layout)
17+
- [Packages in OBS](#packages-in-obs)
18+
- [Package Sources](#package-sources)
19+
- [Package Specs](#package-specs)
20+
- [Integrating OBS with our current release pipeline](#integrating-obs-with-our-current-release-pipeline)
21+
- [Authentication to OBS and User Management](#authentication-to-obs-and-user-management)
22+
- [How are packages used?](#how-are-packages-used)
1423
- [Risks and Mitigations](#risks-and-mitigations)
1524
- [Design Details](#design-details)
1625
- [Test Plan](#test-plan)
@@ -23,7 +32,6 @@
2332
- [Implementation History](#implementation-history)
2433
- [Drawbacks [optional]](#drawbacks-optional)
2534
- [Alternatives [optional]](#alternatives-optional)
26-
- [Infrastructure Needed](#infrastructure-needed)
2735
<!-- /toc -->
2836

2937
## Release Signoff Checklist
@@ -84,14 +92,18 @@ and this will implicitly achieve the main goal of
8492
## Proposal
8593

8694
- Make the infrastructure generic and simple enough to be easily handed off to the CNCF
87-
- Storage buckets (to store the staged/released packages) or anything similar
88-
- DNS entries (e.g. apt.kubernetes.io, ...)
89-
- package mirror (e.g. a self hosted aptly/artifactory/... or as a service)
90-
- have multiple channels, e.g. `stable`, `dev`, `nightly`
95+
- Choose a Packages as a Service solution (e.g. Open Build Service...) or build
96+
the infrastructure manually. In case we build the infrastructure manually, we need
97+
at least:
98+
- Storage buckets (to store the staged/released packages) or anything similar
99+
- DNS entries (e.g. apt.kubernetes.io, ...)
100+
- Package mirror (e.g. a self hosted aptly/artifactory/... or as a service)
101+
- have multiple channels, e.g. `stable`, `dev`, `nightly`
91102
- Run the package builds as part of [krel stage and release]
92103
- Have a safe way to store the signing key and make it available to the release team and release tooling
104+
- Making key available to the Release Team/Managers is not a requirement if using 'as a service' solution
93105
- Automatically sign the repository and packages
94-
- Automatically build and publish packages on a nightly basis
106+
- Automatically build and publish packages on a nightly basis (not required)
95107

96108
[krel stage and release]: https://github.com/kubernetes/release/blob/master/docs/krel/README.md#usage
97109

@@ -151,49 +163,182 @@ Scenario: [...]
151163

152164
### Implementation Details/Notes/Constraints
153165

154-
Packages will be published for different:
166+
Packages will be built and published using [Open Build Service (OBS)][obs]. openSUSE will sponsor the Kubernetes
167+
project by giving us access to the [OBS instance hosted by openSUSE][obs-build].
168+
169+
[obs]: https://openbuildservice.org/
170+
[obs-build]: https://build.opensuse.org/
171+
172+
#### Using OBS instead of manually building and hosting packages
173+
174+
The reasons for using Open Build Service (OBS) instead of building and hosting packages ourselves are:
175+
176+
- We want to handoff managing GPG keys to the third-party
177+
- Managing GPG keys ourselves represents a security risk. For example, if a Release Manager with access to the GPG key
178+
steps down, we might need to rotate the key. This is a process that affects End Users, therefore
179+
we want to avoid it
180+
- In this case, GPG keys are securely managed by the OBS platform hosted by openSUSE. No one from the Kubernetes
181+
project will have direct access to the key, mitigating one of the main risks of this proposal
182+
- We want to avoid managing the infrastructure ourselves, including buckets, mirrors/CDNs...
183+
- We want to provide 'as a service' access to the packages infrastructure to Release Managers and eventually other
184+
Kubernetes maintainers for their subprojects
185+
186+
#### How Open Build Service works?
187+
188+
From the [OBS website](https://openbuildservice.org/):
189+
190+
> The Open Build Service (OBS) is a generic system to build and distribute binary packages from sources in an automatic, consistent and reproducible way. You can release packages as well as updates, add-ons, appliances and entire distributions for a wide range of operating systems and hardware architectures.
191+
192+
OBS works in a way that we push sources and package spec files. Upon pushing packages/changes, OBS automatically
193+
triggers builds for all chosen operating systems and architectures. Under the hood, OBS uses the same set of tools that
194+
we use for building packages: `dpkg-buildpackage` and `rpmbuild`.
195+
196+
OBS implements a simple source-control management (SCM) system. It provides a complete history for all packages
197+
allowing users to see what spec files and sources we used to build the concrete package. The history is accessible
198+
via the OBS web interface.
199+
200+
Interaction with the OBS platform is done mainly via the [`osc` command-line tool][osc]. Alternatively, it's possible
201+
to interact via the web interface. Currently there are no (Go) libraries that we can use instead of the `osc` tool.
202+
203+
[osc]: https://openbuildservice.org/help/manuals/obs-user-guide/cha.obs.osc.html
204+
205+
#### OBS configuration and packages layout
206+
207+
Packages will be published for the following Debian-based (`apt`) and RPM-based (`yum`) distributions and architectures:
208+
209+
- Ubuntu 20.04 (`aarch64`, `armv7l`, `ppc64le`, `s390x`, `x86_64`)
210+
- CentOS Stream 8 (`aarch64`, `ppc64le`, `x86_64`)
211+
- OpenSUSE Factory (`armv7l`, `s390x`)
212+
213+
Those operating systems are supposed to provide the best compatibility with all Debian-based and RPM-based
214+
distributions, respectively.
215+
216+
The following packages will be published for all operating system and architectures listed earlier. For simplicity,
217+
we'll refer to those as packages as the **core packages**:
218+
219+
- `cri-tools`
220+
- `kubeadm`
221+
- `kubectl`
222+
- `kubelet`
223+
- `kubernetes-cni`
224+
225+
We'll use this layout for the core packages:
155226

156-
- Package managers, like `apt` (consumes deb packages) and `yum` (consumes rpm packages).
157-
- **`${k8s_release}`**: the version of kubernetes `<major>.<minor>`
158-
(e.g. `1.12`, `1.13`, `1.14`, ...)
159227
- **`${channel}`**: can be `stable`, `dev`, `nightly`
160228
- `stable`: all official releases for `${k8s_release}`
161-
(e.g.: `1.13.0`, `1.13.1`, `1.13.2`, ...)
162-
- `dev`: all development releases for all minor releases in this `${k8s_release}`, including `alpha`s, `beta`s and `rc`s
163-
(e.g.: `1.13.0-rc.2`, `1.13.2-beta.0`, `1.13.1-alpha.3`, ...)
164-
- `nightly`: any package cut automatically on a daily basis (optionally)
229+
(e.g.: `1.26.0`, `1.26.1`, `1.26.2`, ...)
230+
- `dev`: all development releases for all minor releases in this `${k8s_release}`,
231+
including `alpha`s, `beta`s and `rc`s (e.g.: `1.26.0-rc.2`, `1.26.2-beta.0`, `1.26.1-alpha.3`, ...)
232+
- `nightly`: any package cut automatically from the `master` branch on a daily basis (optionally)
233+
- Nightly packages are currently out of scope and might be handled via a different KEP
234+
- **`${k8s_release}`**: the version of Kubernetes `<major>.<minor>`
235+
(e.g. `1.12`, `1.13`, `1.14`, ...)
165236

166-
This means, that End Users can configure their systems’ package managers to use
167-
those different `${channel}`s of a kubernetes `${k8s_release}` for their
168-
corresponding package manager.
237+
In OBS, this layout replicates as:
169238

170-
A configuration for the package managers might look something like:
239+
- The root OBS project is [**`isv:kubernetes`**](https://build.opensuse.org/project/show/isv:kubernetes)
240+
- **`core`** subproject will be created in the root project to be used for the core packages
241+
- In the future, we might want to allow other subprojects to use OBS, so we want to properly layout our root project
242+
- Each **`${channel}`** has a subproject in the **`core`** project (e.g. **`isv:kubernetes:core:stable`**)
243+
- Each **`${k8s_release}`** has a subproject in the **`${channel}`** subproject
244+
(e.g. **`isv:kubernetes:core:stable:v1.26`**)
245+
- Packages are published to this subproject. Other subprojects are only placeholders
246+
for **`${k8s_release}`** subprojects
247+
248+
Having **`${k8s_release}`** subproject as a subproject of **`${channel}`** is required so we can build multiple
249+
releases in parallel. Otherwise, we would have to build a mechanism to wait for ongoing build process to be done
250+
before starting the build process for the next release in the pipeline. This is because if changes are pushed to
251+
the package, the ongoing build process is aborted. Running builds sequentially is not an option because
252+
that would slow down the release process too much.
171253

172-
- deb:
173-
```
174-
# deb http://apt.kubernetes.io ${k8s_release} ${channel}
175-
deb [signed-by=/etc/keyrings/kubernetes-keyring.gpg] http://apt.kubernetes.io/debian 1.26 nightly
176-
```
177-
- rpm/yum:
178-
```
179-
[kubernetes]
180-
name=Kubernetes
181-
# baseurl=http://yum.kubernetes.io/${k8s_release}/${channel}
182-
baseurl=http://yum.kubernetes.io/fedora/1.26/nightly
183-
enabled=1
184-
gpgcheck=1
185-
repo_gpgcheck=1
186-
gpgkey=file:///etc/pki/rpm-gpg/kubernetes.gpg.pub
187-
```
254+
The subprojects can be created manually via the web interface. Upon creating a **`${k8s_release}`** subproject,
255+
the target operating systems and architectures (listed at the beginning of this subheading) must be configured for
256+
the subproject (via the Repositories option). This is to be done by the Release Managers before cutting the first
257+
alpha release for that minor release.
188258

189-
Different architectures will be published into the same repos, it is up to the package managers to pull and install the correct package for the target platform.
259+
Note: it's important to ensure that the subproject and created packages are configured in a way to keep
260+
previous build (i.e. previous patch releases).
261+
262+
#### Packages in OBS
263+
264+
Before pushing packages, a **Package** object must be created in each **`${k8s_release}`** subproject for each package
265+
that we want to publish. This can be done via the `osc` command-line tool or the web interface. The created package
266+
inherits information about the target operating systems and architectures from the subproject. Creating packages is
267+
to be done by the Release Managers before cutting the first alpha release for that minor release.
268+
269+
Once all Package objects are created, sources and spec files can be pushed to those packages using `osc`.
270+
271+
#### Package Sources
272+
273+
We'll push pre-built binaries to OBS instead of pushing sources and then building binaries in the OBS pipeline.
274+
The reasoning for this is:
275+
276+
- We already have our own release pipeline. Adding another release pipeline would increase the maintenance burden for
277+
Release Managers
278+
- It would increase the effort for updating build dependencies such as Go
279+
- It would increase the effort for validating correctness of created binaries
280+
- Binary published by our release process would differ to binaries built by OBS
281+
- Additional efforts would be needed to get reproducible builds working
282+
- We would also lose cosign signatures for binaries built by OBS
283+
284+
`kubepkg` will be extended with a subcommand to create a tarball with all required binaries and files (e.g. systemd
285+
units and config files). The tarball is supposed to be created with the maximum compression to save on bandwidth and
286+
storage. The structure of the tarball is supposed to be:
287+
288+
- Root of tarball:
289+
- LICENSE file
290+
- All accompanying files (e.g. systemd units)
291+
- Subdirectory for each target architecture:
292+
- Binary for that architecture (e.g. `kubectl`)
293+
294+
#### Package Specs
295+
296+
There are two key changes to the package specs compared to what specs we have at the time of writing this KEP:
297+
298+
- We'll maintain specs only for the RPM-based distros
299+
- We'll have a dedicated spec for each package
300+
- Right now, for RPM-based distros, we have one spec file that builds all packages
301+
- This is to make it easier to maintain and update those spec files / packages, as well as, to make it easier for
302+
distributors to consume and use those spec files
303+
304+
The starting point for creating RPM specs is going to be the [RPM specs currently embedded in `kubepkg`][kubepkg-rpm].
305+
The following changes are needed to those RPM specs:
306+
307+
- Parametrize specs so the build tooling is able to pick a binary for the correct target architecture
308+
- Ensure all spec files are passing rpm-lint
309+
310+
The reason for dropping deb specs is that maintaining and generating those specs is much more complicated than
311+
maintaining RPM specs. Considering that we use pre-built binaries, we can easily convert RPM specs to Debian specs
312+
using the [`debbuild` tool][debbuild]. The `debbuild` tool is already available in the OBS pipeline. This tool
313+
can also be used by distributors if they want to build deb packages on their own.
314+
315+
The RPM specs will be generated by `kubepkg`, which already supports this. We only need to update the spec files.
316+
317+
[kubepkg-rpm]: https://github.com/kubernetes/release/tree/e10a44f8f9a9c08441260574e3d2a8711031fafe/cmd/kubepkg/templates/latest/rpm
318+
[debbuild]: https://github.com/debbuild/debbuild
319+
320+
#### Integrating OBS with our current release pipeline
321+
322+
As described above, currently, it's up to the Release Manager to create the subproject and packages structure in OBS
323+
before releasing the first alpha release. This should be the only manual steps required by Release Managers (besides
324+
the user management, described below).
325+
326+
The workflow for publishing packages is:
327+
328+
- Authenticate to OBS via `osc`
329+
- Pull all packages that we'll be publishing from OBS using `osc`
330+
- Regenerate specs for all packages using `kubepkg`
331+
- Generate the sources tarballs for all packages using `kubepkg`
332+
- Commit all changes and push them to OBS using `osc`
333+
- Wait for packages to be built and published successfully
334+
- There's [RabbitMQ][obs-rabbitmq] available that we can use to listen for events
335+
- This might not be feasible for all architectures, for example, building for `s390x` can take quite a while
190336

191337
Ideally and optionally, publishing/promoting a package means to commit a change
192338
to a configuration file which triggers a "package promotion tool", which:
193339

194340
- manages which packages need to go into which `${channel}` for which package manager of which `${k8s_release}`
195341
- guard that by the packages checksum
196-
- is able to promote a package from a bucket and also from a `${channel}` to the other
197342
- work off of a declarative configuration
198343

199344
This tool does for packages what the [Image Promoter][img-promoter] tool does
@@ -207,20 +352,55 @@ promotion is an optional part of this KEP. As an intermediate solution we can
207352
also leave the package publishing on the Google side and focus on building them
208353
before graduating the KEP to GA.
209354

210-
All architectures that are supported by the [package building tool][pkg-gen-kep] should be published.
211-
This KEP suggests to start with publishing a single supported architecture
212-
(e.g. `linux/amd64`) and extend that iteratively, when we verify that creating
213-
all packages for all architectures is fast enough to be done as part of the
214-
release process. If it turns out this step takes too long, we need to think
215-
about doing the package building & publishing asynchronous to the release
216-
process (see also: [Risks](#risks-and-mitigations)).
355+
At the time of writing this KEP, there are no Go libraries for working with OBS that we could use to integrate directly
356+
with `krel`. Eventually, we could evaluate if it makes sense to build such a library for our purposes. Until then,
357+
we'll use `osc` directly (by exec-ing), which also requires adding `osc` to our build images.
358+
359+
[obs-rabbitmq]: https://rabbit.opensuse.org/
360+
361+
#### Authentication to OBS and User Management
362+
363+
The concept of API tokens in OBS is very limited and provides access only to a very few endpoints. In other words,
364+
it's not possible to use API tokens for publishing to OBS. Instead, we need to create some sort of a service account
365+
to be used when publishing packages. This is one time operation that can be done by SIG Release Leads.
366+
367+
Users are managed manually via the OBS web interface. SIG Release Leads must have access to add/remove users from
368+
our OBS project. Release Managers should be given read/write access, so they can maintain and create projects and
369+
packages.
370+
371+
#### How are packages used?
372+
373+
The End Users can configure their systems’ package managers to use
374+
those different `${channel}`s of a kubernetes `${k8s_release}` for their
375+
corresponding package manager.
376+
377+
A configuration for the package managers might look something like:
378+
379+
- deb:
380+
```
381+
# deb http://apt.kubernetes.io ${k8s_release} ${channel}
382+
deb [signed-by=/etc/keyrings/kubernetes-keyring.gpg] http://obs.kubernetes.io/core:/stable:/v1.26/deb/ /
383+
```
384+
- rpm/yum:
385+
```
386+
[kubernetes]
387+
name=Kubernetes
388+
# baseurl=http://yum.kubernetes.io/${k8s_release}/${channel}
389+
baseurl=http://obs.kubernetes.io/core:/stable:/v1.26/rpm/
390+
enabled=1
391+
gpgcheck=1
392+
repo_gpgcheck=1
393+
gpgkey=file:///etc/pki/rpm-gpg/kubernetes.gpg.pub
394+
```
395+
396+
Different architectures will be published into the same repos, it is up to the package managers to pull and install the correct package for the target platform.
217397

218398
### Risks and Mitigations
219399

220-
- _Risk_: We don't find a proper way to share secrets like the signing key
221-
_Mitigation_: Using a third party tool like 1Password
400+
- _Risk_: The OBS installation provided by openSUSE is unable to serve the load generated by the Kubernetes project
401+
_Mitigation_: We can host our own mirrors and take some load from openSUSE (e.g. on Equinix Metal)
222402
- _Risk_: Building all the packages for all the distributions and their version takes too long to be done nightly or via cutting the release
223-
_Mitigation_: We do not deliver nightly packages.
403+
_Mitigation_: We do not deliver nightly packages or wait for packages to be published in the release pipeline.
224404

225405
## Design Details
226406

@@ -261,15 +441,15 @@ Once the tests show that the mirrors are good, we can adapt the official documen
261441

262442
#### Alpha
263443

264-
- Needed infrastructure is in place (buckets, DNS, repos, …)
444+
- Open Build Service is configured and ready to host packages
445+
- Spec files are ready and can be used in OBS to bulid packages
265446
- There is a documented process to create and publish deb and rpm packages of Kubernetes components
266447
- It is possible to consume the published deb and rpm packages using steps similar to the documented process
267448

268449
#### Alpha -> Beta Graduation
269450

270-
- [ ] [krel] creates deb and rpm packages of Kubernetes components
451+
- [ ] [krel] interacts with Open Build Service to automatically trigger package builds and publishing
271452
- [ ] Packages are signed
272-
- [ ] Repository indices are updated after packages are copied to the repositories
273453
- [ ] Post-publish tests are written and run as part of the release process
274454
- [ ] Nightly builds will be built and published on a daily basis using [krel] which will be improved to take over this task from [kubepkg] making use of [pre-existing periodic jobs] (https://github.com/kubernetes/test-infra/blob/97cb34fa9e2bfc4af35de3e561cb9fc5a1094da1/config/jobs/kubernetes/sig-release/kubernetes-builds.yaml#L120-L166)
275455
- [ ] Documentation written checked to be complete and correct.
@@ -312,9 +492,3 @@ N/A
312492
## Alternatives [optional]
313493

314494
N/A
315-
316-
## Infrastructure Needed
317-
318-
New infrastructure is required to manage keys used to sign the deb and rpm
319-
artifacts so as to remove the dependency on existing infrastructure and
320-
personal.

keps/sig-release/1731-publishing-packages/kep.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ authors:
44
- "@hoegaarden"
55
- "@RobertKielty"
66
- "@saschagrunert"
7+
- "@xmudrii"
78
owning-sig: sig-release
89
participating-sigs:
910
- sig-cluster-lifecycle
@@ -19,7 +20,7 @@ approvers:
1920
- "@tpepper"
2021
editor: TBD
2122
creation-date: 2019-02-19
22-
last-updated: 2022-10-12
23+
last-updated: 2023-01-18
2324
status: provisional
2425
see-also:
2526
- "https://github.com/kubernetes/enhancements/pull/858"

0 commit comments

Comments
 (0)