feat: new admin command with ZFS without restic nor encryption, native ZFS encryption
This commit is contained in:
parent
25cbbddebf
commit
c20da7b9ea
585
newadmin.sh
Executable file
585
newadmin.sh
Executable file
@ -0,0 +1,585 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
# Configuration
|
||||
LOCAL_TEMP_DIR="/tmp/zfs_backup"
|
||||
KEEP_FULL_SNAP_MONTHS=10
|
||||
KEEP_INCR_SNAP_MONTHS=3
|
||||
DATE=$(date +"%Y-%m-%d")
|
||||
DAY=$(date +"%d")
|
||||
DEBUG=0 # Passer à 1 pour activer le mode verbeux (-vv) pour rclone
|
||||
|
||||
PCLOUD_CREDENTIALS_FILE="/root/pcloud"
|
||||
TANG_URL="https://tang.ia86.cc"
|
||||
|
||||
mkdir -p "$LOCAL_TEMP_DIR"
|
||||
|
||||
suid()
|
||||
{
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
echo "*** Ce script nécessite des privilèges administrateur. Relance avec sudo..."
|
||||
exec sudo "$0" "$@"
|
||||
fi
|
||||
trap cleanup EXIT
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
echo "*** Effacement credentials"
|
||||
umount /mnt/usb 2>/dev/null || true
|
||||
rm -rf /mnt/usb
|
||||
rm -rf "$LOCAL_TEMP_DIR"
|
||||
rm -rf /tmp/credentials-vel
|
||||
}
|
||||
|
||||
mount_tmpfs() {
|
||||
echo "*** Montage tmpfs pour credentials"
|
||||
mkdir -p /mnt/usb
|
||||
mount -t tmpfs tmpfs /mnt/usb
|
||||
mkdir -p /mnt/usb/rclone
|
||||
}
|
||||
|
||||
encrypt_tang() {
|
||||
echo -n "$1" | clevis encrypt tang "{\"url\": \"$TANG_URL\"}" | base64 -w0
|
||||
}
|
||||
|
||||
decrypt_tang() {
|
||||
echo -n "$1" | base64 -d | clevis decrypt tang
|
||||
}
|
||||
|
||||
# Définit RCLONE_OPTS en fonction de DEBUG
|
||||
if [ "$DEBUG" -eq 1 ]; then
|
||||
RCLONE_OPTS="--checksum -vv"
|
||||
else
|
||||
RCLONE_OPTS="--checksum"
|
||||
fi
|
||||
|
||||
config() {
|
||||
read -ps "Pcloud Token : " token
|
||||
echo
|
||||
read -p "Remote Directory : " remote_dir
|
||||
|
||||
cat <<EOF > "$PCLOUD_CREDENTIALS_FILE"
|
||||
PCLOUD_TOKEN="$(encrypt_tang "$token")"
|
||||
REMOTE_DIR="$remote_dir"
|
||||
EOF
|
||||
|
||||
chmod 600 "$PCLOUD_CREDENTIALS_FILE"
|
||||
echo "*** Configuration sauvegardée dans $PCLOUD_CREDENTIALS_FILE"
|
||||
}
|
||||
|
||||
mount_rclone_conf() {
|
||||
mount_tmpfs
|
||||
|
||||
if [ ! -f "$PCLOUD_CREDENTIALS_FILE" ]; then
|
||||
echo "*** ERREUR : fichier de credentials $PCLOUD_CREDENTIALS_FILE introuvable"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
source "$PCLOUD_CREDENTIALS_FILE"
|
||||
PCLOUD_TOKEN=$(decrypt_tang "$PCLOUD_TOKEN")
|
||||
|
||||
cat <<EOF > /mnt/usb/rclone/rclone.conf
|
||||
[pcloud]
|
||||
type = pcloud
|
||||
hostname = eapi.pcloud.com
|
||||
token = {"access_token":"${PCLOUD_TOKEN}","token_type":"bearer","expiry":"0001-01-01T00:00:00Z"}
|
||||
EOF
|
||||
echo "*** rclone.conf généré"
|
||||
}
|
||||
|
||||
backup() {
|
||||
local dataset="$1"
|
||||
echo "*** Dataset: ${dataset:-TOUS}"
|
||||
mount_rclone_conf
|
||||
|
||||
if [ -z "$dataset" ]; then
|
||||
datasets_to_backup=$(zfs list -H -o name)
|
||||
else
|
||||
datasets_to_backup=("$dataset")
|
||||
fi
|
||||
|
||||
for ds in ${datasets_to_backup[@]}; do
|
||||
echo "*** Dataset: $ds"
|
||||
DATASET_SAFE_NAME=$(echo "$ds" | tr '/' '_')
|
||||
REMOTE_PATH="pcloud:${REMOTE_DIR}/$DATASET_SAFE_NAME/"
|
||||
|
||||
echo "- Détermination du type de snapshot"
|
||||
if ! rclone --config /mnt/usb/rclone/rclone.conf ls $RCLONE_OPTS "$REMOTE_PATH" | grep -q "\.zfs\.xz$"; then
|
||||
SNAPSHOT_TYPE="full"
|
||||
elif [ "$DAY" -eq "01" ]; then
|
||||
SNAPSHOT_TYPE="full"
|
||||
else
|
||||
SNAPSHOT_TYPE="incr"
|
||||
fi
|
||||
|
||||
SNAPSHOT_NAME="$ds@$DATE-$SNAPSHOT_TYPE"
|
||||
echo "- Gestion des anciens snapshots"
|
||||
if zfs list -t snapshot -H -o name | grep -q "^${SNAPSHOT_NAME}$"; then
|
||||
echo "- Suppression ancien snapshot: $SNAPSHOT_NAME"
|
||||
zfs destroy "$SNAPSHOT_NAME"
|
||||
fi
|
||||
|
||||
echo "- Création snapshot: $SNAPSHOT_NAME"
|
||||
zfs snapshot "$SNAPSHOT_NAME"
|
||||
|
||||
# Si incrémental, déterminer le snapshot précédent
|
||||
if [ "$SNAPSHOT_TYPE" = "incr" ]; then
|
||||
prev_snap=$(zfs list -t snapshot -H -o name -s creation | grep "^${ds}@" | tail -n2 | head -n1)
|
||||
echo "- Snapshot précédent pour incrémental: $prev_snap"
|
||||
fi
|
||||
|
||||
# Nom de fichier : si full => sans '-full', si incr => avec '-incr'
|
||||
if [ "$SNAPSHOT_TYPE" = "full" ]; then
|
||||
FILENAME="$DATASET_SAFE_NAME-$DATE.zfs.xz"
|
||||
else
|
||||
FILENAME="$DATASET_SAFE_NAME-$DATE-incr.zfs.xz"
|
||||
fi
|
||||
|
||||
echo "- Compression et envoi streaming"
|
||||
SHA_FILE="$LOCAL_TEMP_DIR/$FILENAME.sha256"
|
||||
|
||||
if [ "$SNAPSHOT_TYPE" = "full" ]; then
|
||||
send_cmd="zfs send --raw $SNAPSHOT_NAME"
|
||||
else
|
||||
send_cmd="zfs send --raw -i $prev_snap $SNAPSHOT_NAME"
|
||||
fi
|
||||
|
||||
echo "- $send_cmd | xz -9e | tee | rclone rcat"
|
||||
$send_cmd \
|
||||
| xz -9e \
|
||||
| tee >(
|
||||
sha256sum | awk -v fn="$FILENAME" '{print $1 " " fn}' > "$SHA_FILE"
|
||||
) \
|
||||
| rclone --config /mnt/usb/rclone/rclone.conf rcat $RCLONE_OPTS "$REMOTE_PATH$FILENAME"
|
||||
|
||||
echo "- Envoi du fichier checksum"
|
||||
rclone --config /mnt/usb/rclone/rclone.conf rcat $RCLONE_OPTS "$REMOTE_PATH$FILENAME.sha256" < "$SHA_FILE"
|
||||
rm -f "$SHA_FILE"
|
||||
|
||||
echo "- Montage temporaire et génération du fichier .list"
|
||||
MOUNT_DIR="/mnt/tmp_snapshot"
|
||||
mkdir -p "$MOUNT_DIR"
|
||||
# Monte temporairement le snapshot en lecture seule
|
||||
mount -t zfs "$SNAPSHOT_NAME" "$MOUNT_DIR" -o ro
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "*** ERREUR : impossible de monter le snapshot $SNAPSHOT_NAME"
|
||||
exit 1
|
||||
fi
|
||||
# Génère la liste des fichiers avec taille, date et chemin complet
|
||||
LIST_FILE="$LOCAL_TEMP_DIR/$FILENAME.list"
|
||||
find "$MOUNT_DIR" -printf "%P\t%s\t%TY-%Tm-%Td %TH:%TM:%TS\n" > "$LIST_FILE"
|
||||
# Démonte le snapshot après utilisation
|
||||
umount "$MOUNT_DIR"
|
||||
echo "- Envoi du fichier .list"
|
||||
rclone --config /mnt/usb/rclone/rclone.conf copy $RCLONE_OPTS "$LIST_FILE" "$REMOTE_PATH"
|
||||
rm -f "$LIST_FILE"
|
||||
done
|
||||
echo "*** Backup terminé"
|
||||
}
|
||||
|
||||
check() {
|
||||
local dataset="$1"
|
||||
|
||||
echo "*** Début vérification: ${dataset:-TOUS}"
|
||||
mount_rclone_conf
|
||||
|
||||
ALL_FILE="$LOCAL_TEMP_DIR/ALL.sha256"
|
||||
mkdir -p "$LOCAL_TEMP_DIR/check"
|
||||
echo "" > "$ALL_FILE"
|
||||
|
||||
if [ -z "$dataset" ]; then
|
||||
for dir in $(rclone --config /mnt/usb/rclone/rclone.conf lsf $RCLONE_OPTS "pcloud:${REMOTE_DIR}" --dirs-only); do
|
||||
dir_name="${dir%/}"
|
||||
echo "*** Dataset: $dir_name"
|
||||
DATASET_PATH="pcloud:${REMOTE_DIR}/$dir_name/"
|
||||
tmpdir="$LOCAL_TEMP_DIR/check/$dir_name"
|
||||
mkdir -p "$tmpdir"
|
||||
|
||||
echo "- Téléchargement .sha256 pour dataset $dir_name"
|
||||
rclone --config /mnt/usb/rclone/rclone.conf copy $RCLONE_OPTS "$DATASET_PATH" "$tmpdir" --include "*.sha256"
|
||||
|
||||
echo "- Ajout au fichier ALL.sha256"
|
||||
for f in "$tmpdir"/*.sha256; do
|
||||
sed "s# # $dir_name/#" "$f" >> "$ALL_FILE"
|
||||
done
|
||||
done
|
||||
echo "*** Exécution rclone checksum pour tous les chemins listés dans ALL.sha256"
|
||||
rclone --config /mnt/usb/rclone/rclone.conf checksum $RCLONE_OPTS sha256 "$ALL_FILE" "pcloud:${REMOTE_DIR}" --exclude "*.sha256" --exclude "*.list"
|
||||
else
|
||||
echo "*** Dataset: $dataset"
|
||||
DATASET_SAFE_NAME=$(echo "$dataset" | tr '/' '_')
|
||||
DATASET_PATH="pcloud:${REMOTE_DIR}/$DATASET_SAFE_NAME/"
|
||||
tmpdir="$LOCAL_TEMP_DIR/check/$DATASET_SAFE_NAME"
|
||||
mkdir -p "$tmpdir"
|
||||
|
||||
echo "- Téléchargement .sha256 pour dataset $DATASET_SAFE_NAME"
|
||||
rclone --config /mnt/usb/rclone/rclone.conf copy $RCLONE_OPTS "$DATASET_PATH" "$tmpdir" --include "*.sha256"
|
||||
|
||||
echo "- Ajout au fichier ALL.sha256"
|
||||
for f in "$tmpdir"/*.sha256; do
|
||||
cat "$f" >> "$ALL_FILE"
|
||||
done
|
||||
echo "*** Exécution rclone checksum pour tous les chemins listés dans ALL.sha256"
|
||||
rclone --config /mnt/usb/rclone/rclone.conf checksum $RCLONE_OPTS sha256 "$ALL_FILE" "pcloud:${REMOTE_DIR}/${DATASET_SAFE_NAME}" --include "*.xz"
|
||||
fi
|
||||
echo "*** Vérification terminée"
|
||||
}
|
||||
|
||||
view() {
|
||||
echo "*** Lecture du répertoire distant ${REMOTE_DIR} via ncdu"
|
||||
mount_rclone_conf
|
||||
rclone --config /mnt/usb/rclone/rclone.conf ncdu $RCLONE_OPTS "pcloud:${REMOTE_DIR}"
|
||||
}
|
||||
|
||||
install() {
|
||||
echo "*** Installation dépendances"
|
||||
apt update
|
||||
apt install -y rclone zfsutils-linux xz-utils clevis tang ncdu
|
||||
echo "*** Installation terminée"
|
||||
}
|
||||
|
||||
restore() {
|
||||
dataset="$1"
|
||||
newdataset="$2"
|
||||
|
||||
[ -z "$dataset" ] && { echo "*** ERROR: Dataset required"; exit 1; }
|
||||
mount_rclone_conf
|
||||
|
||||
DATASET_SAFE_NAME=$(echo "$dataset" | tr '/' '_')
|
||||
REMOTE_PATH="pcloud:${REMOTE_DIR}/$DATASET_SAFE_NAME/"
|
||||
|
||||
files=( $(rclone --config /mnt/usb/rclone/rclone.conf lsf "$REMOTE_PATH" | grep '\.zfs\.xz$') )
|
||||
|
||||
if [ ${#files[@]} -eq 0 ]; then
|
||||
echo "*** ERROR: No backups found at $REMOTE_PATH"; exit 1
|
||||
fi
|
||||
|
||||
full_files=( $(printf "%s\n" "${files[@]}" | grep -v '\-incr\.zfs\.xz$') )
|
||||
|
||||
if [ ${#full_files[@]} -eq 0 ]; then
|
||||
echo "*** ERROR: No full backups found."; exit 1
|
||||
fi
|
||||
|
||||
preferred_full=$(printf "%s\n" "${full_files[@]}" | sort | tail -n1)
|
||||
|
||||
#echo "- Restoring from full backup: $preferred_full"
|
||||
|
||||
# Remove descendants and snapshots
|
||||
zfs destroy -r "${newdataset:-$dataset}" || true
|
||||
|
||||
#rclone --config /mnt/usb/rclone/rclone.conf copy "$REMOTE_PATH$preferred_full" "$LOCAL_TEMP_DIR"
|
||||
#rclone --config /mnt/usb/rclone/rclone.conf copy "$REMOTE_PATH${preferred_full}.sha256" "$LOCAL_TEMP_DIR"
|
||||
|
||||
#(cd "$LOCAL_TEMP_DIR" && sha256sum -c "${preferred_full}.sha256") || { echo "*** ERROR: Checksum failed."; exit 1; }
|
||||
|
||||
#xz -d < "$LOCAL_TEMP_DIR/$preferred_full" | zfs receive "${newdataset:-$dataset}"
|
||||
|
||||
#rm -f "$LOCAL_TEMP_DIR/$preferred_full" "$LOCAL_TEMP_DIR/${preferred_full}.sha256"
|
||||
|
||||
# Incrementals
|
||||
incr_files=( $(printf "%s\n" "${files[@]}" | grep '\-incr\.zfs\.xz$' | sort) )
|
||||
|
||||
for inc in "${incr_files[@]}"; do
|
||||
echo "- Applying incremental: $inc"
|
||||
rclone --config /mnt/usb/rclone/rclone.conf copy "$REMOTE_PATH$inc" "$LOCAL_TEMP_DIR"
|
||||
rclone --config /mnt/usb/rclone/rclone.conf copy "$REMOTE_PATH${inc}.sha256" "$LOCAL_TEMP_DIR"
|
||||
|
||||
(cd "$LOCAL_TEMP_DIR" && sha256sum -c "${inc}.sha256") || { echo "*** ERROR: Incremental checksum failed."; exit 1; }
|
||||
|
||||
xz -d < "$LOCAL_TEMP_DIR/$inc" | zfs receive -F "${newdataset:-$dataset}"
|
||||
|
||||
rm -f "$LOCAL_TEMP_DIR/$inc" "$LOCAL_TEMP_DIR/${inc}.sha256"
|
||||
done
|
||||
#echo "*** Activate key location"
|
||||
#zfs set keylocation=file:///root/key "${newdataset:-$dataset}"
|
||||
#zfs load-key "${newdataset:-$dataset}"
|
||||
|
||||
echo "*** Restoration completed successfully."
|
||||
}
|
||||
|
||||
prune() {
|
||||
mount_rclone_conf
|
||||
echo "*** Nettoyage snapshots obsolètes"
|
||||
zfs list -t snapshot -H -o name | grep "^${ds}@" | while read old_snap; do
|
||||
SNAP_DATE=$(echo "$old_snap" | cut -d'@' -f2 | cut -d'-' -f1-3)
|
||||
SNAP_TYPE=$(echo "$old_snap" | grep -oE '(full|incr)$')
|
||||
RETENTION_MONTHS=$KEEP_INCR_SNAP_MONTHS
|
||||
[ "$SNAP_TYPE" = "full" ] && RETENTION_MONTHS=$KEEP_FULL_SNAP_MONTHS
|
||||
|
||||
if [[ "$(date -d "$SNAP_DATE" +%s)" -lt "$(date -d "$RETENTION_MONTHS months ago" +%s)" ]]; then
|
||||
echo "- Suppression ancien snapshot: $old_snap"
|
||||
zfs destroy "$old_snap"
|
||||
fi
|
||||
done
|
||||
datasets=$(zfs list -H -o name)
|
||||
for ds in ${datasets[@]}; do
|
||||
echo "*** Pruning dataset: $ds"
|
||||
DATASET_SAFE_NAME=$(echo "$ds" | tr '/' '_')
|
||||
REMOTE_PATH="pcloud:${REMOTE_DIR}/$DATASET_SAFE_NAME/"
|
||||
|
||||
# Snapshot pruning
|
||||
zfs list -t snapshot -H -o name | grep "^${ds}@" | while read old_snap; do
|
||||
SNAP_DATE=$(echo "$old_snap" | cut -d'@' -f2 | cut -d'-' -f1-3)
|
||||
SNAP_TYPE=$(echo "$old_snap" | grep -oE '(full|incr)$')
|
||||
|
||||
RETENTION_MONTHS=$KEEP_INCR_SNAP_MONTHS
|
||||
[ "$SNAP_TYPE" = "full" ] && RETENTION_MONTHS=$KEEP_FULL_SNAP_MONTHS
|
||||
|
||||
if [[ "$(date -d "$SNAP_DATE" +%s)" -lt "$(date -d "$RETENTION_MONTHS months ago" +%s)" ]]; then
|
||||
echo "- Removing old snapshot: $old_snap"
|
||||
zfs destroy "$old_snap"
|
||||
|
||||
# Determine corresponding remote filename
|
||||
if [ "$SNAP_TYPE" = "incr" ]; then
|
||||
FILE_DATE_SUFFIX="$SNAP_DATE-incr"
|
||||
else
|
||||
FILE_DATE_SUFFIX="$SNAP_DATE"
|
||||
fi
|
||||
|
||||
FILENAME="$DATASET_SAFE_NAME-$FILE_DATE_SUFFIX.zfs.xz"
|
||||
echo "- Removing remote backup file: $FILENAME"
|
||||
rclone deletefile --config /mnt/usb/rclone/rclone.conf $RCLONE_OPTS "$REMOTE_PATH$FILENAME"
|
||||
|
||||
# Remove the checksum file as well
|
||||
echo "- Removing remote checksum file: $FILENAME.sha256"
|
||||
rclone deletefile --config /mnt/usb/rclone/rclone.conf $RCLONE_OPTS "$REMOTE_PATH$FILENAME.sha256"
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
echo "*** Pruning completed"
|
||||
}
|
||||
|
||||
pv_info() {
|
||||
dataset=$1
|
||||
pvc_name=$(echo "$dataset" | grep -o "pvc-[a-z0-9-]*")
|
||||
echo "🔍 PVC detected: $pvc_name"
|
||||
all=$(kubectl get pv "$pvc_name" -o jsonpath='{.spec.claimRef.namespace}/{.spec.claimRef.name}')
|
||||
pvc_name=$(echo "$all"|cut -d"/" -f2)
|
||||
pvc_namespace=$(echo "$all"|cut -d"/" -f1)
|
||||
echo "📌 Associated PV: $pvc_name"
|
||||
echo "📌 PVC Namespace: $pvc_namespace"
|
||||
echo "🔎 Workloads using PVC:"
|
||||
kubectl get pods,statefulset,deployment,replicaset -n "$pvc_namespace" -o jsonpath='{range .items[*]}{.kind}/{.metadata.name}{"\n"}{end}' | while read resource; do
|
||||
volumes=$(kubectl get "$resource" -n "$pvc_namespace" -o json | jq '.spec.volumes[].persistentVolumeClaim.claimName' -r 2>/dev/null)
|
||||
if [[ "$volumes" =~ "$pvc_name" ]]; then
|
||||
count=$(kubectl get "$resource" -n "$pvc_namespace" -o jsonpath='{.spec.replicas}')
|
||||
echo "📦 $resource (instances: ${count:-1})"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
save_state() {
|
||||
NAMESPACE="$1"
|
||||
STATE_FILE="./${NAMESPACE}.state"
|
||||
|
||||
echo "🔍 Saving state to $STATE_FILE"
|
||||
:> "$STATE_FILE"
|
||||
|
||||
kubectl get deployment,statefulset,replicaset -n "$NAMESPACE" -o jsonpath='{range .items[*]}{.kind}/{.metadata.name}{" "}{.spec.replicas}{"\n"}{end}' >> "$STATE_FILE" || true
|
||||
|
||||
kubectl get sgcluster -n "$NAMESPACE" -o jsonpath='{range .items[*]}sgcluster/{.metadata.name}{" "}{.spec.instances}{"\n"}{end}' >> "$STATE_FILE" || true
|
||||
|
||||
echo "✅ State saved."
|
||||
}
|
||||
|
||||
scale_down() {
|
||||
NAMESPACE="$1"
|
||||
STATE_FILE="./${NAMESPACE}.state"
|
||||
|
||||
if [ -f "$STATE_FILE" ]; then
|
||||
echo "❌ State file $STATE_FILE already exist. Abort."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
save_state "$NAMESPACE"
|
||||
|
||||
while read kind_full replicas; do
|
||||
kind=$(echo "$kind_full" | cut -d'/' -f1 | tr '[:upper:]' '[:lower:]')
|
||||
name=$(echo "$kind_full" | cut -d'/' -f2)
|
||||
echo "🛑 Scaling down $kind/$name from $replicas replicas"
|
||||
|
||||
if [ "$kind" == "sgcluster" ]; then
|
||||
kubectl patch sgcluster "$name" -n "$NAMESPACE" --type merge -p '{"spec":{"instances":0}}'
|
||||
else
|
||||
kubectl scale "$kind" "$name" -n "$NAMESPACE" --replicas=0
|
||||
fi
|
||||
done < "$STATE_FILE"
|
||||
|
||||
echo "✅ Scaled down successfully."
|
||||
}
|
||||
|
||||
scale_up() {
|
||||
NAMESPACE="$1"
|
||||
STATE_FILE="./${NAMESPACE}.state"
|
||||
|
||||
if [ ! -f "$STATE_FILE" ]; then
|
||||
echo "❌ State file $STATE_FILE not found. Abort."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
while read kind_full replicas; do
|
||||
kind=$(echo "$kind_full" | cut -d'/' -f1 | tr '[:upper:]' '[:lower:]')
|
||||
name=$(echo "$kind_full" | cut -d'/' -f2)
|
||||
|
||||
if [ -z "$replicas" ]; then
|
||||
echo "⚠️ No replicas count found for $kind/$name. Skipping..."
|
||||
continue
|
||||
fi
|
||||
|
||||
echo "🚀 Scaling up $kind/$name to $replicas replicas"
|
||||
|
||||
if [ "$kind" == "sgcluster" ]; then
|
||||
kubectl patch sgcluster "$name" -n "$NAMESPACE" --type merge -p "{\"spec\":{\"instances\":$replicas}}"
|
||||
else
|
||||
kubectl scale "$kind" "$name" -n "$NAMESPACE" --replicas="$replicas"
|
||||
fi
|
||||
|
||||
done < "$STATE_FILE"
|
||||
|
||||
rm "$STATE_FILE"
|
||||
echo "✅ Scaled up successfully and state removed."
|
||||
}
|
||||
|
||||
function veleroapp()
|
||||
{
|
||||
case "$1" in
|
||||
init)
|
||||
trap cleanup EXIT
|
||||
read -p "👣 MinIO url (with http/s) : " PATH_MINIO
|
||||
read -p "👣 Bucket name:: " BUCKET
|
||||
read -p "🔑 MinIO Access Key: " ACCESS_KEY
|
||||
read -sp "🔒 MinIO Secret Key: " SECRET_KEY
|
||||
cat <<EOF > /tmp/credentials-vel
|
||||
[default]
|
||||
aws_access_key_id=${ACCESS_KEY}
|
||||
aws_secret_access_key=${SECRET_KEY}
|
||||
EOF
|
||||
echo ""
|
||||
if [[ ! -f /usr/local/bin/velero ]]; then
|
||||
echo "🔍 Velero non trouvé, téléchargement et installation de v1.16.0…"
|
||||
wget -q https://github.com/vmware-tanzu/velero/releases/download/v1.16.0/velero-v1.16.0-linux-amd64.tar.gz
|
||||
tar -xzf velero-v1.16.0-linux-amd64.tar.gz
|
||||
chmod +x velero-v1.16.0-linux-amd64/velero
|
||||
sudo chown root:root velero-v1.16.0-linux-amd64/velero
|
||||
sudo mv velero-v1.16.0-linux-amd64/velero /usr/local/bin/velero
|
||||
rm -rf velero-v1.16.0-linux-amd64 velero-v1.16.0-linux-amd64.tar.gz
|
||||
echo "✅ Velero installé."
|
||||
else
|
||||
echo "✅ Velero déjà présent, version : $(velero version --client-only | head -n1)"
|
||||
fi
|
||||
echo "▶️ Déploiement Velero dans le cluster…"
|
||||
velero install \
|
||||
--provider aws \
|
||||
--plugins velero/velero-plugin-for-aws:v1.10.0,openebs/velero-plugin:3.6.0 \
|
||||
--features=EnableCSI \
|
||||
--use-node-agent \
|
||||
--bucket ${BUCKET} \
|
||||
--backup-location-config region=us-east-1,s3ForcePathStyle="true",s3Url=${PATH_MINIO},checksumAlgorithm="" \
|
||||
--snapshot-location-config region=us-east-1 \
|
||||
--secret-file /tmp/credentials-vel \
|
||||
--uploader-type kopia \
|
||||
--kubeconfig /home/user/.kube/config \
|
||||
|| echo "ℹ️ Velero est peut-être déjà installé dans le cluster."
|
||||
echo "🎉 Script terminé."
|
||||
;;
|
||||
uninstall)
|
||||
velero uninstall --kubeconfig /home/user/.kube/config
|
||||
;;
|
||||
backup)
|
||||
NOW=$(date +"%Y%m%d-%H%M")
|
||||
velero backup create backup-complet-cluster2-${NOW} \
|
||||
--include-namespaces '*' \
|
||||
--include-resources '*' \
|
||||
--include-cluster-resources=true \
|
||||
--kubeconfig /home/user/.kube/config \
|
||||
--default-volumes-to-fs-backup
|
||||
echo "${NOW}" > /var/log/lastfilename
|
||||
;;
|
||||
info)
|
||||
velero backup describe $2 --kubeconfig /home/user/.kube/config
|
||||
;;
|
||||
restore)
|
||||
BACKUP_NAME="$2"
|
||||
read -p "Are you sure you want to restore from backup '$BACKUP_NAME'? [y/N] " confirm
|
||||
case "$confirm" in
|
||||
[Yy]* )
|
||||
echo "▶️ Restoring from backup '$BACKUP_NAME'…"
|
||||
velero restore create --from-backup "$BACKUP_NAME" \
|
||||
--include-namespaces '*' \
|
||||
--include-resources '*' \
|
||||
--include-cluster-resources=true \
|
||||
--kubeconfig /home/user/.kube/config \
|
||||
--restore-volumes \
|
||||
;;
|
||||
* )
|
||||
echo "❌ Restore aborted."
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
echo "Usage: admin velero [init|backup|restore|info ] [dataname]"
|
||||
echo ""
|
||||
echo "Use the velero backend to make some kubernetes backup operations"
|
||||
echo ""
|
||||
echo "init - initialize the data storage on kubernetes"
|
||||
echo "uninstall - uninstall velero on kubernetes"
|
||||
echo "backup - backup the kubernetes objects"
|
||||
echo "restore - restore [dataname] backup on kubernetes"
|
||||
echo "info - get informations about [dataname]"
|
||||
echo ""
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Ajouter le case "prune"
|
||||
case "$1" in
|
||||
install)
|
||||
suid $@
|
||||
install
|
||||
;;
|
||||
config)
|
||||
suid $@
|
||||
config
|
||||
;;
|
||||
backup)
|
||||
suid $@
|
||||
backup "$2"
|
||||
;;
|
||||
restore)
|
||||
suid $@
|
||||
restore "$2" "$3"
|
||||
;;
|
||||
check)
|
||||
suid $@
|
||||
check "$2"
|
||||
;;
|
||||
view)
|
||||
suid $@
|
||||
view
|
||||
;;
|
||||
prune)
|
||||
suid $@
|
||||
prune
|
||||
;;
|
||||
test)
|
||||
pv_info "$2"
|
||||
;;
|
||||
state)
|
||||
save_state "$2"
|
||||
;;
|
||||
down)
|
||||
scale_down "$2"
|
||||
;;
|
||||
up)
|
||||
scale_up "$2"
|
||||
;;
|
||||
velero)
|
||||
veleroapp $2 $3 $4
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 {install|config|backup [dataset]|restore dataset [newdataset]|check [dataset]|view|prune}"
|
||||
echo "Usage: $0 {test <dataset>|state <namespace>|down <namespace>|up <namespace>}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
Loading…
x
Reference in New Issue
Block a user