共计 55451 个字符,预计需要花费 139 分钟才能阅读完成。
RDS太贵了,除了生产用到,其他一律自建。。。本来博主自建是在ecs上进行,用二进制创建也很快,但是后面领导说要在k8s中创建,且以后缩小公用范围,将范围缩减到部门,让部门的成本中心自行买单
作为中间件平台的k8s集群,同时还得考虑集群外访问方式,不过可比其他那些有注册模式得中间件好多了,看下需求:
- 持久化数据落盘
- 部署模式:单实例模式,一主多从
- 访问方式:集群内/外都可访问
- 数据监控:mysqld_exporter
- 读写分离:要么程序上处理读写逻辑,或者用中间件
- 多平台架构镜像:x86和arm,都用ubuntu/debian系统镜像
standalone单实例此处就不i赘述,很久以前写过类似的样例,此篇只描述主从结构
x86平台架构镜像制作
mysql官方镜像:https://hub.docker.com/_/mysql,根据这个debian镜像坐下改造,让它初始化时创建以下用户和授权:
- replication:用于主从复制同步
- monitor:用于mysqld_exporter采集
- xbk:用xbk工具备份还原(为新slave节点加快还原速度)
修改官方得docker-entrypoint.sh
中的 docker_setup_db
函数,在其中加入创建用户和授权的语句
# 创建replication用户并授权
if [ -n "$MYSQL_REPLICATION_USER" ] && [ -n "$MYSQL_REPLICATION_PASSWORD" ]; then
mysql_note "Creating user $MYSQL_REPLICATION_USER"
docker_process_sql --database=mysql <<<"CREATE USER '$MYSQL_REPLICATION_USER'@'%' IDENTIFIED BY '$MYSQL_REPLICATION_PASSWORD';"
docker_process_sql --database=mysql <<<"GRANT REPLICATION SLAVE,SUPER ON *.* TO '$MYSQL_REPLICATION_USER'@'%';"
docker_process_sql --database=mysql <<<"FLUSH PRIVILEGES ;"
fi
# 创建monitor用户并授权
if [ -n "$MYSQL_MONITOR_USER" ] && [ -n "$MYSQL_MONITOR_PASSWORD" ]; then
mysql_note "Creating user $MYSQL_MONITOR_USER"
docker_process_sql --database=mysql <<<"CREATE USER '$MYSQL_MONITOR_USER'@'%' IDENTIFIED BY '$MYSQL_MONITOR_PASSWORD' WITH MAX_USER_CONNECTIONS 3;"
docker_process_sql --database=mysql <<<"GRANT PROCESS, REPLICATION CLIENT, SELECT ON *.* TO '$MYSQL_MONITOR_USER'@'%';"
docker_process_sql --database=mysql <<<"FLUSH PRIVILEGES ;"
fi
# 创建xbk用户并授权
if [ -n "$MYSQL_XBK_USER" ] && [ -n "$MYSQL_XBK_PASSWORD" ]; then
mysql_note "Creating user $MYSQL_XBK_USER"
docker_process_sql --database=mysql <<<"CREATE USER '$MYSQL_XBK_USER'@'%' IDENTIFIED BY '$MYSQL_XBK_PASSWORD';"
docker_process_sql --database=mysql <<<"GRANT RELOAD, LOCK TABLES, PROCESS, REPLICATION CLIENT,SUPER ON *.* TO '$MYSQL_XBK_USER'@'%';"
docker_process_sql --database=mysql <<<"FLUSH PRIVILEGES ;"
fi
完整dockerfile和docker-entrypoint.sh如下
[root@k8s-master master-slave]# mkdir mysql-image
[root@k8s-master master-slave]# cd mysql-image/
# 准备docker-entrypoint.sh脚本
[root@k8s-master mysql-image]# cat docker-entrypoint.sh
#!/bin/bash
set -eo pipefail
shopt -s nullglob
# logging functions
mysql_log() {
local type="$1"; shift
# accept argument string or stdin
local text="$*"; if [ "$#" -eq 0 ]; then text="$(cat)"; fi
local dt; dt="$(date --rfc-3339=seconds)"
printf '%s [%s] [Entrypoint]: %s\n' "$dt" "$type" "$text"
}
mysql_note() {
mysql_log Note "$@"
}
mysql_warn() {
mysql_log Warn "$@" >&2
}
mysql_error() {
mysql_log ERROR "$@" >&2
exit 1
}
# usage: file_env VAR [DEFAULT]
# ie: file_env 'XYZ_DB_PASSWORD' 'example'
# (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of
# "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature)
file_env() {
local var="$1"
local fileVar="${var}_FILE"
local def="${2:-}"
if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then
mysql_error "Both $var and $fileVar are set (but are exclusive)"
fi
local val="$def"
if [ "${!var:-}" ]; then
val="${!var}"
elif [ "${!fileVar:-}" ]; then
val="$(< "${!fileVar}")"
fi
export "$var"="$val"
unset "$fileVar"
}
# check to see if this file is being run or sourced from another script
_is_sourced() {
# https://unix.stackexchange.com/a/215279
[ "${#FUNCNAME[@]}" -ge 2 ] \
&& [ "${FUNCNAME[0]}" = '_is_sourced' ] \
&& [ "${FUNCNAME[1]}" = 'source' ]
}
# usage: docker_process_init_files [file [file [...]]]
# ie: docker_process_init_files /always-initdb.d/*
# process initializer files, based on file extensions
docker_process_init_files() {
# mysql here for backwards compatibility "${mysql[@]}"
mysql=( docker_process_sql )
echo
local f
for f; do
case "$f" in
*.sh)
# https://github.com/docker-library/postgres/issues/450#issuecomment-393167936
# https://github.com/docker-library/postgres/pull/452
if [ -x "$f" ]; then
mysql_note "$0: running $f"
"$f"
else
mysql_note "$0: sourcing $f"
. "$f"
fi
;;
*.sql) mysql_note "$0: running $f"; docker_process_sql < "$f"; echo ;;
*.sql.gz) mysql_note "$0: running $f"; gunzip -c "$f" | docker_process_sql; echo ;;
*.sql.xz) mysql_note "$0: running $f"; xzcat "$f" | docker_process_sql; echo ;;
*) mysql_warn "$0: ignoring $f" ;;
esac
echo
done
}
# arguments necessary to run "mysqld --verbose --help" successfully (used for testing configuration validity and for extracting default/configured values)
_verboseHelpArgs=(
--verbose --help
--log-bin-index="$(mktemp -u)" # https://github.com/docker-library/mysql/issues/136
)
mysql_check_config() {
local toRun=( "$@" "${_verboseHelpArgs[@]}" ) errors
if ! errors="$("${toRun[@]}" 2>&1 >/dev/null)"; then
mysql_error $'mysqld failed while attempting to check config\n\tcommand was: '"${toRun[*]}"$'\n\t'"$errors"
fi
}
# Fetch value from server config
# We use mysqld --verbose --help instead of my_print_defaults because the
# latter only show values present in config files, and not server defaults
mysql_get_config() {
local conf="$1"; shift
"$@" "${_verboseHelpArgs[@]}" 2>/dev/null \
| awk -v conf="$conf" '$1 == conf && /^[^ \t]/ { sub(/^[^ \t]+[ \t]+/, ""); print; exit }'
# match "datadir /some/path with/spaces in/it here" but not "--xyz=abc\n datadir (xyz)"
}
# Do a temporary startup of the MySQL server, for init purposes
docker_temp_server_start() {
if [ "${MYSQL_MAJOR}" = '5.6' ] || [ "${MYSQL_MAJOR}" = '5.7' ]; then
"$@" --skip-networking --default-time-zone=SYSTEM --socket="${SOCKET}" &
mysql_note "Waiting for server startup"
local i
for i in {30..0}; do
# only use the root password if the database has already been initialized
# so that it won't try to fill in a password file when it hasn't been set yet
extraArgs=()
if [ -z "$DATABASE_ALREADY_EXISTS" ]; then
extraArgs+=( '--dont-use-mysql-root-password' )
fi
if docker_process_sql "${extraArgs[@]}" --database=mysql <<<'SELECT 1' &> /dev/null; then
break
fi
sleep 1
done
if [ "$i" = 0 ]; then
mysql_error "Unable to start server."
fi
else
# For 5.7+ the server is ready for use as soon as startup command unblocks
if ! "$@" --daemonize --skip-networking --default-time-zone=SYSTEM --socket="${SOCKET}"; then
mysql_error "Unable to start server."
fi
fi
}
# Stop the server. When using a local socket file mysqladmin will block until
# the shutdown is complete.
docker_temp_server_stop() {
if ! mysqladmin --defaults-extra-file=<( _mysql_passfile ) shutdown -uroot --socket="${SOCKET}"; then
mysql_error "Unable to shut down server."
fi
}
# Verify that the minimally required password settings are set for new databases.
docker_verify_minimum_env() {
if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" -a -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then
mysql_error <<-'EOF'
Database is uninitialized and password option is not specified
You need to specify one of the following:
- MYSQL_ROOT_PASSWORD
- MYSQL_ALLOW_EMPTY_PASSWORD
- MYSQL_RANDOM_ROOT_PASSWORD
EOF
fi
# This will prevent the CREATE USER from failing (and thus exiting with a half-initialized database)
if [ "$MYSQL_USER" = 'root' ]; then
mysql_error <<-'EOF'
MYSQL_USER="root", MYSQL_USER and MYSQL_PASSWORD are for configuring a regular user and cannot be used for the root user
Remove MYSQL_USER="root" and use one of the following to control the root user password:
- MYSQL_ROOT_PASSWORD
- MYSQL_ALLOW_EMPTY_PASSWORD
- MYSQL_RANDOM_ROOT_PASSWORD
EOF
fi
# warn when missing one of MYSQL_USER or MYSQL_PASSWORD
if [ -n "$MYSQL_USER" ] && [ -z "$MYSQL_PASSWORD" ]; then
mysql_warn 'MYSQL_USER specified, but missing MYSQL_PASSWORD; MYSQL_USER will not be created'
elif [ -z "$MYSQL_USER" ] && [ -n "$MYSQL_PASSWORD" ]; then
mysql_warn 'MYSQL_PASSWORD specified, but missing MYSQL_USER; MYSQL_PASSWORD will be ignored'
fi
}
# creates folders for the database
# also ensures permission for user mysql of run as root
docker_create_db_directories() {
local user; user="$(id -u)"
# TODO other directories that are used by default? like /var/lib/mysql-files
# see https://github.com/docker-library/mysql/issues/562
mkdir -p "$DATADIR"
if [ "$user" = "0" ]; then
# this will cause less disk access than `chown -R`
find "$DATADIR" \! -user mysql -exec chown mysql '{}' +
fi
}
# initializes the database directory
docker_init_database_dir() {
mysql_note "Initializing database files"
if [ "$MYSQL_MAJOR" = '5.6' ]; then
mysql_install_db --datadir="$DATADIR" --rpm --keep-my-cnf "${@:2}" --default-time-zone=SYSTEM
else
"$@" --initialize-insecure --default-time-zone=SYSTEM
fi
mysql_note "Database files initialized"
if command -v mysql_ssl_rsa_setup > /dev/null && [ ! -e "$DATADIR/server-key.pem" ]; then
# https://github.com/mysql/mysql-server/blob/23032807537d8dd8ee4ec1c4d40f0633cd4e12f9/packaging/deb-in/extra/mysql-systemd-start#L81-L84
mysql_note "Initializing certificates"
mysql_ssl_rsa_setup --datadir="$DATADIR"
mysql_note "Certificates initialized"
fi
}
# Loads various settings that are used elsewhere in the script
# This should be called after mysql_check_config, but before any other functions
docker_setup_env() {
# Get config
declare -g DATADIR SOCKET
DATADIR="$(mysql_get_config 'datadir' "$@")"
SOCKET="$(mysql_get_config 'socket' "$@")"
# Initialize values that might be stored in a file
file_env 'MYSQL_ROOT_HOST' '%'
file_env 'MYSQL_DATABASE'
file_env 'MYSQL_USER'
file_env 'MYSQL_PASSWORD'
file_env 'MYSQL_ROOT_PASSWORD'
declare -g DATABASE_ALREADY_EXISTS
if [ -d "$DATADIR/mysql" ]; then
DATABASE_ALREADY_EXISTS='true'
fi
}
# Execute sql script, passed via stdin
# usage: docker_process_sql [--dont-use-mysql-root-password] [mysql-cli-args]
# ie: docker_process_sql --database=mydb <<<'INSERT ...'
# ie: docker_process_sql --dont-use-mysql-root-password --database=mydb <my-file.sql
docker_process_sql() {
passfileArgs=()
if [ '--dont-use-mysql-root-password' = "$1" ]; then
passfileArgs+=( "$1" )
shift
fi
# args sent in can override this db, since they will be later in the command
if [ -n "$MYSQL_DATABASE" ]; then
set -- --database="$MYSQL_DATABASE" "$@"
fi
mysql --defaults-extra-file=<( _mysql_passfile "${passfileArgs[@]}") --protocol=socket -uroot -hlocalhost --socket="${SOCKET}" --comments "$@"
}
# Initializes database with timezone info and root password, plus optional extra db/user
docker_setup_db() {
# Load timezone info into database
if [ -z "$MYSQL_INITDB_SKIP_TZINFO" ]; then
# sed is for https://bugs.mysql.com/bug.php?id=20545
mysql_tzinfo_to_sql /usr/share/zoneinfo \
| sed 's/Local time zone must be set--see zic manual page/FCTY/' \
| docker_process_sql --dont-use-mysql-root-password --database=mysql
# tell docker_process_sql to not use MYSQL_ROOT_PASSWORD since it is not set yet
fi
# Generate random root password
if [ -n "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then
export MYSQL_ROOT_PASSWORD="$(pwgen -1 32)"
mysql_note "GENERATED ROOT PASSWORD: $MYSQL_ROOT_PASSWORD"
fi
# Sets root password and creates root users for non-localhost hosts
local rootCreate=
# default root to listen for connections from anywhere
if [ -n "$MYSQL_ROOT_HOST" ] && [ "$MYSQL_ROOT_HOST" != 'localhost' ]; then
# no, we don't care if read finds a terminating character in this heredoc
# https://unix.stackexchange.com/questions/265149/why-is-set-o-errexit-breaking-this-read-heredoc-expression/265151#265151
read -r -d '' rootCreate <<-EOSQL || true
CREATE USER 'root'@'${MYSQL_ROOT_HOST}' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}' ;
GRANT ALL ON *.* TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ;
EOSQL
fi
local passwordSet=
if [ "$MYSQL_MAJOR" = '5.6' ]; then
# no, we don't care if read finds a terminating character in this heredoc (see above)
read -r -d '' passwordSet <<-EOSQL || true
DELETE FROM mysql.user WHERE user NOT IN ('mysql.sys', 'mysqlxsys', 'root') OR host NOT IN ('localhost') ;
SET PASSWORD FOR 'root'@'localhost'=PASSWORD('${MYSQL_ROOT_PASSWORD}') ;
-- 5.5: https://github.com/mysql/mysql-server/blob/e48d775c6f066add457fa8cfb2ebc4d5ff0c7613/scripts/mysql_secure_installation.sh#L192-L210
-- 5.6: https://github.com/mysql/mysql-server/blob/06bc670db0c0e45b3ea11409382a5c315961f682/scripts/mysql_secure_installation.sh#L218-L236
-- 5.7: https://github.com/mysql/mysql-server/blob/913071c0b16cc03e703308250d795bc381627e37/client/mysql_secure_installation.cc#L792-L818
-- 8.0: https://github.com/mysql/mysql-server/blob/b93c1661d689c8b7decc7563ba15f6ed140a4eb6/client/mysql_secure_installation.cc#L726-L749
DELETE FROM mysql.db WHERE Db='test' OR Db='test\_%' ;
-- https://github.com/docker-library/mysql/pull/479#issuecomment-414561272 ("This is only needed for 5.5 and 5.6")
EOSQL
else
# no, we don't care if read finds a terminating character in this heredoc (see above)
read -r -d '' passwordSet <<-EOSQL || true
ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}' ;
EOSQL
fi
# tell docker_process_sql to not use MYSQL_ROOT_PASSWORD since it is just now being set
docker_process_sql --dont-use-mysql-root-password --database=mysql <<-EOSQL
-- What's done in this file shouldn't be replicated
-- or products like mysql-fabric won't work
SET @@SESSION.SQL_LOG_BIN=0;
${passwordSet}
GRANT ALL ON *.* TO 'root'@'localhost' WITH GRANT OPTION ;
FLUSH PRIVILEGES ;
${rootCreate}
DROP DATABASE IF EXISTS test ;
EOSQL
# Creates a custom database and user if specified
if [ -n "$MYSQL_DATABASE" ]; then
mysql_note "Creating database ${MYSQL_DATABASE}"
docker_process_sql --database=mysql <<<"CREATE DATABASE IF NOT EXISTS \`$MYSQL_DATABASE\` ;"
fi
if [ -n "$MYSQL_USER" ] && [ -n "$MYSQL_PASSWORD" ]; then
mysql_note "Creating user ${MYSQL_USER}"
docker_process_sql --database=mysql <<<"CREATE USER '$MYSQL_USER'@'%' IDENTIFIED BY '$MYSQL_PASSWORD' ;"
if [ -n "$MYSQL_DATABASE" ]; then
mysql_note "Giving user ${MYSQL_USER} access to schema ${MYSQL_DATABASE}"
docker_process_sql --database=mysql <<<"GRANT ALL ON \`${MYSQL_DATABASE//_/\\_}\`.* TO '$MYSQL_USER'@'%' ;"
fi
fi
# 创建replication用户并授权
if [ -n "$MYSQL_REPLICATION_USER" ] && [ -n "$MYSQL_REPLICATION_PASSWORD" ]; then
mysql_note "Creating user $MYSQL_REPLICATION_USER"
docker_process_sql --database=mysql <<<"CREATE USER '$MYSQL_REPLICATION_USER'@'%' IDENTIFIED BY '$MYSQL_REPLICATION_PASSWORD';"
docker_process_sql --database=mysql <<<"GRANT REPLICATION SLAVE,SUPER ON *.* TO '$MYSQL_REPLICATION_USER'@'%';"
docker_process_sql --database=mysql <<<"FLUSH PRIVILEGES ;"
fi
# 创建monitor用户并授权
if [ -n "$MYSQL_MONITOR_USER" ] && [ -n "$MYSQL_MONITOR_PASSWORD" ]; then
mysql_note "Creating user $MYSQL_MONITOR_USER"
docker_process_sql --database=mysql <<<"CREATE USER '$MYSQL_MONITOR_USER'@'%' IDENTIFIED BY '$MYSQL_MONITOR_PASSWORD' WITH MAX_USER_CONNECTIONS 3;"
docker_process_sql --database=mysql <<<"GRANT PROCESS, REPLICATION CLIENT, SELECT ON *.* TO '$MYSQL_MONITOR_USER'@'%';"
docker_process_sql --database=mysql <<<"FLUSH PRIVILEGES ;"
fi
# 创建xbk用户并授权
if [ -n "$MYSQL_XBK_USER" ] && [ -n "$MYSQL_XBK_PASSWORD" ]; then
mysql_note "Creating user $MYSQL_XBK_USER"
docker_process_sql --database=mysql <<<"CREATE USER '$MYSQL_XBK_USER'@'%' IDENTIFIED BY '$MYSQL_XBK_PASSWORD';"
docker_process_sql --database=mysql <<<"GRANT RELOAD, LOCK TABLES, PROCESS, REPLICATION CLIENT,SUPER ON *.* TO '$MYSQL_XBK_USER'@'%';"
docker_process_sql --database=mysql <<<"FLUSH PRIVILEGES ;"
fi
}
_mysql_passfile() {
# echo the password to the "file" the client uses
# the client command will use process substitution to create a file on the fly
# ie: --defaults-extra-file=<( _mysql_passfile )
if [ '--dont-use-mysql-root-password' != "$1" ] && [ -n "$MYSQL_ROOT_PASSWORD" ]; then
cat <<-EOF
[client]
password="${MYSQL_ROOT_PASSWORD}"
EOF
fi
}
# Mark root user as expired so the password must be changed before anything
# else can be done (only supported for 5.6+)
mysql_expire_root_user() {
if [ -n "$MYSQL_ONETIME_PASSWORD" ]; then
docker_process_sql --database=mysql <<-EOSQL
ALTER USER 'root'@'%' PASSWORD EXPIRE;
EOSQL
fi
}
# check arguments for an option that would cause mysqld to stop
# return true if there is one
_mysql_want_help() {
local arg
for arg; do
case "$arg" in
-'?'|--help|--print-defaults|-V|--version)
return 0
;;
esac
done
return 1
}
_main() {
# if command starts with an option, prepend mysqld
if [ "${1:0:1}" = '-' ]; then
set -- mysqld "$@"
fi
# skip setup if they aren't running mysqld or want an option that stops mysqld
if [ "$1" = 'mysqld' ] && ! _mysql_want_help "$@"; then
mysql_note "Entrypoint script for MySQL Server ${MYSQL_VERSION} started."
mysql_check_config "$@"
# Load various environment variables
docker_setup_env "$@"
docker_create_db_directories
# If container is started as root user, restart as dedicated mysql user
if [ "$(id -u)" = "0" ]; then
mysql_note "Switching to dedicated user 'mysql'"
exec gosu mysql "$BASH_SOURCE" "$@"
fi
# there's no database, so it needs to be initialized
if [ -z "$DATABASE_ALREADY_EXISTS" ]; then
docker_verify_minimum_env
# check dir permissions to reduce likelihood of half-initialized database
ls /docker-entrypoint-initdb.d/ > /dev/null
docker_init_database_dir "$@"
mysql_note "Starting temporary server"
docker_temp_server_start "$@"
mysql_note "Temporary server started."
docker_setup_db
docker_process_init_files /docker-entrypoint-initdb.d/*
mysql_expire_root_user
mysql_note "Stopping temporary server"
docker_temp_server_stop
mysql_note "Temporary server stopped"
echo
mysql_note "MySQL init process done. Ready for start up."
echo
fi
fi
exec "$@"
}
# If we are sourced from elsewhere, don't perform any further actions
if ! _is_sourced; then
_main "$@"
fi
# 官方dockerfile
[root@k8s-master mysql-image]# cat dockerfile
#
# NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh"
#
# PLEASE DO NOT EDIT IT DIRECTLY.
#
FROM debian:buster-slim
# add our user and group first to make sure their IDs get assigned consistently, regardless of whatever dependencies get added
RUN groupadd -r mysql && useradd -r -g mysql mysql
RUN apt-get update && apt-get install -y --no-install-recommends gnupg dirmngr && rm -rf /var/lib/apt/lists/*
# add gosu for easy step-down from root
# https://github.com/tianon/gosu/releases
ENV GOSU_VERSION 1.14
RUN set -eux; \
savedAptMark="$(apt-mark showmanual)"; \
apt-get update; \
apt-get install -y --no-install-recommends ca-certificates wget; \
rm -rf /var/lib/apt/lists/*; \
dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')"; \
wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch"; \
wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc"; \
export GNUPGHOME="$(mktemp -d)"; \
gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \
gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; \
gpgconf --kill all; \
rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc; \
apt-mark auto '.*' > /dev/null; \
[ -z "$savedAptMark" ] || apt-mark manual $savedAptMark > /dev/null; \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
chmod +x /usr/local/bin/gosu; \
gosu --version; \
gosu nobody true
RUN mkdir /docker-entrypoint-initdb.d
RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends \
bzip2 \
openssl \
# FATAL ERROR: please install the following Perl modules before executing /usr/local/mysql/scripts/mysql_install_db:
# File::Basename
# File::Copy
# Sys::Hostname
# Data::Dumper
perl \
xz-utils \
zstd \
; \
rm -rf /var/lib/apt/lists/*
RUN set -eux; \
# gpg: key 3A79BD29: public key "MySQL Release Engineering <mysql-build@oss.oracle.com>" imported
key='859BE8D7C586F538430B19C2467B942D3A79BD29'; \
export GNUPGHOME="$(mktemp -d)"; \
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \
mkdir -p /etc/apt/keyrings; \
gpg --batch --export "$key" > /etc/apt/keyrings/mysql.gpg; \
gpgconf --kill all; \
rm -rf "$GNUPGHOME"
ENV MYSQL_MAJOR 5.7
ENV MYSQL_VERSION 5.7.40-1debian10
RUN echo 'deb [ signed-by=/etc/apt/keyrings/mysql.gpg ] http://repo.mysql.com/apt/debian/ buster mysql-5.7' > /etc/apt/sources.list.d/mysql.list
# the "/var/lib/mysql" stuff here is because the mysql-server postinst doesn't have an explicit way to disable the mysql_install_db codepath besides having a database already "configured" (ie, stuff in /var/lib/mysql/mysql)
# also, we set debconf keys to make APT a little quieter
RUN { \
echo mysql-community-server mysql-community-server/data-dir select ''; \
echo mysql-community-server mysql-community-server/root-pass password ''; \
echo mysql-community-server mysql-community-server/re-root-pass password ''; \
echo mysql-community-server mysql-community-server/remove-test-db select false; \
} | debconf-set-selections \
&& apt-get update \
&& apt-get install -y \
mysql-server="${MYSQL_VERSION}" \
# comment out a few problematic configuration values
&& find /etc/mysql/ -name '*.cnf' -print0 \
| xargs -0 grep -lZE '^(bind-address|log)' \
| xargs -rt -0 sed -Ei 's/^(bind-address|log)/#&/' \
# don't reverse lookup hostnames, they are usually another container
&& echo '[mysqld]\nskip-host-cache\nskip-name-resolve' > /etc/mysql/conf.d/docker.cnf \
&& rm -rf /var/lib/apt/lists/* \
&& rm -rf /var/lib/mysql && mkdir -p /var/lib/mysql /var/run/mysqld \
&& chown -R mysql:mysql /var/lib/mysql /var/run/mysqld \
# ensure that /var/run/mysqld (used for socket and lock files) is writable regardless of the UID our mysqld instance ends up having at runtime
&& chmod 1777 /var/run/mysqld /var/lib/mysql
VOLUME /var/lib/mysql
COPY docker-entrypoint.sh /usr/local/bin/
RUN ln -s usr/local/bin/docker-entrypoint.sh /entrypoint.sh # backwards compat
ENTRYPOINT ["docker-entrypoint.sh"]
EXPOSE 3306 33060
CMD ["mysqld"]
如果不想自己从头编译,则可以用下面dockerfile
[root@k8s-master mysql-image]# cat dockerfile
FROM mysql:5.7.40
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
COPY docker-entrypoint.sh /usr/local/bin/
RUN ln -sf usr/local/bin/docker-entrypoint.sh /entrypoint.sh # backwards compat
# 开始编译镜像
[root@k8s-master mysql-image]# docker build . -t mysql-x86:5.7.40
部署主从
准备configmap和statefulset创建主从
[root@k8s-master master-slave]# kubectl create ns mysql
[root@k8s-master master-slave]# cat mysql-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: mysql
namespace: mysql
labels:
app: mysql
data:
master.cnf: |
# Apply this config only on the master.
[mysqld]
log-bin
slave.cnf: |
# Apply this config only on slaves.
[mysqld]
super-read-only
[root@k8s-master master-slave]# kubectl apply -f mysql-configmap.yaml
[root@k8s-master master-slave]# cat mysql-sts.yaml
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
namespace: mysql
spec:
selector:
matchLabels:
app: mysql
serviceName: mysql
replicas: 2
template:
metadata:
labels:
app: mysql
spec:
initContainers:
- name: init-mysql
image: mysql-x86:5.7.40
command:
- bash
- "-c"
- |
set -ex
# Generate mysql server-id from pod ordinal index.
[[ `hostname` =~ -([0-9]+)$ ]] || exit 1
ordinal=${BASH_REMATCH[1]}
echo [mysqld] > /mnt/conf.d/server-id.cnf
# Add an offset to avoid reserved server-id=0 value.
echo server-id=$((100 + $ordinal)) >> /mnt/conf.d/server-id.cnf
# Copy appropriate conf.d files from config-map to emptyDir.
if [[ $ordinal -eq 0 ]]; then
cp /mnt/config-map/master.cnf /mnt/conf.d/
else
cp /mnt/config-map/slave.cnf /mnt/conf.d/
fi
volumeMounts:
- name: conf
mountPath: /mnt/conf.d
- name: config-map
mountPath: /mnt/config-map
- name: clone-mysql
image: registry.cn-shanghai.aliyuncs.com/soulchild/xtrabackup:2.4
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-pass
key: root_pass
command:
- bash
- "-c"
- |
set -ex
# Skip the clone if data already exists.
[[ -d /var/lib/mysql/mysql ]] && exit 0
# Skip the clone on master (ordinal index 0).
[[ `hostname` =~ -([0-9]+)$ ]] || exit 1
ordinal=${BASH_REMATCH[1]}
[[ $ordinal -eq 0 ]] && exit 0
# Clone data from previous peer.
ncat --recv-only mysql-$(($ordinal-1)).mysql 3307 | xbstream -x -C /var/lib/mysql
# Prepare the backup.
xtrabackup --prepare --target-dir=/var/lib/mysql
volumeMounts:
- name: data
mountPath: /var/lib/mysql
subPath: mysql
- name: conf
mountPath: /etc/mysql/conf.d
containers:
- name: mysql
image: mysql-x86:5.7.40
env:
- name: MYSQL_ROOT_HOST
value: '127.0.0.1'
- name: MYSQL_ROOT_PASSWORD
value: "abcd123456"
- name: MYSQL_REPLICATION_USER
value: replication
- name: MYSQL_REPLICATION_PASSWORD
value: "abcd123456"
- name: MYSQL_MONITOR_USER
value: monitor
- name: MYSQL_MONITOR_PASSWORD
value: "abcd123456"
- name: MYSQL_XBK_USER
value: xbk
- name: MYSQL_XBK_PASSWORD
value: "abcd123456"
ports:
- name: mysql
containerPort: 3306
volumeMounts:
- name: data
mountPath: /var/lib/mysql
subPath: mysql
- name: conf
mountPath: /etc/mysql/conf.d
resources:
requests:
cpu: 500m
memory: 1Gi
livenessProbe:
exec:
command: ["mysqladmin", "ping", "-u${MYSQL_MONITOR_USER}", "-p${MYSQL_MONITOR_PASSWORD}"]
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
readinessProbe:
exec:
# Check we can execute queries over TCP (skip-networking is off).
command: ["mysqladmin", "ping", "-u${MYSQL_MONITOR_USER}", "-p${MYSQL_MONIOTR_PASSWORD}"]
initialDelaySeconds: 5
periodSeconds: 2
timeoutSeconds: 1
- name: xtrabackup
image: registry.cn-shanghai.aliyuncs.com/soulchild/xtrabackup:2.4
env:
- name: MYSQL_ROOT_PASSWORD
value: "abcd123456"
- name: MYSQL_REPLICATION_USER
value: replication
- name: MYSQL_REPLICATION_PASSWORD
value: "abcd123456"
- name: MYSQL_MONITOR_USER
value: monitor
- name: MYSQL_MONITOR_PASSWORD
value: "abcd123456"
- name: MYSQL_XBK_USER
value: xbk
- name: MYSQL_XBK_PASSWORD
value: "abcd123456"
ports:
- name: xtrabackup
containerPort: 3307
command:
- bash
- "-c"
- |
set -ex
cd /var/lib/mysql
# Determine binlog position of cloned data, if any.
if [[ -f xtrabackup_slave_info && "x$(<xtrabackup_slave_info)" != "x" ]]; then
# XtraBackup already generated a partial "CHANGE MASTER TO" query
# because we're cloning from an existing slave. (Need to remove the tailing semicolon!)
cat xtrabackup_slave_info | sed -E 's/;$//g' > change_master_to.sql.in
# Ignore xtrabackup_binlog_info in this case (it's useless).
rm -f xtrabackup_slave_info xtrabackup_binlog_info
elif [[ -f xtrabackup_binlog_info ]]; then
# We're cloning directly from master. Parse binlog position.
[[ `cat xtrabackup_binlog_info` =~ ^(.*?)[[:space:]]+(.*?)$ ]] || exit 1
rm -f xtrabackup_binlog_info xtrabackup_slave_info
echo "CHANGE MASTER TO MASTER_LOG_FILE='${BASH_REMATCH[1]}',\
MASTER_LOG_POS=${BASH_REMATCH[2]}" > change_master_to.sql.in
fi
# Check if we need to complete a clone by starting replication.
if [[ -f change_master_to.sql.in ]]; then
echo "Waiting for mysqld to be ready (accepting connections)"
until mysql -h 127.0.0.1 -u${MYSQL_REPLICATION_USER} -p${MYSQL_REPLICATION_PASSWORD} -e "SELECT 1"; do sleep 1; done
echo "Initializing replication from clone position"
mysql -h 127.0.0.1 -u${MYSQL_REPLICATION_USER} -p${MYSQL_REPLICATION_PASSWORD}\
-e "$(<change_master_to.sql.in), \
MASTER_HOST='mysql-0.mysql', \
MASTER_USER='${MYSQL_REPLICATION_USER}', \
MASTER_PASSWORD='${MYSQL_REPLICATION_PASSWORD}', \
MASTER_CONNECT_RETRY=10; \
START SLAVE;" || exit 1
# In case of container restart, attempt this at-most-once.
mv change_master_to.sql.in change_master_to.sql.orig
fi
# Start a server to send backups when requested by peers.
exec ncat --listen --keep-open --send-only --max-conns=1 3307 -c \
"xtrabackup --backup --slave-info --stream=xbstream --host=127.0.0.1 --user=${MYSQL_XBK_USER} --password=${MYSQL_XBK_PASSWORD}"
volumeMounts:
- name: data
mountPath: /var/lib/mysql
subPath: mysql
- name: conf
mountPath: /etc/mysql/conf.d
resources:
requests:
cpu: 100m
memory: 100Mi
- name: mysqld-exporter
image: prom/mysqld-exporter:v0.12.1
args:
- --collect.info_schema.tables
- --collect.info_schema.innodb_tablespaces
- --collect.info_schema.innodb_metrics
- --collect.global_status
- --collect.global_variables
- --collect.slave_status
- --collect.info_schema.processlist
- --collect.perf_schema.tablelocks
- --collect.perf_schema.eventsstatements
- --collect.perf_schema.eventsstatementssum
- --collect.perf_schema.eventswaits
- --collect.auto_increment.columns
- --collect.binlog_size
- --collect.perf_schema.tableiowaits
- --collect.perf_schema.indexiowaits
- --collect.info_schema.userstats
- --collect.info_schema.clientstats
- --collect.info_schema.tablestats
- --collect.info_schema.schemastats
- --collect.perf_schema.file_events
- --collect.perf_schema.file_instances
- --collect.perf_schema.replication_group_member_stats
- --collect.perf_schema.replication_applier_status_by_worker
- --collect.slave_hosts
- --collect.info_schema.innodb_cmp
- --collect.info_schema.innodb_cmpmem
- --collect.info_schema.query_response_time
- --collect.engine_tokudb_status
- --collect.engine_innodb_status
ports:
- containerPort: 9104
protocol: TCP
env:
- name: DATA_SOURCE_NAME
value: "monitor:abcd123456@(127.0.0.1:3306)/"
volumes:
- name: conf
emptyDir: {}
- name: config-map
configMap:
name: mysql
volumeClaimTemplates:
- metadata:
name: data
annotations:
volume.beta.kubernetes.io/storage-class: "nfs-storage"
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
创建主从资源实例
[root@k8s-master master-slave]# kubectl apply -f mysql-sts.yaml
[root@k8s-master master-slave]# kubectl get -f mysql-sts.yaml
NAME READY AGE
statefulset.apps/mysql 2/2 61m
[root@k8s-master master-slave]# kubectl get pod -n mysql -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
mysql-0 3/3 Running 0 62m 10.100.235.248 k8s-master <none> <none>
mysql-1 3/3 Running 1 62m 10.100.235.229 k8s-master <none> <none>
测试主从同步
测试主从数据同步
# 登录主库
[root@k8s-master master-slave]# kubectl -n mysql exec -it mysql-0 -c mysql -- /bin/bash
root@mysql-0:/#
root@mysql-0:/# mysql -uroot -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 2413
Server version: 5.7.35-log MySQL Community Server (GPL)
Copyright (c) 2000, 2021, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> show databases;
+------------------------+
| Database |
+------------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| xtrabackup_backupfiles |
+------------------------+
5 rows in set (0.01 sec)
mysql> create database xadocker;
Query OK, 1 row affected (0.01 sec)
mysql> use xadocker;
Database changed
mysql> create table test_tb(id int(4),name char(10));
Query OK, 0 rows affected (0.02 sec)
mysql> insert into test_tb values(0001,'xadocker');
Query OK, 1 row affected (0.01 sec)
mysql> insert into test_tb values(0002,'xadocker2');
Query OK, 1 row affected (0.00 sec)
# 登录从库查看数据是否同步
[root@k8s-master master-slave]# kubectl -n mysql exec -it mysql-1 -c mysql -- /bin/bash
root@mysql-1:/# mysql -uroot -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 2558
Server version: 5.7.35 MySQL Community Server (GPL)
Copyright (c) 2000, 2021, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> show databases;
+------------------------+
| Database |
+------------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| xadocker |
| xtrabackup_backupfiles |
+------------------------+
6 rows in set (0.02 sec)
mysql> use xadocker;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> select * from test_tb;
+------+-----------+
| id | name |
+------+-----------+
| 1 | xadocker |
| 2 | xadocker2 |
+------+-----------+
2 rows in set (0.00 sec)
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: mysql-0.mysql
Master_User: replication
Master_Port: 3306
Connect_Retry: 10
Master_Log_File: mysql-0-bin.000003
Read_Master_Log_Pos: 1074
Relay_Log_File: mysql-1-relay-bin.000002
Relay_Log_Pos: 1242
Relay_Master_Log_File: mysql-0-bin.000003
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 1074
Relay_Log_Space: 1451
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 100
Master_UUID: 1725e679-6008-11ed-8fa6-d604459b68a9
Master_Info_File: /var/lib/mysql/master.info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set:
Executed_Gtid_Set:
Auto_Position: 0
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
1 row in set (0.00 sec)
扩容从库实例后测试数据同步
[root@k8s-master master-slave]# kubectl scale sts mysql -n mysql --replicas=3
statefulset.apps/mysql scaled
[root@k8s-master master-slave]# kubectl -n mysql exec -it mysql-2 -c mysql -- /bin/bash
root@mysql-2:/# mysql -uroot -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 42
Server version: 5.7.35 MySQL Community Server (GPL)
Copyright (c) 2000, 2021, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> use xadocker;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> select * from test_tb;
+------+-----------+
| id | name |
+------+-----------+
| 1 | xadocker |
| 2 | xadocker2 |
+------+-----------+
2 rows in set (0.01 sec)
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: mysql-0.mysql
Master_User: replication
Master_Port: 3306
Connect_Retry: 10
Master_Log_File: mysql-0-bin.000003
Read_Master_Log_Pos: 1074
Relay_Log_File: mysql-2-relay-bin.000002
Relay_Log_Pos: 322
Relay_Master_Log_File: mysql-0-bin.000003
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 1074
Relay_Log_Space: 531
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 100
Master_UUID: 1725e679-6008-11ed-8fa6-d604459b68a9
Master_Info_File: /var/lib/mysql/master.info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set:
Executed_Gtid_Set:
Auto_Position: 0
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
1 row in set (0.00 sec)
集群内外暴露主从实例服务
在应用中有两种方式实现主从读写分离:
- 暴露主库的代理地址和暴露从库实例代理地址,开发人员在程序中封装读写调用地址即可
- 提供数据库代理中间件负责处理读写分离,比如sqlproxy/mycat等
提供读写两个地址或域名
第一种方式运维侧处理起来比较简单
# 对于写,则程序调用第一个实例的域名:mysql-0.mysql.svc.cluster.local
# 而对于读,则可以再创建一个svc来提供域名: mysql-read.mysql.svc.cluster.local
[root@k8s-master master-slave]# cat mysql-service.yaml
# Headless service for stable DNS entries of StatefulSet members.
apiVersion: v1
kind: Service
metadata:
name: mysql
namespace: mysql
labels:
app: mysql
spec:
ports:
- name: mysql
port: 3306
clusterIP: None
selector:
app: mysql
---
# Client service for connecting to any MySQL instance for reads.
# For writes, you must instead connect to the master: mysql-0.mysql.
apiVersion: v1
kind: Service
metadata:
name: mysql-read
namespace: mysql
labels:
app: mysql
spec:
ports:
- name: mysql
port: 3306
selector:
app: mysql
但是这种方式如何提供集群外部使用呢?因为集群外部无法解析域名,对于mysql-read这个好处理,只需要增加nodeport或loadbalance就可以了,但是对于写该如何操作?
其实这个依然还是通过svc来处理,方式是让这个svc只提供一个pod的转发,可以看下目前创建出来的sts实例labels
[root@k8s-master mysql-exporter]# kubectl get pod -n mysql --show-labels
NAME READY STATUS RESTARTS AGE LABELS
mysql-0 3/3 Running 0 97m app=mysql,controller-revision-hash=mysql-7cb768ff95,statefulset.kubernetes.io/pod-name=mysql-0
mysql-1 3/3 Running 1 96m app=mysql,controller-revision-hash=mysql-7cb768ff95,statefulset.kubernetes.io/pod-name=mysql-1
mysql-2 3/3 Running 1 22m app=mysql,controller-revision-hash=mysql-7cb768ff95,statefulset.kubernetes.io/pod-name=mysql-2
从上面pod的labels可以看出,每个pod都打赏了statefulset.kubernetes.io/pod-name=xxx
的k/v
,而value值正好是pod name,由于sts的网络标识不变的特性,则可以利用这点来创建svc
[root@k8s-master master-slave]# cat mysql-write-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: mysql-write
namespace: mysql
labels:
app: mysql
spec:
ports:
- name: mysql
port: 3306
selector:
app: mysql
statefulset.kubernetes.io/pod-name: mysql-0
[root@k8s-master master-slave]# kubectl apply -f mysql-write-svc.yaml
service/mysql-write configured
[root@k8s-master master-slave]# kubectl get -f mysql-write-svc.yaml
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
mysql-write ClusterIP 10.96.193.60 <none> 3306/TCP 15s
[root@k8s-master master-slave]# kubectl describe -f mysql-write-svc.yaml
Name: mysql-write
Namespace: mysql
Labels: app=mysql
Annotations: Selector: app=mysql,statefulset.kubernetes.io/pod-name=mysql-0
Type: ClusterIP
IP: 10.96.193.60
Port: mysql 3306/TCP
TargetPort: 3306/TCP
Endpoints: 10.100.235.248:3306
Session Affinity: None
Events: <none>
# 此时暴露到集群外就可以采用nodepore或loadbalance的方式,此处略
提供读写代理
埋个坑,后续补充上
prometheus-operator监控mysql
测试获取mysqld_exporter数据
在前面博主已将每个mysqld_exporter运行在pod中,可以测试查看下获取数据
[root@k8s-master master-slave]# kubectl get pods -n mysql -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
mysql-0 3/3 Running 0 106s 10.100.235.243 k8s-master <none> <none>
mysql-1 3/3 Running 0 95s 10.100.235.230 k8s-master <none> <none>
mysql-2 3/3 Running 0 87s 10.100.235.204 k8s-master <none> <none>
[root@k8s-master master-slave]# curl -s 10.100.235.243:9104/metrics | head -n 20
# HELP go_gc_duration_seconds A summary of the GC invocation durations.
# TYPE go_gc_duration_seconds summary
go_gc_duration_seconds{quantile="0"} 3.4808e-05
go_gc_duration_seconds{quantile="0.25"} 5.086e-05
go_gc_duration_seconds{quantile="0.5"} 0.000624944
go_gc_duration_seconds{quantile="0.75"} 0.000657479
go_gc_duration_seconds{quantile="1"} 0.000753488
go_gc_duration_seconds_sum 0.002710554
go_gc_duration_seconds_count 6
# HELP go_goroutines Number of goroutines that currently exist.
# TYPE go_goroutines gauge
go_goroutines 8
# HELP go_info Information about the Go environment.
# TYPE go_info gauge
go_info{version="go1.12.7"} 1
# HELP go_memstats_alloc_bytes Number of bytes allocated and still in use.
# TYPE go_memstats_alloc_bytes gauge
go_memstats_alloc_bytes 2.827152e+06
# HELP go_memstats_alloc_bytes_total Total number of bytes allocated, even if freed.
# TYPE go_memstats_alloc_bytes_total counter
为监控端口创建svc和servicemonitor
[root@k8s-master master-slave]# cat mysql-monitor-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: mysql-monitor
namespace: mysql
labels:
app: mysql-ms
spec:
ports:
- name: monitor
protocol: TCP
port: 9104
selector:
app: mysql
[root@k8s-master master-slave]# cat mysql-exporter-servicemonitor.yaml
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: mysqld-exporter-ms
namespace: monitoring
spec:
jobLabel: mysqld-exporter-ms
endpoints:
- port: monitor
interval: 30s
scheme: http
namespaceSelector:
matchNames:
- mysql
selector:
matchLabels:
app: mysql-ms
grafana上导入dashboard ID: 7371
由于博主这边得svc是采集了master和slave,而该原图标中instance变量不太符合当前得环境取值,需要调整下,博主将instance变量删除,增加以下三个变量:
- job (用于区分多套ms集群)
label_values({name=~"(mysql_binlog_files|mysql_slave_status_seconds_behind_master)"}, job)
- masterPod (用于获取master得pod名称)
label_values({name=~"(mysql_binlog_files)"}, pod)
- slavePod(用于获取slave得pod名称)
label_values({name=~"(mysql_slave_status_master_server_id)"}, pod)
{
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": {
"type": "datasource",
"uid": "grafana"
},
"enable": true,
"hide": false,
"iconColor": "#e0752d",
"limit": 100,
"name": "PMM Annotations",
"showIn": 0,
"tags": [
"pmm_annotation"
],
"target": {
"limit": 100,
"matchAny": false,
"tags": [
"pmm_annotation"
],
"type": "tags"
},
"type": "tags"
}
]
},
"description": "Dashboard from Percona Monitoring and Management project. https://github.com/percona/grafana-dashboards",
"editable": true,
"fiscalYearStartMonth": 0,
"gnetId": 7371,
"graphTooltip": 1,
"id": 34,
"links": [
{
"icon": "dashboard",
"includeVars": true,
"keepTime": true,
"tags": [
"QAN"
],
"targetBlank": false,
"title": "Query Analytics",
"type": "link",
"url": "/graph/dashboard/db/_pmm-query-analytics"
},
{
"asDropdown": true,
"includeVars": true,
"keepTime": true,
"tags": [
"OS"
],
"targetBlank": false,
"title": "OS",
"type": "dashboards"
},
{
"asDropdown": true,
"includeVars": true,
"keepTime": true,
"tags": [
"MySQL"
],
"targetBlank": false,
"title": "MySQL",
"type": "dashboards"
},
{
"asDropdown": true,
"includeVars": true,
"keepTime": true,
"tags": [
"MongoDB"
],
"targetBlank": false,
"title": "MongoDB",
"type": "dashboards"
},
{
"asDropdown": true,
"includeVars": true,
"keepTime": true,
"tags": [
"HA"
],
"targetBlank": false,
"title": "HA",
"type": "dashboards"
},
{
"asDropdown": true,
"includeVars": true,
"keepTime": true,
"tags": [
"Cloud"
],
"targetBlank": false,
"title": "Cloud",
"type": "dashboards"
},
{
"asDropdown": true,
"includeVars": true,
"keepTime": true,
"tags": [
"Insight"
],
"targetBlank": false,
"title": "Insight",
"type": "dashboards"
},
{
"asDropdown": true,
"includeVars": true,
"keepTime": true,
"tags": [
"PMM"
],
"targetBlank": false,
"title": "PMM",
"type": "dashboards"
}
],
"liveNow": false,
"panels": [
{
"datasource": {
"type": "prometheus",
"uid": "P70940297EF37E8D3"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"decimals": 0,
"mappings": [
{
"options": {
"0": {
"text": "No"
},
"1": {
"text": "Yes"
}
},
"type": "value"
}
],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "rgba(161, 18, 18, 0.9)"
},
{
"color": "rgba(237, 129, 40, 0.89)",
"value": 0.5
},
{
"color": "rgba(36, 112, 33, 0.97)",
"value": 1
}
]
},
"unit": "short"
},
"overrides": []
},
"gridPos": {
"h": 4,
"w": 6,
"x": 0,
"y": 0
},
"id": 26,
"interval": "$interval",
"links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "background",
"graphMode": "none",
"justifyMode": "center",
"orientation": "auto",
"reduceOptions": {
"calcs": [
"lastNotNull"
],
"fields": "",
"values": false
},
"textMode": "auto"
},
"pluginVersion": "9.2.4",
"targets": [
{
"calculatedInterval": "10m",
"datasource": {
"type": "prometheus",
"uid": "P70940297EF37E8D3"
},
"datasourceErrors": {},
"editorMode": "code",
"errors": {},
"exemplar": false,
"expr": "mysql_slave_status_slave_io_running{job=~\"${job}\",pod=~\"${slavePod}\"}",
"instant": false,
"interval": "1m",
"intervalFactor": 1,
"legendFormat": "{{pod}}",
"metric": "",
"range": true,
"refId": "A",
"step": 300
}
],
"title": "IO Thread Running",
"type": "stat"
},
{
"datasource": {
"type": "prometheus",
"uid": "P70940297EF37E8D3"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"decimals": 0,
"mappings": [
{
"options": {
"0": {
"text": "No"
},
"1": {
"text": "Yes"
}
},
"type": "value"
}
],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "rgba(161, 18, 18, 0.9)"
},
{
"color": "rgba(237, 129, 40, 0.89)",
"value": 0.5
},
{
"color": "rgba(36, 112, 33, 0.97)",
"value": 1
}
]
},
"unit": "short"
},
"overrides": []
},
"gridPos": {
"h": 4,
"w": 6,
"x": 6,
"y": 0
},
"id": 17,
"interval": "$interval",
"links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "background",
"graphMode": "none",
"justifyMode": "auto",
"orientation": "auto",
"reduceOptions": {
"calcs": [
"lastNotNull"
],
"fields": "",
"values": false
},
"textMode": "auto"
},
"pluginVersion": "9.2.4",
"targets": [
{
"calculatedInterval": "10m",
"datasource": {
"type": "prometheus",
"uid": "P70940297EF37E8D3"
},
"datasourceErrors": {},
"editorMode": "code",
"errors": {},
"exemplar": true,
"expr": "mysql_slave_status_slave_sql_running{job=~\"${job}\",pod=~\"${slavePod}\"}",
"instant": false,
"interval": "1m",
"intervalFactor": 1,
"legendFormat": "{{pod}}",
"metric": "",
"range": true,
"refId": "A",
"step": 300
}
],
"title": "SQL Thread Running",
"transformations": [],
"type": "stat"
},
{
"datasource": {
"type": "prometheus",
"uid": "P70940297EF37E8D3"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"decimals": 0,
"mappings": [
{
"options": {
"0": {
"text": "N/A"
}
},
"type": "value"
}
],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "rgba(50, 172, 45, 0.97)"
},
{
"color": "rgba(237, 129, 40, 0.89)",
"value": 0.5
},
{
"color": "rgba(245, 54, 54, 0.9)",
"value": 1
}
]
},
"unit": "none"
},
"overrides": []
},
"gridPos": {
"h": 4,
"w": 6,
"x": 12,
"y": 0
},
"id": 39,
"interval": "$interval",
"links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "background",
"graphMode": "none",
"justifyMode": "auto",
"orientation": "auto",
"reduceOptions": {
"calcs": [
"lastNotNull"
],
"fields": "",
"values": false
},
"textMode": "auto"
},
"pluginVersion": "9.2.4",
"targets": [
{
"calculatedInterval": "10m",
"datasource": {
"type": "prometheus",
"uid": "P70940297EF37E8D3"
},
"datasourceErrors": {},
"editorMode": "code",
"errors": {},
"expr": "mysql_slave_status_last_errno{job=~\"${job}\",pod=~\"${slavePod}\"}",
"interval": "5m",
"intervalFactor": 1,
"legendFormat": "{{pod}}",
"metric": "",
"range": true,
"refId": "A",
"step": 300
}
],
"title": "Replication Error No",
"type": "stat"
},
{
"datasource": {
"type": "prometheus",
"uid": "P70940297EF37E8D3"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"decimals": 0,
"mappings": [
{
"options": {
"0": {
"text": "No"
},
"1": {
"text": "Yes"
}
},
"type": "value"
}
],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "rgba(50, 172, 45, 0.97)"
},
{
"color": "rgba(237, 129, 40, 0.89)",
"value": 0.5
},
{
"color": "rgba(245, 54, 54, 0.9)",
"value": 1
}
]
},
"unit": "short"
},
"overrides": []
},
"gridPos": {
"h": 4,
"w": 6,
"x": 18,
"y": 0
},
"id": 27,
"interval": "$interval",
"links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "background",
"graphMode": "none",
"justifyMode": "auto",
"orientation": "auto",
"reduceOptions": {
"calcs": [
"lastNotNull"
],
"fields": "",
"values": false
},
"textMode": "auto"
},
"pluginVersion": "9.2.4",
"targets": [
{
"calculatedInterval": "10m",
"datasource": {
"type": "prometheus",
"uid": "P70940297EF37E8D3"
},
"datasourceErrors": {},
"editorMode": "code",
"errors": {},
"expr": "mysql_global_variables_read_only{job=\"$job\"}",
"interval": "5m",
"intervalFactor": 1,
"legendFormat": "{{pod}}",
"metric": "",
"range": true,
"refId": "A",
"step": 300
}
],
"title": "Read Only",
"type": "stat"
},
{
"aliasColors": {
"Lag": "#E24D42"
},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": {
"type": "prometheus",
"uid": "P70940297EF37E8D3"
},
"decimals": 0,
"editable": true,
"error": false,
"fill": 2,
"fillGradient": 0,
"grid": {},
"gridPos": {
"h": 7,
"w": 24,
"x": 0,
"y": 4
},
"hiddenSeries": false,
"id": 16,
"legend": {
"alignAsTable": true,
"avg": true,
"current": false,
"hideEmpty": false,
"max": true,
"min": true,
"rightSide": true,
"show": true,
"total": false,
"values": true
},
"lines": true,
"linewidth": 2,
"links": [],
"nullPointMode": "null",
"options": {
"alertThreshold": true
},
"percentage": false,
"pluginVersion": "9.2.4",
"pointradius": 5,
"points": false,
"renderer": "flot",
"seriesOverrides": [
{
"$$hashKey": "object:420",
"alias": "Lag",
"color": "#E24D42",
"yaxis": 1
}
],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"calculatedInterval": "2m",
"datasource": {
"type": "prometheus",
"uid": "P70940297EF37E8D3"
},
"datasourceErrors": {},
"editorMode": "code",
"errors": {},
"exemplar": false,
"expr": "mysql_slave_status_seconds_behind_master{job=~\"${job}\",pod=~\"${slavePod}\"}",
"format": "time_series",
"instant": false,
"interval": "$interval",
"intervalFactor": 1,
"legendFormat": "{{pod}} Lag",
"metric": "",
"range": true,
"refId": "A",
"step": 300
}
],
"thresholds": [],
"timeRegions": [],
"title": "MySQL Replication Delay",
"tooltip": {
"msResolution": false,
"shared": true,
"sort": 0,
"value_type": "individual"
},
"transformations": [],
"type": "graph",
"xaxis": {
"mode": "time",
"show": true,
"values": []
},
"yaxes": [
{
"$$hashKey": "object:433",
"format": "short",
"logBase": 1,
"min": 0,
"show": true
},
{
"$$hashKey": "object:434",
"format": "short",
"logBase": 1,
"min": 0,
"show": true
}
],
"yaxis": {
"align": false
}
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": {
"type": "prometheus",
"uid": "P70940297EF37E8D3"
},
"editable": true,
"error": false,
"fill": 2,
"fillGradient": 0,
"grid": {},
"gridPos": {
"h": 7,
"w": 12,
"x": 0,
"y": 11
},
"hiddenSeries": false,
"id": 33,
"legend": {
"alignAsTable": true,
"avg": true,
"current": false,
"max": true,
"min": true,
"rightSide": false,
"show": true,
"total": false,
"values": true
},
"lines": true,
"linewidth": 2,
"links": [],
"nullPointMode": "null",
"options": {
"alertThreshold": true
},
"percentage": false,
"pluginVersion": "9.2.4",
"pointradius": 5,
"points": false,
"renderer": "flot",
"seriesOverrides": [
{
"alias": "Size",
"color": "#1F78C1"
}
],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"calculatedInterval": "2m",
"datasource": {
"type": "prometheus",
"uid": "P70940297EF37E8D3"
},
"datasourceErrors": {},
"editorMode": "code",
"errors": {},
"expr": "mysql_binlog_size_bytes{job=~\"${job}\",pod=~\"${masterPod}\"} ",
"interval": "$interval",
"intervalFactor": 1,
"legendFormat": "{{pod}} Size",
"metric": "",
"range": true,
"refId": "A",
"step": 300
}
],
"thresholds": [],
"timeRegions": [],
"title": "Binlogs Size",
"tooltip": {
"msResolution": false,
"shared": true,
"sort": 0,
"value_type": "individual"
},
"type": "graph",
"xaxis": {
"mode": "time",
"show": true,
"values": []
},
"yaxes": [
{
"$$hashKey": "object:710",
"format": "bytes",
"logBase": 1,
"min": 0,
"show": true
},
{
"$$hashKey": "object:711",
"format": "bytes",
"logBase": 1,
"min": 0,
"show": true
}
],
"yaxis": {
"align": false
}
},
{
"aliasColors": {},
"bars": true,
"dashLength": 10,
"dashes": false,
"datasource": {
"type": "prometheus",
"uid": "P70940297EF37E8D3"
},
"decimals": 2,
"editable": true,
"error": false,
"fill": 2,
"fillGradient": 0,
"grid": {},
"gridPos": {
"h": 7,
"w": 12,
"x": 12,
"y": 11
},
"hiddenSeries": false,
"id": 35,
"legend": {
"alignAsTable": true,
"avg": true,
"current": false,
"max": true,
"min": true,
"rightSide": false,
"show": true,
"total": false,
"values": true
},
"lines": false,
"linewidth": 2,
"links": [],
"nullPointMode": "null",
"options": {
"alertThreshold": true
},
"percentage": false,
"pluginVersion": "9.2.4",
"pointradius": 5,
"points": false,
"renderer": "flot",
"seriesOverrides": [
{
"alias": "Size",
"color": "#1F78C1"
}
],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"calculatedInterval": "2m",
"datasource": {
"type": "prometheus",
"uid": "P70940297EF37E8D3"
},
"datasourceErrors": {},
"editorMode": "code",
"errors": {},
"expr": "increase(mysql_binlog_size_bytes{job=~\"${job}\",pod=~\"${masterPod}\"}[1h])",
"interval": "1h",
"intervalFactor": 1,
"legendFormat": "{{pod}} Size",
"metric": "",
"range": true,
"refId": "A",
"step": 3600
}
],
"thresholds": [],
"timeFrom": "24h",
"timeRegions": [],
"title": "Binlog Data Written Hourly",
"tooltip": {
"msResolution": false,
"shared": true,
"sort": 0,
"value_type": "individual"
},
"type": "graph",
"xaxis": {
"mode": "time",
"show": true,
"values": []
},
"yaxes": [
{
"$$hashKey": "object:871",
"format": "bytes",
"logBase": 1,
"min": 0,
"show": true
},
{
"$$hashKey": "object:872",
"format": "bytes",
"logBase": 1,
"min": 0,
"show": true
}
],
"yaxis": {
"align": false
}
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": {
"type": "prometheus",
"uid": "P70940297EF37E8D3"
},
"decimals": 0,
"editable": true,
"error": false,
"fill": 2,
"fillGradient": 0,
"grid": {},
"gridPos": {
"h": 7,
"w": 12,
"x": 0,
"y": 18
},
"hiddenSeries": false,
"id": 34,
"legend": {
"alignAsTable": true,
"avg": true,
"current": false,
"max": true,
"min": true,
"rightSide": false,
"show": true,
"total": false,
"values": true
},
"lines": true,
"linewidth": 2,
"links": [],
"nullPointMode": "null",
"options": {
"alertThreshold": true
},
"percentage": false,
"pluginVersion": "9.2.4",
"pointradius": 5,
"points": false,
"renderer": "flot",
"seriesOverrides": [
{
"alias": "Count",
"color": "#E0752D"
}
],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"calculatedInterval": "2m",
"datasource": {
"type": "prometheus",
"uid": "P70940297EF37E8D3"
},
"datasourceErrors": {},
"editorMode": "code",
"errors": {},
"expr": "mysql_binlog_size_bytes{job=~\"${job}\",pod=~\"${masterPod}\"} ",
"interval": "$interval",
"intervalFactor": 1,
"legendFormat": "{{pod}} Count",
"metric": "",
"range": true,
"refId": "A",
"step": 300
}
],
"thresholds": [],
"timeRegions": [],
"title": "Binlogs Count",
"tooltip": {
"msResolution": false,
"shared": true,
"sort": 0,
"value_type": "individual"
},
"type": "graph",
"xaxis": {
"mode": "time",
"show": true,
"values": []
},
"yaxes": [
{
"$$hashKey": "object:1448",
"format": "none",
"logBase": 1,
"min": 0,
"show": true
},
{
"$$hashKey": "object:1449",
"format": "none",
"logBase": 1,
"min": 0,
"show": true
}
],
"yaxis": {
"align": false
}
},
{
"aliasColors": {},
"bars": true,
"dashLength": 10,
"dashes": false,
"datasource": {
"type": "prometheus",
"uid": "P70940297EF37E8D3"
},
"decimals": 0,
"editable": true,
"error": false,
"fill": 2,
"fillGradient": 0,
"grid": {},
"gridPos": {
"h": 7,
"w": 12,
"x": 12,
"y": 18
},
"hiddenSeries": false,
"id": 36,
"legend": {
"alignAsTable": true,
"avg": true,
"current": false,
"max": true,
"min": true,
"rightSide": false,
"show": true,
"total": false,
"values": true
},
"lines": false,
"linewidth": 2,
"links": [],
"nullPointMode": "null",
"options": {
"alertThreshold": true
},
"percentage": false,
"pluginVersion": "9.2.4",
"pointradius": 5,
"points": false,
"renderer": "flot",
"seriesOverrides": [
{
"alias": "Count",
"color": "#E0752D"
}
],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"calculatedInterval": "2m",
"datasource": {
"type": "prometheus",
"uid": "P70940297EF37E8D3"
},
"datasourceErrors": {},
"editorMode": "code",
"errors": {},
"expr": "increase(mysql_binlog_file_number{job=~\"${job}\",pod=~\"${masterPod}\"}[1h])",
"interval": "1h",
"intervalFactor": 1,
"legendFormat": "{{pod}} Count",
"metric": "",
"range": true,
"refId": "A",
"step": 3600
}
],
"thresholds": [],
"timeFrom": "24h",
"timeRegions": [],
"title": "Binlogs fiile Created Hourly",
"tooltip": {
"msResolution": false,
"shared": true,
"sort": 0,
"value_type": "individual"
},
"type": "graph",
"xaxis": {
"mode": "time",
"show": true,
"values": []
},
"yaxes": [
{
"$$hashKey": "object:1928",
"format": "none",
"logBase": 1,
"min": 0,
"show": true
},
{
"$$hashKey": "object:1929",
"format": "none",
"logBase": 1,
"min": 0,
"show": true
}
],
"yaxis": {
"align": false
}
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": {
"type": "prometheus",
"uid": "P70940297EF37E8D3"
},
"editable": true,
"error": false,
"fill": 2,
"fillGradient": 0,
"grid": {},
"gridPos": {
"h": 7,
"w": 12,
"x": 0,
"y": 25
},
"hiddenSeries": false,
"id": 37,
"legend": {
"alignAsTable": true,
"avg": true,
"current": false,
"max": true,
"min": true,
"rightSide": true,
"show": true,
"total": false,
"values": true
},
"lines": true,
"linewidth": 2,
"links": [],
"nullPointMode": "null",
"options": {
"alertThreshold": true
},
"percentage": false,
"pluginVersion": "9.2.4",
"pointradius": 5,
"points": false,
"renderer": "flot",
"seriesOverrides": [
{
"alias": "Size",
"color": "#BA43A9"
}
],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"calculatedInterval": "2m",
"datasource": {
"type": "prometheus",
"uid": "P70940297EF37E8D3"
},
"datasourceErrors": {},
"editorMode": "code",
"errors": {},
"expr": "mysql_slave_status_relay_log_space{job=~\"${job}\",pod=~\"${slavePod}\"}",
"interval": "$interval",
"intervalFactor": 1,
"legendFormat": "{{pod}} Size",
"metric": "",
"range": true,
"refId": "A",
"step": 300
}
],
"thresholds": [],
"timeRegions": [],
"title": "Relay Log Space",
"tooltip": {
"msResolution": false,
"shared": true,
"sort": 0,
"value_type": "individual"
},
"type": "graph",
"xaxis": {
"mode": "time",
"show": true,
"values": []
},
"yaxes": [
{
"$$hashKey": "object:2011",
"format": "bytes",
"logBase": 1,
"min": 0,
"show": true
},
{
"$$hashKey": "object:2012",
"format": "bytes",
"logBase": 1,
"min": 0,
"show": true
}
],
"yaxis": {
"align": false
}
},
{
"aliasColors": {},
"bars": true,
"dashLength": 10,
"dashes": false,
"datasource": {
"type": "prometheus",
"uid": "P70940297EF37E8D3"
},
"decimals": 2,
"editable": true,
"error": false,
"fill": 2,
"fillGradient": 0,
"grid": {},
"gridPos": {
"h": 7,
"w": 12,
"x": 12,
"y": 25
},
"hiddenSeries": false,
"id": 38,
"legend": {
"alignAsTable": true,
"avg": true,
"current": false,
"max": true,
"min": true,
"rightSide": true,
"show": true,
"total": false,
"values": true
},
"lines": false,
"linewidth": 2,
"links": [],
"nullPointMode": "null",
"options": {
"alertThreshold": true
},
"percentage": false,
"pluginVersion": "9.2.4",
"pointradius": 5,
"points": false,
"renderer": "flot",
"seriesOverrides": [
{
"alias": "Size",
"color": "#BA43A9"
}
],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"calculatedInterval": "2m",
"datasource": {
"type": "prometheus",
"uid": "P70940297EF37E8D3"
},
"datasourceErrors": {},
"editorMode": "code",
"errors": {},
"expr": "increase(mysql_slave_status_relay_log_space{job=~\"${job}\",pod=~\"${slavePod}\"}[1h])",
"interval": "1h",
"intervalFactor": 1,
"legendFormat": "{{pod}} Size",
"metric": "",
"range": true,
"refId": "A",
"step": 3600
}
],
"thresholds": [],
"timeFrom": "24h",
"timeRegions": [],
"title": "Relay Log Written Hourly",
"tooltip": {
"msResolution": false,
"shared": true,
"sort": 0,
"value_type": "individual"
},
"type": "graph",
"xaxis": {
"mode": "time",
"show": true,
"values": []
},
"yaxes": [
{
"$$hashKey": "object:2253",
"format": "bytes",
"logBase": 1,
"min": 0,
"show": true
},
{
"$$hashKey": "object:2254",
"format": "bytes",
"logBase": 1,
"min": 0,
"show": true
}
],
"yaxis": {
"align": false
}
}
],
"refresh": "1m",
"schemaVersion": 37,
"style": "dark",
"tags": [
"Percona",
"MySQL"
],
"templating": {
"list": [
{
"allFormat": "glob",
"auto": true,
"auto_count": 200,
"auto_min": "1s",
"current": {
"selected": false,
"text": "auto",
"value": "$__auto_interval_interval"
},
"datasource": "P70940297EF37E8D3",
"hide": 0,
"includeAll": false,
"label": "Interval",
"multi": false,
"multiFormat": "glob",
"name": "interval",
"options": [
{
"selected": true,
"text": "auto",
"value": "$__auto_interval_interval"
},
{
"selected": false,
"text": "1s",
"value": "1s"
},
{
"selected": false,
"text": "5s",
"value": "5s"
},
{
"selected": false,
"text": "1m",
"value": "1m"
},
{
"selected": false,
"text": "5m",
"value": "5m"
},
{
"selected": false,
"text": "1h",
"value": "1h"
},
{
"selected": false,
"text": "6h",
"value": "6h"
},
{
"selected": false,
"text": "1d",
"value": "1d"
}
],
"query": "1s,5s,1m,5m,1h,6h,1d",
"refresh": 2,
"skipUrlSync": false,
"type": "interval"
},
{
"allFormat": "glob",
"current": {
"selected": false,
"text": "mysql-monitor",
"value": "mysql-monitor"
},
"datasource": {
"type": "prometheus",
"uid": "P70940297EF37E8D3"
},
"definition": "label_values({__name__=~\"(mysql_binlog_files|mysql_slave_status_seconds_behind_master)\"}, job)",
"hide": 0,
"includeAll": false,
"label": "job",
"multi": false,
"multiFormat": "regex values",
"name": "job",
"options": [],
"query": {
"query": "label_values({__name__=~\"(mysql_binlog_files|mysql_slave_status_seconds_behind_master)\"}, job)",
"refId": "StandardVariableQuery"
},
"refresh": 1,
"refresh_on_load": false,
"regex": "",
"skipUrlSync": false,
"sort": 1,
"type": "query",
"useTags": false
},
{
"current": {
"selected": false,
"text": "All",
"value": "$__all"
},
"datasource": {
"type": "prometheus",
"uid": "P70940297EF37E8D3"
},
"definition": "label_values({__name__=~\"(mysql_binlog_files)\"}, pod)",
"hide": 0,
"includeAll": true,
"label": "master pod",
"multi": false,
"name": "masterPod",
"options": [],
"query": {
"query": "label_values({__name__=~\"(mysql_binlog_files)\"}, pod)",
"refId": "StandardVariableQuery"
},
"refresh": 1,
"regex": "",
"skipUrlSync": false,
"sort": 0,
"type": "query"
},
{
"current": {
"selected": true,
"text": [
"All"
],
"value": [
"$__all"
]
},
"datasource": {
"type": "prometheus",
"uid": "P70940297EF37E8D3"
},
"definition": "label_values({__name__=~\"(mysql_slave_status_master_server_id)\"}, pod)",
"hide": 0,
"includeAll": true,
"label": "slave pod",
"multi": true,
"name": "slavePod",
"options": [],
"query": {
"query": "label_values({__name__=~\"(mysql_slave_status_master_server_id)\"}, pod)",
"refId": "StandardVariableQuery"
},
"refresh": 1,
"regex": "",
"skipUrlSync": false,
"sort": 0,
"type": "query"
}
]
},
"time": {
"from": "now-3h",
"to": "now"
},
"timepicker": {
"collapse": false,
"enable": true,
"hidden": false,
"notice": false,
"now": true,
"refresh_intervals": [
"5s",
"10s",
"30s",
"1m",
"5m",
"15m",
"30m",
"1h",
"2h",
"1d"
],
"status": "Stable",
"time_options": [
"5m",
"15m",
"1h",
"6h",
"12h",
"24h",
"2d",
"7d",
"30d"
],
"type": "timepicker"
},
"timezone": "browser",
"title": "MySQL Replication",
"uid": "_9zrwMHmk",
"version": 5,
"weekStart": ""
}
ARM架构平台镜像提供
找了下官方,似乎只有8.0起的arm镜像,没有5.x,看啦只能自己编译一个,参考后续文章~~~~