1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Libertyの性能情報をPythonのSidecarで取得する(restConnector)

Last updated at Posted at 2019-01-07

Libertyの性能情報をREST APIで取得するPythonのスクリプトを作成し、サイドカーコンテナとして動かしてみたメモ。

なお、Libertyの性能情報をREST APIで取得するには、JMXのRest Connectorを使う方法とMicroProfile Metricを使う方法があり、今回試しているのは前者。

mpMetricを使う方法は以下。

参考リンク

ローカルLibertyの準備

はじめにローカルでLibertyを動かして確認する。以下のようなserver.xmlでLibertyを起動する。

monitor-1.0フィーチャーを追加することでWebSphere:type=JvmStatsWebSphere:type=ThreadPoolStatsなどのパフォーマンスデータが追加で取得できるようになる。ローカルJMX接続にはlocalConnector-1.0が必要であり、REST APIでの接続にはrestConnector-2.0が必要。また、RESTでは認証のための管理者ロールを持つユーザーが必要。

server.xml
<server description="new server">

    <!-- Enable features -->
    <featureManager>
        <feature>webProfile-8.0</feature>
        <feature>monitor-1.0</feature>
        <feature>localConnector-1.0</feature>
        <feature>restConnector-2.0</feature>
    </featureManager>

    <!-- To access this server from a remote client add a host attribute to the following element, e.g. host="*" -->
    <httpEndpoint id="defaultHttpEndpoint"
                  host="*"
                  httpPort="9080"
                  httpsPort="9443" />

    <keyStore id="defaultKeyStore" password="password"/>

    <basicRegistry>
        <user name="jmxadmin" password="password" />
    </basicRegistry>

    <administrator-role>
        <user>jmxadmin</user>
    </administrator-role>

    <!-- Automatically expand WAR files and EAR files -->
    <applicationManager autoExpand="true"/>

    <applicationMonitor updateTrigger="mbean"/>

    <webApplication id="sample" location="sample.war" name="sample"/>

</server>

jconsole

Libertyの性能情報としてどのような情報がとれるのかをjconsoleで確認してみる。

ローカルJMX接続

jconsoleを起動する。

jconsole

「ローカル・プロセス」でws-server.jar defaultServerを選択する。

image.png

あるいは、${server.output.dir}/logs/state/com.ibm.ws.jmx.local.address の内容を「リモート・プロセス」に入力する。こちらの方がより高い信頼性があるとKnowledgeCenterには書いてある。どちらの場合も、セキュアな接続は失敗するので非セキュアで接続する。

image.png

MBeansタブでどのような情報が取得できるのか確認できる。

image.png image.png

REST接続

jconsoleからREST接続するのは少々ややこしい。

jconsoleにいろいろオプションをつけて起動する必要がある。

jconsole \
  -J-Djava.class.path=${JAVA_HOME}/lib/jconsole.jar:${JAVA_HOME}/lib/tools.jar:${WLP_HOME}/clients/restConnector.jar \
  -J-Djavax.net.ssl.trustStore=${WLP_HOME}/usr/servers/defaultServer/resources/security/key.jks \
  -J-Djavax.net.ssl.trustStorePassword=password \
  -J-Djavax.net.ssl.trustStoreType=jks

${server.output.dir}/logs/state/com.ibm.ws.jmx.rest.address の内容を「リモート・プロセス」に入力する。このときの接続先のホスト名は証明書のCNと一致する必要があるので、192.168.99.1とかになっていたらlocalhostにする必要があるかもしれない。ブラウザで証明書を確認してそれに合わせること。

image.png image.png image.png

curl

curlコマンドでREST APIから情報がとれるのかを確認する。https://localhost:9443/IBMJMXConnectorREST/mbeans/でどのようなMBeanがあるのか確認できる。以下ではWebSphereを含むもののみを抽出。ここで返されているURLにアクセスすることで性能情報を取得できる。

