Initial commit.
This commit is contained in:
commit
840bd2e12a
10 changed files with 322 additions and 0 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
dummyhttp-secret.yaml
|
||||||
|
dummyhttp-sealed-secret.yaml
|
4
README.md
Normal file
4
README.md
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
# vCluster
|
||||||
|
|
||||||
|
This repository contains scripts and templates to test `vcluster` on a `k3d` cluster (we are going to use the one
|
||||||
|
created for this [post](https://blogops.mixinet.net/posts/gitops/argocd-autopilot/)).
|
33
apps/dummyhttp/kustomization.yaml
Normal file
33
apps/dummyhttp/kustomization.yaml
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
resources:
|
||||||
|
- https://forgejo.mixinet.net/blogops/argocd-applications.git//dummyhttp/?ref=dummyhttp-v1.0.0
|
||||||
|
# Add the config map
|
||||||
|
configMapGenerator:
|
||||||
|
- name: dummyhttp-configmap
|
||||||
|
literals:
|
||||||
|
- CM_VAR="Vcluster Test Value"
|
||||||
|
behavior: create
|
||||||
|
options:
|
||||||
|
disableNameSuffixHash: true
|
||||||
|
patches:
|
||||||
|
# Change the ingress host name
|
||||||
|
- target:
|
||||||
|
kind: Ingress
|
||||||
|
name: dummyhttp
|
||||||
|
patch: |-
|
||||||
|
- op: replace
|
||||||
|
path: /spec/rules/0/host
|
||||||
|
value: vcluster-dummyhttp.lo.mixinet.net
|
||||||
|
# Add reloader annotations -- it will only work if we install reloader on the
|
||||||
|
# virtual cluster, as the one on the host cluster doesn't see the vcluster
|
||||||
|
# deployment objects
|
||||||
|
- target:
|
||||||
|
kind: Deployment
|
||||||
|
name: dummyhttp
|
||||||
|
patch: |-
|
||||||
|
- op: add
|
||||||
|
path: /metadata/annotations
|
||||||
|
value:
|
||||||
|
reloader.stakater.com/auto: "true"
|
||||||
|
reloader.stakater.com/rollout-strategy: "restart"
|
17
apps/reloader/kustomization.yaml
Normal file
17
apps/reloader/kustomization.yaml
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
namespace: kube-system
|
||||||
|
resources:
|
||||||
|
- github.com/stakater/Reloader/deployments/kubernetes/?ref=v1.4.2
|
||||||
|
patches:
|
||||||
|
# Add flags to reload workloads when ConfigMaps or Secrets are created or deleted
|
||||||
|
- target:
|
||||||
|
kind: Deployment
|
||||||
|
name: reloader-reloader
|
||||||
|
patch: |-
|
||||||
|
- op: add
|
||||||
|
path: /spec/template/spec/containers/0/args
|
||||||
|
value:
|
||||||
|
- '--reload-on-create=true'
|
||||||
|
- '--reload-on-delete=true'
|
||||||
|
- '--reload-strategy=annotations'
|
37
bin/arkade-install.sh
Executable file
37
bin/arkade-install.sh
Executable file
|
@ -0,0 +1,37 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# TOOLS LIST
|
||||||
|
ARKADE_APPS="kubectl vcluster"
|
||||||
|
|
||||||
|
# Add the arkade binary directory to the path if missing
|
||||||
|
case ":${PATH}:" in
|
||||||
|
*:"${HOME}/.arkade/bin":*) ;;
|
||||||
|
*) export PATH="${PATH}:${HOME}/.arkade/bin" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Install or update arkade
|
||||||
|
if command -v arkade >/dev/null; then
|
||||||
|
echo "Trying to update the arkade application"
|
||||||
|
sudo arkade update
|
||||||
|
else
|
||||||
|
echo "Installing the arkade application"
|
||||||
|
curl -sLS https://get.arkade.dev | sudo sh
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Installing tools with arkade"
|
||||||
|
echo ""
|
||||||
|
for app in $ARKADE_APPS; do
|
||||||
|
app_path="$(command -v $app)" || true
|
||||||
|
if [ "$app_path" ]; then
|
||||||
|
echo "The application '$app' already available on '$app_path'"
|
||||||
|
else
|
||||||
|
arkade get "$app"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
cat <<EOF
|
||||||
|
|
||||||
|
Add the ~/.arkade/bin directory to your PATH if tools have been installed there
|
||||||
|
|
||||||
|
EOF
|
75
bin/create-vcluster.sh
Executable file
75
bin/create-vcluster.sh
Executable file
|
@ -0,0 +1,75 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# VARIABLES
|
||||||
|
# Relative PATH to the workdir from the script directory
|
||||||
|
WORK_DIR_RELPATH="../vcluster"
|
||||||
|
|
||||||
|
# Compute WORKDIR
|
||||||
|
SCRIPT="$(readlink -f "$0")"
|
||||||
|
SCRIPT_DIR="$(dirname "$SCRIPT")"
|
||||||
|
WORK_DIR="$(readlink -f "$SCRIPT_DIR/$WORK_DIR_RELPATH")"
|
||||||
|
|
||||||
|
# Update the PATH to add the arkade bin directory
|
||||||
|
# Add the arkade binary directory to the path if missing
|
||||||
|
case ":${PATH}:" in
|
||||||
|
*:"${HOME}/.arkade/bin":*) ;;
|
||||||
|
*) export PATH="${PATH}:${HOME}/.arkade/bin" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Go to the working directory
|
||||||
|
cd "$WORK_DIR" || exit 1
|
||||||
|
|
||||||
|
echo "=> Creating or updating the vcluster"
|
||||||
|
vcluster create my-vcluster --namespace my-vcluster --upgrade --connect=false \
|
||||||
|
--values vcluster.yaml
|
||||||
|
|
||||||
|
echo "=> Adding a traefik ingress route tcp to the vcluster api"
|
||||||
|
kubectl apply -f ingress_route_tcp.yaml
|
||||||
|
|
||||||
|
echo "=> Exporting vcluster kubeconfig"
|
||||||
|
tries="0"
|
||||||
|
while true; do
|
||||||
|
if kubectl get -n my-vcluster secret/my-vcluster-kubeconfig >/dev/null 2>&1; then
|
||||||
|
# Dump the kubeconfig if available
|
||||||
|
kubectl get -n my-vcluster secret/my-vcluster-kubeconfig \
|
||||||
|
--template="{{.data.config}}" | base64 -d > ~/.kube/my-vcluster-config
|
||||||
|
echo "KubeConfig dumped to '~/.kube/my-vcluster-config'"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
tries="$((tries + 1))"
|
||||||
|
echo "KubeConfig not avaliable after attempt '$tries'"
|
||||||
|
if [ "$tries" -lt "10" ]; then
|
||||||
|
sleep 5
|
||||||
|
else
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ "$tries" -eq "10" ]; then
|
||||||
|
echo "=> Failed to get the vcluster kubeconfig, try again"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
cat <<EOF
|
||||||
|
=> NOTE
|
||||||
|
Overwrite the KUBECONFIG variable to access the vcluster with 'kubectl':
|
||||||
|
|
||||||
|
KUBECONFIG=~/.kube/my-vcluster-config kubectl
|
||||||
|
|
||||||
|
You can define the following 'vkubectl' alias to make it easier:
|
||||||
|
|
||||||
|
alias vkubectl="KUBECONFIG=~/.kube/my-vcluster-config kubectl"
|
||||||
|
|
||||||
|
Or you can merge it with the one on the KUBECONFIG variable and use 'kubectx' or
|
||||||
|
a similar tool to change the context (for our vcluster the context will be
|
||||||
|
'my-vcluster_k3d-argocd').
|
||||||
|
|
||||||
|
If your KUBECONFIG variable is defined and only has the path to a single file
|
||||||
|
you can merge it with the vcluster config running the following:
|
||||||
|
|
||||||
|
KUBECONFIG="\$KUBECONFIG:~/.kube/my-vcluster-config" \\
|
||||||
|
kubectl config view --flatten > "\$KUBECONFIG.new";
|
||||||
|
mv "\$KUBECONFIG.new" "\$KUBECONFIG"
|
||||||
|
EOF
|
30
bin/install-vcluster-apps.sh
Executable file
30
bin/install-vcluster-apps.sh
Executable file
|
@ -0,0 +1,30 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Applications to install
|
||||||
|
APPS="dummyhttp reloader"
|
||||||
|
|
||||||
|
# Relative PATH to the workdir from the script directory
|
||||||
|
WORK_DIR_RELPATH="../apps"
|
||||||
|
|
||||||
|
# Compute WORKDIR
|
||||||
|
SCRIPT="$(readlink -f "$0")"
|
||||||
|
SCRIPT_DIR="$(dirname "$SCRIPT")"
|
||||||
|
WORK_DIR="$(readlink -f "$SCRIPT_DIR/$WORK_DIR_RELPATH")"
|
||||||
|
|
||||||
|
# Update the PATH to add the arkade bin directory
|
||||||
|
# Add the arkade binary directory to the path if missing
|
||||||
|
case ":${PATH}:" in
|
||||||
|
*:"${HOME}/.arkade/bin":*) ;;
|
||||||
|
*) export PATH="${PATH}:${HOME}/.arkade/bin" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Go to the working directory
|
||||||
|
cd "$WORK_DIR" || exit 1
|
||||||
|
|
||||||
|
for app in $APPS; do
|
||||||
|
echo "=> Deploying the '$app' application"
|
||||||
|
kustomize build "$app" | \
|
||||||
|
KUBECONFIG=~/.kube/my-vcluster-config kubectl apply -f -
|
||||||
|
done
|
78
bin/vcluster-dummyhttp-secret.sh
Executable file
78
bin/vcluster-dummyhttp-secret.sh
Executable file
|
@ -0,0 +1,78 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# VARIABLES
|
||||||
|
SECRET_VALUE="${*:-Vcluster Boo}"
|
||||||
|
SECRET_CONTEXT="k3d-argocd"
|
||||||
|
SECRET_NAME="dummyhttp-secret"
|
||||||
|
SECRET_NAMESPACE="my-vcluster-default"
|
||||||
|
|
||||||
|
# Relative PATH to the workdir from the script directory
|
||||||
|
WORK_DIR_RELPATH="../"
|
||||||
|
|
||||||
|
# Compute WORKDIR
|
||||||
|
SCRIPT="$(readlink -f "$0")"
|
||||||
|
SCRIPT_DIR="$(dirname "$SCRIPT")"
|
||||||
|
WORK_DIR="$(readlink -f "$SCRIPT_DIR/$WORK_DIR_RELPATH")"
|
||||||
|
|
||||||
|
# Update the PATH to add the arkade bin directory
|
||||||
|
# Add the arkade binary directory to the path if missing
|
||||||
|
case ":${PATH}:" in
|
||||||
|
*:"${HOME}/.arkade/bin":*) ;;
|
||||||
|
*) export PATH="${PATH}:${HOME}/.arkade/bin" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Go to the working directory
|
||||||
|
cd "$WORK_DIR" || exit 1
|
||||||
|
|
||||||
|
echo "=> Checking if the '$SECRET_NAMESPACE' is available"
|
||||||
|
if kubectl get namespace "$SECRET_NAMESPACE" >/dev/null 2>&1; then
|
||||||
|
echo "The '$SECRET_NAMESPACE' namespace already exists"
|
||||||
|
else
|
||||||
|
kubectl create namespace "$SECRET_NAMESPACE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "=> Creating secret file with SECRET_VAR = '$SECRET_VALUE'"
|
||||||
|
echo -n "$SECRET_VALUE" | \
|
||||||
|
kubectl create secret generic "$SECRET_NAME" --namespace "$SECRET_NAMESPACE" \
|
||||||
|
--dry-run=client --from-file=SECRET_VAR=/dev/stdin -o yaml \
|
||||||
|
>dummyhttp-secret.yaml
|
||||||
|
|
||||||
|
echo "=> Creating sealed secret on file"
|
||||||
|
kubeseal --context "$SECRET_CONTEXT" -f dummyhttp-secret.yaml \
|
||||||
|
-w dummyhttp-sealed-secret.yaml
|
||||||
|
|
||||||
|
rm -f dummyhttp-secret.yaml
|
||||||
|
|
||||||
|
echo "=> Adding or updating sealed secret on '$SECRET_NAMESPACE' namespace"
|
||||||
|
kubectl apply --context "$SECRET_CONTEXT" -f dummyhttp-sealed-secret.yaml
|
||||||
|
|
||||||
|
rm -f dummyhttp-sealed-secret.yaml
|
||||||
|
|
||||||
|
tries="0"
|
||||||
|
while true; do
|
||||||
|
if kubectl get --context "$SECRET_CONTEXT" --namespace "$SECRET_NAMESPACE" \
|
||||||
|
secret/dummyhttp-secret >/dev/null 2>&1; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
tries="$((tries+1))"
|
||||||
|
echo "Secret not avaliable after attempt '$tries'"
|
||||||
|
if [ "$tries" -lt "10" ]; then
|
||||||
|
sleep 2
|
||||||
|
else
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ "$tries" -eq "10" ]; then
|
||||||
|
echo "Failed to get 'dummyhttp-secret', something dind't work as expected"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
SECRET_VAR="$(
|
||||||
|
kubectl get --context "$SECRET_CONTEXT" --namespace "$SECRET_NAMESPACE" \
|
||||||
|
secret/dummyhttp-secret --template="{{.data.SECRET_VAR}}" | base64 -d
|
||||||
|
)"
|
||||||
|
|
||||||
|
echo "=> Found secret/dummyhttp-secret: SECRET_VAR = '$SECRET_VAR'"
|
15
vcluster/ingress_route_tcp.yaml
Normal file
15
vcluster/ingress_route_tcp.yaml
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
apiVersion: traefik.containo.us/v1alpha1
|
||||||
|
kind: IngressRouteTCP
|
||||||
|
metadata:
|
||||||
|
name: my-vcluster-api
|
||||||
|
namespace: my-vcluster
|
||||||
|
spec:
|
||||||
|
entryPoints:
|
||||||
|
- websecure
|
||||||
|
routes:
|
||||||
|
- match: HostSNI(`my-vcluster-api.lo.mixinet.net`)
|
||||||
|
services:
|
||||||
|
- name: my-vcluster
|
||||||
|
port: 443
|
||||||
|
tls:
|
||||||
|
passthrough: true
|
31
vcluster/vcluster.yaml
Normal file
31
vcluster/vcluster.yaml
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
controlPlane:
|
||||||
|
proxy:
|
||||||
|
# Extra hostnames to sign the vCluster proxy certificate for
|
||||||
|
extraSANs:
|
||||||
|
- my-vcluster-api.lo.mixinet.net
|
||||||
|
exportKubeConfig:
|
||||||
|
context: my-vcluster_k3d-argocd
|
||||||
|
server: https://my-vcluster-api.lo.mixinet.net:8443
|
||||||
|
secret:
|
||||||
|
name: my-vcluster-kubeconfig
|
||||||
|
sync:
|
||||||
|
toHost:
|
||||||
|
ingresses:
|
||||||
|
enabled: true
|
||||||
|
serviceAccounts:
|
||||||
|
enabled: true
|
||||||
|
fromHost:
|
||||||
|
ingressClasses:
|
||||||
|
enabled: true
|
||||||
|
nodes:
|
||||||
|
enabled: true
|
||||||
|
clearImageStatus: true
|
||||||
|
secrets:
|
||||||
|
enabled: true
|
||||||
|
mappings:
|
||||||
|
byName:
|
||||||
|
# Sync all Secrets from the 'my-vcluster-default' namespace to the
|
||||||
|
# virtual 'default' namespace.
|
||||||
|
"my-vcluster-default/*": "default/*"
|
||||||
|
# We could add other namespace mappings if needed, i.e.:
|
||||||
|
# "my-vcluster-kube-system/*": "kube-system/*"
|
Loading…
Add table
Add a link
Reference in a new issue