JujuとCharmed Operators on Ubuntu:Model-drivenモデルによるアプリケーションのデプロイとライフサイクル管理の自動化

Ubuntu tutorial - IT technology blog
Ubuntu tutorial - IT technology blog

複数サービスを同時管理する際に頭を悩ませた問題

本番環境で5〜10個のサービスが並行稼働している場合 — MySQL、Redis、Nginx、Flaskアプリ、Celeryワーカーなど — 手動管理はすぐに限界を迎えます。以前、deploy.shのようなbashスクリプトを大量に抱えていた時期がありました。新しいサービスを追加するたびにスクリプトを書き、ドキュメントを更新し(誰も読まないのですが)、起動順序を頭に入れておく必要がありました。「MySQLを先に、次にRedis、アプリは最後…」といった具合に。

スケールが必要になった時はさらに大変でした。トラフィックのピーク時に対応するためWebノードを2台追加しなければならず、1台ずつ手動でインストールし、設定をコピーして接続テストをする作業に半日かかりました。しかも更新のたびにどのサービスが壊れるか心配でした。新メンバーはシステムを理解するためにWikiを何十ページも読む必要があり、そのWikiは常に実態より数ヶ月遅れていました。

原因分析:従来ツールに何が足りないのか?

Ansible、Chef、Puppet — どれも優れた構成管理ツールです。しかし、共通の盲点があります。「WHAT」(マシンをどう設定するか)は表現できるが、「HOW」(サービス同士がどのように連携するか)は理解できないという点です。

Ansibleでは、ノードAにMySQLをインストールし、ノードBにWordPressをインストールするplaybookを書けます。しかし、その関係性 — WordPressがどのユーザーで、どのデータベースに、どんなパスワードで接続するか — はハードコードするか、variableで個別管理しなければなりません。トポロジーが変わると(MySQLレプリカの追加、IP変更など)、3〜4箇所を手動で更新してからplaybookを再実行する必要があります。

Kubernetes + Helmはコンテナオーケストレーションの問題をうまく解決します。しかし、ベアメタルや古いVM上で動作している場合や、コンテナ化が難しいサービス(レガシーデータベース、ハードウェア固有のワークロードなど)がある場合は、Helmは適切な選択肢ではありません。

3つすべてが見落としていること:どのツールもサービス間の関係のセマンティクスを理解できていません。「WordPressはデータベースが必要」「KafkaにはZooKeeperが必要」「GrafanaはPrometheusをデータソースとして必要」といった意味的な関係です。トポロジーが変わると、結局人間が手で介入しなければなりません。

複雑なオーケストレーション問題の解決アプローチ

アプローチ1:バージョン管理された手動スクリプト

bash/Pythonスクリプトを丁寧に書き、Gitで管理し、ドキュメントを整備する方法です。最も一般的なアプローチですが、メンテナンスに手間がかかり、スケールが難しい — トポロジーが変わるたびに手動での介入が必要です。

アプローチ2:Dynamic InventoryによるAnsible

Ansibleのdynamic inventoryとgroup_varsを組み合わせてサービス間の関係を管理する方法です。純粋なスクリプトよりは優れていますが、サービスの追加・削除時のロジックは自分で書く必要があります。

アプローチ3:Kubernetes Operators

Kubernetesをすでに使用している場合、Operatorsパターン(Prometheus OperatorやMongoDB Operatorが行っているようなもの)はコンテナ環境でのライフサイクル管理問題を解決します。ただし、K8sクラスタと、operatorを自作するためのGo/Pythonの深い知識が必要で、production-readyな状態にするまで通常数週間かかります。

アプローチ4:JujuとCharmed Operators

JujuはoperatorパターンをKubernetesだけでなく、ベアメタルやVMにも適用します。Charmed Operators(Charms)は、deploy、configure、scale、upgradeのロジック全体をパッケージ化したPythonパッケージです — 他サービスとの関係も含めて。

最善策:Juju Model-drivenオーケストレーション

把握すべき核心概念

  • Controller:Jujuの「頭脳」。システム全体を管理し、専用マシンまたはコンテナ上で動作する
  • Model:アプリケーションとそれらの関係をまとめた論理グループ(namespaceに相当)
  • Charm:特定アプリのdeploy/configure/scale/upgradeロジックを格納したPythonパッケージ
  • Relation:2つのサービスが情報(credentials、endpoints、config)をやり取りする方法を定義
  • Unit:アプリケーションの1インスタンス(K8sのPodに相当)

