2021年1月11日月曜日

docker swarm 上に cAdvisor をデプロイして swarm 上のコンテンのメトリックを取得してみる

概要

docker swarm 上で動作しているコンテナのメトリックを取得するのに cAdvisor を試してみました
検証ポイントとしては cAdvisor を各ホストで動作させる必要があるのか manager ノードだけで良いのかという点です

環境

  • macOS 11.1
  • docker 19.03.12

docker swarm の構築

こちらを参考に構築してください

cAdvisor のデプロイ: manager のみ

まずは cAdvisor を manager ノードのみにデプロイしてみます

  • docker run --volume=/:/rootfs:ro --volume=/var/run:/var/run:ro --volume=/sys:/sys:ro --volume=/var/lib/docker/:/var/lib/docker:ro --volume=/dev/disk/:/dev/disk:ro --publish=8080:8080 --detach=true --name=cadvisor google/cadvisor:latest

デプロイ完了後以下のエンドポイントでメトリックが取得できることを確認します
269 項目のメトリックが確認できます

  • curl http://localhost:8080/metrics

node1 側でコンテナを起動してみる

manager 側にデプロイした cAdvisor に変化があるか node1 側にコンテナを立てて確認してみます

  • docker run -d nginx

起動したら再度 manager 側にデプロイした cAdvisor のメトリックを確認してみます
メトリック数に変化がないことが確認できると思います

manager 側でコンテナを起動してみる

今度は manager ノード側で上記同様にコンテナを 1 つ起動してみます
すると取得できるメトリックが 336 に増えているのが確認できると思います

つまり cAdvisor は swarm クラスタであっても各ノードにデプロイしなければいけないことがわかります

最後に

swarm 上のコンテナのメトリックを取得したい場合は各ノードで cAdvisor を動作させる必要があることがわかりました
ノードが増えた場合に各ノードにある cAdvisor の値を横断的に見る方法として Prometheus を使う感じなのかなと思います

参考サイト

2021年1月10日日曜日

docker-machine で構築したホストのデーモンオプションを変更する方法

概要

docker-machine で構築した docker ホストは TinyCoreLinux になっています
dockerd も自動的に起動するのですがデーモンのオプションを設定する方法がわからなかったので紹介します

環境

  • macOS 11.1
  • docker-machine 0.16.2
  • Virtualbox 6.1.16r140961

docker-machine で docker ホストの作成

過去に紹介しているのでこちらの記事を参考に作成してみてください

docker ホストにログイン

  • docker-machine ssh master

daemon.json の作成

ここからは TinyCoreLinux 上での作業になります

  • sudo touch /etc/docker/daemon.json

metrics-addr の追加

  • sudo vi /etc/docker/daemon.json
{
  "metrics-addr" : "0.0.0.0:9323",
  "experimental" : true
}

dockerd の再起動

  • sudo /etc/init.d/docker restart

動作確認

  • curl localhost:9323/metrics

Prometheus のメトリック情報が取得できれば OK です

参考サイト

2021年1月9日土曜日

fluentd -> kafka -> logstash -> elasticsearch の順番でログを格納する方法

概要

fluentd -> kafka -> logstash -> elasticsearch という順番でログを確認する方法を紹介します
fluentd, kafka, elasticsearch の構築方法は過去に紹介しているので別記事を参照しています

環境

  • kafka 2.6.0
  • logstash 7.10.1
  • elasticsearch 6.4.0

fluent-kafka-plugin が動作する環境の構築

こちらを参考に構築してください
kafka と fluent-kafka-plugin がインストールされた fluent コンテナが起動している状態になれば OK です

elasticsearch の構築

こちらを参考に構築してください
9200 ポートで elasticsearch にアクセスできれば OK です

logstash のインストール

  • brew install logstash

logstash kafka input plugin のインストールと設定

ここが今回の肝になる部分です
logstash-integration-kafka を使います

  • logstash-plugin install logstash-integration-kafka

