AlmaLinux 9 一覧へ戻る トップAlmaLinux 9 / Phase 1
AlmaLinux 9 ・ Phase 1

インフラ基盤とホスト-コンテナ間通信の疎通

Macvlanで「ホストとコンテナが話せない問題」を乗り越える

対象: AlmaLinux 9(192.168.2.3) Podman Macvlan

目次

  1. このガイドのゴール
  2. 概念を理解する
  3. 必要なもの
  4. 構築手順
  5. トラブルシューティング
  6. 完了チェックリスト

このガイドのゴール

AlmaLinux 9(ホスト)の上で、Podmanのコンテナが「SERVERセグメントに直接つながった本物のサーバー」のように振る舞える土台を作ります。完了すると、ホスト(192.168.2.3)からも、これから作る各コンテナ(192.168.2.11〜.17)からも、お互いに自由に通信できるようになります。これは今後のフェーズ全部の土台になるので、焦らず1ステップずつ確認しながら進めましょう。

0. まず概念を理解する(3分で読めます)

0-1. なぜ「NAT」ではなく「Macvlan」を使うのか

コンテナを作るとき、何も指定しなければ Podman は「NAT」というモードを使います。これは、コンテナたちをホストの内側に隠れたプライベートな小部屋(例:10.88.0.x)に押し込めるイメージです。外からアクセスするには、ホストの特定のポートを「転送(フォワード)」してあげる必要があります。

NATモードのイメージ
外部ホスト(2.3)の特定ポート→(転送)→コンテナ(10.88.0.x)

※ コンテナは「本物のサーバー」のようには見えない

Macvlanモードのイメージ
SERVER(192.168.2.0/24)
├─ ホストOS (2.3)
├─ コンテナA (2.11) ← LANに直接、独立したIP
└─ コンテナB (2.12) ← 同上

※ それぞれが「別のLANポートに挿さった本物のPC」のように見える

今回作りたいのは、DNSサーバーやHeadscaleサーバーが、まるでSERVERセグメントに直接挿さった独立した1台のサーバーであるかのように振る舞う環境です。そこで使うのが Macvlan です。

0-2. 立ちはだかる壁:「ホストとコンテナが会話できない」

ところが、Linuxカーネルの仕様(安全のための制限)により、同じ物理LANカードから分かれたMacvlanコンテナと、ホストOS自身は、直接パケットをやり取りできません。

物理NIC(eth0)を境にした断絶

ホストOS(2.3) ✕──────✕ コンテナ(2.11)

同じeth0から分かれた者同士は、カーネルの仕様で直接会話できません。これでは、ホスト上で動かすAnsibleが各コンテナへSSHできません。そこで、ホストOS側にも「仮想的なLANカード(macv0)」をもう1枚作り、それを通じて会話する、というのが今回の作戦です。

0-3. もう1つの壁:「出口が2つあると、どちらを使うか迷う」

macv0 を作って 192.168.2.99 というIPを与えると、ホストの中に「192.168.2.0/24への出口」が2つできてしまいます(eth0 と macv0)。

ルート未設定の状態(まだ解決していない)
ホスト(2.3)
├─ eth0 → 192.168.2.0/24 への出口①
└─ macv0(2.99) → 192.168.2.0/24 への出口②

→ カーネルはどちらを使うべきか分からず、結局コンテナと話せないまま

ルート設定後(解決)
ホスト(2.3)
├─ eth0 → それ以外すべての通信
└─ macv0 → 2.11〜.17 だけをピンポイント担当

→ 迷いがなくなり、ホスト⇔コンテナ間で確実に通信できる

この迷いを解消するため、「コンテナ宛て(2.11〜2.17)の通信だけはピンポイントで macv0 を使う」という専用ルートを明示的に教えてあげます。これが今回の作業の核心です。

必要なもの

構築手順

0

物理インターフェース名を確認する

作業を始める前に、自分のサーバーの「物理LANカードの名前」を確認します。環境によって eth0 だったり enp1s0 だったり様々です。

ip link show
出力例
1: lo: <LOOPBACK,UP,LOWER_UP> ...
2: enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 ...

この例では enp1s0 が物理LANカードです。以降のコマンドはすべて enp1s0 と仮定して書いていますが、ご自身の環境名に置き換えてください。

1

Podmanのインストールとmacvlanネットワークの作成

# パッケージ一覧を最新化し、Podmanをインストール
sudo dnf update -y
sudo dnf install -y podman

# Podman用のMacvlanネットワーク(local_lan)を作成
# -o parent=enp1s0 の部分を、ステップ0で確認した名前に置き換えてください
sudo podman network create -d macvlan --subnet=192.168.2.0/24 --gateway=192.168.2.1 -o parent=enp1s0 local_lan
確認
sudo podman network ls

出力に local_lan が表示されていればOKです。出力の中の subnets(192.168.2.0/24か)、gateway(192.168.2.1か)、parent(ステップ0で確認した名前になっているか)を確認してください。

2

仮想インターフェース(macv0)の作成

# ホスト用の仮想LANカード(macv0)を、enp1s0を親として追加
sudo nmcli connection add type macvlan dev enp1s0 con-name macv0 ifname macv0 mode bridge

# macv0にホスト専用の予備IP(192.168.2.99)を割り当てる
sudo nmcli connection modify macv0 ipv4.addresses 192.168.2.99/24 ipv4.method manual

補足:ここではまだ nmcli connection up を実行しません。次のステップでルートも設定してから、まとめて起動します。

3

【最重要】コンテナ個別ルート(/32)の追加

ここが0-3で説明した「出口を2つから1つに絞り込む」作業です。/32 は「このIPアドレス1つだけ」を意味する、最も狭い指定方法です。

# 今後作成する予定の全コンテナIP(2.11〜2.17)へのルートを、macv0経由に固定
sudo nmcli connection modify macv0 +ipv4.routes "192.168.2.11/32"
sudo nmcli connection modify macv0 +ipv4.routes "192.168.2.12/32"
sudo nmcli connection modify macv0 +ipv4.routes "192.168.2.13/32"
sudo nmcli connection modify macv0 +ipv4.routes "192.168.2.14/32"
sudo nmcli connection modify macv0 +ipv4.routes "192.168.2.15/32"
sudo nmcli connection modify macv0 +ipv4.routes "192.168.2.16/32"
sudo nmcli connection modify macv0 +ipv4.routes "192.168.2.17/32"

運用ルール

今後コンテナを追加するたびに、この「採番表」と「ルート追加」をセットで更新してください。忘れると、新しいコンテナにだけ通信できない、という分かりにくい不具合になります。フェーズ6(Ansible)で、この作業自体も自動化します。

4

設定の反映

sudo nmcli connection reload
sudo nmcli connection up macv0
出力例(成功時)
接続が正常にアクティベートされました(D-Bus アクティブパス: /org/freedesktop/NetworkManager/...)
5

本当に動くか証明する(疎通テスト)

設定が「正しく書けているか」と「実際に動くか」は別問題です。必ず実機で確認しましょう。

5-1. 仮想カードの状態確認
ip addr show macv0

state UP192.168.2.99/24 が表示されていればOKです。

参考:IPアドレスが異なっていた場合の修正方法

nmcli connection show macv0 | grep ipv4.method
nmcli connection show macv0 | grep ipv4.addresses

# ipv4.method: auto の場合、改めて設定し直す
sudo nmcli connection modify macv0 ipv4.method manual ipv4.addresses 192.168.2.99/24

# いったん落として上げ直せば反映される
sudo nmcli connection down macv0
sudo nmcli connection up macv0
5-2. ルートが反映されているか確認
ip route | grep macv0
出力例
192.168.2.11 dev macv0 scope link
192.168.2.12 dev macv0 scope link
...

このように7行(2.11〜2.17)表示されていれば成功です。

5-3. テスト用の使い捨てコンテナで実証する
# 軽量なAlpine Linuxで、IP 192.168.2.11 のテストコンテナを起動
sudo podman run -it --rm --name test-ping --network local_lan --ip 192.168.2.11 docker.io/library/alpine:latest sh

実行するとコンテナの中(/ # というプロンプト)に入ります。

コンテナ → ホストへの確認(コンテナの中で実行)
ping -c 3 192.168.2.99
ホスト → コンテナへの確認(別ターミナル・ホスト側で実行)
ping -c 3 192.168.2.11

両方向とも 0% packet loss であればOKです。確認できたら、コンテナ側で exit と入力してテストを終了します(--rm オプションにより自動的に消えます)。

6

FortiGate側のDHCP除外設定(忘れずに)

192.168.2.99(macv0)と 192.168.2.11〜192.168.2.17(各コンテナ)が、将来DHCPで他の機器に払い出されてしまわないよう、FortiGateのDHCPサーバー設定で「除外範囲(Excluded Range)」に追加してください。

トラブルシューティング

症状原因の可能性対処法
ip route get 192.168.2.11 の結果が dev enp1s0 のままルートが反映されていないnmcli connection show macv0 で接続がactiveか確認し、nmcli connection down macv0 && nmcli connection up macv0 で再起動
nmcli connection add type macvlan でエラーNetworkManagerのバージョンが古い、または該当プラグイン未導入nmcli --version を確認し、sudo dnf update NetworkManager を実施
pingが片方向しか通らないファイアウォール(firewalld)がICMPをブロックしている可能性sudo firewall-cmd --list-all でICMP許可状況を確認
enp1s0 という名前が存在しない環境によって命名規則が異なる(ens18、eth0 など)ステップ0の ip link show の結果を再確認し、全コマンド内の名前を実際の名前に置き換える
再起動後にmacv0が消える/IPが消えるautoconnect が無効になっているnmcli connection modify macv0 connection.autoconnect yes を実行

フェーズ1完了チェックリスト

すべてチェックできれば、フェーズ1は完了です。

AlmaLinux 9 一覧へ戻る