|
| 1 | +#!/usr/bin/env bash |
| 2 | + |
| 3 | +# Copyright 2025 The Kubernetes Authors. |
| 4 | +# |
| 5 | +# Licensed under the Apache License, Version 2.0 (the "License"); |
| 6 | +# you may not use this file except in compliance with the License. |
| 7 | +# You may obtain a copy of the License at |
| 8 | +# |
| 9 | +# http://www.apache.org/licenses/LICENSE-2.0 |
| 10 | +# |
| 11 | +# Unless required by applicable law or agreed to in writing, software |
| 12 | +# distributed under the License is distributed on an "AS IS" BASIS, |
| 13 | +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 14 | +# See the License for the specific language governing permissions and |
| 15 | +# limitations under the License. |
| 16 | + |
| 17 | + |
| 18 | +# This script installs a local Kind cluster with a local container registry and the correct files |
| 19 | +# mounted for using CAPK to test Cluster API. |
| 20 | +# The default Kind CNI is disabled because it doesn't work CAPK. Instead, Calico is used. |
| 21 | +# MetalLB is used as a local layer 2 load balancer to support exposing the API servers of workload |
| 22 | +# clusters on the local machine that's running this script. |
| 23 | + |
| 24 | +set -o errexit |
| 25 | +set -o nounset |
| 26 | +set -o pipefail |
| 27 | + |
| 28 | +CALICO_VERSION=${CAPI_CALICO_VERSION:-"v3.29.1"} |
| 29 | +METALLB_VERSION=${CAPI_METALLB_VERSION:-""} |
| 30 | +# Set manually for non-Docker runtimes - example: "172.20" |
| 31 | +METALLB_IP_PREFIX=${CAPI_METALLB_IP_PREFIX:-""} |
| 32 | +KUBEVIRT_VERSION=${CAPI_KUBEVIRT_VERSION:-""} |
| 33 | +# Required to support pulling KubeVirt container disk images from private registries as well as |
| 34 | +# avoid Docker Hub rate limiting |
| 35 | +KIND_DOCKER_CONFIG_PATH=${CAPI_KIND_DOCKER_CONFIG_PATH:-"$HOME/.docker/config.json"} |
| 36 | + |
| 37 | +# Deploy Kind cluster |
| 38 | +KIND_CLUSTER_CONFIG="$(cat <<EOF |
| 39 | +kind: Cluster |
| 40 | +apiVersion: kind.x-k8s.io/v1alpha4 |
| 41 | +networking: |
| 42 | + disableDefaultCNI: true |
| 43 | +nodes: |
| 44 | +- role: control-plane |
| 45 | + extraMounts: |
| 46 | + - containerPath: /var/lib/kubelet/config.json |
| 47 | + hostPath: ${KIND_DOCKER_CONFIG_PATH} |
| 48 | +containerdConfigPatches: |
| 49 | +- |- |
| 50 | + [plugins."io.containerd.grpc.v1.cri".registry] |
| 51 | + config_path = "/etc/containerd/certs.d" |
| 52 | +EOF |
| 53 | +)" |
| 54 | +export KIND_CLUSTER_CONFIG |
| 55 | + |
| 56 | +"$(dirname "${BASH_SOURCE[0]}")/kind-install.sh" |
| 57 | + |
| 58 | +# Deploy Calico |
| 59 | +kubectl apply -f \ |
| 60 | + "https://raw.githubusercontent.com/projectcalico/calico/${CALICO_VERSION}/manifests/calico.yaml" |
| 61 | + |
| 62 | +# Deploy MetalLB |
| 63 | +if [[ -z "$METALLB_VERSION" ]]; then |
| 64 | + METALLB_VERSION=$(curl "https://api.github.com/repos/metallb/metallb/releases/latest" \ |
| 65 | + | jq -r ".tag_name") |
| 66 | +fi |
| 67 | + |
| 68 | +kubectl apply -f \ |
| 69 | + "https://raw.githubusercontent.com/metallb/metallb/${METALLB_VERSION}/config/manifests/metallb-native.yaml" |
| 70 | + |
| 71 | +echo "Waiting for controller pod to be created..." |
| 72 | +while [[ -z $(kubectl -n metallb-system get pods \ |
| 73 | + -l app=metallb,component=controller -o jsonpath="{.items[0].metadata.name}" 2>/dev/null) ]]; do |
| 74 | + sleep 2 |
| 75 | +done |
| 76 | +echo "Pod created!" |
| 77 | + |
| 78 | +echo "Waiting for speaker pod to be created..." |
| 79 | +while [[ -z $(kubectl -n metallb-system get pods \ |
| 80 | + -l app=metallb,component=speaker -o jsonpath="{.items[0].metadata.name}" 2>/dev/null) ]]; do |
| 81 | + sleep 2 |
| 82 | +done |
| 83 | +echo "Pod created!" |
| 84 | + |
| 85 | +echo "Waiting for pods to become ready..." |
| 86 | +kubectl wait pods -n metallb-system \ |
| 87 | + -l app=metallb,component=controller --for=condition=Ready --timeout=10m |
| 88 | +kubectl wait pods -n metallb-system \ |
| 89 | + -l app=metallb,component=speaker --for=condition=Ready --timeout=2m |
| 90 | +echo "Pods ready!" |
| 91 | + |
| 92 | +if [[ -z "$METALLB_IP_PREFIX" ]]; then |
| 93 | + SUBNET=$(docker network inspect \ |
| 94 | + -f '{{range .IPAM.Config}}{{if .Gateway}}{{.Subnet}}{{end}}{{end}}' kind) |
| 95 | + METALLB_IP_PREFIX=$(echo "$SUBNET" | sed -E 's|^([0-9]+\.[0-9]+)\..*$|\1|g') |
| 96 | +fi |
| 97 | + |
| 98 | +cat <<EOF | kubectl apply -f - |
| 99 | +apiVersion: metallb.io/v1beta1 |
| 100 | +kind: IPAddressPool |
| 101 | +metadata: |
| 102 | + name: capi-ip-pool |
| 103 | + namespace: metallb-system |
| 104 | +spec: |
| 105 | + addresses: |
| 106 | + - ${METALLB_IP_PREFIX}.255.200-${METALLB_IP_PREFIX}.255.250 |
| 107 | +--- |
| 108 | +apiVersion: metallb.io/v1beta1 |
| 109 | +kind: L2Advertisement |
| 110 | +metadata: |
| 111 | + name: empty |
| 112 | + namespace: metallb-system |
| 113 | +EOF |
| 114 | + |
| 115 | +# Deploy KubeVirt |
| 116 | +if [[ -z "$KUBEVIRT_VERSION" ]]; then |
| 117 | + KUBEVIRT_VERSION=$(curl "https://api.github.com/repos/kubevirt/kubevirt/releases/latest" \ |
| 118 | + | jq -r ".tag_name") |
| 119 | +fi |
| 120 | +kubectl apply -f \ |
| 121 | + "https://github.com/kubevirt/kubevirt/releases/download/${KUBEVIRT_VERSION}/kubevirt-operator.yaml" |
| 122 | +kubectl apply -f \ |
| 123 | + "https://github.com/kubevirt/kubevirt/releases/download/${KUBEVIRT_VERSION}/kubevirt-cr.yaml" |
| 124 | +echo "Waiting for KubeVirt to become ready..." |
| 125 | +kubectl wait -n kubevirt kv kubevirt --for=condition=Available --timeout=10m |
| 126 | +echo "KubeVirt ready!" |
0 commit comments