Quickstart with kind¶
This guide walks you through deploying kcp on a kind (Kubernetes in Docker) cluster using Helm, setting up multiple workspaces, and configuring access for different teams using client certificates.
This guide covers the Helm-based deployment. A kcp-operator-based walkthrough will be added in a follow-up.
Prerequisites¶
Before starting, ensure you have the following tools installed:
- Docker
- kind
- kubectl
- Helm (v3.x)
- kubectl kcp plugin
Step 1: Create a kind Cluster¶
Create a kind cluster with port mapping for kcp access:
cat <<EOF | kind create cluster --name kcp --config=-
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
extraPortMappings:
- containerPort: 30443
hostPort: 8443
protocol: TCP
EOF
Verify the cluster is running:
Step 2: Install cert-manager¶
kcp requires cert-manager for TLS certificate management:
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.19.2/cert-manager.yaml
Wait for cert-manager to be ready:
Step 3: Configure DNS¶
For local development, add an entry to your hosts file:
Step 4: Deploy kcp with Helm¶
Add the kcp Helm repository:
Install kcp:
helm upgrade --install kcp kcp/kcp \
--namespace kcp \
--create-namespace \
--set externalHostname=kcp.local.test \
--set-string externalPort=8443 \
--set kcpFrontProxy.service.type=NodePort \
--set kcpFrontProxy.service.nodePort=30443 \
--set audit.enabled=false \
--wait
Set up host aliases so in-cluster kcp components can resolve kcp.local.test:
KCP_FRONT_PROXY_IP=$(kubectl get svc kcp-front-proxy -n kcp -o jsonpath='{.spec.clusterIP}')
helm upgrade kcp kcp/kcp \
--namespace kcp \
--reuse-values \
--set kcp.hostAliases.enabled=true \
--set "kcp.hostAliases.values[0].ip=${KCP_FRONT_PROXY_IP}" \
--set "kcp.hostAliases.values[0].hostnames[0]=kcp.local.test" \
--set kcpFrontProxy.hostAliases.enabled=true \
--set "kcpFrontProxy.hostAliases.values[0].ip=${KCP_FRONT_PROXY_IP}" \
--set "kcpFrontProxy.hostAliases.values[0].hostnames[0]=kcp.local.test" \
--wait
Verify the deployment:
All pods should reach the Running state.
Step 5: Configure Admin Access¶
Set environment variables for easier access:
Extract the CA Certificate¶
Create Admin Kubeconfig¶
kubectl --kubeconfig=admin.kubeconfig config set-cluster base \
--server https://${KCP_EXTERNAL_HOSTNAME}:${KCP_PORT}/clusters/root \
--certificate-authority=ca.crt
Generate Admin Client Certificate¶
Create a certificate for the admin user:
kubectl apply -n kcp -f - <<EOF
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: cluster-admin-client-cert
spec:
commonName: cluster-admin
issuerRef:
name: kcp-front-proxy-client-issuer
kind: Issuer
secretName: cluster-admin-client-cert
privateKey:
algorithm: RSA
size: 2048
rotationPolicy: Always
usages:
- client auth
subject:
organizations:
- system:kcp:admin
EOF
Wait for the certificate:
Extract the credentials:
kubectl get secret cluster-admin-client-cert -n kcp \
-o=jsonpath='{.data.tls\.crt}' | base64 -d > admin-client.crt
kubectl get secret cluster-admin-client-cert -n kcp \
-o=jsonpath='{.data.tls\.key}' | base64 -d > admin-client.key
Add credentials to kubeconfig:
kubectl --kubeconfig=admin.kubeconfig config set-credentials kcp-admin \
--client-certificate=admin-client.crt \
--client-key=admin-client.key
kubectl --kubeconfig=admin.kubeconfig config set-context base \
--cluster=base \
--user=kcp-admin
kubectl --kubeconfig=admin.kubeconfig config use-context base
Verify admin access:
Step 6: Create Team Workspaces¶
Create workspaces for the two teams:
kubectl create workspace team-alpha --enter
kubectl ws ..
kubectl create workspace team-beta --enter
kubectl ws :root
Note: Steps 6 through 10 can be automated using the verification script (it reads your kind kubeconfig from
~/.kube/configby default):To capture a verification log for troubleshooting or sharing with reviewers:
Verify the workspaces:
You should see:
Step 7: Generate Team Certificates¶
Create client certificates for each team with their respective groups.
These certificates are managed by cert-manager running in the underlying kind cluster.
If you exported KUBECONFIG=admin.kubeconfig, use your kind kubeconfig for the cert-manager steps:
Team Alpha¶
KUBECONFIG=${KIND_KUBECONFIG} kubectl apply -n kcp -f - <<EOF
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: team-alpha-cert
spec:
commonName: team-alpha-admin
issuerRef:
name: kcp-front-proxy-client-issuer
kind: Issuer
secretName: team-alpha-cert
privateKey:
algorithm: RSA
size: 2048
rotationPolicy: Always
usages:
- client auth
subject:
organizations:
- team-alpha
EOF
Team Beta¶
KUBECONFIG=${KIND_KUBECONFIG} kubectl apply -n kcp -f - <<EOF
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: team-beta-cert
spec:
commonName: team-beta-admin
issuerRef:
name: kcp-front-proxy-client-issuer
kind: Issuer
secretName: team-beta-cert
privateKey:
algorithm: RSA
size: 2048
rotationPolicy: Always
usages:
- client auth
subject:
organizations:
- team-beta
EOF
Wait for all certificates:
for team in alpha beta; do
KUBECONFIG=${KIND_KUBECONFIG} kubectl wait --for=condition=Ready certificate/team-${team}-cert -n kcp --timeout=60s
done
Step 8: Grant Workspace Access¶
Grant each team access to their respective workspace using RBAC.
Team Alpha Access¶
kubectl ws :root:team-alpha
kubectl apply -f - <<EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: team-alpha-admin
subjects:
- kind: Group
name: team-alpha
apiGroup: rbac.authorization.k8s.io
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
EOF
Team Beta Access¶
kubectl ws :root:team-beta
kubectl apply -f - <<EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: team-beta-admin
subjects:
- kind: Group
name: team-beta
apiGroup: rbac.authorization.k8s.io
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
EOF
Return to root workspace:
Step 9: Create Team Kubeconfigs¶
Extract team certificates and create kubeconfigs for each team.
Extract Team Certificates¶
for team in alpha beta; do
KUBECONFIG=${KIND_KUBECONFIG} kubectl get secret team-${team}-cert -n kcp \
-o=jsonpath='{.data.tls\.crt}' | base64 -d > team-${team}.crt
KUBECONFIG=${KIND_KUBECONFIG} kubectl get secret team-${team}-cert -n kcp \
-o=jsonpath='{.data.tls\.key}' | base64 -d > team-${team}.key
done
Create Team Kubeconfigs¶
for team in alpha beta; do
kubectl --kubeconfig=team-${team}.kubeconfig config set-cluster kcp \
--server https://${KCP_EXTERNAL_HOSTNAME}:${KCP_PORT}/clusters/root:team-${team} \
--certificate-authority=ca.crt
kubectl --kubeconfig=team-${team}.kubeconfig config set-credentials team-${team} \
--client-certificate=team-${team}.crt \
--client-key=team-${team}.key
kubectl --kubeconfig=team-${team}.kubeconfig config set-context team-${team} \
--cluster=kcp \
--user=team-${team}
kubectl --kubeconfig=team-${team}.kubeconfig config use-context team-${team}
done
Step 10: Verify Team Access¶
Test that each team can access their workspace and is isolated from others:
for team in alpha beta; do
echo "--- team-${team} ---"
KUBECONFIG=team-${team}.kubeconfig kubectl get namespaces
done
Create a namespace in each team workspace to confirm write access:
for team in alpha beta; do
KUBECONFIG=team-${team}.kubeconfig kubectl get namespace demo-${team} >/dev/null 2>&1 || \
KUBECONFIG=team-${team}.kubeconfig kubectl create namespace demo-${team}
KUBECONFIG=team-${team}.kubeconfig kubectl get namespace demo-${team}
done
Verify workspace isolation — each team should be denied access to other workspaces:
# Team Alpha should NOT be able to access Team Beta's workspace
KUBECONFIG=team-alpha.kubeconfig kubectl get namespaces \
--server https://${KCP_EXTERNAL_HOSTNAME}:${KCP_PORT}/clusters/root:team-beta && \
echo "ERROR: Team Alpha can access Team Beta (isolation broken)" || \
echo "OK: Team Alpha cannot access Team Beta (isolation works)"
Summary¶
You now have a fully functional kcp deployment on kind with:
- kcp deployed via Helm with TLS certificates managed by cert-manager
- 2 team workspaces: team-alpha, team-beta
- 2 client certificates: One for each team with group membership
- RBAC configuration: Each team has cluster-admin access to their workspace
Each team can independently:
- Create and manage resources in their workspace
- Deploy applications
- Configure their own RBAC policies within their workspace
Cleanup¶
To remove everything:
# Delete the kind cluster
kind delete cluster --name kcp
# Remove generated files
rm -f ca.crt admin-client.crt admin-client.key admin.kubeconfig
rm -f team-*.crt team-*.key team-*.kubeconfig
# Remove hosts entry (optional)
# macOS:
sudo sed -i '' '/kcp.local.test/d' /etc/hosts
# Linux:
# sudo sed -i '/kcp.local.test/d' /etc/hosts
Next Steps¶
- Authorization - Learn more about kcp's authorization model
- Workspaces - Deep dive into workspace concepts
- APIs - Learn how to export and bind APIs across workspaces
- Production Setup - Guidelines for production deployments