From ba4e1fce421534a3fe0933c12c8832011a16d9e5 Mon Sep 17 00:00:00 2001 From: Thomas Riegler Date: Thu, 13 Jun 2024 14:35:48 +0200 Subject: [PATCH] Added instructions on how to use official CloudRetro image with mounted game --- scripts/cloudretro-custom/README.md | 4 + .../cloudretro-setup-coordinator.yaml | 74 +++++++++++++++ .../cloudretro-setup-workers.yaml | 91 +++++++++++++++++++ .../cloudretro-stunner-cleanup.yaml | 25 +++++ .../cloudretro-custom/coordinator-config.sh | 35 +++++++ scripts/cloudretro-custom/init.sh | 72 +++++++++++++++ scripts/cloudretro-custom/kind-config.yaml | 7 ++ .../metallb-config-template.yaml | 14 +++ scripts/cloudretro-custom/metallb-config.yaml | 14 +++ .../cloudretro-custom/stunner-gateway.yaml | 35 +++++++ scripts/cloudretro-custom/stunner-gwcc.yaml | 24 +++++ .../stunner-setup-for-cloudretro.sh | 41 +++++++++ scripts/cloudretro-custom/worker-config.sh | 20 ++++ 13 files changed, 456 insertions(+) create mode 100644 scripts/cloudretro-custom/README.md create mode 100644 scripts/cloudretro-custom/cloudretro-setup-coordinator.yaml create mode 100644 scripts/cloudretro-custom/cloudretro-setup-workers.yaml create mode 100644 scripts/cloudretro-custom/cloudretro-stunner-cleanup.yaml create mode 100755 scripts/cloudretro-custom/coordinator-config.sh create mode 100755 scripts/cloudretro-custom/init.sh create mode 100644 scripts/cloudretro-custom/kind-config.yaml create mode 100644 scripts/cloudretro-custom/metallb-config-template.yaml create mode 100644 scripts/cloudretro-custom/metallb-config.yaml create mode 100644 scripts/cloudretro-custom/stunner-gateway.yaml create mode 100644 scripts/cloudretro-custom/stunner-gwcc.yaml create mode 100644 scripts/cloudretro-custom/stunner-setup-for-cloudretro.sh create mode 100755 scripts/cloudretro-custom/worker-config.sh diff --git a/scripts/cloudretro-custom/README.md b/scripts/cloudretro-custom/README.md new file mode 100644 index 0000000..e07d6f9 --- /dev/null +++ b/scripts/cloudretro-custom/README.md @@ -0,0 +1,4 @@ +# How to mount games into a CloudRetro instance +We are using the image `ghcr.io/giongto35/cloud-game/cloud-game:v3.0.5` (see https://github.com/giongto35/cloud-game/tree/v3.0.5). +You can use the image as the old image, but you have to additionally mount the game file into `/usr/local/share/cloud-game/assets/games`. +It may be useful to set `CLOUD_GAME_WORKER_DEBUG` and `CLOUD_GAME_COORDINATOR_DEBUG` to true. Furthermore, `CLOUD_GAME_WEBRTC_LOGLEVEL=-1` gives trace level logs for WebRTC. \ No newline at end of file diff --git a/scripts/cloudretro-custom/cloudretro-setup-coordinator.yaml b/scripts/cloudretro-custom/cloudretro-setup-coordinator.yaml new file mode 100644 index 0000000..5d60314 --- /dev/null +++ b/scripts/cloudretro-custom/cloudretro-setup-coordinator.yaml @@ -0,0 +1,74 @@ +# +# +# The following yaml script will install a cloud-retro setup in your Kubernetes cluster +# with the needed services. With an invalid configuration of course, for this to properly work +# You need the apply-config.sh minimalistic shell script to update the config with the unclear addresses. +# +# +# In short, no touching. +# +apiVersion: v1 +kind: Namespace +metadata: + name: cloudretro +--- +# Configmap for Coordinator +apiVersion: v1 +kind: ConfigMap +metadata: + name: cloudretro-config-c + namespace: cloudretro + labels: + app: coordinator +data: + CLOUD_GAME_COORDINATOR_DEBUG: "false" + CLOUD_GAME_WEBRTC_LOGLEVEL: "6" +--- +# Coordinator deployment +apiVersion: apps/v1 +kind: Deployment +metadata: + name: coordinator-deployment + namespace: cloudretro +spec: + replicas: 1 + selector: + matchLabels: + app: coordinator + template: + metadata: + labels: + app: coordinator + spec: + containers: + - name: coordinator + image: ghcr.io/giongto35/cloud-game/cloud-game:v3.0.5 + envFrom: + - configMapRef: + name: cloudretro-config-c + command: ["./coordinator"] + ports: + - containerPort: 8000 + volumeMounts: + - name: game-mount + mountPath: '/usr/local/share/cloud-game/assets/games/anguna.gba' + volumes: + - name: game-mount + hostPath: + path: '/games/anguna.gba' + type: File +--- +# Coordinator LoadBalancer for HTTP +apiVersion: v1 +kind: Service +metadata: + name: coordinator-lb-svc + namespace: cloudretro +spec: + selector: + app: coordinator + ports: + - port: 8000 + targetPort: 8000 + #nodePort: 30001 + type: LoadBalancer \ No newline at end of file diff --git a/scripts/cloudretro-custom/cloudretro-setup-workers.yaml b/scripts/cloudretro-custom/cloudretro-setup-workers.yaml new file mode 100644 index 0000000..408368d --- /dev/null +++ b/scripts/cloudretro-custom/cloudretro-setup-workers.yaml @@ -0,0 +1,91 @@ +# +# +# The following yaml script will install a cloud-retro setup in your Kubernetes cluster +# with the needed services. With an invalid configuration of course, for this to properly work +# You need the apply-config.sh minimalistic shell script to update the config with the unclear addresses. +# +# Please not that this will only install the workers. For them to work, you will need a coordinator deployment as well. +# +# In short, no touching. +# +apiVersion: v1 +kind: Namespace +metadata: + name: cloudretro +--- +# Configmap for Worker +apiVersion: v1 +kind: ConfigMap +metadata: + name: cloudretro-config-w + namespace: cloudretro + labels: + app: worker +data: + CLOUD_GAME_WORKER_DEBUG: "false" + CLOUD_GAME_WEBRTC_LOGLEVEL: "6" +--- +# Worker deployment +apiVersion: apps/v1 +kind: Deployment +metadata: + name: worker-deployment + namespace: cloudretro +spec: + replicas: 2 + selector: + matchLabels: + app: worker + template: + metadata: + labels: + app: worker + spec: + containers: + - name: worker + image: ghcr.io/giongto35/cloud-game/cloud-game:v3.0.5 + envFrom: + - configMapRef: + name: cloudretro-config-w + command: ["./worker"] + ports: + - containerPort: 9000 + - containerPort: 8443 + volumeMounts: + - name: game-mount + mountPath: '/usr/local/share/cloud-game/assets/games/anguna.gba' + volumes: + - name: game-mount + hostPath: + path: '/games/anguna.gba' + type: File +--- +# Worker LoadBalancer for HTTP +apiVersion: v1 +kind: Service +metadata: + name: worker-lb-svc + namespace: cloudretro +spec: + selector: + app: worker + ports: + - port: 9000 + targetPort: 9000 + #nodePort: 30002 + type: LoadBalancer +--- +# Worker ClusterIP for STUNner forwarding +apiVersion: v1 +kind: Service +metadata: + name: worker-ci-udp-svc + namespace: cloudretro +spec: + selector: + app: worker + ports: + - protocol: UDP + port: 8443 + targetPort: 8443 + type: ClusterIP \ No newline at end of file diff --git a/scripts/cloudretro-custom/cloudretro-stunner-cleanup.yaml b/scripts/cloudretro-custom/cloudretro-stunner-cleanup.yaml new file mode 100644 index 0000000..ddd5fbc --- /dev/null +++ b/scripts/cloudretro-custom/cloudretro-stunner-cleanup.yaml @@ -0,0 +1,25 @@ +# Script for the required STUNner components for CloudRetro +apiVersion: gateway.networking.k8s.io/v1 +kind: Gateway +metadata: + name: udp-gateway + namespace: stunner +spec: + gatewayClassName: stunner-gatewayclass + listeners: + - name: udp-listener + port: 3478 + protocol: TURN-UDP +--- +apiVersion: stunner.l7mp.io/v1 +kind: UDPRoute +metadata: + name: worker-udp-route + namespace: stunner +spec: + parentRefs: + - name: udp-gateway + rules: + - backendRefs: + - name: worker-ci-udp-svc + namespace: cloudretro diff --git a/scripts/cloudretro-custom/coordinator-config.sh b/scripts/cloudretro-custom/coordinator-config.sh new file mode 100755 index 0000000..80f6fa8 --- /dev/null +++ b/scripts/cloudretro-custom/coordinator-config.sh @@ -0,0 +1,35 @@ +#!/bin/bash +# +# Shellscript for patching multicluster coordinator configmap with additional ICE-server addresses +# +primary_context=$1 +secondary_context=$2 +if [ $# -eq 0 ] +then + primary_context=$(kubectl config current-context) + secondary_context=$(kubectl config current-context) +fi +max=10 +raw=$(kubectl get configmap -n cloudretro cloudretro-config-c -o yaml --context $primary_context) +for i in `seq 0 $max` +do + s="CLOUD_GAME_WEBRTC_ICESERVERS_$(echo $i)_URL" + c=$(echo $raw | grep $s) + if [ -z "$c" ] + then + contextnumber=$i + break + fi +done + +username=$(kubectl get gatewayconfig -n stunner stunner-gatewayconfig -o jsonpath='{.spec.userName}' --context $secondary_context) +credential=$(kubectl get gatewayconfig -n stunner stunner-gatewayconfig -o jsonpath='{.spec.password}' --context $secondary_context) +gwip=$(kubectl get service -n stunner udp-gateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}' --context $secondary_context) + +kubectl patch configmap -n cloudretro cloudretro-config-c --context $primary_context --patch-file=/dev/stdin <<-EOF +data: + CLOUD_GAME_WEBRTC_ICESERVERS_$(echo $contextnumber)_CREDENTIAL: $(echo $credential) + CLOUD_GAME_WEBRTC_ICESERVERS_$(echo $contextnumber)_URLS: turn:$(echo $gwip):3478 + CLOUD_GAME_WEBRTC_ICESERVERS_$(echo $contextnumber)_USERNAME: $(echo $username) +EOF +kubectl rollout restart deployment -n cloudretro coordinator-deployment --context $primary_context \ No newline at end of file diff --git a/scripts/cloudretro-custom/init.sh b/scripts/cloudretro-custom/init.sh new file mode 100755 index 0000000..1635255 --- /dev/null +++ b/scripts/cloudretro-custom/init.sh @@ -0,0 +1,72 @@ +#!/bin/bash + +set -e + +kind delete cluster +kind create cluster --config kind-config.yaml + +kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.14.4/config/manifests/metallb-native.yaml +{ grep -q "controller"; kill $!; } < <(kubectl get pod -w -n metallb-system) +kubectl wait --namespace metallb-system \ + --for=condition=ready pod \ + --selector=app=metallb \ + --timeout=90s +lb_subnet=$(docker network inspect kind --format '{{json .}}' | jq -r '.IPAM.Config[0].Subnet') + +# Extract the base IP and calculate the range start and end +# This example assumes the subnet is in CIDR notation e.g., 172.20.0.0/16 +IFS='/' read -r base_ip cidr <<< "$lb_subnet" +IFS='.' read -r ip1 ip2 ip3 ip4 <<< "$base_ip" + +echo "Using $base_ip/$_cidr subnet for MetalLB" + +# Example calculation: Use the .10.1 for start and .10.50 for the end of the range +# This is a simplistic calculation that might not suit all subnets or requirements +range_start="${ip1}.${ip2}.10.1" +range_end="${ip1}.${ip2}.10.50" + +# Combine them into the range string expected by MetalLB +RANGE="${range_start}-${range_end}" +export RANGE + +# Prepare your YAML file with the ${RANGE} placeholder and use envsubst +envsubst < metallb-config-template.yaml | kubectl apply -f - + +# Apply the YAML file +#kubectl apply -f metallb-config.yaml + +helm repo add stunner https://l7mp.io/stunner +helm repo update +#disable errors +set +e +helm install stunner-gateway-operator stunner/stunner-gateway-operator --create-namespace --namespace=stunner +set -e + + + +kubectl apply -f stunner-gateway.yaml +kubectl apply -f stunner-gwcc.yaml + + +kubectl apply -f cloudretro-setup-coordinator.yaml +kubectl apply -f cloudretro-setup-workers.yaml + +printf "\nStart cloudretro: \n" + +kubectl wait --namespace cloudretro --for=condition=available --timeout=600s deployment/coordinator-deployment deployment/worker-deployment +while ! kubectl get svc coordinator-lb-svc -n cloudretro -o jsonpath='{.status.loadBalancer.ingress[0].ip}' | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$'; do + echo "Waiting for coordinator LoadBalancer IP..." + sleep 10 +done +echo "Coordinator LoadBalancer IP is ready." + +./worker-config.sh + +{ grep -q "udp"; kill $!; } < <(kubectl get service -w -n stunner) + +./coordinator-config.sh + +# print the external IP +EXTERNAL_IP=$(kubectl get service -n cloudretro coordinator-lb-svc -o jsonpath='{.status.loadBalancer.ingress[0].ip}') + +printf "\nCloudRetro is ready to use. Access the coordinator at http://${EXTERNAL_IP}:8000\n" diff --git a/scripts/cloudretro-custom/kind-config.yaml b/scripts/cloudretro-custom/kind-config.yaml new file mode 100644 index 0000000..75651da --- /dev/null +++ b/scripts/cloudretro-custom/kind-config.yaml @@ -0,0 +1,7 @@ +apiVersion: kind.x-k8s.io/v1alpha4 +kind: Cluster +nodes: + - role: control-plane + extraMounts: + - hostPath: /home/user/CloudRetro/assets/games + containerPath: /games diff --git a/scripts/cloudretro-custom/metallb-config-template.yaml b/scripts/cloudretro-custom/metallb-config-template.yaml new file mode 100644 index 0000000..97dd9b8 --- /dev/null +++ b/scripts/cloudretro-custom/metallb-config-template.yaml @@ -0,0 +1,14 @@ +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: example + namespace: metallb-system +spec: + addresses: + - ${RANGE} +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system \ No newline at end of file diff --git a/scripts/cloudretro-custom/metallb-config.yaml b/scripts/cloudretro-custom/metallb-config.yaml new file mode 100644 index 0000000..c013bcc --- /dev/null +++ b/scripts/cloudretro-custom/metallb-config.yaml @@ -0,0 +1,14 @@ +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: example + namespace: metallb-system +spec: + addresses: + - 172.20.10.1-172.20.10.50 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system \ No newline at end of file diff --git a/scripts/cloudretro-custom/stunner-gateway.yaml b/scripts/cloudretro-custom/stunner-gateway.yaml new file mode 100644 index 0000000..05263b8 --- /dev/null +++ b/scripts/cloudretro-custom/stunner-gateway.yaml @@ -0,0 +1,35 @@ +apiVersion: gateway.networking.k8s.io/v1 +kind: Gateway +metadata: + name: udp-gateway + namespace: stunner +spec: + gatewayClassName: stunner-gatewayclass + listeners: + - name: udp-listener + port: 3478 + protocol: TURN-UDP +--- +apiVersion: stunner.l7mp.io/v1 +kind: UDPRoute +metadata: + name: worker-udp-route + namespace: stunner +spec: + parentRefs: + - name: udp-gateway + rules: + - backendRefs: + - name: worker-ci-udp-svc + namespace: cloudretro +--- +apiVersion: stunner.l7mp.io/v1 +kind: GatewayConfig +metadata: + name: stunner-gatewayconfig + namespace: stunner +spec: + realm: stunner.l7mp.io + authType: static + userName: "user-1" + password: "pass-1" diff --git a/scripts/cloudretro-custom/stunner-gwcc.yaml b/scripts/cloudretro-custom/stunner-gwcc.yaml new file mode 100644 index 0000000..23c5ec1 --- /dev/null +++ b/scripts/cloudretro-custom/stunner-gwcc.yaml @@ -0,0 +1,24 @@ +# Required STUNner components +apiVersion: gateway.networking.k8s.io/v1 +kind: GatewayClass +metadata: + name: stunner-gatewayclass +spec: + controllerName: "stunner.l7mp.io/gateway-operator" + parametersRef: + group: "stunner.l7mp.io" + kind: GatewayConfig + name: stunner-gatewayconfig + namespace: stunner + description: "STUNner is a WebRTC ingress gateway for Kubernetes" +--- +apiVersion: stunner.l7mp.io/v1 +kind: GatewayConfig +metadata: + name: stunner-gatewayconfig + namespace: stunner +spec: + realm: stunner.l7mp.io + authType: static + userName: "user-1" + password: "pass-1" diff --git a/scripts/cloudretro-custom/stunner-setup-for-cloudretro.sh b/scripts/cloudretro-custom/stunner-setup-for-cloudretro.sh new file mode 100644 index 0000000..4b7a2ad --- /dev/null +++ b/scripts/cloudretro-custom/stunner-setup-for-cloudretro.sh @@ -0,0 +1,41 @@ +#!/bin/bash +# +# Script used to install all the needed STUNner components on a secondary cluster in a multicluster CLoudRetro setup +# +kcontext="--kube-context $(echo $1)" +context="--context $(echo $1)" +if [ -z "$1" ] +then + context= + kcontext= +fi +helm install stunner-gateway-operator stunner/stunner-gateway-operator --create-namespace --namespace stunner $kcontext +helm install stunner stunner/stunner --namespace stunner $kcontext +kubectl apply -f stunner-gwcc.yaml $context +kubectl apply $context -f - <