K8S,Zabbix Agent2 コンテナのホスト名カスタマイズ-NodeNameとPodNameを組み合わせる

## Zabbix Agent2 コンテナのホスト名カスタマイズ: `POD_NAME` と `NODE_NAME` の活用

このガイドは、`zabbix/zabbix-agent2` Docker イメージの `ENTRYPOINT` と `CMD` の動作原理を深く理解し、`command: ["/bin/sh", "-c"]` パターンを使用して `POD_NAME` と `NODE_NAME` 環境変数を活用し、`ZBX_HOSTNAME` を設定する**高度なカスタマイズ方法**を段階的に説明します。

### 結論: シェルスクリプト内で `export` を使用して `ZBX_HOSTNAME` を設定し、その後 `docker-entrypoint.sh` を実行する！

#### kubectl logsの結果(中略)
```powershell
PS C:\Users\hoge> kubectl logs zabbix-agent2-custom-shell
(中略)
2025/06/10 04:16:37.935974 Zabbix Agent2 hostname: [zabbix-agent2-custom-shell-kind-control-plane]
Press Ctrl+C to exit.
```

Zabbix Agent2 Docker イメージは、`ENTRYPOINT` に `/usr/bin/docker-entrypoint.sh` スクリプトを、`CMD` に `/usr/sbin/zabbix_agent2 --foreground -c /etc/zabbix/zabbix_agent2.conf` を使用するように設計されています。この `docker-entrypoint.sh` スクリプトは、コンテナの環境変数を読み取り、Zabbix Agent2 の設定ファイルに適切に適用する重要な役割を担っています。

この高度な方法では、Kubernetes の `command` フィールドで `/bin/sh -c` を使用して**カスタムシェルスクリプトを最初に実行**します。このスクリプト内で `export ZBX_HOSTNAME` を設定した後、**元のイメージの `docker-entrypoint.sh` スクリプトを直接呼び出して** Zabbix Agent2 を起動します。

---

### ステップバイステップ設定ガイド

以下の YAML コードに従って、Zabbix Agent2 コンテナを適切に設定してください。

```yaml
apiVersion: v1
kind: Pod
metadata:
  name: zabbix-agent2-custom-shell
spec:
  containers:
  - name: zabbix-agent2
    image: zabbix/zabbix-agent2:7.0-alpine-latest # 使用するZabbix Agent2イメージのタグに変更してください。
    
    # --- ステップ1: シェルを直接呼び出し、全てのカスタマイズロジックを args に含める ---
    # Kubernetes の command フィールドで /bin/sh -c を使用してシェルを明示的に呼び出します。
    # これにより、Dockerfile の元の ENTRYPOINT は無視されます。
    command: ["/bin/sh", "-c"]
    args: 
    - | # パイプ(|)記号を使用して複数行のシェルスクリプトを args に記述します。
      # ここに任意の追加シェルコードを挿入できます。
      echo "Zabbix Agent2 のカスタム初期化を開始します..."
      
      # --- ステップ2: ZBX_HOSTNAME 環境変数をシェルスクリプト内で設定 (ここが重要！) ---
      # POD_NAME と NODE_NAME は env フィールドですでに注入されているため、使用可能です。
      # この方法は、docker-entrypoint.sh が ENTRYPOINT として設定されているため、
      # export コマンドを直接実行できない場合に役立ちます。
      export ZBX_HOSTNAME="${POD_NAME}-${NODE_NAME}"
      echo "ZBX_HOSTNAME が ${ZBX_HOSTNAME} に設定されました。"
      
      # --- ステップ3: 元の Dockerfile の ENTRYPOINT スクリプトを直接実行 ---
      # このスクリプトが ZBX_HOSTNAME を含む環境変数を読み取り、Zabbix 設定を処理します。
      # そして、元の CMD の引数をこのスクリプトに渡し、Zabbix Agent2 を起動します。
      /usr/bin/docker-entrypoint.sh /usr/sbin/zabbix_agent2 --foreground -c /etc/zabbix/zabbix_agent2.conf
      
      echo "カスタム初期化が完了し、Zabbix Agent2 が起動しました。"
    
    # --- ステップ4: POD_NAME, NODE_NAME, ZBX_SERVER_HOST 環境変数を注入 ---
    # これらの環境変数は、シェルスクリプト内および docker-entrypoint.sh スクリプトの両方で利用可能です。
    env: 
    - name: POD_NAME
      valueFrom:
        fieldRef:
          fieldPath: metadata.name # 現在の Pod の名前を取得し、POD_NAME 変数に割り当てます。
    - name: NODE_NAME
      valueFrom:
        fieldRef:
          fieldPath: spec.nodeName # 現在の Pod がスケジュールされているノードの名前を取得し、NODE_NAME 変数に割り当てます。
    - name: ZBX_SERVER_HOST 
      value: "your-zabbix-server-ip-or-hostname" # 実際の Zabbix サーバーのアドレスに変更してください。
    # 必要な他の Zabbix 環境変数もここに追加できます (例: ZBX_SERVER_ACTIVE)
    
    ports:
    - containerPort: 10050 # Zabbix Agent のデフォルトポート
      protocol: TCP
    
    resources:
      limits:
        cpu: "100m"
        memory: "128Mi"
      requests:
        cpu: "50m"
        memory: "64Mi"

```

#### YAML コードの詳細説明とポイント

1.  **`command: ["/bin/sh", "-c"]`**:
    * これは Kubernetes に対して、`args` に定義された内容全体を**単一のシェルスクリプト**として実行するよう指示するコマンドです。
    * **注意点:** この設定により、Dockerfile に定義された元の **`ENTRYPOINT` (`/usr/bin/docker-entrypoint.sh`) は無視されます**。つまり、この時点からコンテナの起動ロジックは、完全に `args` フィールド内のスクリプトによって制御されます。

2.  **`args: - |`**:
    * `|` (パイプ) 記号は、それに続く複数行の内容を一つの長い文字列として認識させます。これにより、複雑なシェルスクリプトも読みやすく記述できます。
    * このスクリプトブロック内で、必要に応じて任意のシェルコマンドを実行できます。例えば、特定の条件チェック、ファイルの準備待ち、他の初期化スクリプトの実行などが可能です。

3.  **`export ZBX_HOSTNAME="${POD_NAME}-${NODE_NAME}"`**:
    * **ここが非常に重要です！** `env` フィールドを通じて注入された `POD_NAME` と `NODE_NAME` 環境変数をここで活用します。
    * この方法を選択した主な理由は次のとおりです:
        * Dockerfile の `ENTRYPOINT` が `/usr/bin/docker-entrypoint.sh` のように**「Exec Form」で特定のスクリプトを直接呼び出すように設定されている**ため、`export` のようなシェル組み込みコマンドを Dockerfile の `CMD` や Kubernetes Pod の `args` に直接含めても機能しません。`docker-entrypoint.sh` スクリプト自体が `export` を解釈するシェルではないからです。
        * さらに、Kubernetes の `env` フィールドで `value: "$(POD_NAME)-$(NODE_NAME)"` のように環境変数を直接組み合わせた場合、Zabbix Agent2 の `docker-entrypoint.sh` スクリプトの内部ロジック、特に設定ファイルをパースまたは変更する部分で、その値に含まれる `$()` 記号のような特殊文字が**正規表現の特殊文字と誤認され**、`grep: bad regex '^Hostname=\${POD_NAME}-\${NODE_NAME}$': Invalid contents of {}` のようなエラーが発生することがあります。
    * これらの問題を解決するため、`/bin/sh -c` を介して**まずシェル環境を構築**し、その中で `export` コマンドを使用して `POD_NAME` と `NODE_NAME` が展開された**純粋な文字列値**を `ZBX_HOSTNAME` に割り当てます。このように純粋な文字列として設定された `ZBX_HOSTNAME` は、その後に実行される `/usr/bin/docker-entrypoint.sh` スクリプトによって問題なく処理されます。

