Ubuntu 18.04にApache ZooKeeperクラスターをインストールおよび構成する方法

著者は、Write for DOnationsプログラムの一部として寄付を受け取るためにWikimedia Foundation Inc.を選択しました。

前書き

Apache ZooKeeperは、復元力と信頼性の高い分散調整を可能にするオープンソースソフトウェアです。 分散システムで一般的に使用され、構成情報、ネームサービス、分散同期、クォーラム、および状態を管理します。 さらに、分散システムは、コンセンサス、リーダー選挙、およびグループ管理を実装するためにZooKeeperに依存しています。

このガイドでは、Ubuntu 18.04にApache ZooKeeper 3.4.13をインストールして構成します。 復元力と高可用性を実現するために、ZooKeeperは、アンサンブルと呼ばれる一連のホストに複製されることを目的としています。 最初に、単一ノードのZooKeeperサーバーのスタンドアロンインストールを作成し、マルチノードクラスターをセットアップするための詳細を追加します。 スタンドアロンインストールは開発環境とテスト環境で役立ちますが、クラスターは実稼働環境で最も実用的なソリューションです。

前提条件

このインストールおよび構成ガイドを開始する前に、次のものが必要です。

  • スタンドアロンインストールには、sudo権限を持つ非rootユーザーとファイアウォールを含め、the Ubuntu 18.04 initial server setup guideに従って設定された最低4GBのRAMを備えた1台のUbuntu18.04サーバーが必要です。 マルチノードクラスタには、同じ手順に従ってセットアップされた2つの追加サーバーが必要です。

  • ZooKeeperの実行にはJavaが必要であるため、サーバーにOpenJDK 8がインストールされています。 これを行うには、How To Install Java with apt on Ubuntu 18.04ガイドの「OpenJDKの特定のバージョンをインストールする」手順に従います。

ZooKeeperはデータをメモリに保持して高スループットと低レイテンシを実現するため、実稼働システムは8GBのRAMで最適に動作します。 RAMの量が少ないと、JVMスワッピングが発生し、ZooKeeperサーバーの待ち時間が発生する可能性があります。 ZooKeeperサーバーの遅延が大きいと、クライアントセッションのタイムアウトなどの問題が発生し、システムの機能に悪影響を及ぼす可能性があります。

[[step-1 -—- creating-a-user-for-zookeeper]] ==ステップ1—ZooKeeperのユーザーを作成する

専用ユーザーは、ネットワーク経由でリクエストを処理し、リソースを消費するサービスを実行する必要があります。 このプラクティスにより、環境のセキュリティと管理性を向上させる分離と制御が作成されます。 このステップでは、このチュートリアルでzkという名前の非root sudoユーザーを作成して、ZooKeeperサービスを実行します。

最初に、前提条件で作成した非ルートsudoユーザーとしてログインします。

ssh sammy@your_server_ip

ZooKeeperサービスを実行するユーザーを作成します。

sudo useradd zk -m

-mフラグをuseraddコマンドに渡すと、このユーザーのホームディレクトリが作成されます。 zkのホームディレクトリは、デフォルトでは/home/zkになります。

zkユーザーのデフォルトシェルとしてbashを設定します。

sudo usermod --shell /bin/bash zk

このユーザーのパスワードを設定します。

sudo passwd zk

次に、zkユーザーをsudoグループに追加して、特権モードでコマンドを実行できるようにします。

usermod -aG sudo zk

セキュリティの観点から、できる限り少ないユーザーにSSHアクセスを許可することをお勧めします。 sammyとしてリモートでログインし、suを使用して目的のユーザーに切り替えると、システムにアクセスするための資格情報と実行中のプロセスの資格情報が一定レベル分離されます。 この手順では、zkユーザーとrootユーザーの両方のSSHアクセスを無効にします。

sshd_configファイルを開きます。

sudo nano /etc/ssh/sshd_config

PermitRootLogin行を見つけ、値をnoに設定して、rootユーザーのSSHアクセスを無効にします。

/etc/ssh/sshd_config