$ curl -s -k --basic -u jmxadmin:password https://localhost:9443/IBMJMXConnectorREST/mbeans/ | jq '.[] | select( .objectName | test("WebSphere") )'
{
  "objectName": "WebSphere:type=ServletStats,name=com.ibm.ws.jmx.connector.server.rest.JMXRESTProxyServlet",
  "className": "com.ibm.ws.webcontainer.monitor.ServletStats",
  "URL": "/IBMJMXConnectorREST/mbeans/WebSphere%3Aname%3Dcom.ibm.ws.jmx.connector.server.rest.JMXRESTProxyServlet%2Ctype%3DServletStats"
}
{
  "objectName": "WebSphere:name=com.ibm.websphere.config.mbeans.FeatureListMBean",
  "className": "com.ibm.ws.config.featuregen.internal.FeatureListMBeanImpl",
  "URL": "/IBMJMXConnectorREST/mbeans/WebSphere%3Aname%3Dcom.ibm.websphere.config.mbeans.FeatureListMBean"
}
{
  "objectName": "WebSphere:name=com.ibm.websphere.runtime.update.RuntimeUpdateNotificationMBean",
  "className": "com.ibm.ws.runtime.update.internal.RuntimeUpdateNotificationMBeanImpl",
  "URL": "/IBMJMXConnectorREST/mbeans/WebSphere%3Aname%3Dcom.ibm.websphere.runtime.update.RuntimeUpdateNotificationMBean"
}
{
  "objectName": "WebSphere:name=com.ibm.ws.jmx.mbeans.sessionManagerMBean",
  "className": "com.ibm.ws.session.SessionManagerMBeanImpl",
  "URL": "/IBMJMXConnectorREST/mbeans/WebSphere%3Aname%3Dcom.ibm.ws.jmx.mbeans.sessionManagerMBean"
}
{
  "objectName": "WebSphere:name=com.ibm.ws.config.serverSchemaGenerator",
  "className": "com.ibm.ws.config.schemagen.internal.ServerSchemaGeneratorImpl",
  "URL": "/IBMJMXConnectorREST/mbeans/WebSphere%3Aname%3Dcom.ibm.ws.config.serverSchemaGenerator"
}
{
  "objectName": "WebSphere:feature=kernel,name=ServerInfo",
  "className": "com.ibm.ws.kernel.server.internal.ServerInfoMBeanImpl",
  "URL": "/IBMJMXConnectorREST/mbeans/WebSphere%3Afeature%3Dkernel%2Cname%3DServerInfo"
}
{
  "objectName": "WebSphere:type=ThreadPoolStats,name=Default Executor",
  "className": "com.ibm.ws.monitors.helper.ThreadPoolStats",
  "URL": "/IBMJMXConnectorREST/mbeans/WebSphere%3Aname%3DDefault+Executor%2Ctype%3DThreadPoolStats"
}
{
  "objectName": "WebSphere:name=com.ibm.ws.jmx.mbeans.generatePluginConfig",
  "className": "com.ibm.ws.webcontainer.osgi.mbeans.GeneratePluginConfigMBean",
  "URL": "/IBMJMXConnectorREST/mbeans/WebSphere%3Aname%3Dcom.ibm.ws.jmx.mbeans.generatePluginConfig"
}
{
  "objectName": "WebSphere:feature=PluginUtility,name=PluginConfigRequester",
  "className": "com.ibm.ws.webserver.plugin.runtime.requester.PluginConfigRequesterImpl",
  "URL": "/IBMJMXConnectorREST/mbeans/WebSphere%3Afeature%3DPluginUtility%2Cname%3DPluginConfigRequester"
}
{
  "objectName": "WebSphere:feature=CacheAdmin,type=DynaCache,name=DistributedMap",
  "className": "com.ibm.ws.cache.MBeans",
  "URL": "/IBMJMXConnectorREST/mbeans/WebSphere%3Afeature%3DCacheAdmin%2Cname%3DDistributedMap%2Ctype%3DDynaCache"
}
{
  "objectName": "WebSphere:feature=channelfw,type=endpoint,name=defaultHttpEndpoint",
  "className": "com.ibm.ws.channelfw.internal.chains.EndPointInfoImpl",
  "URL": "/IBMJMXConnectorREST/mbeans/WebSphere%3Afeature%3Dchannelfw%2Cname%3DdefaultHttpEndpoint%2Ctype%3Dendpoint"
}
{
  "objectName": "WebSphere:type=SessionStats,name=default_host/IBMJMXConnectorREST",
  "className": "com.ibm.ws.session.monitor.SessionStats",
  "URL": "/IBMJMXConnectorREST/mbeans/WebSphere%3Aname%3Ddefault_host%2FIBMJMXConnectorREST%2Ctype%3DSessionStats"
}
{
  "objectName": "WebSphere:name=com.ibm.websphere.config.mbeans.ServerXMLConfigurationMBean",
  "className": "com.ibm.ws.config.xml.internal.ServerXMLConfigurationMBeanImpl",
  "URL": "/IBMJMXConnectorREST/mbeans/WebSphere%3Aname%3Dcom.ibm.websphere.config.mbeans.ServerXMLConfigurationMBean"
}
{
  "objectName": "WebSphere:type=JvmStats",
  "className": "com.ibm.ws.monitors.helper.JvmStats",
  "URL": "/IBMJMXConnectorREST/mbeans/WebSphere%3Atype%3DJvmStats"
}
{
  "objectName": "WebSphere:feature=kernel,name=ServerEndpointControl",
  "className": "com.ibm.ws.kernel.server.internal.ServerEndpointControlMBeanImpl",
  "URL": "/IBMJMXConnectorREST/mbeans/WebSphere%3Afeature%3Dkernel%2Cname%3DServerEndpointControl"
}
{
  "objectName": "WebSphere:service=com.ibm.ws.kernel.filemonitor.FileNotificationMBean",
  "className": "com.ibm.ws.kernel.filemonitor.internal.FileNotificationImpl",
  "URL": "/IBMJMXConnectorREST/mbeans/WebSphere%3Aservice%3Dcom.ibm.ws.kernel.filemonitor.FileNotificationMBean"
}
{
  "objectName": "WebSphere:feature=restConnector,type=FileService,name=FileService",
  "className": "com.ibm.ws.filetransfer.internal.mbean.FileService",
  "URL": "/IBMJMXConnectorREST/mbeans/WebSphere%3Afeature%3DrestConnector%2Cname%3DFileService%2Ctype%3DFileService"
}
{
  "objectName": "WebSphere:service=com.ibm.websphere.application.ApplicationMBean,name=sample",
  "className": "com.ibm.ws.app.manager.internal.ApplicationConfigurator$NamedApplication$2",
  "URL": "/IBMJMXConnectorREST/mbeans/WebSphere%3Aname%3Dsample%2Cservice%3Dcom.ibm.websphere.application.ApplicationMBean"
}
{
  "objectName": "WebSphere:feature=channelfw,type=endpoint,name=defaultHttpEndpoint-ssl",
  "className": "com.ibm.ws.channelfw.internal.chains.EndPointInfoImpl",
  "URL": "/IBMJMXConnectorREST/mbeans/WebSphere%3Afeature%3Dchannelfw%2Cname%3DdefaultHttpEndpoint-ssl%2Ctype%3Dendpoint"
}
{
  "objectName": "WebSphere:feature=restConnector,type=FileTransfer,name=FileTransfer",
  "className": "com.ibm.ws.filetransfer.internal.mbean.FileTransfer",
  "URL": "/IBMJMXConnectorREST/mbeans/WebSphere%3Afeature%3DrestConnector%2Cname%3DFileTransfer%2Ctype%3DFileTransfer"
}
$