4.  **`/usr/bin/docker-entrypoint.sh /usr/sbin/zabbix_agent2 --foreground -c /etc/zabbix/zabbix_agent2.conf`**:
    * これは**元の Dockerfile の `ENTRYPOINT` スクリプトを直接呼び出す**部分です。
    * **非常に重要:** `command: ["/bin/sh", "-c"]` を使用することで元の `ENTRYPOINT` が無視されたため、`docker-entrypoint.sh` が実行する重要な初期化処理（環境変数を読み取り Zabbix 設定ファイルに適用するロジックを含む）を実行するには、このように明示的に呼び出す必要があります。
    * 後に続く `/usr/sbin/zabbix_agent2 --foreground -c /etc/zabbix/zabbix_agent2.conf` は、元の Dockerfile の `CMD` に対応する部分で、`docker-entrypoint.sh` スクリプトへの引数として渡され、最終的に Zabbix Agent2 バイナリを起動します。

5.  **`env` フィールド**:
    * `POD_NAME`、`NODE_NAME`、`ZBX_SERVER_HOST` などの環境変数は、**前のステップで実行されたシェルスクリプトと `docker-entrypoint.sh` スクリプトの両方で利用できるように、事前に注入されます**。
    * **Kubernetes `env` フィールドの限界:** `env` フィールドでは、シェルスクリプトのように複雑な文字列操作や条件付きロジックを直接実行することはできません。他の環境変数の値を単純に結合する**変数展開**はサポートされますが、`shell` コマンドの実行や複雑な算術演算などは不可能です。このような複雑なロジックは、上記の YAML コードのように `command` と `args` で渡されるシェルスクリプト内で処理する必要があります。

---

### なぜこの方法が必要なのか？ 

この `command: ["/bin/sh", "-c"]` パターンを使用してシェルスクリプトを最初に実行する方法は、非常に強力な柔軟性を提供しますが、YAML コードが複雑になり、デバッグが難しくなる可能性があることを常に覚えておく必要があります。

**この方法を選択した主な理由は明確です:**

1.  **`export` コマンドの必要性:** Dockerfile の `ENTRYPOINT` がシェルスクリプトではない「Exec Form」で設定された実行ファイル（`docker-entrypoint.sh`）を指しているため、`CMD` や Kubernetes `args` に `export` のようなシェル組み込みコマンドを直接使用しても機能しません。シェル環境を最初に作成して初めて `export` を実行できます。
2.  **環境変数展開と `docker-entrypoint.sh` との互換性の問題解決:** `ZBX_HOSTNAME` のように動的に値を生成する必要がある環境変数を Kubernetes の `env` フィールドで直接 `$(VAR)` 形式で組み合わせて渡した場合、`zabbix/zabbix-agent2` イメージの `docker-entrypoint.sh` スクリプト内部で、**その値が正規表現の特殊文字として誤認され、処理エラーが発生**しました (`grep: bad regex...`)。シェルスクリプト内で `export ZBX_HOSTNAME="${POD_NAME}-${NODE_NAME}"` のように変数を設定すると、シェルが最初に値を展開して `hostname-node1` のような**純粋な文字列**にしてくれるため、`docker-entrypoint.sh` がそれを問題なくパースし、Zabbix 設定ファイルに適用できるようになります。

このように、複雑な初期化ロジックが必要な場合や、シェルユーティリティ（例: `sed`、`awk`、`grep`）を使用して環境を精巧に制御する必要がある場合に、この高度なカスタマイズ方法が非常に役立ちます。慎重に計画し、テストを行うことが重要です。

---
**このガイドは、AI を活用して作成されました。**