PermitRootLogin no

PermitRootLogin値の下に、DenyUsers行を追加し、SSHアクセスを無効にする必要があるユーザーとして値を設定します。

/etc/ssh/sshd_config

DenyUsers zk

ファイルを保存して終了し、SSHデーモンを再起動して変更を有効にします。

sudo systemctl restart sshd

zkユーザーに切り替えます。

su -l zk

-lフラグは、ユーザーを切り替えた後にログインシェルを呼び出します。 ログインシェルは環境変数をリセットし、ユーザーにクリーンスタートを提供します。

プロンプトでパスワードを入力して、ユーザーを認証します。

zkユーザーとして作成、構成、およびログインしたので、ZooKeeperデータを格納するためのディレクトリーを作成します。

[[step-2 -—- creating-a-data-directory-for-zookeeper]] ==ステップ2—ZooKeeperのデータディレクトリを作成する

ZooKeeperは、すべての構成および状態データをディスクに保持するため、再起動後も存続できます。 この手順では、ZooKeeperがデータの読み取りと書き込みに使用するデータディレクトリを作成します。 ローカルファイルシステムまたはリモートストレージドライブにデータディレクトリを作成できます。 このチュートリアルでは、ローカルファイルシステムにデータディレクトリを作成することに焦点を当てます。

ZooKeeperが使用するディレクトリを作成します。

sudo mkdir -p /data/zookeeper

zkのユーザー所有権をディレクトリに付与します。

sudo chown zk:zk /data/zookeeper

chownは、/data/zookeeperディレクトリの所有権とグループを変更して、グループzkに属するユーザーzkがデータディレクトリを所有するようにします。

データディレクトリの作成と設定が正常に完了しました。 ZooKeeperの構成に移るとき、ZooKeeperがファイルの保存に使用するデータディレクトリとしてこのパスを指定します。

[[step-3 -—- download-and-extracting-the-zookeeper-binaries]] ==ステップ3—ZooKeeperバイナリのダウンロードと抽出

このステップでは、ZooKeeperバイナリを手動でダウンロードして/optディレクトリに抽出します。 Advanced Packaging Toolaptを使用してZooKeeperをダウンロードできますが、機能が異なる古いバージョンがインストールされる場合があります。 ZooKeeperを手動でインストールすると、使用するバージョンを完全に制御できます。

これらのファイルを手動でダウンロードしているので、/optディレクトリに移動することから始めます。

cd /opt

ローカルマシンから、Apache download pageに移動します。 このページは、最速のダウンロードのために、あなたに最も近いミラーを自動的に提供します。 提案されたミラーサイトへのリンクをクリックし、下にスクロールしてzookeeper/をクリックし、利用可能なリリースを表示します。 インストールするZooKeeperのバージョンを選択します。 このチュートリアルでは、3.4.13の使用に焦点を当てます。 バージョンを選択したら、.tar.gzで終わるバイナリファイルを右クリックして、リンクアドレスをコピーします。

サーバーから、コピーされたリンクとともにwgetコマンドを使用して、ZooKeeperバイナリをダウンロードします。

sudo wget http://apache.osuosl.org/zookeeper/zookeeper-3.4.13/zookeeper-3.4.13.tar.gz

圧縮アーカイブからバイナリを抽出します。

sudo tar -xvf zookeeper-3.4.13.tar.gz

.tar.gz拡張子は、TARパッケージとそれに続くGNU zip(gzip)圧縮の組み合わせを表します。 アーカイブを抽出するコマンドにフラグ-xvfを渡したことがわかります。 フラグxは抽出を表し、vは詳細モードで抽出の進行状況を表示し、fは入力(この場合はzookeeper-3.4.13.tar.gz)をSTDINではなく指定できるようにします。

次に、実行可能ファイルを実行できるように、抽出されたバイナリのzkユーザー所有権を付与します。 次のように所有権を変更できます。

sudo chown zk:zk -R  zookeeper-3.4.13

