IBM MQとアプリコンテナー間のプロセス名前空間の共有

MQアプリケーションをローカル・キュー・マネージャーに接続(以下、ローカル接続と表記)するときには、アプリケーションとキュー・マネージャーが同一OS上で稼働しプロセス間通信を行います。この接続形態のアプリケーションを、1プロセス1コンテナーを原則とするコンテナー環境にそのまま移行することはできません。そこでKubernetesのプロセス名前空間の共有機能を使い、MQコンテナーとアプリコンテナーを同一Podで起動させる構成への移行を検証してみました。今回はMQを使用していますが、ローカル接続を使用するミドルウェアやアプリケーションでも同様の考え方で検証できます。

## コンテナー環境でのIBM MQの使用
コンテナー環境でのIBM MQの使用方法は2種類あります。(詳細はマニュアル [コンテナーでの IBM MQ の計画](https://www.ibm.com/docs/ja/ibm-mq/9.3?topic=integration-planning-mq-in-containers) に記載されています。)

1. IBM MQ Operator の使用
1. 独自のイメージとデプロイメント・コードのビルド

上記2種類について簡単に説明します。

### IBM MQ Operator の使用
IBM MQ Operator はRed Hat OpenShift Container Platform (以下OpenShiftと表記) にデプロイされている場合のみサポートされるオペレーターです。IBM MQ OperatorをOpenShiftにインストールすると、図1のようにキュー・マネージャーを作成できるようになります。図2のように、yaml ビューで編集してからキュー・マネージャーを作成できるようになっていますが、マニュアル等には明記されていないもののあらゆる構成変更が可能な訳では無いようです。柔軟に構成変更しながら検証するため、今回は後述の「独自のイメージとデプロイメント・コードのビルド」を選択しました。
なお KubernetesでIBM MQコンテナーを使用するには、[IBM MQ Sample Helm Chart](https://github.com/ibm-messaging/mq-helm)を使用するか、「独自のイメージとデプロイメント・コードのビルド」を利用することになります。

![operator0101.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/922552/7892ce14-b3c4-ecd9-3693-431cb251bff2.png)
図1. IBM MQ Operatorによるキュー・マネージャーの作成

![operator0102.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/922552/07ed4cdb-a63e-ec8a-717e-ff07dfd8f7af.png)
図2. キュー・マネージャーの作成 - YAMLビュー

### 独自のイメージとデプロイメント・コードのビルド
独自のIBM MQキュー・マネージャーのイメージをビルドして利用できます。ビルド方法の詳細については、[mq-contaier GitHubレポジトリー](https://github.com/ibm-messaging/mq-container)にある[コンテナー・イメージのビルド](https://github.com/ibm-messaging/mq-container/blob/master/docs/building.md)に本番向けと開発向けの手順が掲載されています。基本的にはドキュメント通りにビルドできました。この方法はイメージのビルドや利用時にオペレーターには無い柔軟性を発揮できますが、イメージのビルドや利用方法を自身で管理することになります。
上記に関連して、開発用途に使えるビルド済みの [IBM MQ Advanced for Developers コンテナー・イメージ](https://www.ibm.com/docs/ja/ibm-mq/9.3?topic=containers-mq-advanced-developers-container-image)がIBM Container Registryの`icr.io/ibm-messaging/mq`にあります。
この記事では、ビルド済み開発用MQコンテナー・イメージを使ったOpenShift上でのデプロイ検証結果について記述します。ちなみに独自にビルドしたイメージでも同様に動作しました。

## ビルドされたイメージの起動
OpenShift上でMQコンテナー・イメージとアプリケーションのイメージを同一Podで起動し、プロセス名前空間の共有によりアプリケーションがキュー・マネージャーにローカル接続でアクセスできるようにします。前提として、MQコンテナー・イメージとアプリコンテナー・イメージは /mnt/mqm を共有します。

![ocpcluster.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/922552/13846662-c8bf-b933-0aba-4bd20cb0c542.png)
図3. 検証構成図

パラメーターは以下の表の通りです。
| 項目                     | 値         |
|-------------------------|------------|
| デプロイメントの名前     　 | mq-01     |
| クラスターのネームスペース   | test-01    |
| ビルド済み開発用MQコンテナー・イメージの名前 | mq-built-container  |
| アプリコンテナー・イメージの名前           | mq-agent          |

deployment.yaml 記述例の抜粋を以下に示します。プロセス名前空間の共有に必須となるフィールドと値は`shareProcessNamespace: true`です。このフィールドの意味や有効化によって生じる動作の違いはKubernetesのドキュメントの[Pod内のコンテナ間でプロセス名前空間を共有する](https://kubernetes.io/ja/docs/tasks/configure-pod-container/share-process-namespace/)に説明されています。下記に示すように、このフィールドを deployment.yaml のspec > template > spec の下に記述します。

```yaml:deployment.yaml 抜粋
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mq-01
  namespace: test-01
  labels:
    app.kubernetes.io/instance: mq-01
    app.kubernetes.io/name: mq-built-container
spec:
  selector:
    matchLabels:
      app: mq-01
  replicas: 1
  template:
    metadata:
      labels:
        app: mq-01
        app.kubernetes.io/instance: mq-01
        app.kubernetes.io/name: mq-built-container
    spec:
      shareProcessNamespace: true
```

この設定をベースにして、今回試したデプロイメントは以下の通りです。デプロイメントの一部、共有ストレージやConfigMapの詳細については省略して示しています。

```yaml:deployment.yaml 記述例
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mq-01
  namespace: test-01
  labels:
    app.kubernetes.io/instance: mq-01
    app.kubernetes.io/name: mq-built-container
spec:
  selector:
    matchLabels:
      app: mq-01
  replicas: 1
  template:
    metadata:
      labels:
        app: mq-01
        app.kubernetes.io/instance: mq-01
        app.kubernetes.io/name: mq-built-container
    spec:
      shareProcessNamespace: true
      securityContext:
        supplementalGroups: [99]
      containers:
      - name: mq-built-container-01
        envFrom:
        - configMapRef:
            name: configmap-mq-01
        image: icr.io/ibm-messaging/mq:latest
        volumeMounts:
        - mountPath: /mnt/mqm
          name: mq-volume
        ports:
          - name: qm
            containerPort: 1414
            protocol: TCP
      - name: mq-agent-01
        envFrom:
        - configMapRef:
            name: configmap-agent-01
        image: image-registry.openshift-image-registry.svc:5000/test-01/mq-agent:latest
        volumeMounts:
        - mountPath: /tmp/mqagent
          name: conf-volume
          readOnly: true
        - mountPath: /mnt/mqm
          name: mq-volume
      volumes:
        - name: mq-volume
          persistentVolumeClaim:
            claimName: pvc-mq-01
        - name: conf-volume
          projected:
            sources:
            - configMap:
                name: mqagent-conf
            - configMap:
                name: mqagent-access-conf
```
上記のdeploymentをデプロイします。
```shell
$ oc apply -f deployment.yaml
```

アプリの動作内容は省略しますが、これでローカル接続のアプリケーションを実行できました。Kubernetes上でも同様のデプロイメントで技術的には起動可能と考えられます。
今回は開発用イメージを使った検証を実施しました。本番環境への適用を想定すると、高可用性の実現、共有ストレージの選択、ビルドされたMQコンテナー・イメージのメンテナンスや環境依存の項目等の考慮点が考えられます。技術的な検証にこの記事が参考になれば幸いです。

#### 参考資料:
Kubernetesドキュメント:  Pod内のコンテナ間でプロセス名前空間を共有する
[https://kubernetes.io/ja/docs/tasks/configure-pod-container/share-process-namespace/](https://kubernetes.io/ja/docs/tasks/configure-pod-container/share-process-namespace/)