JvmStats

JvmStatsを取得する。

$ curl -s -k --basic -u jmxadmin:password https://localhost:9443/IBMJMXConnectorREST/mbeans/WebSphere%3Atype%3DJvmStats/attributes | jq .
[
  {
    "name": "ProcessCPU",
    "value": {
      "value": "0.23676892201834862",
      "type": "java.lang.Double"
    }
  },
  {
    "name": "GcCount",
    "value": {
      "value": "7",
      "type": "java.lang.Long"
    }
  },
  {
    "name": "GcTime",
    "value": {
      "value": "78",
      "type": "java.lang.Long"
    }
  },
  {
    "name": "UpTime",
    "value": {
      "value": "1871036",
      "type": "java.lang.Long"
    }
  },
  {
    "name": "UsedMemory",
    "value": {
      "value": "157499176",
      "type": "java.lang.Long"
    }
  },
  {
    "name": "FreeMemory",
    "value": {
      "value": "427606232",
      "type": "java.lang.Long"
    }
  },
  {
    "name": "Heap",
    "value": {
      "value": "585105408",
      "type": "java.lang.Long"
    }
  }
]
$

ThreadPoolStats

Default ExecutorのThreadPoolStatsを取得する。

$ curl -s -k --basic -u jmxadmin:password https://localhost:9443/IBMJMXConnectorREST/mbeans/WebSphere%3Aname%3DDefault+Executor%2Ctype%3DThreadPoolStats/attributes | jq .
[
  {
    "name": "PoolSize",
    "value": {
      "value": "16",
      "type": "java.lang.Integer"
    }
  },
  {
    "name": "PoolName",
    "value": {
      "value": "Default Executor",
      "type": "java.lang.String"
    }
  },
  {
    "name": "ActiveThreads",
    "value": {
      "value": "1",
      "type": "java.lang.Integer"
    }
  }
]
$