次に、シンボリックリンクを構成して、ZooKeeperディレクトリが更新後も関連性を保つようにします。 シンボリックリンクを使用してディレクトリ名を短縮することもできます。これにより、構成ファイルのセットアップにかかる時間を短縮できます。

lnコマンドを使用してシンボリックリンクを作成します。

sudo ln -s zookeeper-3.4.13 zookeeper

そのリンクの所有権をzk:zkに変更します。 リンク自体の所有権を変更するために-hフラグを渡したことに注意してください。 -hを指定しないと、前の手順で明示的に行ったリンクのターゲットの所有権が変更されます。

sudo chown -h zk:zk zookeeper

シンボリックリンクが作成されると、構成内のディレクトリパスは関連性を維持し、将来のアップグレードを通じて変更されません。 ZooKeeperを構成できるようになりました。

[[step-4 -—- configuring-zookeeper]] ==ステップ4—ZooKeeperの構成

環境を設定したら、ZooKeeperを設定する準備ができました。

構成ファイルは/opt/zookeeper/confディレクトリにあります。 このディレクトリには、ZooKeeperディストリビューションに付属のサンプル構成ファイルが含まれています。 zoo_sample.cfgという名前のこのサンプルファイルには、最も一般的な構成パラメーター定義とこれらのパラメーターのサンプル値が含まれています。 一般的なパラメータの一部は次のとおりです。

  • tickTime:ティックの長さをミリ秒単位で設定します。 ティックは、ZooKeeperがハートビート間の長さを測定するために使用する時間単位です。 最小セッションタイムアウトはtickTimeの2倍です。

  • dataDir:インメモリデータベースのスナップショットと更新のトランザクションログを保存するために使用されるディレクトリを指定します。 トランザクションログ用に別のディレクトリを指定することもできます。

  • clientPort:クライアント接続をリッスンするために使用されるポート。

  • maxClientCnxns:クライアント接続の最大数を制限します。

/opt/zookeeper/confzoo.cfgという名前の構成ファイルを作成します。 nanoまたはお気に入りのエディターを使用してファイルを作成して開くことができます。

nano /opt/zookeeper/conf/zoo.cfg

そのファイルに次のプロパティと値のセットを追加します。

/opt/zookeeper/conf/zoo.cfg

tickTime=2000
dataDir=/data/zookeeper
clientPort=2181
maxClientCnxns=60

2000ミリ秒のtickTimeは、ハートビート間の推奨間隔です。 間隔を短くすると、システムのオーバーヘッドにつながり、メリットが制限される可能性があります。 dataDirパラメータは、前のセクションで作成したシンボリックリンクによって定義されたパスを指します。 従来、ZooKeeperはポート2181を使用してクライアント接続をリッスンしていました。 ほとんどの場合、60の許可されたクライアント接続で開発とテストに十分です。

ファイルを保存し、エディターを終了します。

ZooKeeperを構成し、サーバーを起動する準備ができました。

[[step-5 -—- starting-zookeeper-and-testing-the-standalone-installation]] ==ステップ5—ZooKeeperを起動してスタンドアロンインストールをテストする

ZooKeeperの実行に必要なすべてのコンポーネントを構成しました。 この手順では、ZooKeeperサービスを開始し、サービスにローカルに接続して構成をテストします。

/opt/zookeeperディレクトリに戻ります。

cd /opt/zookeeper

zkServer.shコマンドでZooKeeperを起動します。

bin/zkServer.sh start

標準出力に以下が表示されます。

OutputZooKeeper JMX enabled by default
Using config: /opt/zookeeper/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED

次のコマンドを使用して、ローカルのZooKeeperサーバーに接続します。

bin/zkCli.sh -server 127.0.0.1:2181

ラベルCONNECTEDのプロンプトが表示されます。 これにより、ローカルのスタンドアロンZooKeeperが正常にインストールされたことを確認できます。 エラーが発生した場合は、構成が正しいことを確認する必要があります。

OutputConnecting to 127.0.0.1:2181
...
...
[zk: 127.0.0.1:2181(CONNECTED) 0]

このプロンプトでhelpと入力して、クライアントから実行できるコマンドのリストを取得します。 出力は次のようになります。

Output[zk: 127.0.0.1:2181(CONNECTED) 0] help
ZooKeeper -server host:port cmd args
    stat path [watch]
    set path data [version]
    ls path [watch]
    delquota [-n|-b] path
    ls2 path [watch]
    setAcl path acl
    setquota -n|-b val path
    history
    redo cmdno
    printwatches on|off
    delete path [version]
    sync path
    listquota path
    rmr path
    get path [watch]
    create [-s] [-e] path data acl
    addauth scheme auth
    quit
    getAcl path
    close
    connect host:port

いくつかのテストを行った後、プロンプトでquitと入力して、クライアントセッションを閉じます。 クライアントセッションを閉じた後、ZooKeeperサービスは引き続き実行されます。 次の手順でsystemdサービスとして構成するため、ZooKeeperサービスをシャットダウンします。

bin/zkServer.sh stop

これで、スタンドアロンのZooKeeperサービスをインストール、構成、およびテストできました。 この設定は、ZooKeeperに慣れるのに役立ちますが、開発環境およびテスト環境にも役立ちます。 構成が機能することがわかったので、systemdを構成して、ZooKeeperサービスの管理を簡素化します。

[[step-6 -—- systemd-unit-fileの作成と使用]] ==ステップ6—systemdユニットファイルの作成と使用

systemd、システムおよびサービスマネージャーは、ユーザースペースをブートストラップし、ブート後にシステムプロセスを管理するために使用されるinitシステムです。 systemdを使用して、ZooKeeperのステータスを開始および確認するためのデーモンを作成できます。

Systemd Essentialsは、systemdとその構成要素についてさらに学ぶための優れた入門リソースです。

エディタを使用して、/etc/systemd/system/zk.serviceという名前の.serviceファイルを作成します。

sudo nano /etc/systemd/system/zk.service

ファイルに次の行を追加して、ZooKeeperサービスを定義します。

/etc/systemd/system/zk.service

[Unit]
Description=Zookeeper Daemon
Documentation=http://zookeeper.apache.org
Requires=network.target
After=network.target

[Service]
Type=forking
WorkingDirectory=/opt/zookeeper
User=zk
Group=zk
ExecStart=/opt/zookeeper/bin/zkServer.sh start /opt/zookeeper/conf/zoo.cfg
ExecStop=/opt/zookeeper/bin/zkServer.sh stop /opt/zookeeper/conf/zoo.cfg
ExecReload=/opt/zookeeper/bin/zkServer.sh restart /opt/zookeeper/conf/zoo.cfg
TimeoutSec=30
Restart=on-failure

[Install]
WantedBy=default.target

ユニットファイル構成のServiceセクションは、作業ディレクトリ、サービスを実行するユーザー、およびZooKeeperサービスを開始、停止、および再起動するための実行可能コマンドを指定します。 すべてのユニットファイル構成オプションの詳細については、Understanding Systemd Units and Unit Filesの記事を参照してください。

ファイルを保存し、エディターを終了します。

systemd構成が整ったので、次のサービスを開始できます。

sudo systemctl start zk

systemdファイルでサービスを正常に開始できることを確認したら、起動時にサービスを開始できるようにします。

sudo systemctl enable zk

この出力は、シンボリックリンクの作成を確認します。

OutputCreated symlink /etc/systemd/system/multi-user.target.wants/zk.service → /etc/systemd/system/zk.service.

次を使用して、ZooKeeperサービスのステータスを確認します。

sudo systemctl status zk

systemctlを使用してZooKeeperサービスを停止します。

sudo systemctl stop zk

最後に、デーモンを再起動するには、次のコマンドを使用します。

sudo systemctl restart zk

systemdメカニズムは、多くのLinuxディストリビューションで選択されるinitシステムになりつつあります。 ZooKeeperを管理するようにsystemdを構成したので、この高速で柔軟なinitモデルを利用して、ZooKeeperサービスを開始、停止、および再起動できます。

