午前2時の緊急呼び出し:Kubernetesはそれほどストレスをかける価値があるのか?
火曜日の午前2時、PagerDutyのアラートが鳴り響きました。大手Kubernetesプロバイダーで管理していた私たちのマイクロサービスクラスターが限界に達したのです。etcdのステートは遅延し、イングレスコントローラーは504エラーを吐き出し、私は単なるNginxポッドが起動しない理由を突き止めるために400行ものYAMLに埋もれていました。カフェインに頼りながらその時、私は確信しました。実際には一度も使っていない機能のために、あまりにも高い代償を払っている、と。
Kubernetesは大規模なスケーリングには強力なツールです。しかし、多くのチームにとって、それはまるでピザを買いに行くのにセミトレーラーを運転しているようなものです。それが、私がワークロードをHashiCorp Nomadへ移行し始めた理由です。
K8sとは異なり、Nomadはわずか75MBの単一バイナリとして提供されます。コンテナ、ローカルバイナリ、JavaのJARファイルを同様に簡単に処理できます. トラフィックを流すために、クラウドネイティブなネットワーキングの専門学位は必要ありません。K8sコントロールプレーンの維持管理に疲れ果てているなら、Nomadこそがあなたが探し求めていた軽量な選択肢です。
なぜNomadが中規模インフラに適しているのか
Nomadは、「一つのことを、うまくやる」という古典的なUnix哲学に従っています。スケジューリングに厳格に焦点を当てており、データベース、サービスメッシュ、クラウドプロバイダーのすべてを一度に担おうとはしません。一般的なKubernetesノードがアイドル状態を維持するだけで2GBのRAMを消費するのに対し、Nomadクライアントは100MB未満で動作することも珍しくありません。
クラスターを立ち上げる前に、私はいつもネットワークアーキテクチャを計画します。NomadクライアントのCIDRブロックを定義する際には、通常このサブネット計算機を使用します。これはブラウザ上でローカルに動作するため、非常に便利なツールです。つまり、プライベートネットワークのトポロジーがリモートサーバーに送信されることがなく、インフラの詳細を秘密に保つことができます。
インストール:5分足らずでゼロからクラスター構築へ
NomadはGo言語で書かれているため、デプロイは驚くほど高速です。バイナリをダウンロードしてすぐに実行できます。ただし、本番環境では公式のHashiCorpリポジトリを使用するのが賢明です。Ubuntuでのセットアップ方法は以下の通りです。
# HashiCorpのGPGキーを追加
wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
# リポジトリを追加
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
# Nomadをインストール
sudo apt update && sudo apt install nomad
正しくインストールされたか確認します:
nomad version
サーバーとクライアントの設定
Nomadは2つのモードで動作します。サーバーはスケジューリングの意思決定を行い、クライアントは実際にタスクを実行する実働部隊です。テスト用には1つのt3.microインスタンスで両方を実行できますが、本番環境では安定性を確保するために分離する必要があります。
Nomadの設定にはHCL(HashiCorp Configuration Language)を使用します。JSONよりもはるかに読みやすい形式です。古い設定を変換する場合は、このYAML ↔ JSON 変換ツールが便利です。サードパーティのサーバーにデータが漏れるリスクを冒さずに、素早く整合性をチェックできます。
/etc/nomad.d/nomad.hclを開き、以下の基本設定を入力します:
datacenter = "dc1"
data_dir = "/opt/nomad/data"
server {
enabled = true
bootstrap_expect = 1 # 高可用性の構成にする場合は3または5に設定
}
client {
enabled = true
servers = ["127.0.0.1"]
}
ui {
enabled = true
}
systemdでサービスを起動します:
sudo systemctl enable nomad
sudo systemctl start nomad
sudo systemctl status nomad
最初のジョブをデプロイする
Nomadの世界では、Podは扱いません。代わりにジョブ(Job)を作成します。ジョブにはグループ(Group)が含まれ、グループにはタスク(Task)が含まれます。この構造により、どのサービスが同じホスト上で一緒に動作しているかが非常に明確になります。
Nginxをデプロイするためのwebapp.nomadファイルを作成してみましょう。本番環境にイメージをプッシュする前に、私は必ずアーティファクトのハッシュを確認します。ハッシュ生成ツールを使用すれば、ダウンロードしたバイナリがベンダーのチェックサムと完全に一致するかを再確認できます。
job "web-server" {
datacenters = ["dc1"]
type = "service"
group "nginx-group" {
count = 2
network {
port "http" {
static = 8080
}
}
task "nginx-task" {
driver = "docker"
config {
image = "nginx:1.25.3"
ports = ["http"]
}
resources {
cpu = 500 # 500 MHz相当
memory = 256 # 256 MB
}
}
}
}
コマンド一つでジョブを起動します:
nomad job run webapp.nomad
モニタリングとデバッグ
http://your-server-ip:4646にアクセスすると、内蔵のUIが開きます。高速でクリーン、そしてクラスターの状態を即座に把握できます。後付け感のあるKubernetesダッシュボードとは異なり、NomadのUIはコア機能の一部として統合されています。
デバッグも同様にスピーディーです。複雑なkubectlのコンテキストと格闘する必要はありません。アロケーションID(allocation ID)を使用するだけです:
# アロケーションIDを確認する
nomad job status web-server
# リアルタイムでログを監視する
nomad alloc logs <allocation_id>