SessionStats

SessionStatsを取得する。このMBeanはアプリケーション毎であり、アプリケーションが実際にセッションを使うまで作成されない。本来は自分がセッション情報をとりたいアプリケーション名を指定する必要があるが、今回はIBMJMXConnectorRESTアプリケーションを指定する。

$ curl -s -k --basic -u jmxadmin:password https://localhost:9443/IBMJMXConnectorREST/mbeans/WebSphere%3Aname%3Ddefault_host%2FIBMJMXConnectorREST%2Ctype%3DSessionStats/attributes | jq .
[
  {
    "name": "ActiveCount",
    "value": {
      "value": "0",
      "type": "java.lang.Long"
    }
  },
  {
    "name": "CreateCount",
    "value": {
      "value": "1",
      "type": "java.lang.Long"
    }
  },
  {
    "name": "LiveCount",
    "value": {
      "value": "0",
      "type": "java.lang.Long"
    }
  },
  {
    "name": "InvalidatedCountbyTimeout",
    "value": {
      "value": "1",
      "type": "java.lang.Long"
    }
  },
  {
    "name": "InvalidatedCount",
    "value": {
      "value": "1",
      "type": "java.lang.Long"
    }
  }
]
$

ConnectionPoolStats

他に一般的にモニターしたくなりそうな情報としてはコネクションプールがある。コネクションプールはその定義を作成し、また、実際にコネクションが発生しないとMBeanが作成されないと思われる。今回は省略。

Python

PythonからローカルLibertyに接続してみる。

コード作成

Pythonスクリプトは以下の通り作成。→GitHub

monitor_restConnector.py
#!/usr/bin/env python3

import argparse
import csv
import datetime
import logging
import os
import sys
import time

import requests
import urllib3


# 警告を非表示にする
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

formatter = '%(asctime)s %(name)-12s %(levelname)-8s %(message)s'
logging.basicConfig(level=logging.WARNING, format=formatter)
logger = logging.getLogger(__name__)