[[step-7 -—- configuring-a-multi-node-zookeeper-cluster]] ==ステップ7—マルチノードZooKeeperクラスターの構成

スタンドアロンZooKeeperサーバーは開発とテストに役立ちますが、すべての実稼働環境には複製されたマルチノードクラスターが必要です。

アプリケーションとして連携するZooKeeperクラスター内のノードは、quorumを形成します。 クォーラムとは、トランザクションをコミットする前に合意する必要があるノードの最小数を指します。 クォーラムには、過半数を確立できるように奇数のノードが必要です。 ノードの数が偶数の場合、同点になる可能性があります。これは、ノードが過半数またはコンセンサスに達しないことを意味します。

実稼働環境では、各ZooKeeperノードを個別のホストで実行する必要があります。 これにより、ホストのハードウェア障害または再起動によるサービスの中断を防ぎます。 これは、復元力があり、可用性の高い分散システムを構築するための重要で必要なアーキテクチャ上の考慮事項です。

このチュートリアルでは、クォーラムに3つのノードをインストールして構成し、マルチノードセットアップを示します。 3ノードクラスターを構成する前に、スタンドアロンZooKeeperインストールと同じ構成で2つの追加サーバーをスピンアップします。 2つの追加ノードが前提条件を満たしていることを確認してから、手順1〜6を実行して、実行中のZooKeeperインスタンスをセットアップします。

新しいノードの手順1〜6を実行したら、各ノードのエディターでzoo.cfgを開きます。

sudo nano /opt/zookeeper/conf/zoo.cfg

クォーラムのすべてのノードには、同じ構成ファイルが必要です。 3つのノードのそれぞれのzoo.cfgファイルで、ファイルの最後に、クォーラム内のinitLimitsyncLimit、およびサーバーの追加の構成パラメーターと値を追加します。

/opt/zookeeper/conf/zoo.cfg

tickTime=2000
dataDir=/data/zookeeper
clientPort=2181
maxClientCnxns=60
initLimit=10
syncLimit=5
server.1=your_zookeeper_node_1:2888:3888
server.2=your_zookeeper_node_2:2888:3888
server.3=your_zookeeper_node_3:2888:3888

initLimitは、最初の同期フェーズにかかる時間を指定します。 これは、クォーラム内の各ノードがリーダーに接続する必要がある時間です。 syncLimitは、要求を送信してから確認応答を受信するまでに経過できる時間を指定します。 これは、ノードがリーダーから同期できなくなる最大時間です。 ZooKeeperノードは、フォロワーノードがリーダーノードに接続するため、およびリーダーの選出のために、それぞれポートのペア:2888:3888を使用します。

各ノードでファイルを更新したら、エディターを保存して終了します。

マルチノード構成を完了するには、各サーバーでノードIDを指定します。 これを行うには、各ノードにmyidファイルを作成します。 各ファイルには、構成ファイルで割り当てられたサーバー番号に相関する番号が含まれます。

your_zookeeper_node_1で、ノードIDを指定するmyidファイルを作成します。

sudo nano /data/zookeeper/myid

your_zookeeper_node_1server.1として識別されるため、1と入力してノードIDを定義します。 値を追加すると、ファイルは次のようになります。

your_zookeeper_node_1 /data/zookeeper/myid1

残りのノードについても同じ手順に従います。 各ノードのmyidファイルは次のようになります。

your_zookeeper_node_1 /data/zookeeper/myid1
your_zookeeper_node_2 /data/zookeeper/myid2
your_zookeeper_node_3 /data/zookeeper/myid3

これで、3ノードのZooKeeperクラスターが構成されました。 次に、クラスターを実行し、インストールをテストします。

[[step-8 -—- running-and-testing-the-multi-node-installation]] ==ステップ8—マルチノードインストールの実行とテスト

各ノードがクラスターとして機能するように構成されたら、クォーラムを開始する準備が整います。 この手順では、各ノードでクォーラムを開始し、ZooKeeperでサンプルデータを作成してクラスターをテストします。

