Drupal を OpenShift on IBM Cloud 上で稼働させてみる

## はじめに

世界中のWebサイトで多く使われている、オープンソースのCMS（コンテンツ・マネージメント・システム）である Drupal を、エンタープライズ環境で多く採用されている（Kubernetesディストリビューションの）OpenShift上で稼働させてみました。
今回は、OpenShiftのインフラ環境として、OpenShiftをフルマネージドにて提供する、IBM Cloud 上の Red Hat OpenShift Kubernetes Services (以下、通称ROKS) を使って、コンテナ環境にて、Drupalを稼働させるまでの一連の手順をご紹介いたします。

### Drupalとは
まず、簡単にDrupalの概要を説明いたします。
DrupalはオープンソースのCMSで、Webサイトのコンテンツを作成したり、管理したり、新たな機能を追加する際に利用するツール（プラットフォーム）です。

Wikipedia：https://ja.wikipedia.org/wiki/Drupal
公式サイト：https://www.drupal.org/project/drupal

同じカテゴリーのツール（OSS）で、世界的に有名なものとしては、「WordPress」などが上げられるかと思いますが、Googleで検索すると、以下のサイトなどに、その共通点と違いなどがわかりやすくまとめられていましたので、ご参考までに記載させていただきます。
https://dyno.design/articles/wordpress-drupal-comparison/
https://www.ossnews.jp/compare/WordPress/Drupal
https://www.sungrove.co.jp/drupal/

上記サイトに書かれている内容を簡単にまとめると
「Drupalは、主にエンタープライズ（大企業）を対象として、少しプロフェッショナル向けのツールであり、拡張性の高い、汎用デジタル・エクスペリエンス・プラットフォームとして、開発・提供されている」
といった感じでしょうか。

### 今回作成するシステムアーキテクチャのイメージ

では、このDrupalを使って、今回の一連の手順にて稼働させるコンポーネントのアーキテクチャイメージを以下に示します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355635/ae99e042-e69d-57b2-c99a-42cab46dd1f5.png)

Drupalは現行の最新バージョンであるv9系を使い、データベースとしてはPostgreSQLを使って、できるだけシンプルに、OpenShift上にデプロイする手順を示します。

## 全体ステップ

1. OpenShiftの環境を用意する
2. OpenShiftクラスターへの、コンソールからのコマンド操作をするための準備をする
3. OpenShiftクラスターへの、Podデプロイの事前準備を行う
4. OpenShift 上に PostgreSQL をデプロイする
5. OpenShift 上に Drupal をデプロイする
6. OpenShift 上に NGINX をデプロイする
7. 外部からのアクセス可能にするため、Routeを作成する
8. Drupal の初期設定を行う

ここから、各ステップを順に追って説明していきます。

### ステップ1: OpenShift の環境を用意する

ステップ１では、OpenShiftの環境を準備する方法について示します。
既にOpenShift（＋CLIでocコマンドで操作できる）環境がある方は、ステップ２に進んでください。

手順１. IBM Cloudで、OpenShift Kubernetes Servies を発注する

IBM Cloudのカタログのサービスから「Containers」カテゴリーを選んで、「Red Hat OpenShift on IBM Cloud」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355635/eba6511f-ba55-c80e-f3d1-a0eeac1aed4d.png)
OpenShiftのバージョン、ロケーション、フレーバー（サーバの種類）、台数などを選択しオーダーします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355635/eefb5e48-966c-c090-2cd9-0135f8aadb1d.png)
３０分程度でクラスターが立ち上がってきます。　
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355635/23acca2b-d9a0-7c41-6e9e-04be7a4d9204.png)
＃「Ingress状況」のステータス（不明）は、少し時間が経過した後「正常」になります

手順2. 上部の「OpenShift Webコンソール」ボタンを押して、OpenShiftのポータル画面にアクセスする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355635/e9cb598f-64c9-941b-494a-f497e4da0d2c.png)
以上で、OpenShiftクラスター環境の払い出しと、Webブラウザーからのアクセスが確認できました。