UbuntuにJujuをインストールする

sudo snap install juju --classic

LXDでControllerをBootstrapする(ローカル環境)

# LXDがインストールされていない場合はインストール
sudo snap install lxd
lxd init --auto

# Controllerをブートストラップ — JujuがControllerとして専用LXDコンテナを作成
juju bootstrap localhost lxd-controller

Ubuntu 22.04で動作する会社のステージング環境でこの設定をテストしてから本番に適用しました。Bootstrapはネットワーク速度にもよりますが、約3〜5分かかります。

アプリケーションのデプロイとサービスの接続

# 新しいモデルを作成
juju add-model mywebapp

# CharmhubからMySQLとWordPressをデプロイ
juju deploy mysql
juju deploy wordpress

# ステータスを監視 — "active"になるまで待機
juju status

juju statusの典型的な出力:

App        Version  Status   Scale  Charm
mysql      8.0.36   active       1  mysql
wordpress  6.4.2    waiting      1  wordpress   waiting: ready

Unit          Workload  Agent  Public address
mysql/0*      active    idle   10.0.0.10
wordpress/0*  waiting   idle   10.0.0.11

最も重要なステップ — 2つのサービスを接続する:

juju integrate wordpress:db mysql:db

このコマンド実行後、Jujuが自動で:

  1. MySQL charmが新しいデータベースとユーザーをランダムcredentialsで作成
  2. host、port、dbname、user、passwordをrelation data経由でWordPress charmに送信
  3. WordPress charmがその情報でwp-config.phpを書き込む
  4. 必要に応じてPHP-FPMを再起動 — SSHで入る必要なし

ライフサイクル管理:スケール・設定・アップグレード

# WordPressを3ユニットにスケール — Jujuが自動でコンテナ作成、デプロイ、MySQL接続
juju scale-application wordpress 3

# 設定の確認と変更 — charmが自動適用、SSH不要
juju config wordpress
juju config wordpress blog-title="IT From Zero"

# charmを新バージョンにアップグレード
juju refresh wordpress --channel latest/stable

# charmに定義されたアクションを実行
juju actions mysql          # アクション一覧を確認
juju run mysql/0 backup     # バックアップを実行

複雑なスタックのデプロイ:数分でKafkaとモニタリング環境を構築する

juju add-model kafka-stack

# KafkaとZooKeeperをデプロイ
juju deploy kafka --channel 3/stable
juju deploy zookeeper --channel 3/stable
juju integrate kafka:zookeeper zookeeper:zookeeper

# モニタリングを追加 — PrometheusとGrafanaが自動で相互設定
juju deploy prometheus2
juju deploy grafana
juju integrate kafka:metrics prometheus2:scrape
juju integrate prometheus2:grafana-source grafana:grafana-source

# システム全体を確認
juju status --color

結果:手動で設定ファイルを1行も書かずに、PrometheusメトリクスとGrafanaダッシュボードを完備したKafkaクラスタが構築できます。

実際に導入する際の注意点

  • JujuはDocker/Kubernetesの代替ではない — 補完関係にあります。JujuはK8sクラスタにcharmをデプロイできます(Juju + K8sモード)。その場合、charmはVMではなくKubernetesリソースを管理します。
  • 高品質なcharmを選ぶ:Charmhub上のすべてのcharmがproduction-readyとは限りません。Canonicalバッジやダウンロード数の多いcharmを優先し、実際に使う前にREADMEをよく読んでください。
  • 概念の学習に投資する:本番デプロイの前に、model、controller、charm、relation、unitを理解するために1〜2日かけましょう。
  • 複雑なスタックに最適:Charmed Kubernetes、Kubeflow charmを使ったMLOps、Spark + HDFSのデータプラットフォームなど。1〜2つの単純なサービスであれば、Ansibleの方が手軽です。

まとめると:Jujuは「マシンにソフトウェアをインストールする」問題を解決するのではなく、「複雑なアプリケーションのライフサイクル全体を、再現可能でチーム全体が標準化された方法で管理する」問題を解決します。それはAnsible、Chef、Helmがこれまで目指してきたものとは根本的に異なります。

Share: