--- apiVersion: v1 kind: ServiceAccount metadata: name: gitea-runner-rebalancer namespace: gitea --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: gitea-runner-rebalancer namespace: gitea rules: - apiGroups: - "" resources: - pods verbs: - get - list - delete --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: gitea-runner-rebalancer namespace: gitea roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: gitea-runner-rebalancer subjects: - kind: ServiceAccount name: gitea-runner-rebalancer namespace: gitea --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: gitea-runner-rebalancer rules: - apiGroups: - "" resources: - nodes resourceNames: - ai.tail2fe2d.ts.net verbs: - get --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: gitea-runner-rebalancer roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: gitea-runner-rebalancer subjects: - kind: ServiceAccount name: gitea-runner-rebalancer namespace: gitea --- apiVersion: batch/v1 kind: CronJob metadata: name: gitea-runner-rebalancer namespace: gitea spec: schedule: "*/2 * * * *" concurrencyPolicy: Forbid successfulJobsHistoryLimit: 1 failedJobsHistoryLimit: 3 jobTemplate: spec: ttlSecondsAfterFinished: 300 template: metadata: labels: app: gitea-runner-rebalancer spec: serviceAccountName: gitea-runner-rebalancer restartPolicy: Never containers: - name: rebalance image: bitnami/kubectl:latest imagePullPolicy: IfNotPresent command: - /bin/sh - -ec - | target_node="ai.tail2fe2d.ts.net" ready="$( kubectl get node "${target_node}" \ -o jsonpath='{range .status.conditions[?(@.type=="Ready")]}{.status}{end}' )" if [ "${ready}" != "True" ]; then echo "${target_node} is not Ready; keeping the runner on its current node" exit 0 fi runner_pod="$( kubectl -n gitea get pods \ -l app=gitea-runner \ --field-selector=status.phase=Running \ -o jsonpath='{.items[0].metadata.name}' )" runner_node="$( kubectl -n gitea get pods \ -l app=gitea-runner \ --field-selector=status.phase=Running \ -o jsonpath='{.items[0].spec.nodeName}' )" if [ -z "${runner_pod}" ] || [ -z "${runner_node}" ]; then echo "No running Gitea runner found" exit 0 fi if [ "${runner_node}" = "${target_node}" ]; then echo "${runner_pod} already runs on ${target_node}" exit 0 fi echo "Moving ${runner_pod} from ${runner_node} to preferred node ${target_node}" kubectl -n gitea delete pod "${runner_pod}" --wait=false