ℹ️本記事は古いコンテンツを変換して表示しています。
表示が崩れたり、リンクが正しくない可能性があります。ご了承ください。
ℹ️本記事は古いコンテンツを変換して表示しています。
表示が崩れたり、リンクが正しくない可能性があります。ご了承ください。
2023/09/18 12:09 : FreeBSDでOpenObserveクラスタ構築
elasticsearchとlogstash(とJava)に嫌気が差したので、MinIO+OpenObserveに引っ越した。
go install github.com/minio/minio@latest
でさくっと入る。特に書くことはない。やることはこれだけ。
go install github.com/minio/minio@latest go install github.com/minio/mc@latest
jail上で起動すると、root disk判定が誤判定するので、 MINIO_ROOTDISK_THRESHOLD_SIZE=1
など環境変数を設定しておく。もちろん保存先を間違えると大変な目に遭うので注意。
pkg install coreos-etcd34
で入る。ちなみにrc scriptがないので、自分で daemon
を呼ぶ。
起こし方は素直にhttps://etcd.io/docs/v3.5/op-guide/clustering/のガイドを読むのがいい。
一応残しておくと、試した設定はこんな感じ。各ホストで調整が必要なURLが多いので注意する。quorumを満たしていないと起動しないことと、一度起動できちゃうと無視される設定があるので注意する。変だなと思ったら rm -rf /var/db/etcd
して起動しなおすほうが早い。
name: openobserve1 data-dir: "/var/db/etcd/data" wal-dir: "/var/db/etcd/wal" strict-reconfig-check: true initial-cluster-state: new #initial-cluster-state: existing initial-cluster-token: openobserve-etcd initial-cluster: "openobserve1=http://10.0.0.1:2380,openobserve2=http://10.0.0.2:2380" initial-advertise-peer-urls: "http://10.0.0.1:2380" listen-peer-urls: "http://10.0.0.1:2380" advertise-client-urls: "http://10.0.0.1:2379" listen-client-urls: "http://10.0.0.1:2379,http://127.0.0.1:2379"
ビルドはサーバプロセス(rust)とWebUI(node.js)の2本立て。それぞれビルドする。
サーバ側はrustup.rsを使ってrustのnightlyを入れておく。pkg install rust-nightly
でも良さそうだが、どうもいつもcargoがコケるのでrustupを使っている。
rust(とcargo)を入れたらサーバをビルドする。そのままだとsimdjsonのビルドが失敗するので、.cargo/config.toml
に以下を書き加える。
[target.x86_64-unknown-freebsd] rustflags = ["-C", "target-feature=+sse2,+ssse3,+sse4.1,+sse4.2"]
書き加えたら、cargo build --release
でビルドする。
WebUIはnodeとnpmでビルドする。ちなみにpkg install node npm
したものだが、node18-18.16.0とnpm-node18-9.7.2になっている。まずはビルドに必要がなく、FreeBSDがunsupportedなCypressをpackage.jsonからもぎ取っておく。diffだとこんな感じ:
*** web/package.json.orig Mon Sep 11 08:34:13 2023 --- web/package.json Mon Sep 11 08:37:21 2023 *************** *** 14,21 **** "copy": "cd dist && mkdir src && cd src && mkdir assets && cd .. && cd .. && cp -r src/assets/* dist/src/assets/", "test:unit": "vitest --environment jsdom --root src/", "test:unit:coverage": "vitest --coverage", - "test:e2e": "start-server-and-test preview :4173 'cypress run --e2e'", - "test:e2e:dev": "start-server-and-test 'vite dev --port 4173' :4173 'cypress open --e2e'", "build-only": "vite build", "build-only-alpha1": "vite build --mode=alpha1", "build-only-cloud-prod": "vite build --mode=production", --- 14,19 ---- *************** *** 52,59 **** "vuex": "^4.0.2" }, "devDependencies": { - "@cypress/vue": "^4.0.0", - "@cypress/webpack-dev-server": "^2.0.0", "@quasar/vite-plugin": "^1.0.10", "@rushstack/eslint-patch": "^1.1.0", "@types/d3-hierarchy": "^3.1.2", --- 50,55 ---- *************** *** 71,82 **** "@vue/test-utils": "^2.0.2", "@vue/tsconfig": "^0.1.3", "c8": "^7.11.3", - "cypress": "^10.3.0", - "cypress-localstorage-commands": "^2.2.1", "dotenv": "^16.0.3", "eslint": "^8.5.0", "eslint-config-prettier": "^8.5.0", - "eslint-plugin-cypress": "^2.12.1", "eslint-plugin-vue": "^9.5.1", "fs-extra": "^11.1.1", "happy-dom": "^6.0.4", --- 67,75 ----
変更したら、npm i
、npm run build
でビルドする。distに成果物が入るので、ここをnginxなどで公開する。(後述)
それぞれビルドしたら起動する。WebUI側はstatic contentsなので、nginxなどでserveする。nginx.confはこんな感じだろうか:
worker_processes 1; events { worker_connections 1024; } http { include mime.types; sendfile on; keepalive_timeout 65; server { listen 80; server_name openobserve.coco.local; location / { proxy_pass http://127.0.0.1:5080; } location /assets { alias /openobserve/web/dist/assets; index index.html; } location /web { alias /openobserve/web/dist; index index.html; } } }
サーバプロセスは環境変数を設定して起こす。一覧はこちら: https://openobserve.ai/docs/environment-variables/たとえばこんな感じ。ZO_LOCAL_MODE_STORAGEはたぶん要らない。ZO_TELEMETRYとZO_PROMETHEUS_ENABLEDはお好みで。今回はminio/etcd/openobserveを全サーバにそれぞれ入れたので127.0.0.1になっているが、そこは環境に合わせて適宜調整。
ZO_LOCAL_MODE="false" ZO_LOCAL_MODE_STORAGE="s3" ZO_GRPC_ORG_HEADER_KEY="cluster" ZO_TELEMETRY="false" ZO_PROMETHEUS_ENABLED="true" ZO_ETCD_ADDR="http://127.0.0.1:2379" ZO_ROOT_USER_EMAIL="user@localhost.local" ZO_ROOT_USER_PASSWORD="super-complex-password" ZO_S3_ACCESS_KEY="" ZO_S3_SECRET_KEY=" " ZO_S3_REGION_NAME="any" ZO_S3_BUCKET_NAME="openobserve" ZO_S3_SERVER_URL="http://127.0.0.1:9000" ZO_S3_PROVIDER="minio"
これらをexportしたら引数なしでopenobserveを起動すればよい。
ところでOpenObserveのクラスタ構成はガイドがなくてやや不親切。ただ、k8s用helm chartがあるので、こいつを見ながら設定していた。
[2023-09-18T01:38:46Z INFO openobserve::service::search] service:search:enter; org_id="default" stream_type=Logs [2023-09-18T01:38:46Z INFO openobserve::service::search] service:search:cluster; org_id="default" [2023-09-18T01:38:46Z INFO openobserve::service::search::sql] service:search:sql:new; org_id="default" [2023-09-18T01:38:46Z INFO openobserve::service::search] get_file_list; stream_type=Logs time_level=Unset org_id="default" stream_name="default" [2023-09-18T01:38:46Z INFO openobserve::service::search] search->file_list: time_range: Some((1694914712941000, 1695001112941000)), num: 114, offset: 39 [2023-09-18T01:38:46Z INFO openobserve::service::search] service:search:cluster:grpc_search; org_id="default" [2023-09-18T01:38:46Z INFO openobserve::service::search] service:search:cluster:grpc_search; org_id="default" [2023-09-18T01:38:46Z INFO openobserve::service::search] service:search:cluster:grpc_search; org_id="default" [2023-09-18T01:38:46Z INFO openobserve::handler::grpc::request::search] grpc:search:enter; org_id="default" [2023-09-18T01:38:46Z INFO openobserve::service::search::grpc] service:search:grpc:search; org_id="default" [2023-09-18T01:38:46Z INFO openobserve::service::search::sql] service:search:sql:new; org_id="default" [2023-09-18T01:38:46Z ERROR openobserve::service::search] search->grpc: node: 2, search err: Status { code: Unauthenticated, message: "No valid auth token", metadata: MetadataMap { headers: {"c ontent-type": "application/grpc", "date": "Mon, 18 Sep 2023 01:38:46 GMT"} }, source: None } [2023-09-18T01:38:46Z INFO openobserve::service::search::grpc] service:search:grpc:in_wal; org_id="default" stream_name="default" stream_type=Logs [2023-09-18T01:38:46Z INFO openobserve::service::search::grpc] service:search:grpc:in_storage; org_id="default" stream_name="default" stream_type=Logs [2023-09-18T01:38:46Z INFO openobserve::service::search::grpc::storage] service:search:grpc:storage:enter; org_id="default" stream_name="default" [2023-09-18T01:38:46Z INFO openobserve::service::search::grpc::storage] search->storage: org default, stream default, load file_list num 39 [2023-09-18T01:38:46Z INFO openobserve::service::search::grpc::storage] search->storage: org default, stream default, load files 39, scan_size 17390808, compressed_size 1598007 [2023-09-18T01:38:46Z INFO tracing::span] service:search:grpc:storage:cache_parquet_files; [2023-09-18T01:38:46Z INFO openobserve::service::search::grpc::wal] service:search:wal:enter; org_id="default" stream_name="default" [2023-09-18T01:38:46Z INFO openobserve::service::search::grpc::wal] service:search:grpc:wal:get_file_list; org_id="default" stream_name="default" [2023-09-18T01:38:46Z INFO openobserve::service::search::grpc::wal] wal->search: load files 2, scan_size 34366 [2023-09-18T01:38:46Z INFO openobserve::service::search::grpc::wal] service:search:grpc:wal:datafusion; org_id="default" stream_name="default" stream_type=Logs [2023-09-18T01:38:46Z INFO openobserve::service::search::grpc::storage] search->storage: org default, stream default, load files 39, into memory cache done [2023-09-18T01:38:46Z INFO openobserve::service::search::grpc::storage] service:search:grpc:storage:datafusion; org_id="default" stream_name="default" stream_type=Logs [2023-09-18T01:38:46Z INFO tracing::span] datafusion::storage::memory::list; [2023-09-18T01:38:46Z INFO openobserve::service::search::datafusion::exec] Query took 0.008 seconds. [2023-09-18T01:38:46Z INFO openobserve::service::search::datafusion::exec] Query all took 0.009 seconds. [2023-09-18T01:38:46Z INFO openobserve::service::search::datafusion::exec] Query took 0.011 seconds. [2023-09-18T01:38:46Z INFO openobserve::service::search::datafusion::exec] Query all took 0.011 seconds. [2023-09-18T01:38:46Z INFO openobserve::service::search] search->grpc: result node: 3, is_querier: true, total: 0, took: 31, files: 36, scan_size: 22 [2023-09-18T01:38:46Z INFO openobserve::service::search] search->grpc: result node: 1, is_querier: true, total: 0, took: 41, files: 41, scan_size: 16 [2023-09-18T01:38:46Z ERROR openobserve::handler::http::request::search] search error: ErrorCode(ServerInternalError("search node error")) [2023-09-18T01:38:46Z INFO actix_web::middleware::logger] 10.33.3.28 "POST /api/default/_search?type=logs HTTP/1.0" 500 94 "141" "http://openobserve1.local/web/logstreams/stream-explore?s tream_name=default&stream_type=logs&org_identifier=default" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/117.0" 0.148536
ポイントは以下のログであろう。
[2023-09-18T01:38:46Z ERROR openobserve::service::search] search->grpc: node: 2, search err: Status { code: Unauthenticated, message: "No valid auth token", metadata: MetadataMap { headers: {"c ontent-type": "application/grpc", "date": "Mon, 18 Sep 2023 01:38:46 GMT"} }, source: None } [2023-09-18T01:38:46Z ERROR openobserve::handler::http::request::search] search error: ErrorCode(ServerInternalError("search node error"))
openobserver-2で検索を要求した場合、openobserve-1側に以下のようなログが残った。
[2023-09-18T01:39:50Z INFO openobserve::handler::grpc::auth] Err authenticating Invalid value provided for the HTTP Authorization header