mutao.net

いわゆる雑記。

Grafana Prometheusな環境構築

grafanaをラズパイにinstall

環境

Rasberry Pi4 ModelB

CentOS 8

構築

https://grafana.com/grafana/download?platform=arm

$ wget https://dl.grafana.com/oss/release/grafana-8.0.5-1.aarch64.rpm
$ sudo yum install grafana-8.0.5-1.aarch64.rpm
$ systemctl enable grafana-server
Synchronizing state of grafana-server.service with SysV service script with /usr/lib/systemd/systemd-sysv-install.
Executing: /usr/lib/systemd/systemd-sysv-install enable grafana-server
Created symlink /etc/systemd/system/multi-user.target.wants/grafana-server.service → /usr/lib/systemd/system/grafana-server.service.
$ firewall-cmd --zone=public --add-port=3000/tcp --permanent
$ systemctl restart firewalld.service
$ systemctl start grafana-server

デフォルトのログインは root : root でログインできる。

f:id:mutaonet:20210714201109p:plain

node_expoter

https://prometheus.io/download/#node_exporter

 ## documentにあるものだとエラーがでたのでgithubから直接wget
 $ wget https://github.com/prometheus/node_exporter/releases/download/v1.1.2/node_exporter-1.1.2.linux-arm64.tar.gz
 $ tar -xvzf node_exporter-1.1.2.linux-amd64.tar.gz
 
 ## ブラウザ経由でみたい場合firewallを設定する
 $ firewall-cmd --zone=public --add-port=9100/tcp --permanent
 
 $ systemctl restart firewalld.service
 $ ./node_exporter-1.1.2.linux-arm64/node_exporter
level=info ts=2021-07-11T09:35:59.700Z caller=node_exporter.go:178 msg="Starting node_exporter" version="(version=1.1.2, branch=HEAD, revision=b597c1244d7bef49e6f3359c87a56dd7707f6719)"
level=info ts=2021-07-11T09:35:59.700Z caller=node_exporter.go:179 msg="Build context" build_context="(go=go1.15.8, user=root@f07de8ca602a, date=20210305-09:32:30)"
level=warn ts=2021-07-11T09:35:59.700Z caller=node_exporter.go:181 msg="Node Exporter is running as root user. This exporter is designed to run as unpriviledged user, root is not required."
level=info ts=2021-07-11T09:35:59.701Z caller=filesystem_common.go:74 collector=filesystem msg="Parsed flag --collector.filesystem.ignored-mount-points" flag=^/(dev|proc|sys|var/lib/docker/.+)($|/)
level=info ts=2021-07-11T09:35:59.701Z caller=filesystem_common.go:76 collector=filesystem msg="Parsed flag --collector.filesystem.ignored-fs-types" flag=^(autofs|binfmt_misc|bpf|cgroup2?|configfs|debugfs|devpts|devtmpfs|fusectl|hugetlbfs|iso9660|mqueue|nsfs|overlay|proc|procfs|pstore|rpc_pipefs|securityfs|selinuxfs|squashfs|sysfs|tracefs)$
 $ curl http://localhost:9100/metrics
 $ mv node_exporter-1.1.2.linux-amd64/node_exporter /usr/local/bin
 
 ## servideファイルを作成する。
 $ vi /etc/systemd/system/node_exporter.service
 [Unit]
Description=Prometheus Node Exporter
Wants=network-online.target
After=network-online.target

[Service]
#User=node_exporter ## お好みのuserを指定
#Group=node_exporter
Type=simple
ExecStart=/usr/local/bin/node_exporter

[Install]
WantedBy=multi-user.target

Prometheus

https://github.com/prometheus/prometheus/releases/tag/v2.28.1

$ wget https://github.com/prometheus/prometheus/releases/download/v2.28.1/prometheus-2.28.1.linux-arm64.tar.gz
$ tar xvzf prometheus-2.28.1.linux-arm64.tar.gz
$ cd prometheus-2.28.1.linux-arm64
$ ./prometheus --config.file=prometheus.yml
## node_exporterを監視設定に含める
$ vi prometheus.yml
## 追記
  - job_name: 'node_exporter'
    static_configs:
    - targets: ['localhost:9100']
## 配置
$ mv prometheus-2.28.1.linux-arm64/prometheus /usr/local/bin;
$ mv prometheus-2.28.1.linux-arm64/promtool /usr/local/bin;

$ mv prometheus-2.28.1.linux-arm64/prometheus.yml /etc/prometheus/;

$ mv prometheus-2.28.1.linux-arm64/consoles /etc/prometheus/;
$ mv prometheus-2.28.1.linux-arm64/console_libraries /etc/prometheus/;

## Service化
$ vi /etc/systemd/system/prometheus.service
[Unit]
Description=Prometheus
Documentation=https://prometheus.io/docs/introduction/overview/
Wants=network-online.target
After=network-online.target

[Service]
#User=prometheus ## お好みで設定。ここで指定したユーザに/etc/prometheusあたりの権限を付与する。
#Group=prometheus
Type=simple
ExecReload=/bin/kill -HUP $MAINPID
ExecStart=/usr/local/bin/prometheus \
    --config.file=/etc/prometheus/prometheus.yml \
    --storage.tsdb.path=/var/lib/prometheus/ \
    --web.console.templates=/etc/prometheus/consoles \
    --web.console.libraries=/etc/prometheus/console_libraries \
    --web.listen-address=0.0.0.0:9090

SyslogIdentifier=prometheus
Restart=always

[Install]
WantedBy=multi-user.target

f:id:mutaonet:20210714201251p:plain

node_exporterのmetricsをGrafanaで可視化

Prometheusを選択。

f:id:mutaonet:20210714201345p:plain

左メニューからDashboardを作成。

Metrix browserから可視化したいものを選択するだけ。

f:id:mutaonet:20210714201502p:plain

drone-ci構築

drone

Github上のmainブランチへのmergeや、PR作成をhookして.drone.ymlに記載したpipelineを実行する。 build deployなんかができる。詳しくは公式documentを参照。

readme.drone.io

localで構築してみる。

これも公式documentを見るだけでできる。

docker-compose.ymlを作成すれば楽になる。

readme.drone.io

Github OAtuth Appを作成するにはcallback用のパブリックなドメイン(IP)が必要なのでngrokを利用する。

ngrok.com

---
version: '3'

services:
  drone-server:
    image: drone/drone:2
    ports:
      - 8000:80
      - 443:443
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - .:/data
    restart: always
    environment:
      - DRONE_GITHUB_SERVER=https://github.com
      - DRONE_GITHUB_CLIENT_ID=XXX
      - DRONE_GITHUB_CLIENT_SECRET=XXX
      - DRONE_RPC_SECRET=XXX # openssl rand -hex 16 で取得したsecret key
      - DRONE_SERVER_HOST=XXX.ngrok.io # ngrokで取得したドメイン
      - DRONE_SERVER_PROTO=https
      - DRONE_TLS_AUTOCERT=true

  drone-agent:
    image: drone/drone:2
    command: agent
    restart: always
    depends_on:
      - drone-server
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - DRONE_RPC_SERVER=http://drone-server
      - DRONE_RPC_SECRET=XXX  # openssl rand -hex 16 で取得したsecret key
      - DRONE_RUNNER_CAPACITY=2
$ docker-compose up

ngrokで取得したURLをブラウザで表示すると以下のようなダッシュボードが見える。

f:id:mutaonet:20210711163907p:plain

適当な.drone.ymlをリポジトリに作成してbuildしてみることで完了。

今回はhello worldするだけの.drone.ymlを作成しました。

f:id:mutaonet:20210711164123p:plain

今後のためのメモ

コンテナ起動後にagent側がclusheし続けること。

問題なくbuildもできるけど、正常な状態ではないので調査したい。

drone-agent_1   | {"level":"fatal","msg":"main: source code management system not configured","time":"2021-07-11T07:40:39Z"}
drone-study_drone-agent_1 exited with code 1
drone-study_drone-agent_1 exited with code 1

ngrokでToo Many Connections

drone2系で起きやすい。1系よりも多くのconnectionを貼るのかもしれない。

安定した環境で入門してみるなら1系の方がいいかもしれない。UIは異なる。

f:id:mutaonet:20210711164337p:plain

ngrok再起動でdocker-compose.ymlを修正しなければならない

DRONE_SERVER_HOST の値を変更する必要がある。以外と手間なのでちゃんとした環境を作りたい。

decleareでエラー

decleareでエラー

bashを使って簡単なscriptを書いたときにエラーが出たので軽くメモ

「decleareでエラー」の語感が好きだったという理由です。

#!/bin/bash
declare -A arr=(
    ["aaa"]="100"
    ["bbb"]="200"
    ["ccc"]="300"
)

for value in ${!arr[@]}; do
   echo ${value} ${arr[${value}]}
done
## 実行
$ ./test.sh
./test.sh: line 2: declare: -A: invalid option
declare: usage: declare [-afFirtx] [-p] [name[=value] ...]
0 300

原因はbashのバージョンが低いから

https://stackoverflow.com/questions/6047648/associative-arrays-error-declare-a-invalid-option

/bin/bash --version
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin20)
Copyright (C) 2007 Free Software Foundation, Inc.

brewbashをinstallします。4系からdeclareは使用可能です。

