Skip to content

Instantly share code, notes, and snippets.

@kenzo0107
Created July 17, 2025 04:23
Show Gist options
  • Save kenzo0107/610df8182f47476e263bc080d164e840 to your computer and use it in GitHub Desktop.
Save kenzo0107/610df8182f47476e263bc080d164e840 to your computer and use it in GitHub Desktop.
#!/bin/bash
# 設定
REGION="ap-northeast-1" # 必要に応じて変更してください
echo "=== Aurora MySQL Cluster Discovery ==="
echo "Region: $REGION"
echo ""
# Aurora MySQL クラスターを取得
echo "Discovering Aurora MySQL clusters..."
AURORA_CLUSTERS=$(aws rds describe-db-clusters \
--region $REGION \
--query 'DBClusters[?Engine==`aurora-mysql`].{ClusterIdentifier:DBClusterIdentifier,Status:Status,Engine:Engine}' \
--output table)
if [ $? -eq 0 ]; then
echo "Available Aurora MySQL Clusters:"
echo "$AURORA_CLUSTERS"
echo ""
# クラスター一覧を配列で取得
CLUSTER_ARRAY=($(aws rds describe-db-clusters \
--region $REGION \
--query 'DBClusters[?Engine==`aurora-mysql`].DBClusterIdentifier' \
--output text))
if [ ${#CLUSTER_ARRAY[@]} -gt 0 ]; then
# 複数クラスターがある場合は選択画面を表示
if [ ${#CLUSTER_ARRAY[@]} -gt 1 ]; then
echo "Multiple clusters found. Please select one:"
for i in "${!CLUSTER_ARRAY[@]}"; do
echo "$((i+1))) ${CLUSTER_ARRAY[$i]}"
done
echo ""
echo "Enter selection (1-${#CLUSTER_ARRAY[@]}) or press Enter for #1:"
read selection
if [ -z "$selection" ]; then
selection=1
fi
# 選択の検証
if [[ "$selection" =~ ^[0-9]+$ ]] && [ "$selection" -ge 1 ] && [ "$selection" -le ${#CLUSTER_ARRAY[@]} ]; then
DB_CLUSTER_IDENTIFIER=${CLUSTER_ARRAY[$((selection-1))]}
else
echo "ERROR: Invalid selection"
exit 1
fi
else
# クラスターが1つの場合は自動選択
DB_CLUSTER_IDENTIFIER=${CLUSTER_ARRAY[0]}
fi
echo "Selected cluster: $DB_CLUSTER_IDENTIFIER"
# クラスターのライターインスタンスを取得
echo "Finding writer instance for cluster: $DB_CLUSTER_IDENTIFIER"
DB_WRITER_INSTANCE=$(aws rds describe-db-clusters \
--db-cluster-identifier $DB_CLUSTER_IDENTIFIER \
--region $REGION \
--query 'DBClusters[0].DBClusterMembers[?IsClusterWriter==`true`].DBInstanceIdentifier' \
--output text)
if [ -n "$DB_WRITER_INSTANCE" ] && [ "$DB_WRITER_INSTANCE" != "None" ]; then
echo "Writer instance: $DB_WRITER_INSTANCE"
# クラスター詳細情報を取得
echo ""
echo "=== Cluster Details ==="
aws rds describe-db-clusters \
--db-cluster-identifier $DB_CLUSTER_IDENTIFIER \
--region $REGION \
--query 'DBClusters[0].{
ClusterIdentifier:DBClusterIdentifier,
Engine:Engine,
EngineVersion:EngineVersion,
Status:Status,
MultiAZ:MultiAZ,
Members:DBClusterMembers[].{
Instance:DBInstanceIdentifier,
IsWriter:IsClusterWriter,
Status:DBInstanceStatus
}
}' \
--output table
else
echo "ERROR: No writer instance found for cluster $DB_CLUSTER_IDENTIFIER"
exit 1
fi
else
echo "ERROR: No Aurora MySQL clusters found in region $REGION"
exit 1
fi
else
echo "ERROR: Failed to retrieve cluster information"
exit 1
fi
echo ""
echo "=== Starting CDC Throughput Analysis ==="
# 時刻設定
START_TIME=$(date -u -v-7d +%Y-%m-%dT%H:%M:%S)
END_TIME=$(date -u +%Y-%m-%dT%H:%M:%S)
echo "Cluster: $DB_CLUSTER_IDENTIFIER"
echo "Writer Instance: $DB_WRITER_INSTANCE"
echo "Period: $START_TIME to $END_TIME"
echo ""
# メトリクス取得関数
get_metrics() {
local identifier=$1
local dimension_name=$2
local metric_name=$3
local stat_type=$4
local output_file=$5
echo "Retrieving $metric_name ($stat_type) for $identifier..."
aws cloudwatch get-metric-statistics \
--namespace AWS/RDS \
--metric-name $metric_name \
--dimensions Name=$dimension_name,Value=$identifier \
--start-time "$START_TIME" \
--end-time "$END_TIME" \
--period 3600 \
--statistics $stat_type \
--region $REGION \
--output json > "$output_file"
if [ $? -ne 0 ]; then
echo " Warning: Failed to retrieve $metric_name for $identifier"
return 1
fi
return 0
}
# メトリクス取得実行
echo "=== Retrieving Metrics ==="
# クラスターレベルのメトリクス
get_metrics "$DB_CLUSTER_IDENTIFIER" "DBClusterIdentifier" "WriteThroughput" "Maximum" "cluster_write_max.json"
get_metrics "$DB_CLUSTER_IDENTIFIER" "DBClusterIdentifier" "WriteThroughput" "Average" "cluster_write_avg.json"
get_metrics "$DB_CLUSTER_IDENTIFIER" "DBClusterIdentifier" "WriteIOPS" "Maximum" "cluster_iops_max.json"
get_metrics "$DB_CLUSTER_IDENTIFIER" "DBClusterIdentifier" "WriteIOPS" "Average" "cluster_iops_avg.json"
# ライターインスタンスのメトリクス
get_metrics "$DB_WRITER_INSTANCE" "DBInstanceIdentifier" "WriteThroughput" "Maximum" "writer_write_max.json"
get_metrics "$DB_WRITER_INSTANCE" "DBInstanceIdentifier" "WriteThroughput" "Average" "writer_write_avg.json"
get_metrics "$DB_WRITER_INSTANCE" "DBInstanceIdentifier" "WriteIOPS" "Maximum" "writer_iops_max.json"
get_metrics "$DB_WRITER_INSTANCE" "DBInstanceIdentifier" "WriteIOPS" "Average" "writer_iops_avg.json"
# Aurora MySQL 固有メトリクス
get_metrics "$DB_WRITER_INSTANCE" "DBInstanceIdentifier" "BinLogDiskUsage" "Maximum" "writer_binlog.json"
echo ""
# メトリクス解析関数
extract_value() {
local file=$1
local stat_type=$2
if [ ! -f "$file" ]; then
echo "0"
return
fi
# ファイルサイズチェック
if [ ! -s "$file" ]; then
echo "0"
return
fi
if command -v jq &> /dev/null; then
if [ "$stat_type" = "Maximum" ]; then
local value=$(cat "$file" | jq -r '.Datapoints[].Maximum' 2>/dev/null | grep -v null | sort -n | tail -1)
else
local value=$(cat "$file" | jq -r '.Datapoints[].Average' 2>/dev/null | grep -v null | awk '{sum+=$1; count++} END {if(count>0) print sum/count; else print 0}')
fi
else
if [ "$stat_type" = "Maximum" ]; then
local value=$(grep -o "\"Maximum\": [0-9.]*" "$file" | cut -d' ' -f2 | sort -n | tail -1)
else
local value=$(grep -o "\"Average\": [0-9.]*" "$file" | cut -d' ' -f2 | awk '{sum+=$1; count++} END {if(count>0) print sum/count; else print 0}')
fi
fi
echo "${value:-0}"
}
# データ抽出
echo "=== Metric Analysis ==="
echo ""
# クラスターメトリクス
CLUSTER_WRITE_MAX=$(extract_value "cluster_write_max.json" "Maximum")
CLUSTER_WRITE_AVG=$(extract_value "cluster_write_avg.json" "Average")
CLUSTER_IOPS_MAX=$(extract_value "cluster_iops_max.json" "Maximum")
CLUSTER_IOPS_AVG=$(extract_value "cluster_iops_avg.json" "Average")
# ライターメトリクス
WRITER_WRITE_MAX=$(extract_value "writer_write_max.json" "Maximum")
WRITER_WRITE_AVG=$(extract_value "writer_write_avg.json" "Average")
WRITER_IOPS_MAX=$(extract_value "writer_iops_max.json" "Maximum")
WRITER_IOPS_AVG=$(extract_value "writer_iops_avg.json" "Average")
WRITER_BINLOG=$(extract_value "writer_binlog.json" "Maximum")
# 値の検証とフォールバック
validate_value() {
local value=$1
if [ -z "$value" ] || [ "$value" = "null" ] || [ "$value" = "" ]; then
echo "0"
else
echo "$value"
fi
}
CLUSTER_WRITE_MAX=$(validate_value "$CLUSTER_WRITE_MAX")
CLUSTER_WRITE_AVG=$(validate_value "$CLUSTER_WRITE_AVG")
WRITER_WRITE_MAX=$(validate_value "$WRITER_WRITE_MAX")
WRITER_WRITE_AVG=$(validate_value "$WRITER_WRITE_AVG")
# 結果表示
echo "Cluster-Level Metrics:"
echo " WriteThroughput - Maximum: $CLUSTER_WRITE_MAX bytes/sec"
echo " WriteThroughput - Average: $CLUSTER_WRITE_AVG bytes/sec"
echo " WriteIOPS - Maximum: $CLUSTER_IOPS_MAX ops/sec"
echo " WriteIOPS - Average: $CLUSTER_IOPS_AVG ops/sec"
echo ""
echo "Writer Instance Metrics:"
echo " WriteThroughput - Maximum: $WRITER_WRITE_MAX bytes/sec"
echo " WriteThroughput - Average: $WRITER_WRITE_AVG bytes/sec"
echo " WriteIOPS - Maximum: $WRITER_IOPS_MAX ops/sec"
echo " WriteIOPS - Average: $WRITER_IOPS_AVG ops/sec"
echo " BinLogDiskUsage - Maximum: $WRITER_BINLOG bytes"
echo ""
# CDC 計算関数
calculate_cdc() {
local throughput=$1
local label=$2
if [ -n "$throughput" ] && [ "$throughput" != "0" ] && [ "$throughput" != "" ]; then
# Aurora MySQL CDC 係数: 0.576
local cdc_bytes=$(echo "$throughput" | awk '{printf "%.0f", $1 * 0.576}')
local cdc_mbps=$(echo "$cdc_bytes" | awk '{printf "%.3f", $1 * 8 / 1000000}')
printf " %-20s: %s bytes/sec (%.3f Mbps)\n" "$label" "$cdc_bytes" "$cdc_mbps"
else
printf " %-20s: No data available\n" "$label"
fi
}
# CDC 推定値
echo "=== CDC Throughput Estimates ==="
echo ""
echo "Based on Cluster WriteThroughput:"
calculate_cdc "$CLUSTER_WRITE_MAX" "Peak CDC"
calculate_cdc "$CLUSTER_WRITE_AVG" "Average CDC"
echo ""
echo "Based on Writer Instance WriteThroughput:"
calculate_cdc "$WRITER_WRITE_MAX" "Peak CDC"
calculate_cdc "$WRITER_WRITE_AVG" "Average CDC"
echo ""
echo "=== Data Point Validation ==="
for file in cluster_write_max.json writer_write_max.json; do
if [ -f "$file" ]; then
if command -v jq &> /dev/null; then
datapoints=$(cat "$file" | jq '.Datapoints | length' 2>/dev/null)
else
datapoints=$(grep -c '"Timestamp"' "$file" 2>/dev/null)
fi
echo "$file: ${datapoints:-0} data points"
else
echo "$file: File not found"
fi
done
echo ""
echo "=== Recommendations ==="
echo "1. Use cluster-level metrics for overall CDC capacity planning"
echo "2. Peak values should guide maximum Confluent Cloud throughput settings"
echo "3. Average values should guide standard operational capacity"
echo "4. Consider 20-50% safety margin for production deployment"
echo "5. Monitor BinLogDiskUsage to ensure CDC can keep up with log generation"
# クリーンアップ
echo ""
echo "Cleaning up temporary files..."
rm -f cluster_*.json writer_*.json
echo "Analysis complete."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment