暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Prometheus Grafana之Oracle监控无侵入部署方案

MeetDB 2022-09-16
3563



    自从prometheus监控oracle的文章发出后,好多朋友留言咨询讨论oracle监控的技术知识,这里也汇总整理了一期资料,作为对读者朋友的回馈,本文主要介绍oracle exporter的无侵入部署,部署过oracle exporter的朋友都知道,当前的exporter是不支持11G,12C数据库环境的,部署时需要替换成18C的库文件,这个小小的操作在生产环境通常是不被允许的,经过深入学习,发现我们是可以通过另外一种方式去取代的,数据库上仅需要开放监控用户即可,实现无需数据库其他操作,提升了安全保险性。


    这里核心用到的一个环境变量是DSN,该环境变量的作用是告诉exporter往哪里链接,如下配置。

    DATA_SOURCE_NAME=username/password@tcps://dbhost:port/service

    在默认部署版本中,我们将该环境变量添加到.bash_profile文件中。如果我们将exporter部署到其他机器,不在数据库服务器部署,那么同样,仅需要将DSN告诉exporter即可。这里我推荐将exporter部署到prometheus服务器,管理方便。


        如果在prometheus服务器部署oracle exporter,则我们需要需要在该服务器部署oracle客户端,供exporter调用。不同数据库对应的exporter,我们通过给exporter指定不同的端口即可做区分。


    简单介绍安装oracle客户端:

        准备如下三个安装包,通过rpm -ivh安装即可。

      [root@Prometheus oracle]# ll
      total 104900
      -rw-r--r-- 1 oracle oracle 51434432 Oct 25 11:13 oracle-instantclient18.3-basic-18.3.0.0.0-3.x86_64.rpm
      -rw-r--r-- 1 root root 610364 Oct 25 11:23 oracle-instantclient18.3-devel-18.3.0.0.0-3.x86_64.rpm
      -rw-r--r-- 1 root root 709700 Oct 25 11:12 oracle-instantclient18.3-sqlplus-18.3.0.0.0-3.x86_64.rpm
      [root@Prometheus oracle]#

          添加环境变量,这里如果创建oracle用户,就加入到oracle用户家目录的.bash_profile文件,如果用root,则加入到root用户家目录下的.bash_profile。

        export ORACLE_HOME=/usr/lib/oracle/18.3/client64
        export PATH=$PATH:/usr/lib/oracle/18.3/client64/bin
        export LD_LIBRARY_PATH=/usr/lib/oracle/18.3/client64/lib

            测试使用sqlplus是否正常执行:

          [oracle@Prometheus ~]$ sqlplus
          sqlplus: error while loading shared libraries: libnsl.so.1: cannot open shared object file: No such file or directory
          [oracle@Prometheus ~]$

          如上图,就是缺包报错,这里推荐使用ldd查看缺少的具体是哪个文件,然后针对性安装缺少的包。

            [oracle@Prometheus ~]$ ldd sqlplus
            ldd: ./sqlplus: No such file or directory
            [oracle@Prometheus ~]$ ldd usr/lib/oracle/18.3/client64/bin/sqlplus
            linux-vdso.so.1 (0x00007ffcee967000)
            libsqlplus.so => /usr/lib/oracle/18.3/client64/lib/libsqlplus.so (0x00007f78c6b8d000)
            libclntsh.so.18.1 => /usr/lib/oracle/18.3/client64/lib/libclntsh.so.18.1 (0x00007f78c2c1b000)
            libclntshcore.so.18.1 => /usr/lib/oracle/18.3/client64/lib/libclntshcore.so.18.1 (0x00007f78c2639000)
            libmql1.so => /usr/lib/oracle/18.3/client64/lib/libmql1.so (0x00007f78c23d9000)
            libipc1.so => /usr/lib/oracle/18.3/client64/lib/libipc1.so (0x00007f78c1f6a000)
            libnnz18.so => /usr/lib/oracle/18.3/client64/lib/libnnz18.so (0x00007f78c1815000)
            libdl.so.2 => /lib64/libdl.so.2 (0x00007f78c1611000)
            libm.so.6 => /lib64/libm.so.6 (0x00007f78c128f000)
            libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f78c106f000)
            libnsl.so.1 => not found
            librt.so.1 => /lib64/librt.so.1 (0x00007f78c0e66000)
            libaio.so.1 => /lib64/libaio.so.1 (0x00007f78c0c63000)
            libresolv.so.2 => /lib64/libresolv.so.2 (0x00007f78c0a4c000)
            libc.so.6 => /lib64/libc.so.6 (0x00007f78c0688000)
            libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f78c0470000)
            libnsl.so.1 => not found
            libons.so => /usr/lib/oracle/18.3/client64/lib/libons.so (0x00007f78c0220000)
            lib64/ld-linux-x86-64.so.2 (0x00007f78c6e81000)
            libnsl.so.1 => not found
            libnsl.so.1 => not found
            [oracle@Prometheus ~]$ yum repolist */libnsl.so.1

            如上报错,我们单独安装libns1.so.1即可

              yum -y install libnsl.so.1

              此时,我们在prometheus安装oracle exporter后,就可以声明一个DSN,然后启动。如下:

                export DATA_SOURCE_NAME=....
                nohup /app/monitor/exporter/oracledb_exporter -default.metrics /app/monitor/exporter/single-metrics.toml -web.listen-address :9161  -query.timeout 10 1>9161.log 2>&1 &"


                如上,我们启动大量的exporter可能非常费时间,管理也不方便。这里我自己写了一个脚本进行集中管理,包含一个脚本,和一个DSN记录文件。


                这里分享给大家:

                  #Oracle exporter 参数文件
                  #配置说明:
                  # 每行代表一个exporter的参数
                  # DSN: 被监控数据库连接信息
                  # Port: exporter 启动端口,每个exporter唯一,建议从9161开始使用
                  # SQLTIMEOUT: SQL执行查询超时时间设置,建议10s
                  # RAC?: 数据库是否为rac环境,1表示是,0表示不是。根据此状态自动选择对应采集项文件
                  # YEWU: 是否启用业务监控脚本,1表示启用,0表示不启用
                  #
                  #Exporter List:
                  #
                  # DSN Port SQLTIMEOUT RAC? YEWU
                  #---------------------------------------- ----- ----------- ----- -----
                  dbsnmp/dbsnmp@192.168.100.100:1521/dbname 9161 10 1 1


                  管理脚本:

                    #!/bin/bash
                    #
                    # 创建日期: 2021-10-27
                    # 创建人员:Kevin YAN
                    # 当前版本: 1.3
                    #
                    # 脚本说明:
                    # 该脚本实现无侵入部署oracle exporter的日常启停及查看功能
                    #
                    # 更新日志记录
                    ########################################################################################################
                    # 变更日期 变更人员 变更内容
                    #------------------ ------------ -----------------------------------------------------------------------
                    #        2021/11/21 Kevin YAN        增加过滤参数文件exporter.ini中空行及注释行,解决存在空行时脚本报错问题;
                    # 2021/11/26 Kevin YAN 增加oracle单机,rac调用不同metrics文件,增加是否启用业务metrics;
                    # 2021/12/23 Kevin YAN 增加参数目录,使兼容mysql exporter无侵入部署;
                    #
                    #########################################################################################################


                    #声明ORACLE Client环境变量
                    export ORACLE_HOME=/usr/lib/oracle/18.3/client64
                    export PATH=$PATH:/usr/lib/oracle/18.3/client64/bin
                    export LD_LIBRARY_PATH=/usr/lib/oracle/18.3/client64/lib




                    #配置相关路径,如果部署路径发生改变,仅修改路径即可
                    init_dir='/app/monitor/scripts'
                    log_dir='/app/monitor/log'


                    #配置oracle相关路径
                    oracledb_exporter='/app/monitor/exporter/oracledb_exporter'
                    rac_metrics_path='/app/monitor/exporter/rac-metrics.toml'
                    single_metrics_path='/app/monitor/exporter/single-metrics.toml'
                    yewu_metrics_path='/app/monitor/exporter/yewu-metrics.toml'


                    #过滤配置文件中空行及注释行
                    if [ -f $init_dir/exporter-oracle.ini ]; then
                    egrep -v '^#|^$' $init_dir/exporter-oracle.ini > tmp/.exporter-oracle.ini
                    oracle_init_file='/tmp/.exporter-oracle.ini'
                    fi




                    #全局声明位置变量
                    arg1=$1
                    arg2=$2
                    arg3=$3


                    #定义帮助函数
                    usage(){
                    cat <<EOF
                    Usage: $0 [Options] [Options]
                    -list List all oracle exporter in exporter-oracle.ini
                    -start
                    -ip Specify you will start oracle exporter of ip;
                    -port Specify you will start oracle exporter of port;
                    all start all instance in exporter.ini
                    -stop
                    -ip Specify you will stop oracle exporter of ip;
                    -port Specify you will stop oracle exporter of port;
                    all stop all instance in exporter-oracle.ini
                    EOF
                    exit 1
                    }




                    #定义展示函数
                    #展示当前配置文件中配置的数据源exporter状态
                    list_active_exporter(){
                    printf "\n%-28s %-6s %-9s %-6s %-6s %-15s %-30s\n" "Instance" "Port" "Timeout" "Rac?" "Yewu" "Status" "Log"
                    echo "--------------------------- ------ --------- ------ ------ -------- -----------------------------------------------"


                    while read line
                    do
                    dsn=$(echo "${line}" |awk '{print $1}')
                    port=$(echo "${line}" |awk '{print $2}')
                    query_timeout=$(echo "${line}" |awk '{print $3}')
                    rac=$(echo "${line}" |awk '{print $4}')
                    yewu=$(echo "${line}" |awk '{print $5}')


                    status=$(ps -ef | grep oracledb| grep $port | wc -l )


                    instance=$(echo "$dsn" | awk -F"@" '{print $2}')

                    if [ "$status" -eq 1 ]; then

                    printf "%-28s %-9s %-8s %-6s %-4s %-7s %-30s\n" "$instance" "$port" "$query_timeout" "$rac" "$yewu" "Active" "$log_dir/$port.log"
                    else
                    printf "%-28s %-9s %-8s %-6s %-4s %-7s %-30s\n" "$instance" "$port" "$query_timeout" "$rac" "$yewu" "Dead" "$log_dir/$port.log"
                    fi
                    done < $oracle_init_file
                    echo "-------------------------------------------------------------------------------------------------------------------"
                    }


                    #定义全部exporter启动函数
                    #启动exprter.ini文件中配置的所有exporter
                    all_exporter_start(){
                    while read line
                    do
                    dsn=$(echo "${line}" |awk '{print $1}')
                    port=$(echo "${line}" |awk '{print $2}')
                    query_timeout=$(echo "${line}" |awk '{print $3}')
                    instance=$(echo "$dsn" | awk -F"@" '{print $2}')


                    rac=$(echo "${line}" |awk '{print $4}')
                    yewu=$(echo "${line}" |awk '{print $5}')

                    status=$(ps -ef | grep oracledb | grep $port | wc -l )


                    if [ "$status" -eq 1 ]; then
                    printf "$instance Started,not need to be executed again.\n"
                    else
                    printf "Starting $instance ...\n"
                    echo "echo env racvalue:"$rac
                    if [ "$rac" -eq 2 ]; then
                    default_metrics="-default.metrics $rac_metrics_path"
                    else
                    default_metrics="-default.metrics $single_metrics_path"
                    fi


                    if [ "$yewu" -eq 1 ]; then
                    custom_metrics="-custom.metrics $yewu_metrics_path"
                    else
                    custom_metrics=""
                    fi


                    export DATA_SOURCE_NAME=$dsn
                    eval "nohup $oracledb_exporter $default_metrics $custom_metrics -web.listen-address :$port -query.timeout $query_timeout 1>$log_dir/$port.log 2>&1 &"
                    if [ $? -eq 0 ]; then
                    printf "Success started $instance \n"
                    else
                    printf "Fail started, For more information, please see file: $log_dir/$port.log\n"
                    fi
                    fi
                    done < $oracle_init_file
                    }


                    #定义启动单一exporter函数
                    #启动exprter.ini文件中配置的某一个exporter,支持ip和端口两种方式启动
                    single_exporter_start(){


                    instance_info=$(grep $arg3 $oracle_init_file)
                    dsn=$(echo "${instance_info}" |awk '{print $1}')
                    query_timeout=$(echo "${instance_info}" |awk '{print $3}')
                    rac=$(echo "${instance_info}" |awk '{print $4}')
                    yewu=$(echo "${instance_info}" |awk '{print $5}')

                    instance=$(echo "$dsn" | awk -F"@" '{print $2}')






                    if [ -z "$instance_info" ]; then
                    echo "$arg3 not exist in $init_dir/exporter-oracle.ini"
                    break;
                    else
                    port=$(echo "${instance_info}" |awk '{print $2}')
                    status=$(ps -ef | grep oracledb | grep $arg3 | wc -l )


                    if [ "$status" -eq 1 ]; then
                    printf "$instance Started,not need to be executed again.\n"
                    else
                    printf "Starting $instance ... \n"


                    if [ "$rac" -eq 1 ]; then
                    default_metrics="-default.metrics $rac_metrics_path"
                    else
                    default_metrics="-default.metrics $single_metrics_path"
                    fi


                    if [ "$yewu" -eq 1 ]; then
                    custom_metrics="-custom.metrics $yewu_metrics_path"
                    else
                    custom_metrics=""
                    fi


                    export DATA_SOURCE_NAME=$dsn
                    eval "nohup $oracledb_exporter $default_metrics $custom_metrics -web.listen-address :$port -query.timeout $query_timeout 1>$log_dir/$port.log 2>&1 &"
                    if [ $? -eq 0 ]; then
                    printf "Success started $instance \n"
                    else
                    printf "Fail started, For more information, please see file: $log_dir/$port.log\n"
                    fi
                    fi
                    fi
                    }




                    #定义关闭exporter函数
                    #关闭exprter.ini文件中配置的全部exporter
                    all_exporter_stop(){
                    pkill oracledb
                    }




                    #定义关闭单一exporter函数
                    #关闭exprter.ini文件中配置的某一个exporter,支持ip和端口两种方式关闭
                    single_exporter_stop(){

                    instance_info=$(grep $arg3 $oracle_init_file)


                    dsn=$(echo "${instance_info}" |awk '{print $1}')
                    instance=$(echo "$dsn" | awk -F"@" '{print $2}')


                    if [ -z "$instance_info" ]; then
                    echo "$arg3 not exist in $init_dir/exporter-oracle.ini"
                    break;
                    else
                    port=$(echo "${instance_info}" |awk '{print $2}')
                    status=$(ps -ef | grep oracledb | grep $arg3 | wc -l )
                    if [ "$status" -eq 1 ]; then
                    ps -ef | grep oracledb | grep $port | awk '{print $2}'| xargs kill -9
                    if [ $? -eq 0 ]; then
                    printf "Success stop $instance \n"
                    fi
                    else
                    echo "Instance $instance is not started,not need stop."
                    fi
                    fi


                    }






                    #定义主函数
                    #实现脚本输入不同参数实现不同功能
                    case $arg1 in
                    -list|-l|-LIST|-L)
                    list_active_exporter;
                    ;;
                    -start|-START)
                    case $arg2 in
                    -ip|-IP)
                    single_exporter_start
                    list_active_exporter
                    ;;
                    -port|-p|-PORT|-P)
                    single_exporter_start
                    list_active_exporter
                    ;;
                    all)
                    all_exporter_start
                    list_active_exporter
                    ;;
                    *)
                    exit;
                    ;;
                    esac
                    ;;
                    -stop|-STOP)
                    case $arg2 in
                    -ip|-IP)
                    single_exporter_stop
                    list_active_exporter
                    ;;
                    -port|-p|-PORT|-P)
                    single_exporter_stop
                    list_active_exporter
                    ;;
                    all)
                    all_exporter_stop
                    list_active_exporter
                    ;;
                    *)
                    exit;
                    ;;
                    esac
                    ;;
                    *)
                    usage
                    ;;
                    esac








                    脚本逻辑为,自动解析DSN文件,然后针对行启动或停止。

                    脚本目前支持查看列表,启动/停止单个exporter,启动/停止所有exporter。

                    使用方式:

                      sh exporter_manager.sh -list          --查看列表,来源DSN记录文件
                      sh exporter_manager.sh -start -ip 192.168.100.100  --启动单个
                      sh exporter_manager.sh -start -port 9161           --启动单个
                      sh exporter_manager.sh -start all                  --启动所有
                      sh exporter_manager.sh -stop -ip 192.168.100.100   --停止单个
                      sh exporter_manager.sh -stop -port 9161            --停止单个
                      sh exporter_manager.sh -stop all                   --停止所有


                          如上启动完成后,prometheus配置文件需将db的监控ip,修改为prometheus服务器IP,端口同样修改,保证prometheus能链接到修改后的exporter服务上。

                           

                          如上,便实现了oracle exporter的外迁,避免了在数据库服务器的改动。核心原理便是理解DSN的作用,然后进行外迁,通过不同端口来区分不同的DB,实现整体的无侵入部署。


                          值得一提的是,mysql的监控同样支持该方法。本文仅提供一个思路,该思路方案,已经在大量客户环境实际使用。感兴趣的朋友可以自己测试,也可找作者交流。


                      更多技术细节,欢迎关注公众号联系作者交流。


                      关注更多精彩



                      文章转载自MeetDB,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                      评论