def request_with_retry(url, user, password, timeout, retry):
    """HTTPリクエストを行い、失敗した場合はリトライを行う。

    :param url:
    :param user:
    :param password:
    :param timeout:
    :param retry:
    :return: jsonデータ
    """

    session = requests.Session()
    
    # backoff_factorが1だとリトライの間のスリープ時間は[0s, 2s, 4s, 8s, ...]となる
    retries = urllib3.util.retry.Retry(total=retry, backoff_factor=1)

    session.mount('https://', requests.adapters.HTTPAdapter(max_retries=retries))
    session.mount('http://', requests.adapters.HTTPAdapter(max_retries=retries))

    logger.info('GET {}'.format(url))
    # verify=Falseで証明書のチェックを行わない
    # ただしこれだけだと警告がでるので最初にurllib3.disable_warningsをしている
    response = session.get(url, auth=(user, password), verify=False, timeout=timeout)

    return response.json()


def get_value(name, items):
    """辞書のリストからnameがマッチする辞書を探し、value.valueを返す。

    :param name:
    :param items:
    :return: データの値
    """

    for item in items:
        if item['name'] == name:
            return item['value']['value']

    return None


def write_header(filepath):
    """ヘッダー書き込む。
    filepathが指定され、ファイルが存在しなかった場合はファイルを作成してヘッダーを書く。
    filepathが指定され、ファイルが空の場合もヘッダーを書く。
    filepathが指定されなかった場合は標準出力にヘッダーを書く。

    :param filepath:
    :return:
    """

    fieldnames = [
        'Time',
        'Heap', 'UsedMemory',
        'PoolSize', 'ActiveThreads',
        'LiveCount', 'ActiveCount']

    # filepathが指定された場合
    if filepath:
        # ファイルが存在しない場合はファイルを作成してヘッダーを書く
        if not os.path.isfile(filepath):
            with open(filepath, 'w') as csv_file:
                writer = csv.DictWriter(csv_file, fieldnames=fieldnames)
                writer.writeheader()
        # ファイルが存在する場合
        else:
            with open(filepath, 'r+') as csv_file:
                # ファイルが空の場合はヘッダーを書く
                if not csv_file.read():
                    writer = csv.DictWriter(csv_file, fieldnames=fieldnames)
                    writer.writeheader()
    # filepathが指定されなかった場合は標準出力にヘッダーを書く
    else:
        writer = csv.DictWriter(sys.stdout, fieldnames=fieldnames)
        writer.writeheader()


def append_data(filepath, jvmstats, threadpoolstats, sessionstats):
    """性能情報の値を追記する。
    filepathが渡された場合はcsvに書き込み、渡されなかった場合は標準出力に書き込む。

    :param filepath:
    :param jvmstats:
    :param threadpoolstats:
    :param sessionstats:
    :return:
    """

    fieldnames = [
        'Time',
        'Heap', 'UsedMemory',
        'PoolSize', 'ActiveThreads',
        'LiveCount', 'ActiveCount']

    item = {
        'Time': datetime.datetime.now(),
        'Heap': get_value('Heap', jvmstats),
        'UsedMemory': get_value('UsedMemory', jvmstats),
        'PoolSize': get_value('PoolSize', threadpoolstats),
        'ActiveThreads': get_value('ActiveThreads', threadpoolstats),
        'LiveCount': get_value('LiveCount', sessionstats),
        'ActiveCount': get_value('ActiveCount', sessionstats)
    }

    if filepath:
        # データをファイルに追記する
        with open(filepath, 'a') as csv_file:
            writer = csv.DictWriter(csv_file, fieldnames=fieldnames)
            writer.writerow(item)
    else:
        # 標準出力に出力する
        writer = csv.DictWriter(sys.stdout, fieldnames=fieldnames)
        writer.writerow(item)