### ステップ2: OpenShiftクラスターへの、コンソールからのコマンド操作をするための準備をする

ステップ２では、ステップ１でデプロイしたOpenShift on IBM Cloud（ROKS）環境に、ローカルPCから、リモートログインして、ocコマンドでOpenShift環境を操作できる環境を整えます。

手順1. IBM Cloudのクラスターのメニューの右上の「アクション」から「CLIを介した接続」を押す
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355635/dce2a69a-6aff-cb22-6594-9c782440b7d0.png)

手順2. 表示される手順の解説に沿ってセットアップを行い、ocコマンドにてクラスターと通信ができる事を確認する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355635/0a2d980b-06bc-9e59-6ec7-c7182d95ab24.png)
補足：久しぶりに接続される場合は、各種コマンドやプラグインなどがバージョンアップされていることも多いので、改めて「セットアップの詳細な説明」のリンク先のガイド内容を確認し、必要に応じて、最新バージョンに更新されると良いかと思います。

### ステップ3: OpenShiftクラスターへの、Podデプロイの事前準備を行う

新規プロジェクト（=namespace）を作成します。（今回はプロジェクト名を「my-drupal」とします）

```
$ oc new-project my-drupal
```

今回起動するコンテナ（Pod）において、一部のroot権限が必要な操作（ディレクトリの作成など）が実行可能になるように、新規サービスアカウント（anyuid-user）を作成し、anyuidのSCC(Security Context Constraints)ポリシーを割り当てます。

```
$ oc create sa anyuid-user
$ oc adm policy add-scc-to-user anyuid -z anyuid-user
```

この内容（実施する意味）については、あまりKubernetesやOpenShiftのセキュリティに詳しくない方にとって、少し理解が難しいかもしれません。ここでは、「できるだけ、この後の作業で利用するオープンソースの修正を減らし、簡単に実行できるようにするための、おまじない」ぐらいに捉えていただき、先に進めてください。

もし、上記コマンドについて、内容を理解したい方は、以下のあたりの記事をご参照ください。

OpenShiftのコンテナセキュリティ
https://qiita.com/kimura-y/items/7ac0ef6f08c33683ab98
https://www.mtioutput.com/entry/openshift-scc-adduser

---
補足：
今回の上記対応の背景について、簡単に補足説明しておきます。
一般に提供されているOSSにおいて、Podをroot権限で動かす（動かせる）ことを前提としたような操作（ローカルストレージに対する操作など）が含まれる場合があります。一方、OpenShiftでは、エンタープライズでの利用を前提として提供されている為、一般的な生K8sより、標準でのセキュリティ設定の基準が高く、Podがroot権限で実行できないような設定がデフォルトで定義されています。今回、DockerHub上で公開されているOSS（NGINX、PostgreSQL、Drupal）の最新版を利用しましたが、これらをOpenShift上で、そのまま動かそうとすると、上記のOpenShiftのセキュリティ制約により、エラーが出てしまい、Podが起動できません。
こういった場合、一般的には、OSSのコンテナ（Pod）側で、root以外のユーザで動かせるようにコンテナをカスタマイズして（或いは、root以外のユーザで動かすことを前提として作られたコンテナイメージを使って）OpenShiftでのセキュリティ基準を保ったまま動かすようにするのが筋ではあります。ただ、今回は、できるだけ簡単に「まず、稼働させてみる」事を主目的とし、コンテナイメージは最も汎用的なものを使いながら、OpenShift上で稼働できるよう、OpenShift側で、root権限でのコマンドが稼働できるサービスアカウントを作成し、そのアカウントでPodを立ち上げるといった回避策を取ることにし、その手順を示していますので、その旨、ご理解ください。

---

### ステップ4: OpenShift 上に PostgreSQL をデプロイする

まず、今回のDrupalで使うデータベースとして、DockerHubにある、「postgres:latest」のイメージを使ってコンテナをデプロイします。

今回は、ローカルPCに、デプロイ用のyamlファイル（postgres_v1.yaml）を作成し、「oc apply」コマンドにて、デプロイしてみます。

手順１. 適当なエディタを開いて、以下のファイル(postgres_v1.yaml）を作成する
（ソースコード右上のコピーマークを押して、コードをコピーして使ってください）

```yaml:postgres_v1.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: postgresql-deployment
  namespace: my-drupal
  labels:
    app: sample-app1
    tier: postgres
spec:
  strategy:
    type: RollingUpdate
  selector:
    matchLabels:
      tier: postgres
  template:
    metadata:
      labels:
        app: sample-app1
        tier: postgres
    spec:
      serviceAccountName: anyuid-user
      containers:
        - image: postgres:latest
          name: postgres-container
          env:
            - name: POSTGRES_DB
              value: drupal
            - name: POSTGRES_USER
              value: postgres
            - name: POSTGRES_PASSWORD
              value: postgres
          ports:
            - containerPort: 5432
```

手順2. 以下のコマンドを実行してPostgreSQLをデプロイし、サービスをexposeする

```
$ oc apply -f postgres_v1.yaml
$ oc expose deployment postgresql-deployment --name=postgresql-service
```

手順3. OpenShiftコンソールで「管理者」の右の▼を押し、「Developer」パースペクティブに切り替えた上で、トポロジーを選択し、プロジェクトで「my-drupal」を選択して、Podが正常稼働していることを確認する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355635/31fa1836-33fa-7306-9131-46b8e61b9df4.png)

以上で、PostgreSQLのデプロイが完了しました。

### ステップ5: OpenShift 上に Drupal をデプロイする

前ステップと同じ要領にて、DockerHubにある、「drupal:latest」のイメージを使ってコンテナをデプロイをする、yamlファイル（drupal_v1.yaml）をローカルPCにて作成し、「oc apply」コマンドにて、デプロイします。

手順１. 適当なエディタを開いて、以下のファイル(drupal_v1.yaml）を作成する
（ソースコード右上のコピーマークを押して、コードをコピーして使ってください）

```yaml:drupal_v1.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: drupal-deployment
  namespace: my-drupal
  labels:
    app: sample-app1
    tier: drupal
spec:
  strategy:
    type: RollingUpdate
  selector:
    matchLabels:
      tier: drupal
  replicas: 1
  template:
    metadata:
      labels:
        app: sample-app1
        tier: drupal
    spec:
      serviceAccountName: anyuid-user
      containers:
      - image: drupal:latest
        name: drupal-container
        ports:
        - containerPort: 80
```

手順2. 以下のコマンドを実行してDrupalをデプロイし、サービスをexposeする

```
$ oc apply -f drupal_v1.yaml
$ oc expose deployment drupal-deployment --name=drupal-service
```

手順3. OpenShiftコンソールのDeveloperパースペクティブのトポロジーにてPodが正常稼働していることを確認する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355635/47c62eca-2389-538e-9801-67e3645d79b4.png)

以上で、Drupalのデプロイが完了しました。

### ステップ6: OpenShift 上に NGINX をデプロイする

DockerHubにある、「nginx:latest」のイメージを使ってコンテナをデプロイします。
今回は、ローカルPCに、デプロイ用の２つのyamlファイル（設定ファイル用のConfigMapと、デプロイ用のDeployment）を作成し、「oc apply」コマンドにて、デプロイしてみます。

手順１. 適当なエディタを開いて、以下の２つのファイル（nginx-configmap_v1.yaml, nginx_v1.yaml）を作成する
（ソースコード右上のコピーマークを押してコピーして使ってください）

```yaml:nginx-configmap_v1.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: sites-conf
  namespace: my-drupal
  labels:
    app: sample-app1
    tier: nginx
data:
  sites.conf: |
    server {
      listen 8080;
      server_name localhost;

      location / {
        proxy_pass                              http://drupal-service;
        proxy_redirect                          off;
        proxy_set_header Host                   $host;
        proxy_set_header X-Real-IP              $remote_addr;
        proxy_set_header X-Forwarded-Host       $host;
        proxy_set_header X-Forwarded-Server     $host;
        proxy_set_header X-Forwarded-Proto      $scheme;
        proxy_set_header X-Forwarded-For        $proxy_add_x_forwarded_for;
      }
    }
```

```yaml:nginx_v1.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  namespace: my-drupal
  labels:
    app: sample-app1
    tier: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      tier: nginx
  strategy:
    type: 
  template:
    metadata:
      labels:
        app: sample-app1
        tier: nginx
    spec:
      serviceAccountName: anyuid-user
      containers:
      - image: nginx:latest
        name: nginx-container
        ports:
        - containerPort: 8080
        volumeMounts:
        - mountPath: /etc/nginx/conf.d
          readOnly: true
          name: sites-conf-vol
      volumes:
      - name: sites-conf-vol
        configMap:
          name: sites-conf
          items:
            - key: sites.conf
              path: sites.conf
```

手順2. 以下のコマンドを実行してNGINXをデプロイし、サービスをexposeする

```
$ oc apply -f nginx-configmap_v1.yaml
$ oc apply -f nginx_v1.yaml
$ oc expose deployment nginx-deployment --name=nginx-service
```

手順3. OpenShiftコンソールのDeveloperパースペクティブのトポロジーにてPodが正常稼働していることを確認する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355635/eef2456e-8f1e-74e9-1882-faafb29bde2d.png)

以上で、NGINXのデプロイが完了しました。

### ステップ7: 外部からのアクセス可能にするため、Routeを作成する

手順1. 以下のコマンドを実行して、Routeをexposeする。

```
$ oc expose service nginx-service --name=my-drupal-route
```

手順2. OpenShiftコンソールのDeveloperパースペクティブのトポロジーにて、nginx-deploymentのリソースタブを開き、ルートが作成されたことを確認し、作成されたURLにアクセスしてみる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355635/32491397-e52d-7d92-e287-0a7e61f93225.png)

Drupalのトップページが出たら、一連のコンポーネントのデプロイは成功です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355635/a049a711-5368-4505-aa5a-c192924cd313.png)

### ステップ8: Drupal の初期設定を行う

最後のステップとして、Drupalを動作させるための初期設定を行います。

画面のUIに従って、進めていきます。

プロフィールの選択では「標準」を選び、
データベースの設定では、以下のような、postgres_v1.yamlファイルで設定した内容を入力します。
（高度なオプション内の「ホスト」は、PostgreSQLのPodをExposeした、Service名「postgresql-service」を入れます。）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355635/9da9db05-1334-63c4-3bab-b6f7272cab80.png)

Drupalのサイト（モジュール）のインストールと翻訳のセットアップが完了するので、次のサイトの環境設定にて、各項目を適当に（適切なものを）入れます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355635/64cf4f58-4822-57d8-51c9-fdfb91b03c07.png)

Drupalのようこそ画面が出たら成功です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355635/7298cbec-42f2-4ab8-c387-f5559a29ce9e.png)

＃ 今後は、先のRouteのURLにアクセスすると、このトップページが表示されるようになります。

---

以上、IBM Cloud上のマネージドOpenShift環境にて、各種コンテナをデプロイし、Drupalのインストールと初期設定をして、DrupalをOpenShift環境上で利用できるところまでの一連の手順についてご紹介させていただきました。

まだ、OpenShiftやIBM Cloudなどを、あまり触ったことの無い方にとって、何かのご参考になれば幸いです。

---
補足1：今回作成した環境（オブジェクト）を消したい（やり直したい）場合は、
・OpenShiftのコンソールで、管理者パースペクティブより、プロジェクトタブで、該当プロジェクト（上記では「my-drupal」）を選択し、プロジェクトを削除
・同じくコンソール上から、管理者パースペクティブより、ユーザー管理のサービスアカウントタブで、今回作成した「anyuid-user」を削除
・ローカルに作成した、各種Yamlファイルを削除
の３点を実施いただくと、作業開始前の状態に戻せるかと思います。

補足2：今後、この環境に対して、CI/CDサービスの追加・統合、データベース（PostgreSQL）のマネージド・サービス（DaaS）の利用するなど、より、IBM Cloudを活用する上でのステップ（手順）などをご紹介させていただく予定です。