$ brew install bash
Updating Homebrew...
==> Auto-updated Homebrew!
Updated 1 tap (homebrew/core).
==> New Formulae
amfora                         ciphey                         envoy@1.17                     git-xargs                      kubeconform                    pythran                        spectra                        wasmtime
argocd-vault-plugin            demumble                       fcp                            jrsonnet                       lexbor                         ronn                           sqsmover                       wxmac@3.0
bosh-cli                       detect-secrets                 frum                           kalker                         multi-git-status               s4cmd                          svgbob
==> Updated Formulae
Updated 1515 formulae.
==> Renamed Formulae
weboob -> woob
==> Deleted Formulae
libinfinity

==> Downloading https://ghcr.io/v2/homebrew/core/bash/manifests/5.1.8
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/bash/blobs/sha256:62569d2e8452dd3cb61168ffc2581193989503f0e419c3cf1c32984d165ce139
==> Downloading from https://pkg-containers.githubusercontent.com/ghcr1/blobs/sha256:62569d2e8452dd3cb61168ffc2581193989503f0e419c3cf1c32984d165ce139?se=2021-07-07T03%3A40%3A00Z&sig=JwNonIiglsc99nsyES8%2BocmdDokosd8yyg5tVPC4RpU%3D&sp=r&spr=https&
######################################################################## 100.0%
==> Pouring bash--5.1.8.big_sur.bottle.tar.gz
🍺  /usr/local/Cellar/bash/5.1.8: 157 files, 10.9MB

## バージョン確認
$ /usr/local/bin/bash --version
GNU bash, バージョン 5.1.8(1)-release (x86_64-apple-darwin20.3.0)
Copyright (C) 2020 Free Software Foundation, Inc.
ライセンス GPLv3+: GNU GPL バージョン 3 またはそれ以降 <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

shebanをbrewで入れたbashのpathに変更します。

#!/usr/local/bin/bash

## 実行
$ ./test.sh          
bbb 200
ccc 300
aaa 100

Macbash書かないので今更遭遇したエラーでした。書くとしてもサーバで書く。

まぁ書くとしてもzshですよね。

td-agentでnginxのaccesslogを収集

前回apacheのtd-agentの設定は書いたけどnginxはまだ書いていなかったのでメモ。

<source>
  @type tail
  path /var/log/nginx/access.log
  format nginx
  tag nginx.access
  pos_file /var/log/td-agent/nginx.access.log.pos
</source>
<match nginx.access>
  @type elasticsearch
  host 127.0.0.1
  port 9200
  logstash_format true
  logstash_prefix nginx
  type_name accesslog
</match>

https://docs.fluentd.org/input/tail

Parameter value メモ
@type tail
path /var/log/nginx/access.log 取得するログのpath。「,」区切りで複数設定可能
tag nginx.access 後のmatchディレクティブで使用
pos_file td-agent(Fluentd)がログを読み取った位置を記載するファイル td-agentユーザの権限がある場所

https://docs.fluentd.org/output/elasticsearch

Parameter value メモ
@type elasticsearch
host elastic nodeが動作しているhost
port elastic nodeが動作しているport
logstash_format true logstash-%Y.%m.%dでindex nameが生成される。
logstash_prefix nginx logstash_format の 「logstash」部分を変更。
type_name elastic search の type

Raspberry Piにdocker-composeをinstall

環境

install

$ wget https://github.com/docker/compose/releases/download/1.25.5/docker-compose-Linux-x86_64
$ mv docker-compose-Linux-x86_64 /usr/local/bin/docker-compose
$ chmod 755 /usr/local/bin/docker-compose

docker-composeでエラー発生。

[dev@localhost drone]$ docker-compose up
-bash: /usr/local/bin/docker-compose: cannot execute binary file: Exec format error

どうやらOSに対応していないバイナリを実行しているのが原因みたい。

RasberryPiのCPUアーキテクチャはARMなのでそれが原因ぽいなぁということでバイナリ探しを始める。

バイナリがないので https://github.com/docker/compose.git をclone。

https://github.com/docker/compose/blob/master/script/build/linux

このscriptを実行する。

https://github.com/docker/compose/pull/6908

このPRを見るとRasberryPiにdocker-composeをinstallする手順が書いてありました。

PRから引用。docker自体は前もってinstall必要です。

Prerequisites

a Raspberry Pi
have Git and Docker installed
How to verify

Login to your Raspberry Pi
git clone https://github.com/docker/compose
cd compose
scripts/build/linux
dist/docker-compose-Linux-armv7l --version

↑の手順ではないですが、git checkout で installしたいバージョンのブランチにします。

https://github.com/docker/compose/tags

## 最新
$ git checkout 1.29.2
## scriptsってPRにあるけどscript配下にありました。
$ ./script/build/linux

## エラーメッセージでるけど無視、PATHが違うだけ、↑のscriptにこのコマンドを実行しているところをコメントアウトしてもいい気がする。
+ mv dist/docker-compose-linux-amd64 dist/docker-compose-Linux-aarch64
mv: 'dist/docker-compose-linux-amd64' を stat できません: No such file or directory

