440 lines
16 KiB
Bash
440 lines
16 KiB
Bash
mariadbLabel="[MariaDB]"
|
|
|
|
# Prepares Kubernetes secrets for MariaDB.
|
|
function cmdMariadbPreparation() {
|
|
printInfo "Preparation..."
|
|
|
|
local error
|
|
runError error k3sRun delete secret "$mariadbKube-secret" --ignore-not-found || {
|
|
printDotText "preparation" "$labelFail"
|
|
printDanger "Delete old Secret: $error"
|
|
return 1
|
|
}
|
|
|
|
runError error k3sRun create secret generic "$mariadbKube-secret" --from-literal=root-password="$mariadbRootPass" --from-literal=replication-password="$mariadbRootPass" || {
|
|
printDotText "preparation" "$labelFail"
|
|
printDanger "Create new Secret: $error"
|
|
return 1
|
|
}
|
|
|
|
printDotText "preparation" "$labelDone"
|
|
}
|
|
|
|
# Renders the MariaDB Kubernetes YAML manifest via Helm.
|
|
function cmdMariadbYamlRender() {
|
|
local templateFile="templates/$mariadbKube.yaml"
|
|
|
|
printSection "Render YAML file | Helm"
|
|
printDotText "Template" "$appAssetsPath/k3s/$templateFile"
|
|
[[ -f "$appAssetsPath/k3s/$templateFile" ]] || {
|
|
printDanger "Template file not found"
|
|
return 1
|
|
}
|
|
|
|
local profileCpuFile="$appAssetsPath/k3s/profiles/cpu-$kubeCpuProfile.yaml"
|
|
printDotText "CPU profile" "$profileCpuFile"
|
|
[[ -f "$profileCpuFile" ]] || {
|
|
printDanger "CPU profile file not found"
|
|
return 1
|
|
}
|
|
|
|
local profileMemoryFile="$appAssetsPath/k3s/profiles/memory-$kubeMemoryProfile.yaml"
|
|
printDotText "Memory profile" "$profileMemoryFile"
|
|
[[ -f "$profileMemoryFile" ]] || {
|
|
printDanger "Memory profile file not found"
|
|
return 1
|
|
}
|
|
|
|
local varsFile
|
|
varsFile=$(mktemp "/tmp/$mariadbKube.vars.XXXXXX.yaml") || {
|
|
printDotText "render" "$labelFail"
|
|
printDanger "Create temp variables file"
|
|
return 1
|
|
}
|
|
printDotText "Variables" "$varsFile"
|
|
trap 'rm -f -- "$varsFile"' RETURN
|
|
cat > "$varsFile" <<EOF
|
|
mariadbHelm: true
|
|
namespace: $k3sNamespace
|
|
mariadb: $mariadbKube
|
|
mariadbMaster: $mariadbMasterKube
|
|
mariadbSlave: $mariadbSlaveKube
|
|
mariadbMasterPath: $mariadbMasterPath
|
|
mariadbSlavePath: $mariadbSlavePath
|
|
EOF
|
|
|
|
printDotText "Result" "$mariadbYaml"
|
|
mkdir -p -- "$(dirname -- "$mariadbYaml")" || return 1
|
|
fileBackup "$mariadbYaml"
|
|
helm template stack "$appAssetsPath/k3s" -f "$varsFile" -f "$profileCpuFile" -f "$profileMemoryFile" --show-only "$templateFile" > "$mariadbYaml" || {
|
|
printDotText "render" "$labelFail"
|
|
printDanger "Render failed"
|
|
return 1
|
|
}
|
|
|
|
printDotText "render" "$labelDone"
|
|
}
|
|
|
|
# Waits until both MariaDB master and slave respond to SQL queries.
|
|
function cmdMariadbWaitMasterSlave() {
|
|
local error step attempts=15
|
|
|
|
for ((step=1; step<=attempts; step++)); do
|
|
runError error mariadbMasterRootQuery "SELECT 1;" && break
|
|
if [[ "$step" -ne "$attempts" ]]; then
|
|
printWarning "Master node | Waiting..."
|
|
sleep 4
|
|
else
|
|
printDanger "Master node | Not responding"
|
|
return 1
|
|
fi
|
|
done
|
|
|
|
for ((step=1; step<=attempts; step++)); do
|
|
runError error mariadbSlaveRootQuery "SELECT 1;" && break
|
|
if [[ "$step" -ne "$attempts" ]]; then
|
|
printWarning "Slave node | Waiting..."
|
|
sleep 4
|
|
else
|
|
printDanger "Slave node | Not responding"
|
|
return 1
|
|
fi
|
|
done
|
|
}
|
|
|
|
# Rebuilds MariaDB replication from master to slave.
|
|
# [$1] (masterPassword): replication password (defaults to $mariadbRootPass).
|
|
function cmdMariadbReplicaRebuild() {
|
|
local masterPassword="${1:-$mariadbRootPass}"
|
|
|
|
printInfo "Replica rebuild..."
|
|
|
|
local output error
|
|
runError error mariadbMasterRootQuery "SELECT 1;" || {
|
|
printDanger "Master node | Not responding: $error"
|
|
return 1
|
|
}
|
|
runError error mariadbSlaveRootQuery "SELECT 1;" || {
|
|
printDanger "Slave node | Not responding: $error"
|
|
return 1
|
|
}
|
|
|
|
runError error mariadbMasterRootQuery "CREATE USER IF NOT EXISTS 'replication_user'@'%' IDENTIFIED BY '$masterPassword'; GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'replication_user'@'%'; ALTER USER 'replication_user'@'%' IDENTIFIED BY '$masterPassword';" || {
|
|
printDanger "Master node | Recreated replication user: $error"
|
|
return 1
|
|
}
|
|
printInfo "Master node | Recreated replication user"
|
|
|
|
local dumpFile="$appDataPath/$mariadbMasterKube/${appDate}_${appTime}_replica_rebuild.sql"
|
|
printInfo "Master node | Exporting full dump..."
|
|
mariadbMasterRootExport all "$dumpFile" || {
|
|
printDanger "Master node | Export failed"
|
|
return 1
|
|
}
|
|
printInfo "Master node | Exported: $dumpFile"
|
|
|
|
local masterFile masterPos
|
|
masterFile=$(grep -m1 -oE "MASTER_LOG_FILE='[^']+'" "$dumpFile" | sed "s/MASTER_LOG_FILE='//;s/'//")
|
|
masterPos=$(grep -m1 -oE "MASTER_LOG_POS=[0-9]+" "$dumpFile" | sed 's/MASTER_LOG_POS=//')
|
|
[[ -n "$masterFile" && -n "$masterPos" ]] || {
|
|
printDanger "Master node | Cannot parse MASTER_LOG_FILE/MASTER_LOG_POS from dump"
|
|
return 1
|
|
}
|
|
printInfo "Master node | Binlog: $masterFile:$masterPos"
|
|
|
|
printInfo "Slave node | Stopping replication..."
|
|
runError error mariadbSlaveRootQuery "STOP SLAVE; RESET SLAVE ALL;" || {
|
|
printDanger "Slave node | Stop/reset failed: $error"
|
|
return 1
|
|
}
|
|
|
|
printInfo "Slave node | Importing full dump..."
|
|
runShell output error k3sRun exec -i pod/"$mariadbSlaveKube"-0 -c "$mariadbSlaveKube" -- mariadb -u "root" -p"$mariadbRootPass" "<" "$dumpFile" ">" /dev/null || {
|
|
printDanger "Slave node | Import failed: ${error:-$output}"
|
|
return 1
|
|
}
|
|
printInfo "Slave node | Import completed"
|
|
|
|
runError error mariadbSlaveRootQuery "CHANGE MASTER TO MASTER_HOST='${mariadbMasterKube}', MASTER_PORT=3306, MASTER_USER='replication_user', MASTER_PASSWORD='${masterPassword}', MASTER_LOG_FILE='${masterFile}', MASTER_LOG_POS=${masterPos}; START SLAVE;" || {
|
|
printDanger "Slave node | Configure replication failed: $error"
|
|
return 1
|
|
}
|
|
printInfo "Slave node | Replication configured"
|
|
|
|
run output error mariadbSlaveRootQuery "SHOW SLAVE STATUS\G" showColumn || {
|
|
printDanger "Slave node | Status: $error"
|
|
return 1
|
|
}
|
|
|
|
local ioRunning sqlRunning secondsBehind lastError
|
|
ioRunning=$(printf '%s\n' "$output" | awk -F': ' '/^ *Slave_IO_Running:/{print $2}' | tr -d '[:space:]')
|
|
sqlRunning=$(printf '%s\n' "$output" | awk -F': ' '/^ *Slave_SQL_Running:/{print $2}' | tr -d '[:space:]')
|
|
secondsBehind=$(printf '%s\n' "$output" | awk -F': ' '/^ *Seconds_Behind_Master:/{print $2}' | tr -d '[:space:]')
|
|
lastError=$(printf '%s\n' "$output" | awk -F': ' '/^ *Last_Error:/{print substr($0, index($0,$2))}')
|
|
if [[ "$ioRunning" != "Yes" || "$sqlRunning" != "Yes" ]]; then
|
|
printWarning "Slave node | IO:${ioRunning:-?} | SQL:${sqlRunning:-?}"
|
|
[[ -n "$lastError" ]] && printWarning "Slave node | Last error: $lastError"
|
|
return 1
|
|
fi
|
|
|
|
printSuccess "Replica rebuild completed | Delay ${secondsBehind:-0}s"
|
|
}
|
|
|
|
# Updates MariaDB Kubernetes resources (limits, config, etc.) without re-initialization.
|
|
function cmdMariadbUpdate() {
|
|
cmdMariadbYamlRender || return 1
|
|
cmdK3sYamlApplyEx "$mariadbYaml" || return 1
|
|
}
|
|
|
|
# Installs MariaDB into Kubernetes and initializes replication.
|
|
function cmdMariadbInstall() {
|
|
cmdMariadbPreparation || return 1
|
|
cmdMariadbYamlRender || return 1
|
|
cmdK3sYamlApplyEx "$mariadbYaml" || return 1
|
|
cmdMariadbWaitMasterSlave || return 1
|
|
cmdMariadbReplicaRebuild || return 1
|
|
}
|
|
|
|
# Uninstalls MariaDB Kubernetes resources.
|
|
function cmdMariadbUninstall() {
|
|
"$k3sCmd" kubectl delete -f "$mariadbYaml"
|
|
}
|
|
|
|
# Checks MariaDB root password, replication health, database/user count, and total data size.
|
|
function cmdMariadbInfo() {
|
|
local password
|
|
password=$(mariadbRootPassSecretGet)
|
|
if [[ "$password" != "$mariadbRootPass" ]]; then
|
|
printRow
|
|
printDotText "Root password" "$labelFail"
|
|
printDanger "Use mariadbRootPassSecretSave"
|
|
return 1
|
|
fi
|
|
|
|
local podList output error pod ready phase reason
|
|
|
|
# Master
|
|
if ! run podList error k3sPodListStatus "$mariadbMasterKube"; then
|
|
printDanger "Get pods (master): $error"
|
|
elif [[ -z "$podList" ]]; then
|
|
printDanger "Pods (master) not found"
|
|
else
|
|
while IFS='|' read -r pod ready phase reason; do
|
|
printSection "$pod"
|
|
|
|
if [[ "$ready" != "1" ]]; then
|
|
printDotText "Status" "$fontGray$reason $fontYellow$phase$fontReset"
|
|
else
|
|
printDotText "Status" "$fontGreen$phase$fontReset"
|
|
|
|
if ! run output error mariadbMasterRootQuery "SELECT VERSION();"; then
|
|
printDotText "MariaDB status" "$fontRed$labelFail$fontReset"
|
|
printDanger "$error"
|
|
continue
|
|
fi
|
|
printDotText "MariaDB status" "$labelRunning"
|
|
printDotText "MariaDB version" "$output"
|
|
|
|
local masterStatus file position activeConnections
|
|
if ! run masterStatus error mariadbMasterRootQuery "SHOW MASTER STATUS\G;" "showColumn"; then
|
|
printDotText "Replica role" "$fontRed$labelUnknown$fontReset"
|
|
printDanger "$error"
|
|
continue
|
|
fi
|
|
|
|
file=$(printf '%s\n' "$masterStatus" | awk '/^ *File:/{print $2}')
|
|
if [[ -z "$file" ]]; then
|
|
printDotText "Replica role" "$fontRed$labelUnknown$fontReset"
|
|
printDanger "Params 'File' not found"
|
|
continue
|
|
fi
|
|
|
|
position=$(printf '%s\n' "$masterStatus" | awk '/^ *Position:/{print $2}')
|
|
if [[ -z "$position" ]]; then
|
|
printDotText "Replica role" "$fontRed$labelUnknown$fontReset"
|
|
printDanger "Params 'Position' not found"
|
|
continue
|
|
fi
|
|
|
|
if ! run output error mariadbMasterRootQuery "SHOW STATUS LIKE 'Threads_connected';"; then
|
|
printDotText "Replica role" "$fontRed$labelUnknown$fontReset"
|
|
printDanger "$error"
|
|
continue
|
|
fi
|
|
|
|
printDotText "Replica role" "${fontGreen}master$fontReset"
|
|
|
|
activeConnections=$(printf '%s\n' "$output" | awk '{print $2}')
|
|
if [[ "$activeConnections" -ge 100 || "$activeConnections" -eq 1 ]]; then
|
|
printDotText "Active connections" "$fontYellow$activeConnections$fontReset"
|
|
else
|
|
printDotText "Active connections" "$fontGreen$activeConnections$fontReset"
|
|
fi
|
|
fi
|
|
done < <(awk 'NF' <<< "$podList")
|
|
fi
|
|
|
|
# Slave
|
|
if ! run podList error k3sPodListStatus "$mariadbSlaveKube"; then
|
|
printDanger "Get pods (slave): $error"
|
|
elif [[ -z "$podList" ]]; then
|
|
printDanger "Pods (slave) not found"
|
|
else
|
|
while IFS='|' read -r pod ready phase reason; do
|
|
printSection "$pod"
|
|
|
|
if [[ "$ready" != "1" ]]; then
|
|
printDotText "Status" "$fontGray$reason $fontYellow$phase$fontReset"
|
|
else
|
|
printDotText "Status" "$fontGreen$phase$fontReset"
|
|
|
|
if ! run output error mariadbSlaveRootQuery "SELECT VERSION();"; then
|
|
printDotText "MariaDB status" "$fontRed$labelFail$fontReset"
|
|
printDanger "$error"
|
|
continue
|
|
fi
|
|
printDotText "MariaDB status" "$labelRunning"
|
|
printDotText "MariaDB version" "$output"
|
|
|
|
local slaveStatus slaveIoRunning slaveSqlRunning lastError secondsBehindMaster
|
|
if ! run slaveStatus error mariadbSlaveRootQuery "SHOW SLAVE STATUS\G;" "showColumn"; then
|
|
printDotText "Replica role" "$fontRed$labelUnknown$fontReset"
|
|
printDanger "$error"
|
|
continue
|
|
fi
|
|
|
|
slaveIoRunning=$(printf '%s\n' "$slaveStatus" | awk '/^ *Slave_IO_Running:/{print $2}')
|
|
if [[ "$slaveIoRunning" != "Yes" ]]; then
|
|
printDotText "Slave IO Running" "$fontRed$slaveIoRunning$fontReset"
|
|
continue
|
|
fi
|
|
|
|
slaveSqlRunning=$(printf '%s\n' "$slaveStatus" | awk '/^ *Slave_SQL_Running:/{print $2}')
|
|
if [[ "$slaveSqlRunning" != "Yes" ]]; then
|
|
printDotText "Slave SQL Running" "$fontRed$slaveSqlRunning$fontReset"
|
|
continue
|
|
fi
|
|
|
|
lastError=$(printf '%s\n' "$slaveStatus" | awk '/^ *Last_Error:/{$1=""; sub(/^[ \t]+/,""); print}')
|
|
if [[ -n "$lastError" ]]; then
|
|
printDotText "Slave SQL Running" "$fontRed$slaveSqlRunning$fontReset"
|
|
printDanger "Last error: $lastError"
|
|
continue
|
|
fi
|
|
|
|
printDotText "Replica role" "${fontGreen}slave$fontReset"
|
|
|
|
secondsBehindMaster=$(printf '%s\n' "$slaveStatus" | awk '/^ *Seconds_Behind_Master:/{print $2}')
|
|
if [[ "$secondsBehindMaster" -ne 0 ]]; then
|
|
printDotText "Replication lags" "$fontYellow${secondsBehindMaster}s$fontReset"
|
|
else
|
|
printDotText "Replication lags" "${fontGreen}0s$fontReset"
|
|
fi
|
|
fi
|
|
done < <(awk 'NF' <<< "$podList")
|
|
fi
|
|
|
|
printSection "MariaDB"
|
|
|
|
local databaseList userList dataSize
|
|
if run output error mariadbDatabaseListGet; then
|
|
mapfile -t databaseList < <(awk 'NF' <<< "$output")
|
|
printDotText "Databases" "${#databaseList[@]}"
|
|
else
|
|
printDotText "Databases" "$labelUnknown"
|
|
printDanger "$error"
|
|
fi
|
|
|
|
if run output error mariadbUserListGet; then
|
|
mapfile -t userList < <(awk 'NF' <<< "$output")
|
|
printDotText "Users" "${#userList[@]}"
|
|
else
|
|
printDotText "Users" "$labelUnknown"
|
|
printDanger "$error"
|
|
fi
|
|
|
|
if ! run dataSize error mariadbMasterRootQuery "SELECT ROUND(COALESCE(SUM(DATA_LENGTH + INDEX_LENGTH), 0) / 1024 / 1024 / 1024, 2) AS t FROM information_schema.TABLES WHERE TABLE_TYPE = 'BASE TABLE';"; then
|
|
printDotText "Size" "$labelUnknown"
|
|
printDanger "$error"
|
|
else
|
|
printDotText "Size" "$dataSize Gb"
|
|
fi
|
|
}
|
|
|
|
# Shows MariaDB master and slave replication status.
|
|
function cmdMariadbStatus() {
|
|
local output error
|
|
|
|
printSection "$mariadbMasterKube"-0
|
|
if ! run output error mariadbMasterRootQuery "SHOW MASTER STATUS;"; then
|
|
printDanger "$error"
|
|
else
|
|
printText "$output"
|
|
fi
|
|
|
|
printSection "$mariadbSlaveKube"-0
|
|
if ! run output error mariadbSlaveRootQuery "SHOW SLAVE STATUS\G;" showColumn; then
|
|
printDanger "$error"
|
|
else
|
|
printText "$output"
|
|
fi
|
|
}
|
|
|
|
# Lists all MariaDB databases.
|
|
function cmdMariadbDatabase() {
|
|
local output error
|
|
|
|
printRow
|
|
|
|
if ! run output error mariadbDatabaseListGet; then
|
|
printDanger "$error"
|
|
elif [[ -z "$output" ]]; then
|
|
printText "$labelNull"
|
|
else
|
|
printText "$output"
|
|
fi
|
|
}
|
|
|
|
# Lists all MariaDB users.
|
|
function cmdMariadbUser() {
|
|
local output error
|
|
|
|
printRow
|
|
|
|
if ! run output error mariadbUserListGet; then
|
|
printDanger "$error"
|
|
elif [[ -z "$output" ]]; then
|
|
printText "$labelNull"
|
|
else
|
|
printText "$output"
|
|
fi
|
|
}
|
|
|
|
# Exports a full dump from the MariaDB master node.
|
|
# [$@] (...): arguments passed to mariadbMasterRootExport (e.g. database name, file).
|
|
function cmdMariadbMasterDump() {
|
|
local output error
|
|
|
|
printRow
|
|
|
|
if ! run output error mariadbMasterRootExport "$@"; then
|
|
printDanger "$error"
|
|
else
|
|
printText "$output"
|
|
fi
|
|
}
|
|
|
|
# Exports a full dump from the MariaDB slave node.
|
|
# [$@] (...): arguments passed to mariadbSlaveRootExport (e.g. database name, file).
|
|
function cmdMariadbSlaveDump() {
|
|
local output error
|
|
|
|
printRow
|
|
|
|
if ! run output error mariadbSlaveRootExport "$@"; then
|
|
printDanger "$error"
|
|
else
|
|
printText "$output"
|
|
fi
|
|
}
|