def main():

    # コマンド引数の処理
    parser = argparse.ArgumentParser()
    parser.add_argument('--host',
                        action='store',
                        type=str,
                        default='localhost',
                        help='接続先のホスト名を指定します')
    parser.add_argument('--port',
                        action='store',
                        type=int,
                        default=9443,
                        help='接続先のポートを指定します')
    parser.add_argument('--interval',
                        action='store',
                        type=int,
                        default=10,
                        help='データの取得間隔(秒)を指定します')
    parser.add_argument('--delay',
                        action='store',
                        type=int,
                        default=30,
                        help='モニターを開始するまでの待機時間(秒)を指定します')
    parser.add_argument('--timeout',
                        action='store',
                        type=int,
                        default=2,
                        help='モニターリクエストのタイムアウト時間(秒)を指定します')
    parser.add_argument('--retry',
                        action='store',
                        type=int,
                        default=10,
                        help='モニターのリトライ回数を指定します')
    parser.add_argument('-f', '--filename',
                        action='store',
                        type=str,
                        help='出力先のファイル名を指定します')
    args = parser.parse_args()
    host = args.host
    port = args.port
    timeout = args.timeout
    retry = args.retry
    filepath = args.filename

    # 接続ユーザーとパスワードは環境変数から取得
    user = os.getenv('JMX_USER', 'jmxadmin')
    password = os.getenv('JMX_PASSWORD', 'password')

    # 待機時間
    time.sleep(args.delay)

    # ヘッダーを書く
    write_header(filepath)

    # MBeanのURL
    jvmstats_url = 'https://{}:{}/IBMJMXConnectorREST/mbeans/' \
                   'WebSphere%3Atype%3DJvmStats/' \
                   'attributes'.format(host, port)
    threadpoolstats_url = 'https://{}:{}/IBMJMXConnectorREST/mbeans/' \
                          'WebSphere%3Aname%3DDefault+Executor%2Ctype%3DThreadPoolStats/' \
                          'attributes'.format(host, port)
    sessionstats_url = 'https://{}:{}/IBMJMXConnectorREST/mbeans/' \
                       'WebSphere%3Aname%3Ddefault_host%2FIBMJMXConnectorREST%2Ctype%3DSessionStats/' \
                       'attributes'.format(host, port)

    # モニター
    while True:
        jvmstats = request_with_retry(jvmstats_url, user, password, timeout, retry)
        threadpoolstats = request_with_retry(threadpoolstats_url, user, password, timeout, retry)
        sessionstats = request_with_retry(sessionstats_url, user, password, timeout, retry)
        append_data(filepath, jvmstats, threadpoolstats, sessionstats)
        time.sleep(args.interval)


if __name__ == '__main__':
    main()
  • ファイル出力と標準出力への出力ができるようにした
  • Libertyのコンテナの起動に時間がかかる場合を想定し、モニター開始までのdelayを設定できるようにした
  • Libertyへの接続に失敗した場合にリトライをするようにした
  • いくつかのパラメータを引数で設定できるようにしたが、接続ユーザーとパスワードについては環境変数から取得するようにした

実行例

$ ./monitor_restConnector.py --help
usage: monitor_restConnector.py [-h] [--host HOST] [--port PORT]
                                [--interval INTERVAL] [--delay DELAY]
                                [--timeout TIMEOUT] [--retry RETRY]
                                [-f FILENAME]

optional arguments:
  -h, --help            show this help message and exit
  --host HOST           接続先のホスト名を指定します default:localhost
  --port PORT           接続先のポートを指定します default:9443
  --interval INTERVAL   データの取得間隔(秒)を指定します default:60
  --delay DELAY         モニターを開始するまでの待機時間(秒)を指定します default:30
  --timeout TIMEOUT     モニターリクエストのタイムアウト時間(秒)を指定します default:2
  --retry RETRY         モニターのリトライ回数を指定します default:10
  -f FILENAME, --filename FILENAME
                        出力先のファイル名を指定します default:未指定(標準出力)
sotoiwa@SotonoMacBook-Pro:~/workspace/liberty_monitor/monitor_restConnector (master)
$ ./monitor_restConnector.py --interval 10 --delay 0
Time,Heap,UsedMemory,PoolSize,ActiveThreads,LiveCount,ActiveCount
2019-01-13 15:43:23.679303,649592832,74171952,16,1,1,0
2019-01-13 15:43:33.753766,649592832,77029800,16,1,1,0
2019-01-13 15:43:43.830487,649592832,82213760,16,1,1,0
2019-01-13 15:43:53.907145,649592832,83140824,16,1,1,0

サイドカーとして動かす

Pythonスクリプトをコンテナ化し、Liberyコンテナのサイドカーとして動かす。

Libertyコンテナのビルド

上に記載したserver.xmlとアプリを含めてLibertyコンテナをビルドする。

Dockerfile
FROM websphere-liberty:18.0.0.4-webProfile8
COPY --chown=1001:0 server.xml /config/
COPY --chown=1001:0 sample.war /config/apps/

ファイル配置は以下。

liberty-restconnector
├── Dockerfile
├── sample.war
└── server.xml

ビルドする。

docker build -t sotoiwa540/liberty-restconnector:1.0 .
docker push sotoiwa540/liberty-restconnector:1.0

Pythonサイドカーコンテナのビルド

Pythonのコンテナをビルドする。pythonコマンドに-uオプションをつけるか、環境変数PYTHONUNBUFFERED=TRUEを設定しないと、標準出力がバッファされてdockerのログに出力されないことに注意。

Dockerfile
FROM python:3-alpine

WORKDIR /usr/src/app

COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt

COPY monitor_restConnector.py ./

ENV PYTHONUNBUFFERED TRUE
ENTRYPOINT [ "python", "./monitor_restConnector.py" ]

ファイル配置は以下。

monitor-restconnector
├── Dockerfile
├── monitor_restConnector.py
└── requirements.txt
docker build -t sotoiwa540/monitor-restconnector:1.0 .
docker push sotoiwa540/monitor-restconnector:1.0

Kubernetesへのデプロイ

パスワードを格納したSecretを作成する。

kubectl create secret generic jmx-secret --from-literal=JMX_USER=jmxadmin --from-literal=JMX_PASSWORD=password

以下のようにLiberty(with サイドカー)のマニフェストを作成。

liberty-restconnector-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: liberty-restconnector
spec:
  selector:
    matchLabels:
      app: liberty
  replicas: 1
  template:
    metadata:
      labels:
        app: liberty
    spec:
      containers:
      - name: liberty
        image: sotoiwa540/liberty-restconnector:1.0
        imagePullPolicy: Always
        ports:
        - containerPort: 9080
      - name: monitor
        image: sotoiwa540/monitor-restconnector:1.0
        imagePullPolicy: Always
        command:
        - python
        - ./monitor_restConnector.py
        args:
        - --host
        - localhost
        - --port
        - "9443"
        - --interval
        - "60"
        - --timeout
        - "2"
        - --delay
        - "30"
        env:
        - name: JMX_USER
          valueFrom:
            secretKeyRef:
              name: jmx-secret
              key: JMX_USER
        - name: JMX_PASSWORD
          valueFrom:
            secretKeyRef:
              name: jmx-secret
              key: JMX_PASSWORD

デプロイする。

kubectl apply -f liberty-restconnector-deployment.yaml

稼働確認

LibertyのPodが稼働していることを確認。コンテナの数が2となっている。

$ kubectl get po
NAME                       READY   STATUS    RESTARTS   AGE
liberty-76c9d556c9-dhmcs   2/2     Running   0          25s
$

サイドカーの方のログを確認。csvが出力できた。

$ kubectl logs -f liberty-restconnector-76c9d556c9-j2gb5 -c monitor
Time,Heap,UsedMemory,PoolSize,ActiveThreads,LiveCount,ActiveCount
2019-01-13 07:20:04.737811,72351744,68460832,6,1,1,0
2019-01-13 07:21:04.963036,72351744,61504136,4,1,1,0

TODO

SessionStatsやConnectionPoolStatsは、アプリケーションやデータソース毎にMBeanができるので、どのアプリケーションあるいはどのデータソースなのか、MBeanのURLを引数か環境変数で指定できるようにする必要がある。
また、このMBeanができるのは、実際にセッションやコネクションプールが使われてからなので、MBeanができる前にアクセスした場合に上手いこと処理が必要。

image.png
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?