[root@localhost compose]# ll dist/
合計 10492
-rwxr-xr-x 1 root root 10741936  7月  3 09:13 docker-compose-linux-arm64
[root@localhost compose]# ./dist/docker-compose-linux-arm64 --version

## /usr/local/bin/に配置
mv /usr/bin/docker-compose /usr/local/bin/docker-compose

作業後気づいたこと

makefileありました。

https://github.com/docker/compose/blob/master/Makefile

調べたところpipで入れることもできるみたいです。

自宅にラズパイ以外のサーバが欲しくなってきている今日この頃。

GoでMySQL操作入門

MySQL用意

  • Localの環境を汚したくないのでテスト用のDBはDockerで用意する。
  • docker-compose でテスト用のデータを事前に入れておく

github.com

実際にSELECT文を打ってみる

  • 使用するモジュールをgo getで取得
go get github.com/go-sql-driver/mysql

github.com

  • テスト用コード
package main

import (
    "fmt"
    "database/sql"
    _ "github.com/go-sql-driver/mysql"
)

type User struct {
    ID   int
    Name string
}
func main() {
    db, err := sql.Open("mysql", "root:rootpassword@tcp(127.0.0.1:3306)/test")
    if err != nil {
        panic(err.Error())
        fmt.Print("connect failed.")
    }
    defer db.Close()
    fmt.Println("connect complete!")
 
    rows, err := db.Query("SELECT * FROM users")
    if err != nil {
        panic(err.Error())
        fmt.Println("select error occuerd.")
    }
    defer rows.Close()

    for rows.Next() {
        var user User
        err := rows.Scan(&user.ID, &user.Name)
        if err != nil {
            panic(err.Error())
        }
        fmt.Println(user.ID, user.Name)
    }
 
    err = rows.Err()
    if err != nil {
        panic(err.Error())
    }
}
  • エラー発生。
panic: sql: expected 4 destination arguments in Scan, not 2

goroutine 1 [running]:
main.main()
        go-learning/lession.go:51 +0x3f0
exit status 2
  • ぐぐってみると素晴らしいPOST発見

qiita.com

rows.Scanはカラムと一致していないとだめとのこと。

今回用意したテスト用データは以下のような構造をとっているため SELECT * で取得するとカラム数が一致せずエラーが発生する。

`id`, `name`, `register_date`, `update_time`

初歩的なSELECTで躓くのは久しぶりだったのでメモ

負荷

負荷とは

「CPU負荷」と「I/O負荷」に大別される。

CPU負荷( CPUバウンド)

  • プログラムの処理が原因でかかるCPUの負荷のこと
  • 大規模な計算を行うプログラムはディスクとの入出力は行わないが、計算処理はCPUの計算速度に依存する。

I/O負荷(I/Oバウンド)

  • ディスクとの入出力で発生する負荷のこと。
  • 大量のデータから任意のドキュメントを探索するプログラムはCPUではなく、ディスクの速度に依存する。
  • DBサーバはその特性によりCPUの計算速度よりもI/Oに対するインパクトが大きくなる。

psコマンド

$ps aux | head -1 をしているのはヘッダを見たいため。

$ ps aux | head -1 && ps aux | grep httpd
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root        6849  0.0  0.1  44256  6536 ?        Ss    5月30   1:40 /usr/sbin/httpd -DFOREGROUND
www       225430  0.0  0.1  56460  4592 ?        S     6月13   0:00 /usr/sbin/httpd -DFOREGROUND
www       225431  0.0  0.1 2293576 6108 ?        Sl    6月13   1:59 /usr/sbin/httpd -DFOREGROUND
www       225432  0.0  0.1 2490256 6340 ?        Sl    6月13   2:03 /usr/sbin/httpd -DFOREGROUND
www       225433  0.0  0.1 2293576 6140 ?        Sl    6月13   1:59 /usr/sbin/httpd -DFOREGROUND
  • %CPU: psコマンドを実行した際のプロセスのCPU使用率

  • %MEM: プロセスが物理メモリを消費しているかを%で表示

  • VSZ、RSS プロセスが確保している仮想メモリ領域のサイズ、物理メモリのサイズ

  • STAT: プロセスの状態

    STAT 状態 説明
    R (Rum) TASK_RUNNING 実行可能状態。CPUが空きさえすればいつでも実行可能
    S (Sleep) TASK_INTERRUPTED 割り込み可能。入力待ち、スリープ等
    D (Disk Sleep) TASK_UNINTERRUPTIBLE 割り込み不可能。主に短時間で復帰する場合の状態。ディスク入出力待ち
    Z(Zombie) TASK_ZOMBIE ゾンビ状態。子プロセスがexitとして親プロセスにリープされるまでの状態
  • TIME: CPUを使用した時間