インストールが完了したら設定ファイルを作成していきます
kafka からデータを受け取って elasticsearch に流す設定を定義します

  • cp /usr/local/etc/logstash/logstash-sample.conf /usr/local/etc/logstash/logstash.conf
  • vim /usr/local/etc/logstash/logstash.conf
input {
  kafka {
    bootstrap_servers => "192.168.1.2:9092"
    topics => ["test"]
    decorate_events => true
  }
}

filter {
  json {
    source => "message"
  }
}

output {
  elasticsearch {
    hosts => ["http://192.168.1.2:9200"]
    index => "%{[@metadata][kafka][topic]}-%{+YYYY.MM.dd}"
  }
}


decorate_events を true にしないと [@metadata][kafka][topic] が output セクションで使えないので true にしています

また filter で json を使っています
どうやらデフォルトでは kafka から受け取ったログはすべて「message」というフィールドに格納されています
なのでそれぞれのフィールドに分割するために filter を挟んでいます

  • logstash -f /usr/local/etc/logstash/logstash.conf

起動に少し時間がかかりますが ERROR がでなければ OK です

動作確認

まずは適当なログを fluentd コンテナに送ります

  • docker run --rm --log-driver=fluentd --log-opt fluentd-address=192.168.1.2:24224 --log-opt tag="docker.{{.Name}}" alpine /bin/sh -c "while :;do echo \"{\\\"timestamp\\\":\\\"$(date)\\\",\\\"msg\\\":\\\"hello\\\"}\"; sleep 3; done;"


ある程度待った後に elasticsearch にインデックスが作成されているか確認しましょう

  • curl 'http://192.168.1.2:9200/_cat/indices?v'
  • curl 'http://192.168.1.2:9200/test-2021.01.06?pretty'

最後に

必ずしも kafka は必要ではないですがスケールによっては必要になります

参考サイト

2021年1月8日金曜日

ruby-kafka を使って kafka との証明書認証をサクっと確認する方法

概要

fluent-kafka-plugin で証明書を使って kafka に接続する場合にうまく接続できない場合があると思います
そんな場合は ruby-kafka を使って確認しましょう

概要

  • macOS 11.1
  • Ruby 3.0.0
  • ruby-kafka 1.3.0

準備

  • bundle init
  • vim Gemfile
gem "ruby-kafka"
  • bundle install

テストコード

  • vim test.rb
require 'kafka'

kafka = Kafka.new(
  ["kafka:9092"],
  ssl_ca_cert: File.read('./ca.pem'),
  ssl_client_cert: File.read('./cert.pem'),
  ssl_client_cert_key: File.read('./key.pem')
)
puts kafka

ret = kafka.deliver_message("Hello, World!", topic: "test")
puts ret


  • bundle exec ruby test.rb

これでエラーが出なければ OK です
証明書が間違っている場合などは OpenSSL のエラーなどが出ると思います

参考サイト

2021年1月7日木曜日

rbenv で Ruby3.0.0 をインストールする方法

概要

タイトルの通りです
グローバルにインストールしてもいいですがとりあえず使ってみたい場合には rbenv を使ってインストールしましょう

環境

  • macOS 11.1
  • rbenv 1.1.2

準備

  • brew update
  • brew upgrade rbenv
  • brew upgrade ruby-build

インストール

  • rbenv install -l

    => 3.0.0 があることを確認する

  • rbenv install 3.0.0

動作確認

  • rbenv local 3.0.0
  • rbenv which ruby
  • /Users/name/.rbenv/versions/3.0.0/bin/ruby -e "0 => a; puts a"

2021年1月6日水曜日

Error: homebrew-core is a shallow clone.

概要

brew update を実行しようとすると発生するエラーです

環境

  • macOS 11.1
  • Homebrew 2.6.0

解決策

  • git -C "/usr/local/Homebrew/Library/Taps/homebrew/homebrew-core" fetch --unshallow
  • git -C "/usr/local/Homebrew/Library/Taps/homebrew/homebrew-cask" fetch --unshallow

