Elastic Stack 8系をFreeBSDにインストール

もしも、FreeBSDにElastic Stack 8をインストールしてみたら

今回はElastic Search 8とKibana 8をFreeBSDにインストールして使用できる状態にする。なお、この記事のタイトルは「Elastic Stack 8のインストール」だがLogstashは次回以降の予定。
「がとらぼ」では過去にElactic Stackの5系と6系のインストール記事を公開していますが、8系ではセキュリティー強化の影響で使えるようになるまでの手順が大幅に変わっています。古い系統のドキュメント参照すると「訳がわからない」「全然動かない?」ということになるので8系をインストールするなら8系向けのドキュメントを参照してください。7系については「がとらぼ」では触ったことがないので全く知りません。

インストール

いつものようにportsを使います。ElasticsearchはJava JDKと関連portsを必要とするのでJDK関連のビルド時間が長めです。KibanaはNode.jsを必要とするのでNode.jsのビルド時間が長めです。

# cd /usr/ports/textproc/elasticsearch8
# make install

configオプション
[x] DOCS Build and/or install documentation

# cd /usr/ports/textproc/kibana8
# make install

Javaを使えるようにするために 以下4つのファイルを編集

/etc/fstab (追記2行)
fdesc           /dev/fd         fdescfs rw      0       0
proc            /proc           procfs  rw      0       0
/boot/loader.conf (追記1行)
fdescfs_load="YES"
/.cshrc (追記1行)
setenv JAVA_HOME /usr/local/openjdk17
/.profile (追記1行)
export JAVA_HOME=/usr/local/openjdk17

Elastic Search本体の稼働で必要なJavaの環境設定は/usr/local/etc/rc.d/elasticsearchの中のES_JAVA_HOMEで行われていますが、Elastic Search本体以外のJavaプログラムの実行に/.cshrcや/.profileのJAVA_HOME変数が要ります。JAVA_HOMEだと警告がうるさいですが。

Elasticsearch 8の設定

