From ef744af165c21e23029ca82b53fb04009ce452f2 Mon Sep 17 00:00:00 2001 From: Javier B Perez Date: Wed, 14 Nov 2018 12:44:10 -0800 Subject: [PATCH] kep: image promoter: process to copy container images --- keps/sig-release/k8s-image-promoter.md | 103 +++++++++++++++++++++++++ keps/sig-release/promote-process.jpg | Bin 0 -> 27200 bytes 2 files changed, 103 insertions(+) create mode 100644 keps/sig-release/k8s-image-promoter.md create mode 100644 keps/sig-release/promote-process.jpg diff --git a/keps/sig-release/k8s-image-promoter.md b/keps/sig-release/k8s-image-promoter.md new file mode 100644 index 000000000..ccaba41e1 --- /dev/null +++ b/keps/sig-release/k8s-image-promoter.md @@ -0,0 +1,103 @@ +--- +title: Image Promoter +authors: + - "@javier-b-perez" +owning-sig: sig-release +participating-sigs: + - TBD +reviewers: + - "@AishSundar" + - "@BenTheElder" + - "@dims" + - "@listx" +approvers: + - "@thockin" +creation-date: 2018-09-05 +last-updated: 2018-11-14 +status: implementable +--- + +# Image Promoter + +## Table of Contents + +* [Table of Contents](#table-of-contents) +* [Summary](#summary) +* [Motivation](#motivation) + * [Goals](#goals) +* [Proposal](#proposal) + * [Staging Container Registry](#staging-container-registry) + * [Production Container Registry](#production-container-registry) + * [Promotion Process](#promotion-process) +* [Graduation Criteria](#graduation-criteria) +* [Infrastructure Needed](#infrastructure-needed) + + +## Summary + +For security reasons, we cannot allow everyone to publish container images into the official kubernetes container registry. This is why we need a process that allows us to review who built an image and who approved it to be shown in the official channels. + + +## Motivation + +There are multiple reasons why we should have a process to publish container images in place: + +* We cannot allow all community members to publish images into the official kubernetes container registry. +* We should restrict who can push images to a small set of members and some systems accounts for automation. +* We can run scans and tests on the images before we publish them into the official kubernetes container registry. +* The process to publish into an official channel shouldn't be hard or long to follow. We don’t want to block developers or releases. + +### Goals + +1. Define a process for publishing container images into an official GCR through a code review process and automated promotion from GCR staging environment. +1. Allow the community to own and manage the project registries. + +## Proposal + +Following the *GitOps* idea, the proposal is to use a code review process to approve publishing container images into official distribution channels. + +This requires two GCR registries: + +* Staging: temporary container registry to share container images for testing and scanning. +* Production or *official*: GCR used to host all the approved container images by the community. + +### Staging Container Registry + +This temporary storage allows to have a public place where to pull images and run qualification tests or vulnerability scans on the images before pushing them to the *official* container registry. + +Each project/subproject in the community, will require at least one member of their community to have push access to the staging area. + +### Production Container Registry + +A restricted set of members can have push access to override any tool or process if necessary. +Ideally we only push images that have been approved by the owners of the production container registry, following the promotion process. + +### Promotion Process + +1. Maintainer create a container image and push it into *staging* GCR. +1. Maintainer creates a PR in GitHub to add the new image into the *official* container registry. +1. Once owners of the official container registry approve the change and merge it into the master branch, the promoter tool will automatically copy the container image(s) from *staging* into *official* container registry. + +If the infrastructure support it, the promoter tool could sign container images when pushing to the official container registry. + +![Promote process](promote-process.jpg?raw=true "Promote process") + +In the future, we could add more information into the context of the PR like the vulnerability scan and test results of the container image. + +## Graduation Criteria + +We will know we are done when we have: + +* User guide for developers/maintainers: how to build? how to promote? +* User guide for owners: review and approve PR, how to push images? +* A repository to host the manifest file. +* Initial set of repository's owners who can approve changes. +* Criteria to grant or remove access to staging and production container registries. +* A tool that automatically copy approved images into official channels. + +## Infrastructure Needed + +* Two GCP projects with GCR enabled. + * One project should have GCB enabled to run the promotion tool in it. +* Repository to host the manifest for promotions. + diff --git a/keps/sig-release/promote-process.jpg b/keps/sig-release/promote-process.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8b74b539b53a82592c3227fb9eef4802f2df32d3 GIT binary patch literal 27200 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 H>CS%xODGd2 literal 0 HcmV?d00001