Skip to content

Commit 9cbff60

Browse files
authored
London KubeCon workshop (#11)
Add London KubeCon kcp workshop
1 parent e9d202d commit 9cbff60

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+2107
-0
lines changed

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,10 @@
2222

2323
# Go workspace file
2424
go.work
25+
*.kubeconfig
26+
27+
**/.kcp
28+
**/bin
29+
**.tar.gz
30+
kcp-operator
31+
.checkpoint-**
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
#!/usr/bin/env bash
2+
3+
set -o nounset
4+
set -o pipefail
5+
6+
source "$(git rev-parse --show-toplevel)/20250401-kubecon-london/workshop/lib/env.sh" "$(cd "$(dirname "$0")" && pwd)"
7+
export GOOS="$( uname | tr '[:upper:]' '[:lower:]' | grep -E 'linux|darwin' )"
8+
export GOARCH="$( uname -m | sed 's/x86_64/amd64/ ; s/aarch64/arm64/' | grep -E 'amd64|arm64' )"
9+
10+
set -o errexit
11+
12+
[[ -n "${GOOS}" ]] || { echo "Unsupported OS: $(uname)" 1>&2 ; exit 1 ; }
13+
[[ -n "${GOARCH}" ]] || { echo "Unsupported platform: $(uname -m)" 1>&2 ; exit 1 ; }
14+
15+
if [[ ! -f "${WORKSHOP_ROOT}/bin/.checkpoint-kcp" ]]; then
16+
echo "🚀 Downloading kcp"
17+
curl -L "https://github.com/kcp-dev/kcp/releases/download/v0.26.1/kcp_0.26.1_${GOOS}_${GOARCH}.tar.gz" \
18+
| tar -C "${WORKSHOP_ROOT}" -xzf - bin/kcp
19+
touch "${WORKSHOP_ROOT}/bin/.checkpoint-kcp"
20+
fi
21+
22+
if [[ ! -f "${WORKSHOP_ROOT}/bin/.checkpoint-api-syncagent" ]]; then
23+
echo "🚀 Downloading api-syncagent"
24+
curl -L "https://github.com/kcp-dev/api-syncagent/releases/download/v0.2.0-alpha.1/api-syncagent_0.2.0-alpha.1_${GOOS}_${GOARCH}.tar.gz" \
25+
| tar -C "${WORKSHOP_ROOT}/bin" -xzf - api-syncagent
26+
touch "${WORKSHOP_ROOT}/bin/.checkpoint-api-syncagent"
27+
fi
28+
29+
if [[ ! -f "${WORKSHOP_ROOT}/bin/.checkpoint-mcp-example-crd" ]]; then
30+
echo "🚀 Downloading KCP's mcp-example-crd"
31+
curl -L "https://github.com/mjudeikis/kcp-multicluster-provider-example/releases/download/v0.0.4/kcp-multicluster-provider-example_0.0.4_${GOOS}_${GOARCH}.tar.gz" \
32+
| tar -C "${WORKSHOP_ROOT}/bin" -xzf - mcp-example-crd
33+
touch "${WORKSHOP_ROOT}/bin/.checkpoint-mcp-example-crd"
34+
fi
35+
36+
if [[ ! -f "${WORKSHOP_ROOT}/bin/.checkpoint-kind" ]]; then
37+
echo "🚀 Downloading kind"
38+
curl -Lo "${WORKSHOP_ROOT}/bin/kind" "https://github.com/kubernetes-sigs/kind/releases/download/v0.27.0/kind-${GOOS}-${GOARCH}"
39+
chmod +x "${WORKSHOP_ROOT}/bin/kind"
40+
touch "${WORKSHOP_ROOT}/bin/.checkpoint-kind"
41+
fi
42+
43+
if [[ ! -f "${WORKSHOP_ROOT}/bin/.checkpoint-kubectl" ]]; then
44+
echo "🚀 Downloading kubectl"
45+
curl -Lo "${WORKSHOP_ROOT}/bin/kubectl" "https://dl.k8s.io/v1.31.7/bin/${GOOS}/${GOARCH}/kubectl"
46+
chmod +x "${WORKSHOP_ROOT}/bin/kubectl"
47+
touch "${WORKSHOP_ROOT}/bin/.checkpoint-kubectl"
48+
fi
49+
50+
if [[ ! -f "${WORKSHOP_ROOT}/bin/.checkpoint-kubectl-krew" ]]; then
51+
echo "🚀 Downloading kubectl-krew"
52+
curl -L "https://github.com/kubernetes-sigs/krew/releases/latest/download/krew-${GOOS}_${GOARCH}.tar.gz" \
53+
| tar -xzf - --strip-components=1 -C "${WORKSHOP_ROOT}/bin" "./krew-${GOOS}_${GOARCH}"
54+
mv "${WORKSHOP_ROOT}/bin/krew-${GOOS}_${GOARCH}" "${WORKSHOP_ROOT}/bin/kubectl-krew"
55+
touch "${WORKSHOP_ROOT}/bin/.checkpoint-kubectl-krew"
56+
fi
57+
58+
if [[ ! -f "${WORKSHOP_ROOT}/bin/.checkpoint-jq" ]]; then
59+
os="${GOOS}"
60+
[[ "${os}" == "darwin" ]] && os="macos"
61+
echo "🚀 Downloading jq"
62+
curl -Lo "${WORKSHOP_ROOT}/bin/jq" "https://github.com/jqlang/jq/releases/download/jq-1.7.1/jq-${os}-${GOARCH}"
63+
chmod +x "${WORKSHOP_ROOT}/bin/jq"
64+
touch "${WORKSHOP_ROOT}/bin/.checkpoint-jq"
65+
fi
66+
67+
"${EXERCISE_DIR}/99-highfive.sh"
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#!/usr/bin/env bash
2+
3+
set -o nounset
4+
set -o pipefail
5+
6+
source "$(git rev-parse --show-toplevel)/20250401-kubecon-london/workshop/lib/env.sh" "$(cd "$(dirname "$0")" && pwd)"
7+
source "${WORKSHOP_ROOT}/lib/ensure.sh"
8+
9+
function check_in_path {
10+
prog="${1}"
11+
args="${@:2}"
12+
ensure::eval_with_msg "${prog} ${args}" \
13+
"'${prog}' looks good!" \
14+
"It seems '${prog}' is not available :(\n\tTIP: Make sure it's installed and available in your \$PATH or ${WORKSHOP_ROOT}/bin."
15+
}
16+
17+
check_in_path "kcp" "--version"
18+
check_in_path "kind" "version"
19+
check_in_path "kubectl" "version --client"
20+
check_in_path "kubectl-krew" "version"
21+
check_in_path "mcp-example-crd" "-h" 2> /dev/null
22+
check_in_path "jq" "-h"
23+
24+
touch "${WORKSHOP_ROOT}/.checkpoint-00"
25+
printf "\n\t🥳 High-five! Move onto the first exercise!\n\n"
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
---
2+
title: "00: Setting up your development environment"
3+
---
4+
# Pre-requisites
5+
6+
In this chapter we'll set up our workshop-dedicated development environment.
7+
8+
## Cloning the workshop repo
9+
10+
Start by cloning the git repository we'll refer to throughout the workshop, and will be the place for the binaries, scripts and kubeconfigs we will create as we move forward.
11+
12+
Important: We will need 4 terminal windows for long running programs & interactions to the same underlaying machine during this workshop.
13+
14+
```shell
15+
git clone -b mjudeikis/kubecon.eu.workshop https://github.com/mjudeikis/kcp-contrib.git
16+
cd 20250401-kubecon-london/workshop/
17+
```
18+
19+
Now, let's see what's inside.
20+
21+
* `00-prerequisites/`
22+
* `01-deploy-kcp/`
23+
* `02-explore-workspaces/`
24+
* `03-dynamic-providers/`
25+
* `clean-all.sh`
26+
27+
Notice the exercises in directories `<Sequence number>-<Exercise name>`. These are to be visited in sequence, and to complete one, all previous exercises need to be completed first to bring the system into the desired state. While it's best if you try to follow the tasks by yourself, if you ever get stuck, you can finish an exercise by running the scripts inside the respective exercise directory.
28+
29+
Also take a note of the `clean-all.sh` script. If you ever get stuck and want to reset, run it and it will clean up and stop processes and containers used in the exercises.
30+
31+
## Get your bins
32+
33+
This one is easy. During the workshop we will make use of these programs:
34+
35+
* [kcp](https://github.com/kcp-dev/kcp/releases/latest),
36+
* kcp's [api-syncagent](https://github.com/kcp-dev/api-syncagent/releases/latest),
37+
* kcp's [multicluster-controller runtime example binary](kcp-multicluster-provider-example),
38+
* [kind](https://github.com/kubernetes-sigs/kind/releases/latest),
39+
* [kubectl](https://kubernetes.io/docs/tasks/tools/),
40+
* and, [kubectl-krew](https://krew.sigs.k8s.io/docs/user-guide/setup/install/).
41+
42+
You may visit the links, download and extract the respective binaries to a new directory called `bin/` in the workshop's root (e.g., `$WORKSHOP/bin/kubectl`). If you already have some of these installed and available in your `$PATH`, you may skip them--just make sure they are up-to-date.
43+
44+
Alternatively, we've prepared a script that does just that:
45+
46+
```shell
47+
00-prerequisites/01-install.sh
48+
```
49+
50+
If you're going the manual way, please make sure the file names are stripped of OS and arch names they may contain (e.g. `mv kubectl-krew-linux_amd64 kubectl-krew`), as we'll refer to them using their system-agnostic names later on.
51+
52+
And that's it!
53+
54+
---
55+
56+
## High-five! 🚀🚀🚀
57+
58+
Done already? High-five! Check-in your completion with:
59+
60+
```shell
61+
00-prerequisites/99-highfive.sh
62+
```
63+
64+
If there were no errors, you may continue with the next exercise.
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#!/usr/bin/env bash
2+
3+
set -o nounset
4+
set -o pipefail
5+
set -o errexit
6+
7+
source "$(git rev-parse --show-toplevel)/20250401-kubecon-london/workshop/lib/env.sh" "$(cd "$(dirname "$0")" && pwd)"
8+
9+
[[ -f "${WORKSHOP_ROOT}/.checkpoint-00" ]] || { printf "\n\t📜 You need to complete the previous exercise!\n\n" ; exit 1 ; }
10+
11+
function try_with_timeout {
12+
attempts=15
13+
while [[ "${attempts}" -gt 0 ]]; do
14+
kubectl version &> /dev/null && return
15+
sleep 5
16+
attempts=$((attempts-1))
17+
done
18+
printf "\n\t❌kcp takes too long to start, maybe something is wrong?\n"
19+
exit 1
20+
}
21+
22+
pgrep kcp &> /dev/null && { "${EXERCISE_DIR}/99-highfive.sh" ; exit $? ; }
23+
24+
cd "${WORKSHOP_ROOT}"
25+
26+
kcp start & kcp_pid=$!
27+
trap 'kill -TERM ${kcp_pid}' TERM INT EXIT
28+
export KUBECONFIG="${WORKSHOP_ROOT}/.kcp/admin.kubeconfig"
29+
try_with_timeout
30+
31+
mkdir -p "${KUBECONFIGS_DIR}"
32+
33+
cp "${WORKSHOP_ROOT}/.kcp/admin.kubeconfig" "${KUBECONFIGS_DIR}/admin.kubeconfig"
34+
cp "${WORKSHOP_ROOT}/.kcp/admin.kubeconfig" "${KUBECONFIGS_DIR}/internal-checkscript.kubeconfig"
35+
cp "${WORKSHOP_ROOT}/.kcp/admin.kubeconfig" "${KUBECONFIGS_DIR}/sync-agent.kubeconfig"
36+
cp "${WORKSHOP_ROOT}/.kcp/admin.kubeconfig" "${KUBECONFIGS_DIR}/mcp-controller.kubeconfig"
37+
38+
"${EXERCISE_DIR}/99-highfive.sh"
39+
wait "${kcp_pid}"
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#!/usr/bin/env bash
2+
3+
set -o nounset
4+
set -o pipefail
5+
6+
source "$(git rev-parse --show-toplevel)/20250401-kubecon-london/workshop/lib/env.sh" "$(cd "$(dirname "$0")" && pwd)"
7+
source "${WORKSHOP_ROOT}/lib/ensure.sh"
8+
9+
[[ -f "${WORKSHOP_ROOT}/.checkpoint-00" ]] || { printf "\n\t📜 You need to complete the previous exercise!\n\n" ; exit 1 ; }
10+
11+
ensure::process_exists "kcp"
12+
ensure::exists_in_kubeconfigs_dir "admin.kubeconfig"
13+
ensure::internal_checkscript_kubeconfig
14+
export KUBECONFIG="${KUBECONFIGS_DIR}/internal-checkscript.kubeconfig"
15+
ensure::eval_with_msg "kubectl version" "kcp is reachable!" "It seems kcp is down :("
16+
17+
touch "${WORKSHOP_ROOT}/.checkpoint-01"
18+
printf "\n\t🥳 High-five! Move onto the second exercise!\n\n"
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
---
2+
title: "01: Deploying kcp"
3+
---
4+
# Deploy kcp
5+
6+
kcp may be deployed via a [Helm chart](https://github.com/kcp-dev/helm-charts), an [operator](https://github.com/kcp-dev/helm-charts), or as a standalone process running on the host. Each of them has its uses as well as advantages and disadvantages. While the most preferable way to deploy kcp is using its dedicated operator, for the sake of simplicity, we've taken the liberty of making the choice for you :) .
7+
8+
## Starting kcp as a standalone process
9+
10+
!!! Important
11+
12+
**Attention**: during these exercises, we'll be making heavy use of environment variables. We will be switching back and forth between clusters, as well as needing access to the binaries we've set up in the previous chapter. Whenever you see this block, it means we are switching an environment. Make sure you `cd` into the workshop git repo, and copy-paste the commands to your terminal. Let's give it a try!
13+
14+
15+
!!! Important
16+
17+
=== "Bash/ZSH"
18+
19+
```shell
20+
export WORKSHOP_ROOT="$(git rev-parse --show-toplevel)/20250401-kubecon-london/workshop"
21+
export PATH="${WORKSHOP_ROOT}/bin:${PATH}"
22+
```
23+
24+
=== "Fish"
25+
26+
```fish
27+
set WORKSHOP_ROOT (git rev-parse --show-toplevel)/20250401-kubecon-london/workshop
28+
set PATH $WORKSHOP_ROOT/bin $PATH
29+
```
30+
31+
Starting kcp in standalone mode is as easy as typing `kcp start` and pressing Enter.
32+
33+
```shell
34+
cd $WORKSHOP_ROOT && kcp start
35+
```
36+
37+
38+
You should see the program running indefinitely, and outputting its logs--starting with some errors that should clean up in a couple of seconds as the different controllers start up. Leave the terminal window open, as we will keep using this kcp instance throughout the duration of the workshop. In this mode, all kcp's state is in-memory only. That means exiting the process (by, for example, pressing _Ctrl+C_ in this terminal), will lose all its etcd contents.
39+
40+
Once kcp's output seems stable, we can start making simple kubectl calls against it. `kcp start` creates a hidden directory `.kcp`, where it places its kubeconfig and the certificates.
41+
42+
Open a new terminal (termianl 2, same 01-deploy-kcp directory) now.
43+
44+
!!! Important
45+
46+
=== "Bash/ZSH"
47+
48+
```shell
49+
export WORKSHOP_ROOT="$(git rev-parse --show-toplevel)/20250401-kubecon-london/workshop"
50+
export KUBECONFIG="${WORKSHOP_ROOT}/.kcp/admin.kubeconfig"
51+
```
52+
53+
=== "Fish"
54+
55+
```fish
56+
set WORKSHOP_ROOT (git rev-parse --show-toplevel)/20250401-kubecon-london/workshop
57+
set KUBECONFIG $WORKSHOP_ROOT/.kcp/admin.kubeconfig"
58+
```
59+
60+
The following command should work now:
61+
62+
```shell-session
63+
$ kubectl version
64+
Client Version: v1.32.1
65+
Kustomize Version: v5.5.0
66+
Server Version: v1.31.0+kcp-v0.26.1
67+
```
68+
69+
We'll have a couple more kubeconfigs to switch between, and it will be convenient to have them all in one place. Let's do that now:
70+
71+
```shell
72+
mkdir -p $WORKSHOP_ROOT/kubeconfigs
73+
ln -s $KUBECONFIG $WORKSHOP_ROOT/kubeconfigs
74+
```
75+
76+
And that's it!
77+
78+
---
79+
80+
## High-five! 🚀🚀🚀
81+
82+
Finished? High-five! Check-in your completion with:
83+
84+
```shell
85+
01-deploy-kcp/99-highfive.sh
86+
```
87+
88+
If there were no errors, you may continue with the next exercise.
89+
90+
### Cheat-sheet
91+
92+
You may fast-forward through this exercise by running:
93+
* `01-deploy-kcp/01-start-kcp.sh` in a new terminal
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#!/usr/bin/env bash
2+
3+
set -o nounset
4+
set -o pipefail
5+
set -o errexit
6+
7+
source "$(git rev-parse --show-toplevel)/20250401-kubecon-london/workshop/lib/env.sh" "$(cd "$(dirname "$0")" && pwd)"
8+
9+
[[ -f "${WORKSHOP_ROOT}/.checkpoint-01" ]] || { printf "\n\t📜 You need to complete the previous exercise!\n\n" ; exit 1 ; }
10+
11+
[[ -z "$(kubectl krew index list | grep 'github.com/kcp-dev/krew-index.git')" ]] \
12+
&& kubectl krew index add kcp-dev https://github.com/kcp-dev/krew-index.git
13+
14+
kubectl krew install kcp-dev/kcp
15+
kubectl krew install kcp-dev/ws
16+
kubectl krew install kcp-dev/create-workspace
17+
18+
# IMPORTANT HACK: https://github.com/kubernetes-sigs/krew/issues/865
19+
cp $(which kubectl-create_workspace) $KREW_ROOT/bin/kubectl-create-workspace
20+
21+
printf "\n\t🥳 krew plugins installed successfully! Continue with the next step, creating provider APIs! 💪\n\n"
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#!/usr/bin/env bash
2+
3+
set -o nounset
4+
set -o pipefail
5+
set -o errexit
6+
7+
source "$(git rev-parse --show-toplevel)/20250401-kubecon-london/workshop/lib/env.sh" "$(cd "$(dirname "$0")" && pwd)"
8+
source "${WORKSHOP_ROOT}/lib/kubectl.sh"
9+
export KUBECONFIG="${KUBECONFIGS_DIR}/admin.kubeconfig"
10+
11+
[[ -f "${WORKSHOP_ROOT}/.checkpoint-01" ]] || { printf "\n\t📜 You need to complete the previous exercise!\n\n" ; exit 1 ; }
12+
13+
::kubectl::ws::use ":"
14+
15+
::kubectl::ws::create_enter "providers" "root:organization"
16+
::kubectl::ws::create_enter "cowboys" "root:universal"
17+
18+
::kubectl::create_from_file "${EXERCISE_DIR}/apis/apiresourceschema.yaml"
19+
::kubectl::create_from_file "${EXERCISE_DIR}/apis/apiexport.yaml"
20+
21+
printf "\n\t🥳 Provider APIs created successfully! Continue with the next step, creating consumers! 💪\n\n"
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#!/usr/bin/env bash
2+
3+
set -o nounset
4+
set -o pipefail
5+
set -o errexit
6+
7+
source "$(git rev-parse --show-toplevel)/20250401-kubecon-london/workshop/lib/env.sh" "$(cd "$(dirname "$0")" && pwd)"
8+
source "${WORKSHOP_ROOT}/lib/kubectl.sh"
9+
export KUBECONFIG="${KUBECONFIGS_DIR}/admin.kubeconfig"
10+
11+
[[ -f "${WORKSHOP_ROOT}/.checkpoint-01" ]] || { printf "\n\t📜 You need to complete the previous exercise!\n\n" ; exit 1 ; }
12+
13+
::kubectl::ws::use ":"
14+
15+
::kubectl::ws::create_enter "consumers" "root:organization"
16+
::kubectl::ws::create_enter "wild-west" "root:universal"
17+
::kubectl::kcp::bind_with_permission_claims "root:providers:cowboys" "cowboys" "cowboys-consumer" "configmaps.core" ""
18+
19+
::kubectl::create_from_file "${EXERCISE_DIR}/apis/consumer-wild-west.yaml"
20+
21+
::kubectl::ws::use :root:consumers
22+
::kubectl::ws::create_enter "wild-north" "root:universal"
23+
::kubectl::kcp::bind_with_permission_claims "root:providers:cowboys" "cowboys" "cowboys-consumer" "configmaps.core" ""
24+
::kubectl::create_from_file "${EXERCISE_DIR}/apis/consumer-wild-north.yaml"
25+
26+
"${EXERCISE_DIR}/99-highfive.sh"

0 commit comments

Comments
 (0)