Elastic Stackを集中ログソリューションとして使用することを決定する前は、何千ものデバイスで構成されるネットワークのログ分析は、複雑で時間のかかる退屈な作業でした。それは非常に賢明な決断であることが証明されました。すべてのログを検索する場所が1つしかないだけでなく、検索結果がほぼ瞬時に得られ、分析とトラブルシューティングに非常に役立つ強力な視覚化と、ネットワークの便利な概要を示す美しいダッシュボードが得られます。
Elastic Stackは常に新しい驚くべき機能をリリースしており、非常に活発な開発ペースを維持しており、毎月2つの新しいリリースを提供することがよくあります。新しい機能や改善点を利用できるように、常に環境を最新の状態に保つのが好きです。また、バグやセキュリティの問題から解放されます。しかし、これには常に環境を更新する必要があります。
ElasticのWebサイトは明確で詳細な状態を維持していますが、 ドキュメンテーション 、製品のアップグレードプロセスを含め、手動でのアップグレードは複雑なタスクであり、特にElasticsearchクラスターではそうです。関係するステップはたくさんあり、非常に特定の順序に従う必要があります。そのため、ずっと前に、AnsiblePlaybooksを使用してプロセス全体を自動化することにしました。
このAnsibleチュートリアルでは、ElasticStackインストールを自動アップグレードするために開発された一連のAnsiblePlaybookについて説明します。
以前はELKスタックと呼ばれていたElasticStackは、 Elasticsearch 、Logstash、およびKibanaは、オープンソース企業Elasticの製品であり、データのインデックス作成、検索、分析のための強力なプラットフォームを提供します。幅広い用途に使用できます。ロギングとセキュリティ分析からアプリケーションパフォーマンス管理とサイト検索まで。
Elasticsearch スタックのコアです。これは、大量の保存データに対してもほぼリアルタイムの検索結果を提供できる分散型の検索および分析エンジンです。
Logstash は、さまざまなソース(私が書いている50の公式入力プラグイン)からデータを取得または受信し、それを解析、フィルタリング、変換して、1つ以上の可能な出力に送信する処理パイプラインです。私たちの場合、Elasticsearch出力プラグインに関心があります。
Kibana ユーザーと操作のフロントエンドです。データを視覚化、検索、ナビゲートし、データに関する驚くべき洞察を提供するダッシュボードを作成できます。
Ansibleは、システムの構成、ソフトウェアの展開またはアップグレード、および複雑なITタスクの調整に使用できるIT自動化プラットフォームです。その主な目標は、シンプルさと使いやすさです。 Ansibleの私のお気に入りの機能は、エージェントレスであるということです。つまり、管理したいホストやデバイスに追加のソフトウェアをインストールして管理する必要がありません。 Ansible自動化の機能を使用して、ElasticStackを自動アップグレードします。
ここで共有するプレイブックは、公式製品のドキュメントに記載されている手順に基づいています。同じメジャーバージョンのアップグレードにのみ使用することを目的としています。例:5.x
→5.y
または6.x
→6.y
ここでx
> y
。メジャーバージョン間のアップグレードには、多くの場合、追加の手順が必要であり、それらのプレイブックはそのような場合には機能しません。
とにかく、プレイブックを使用してアップグレードする前に、リリースノート、特に重大な変更のセクションを常に読んでください。プレイブックで実行されるタスクを理解していることを確認し、アップグレード手順を常にチェックして、重要な変更がないことを確認してください。
そうは言っても、Elasticsearchのバージョン2.2以降、これらのプレイブック(または以前のバージョン)を問題なく使用しています。当時、私は製品ごとに完全に別々のプレイブックを持っていました。彼らが知っているのと同じバージョン番号を共有していなかったからです。
そうは言っても、私はこの記事に含まれる情報の使用について一切責任を負いません。
プレイブックが実行される環境は、6台のCentOS7サーバーで構成されます。
環境のサーバー数が異なっていても問題ありません。それに応じてインベントリファイルに反映するだけで、プレイブックは問題なく実行されます。ただし、RHELベースのディストリビューションを使用していない場合は、ディストリビューション固有のいくつかのタスク(主にパッケージマネージャーのもの)を変更するための演習として残しておきます。
Ansibleには、プレイブックを実行するホストを知るためのインベントリが必要です。 4つの想像上のシナリオでは、次のインベントリファイルを使用します。
Javaでユニットテストケースを書く方法
[logstash] server01 ansible_host=10.0.0.1 [kibana] server02 ansible_host=10.0.0.2 [elasticsearch] server03 ansible_host=10.0.0.3 server04 ansible_host=10.0.0.4 server05 ansible_host=10.0.0.5 server06 ansible_host=10.0.0.6
Ansibleインベントリファイルでは、任意の[section]
ホストのグループを表します。インベントリには、logstash
、kibana
、およびelasticsearch
の3つのホストグループがあります。プレイブックではグループ名のみを使用していることに気付くでしょう。つまり、グループが正しい限り、プレイブックが実行されるので、インベントリ内のホストの数は関係ありません。
アップグレードプロセスは、次の手順で構成されます。
サプライヤーの交渉力を定義する
1)パッケージを事前にダウンロードする
2)Logstashのアップグレード
3)Elasticsearchクラスターのローリングアップグレード
4) Kibana Upgrade
主な目標は、ダウンタイムを最小限に抑えることです。ほとんどの場合、ユーザーは気付かないでしょう。 Kibanaが数秒間利用できない場合があります。それは私には受け入れられます。
アップグレードプロセスは、さまざまなプレイブックのセットで構成されています。 Ansibleのimport_playbook機能を使用して、すべてのプレイブックを1つのメインプレイブックファイルに整理します。このファイルを呼び出して、プロセス全体を処理できます。
- name: pre-download import_playbook: pre-download.yml - name: logstash-upgrade import_playbook: logstash-upgrade.yml - name: elasticsearch-rolling-upgrade import_playbook: elasticsearch-rolling-upgrade.yml - name: kibana-upgrade import_playbook: kibana-upgrade.yml
かなり簡単です。これは、プレイブックの実行を1つの特定の順序で整理する方法にすぎません。
それでは、上記のAnsibleプレイブックの例をどのように使用するかを考えてみましょう。後でどのように実装するかを説明しますが、これはバージョン6.5.4にアップグレードするために実行するコマンドです。
$ ansible-playbook -i inventory -e elk_version=6.5.4 main.yml
その最初のステップは実際にはオプションです。これを使用する理由は、アップグレードする前に実行中のサービスを停止することをお勧めするためです。これで、高速インターネット接続がある場合、パッケージマネージャーがパッケージをダウンロードする時間はごくわずかかもしれません。しかし、常にそうとは限らないので、サービスがダウンする時間を最小限に抑えたいと思います。これが、私の最初のプレイブックがyumを使用してすべてのパッケージを事前にダウンロードする方法です。そうすれば、アップグレードの時期が来たときに、ダウンロード手順はすでに処理されています。
- hosts: logstash gather_facts: no tasks: - name: Validate logstash Version fail: msg='Invalid ELK Version' when: elk_version is undefined or not elk_version is match('d+.d+.d+') - name: Get logstash current version command: rpm -q logstash --qf %{VERSION} args: warn: no changed_when: False register: version_found - name: Pre-download logstash install package yum: name: logstash-{{ elk_version }} download_only: yes when: version_found.stdout is version_compare(elk_version, '<')
最初の行は、このプレイがlogstash
にのみ適用されることを示していますグループ。 2行目は、Ansibleにホストに関する事実をわざわざ収集しないように指示しています。これによりプレイがスピードアップしますが、プレイ内のどのタスクにもホストに関する事実が必要ないことを確認してください。
劇中の最初のタスクはelk_version
を検証します変数。この変数は、アップグレードするElasticStackのバージョンを表します。これは、ansible-playbookコマンドを呼び出すときに渡されます。変数が渡されないか、有効な形式でない場合、プレイはすぐに終了します。そのタスクは、実際にはすべての演劇の最初のタスクになります。その理由は、必要に応じて、または必要に応じて、プレイを分離して実行できるようにするためです。
2番目のタスクはrpm
を使用しますLogstashの現在のバージョンを取得し、変数version_found
に登録するコマンド。その情報は次のタスクで使用されます。行args:
、warn: no
およびchanged_when: False
ansible-lintを幸せにするためにありますが、厳密には必要ありません。
最後のタスクは、実際にパッケージを事前にダウンロードするコマンドを実行します。ただし、インストールされているLogstashのバージョンがターゲットバージョンよりも古い場合に限ります。使用しない場合は、ダウンロードおよび古いバージョンまたは同じバージョンをポイントしないでください。
Logstashの代わりにElasticsearchとKibanaを事前にダウンロードすることを除いて、他の2つのプレイは基本的に同じです。
- hosts: elasticsearch gather_facts: no tasks: - name: Validate elasticsearch Version fail: msg='Invalid ELK Version' when: elk_version is undefined or not elk_version is match('d+.d+.d+') - name: Get elasticsearch current version command: rpm -q elasticsearch --qf %{VERSION} args: warn: no changed_when: False register: version_found - name: Pre-download elasticsearch install package yum: name: elasticsearch-{{ elk_version }} download_only: yes when: version_found.stdout is version_compare(elk_version, '<') - hosts: kibana gather_facts: no tasks: - name: Validate kibana Version fail: msg='Invalid ELK Version' when: elk_version is undefined or not elk_version is match('d+.d+.d+') - name: Get kibana current version command: rpm -q kibana --qf %{VERSION} args: warn: no changed_when: False register: version_found - name: Pre-download kibana install package yum: name: kibana-{{ elk_version }} download_only: yes when: version_found.stdout is version_compare(elk_version, '<')
Logstashは、アップグレードする最初のコンポーネントである必要があります。これは、Logstashが古いバージョンのElasticsearchで動作することが保証されているためです。
プレイの最初のタスクは、ダウンロード前のタスクと同じです。
- name: Upgrade logstash hosts: logstash gather_facts: no tasks: - name: Validate ELK Version fail: msg='Invalid ELK Version' when: elk_version is undefined or not elk_version is match('d+.d+.d+') - name: Get logstash current version command: rpm -q logstash --qf %{VERSION} changed_when: False register: version_found
最後の2つのタスクは、ブロックに含まれています。
- block: - name: Update logstash yum: name: logstash-{{ elk_version }} state: present - name: Restart logstash systemd: name: logstash state: restarted enabled: yes daemon_reload: yes when: version_found.stdout is version_compare(elk_version, '<')
条件付きwhen
ブロック内のタスクが、ターゲットバージョンが現在のバージョンよりも新しい場合にのみ実行されることを保証します。ブロック内の最初のタスクはLogstashアップグレードを実行し、2番目のタスクはサービスを再起動します。
Elasticsearchクラスターにダウンタイムが発生しないようにするには、ローリングアップグレードを実行する必要があります。これは、一度に1つのノードをアップグレードし、クラスターが緑色の状態(完全に正常)であることを確認した後でのみ、任意のノードのアップグレードを開始することを意味します。
プレイの開始から、あなたは何か違うことに気付くでしょう:
- name: Elasticsearch rolling upgrade hosts: elasticsearch gather_facts: no serial: 1
ここにserial: 1
という行があります。 Ansibleのデフォルトの動作は、構成で定義された同時ホストの数である複数のホストに対して並行して再生を実行することです。この行により、プレイは一度に1つのホストに対してのみ実行されます。
次に、プレイに沿って使用するいくつかの変数を定義します。
vars: es_disable_allocation: '{'transient':{'cluster.routing.allocation.enable':'none'}}' es_enable_allocation: '{'transient':{'cluster.routing.allocation.enable': 'all','cluster.routing.allocation.node_concurrent_recoveries': 5,'indices.recovery.max_bytes_per_sec': '500mb'}}' es_http_port: 9200 es_transport_port: 9300
各変数の意味は、劇中に登場するときに明らかになります。
いつものように、最初のタスクはターゲットバージョンを検証することです。
tasks: - name: Validate ELK Version fail: msg='Invalid ELK Version' when: elk_version is undefined or not elk_version is match('d+.d+.d+')
以下のタスクの多くは、Elasticsearchクラスターに対してREST呼び出しを実行することで構成されます。呼び出しは、任意のノードに対して実行できます。プレイ中の現在のホストに対して単純に実行できますが、一部のコマンドは、Elasticsearchサービスが現在のホストに対してダウンしている間に実行されます。したがって、次のタスクでは、REST呼び出しを実行する別のホストを選択するようにしてください。このために、Set_factモジュールとAnsibleインベントリのgroups変数を使用します。
- name: Set the es_host for the first host set_fact: es_host: '{{ groups.elasticsearch[1] }}' when: 'inventory_hostname == groups.elasticsearch[0]' - name: Set the es_host for the remaining hosts set_fact: es_host: '{{ groups.elasticsearch[0] }}' when: 'inventory_hostname != groups.elasticsearch[0]'
次に、続行する前に、サービスが現在のノードで稼働していることを確認します。
- name: Ensure elasticsearch service is running systemd: name: elasticsearch enabled: yes state: started register: response - name: Wait for elasticsearch node to come back up if it was stopped wait_for: port: '{{ es_transport_port }}' delay: 45 when: response.changed == true
前作同様、現在のバージョンを確認します。今回を除いて、rpmを実行する代わりにElasticsearch RESTAPIを使用します。 rpmコマンドを使用することもできますが、この代替手段を示したいと思います。
- name: Check current version uri: url: http://localhost:{{ es_http_port }} method: GET register: version_found retries: 10 delay: 10
残りのタスクは、現在のバージョンがターゲットバージョンよりも古い場合にのみ実行されるブロック内にあります。
- block: - name: Enable shard allocation for the cluster uri: url: http://localhost:{{ es_http_port }}/_cluster/settings method: PUT body_format: json body: '{{ es_enable_allocation }}'
さて、私のアドバイスに従ってドキュメントを読むと、この手順は反対の手順である必要があることに気付くでしょう。シャードの割り当てを無効にすることです。何らかの理由でシャードが以前に無効にされた場合に備えて、このタスクを最初にここに置くのが好きです。次のタスクはクラスターが緑色になるのを待つため、これは重要です。シャードの割り当てが無効になっている場合、クラスターは黄色のままになり、タイムアウトするまでタスクがハングします。
したがって、シャード割り当てが有効になっていることを確認した後、クラスターが緑色の状態にあることを確認します。
- name: Wait for cluster health to return to green uri: url: http://localhost:{{ es_http_port }}/_cluster/health method: GET register: response until: 'response.json.status == 'green'' retries: 500 delay: 15
ノードサービスの再起動後、クラスターが緑色に戻るまでに長い時間がかかる場合があります。それが行の理由ですretries: 500
およびdelay: 15
。これは、クラスターが緑色に戻るまで125分(500 x 15秒)待機することを意味します。ノードが非常に大量のデータを保持している場合は、それを調整する必要があるかもしれません。ほとんどの場合、それで十分です。
ユニットテストについて正しいのは次のうちどれですか?
これで、シャードの割り当てを無効にできます。
- name: Disable shard allocation for the cluster uri: url: http://localhost:{{ es_http_port }}/_cluster/settings method: PUT body_format: json body: {{ es_disable_allocation }}
また、サービスをシャットダウンする前に、オプションでありながら推奨される同期フラッシュを実行します。同期フラッシュを実行すると、一部のインデックスで409エラーが発生することは珍しくありません。これは無視しても安全なので、成功ステータスコードのリストに409を追加しました。
- name: Perform a synced flush uri: url: http://localhost:{{ es_http_port }}/_flush/synced method: POST status_code: '200, 409'
これで、このノードをアップグレードする準備が整いました。
- name: Shutdown elasticsearch node systemd: name: elasticsearch state: stopped - name: Update elasticsearch yum: name: elasticsearch-{{ elk_version }} state: present
サービスが停止した状態で、すべてのシャードが割り当てられるのを待ってから、ノードを再開します。
- name: Wait for all shards to be reallocated uri: url=http://{{ es_host }}:{{ es_http_port }}/_cluster/health method=GET register: response until: 'response.json.relocating_shards == 0' retries: 20 delay: 15
シャードが再割り当てされたら、Elasticsearchサービスを再起動し、完全に準備が整うのを待ちます。
- name: Start elasticsearch systemd: name: elasticsearch state: restarted enabled: yes daemon_reload: yes - name: Wait for elasticsearch node to come back up wait_for: port: '{{ es_transport_port }}' delay: 35 - name: Wait for elasticsearch http to come back up wait_for: port: '{{ es_http_port }}' delay: 5
ここで、シャードの割り当てを再度有効にする前に、クラスターが黄色または緑色であることを確認します。
- name: Wait for cluster health to return to yellow or green uri: url: http://localhost:{{ es_http_port }}/_cluster/health method: GET register: response until: 'response.json.status == 'yellow' or response.json.status == 'green'' retries: 500 delay: 15 - name: Enable shard allocation for the cluster uri: url: http://localhost:{{ es_http_port }}/_cluster/settings method: PUT body_format: json body: '{{ es_enable_allocation }}' register: response until: 'response.json.acknowledged == true' retries: 10 delay: 15
そして、ノードが完全に回復するのを待ってから、次のノードを処理します。
- name: Wait for the node to recover uri: url: http://localhost:{{ es_http_port }}/_cat/health method: GET return_content: yes register: response until: ''green' in response.content' retries: 500 delay: 15
もちろん、前に言ったように、このブロックは、実際にバージョンをアップグレードする場合にのみ実行する必要があります。
when: version_found.json.version.number is version_compare(elk_version, '<')
アップグレードされる最後のコンポーネントはKibanaです。
ご想像のとおり、最初のタスクはLogstashのアップグレードやダウンロード前の再生と同じです。 1つの変数の定義を除いて:
- name: Upgrade kibana hosts: kibana gather_facts: no vars: set_default_index: '{'changes':{'defaultIndex':'syslog'}}' tasks: - name: Validate ELK Version fail: msg='Invalid ELK Version' when: elk_version is undefined or not elk_version is match('d+.d+.d+') - name: Get kibana current version command: rpm -q kibana --qf %{VERSION} args: warn: no changed_when: False register: version_found
set_default_index
について説明しますそれを使用するタスクに到達すると変数。
残りのタスクは、インストールされているKibanaのバージョンがターゲットバージョンよりも古い場合にのみ実行されるブロック内にあります。最初の2つのタスクは、Kibanaを更新して再起動します。
- name: Update kibana yum: name: kibana-{{ elk_version }} state: present - name: Restart kibana systemd: name: kibana state: restarted enabled: yes daemon_reload: yes
そして、Kibanaにとってはそれで十分だったはずです。残念ながら、何らかの理由で、アップグレード後、Kibanaはデフォルトのインデックスパターンへの参照を失います。これにより、アップグレード後にアクセスする最初のユーザーにデフォルトのインデックスパターンを定義するように要求するため、混乱が生じる可能性があります。これを回避するには、デフォルトのインデックスパターンをリセットするタスクを必ず含めてください。以下の例ではsyslog
ですが、使用しているものに変更する必要があります。ただし、インデックスを設定する前に、Kibanaが稼働していて、リクエストを処理する準備ができていることを確認する必要があります。
- name: Wait for kibana to start listening wait_for: port: 5601 delay: 5 - name: Wait for kibana to be ready uri: url: http://localhost:5601/api/kibana/settings method: GET register: response until: ''kbn_name' in response and response.status == 200' retries: 30 delay: 5 - name: Set Default Index uri: url: http://localhost:5601/api/kibana/settings method: POST body_format: json body: '{{ set_default_index }}' headers: 'kbn-version': '{{ elk_version }}'
Elastic Stackは貴重なツールであり、まだ使用していない場合はぜひご覧になることをお勧めします。それはそれなりに素晴らしく、絶えず改善されているので、絶えずアップグレードされていることに追いつくのは難しいかもしれません。それらのAnsiblePlaybookが、私と同じようにあなたにも役立つことを願っています。
最高の静的サイトジェネレーター2018
GitHubで利用できるようにしました https://github.com/orgito/elk-upgrade 。非実稼働環境でテストすることをお勧めします。
Elasticsearchをアプリに組み込むことを検討しているRubyon Rails開発者の場合は、チェックアウトしてください Ruby on RailsのElasticsearch:ChewyGemのチュートリアル CoreApeeScapeソフトウェアエンジニアのArkadiyZabazhanovによる。
Elastic Stackは、オープンソース企業Elasticの製品セットです。スタックの主なコンポーネントは、Logstash、Kibana、Elasticsearchです。これらを組み合わせることで、大量のデータをリアルタイムで収集、解析、視覚化、分析するための完全で強力なソリューションが提供されます。
Elasticsearchは、Elasticの主力製品であり、ElasticStackのコアです。これは、データを保存し、ほぼ瞬時の検索結果を提供する強力な検索および分析エンジンです。
KibanaはElasticStackのフロントエンドです。これは、Elasticsearchの強力な検索機能に簡単にアクセスでき、美しく便利なダッシュボードを作成できるデータ視覚化Webアプリです。
Ansibleは、プロビジョニング、自動化管理、展開、およびほとんどすべての複雑で反復的なITタスクに使用されるIT自動化ツールです。エージェントレスであり、管理するノードにSSHアクセスとPythonのみが存在する必要があります。