cask も使っている場合はそちらも unshallow する必要があります

解説: unshallow するとどうなるのか

--depth 1 は最新のコミットのみ取得しています
fetch --unshallow するとすべてのコミットを取得するのでデータも大きくなるし時間もかかります


リポジトリが大きい場合に shallow clone はよく使うのですがどうやら Github のトラフィックが大きくなるのですべてのコミットをローカルで持ち差分だけを見るように変更したようです

エラー全文

Error: homebrew-core is a shallow clone. To `brew update` first run: git -C "/usr/local/Homebrew/Library/Taps/homebrew/homebrew-core" fetch –unshallow This restriction has been made on GitHub's request because updating shallow clones is an extremely expensive operation due to the tree layout and traffic of Homebrew/homebrew-core. We don't do this for you automatically to avoid repeatedly performing an expensive unshallow operation in CI systems (which should instead be fixed to not use shallow clones). Sorry for the inconvenience!

2021年1月5日火曜日

(Ruby) tilt 超入門

概要

tilt は複数のテンプレートファイルを同じインタフェースで扱うことができる便利ライブラリです
今回は erb を使って簡単な操作方法を紹介します

環境

  • macOS 11.1
  • Ruby 2.7.2p137
    • tilt 2.0.10

インストール

  • bundle init
  • vim Gemfile
gem "tile"
  • bundle install

Getting Started

とりあえず動かしてみます

  • vim sample.erb
<%= @message %>


  • vim test.rb
require 'erb'
require 'tilt'

@message = "hello"
sample = Tilt.new('sample.erb')
output = sample.render(self)
puts output


  • bundle exec ruby test.rb

    => hello


テンプレート側でインスタンス変数を参照する場合は上記のようになります
Ruby スクリプト側でもインスタンス変数を宣言して render する際にインスタンス変数が存在しているクラスのオブジェクトを渡す必要があります

クラス内で使用する

render する際に self や Object.new を渡すケースは少ないのでクラス内で使用する場合は以下のようにします

  • vim test.rb
require 'erb'
require 'tilt'

@message = "hello"

class MyClass
  def initialize
    @sample = Tilt.new('sample.erb')
    @message = "hello in MyClass"
  end

  def render
    output = @sample.render(self)
    puts output
  end
end

cls = MyClass.new
cls.render


  • bundle exec ruby test.rb

    => hello in MyClass

ハッシュを渡す

テンプレートにハッシュを渡すこともできます
参照する場合はハッシュのキーを使って参照します

  • vim sample.erb
<%= message %>


  • vim test.rb
require 'erb'
require 'tilt'

h = {'message': 'hello'}
sample = Tilt.new('sample.erb')
output = sample.render(self, h)
puts output


  • bundle exec ruby test.rb

    => hello

オブジェクトを渡す

テンプレート側で渡されたオブジェクトのメンバを参照してみます

  • vim sample.erb
<%= hello %>


  • vim test.rb
require 'erb'
require 'tilt'

class Message
  def initialize
    @hello = 'hello'
  end

  attr_accessor :hello
end

msg = Message.new
sample = Tilt.new('sample.erb')
output = sample.render(msg)
puts output


  • bundle exec ruby test.rb

    => hello

オブジェクトを渡しているので参照する側はメンバやメソッドを直接参照する感じになります

ブロックを渡す

ブロックを渡してテンプレート側でコールすることもできます
テンプレート側は yield でブロックを受け取りましょう

  • vim sample.erb
<%= yield %>


  • vim test.rb
require 'erb'
require 'tilt'

class Message
  def initialize
    @msg = 'hello'
  end

  def hello
    Proc.new {
      @msg + "!!"
    }
  end
end

msg = Message.new
sample = Tilt.new('sample.erb')
output = sample.render(&msg.hello)
puts output


  • bundle exec ruby test.rb

    => hello!!

参考サイト