Skip to content
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

Script adding a GCR staging repo #186

Merged
merged 3 commits into from
Feb 20, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions gcr/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Managing Kubernetes container regstries

This directory is for tools and things that are used to administer the GCR
repositories used to publish official container images for Kubernetes.

## Staging repos

Each "project" (as decided by people) that feeds into Kubernetes' main
image-serving system (k8s.gcr.io) gets a staging repository. Each staging
repository is governed by a googlegroup, which grants push access to that
repository.

Project owners can push to their staging repository and use the image promoter
to promote images to the main serving repository.

As of Feb 11, 2019 this hierarchical system, including the promoter, are a
work-in-progress.
149 changes: 149 additions & 0 deletions gcr/add-staging-repo.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
#!/bin/sh
#
# This script is used to create a new "staging" repo in GCR. Each sub-project
# that needs to publish container images should have their own staging repo.
#
# Each staging repo exists in its own GCP project, and is writable by a
# dedicated googlegroup.

set -o errexit
set -o nounset
set -o pipefail

function usage() {
echo "usage: $0 <repo>" > /dev/stderr
echo "example:" > /dev/stderr
echo " $0 coredns" > /dev/stderr
echo > /dev/stderr
}

function _color() {
tput setf $1
}

function _nocolor() {
tput sgr0
}

function color() {
_color $1
shift
echo "$@"
_nocolor
}

if [ $# != 1 ]; then
usage
exit 1
fi
if [ -z "$1" ]; then
usage
exit 2
fi

# The name of the sub-project being created, e.g. "coredns".
REPO="$1"

# The GCP project name.
PROJECT="k8s-staging-${REPO}"

# The GCS bucket that backs the GCR repo.
BUCKET="artifacts.${PROJECT}.appspot.com"

# The group that is admins all staging repos.
ADMINS="k8s-infra-gcr-admins@googlegroups.com"

# The group that can write to this staging repo.
WRITERS="k8s-infra-gcr-staging-${REPO}@googlegroups.com"

# The GCP org stuff needed to turn it all on.
ORG="758905017065" # kubernetes.io
BILLING="018801-93540E-22A20E"


# Make the project, if needed
if ! gcloud projects describe "${PROJECT}" >/dev/null 2>&1; then
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if this project name happens to be an unrelated 3rd party?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You won't be able to list those. I don't see a way to only list projects under a specific org - do you know of one? Assuming you have a project with this name pattern in your scope, something else will fail. Or if you have project admin, maybe it won't fail.

We could require this create to happen, which makes the scripts not re-runnable. We could add flags to say --project-exists or something. Is that worth the effort?

color 6 "Creating project ${PROJECT}"
gcloud projects create "${PROJECT}" \
--organization "${ORG}"
else
o=$(gcloud projects \
describe k8s-staging-coredns \
--flatten='parent[]' \
--format='csv[no-heading](type, id)' \
| grep ^organization \
| cut -f2 -d,)
if [ "$o" != "${ORG}" ]; then
echo "project ${PROJECT} exists, but not in our org: got ${o}"
exit 2
fi
fi

color 6 "Configuring billing for ${PROJECT}"
gcloud beta billing projects link "${PROJECT}" \
--billing-account "${BILLING}"

# Grant project viewer so the UI will work.
color 6 "Granting project viewer to ${ADMINS}"
gcloud \
projects add-iam-policy-binding "${PROJECT}" \
--member "group:${ADMINS}" \
--role roles/viewer
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we just want admins as 'viewers'? what about 'owners'?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They only need project viewer for the UI to work. They have bucket admin for the specific buckets.

We're trying to keep untra-limited perms when possible.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

who is going to manage the projects? just who create them?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the set of people who can create projects is very small and should, itself be governed by a googlegroup


# Enable container registry API
color 6 "Enabling the container registry API"
gcloud --project "${PROJECT}" \
services enable containerregistry.googleapis.com

# Push an image to trigger the bucket to be created
color 6 "Activating the registry bucket"
PHONY="ceci-nest-pas-une-image"
docker pull k8s.gcr.io/pause
docker tag k8s.gcr.io/pause "gcr.io/${PROJECT}/${PHONY}"
docker push "gcr.io/${PROJECT}/${PHONY}"
gcloud --project "${PROJECT}" \
container images delete --quiet "gcr.io/${PROJECT}/${PHONY}:latest"

# Grant cross-repo admins access to admin.
color 6 "Granting bucket objectAdmin to ${ADMINS}"
gsutil iam ch "group:${ADMINS}:objectAdmin" "gs://${BUCKET}"
color 6 "Granting bucket legacyBucketOwner to ${ADMINS}"
gsutil iam ch "group:${ADMINS}:legacyBucketOwner" "gs://${BUCKET}"

# Make the bucket publicly readable.
color 6 "Making the bucket public"
gsutil iam ch allUsers:objectViewer "gs://${BUCKET}"

# Grant repo writers access to write.
color 6 "Granting bucket objectAdmin to ${WRITERS}"
gsutil iam ch "group:${WRITERS}:objectAdmin" "gs://${BUCKET}"
color 6 "Granting bucket legacyBucketReader to ${WRITERS}"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need 'legacyBucketReader'?
are we going to store GCS buckets as well or just GCR?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

without buckets.list it didn't work, and there doesn't seem to be a role that includes that permission that isn't "legacy" (and I didn't want to make a custom role, though we could, I guess...)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you are right, the other alternative is 'roles/storage.admin'

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

which is too broad

gsutil iam ch "group:${WRITERS}:legacyBucketReader" "gs://${BUCKET}"

# Set lifecycle policies.
color 6 "Setting lifecycle to age-out old data"
echo '
{
"rule": [
{
"condition": {
"age": 30
},
"action": {
"storageClass": "NEARLINE",
"type": "SetStorageClass"
}
},
{
"condition": {
"age": 90
},
"action": {
"type": "Delete"
}
}
]
}
' | gsutil lifecycle set /dev/stdin "gs://${BUCKET}"

color 6 "Done"