init
This commit is contained in:
Executable
+87
@@ -0,0 +1,87 @@
|
||||
#!/bin/bash
|
||||
# Первый шаг переноса инстанса на другой куб (DST, по умолчанию loop-3): секреты + перепривязка в визоре.
|
||||
# loopctl k8s rebind loop12a40f770b5a
|
||||
# Источник = куб из SOURCES, где есть CR; провайдер БД в визоре ищется по host:port из секрета.
|
||||
# Не делает: sync, гашение на исходном кубе, DNS (это loopctl k8s move).
|
||||
set -euo pipefail
|
||||
|
||||
ID=${1:?loop id, например loop12a40f770b5a}
|
||||
. "$(dirname "$0")/../lib/common.sh"
|
||||
|
||||
copy_secret() { # $1 имя; копирует с $SRC на $DST без вывода данных
|
||||
kubectl --context "$SRC" -n loop get secret "$1" -o json \
|
||||
| jq '{apiVersion,kind,type,data,metadata:{name:.metadata.name,namespace:"loop"}}' \
|
||||
| kubectl --context "$DST" apply -f - >/dev/null
|
||||
echo " $1 скопирован"
|
||||
}
|
||||
|
||||
hash_secrets() { # $1 context
|
||||
kubectl --context "$1" -n loop get secret "$ID-db-credentials" "$ID-s3-credentials" "$ID-license" -o json \
|
||||
| jq -S '[.items[]|{n:.metadata.name,t:.type,d:.data}]' | shasum | cut -c1-12
|
||||
}
|
||||
|
||||
echo "== $ID"
|
||||
# источник = куб, где есть CR (registry неактуален); домен из ingress CR
|
||||
for SRC in $SOURCES ""; do
|
||||
[ -n "$SRC" ] || { echo "CR $ID не найден ни на одном исходном кубе"; exit 1; }
|
||||
DOMAIN=$(kubectl --context "$SRC" -n loop get mattermost "$ID" -o jsonpath='{.spec.ingress.host}' 2>/dev/null) && [ -n "$DOMAIN" ] && break
|
||||
done
|
||||
SRC_CLUSTER=$(echo "select id from cluster_instance where name='$SRC';" | vsql)
|
||||
DST_CLUSTER=$(echo "select id from cluster_instance where name='$DST';" | vsql)
|
||||
[ -n "$DST_CLUSTER" ] || { echo "в визоре нет кластера $DST"; exit 1; }
|
||||
echo " $DOMAIN $SRC"
|
||||
|
||||
# база в секрете на исходном кубе уже должна смотреть в Selectel
|
||||
DBHOST=$(kubectl --context "$SRC" -n loop get secret "$ID-db-credentials" -o json | jq -r '.data.DB_CONNECTION_STRING|@base64d' | sed -E 's#.*@([^/]+)/.*#\1#')
|
||||
echo " БД в секрете: $DBHOST"
|
||||
case $DBHOST in *.mdb.yandexcloud.net*) echo "секрет ещё смотрит в Yandex, стоп"; exit 1;; esac
|
||||
|
||||
# CR с таким именем на $DST быть не должно
|
||||
if kubectl --context "$DST" -n loop get mattermost "$ID" >/dev/null 2>&1; then echo "CR уже есть на $DST, стоп"; exit 1; fi
|
||||
|
||||
# провайдер БД = ON_PREM-провайдер визора с тем же host:port, что в секрете
|
||||
PROVIDER=$(echo "select id||'|'||name from database_provider where vendor='ON_PREM' and host_name='${DBHOST%:*}' and host_port::text='${DBHOST##*:}';" | vsql)
|
||||
[ "$(grep -c . <<<"$PROVIDER")" = 1 ] || { echo "в визоре не один ON_PREM-провайдер для $DBHOST: '$PROVIDER'"; exit 1; }
|
||||
TARGET=${PROVIDER#*|}; PROVIDER=${PROVIDER%%|*}; echo " провайдер: $TARGET"
|
||||
|
||||
confirm "Скопирую секреты $ID на $DST и перепривяжу инстанс в визоре на $DST." || exit 1
|
||||
echo "-- секреты на $DST"
|
||||
for s in wildcard-loop.ru-tls private.docker.wilix.dev; do # общие, копируем один раз
|
||||
kubectl --context "$DST" -n loop get secret "$s" >/dev/null 2>&1 || copy_secret "$s"
|
||||
done
|
||||
for s in db-credentials s3-credentials license; do copy_secret "$ID-$s"; done
|
||||
H1=$(hash_secrets "$SRC"); H3=$(hash_secrets "$DST")
|
||||
[ "$H1" = "$H3" ] || { echo "секреты не совпали: $H1 / $H3"; exit 1; }
|
||||
echo " совпадают ($H1)"
|
||||
|
||||
# свой сертификат (не wildcard): cluster-issuer оставляем, иначе на новом кубе он перестанет продлеваться
|
||||
OWN_TLS=$(kubectl --context "$SRC" -n loop get mattermost "$ID" -o jsonpath='{.spec.ingress.tlsSecret}')
|
||||
[ "$OWN_TLS" = wildcard-loop.ru-tls ] && OWN_TLS=""
|
||||
echo "-- визор"
|
||||
TAIL=${ID#loop}
|
||||
FOUND=$(printf "select i.id, i.domain, c.name, d.id from loop_instance i join cluster_instance c on c.id=i.cluster_instance_id join database_instance d on d.id=i.database_instance_id where i.id like '%%%s' and i.deleted_at is null;\n" "$TAIL" | vsql)
|
||||
[ "$(printf '%s\n' "$FOUND" | grep -c .)" = 1 ] || { echo "в визоре не один инстанс: $FOUND"; exit 1; }
|
||||
IFS='|' read -r VID VDOMAIN VCLUSTER DBID <<<"$FOUND"
|
||||
echo " $VID $VDOMAIN куб=$VCLUSTER"
|
||||
[ "$VDOMAIN" = "$DOMAIN" ] || { echo "домен в визоре другой: $VDOMAIN"; exit 1; }
|
||||
|
||||
vsql <<SQL
|
||||
begin;
|
||||
update loop_instance set cluster_instance_id='$DST_CLUSTER', synchronization_status='NOT_SYNCHRONIZED' where id='$VID';
|
||||
update database_instance set vendor='ON_PREM',
|
||||
database_provider_id='$PROVIDER'
|
||||
where id='$DBID';
|
||||
-- на целевом кубе traefik; без класса оператор ставит nginx. cluster-issuer убрать: с wildcard он перезапишет wildcard-loop.ru-tls
|
||||
delete from loop_instance_annotation where loop_instance_id='$VID'
|
||||
and (annotation='kubernetes.io/ingress.class' or (annotation='cert-manager.io/cluster-issuer' and '$OWN_TLS'=''));
|
||||
insert into loop_instance_annotation(id, loop_instance_id, annotation, annotation_value)
|
||||
values (gen_random_uuid()::text, '$VID', 'kubernetes.io/ingress.class', '${DST_INGRESS_CLASS:-traefik}');
|
||||
select i.domain, c.name, p.name, d.vendor from loop_instance i
|
||||
join cluster_instance c on c.id=i.cluster_instance_id
|
||||
join database_instance d on d.id=i.database_instance_id
|
||||
join database_provider p on p.id=d.database_provider_id where i.id='$VID';
|
||||
commit;
|
||||
SQL
|
||||
|
||||
echo "Готово. Дальше: loopctl k8s move $ID (env, sync, проверки, прокси, DNS)."
|
||||
echo "Откат визора: update loop_instance set cluster_instance_id='$SRC_CLUSTER' where id='$VID';"
|
||||
Reference in New Issue
Block a user