クォーラムノードを開始するには、最初に各ノードの/opt/zookeeperディレクトリに移動します。

cd /opt/zookeeper

次のコマンドで各ノードを起動します。

java -cp zookeeper-3.4.13.jar:lib/log4j-1.2.17.jar:lib/slf4j-log4j12-1.7.25.jar:lib/slf4j-api-1.7.25.jar:conf org.apache.zookeeper.server.quorum.QuorumPeerMain conf/zoo.cfg

ノードが起動すると、接続エラーが断続的に表示され、その後、クォーラムに参加してリーダーを選出する段階が続きます。 数秒の初期化の後、インストールのテストを開始できます。

前提条件で構成した非rootユーザーとしてSSH経由でyour_zookeeper_node_3にログインします。

ssh sammy@your_zookeeper_node_3

ログインしたら、zkユーザーに切り替えます。

your_zookeeper_node_3 /data/zookeeper/myidsu -l zk

zkユーザーのパスワードを入力します。 ログインしたら、ディレクトリを/opt/zookeeperに変更します。

your_zookeeper_node_3 /data/zookeeper/myidcd /opt/zookeeper

ここで、ZooKeeperコマンドラインクライアントを起動し、your_zookeeper_node_1でZooKeeperに接続します。

your_zookeeper_node_3 /data/zookeeper/myidbin/zkCli.sh -server your_zookeeper_node_1:2181

スタンドアロンインストールでは、クライアントとサーバーの両方が同じホストで実行されていました。 これにより、localhostを使用してZooKeeperサーバーとのクライアント接続を確立できました。 クライアントとサーバーはマルチノードクラスター内の異なるノードで実行されているため、前の手順では、それに接続するためにyour_zookeeper_node_1のIPアドレスを指定する必要がありました。

手順5で見たのと同様に、CONNECTEDラベルが付いたおなじみのプロンプトが表示されます。

次に、znodeを作成、一覧表示、削除します。 znodeは、ZooKeeperの基本的な抽象概念であり、ファイルシステム上のファイルおよびディレクトリに類似しています。 ZooKeeperはそのデータを階層的な名前空間で管理し、znodeはこの名前空間のデータレジスタです。

znodeを正常に作成、一覧表示、および削除できることをテストすることは、ZooKeeperクラスターが正しくインストールおよび構成されていることを確認するために不可欠です。

zk_znode_1という名前のznodeを作成し、文字列sample_dataをそれに関連付けます。

create /zk_znode_1 sample_data

作成すると、次の出力が表示されます。

OutputCreated /zk_znode_1

新しく作成されたznodeをリストします。

ls /

関連するデータを取得します。

get /zk_znode_1

ZooKeeperは次のように応答します。

Output[zk: your_zookeeper_node_1:2181(CONNECTED)] ls /
[zk_znode_1, zookeeper]
[zk: your_zookeeper_node_1:2181(CONNECTED)] get /zk_znode_1
sample_data
cZxid = 0x100000002
ctime = Tue Nov 06 19:47:41 UTC 2018
mZxid = 0x100000002
mtime = Tue Nov 06 19:47:41 UTC 2018
pZxid = 0x100000002
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 11
numChildren = 0

出力は、zk_node_1に関連付けた値sample_dataを確認します。 ZooKeeperは、作成時間ctimeおよび変更時間mtimeに関する追加情報も提供します。 ZooKeeperはバージョン管理されたデータストアであるため、データバージョンに関するメタデータも表示されます。

zk_znode_1znodeを削除します。

delete /zk_znode_1

この手順では、2つのZooKeeperノード間の接続を正常にテストしました。 また、znodeを作成、一覧表示、および削除することにより、基本的なznode管理を学びました。 マルチノード設定が完了し、ZooKeeperの使用を開始する準備が整いました。

結論

このチュートリアルでは、スタンドアロン環境とマルチノードZooKeeper環境の両方を構成およびテストしました。 マルチノードのZooKeeperデプロイメントを使用する準備ができたので、追加情報とプロジェクトについてofficial ZooKeeper documentationを確認できます。