/usr/local/etc/elasticsearch/jvm.options (2行の行頭の#を削除)
-Xms4g
-Xmx4g

ヒープサイズは自動設定される(設定ファイルの初期値はコメント状態)ということになっているが、搭載しているシステムメモリが少なめの場合は自動設定ではElasticSearchが起動しないよう。最初は1GB程度(-Xms1g -Xmx1g)で設定しておいて、運用開始後に必要に応じてサイズを大きい方に変更。

システムを再起動する。

システム再起動後
# df -a
Filesystem  1K-blocks      Used     Avail Capacity  Mounted on
/dev/ada0p2 472844096 122611692 312404880    28%    /
devfs               1         1         0   100%    /dev
/dev/ada0p1       767       131       636    17%    /boot/efi
fdescfs             1         1         0   100%    /dev/fd     ←この行があること
procfs              4         4         0   100%    /proc       ←この行があること

Elastic Searchの設定ファイルの編集

殆どはFreeBSDのports/pkgでインストールした設定のままで良い筈。逆に古いバージョンのElastic Searchのインストール/設定系の記事を見て迂闊な設定を行うとElastic Searchが動かくなくて悩むことになるかも。
少なくともElasticSearch 8系は、最初の起動時にlocalhost向けのTLS接続用証明書が作成されてlocalhostからの接続のみを許可する状態になるのでlocalhost以外からの接続を許すnetwork.host設定を行うと起動が失敗するようになるっぽい。旧系の設定では最初からLAN内OKだとかなんなら0.0.0.0(全世界OK)のような設定をしていたと思われるのでそこは注意。
Elasticsearch初起動時に証明書が作成されるのだが、ネットワークインターフェイスに割り当てられているIPアドレスとそのホスト名が正しく認識されないことがあるよう。localhostしか認識されずに証明書が作成されると後で苦労することがあるよう。/etc/hostsの記述が適切な状態にしてからElasticsearchを起動する方がより確実?

/usr/local/etc/elasticsearch/elasticsearch.yml (編集)
node.name: node-1  (任意の名前)
path.data: /var/db/elasticsearch (FreeBSD ports/pkg初期値)
path.logs: /var/log/elasticsearch (FreeBSD ports/pkg初期値)

#network.host: 192.168.0.1      (コメントのままにしておくか network.host: 0.0.0.0)
http.port: 9200
transport.port: 9300
discovery.type: single-node  (Elasticsearchを1ノードで使用する場合)
xpack.ml.enabled: false  (FreeBSD ports/pkg初期値)
/etc/rc.conf (追記1行)
elasticsearch_enable="YES"
Elastic Searchサービスの起動
# service elasticsearch start

初回起動時に以下の設定が自動で追加される。

/usr/local/etc/elasticsearch/elasticsearch.yml (ファイル最後を確認)
# Enable security features
xpack.security.enabled: true

xpack.security.enrollment.enabled: true

# Enable encryption for HTTP API client connections, such as Kibana, Logstash, and Agents
xpack.security.http.ssl:
  enabled: true
  keystore.path: certs/http.p12     (/usr/local/etc/elasticsearch/certs下のこと)

# Enable encryption and mutual authentication between cluster nodes
xpack.security.transport.ssl:
  enabled: true
  verification_mode: certificate
  keystore.path: certs/transport.p12
  truststore.path: certs/transport.p12
# Create a new cluster with the current node only
# Additional nodes can still join the cluster later
cluster.initial_master_nodes: ["node-1"]        (localhostのみ許可で起動すればノード名はこのelasticsearch.ymlで設定したnode.nameと同じなるかと)

最後のcluster.initial_master_nodes:の行はElasticsearchをシングルノードで使用する場合は削除する。設定次第だが、この行があるとElasticsearchが起動に失敗することがあるよう。

自動作成された証明書の確認

Elasticsearch初起動時に /usr/local/etc/elasticsearch/certsに CA証明書 http_ca.crt、Elasticsearchのxpack.security.http.sslで使われる http.p12、xpack.security.transport.sslで使われるtransport.p12の3つが全自動で作成されるが、http_ca.crtとtransport.p12はパスワードの入力も求められてなくて証明書の作成に関する表示も無かったのでそのパスワードが不明。 しかし、パスワードは管理されているらしくキーストアで確認できるよう。

# elasticsearch-keystore show xpack.security.http.ssl.keystore.secure_password
RSbq5dtTRXSuOsuUB4sumB   (← http.p12証明書のパスワードの例)

求めたパスワードを使用し、次のように証明書の中身を表示する。

# keytool -list -v -keystore /usr/local/etc/elasticsearch/certs/http.p12 -storetype PKCS12 -storepass 'RSaq5duTRXSuOsuUB3sumA'
Keystore type: PKCS12
Keystore provider: SUN

Your keystore contains 2 entries

Alias name: http
Creation date: Jan 12, 2023
Entry type: PrivateKeyEntry
Certificate chain length: 2
Certificate[1]:
Owner: CN=node-1
Issuer: CN=Elasticsearch security auto-configuration HTTP CA
Serial number: f01242a44e58729d4857701b8d665ab9955f4265
Valid from: Thu Jan 12 22:37:13 JST 2023 until: Sat Jan 11 22:37:13 JST 2025
Certificate fingerprints:
         SHA1: 84:A3:83:58:87:EF:BE:D7:A5:10:C6:CC:B5:A6:C4:56:EF:D1:B5:AD
         SHA256: AF:66:2D:04:2E:83:BC:56:CE:8B:A0:8F:45:95:73:3E:56:F6:11:3F:75:A5:1A:1F:94:4C:92:2C:3F:10:65:FE
Signature algorithm name: SHA256withRSA
Subject Public Key Algorithm: 4096-bit RSA key
Version: 3

この後もズラズラ出てきます

ここで確認しておきたいのがSAN情報。中段あたりに「SubjectAlternativeName」があるのでそこに含まれるDNSホスト名とIPアドレスを確認します。

SubjectAlternativeName [
  DNSName: localhost
  IPAddress: 127.0.0.1
  IPAddress: 192.168.0.128
  DNSName: es.example.com
  IPAddress: 192.168.16.1
]

ここでループバックアドレスの127.0.0.1とlocalhostしかない場合はそのあと証明書の再作成が必要になると思われます。苦労されられそうなので /usr/local/etc/elasticsearch/certsとelasticsearch.keystore を削除し、 /usr/local/etc/elasticsearch/elasticsearch.yml の最後の方「BEGIN SECURITY AUTO CONFIGURATION 」の行から最後を全て削除します。xpack関係の設定がElasticsearch初起動時に自動で追加されたものです。
そしてElasticsearchを再起動して証明書が再作成されたら再びその証明書を確認します。

Elastic Searchにアクセスしてみる

# curl 'http://localhost:9200/'    (旧版と同じ方法で非HTTPS接続)
curl: (52) Empty reply from server
Elastic Searchからの返事は空でした。
# curl 'https://localhost:9200'    (旧版と同じ方法でHTTPS接続)
curl: (60) SSL certificate problem: self signed certificate in certificate chain
More details here: https://curl.se/docs/sslcerts.html

# curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.
TLS証明書の問題でダメでした。
# curl --cacert /usr/local/etc/elasticsearch/certs/http_ca.crt 'https://localhost:9200'    (証明書を指定してHTTPS接続)
{"error":{"root_cause":[{"type":"security_exception","reason":"missing authentication credentials for REST request [/]","header":{"WWW-Authenticate":["Basic realm=\"security\" charset=\"UTF-8\"","Bearer realm=\"security\"","ApiKey"]}}],"type":"security_exception","reason":"missing authentication credentials for REST request [/]","header":{"WWW-Authenticate":["Basic realm=\"security\" charset=\"UTF-8\"","Bearer realm=\"security\"","ApiKey"]}},"status":401}

Elastic Searchから返事は受け取れましたがユーザー認証が要るようです。
Elastic Searchの特権ユーザーは「elastic」ですが、パスワードなんて知りません。ここは「elastic」ユーザーのパスワードをリセットします。

/usr/local/bin/elasticsearch-setup-passwordsでパスワードを生成します。
# elasticsearch-reset-password --auto --username elastic
warning: ignoring JAVA_HOME=/usr/local/openjdk17; using bundled JDK
This tool will reset the password of the [elastic] user to an autogenerated value.
The password will be printed in the console.
Please confirm that you would like to continue [y/N]y ( yを選択)

Password for the [elastic] user successfully reset.
New value: *i=1234himitsu_abc    (elasticユーザーの新しいパスワードが生成されたのでメモします)

elasticユーザーと発行したパスワードを使ってElasticsearchと通信してみる。

# curl --cacert /usr/local/etc/elasticsearch/certs/http_ca.crt -u elastic 'https://localhost:9200'
Enter host password for user 'elastic':  *i=1234himitsu_abc  (パスワード入力)
{
  "name" : "node-1",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "xOps88YeSGVcnQFQVxXHQ9",
  "version" : {
    "number" : "8.5.3",
    "build_flavor" : "default",
    "build_type" : "tar",
    "build_hash" : "4ed5ee9afac63de92ec98f404ccbed7d3ba9584e",
    "build_date" : "2022-12-05T18:22:22.226119656Z",
    "build_snapshot" : false,
    "lucene_version" : "9.4.2",
    "minimum_wire_compatibility_version" : "7.17.0",
    "minimum_index_compatibility_version" : "7.0.0"
  },
  "tagline" : "You Know, for Search"
}

通信できることを確認できました。

既にあるElasticsearchクラスタにノード登録する

稼働中のElasticsearchクラスタのElasticsearchサービスでエンロールメント(登録)・トークンを発行します。

# elasticsearch-create-enrollment-token -s node
a1b2c3-トークン文字列-7x8y9z

トークンは200文字以上ほどありますがコピーします。トークンは発行から30分間有効です。

発行したトークンを新しく動かすElasticsearchノードに適用します。

# elasticsearch --enrollment-token a1b2c3-トークン文字列-7x8y9z

当然ですが、Elasticsearchのホストが1台しかないのであればこのトークンの発行と登録は行いません。

Kibanaの設定

/usr/local/etc/kibana/kibana.yml
server.port: 5601
server.host: 192.168.2.16   Kibana(+Elastic Search)があるホストのIPアドレス等(ブラウザ側)
elasticsearch.hosts: ['https://localhost:9200']    (KibanaとElasticsearchが別ホストならElasticsearchのIPアドレス等を指定してください)
pid.file: /var/run/kibana.pid
i18n.locale: ja-JP
server.publicBaseUrl: "http://192.168.2.16:5601"

最も基本的な設定ですが、これだと実用的ではないかと思われます。

/usr/local/etc/kibana/kibana.yml (変更)
server.name: kibana.example.com
server.port: 5601
server.host: 0.0.0.0
server.ssl.enabled: true
server.ssl.certificate: /usr/local/etc/kibana/certs/fullchain.pem
server.ssl.key: /usr/local/etc/kibana/certs/privkey.pem
server.publicBaseUrl: 'https://kibana.example.com:5601'
elasticsearch.hosts: ['https://192.168.2.16:9200']
pid.file: /var/run/kibana.pid
i18n.locale: ja-JP

SSL/TLS対応の設定です。
Kibanaが1つのネットワークだけを相手にするならserver.hostには普通にネットワークインターフェイスに割り当てられたIPアドレスを指定しますが、beatsを使用するなどで複数のネットワークのIPアドレスを使うなら0.0.0.0の方が良さそうです。
192.168.2.16はElasticsearchがあるホストです。ElasticsearchとはHTTPSで通信するので https://192.168.2.16:9200 というURLを使用します。ElasticsearchとKibanaが同じホストで稼働するならhttps://localhost:9200というURLでも良いのですが、この次のトークン登録を行うと何故かループバックアドレスからネットワークインターフェイスに割り当てられたIPアドレスに書き換えられます。(理由は不明です)

ユーザーがブラウザでKibanaと通信する側は、server.ssl〜の設定です。elasticの公式ドキュメントではオレオレ証明書を使うようですが、ここではLet's Encryptの証明書を使用することにしました。ユーザーのブラウザ側でCA証明書を登録せずに済みます。ただし、certbotで普通に取得/更新した証明書ファイルはパーミッションの関係でKibanaが読み取れないためKibanaが起動に失敗するか起動してもブラウザでなにも表示できない状態になるかもしれません。
/usr/local/etc/kibana/cert のようなディレクトリを作成してLet's Encryptの証明書置き場(FreeBSDでcertbotを使って証明書を取得/更新しているなら /usr/local/etc//usr/local/etc/letsencrypt/live/ホスト名 )から fullchain.pem と privkey.pem をコピーしKibanaが読めるパーミッションを設定します。Let's Encryptの証明書は3ヶ月で期限を迎えるので自動更新の度に証明書ファイルのコピーとパーミッション設定の変更を行うようにしておきます。Kibanaサービスを再起動させることも忘れずに。

KibanaをElasticsearchクラスタに参加させるためにエンロールメント(登録)・トークンを発行します。Elasticsearchで発行してKibanaに登録するものです。

# elasticsearch-create-enrollment-token -s kibana --url "https://localhost:9200"
eyJ2ZXIiOiI4LjUuMyIsImFkciI6WyIxMjcuMD4wLjE6OTIvMCJdLCJmZ3IiOiI1ODM0Y2EzNjkyNjgxNDBlMWFhNyJiMDU4MzM4NDZzMzIxMDk0Yjc0YzVlNmVh1DM1ZTk5ODBiNWI1MmIwMDAyIiwia2V5IjohNFVUNmxJVUJrM1FfWEM5SXNmdTQ6Z05wNmZ1YzeTSWVQbF85ZnQxYlVhdyH9

トークンは200文字以上ほどありますがコピーします。トークンは発行から30分間有効です。

発行したトークンをKibanaに適用します。
# kibana-setup --enrollment-token eyJ2ZXIiOiI4LjUuMyIsImFkciI6WyIxMjcuMD4wLjE6OTIvMCJdLCJmZ3IiOiI1ODM0Y2EzNjkyNjgxNDBlMWFhNyJiMDU4MzM4NDZzMzIxMDk0Yjc0YzVlNmVh1DM1ZTk5ODBiNWI1MmIwMDAyIiwia2V5IjohNFVUNmxJVUJrM1FfWEM5SXNmdTQ6Z05wNmZ1YzeTSWVQbF85ZnQxYlVhdyH9

✔ Kibana configured successfully.

To start Kibana run:
  bin/kibana

Kibanaの設定ファイル /usr/local/etc/kibana.yml を確認すると既存の設定が全てコメント化された上で設定ファイルの最後に以下のように変更後の設定が追記されています。

### >>>>>>> BACKUP END: Kibana interactive setup (2023-01-09T05:33:59.285Z)

# This section was automatically generated during setup.
server.port: 5601
server.host: 192.168.2.16
server.publicBaseUrl: 'http://192.168.2.16:5601'
elasticsearch.hosts: ['https://127.0.0.1:9200']
pid.file: /var/run/kibana.pid
i18n.locale: ja-JP
elasticsearch.serviceAccountToken: AAEAAVWsYXN0aWMva2liZW5hL2Vucm8sbC2wcm9jZXNzMXRva2VuLTS2NzMyNDI0MzgxMzN6Z2F6RjBhYTtSU1NBVGxa0ElzSOlYdw
elasticsearch.ssl.certificateAuthorities: [/usr/local/www/kibana8/data/ca_1673242439266.crt]
xpack.fleet.outputs: [{id: fleet-default-output, name: default, is_default: true, is_default_monitoring: true, type: elasticsearch, hosts: ['https://127.0.0.1:9200'], ca_trusted_fingerprint: 5834cb430379250e2aa83b169449574432105b85c6e7ea945e0091b6b63b1113}]

elasticsearch.serviceAccountToken以下に見慣れない文字列が追加されたことが確認できる筈です。

Kibana暗号鍵を作成します。 これは今すぐ必要なものかは知りません。

# kibana-encryption-keys generate
## Kibana Encryption Key Generation Utility

The 'generate' command guides you through the process of setting encryption keys for:

xpack.encryptedSavedObjects.encryptionKey
    Used to encrypt stored objects such as dashboards and visualizations
    https://www.elastic.co/guide/en/kibana/current/xpack-security-secure-saved-objects.html#xpack-security-secure-saved-objects

xpack.reporting.encryptionKey
    Used to encrypt saved reports
    https://www.elastic.co/guide/en/kibana/current/reporting-settings-kb.html#general-reporting-settings

xpack.security.encryptionKey
    Used to encrypt session information
    https://www.elastic.co/guide/en/kibana/current/security-settings-kb.html#security-session-and-cookie-settings


Already defined settings are ignored and can be regenerated using the --force flag.  Check the documentation links for instructions on how to rotate encryption keys.
Definitions should be set in the kibana.yml used configure Kibana.

Settings:
xpack.encryptedSavedObjects.encryptionKey: 4763d4056ec09e774c014c4d48ab303b
xpack.reporting.encryptionKey: 1573470ac0b0f11d1bfd6fe8b5a8ceb9
xpack.security.encryptionKey: 54dd262b80818930ac88f641ac621111

生成された鍵(最後の3行まるごと)をコピーして/usr/local/etc/kibana.ymlの最後に貼り付けます。

ビルトインユーザー

Elasticのドキュメントによるとビルトインユーザーは以下のとおり。

  • elastic - スーパーユーザー
  • kibana_system - Kibana が Elasticsearch との接続と通信に使用するユーザー
  • logstash_system - Elasticsearch に監視情報を保存するときに Logstash が使用するユーザー
  • beats_system - Elasticsearch に監視情報を保存するときに Beats が使用するユーザー
  • apm_system - モニタリング情報を Elasticsearch に保管するときに APM サーバーが使用するユーザー
  • remote_monitoring_user - Elasticsearch で監視情報を収集および保存するときに Metricbeat が使用するユーザー

Kibana使用開始

/etc/rc.conf (追記1行)
kibana_enable="YES"
Kibanaを起動します。
# service kibana start

Elastic Stack 8でKibana 8を触る 1
KibanaとElasticsearchが正常に起動していて通信できる状態であればログイン画面が表示される。今回はユーザーをelastic、パスワードは先に取得したものを入力してログインする。
x-packのセキュリティーをfalseにしていたらログイン画面ではないかもしれないが、Elastic Stack 5, 6の頃と違いセキュリティの無効化が面倒?になってるようなのでこの記事のやり方でx-packのセキュリティを有効化した状態で設定する方が無難だと思われます。

Elastic Stack 8でKibana 8を触る 2
とりあえず、「統合を追加」が推奨されているようなので素直にクリック。

Elastic Stack 8でKibana 8を触る 3
多くのサービスが表示されるが、とりあえず左上の (ハンバーガーメニュー)をクリック。

Elastic Stack 8でKibana 8を触る 4
サイドメニューが表示されるので一番下の「スタック管理」をクリック。

Elastic Stack 8でKibana 8を触る 5
サイドメニューが「スタック管理」になるので「セキュリティ」の項目の中の「ロール」をクリック。

Elastic Stack 8でKibana 8を触る 6
「ロール」は役割りのようなもの。kibanaを使うユーザーの役割りはkibana_userかなと思うのだが、よくわからないが「非推奨」になっている。

Elastic Stack 8でKibana 8を触る 7
「kibana_user」ロールをクリックして閲覧すると、「kibana_user ロールは非推奨です。Please use the [kibana_admin] role instead」と書かれている。kibana_adminのロールを使えとのこと。「kibana_user」にはkibanaの「スペース」以外には何の権限も与えられていないよう。これは「kibana_admin」と同じ。つまり、kibana_userとkibana_adminは全く同じ役割りで、今後はkibana_userではなくkibana_adminを使えということのよう。

Elastic Stack 8でKibana 8を触る 8
サイドメニューの「セキュリティ」の項目の中の「ユーザー」をクリック。
Elastic Stack 5,6の頃はルユーザーがKibanaにログイン/操作するのには「kibana」ユーザーを使った認識だが、その「kibana」ユーザーは「非推奨」になっている。そしてこの「kibana」ユーザーに与えられているロールは「kibana_system」。同じロールは「kibana_system」ユーザーにも与えられているが、ありゃりゃ?「Kibana が Elasticsearch との接続と通信に使用するユーザー」ってやつだよね。Kibanaを操作するユーザーでもロールでもない。というか、初期登録済みのユーザーにkibana_adminロールが与えられたものが無いんだけど??

Elastic Stack 8でKibana 8を触る 9
「kibana」ユーザーを閲覧したところ、「このユーザーは廃止予定です。」とのこと。そして「use the 'kibana_system' user instead.」になってるので、「kibana」と「kibana_system」に与えられたロールが同じであることは納得できる。今後は「kibana」ではなく「kibana_system」ユーザーを使えということ。でも、あれ?あれ?

Elastic Stack 8でKibana 8を触る 10
kibana_systemロールを確認した。ビルトインのロールは変更も削除もできないのだが、「このロールはKibanaへのアクセスを許可しません」になっている。つまりこのロールが割り当てられているkibanaユーザーとkibana_systemはKibanaにアクセスできないということ。ビルトインユーザーではスーパーユーザーの「elastic」以外はKibanaにログイン/操作できないということかしら?

Elastic Stack 8でKibana 8を触る 11
唐突たが、この「スタック管理」の「Kibana」の項目にある「高度な設定」の下の方に「使用データ」の設定がある。「使用状況データ」を提供のスイッチは「オフ」にして右下の「変更を保存」をクリック。これはしておいた方が良さそう。

Elastic Stack 5系,6系の頃と別物に見えるくらい変わっていたので驚いたが、素直に行うべきおことを行えば使えるようになるのは変わらない筈。まぁ、何をしたら良いかがわからなくて難しそうに思えるのも変わらないんたけど。

次回以降でいろいろ使えるようにしていく予定。

関連記事: