かんがるーさんの日記

最近自分が興味をもったものを調べた時の手順等を書いています。今は Spring Boot をいじっています。

Spring Boot 1.5.x の Web アプリを 2.0.x へバージョンアップする ( その23 )( Docker Network メモ書き+Prometheus の HTTP API でデータを削除する )

概要

記事一覧はこちらです。

Spring Boot 1.5.x の Web アプリを 2.0.x へバージョンアップする ( その22 )( Docker で RabbitMQ の環境を構築する2(RabbitMQ の Clustering 構成) ) の続きです。

  • 今回の手順で確認できるのは以下の内容です。
    • Docker Compose で Redis と RabbitMQ の Clustering 構成を構築してみましたが、Docker の network 機能が全然分かってないな。。。と思ったので、その辺を調べてみます。
    • 試している途中で Grafana 上に不要なデータが表示されるようになったので、Prometheus の HTTP API を有効にして削除しています。

参照したサイト・書籍

  1. Networking Overview
    https://docs.docker.com/network/

  2. Networking with standalone containers
    https://docs.docker.com/network/network-tutorial-standalone/

  3. Networking in Compose
    https://docs.docker.com/compose/networking/

  4. Prometheus: Delete Time Series Metrics
    https://www.shellhacks.com/prometheus-delete-time-series-metrics/

  5. Prometheus - HTTP API
    https://prometheus.io/docs/prometheus/latest/querying/api/

  6. High Availability Prometheus and Alertmanager
    https://mkezz.wordpress.com/tag/docker/ https://github.com/mkez00/prom-alertmanager-ha

    • 記事とは無関係ですが、Vagrant で自分が知らないことをやっているサンプルを見かけたので、メモとして残しておきます。
  7. Docker Compose - docker-compose.yml リファレンス
    https://qiita.com/zembutsu/items/9e9d80e05e36e882caaa

  8. redis/5.0/alpine/Dockerfile
    https://github.com/docker-library/redis/blob/f1a8498333ae3ab340b5b39fbac1d7e1dc0d628c/5.0/alpine/Dockerfile

  9. Alpine Linux package management
    https://wiki.alpinelinux.org/wiki/Alpine_Linux_package_management

  10. Alpine Linux で軽量な Docker イメージを作る
    https://qiita.com/pottava/items/970d7b5cda565b995fe7

目次

  1. Networking with standalone containers を試してみたメモ書き
  2. docker-compose で network を指定せずにコンテナを作成した時にコンテナ名でも通信できる理由とは?
  3. コンテナ名で通信ができるなら hostname の指定は不要なのでは?
  4. Grafana に追加された rabbit@791f27a3e17b を削除するには?
  5. rabbitmq_exporter → haproxy へはコンテナ名でアクセスさせる
  6. redis-cluster-make コンテナ用の Dockerfile の FROM に指定するイメージを -alpine に変更する

手順

Networking with standalone containers を試してみたメモ書き

Docker のドキュメントに Networking with standalone containers というページがあったので試してみた時のメモ書きです。

  • docker network ls コマンドで作成されている docker network を表示できる。デフォルトで作成されているのは bridge, host, none の3つ。
  • network を指定せずに docker run コマンドを実行した場合、bridge が使用される。
  • デフォルトの bridge ではコンテナ名で通信できない。ping コマンドを実行すると bad address と表示される。IP アドレスでは通信できる。
  • docker network create --driver bridge <network名> コマンドでユーザ定義の bridge ネットワークが作成できる。
  • docker run コマンド実行時に --net オプションでユーザ定義の network を指定すれば、指定された network が使用される。
  • docker run コマンド実行後に docker network connect コマンドで別の network に接続することも可能(複数接続可能らしい)。

ということは、bridge-a-net, bridge-b-net という2つの bridge のユーザ定義 network を作成した後、

f:id:ksby:20181205211008p:plain

alpine1, alpine2, alpine3 の3つのコンテナを作成し、alpine1 は bridge-a-net へ、alpine3 は bridge-b-net へ、そして alpine2 は bridge-a-net, bridge-b-net の両方へ接続します。

f:id:ksby:20181205211315p:plain f:id:ksby:20181205211425p:plain f:id:ksby:20181205211520p:plain

alpine1 から alpine2 に ping は通るが、alpine3 には ping は通らず、

f:id:ksby:20181205211649p:plain

alpine3 から alpine2 に ping は通るが、alpine1 には ping は通らず、

f:id:ksby:20181205211942p:plain

alpine2 から alpine1, alpine2 の両方に ping が通ります。

f:id:ksby:20181205212136p:plain

ifconfig コマンド、route コマンドで各コンテナのネットワークインターフェースやルーティングテーブルを確認すると以下の通り。alpine1, alpine3 には eth0 しかありませんが、alpine2 には eth0, eth1 の2つのネットワークインターフェースがあります。

f:id:ksby:20181205212442p:plain f:id:ksby:20181205212559p:plain f:id:ksby:20181205212701p:plain

なるほど。。。

docker-compose で network を指定せずにコンテナを作成した時にコンテナ名でも通信できる理由とは?

Networking in Compose によると、デフォルトで作成されている bridge network が使われるのではなく、[projectname]_default(projectname は docker-compose.yml のあるディレクトリ名)という名前の network が作成されてそれが使われるとのことでした。

確かに docker-compose up -d コマンドを実行すると、最初に Creating network "ksbysample-webapp-lending_default" with the default driver というメッセージが出力されていました。

f:id:ksby:20181205222609p:plain

docker network inspect ksbysample-webapp-lending_default コマンドを実行すると以下の出力でした。

f:id:ksby:20181205222755p:plain f:id:ksby:20181205222937p:plain f:id:ksby:20181205223118p:plain

コンテナ名で通信ができるなら hostname の指定は不要なのでは?

docker-compose.yml では rabbitmq1 ~ rabbitmq3 のコンテナの定義に hostname: rabbitmq1 のように hostname を設定していますが、コンテナ名と hostname が同じ文字列でコンテナ名で通信できるのであれば書かなくても良い気がします。

  rabbitmq1:
    image: rabbitmq:${RABBITMQ_VERSION}-alpine
    container_name: rabbitmq1
    hostname: rabbitmq1
    environment:
    - RABBITMQ_ERLANG_COOKIE
    - RABBITMQ_DEFAULT_USER
    - RABBITMQ_DEFAULT_PASS
    - RABBITMQ_DEFAULT_VHOST

rabbitmq1 ~ rabbitmq3 の定義から hostname を削除してみます。

  rabbitmq1:
    image: rabbitmq:${RABBITMQ_VERSION}-alpine
    container_name: rabbitmq1
    environment:
    - RABBITMQ_ERLANG_COOKIE
    - RABBITMQ_DEFAULT_USER
    - RABBITMQ_DEFAULT_PASS
    - RABBITMQ_DEFAULT_VHOST
  rabbitmq2:
    image: rabbitmq:${RABBITMQ_VERSION}-alpine
    container_name: rabbitmq2
    depends_on:
    - rabbitmq1
    environment:
    - RABBITMQ_ERLANG_COOKIE
    volumes:
    - ./docker/rabbitmq/cluster-entrypoint.sh:/usr/local/bin/cluster-entrypoint.sh
    entrypoint: /bin/sh -c /usr/local/bin/cluster-entrypoint.sh
  rabbitmq3:
    image: rabbitmq:${RABBITMQ_VERSION}-alpine
    container_name: rabbitmq3
    depends_on:
    - rabbitmq1
    environment:
    - RABBITMQ_ERLANG_COOKIE
    volumes:
    - ./docker/rabbitmq/cluster-entrypoint.sh:/usr/local/bin/cluster-entrypoint.sh
    entrypoint: /usr/local/bin/cluster-entrypoint.sh

docker-compose up -d コマンドを実行するとエラーは出ずに起動し、

f:id:ksby:20181205224740p:plain

HAProxy のログを見ると rabbitmq1 の UP が認識されて(ただし後から rabbitmq2, rabbitmq3 のコンテナが停止していることに気づきました。。。)、

f:id:ksby:20181205224906p:plain

順調かな。。。と思いましたが、管理コンソールを見ると Nodes には1台しか表示されておらず、Name も rabbit@rabbitmq1 ではなく rabbit@791f27a3e17b になっていました。

f:id:ksby:20181205225033p:plain

Grafana でも RabbitMQ が1台追加されて表示されており、

f:id:ksby:20181205225535p:plain

rabbitmq1 コンテナで hostname コマンドを実行すると、rabbitmq1 ではなく 791f27a3e17b という文字列が表示されました。hostname を設定しないとこうなるようです。

f:id:ksby:20181205230103p:plain

RabbitMQ には hostname の設定が必要だったので元に戻します。単に通信するだけならば hostname の設定は不要ですが、サーバによっては hostname が指定の文字列で設定されている必要があるようです。

Grafana に追加された rabbit@791f27a3e17b を削除するには?

hostname の設定を戻してからコンテナを再起動したのですが、rabbit@791f27a3e17b が残ったままでした。。。

f:id:ksby:20181207003552p:plain

削除する方法を調べたところ、Prometheus: Delete Time Series Metrics のページを見つけたので、この方法を試してみます。

最初に Prometheus 起動時に --web.enable-admin-api オプションを追加します。prometheus/Dockerfile から ENTRYPOINT の定義をコピーして --web.enable-admin-api を追加したものを docker-compose.yml に記述します。

  prometheus:
    image: prom/prometheus:latest
    container_name: prometheus
    ports:
    - "9090:9090"
    volumes:
    - ./docker/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
    - ./docker/prometheus/storage:/prometheus
    entrypoint:
    - "/bin/prometheus"
    - "--storage.tsdb.path=/prometheus"
    - "--web.console.libraries=/etc/prometheus/console_libraries"
    - "--web.console.templates=/etc/prometheus/consoles"
    - "--config.file=/etc/prometheus/prometheus.yml"
    - "--web.enable-admin-api"

docker-compose up -d コマンドを実行します。これで Prometheus の HTTP API が呼び出せるようになりました。ブラウザから http://localhost:9090/api/v1/status/flags にアクセスすると、JSON で結果が返ってきます。

f:id:ksby:20181207003949p:plain

削除するデータを特定するための文字列を取得します。Grafana 上で削除対象の「Edit」を選択した後、

f:id:ksby:20181207004411p:plain

rabbitmq_running{node="$node"} の部分をコピーして $node の部分を rabbit@791f27a3e17b に置き換えた文字列 rabbitmq_running{node="rabbit@791f27a3e17b"} を作成します。

f:id:ksby:20181207004518p:plain

コマンドラインから curl -v -X POST -g 'http://localhost:9090/api/v1/admin/tsdb/delete_series?match[]=rabbitmq_running{node="rabbit@791f27a3e17b"}' を実行します。

f:id:ksby:20181207005030p:plain

Grafana 上ですぐに削除されませんが、Dashboard を表示し直すと rabbit@791f27a3e17b が消えました。

f:id:ksby:20181207005241p:plain

--web.enable-admin-api オプションはデフォルトでは無効化されている機能なので、docker-compose.yml を元に戻しておきます。

rabbitmq_exporter → haproxy へはコンテナ名でアクセスさせる

rabbitmq_exporter が haproxy 経由で rabbitmq にアクセスする時にはホストを経由する必要はないので、コンテナ名でアクセスすることにします。docker-compose.yml の以下の点を変更します。

  rabbitmq_exporter:
    image: kbudde/rabbitmq-exporter:latest
    container_name: rabbitmq_exporter
    ports:
    - "9419:9419"
    environment:
    - RABBIT_URL=http://haproxy:15672
    - RABBIT_USER=${RABBITMQ_DEFAULT_USER}
    - RABBIT_PASSWORD=${RABBITMQ_DEFAULT_PASS}
    - RABBIT_CAPABILITIES=bert,no_sort
    - PUBLISH_PORT=9419
  • RABBIT_URL=http://${HOST_IP_ADDRESS}:15672RABBIT_URL=http://haproxy:15672 に変更します。

redis_exporter → redis も REDIS_ADDR=redis://${HOST_IP_ADDRESS}:${REDIS_CLUSTER_1_PORT},.....REDIS_ADDR=redis://redis-cluster-1:6379,..... にしてみたのですが、こちらは正常に動作しなかったので元に戻しました。

redis-cluster-make コンテナ用の Dockerfile の FROM に指定するイメージを -alpine に変更する

docker/redis/Dockerfile の FROM の記述が FROM redis:${REDIS_VERSION} となっており -alpine を付けていなかったので付けることにします。

redis/5.0/alpine/Dockerfile を参考に docker/redis/Dockerfile を以下のように変更します。

ARG REDIS_VERSION
FROM redis:${REDIS_VERSION}
RUN apk add --no-cache expect
  • FROM redis:${REDIS_VERSION}FROM redis:${REDIS_VERSION}-alpine に変更します。
  • RUN apt-get update -qq && apt-get install -y expectRUN apk add --no-cache expect に変更します。Alpine Linux だと、パッケージ管理ツールが apk になる、インストール前に update 不要、--no-cache を付けてキャッシュに残らないようにする、-y オプションは不要、になるようです。

IntelliJ IDEA の Docker Plugin から redis:5.0.2-custom のイメージを削除した後、docker-compose up -d コマンドを実行します。

f:id:ksby:20181208082347p:plain

redis-cluster-make コンテナのログを見ると yes が自動入力されており、redis-cli --cluster create コマンドも正常終了しています。

f:id:ksby:20181208082511p:plain

redis-cluster-6379 コンテナで redis-cli コマンドを起動して cluster nodes コマンドを実行すると、Resis Cluster 構成が構築できていることが確認できます。

f:id:ksby:20181208082750p:plain

履歴

2018/12/08
初版発行。