1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【 OpenShift × Open Liberty × PostgreSQL】REST APIアプリケーション開発:前半

Posted at

はじめに

今回は、以下の構成で2時間で動く本格的なREST APIアプリケーションをIBM製品を用いて作成します。
前半と後半に分けて、実践していきます。

前半(本記事) 👈 今回はこちら!

  • OpenShift環境の準備
  • PostgreSQLのデプロイ
  • Nginxコンテナのデプロイと動作確認

後半(次回)

  • Open LibertyによるREST API実装
  • データベース連携
  • 完全なCRUD操作の実装

この記事で学べること

  • OpenShift上でのコンテナアプリケーションのデプロイ方法
  • PostgreSQLデータベースの構築と接続
  • OpenShiftリソース(Route、Service、Pod)の理解
  • エンタープライズグレードのインフラ構築の基礎
あなたのPC → OpenShift上のREST API → PostgreSQLデータベース

構成

全て一気にやろうとすると自分の理解が追いつかないので、まずはシンプルな構成で全体像を理解した上で(前半)、OpenLibertyを導入します(後半)。

最終的に構築するシステム

┌──────────────────────────────────────────────────┐
│ あなたのPC                                        │
│ • Postman / curl / ブラウザ                      │
└─────────────────┬────────────────────────────────┘
                  │ HTTPS
                  ↓
┌──────────────────────────────────────────────────┐
│ IBM TechZone - OpenShift Cluster (OCP-V)         │
│ IBM Cloud上で動作(完全無料)                     │
│                                                  │
│ ┌──────────────────────────────────────────────┐ │
│ │ Route (外部公開URL)                          │ │
│ │ https://liberty-api-xxx.apps.xxx.cloud       │ │
│ └─────────────────┬────────────────────────────┘ │
│                   ↓                              │
│ ┌──────────────────────────────────────────────┐ │
│ │ Open Liberty Pods (2個)                      │ │
│ │ • REST API (GET/POST/PUT/DELETE)             │ │
│ │ • Java 11 / Jakarta EE                       │ │
│ │ • 自動スケーリング                            │ │
│ └─────────────────┬────────────────────────────┘ │
│                   │ JDBC                         │
│                   ↓                              │
│ ┌──────────────────────────────────────────────┐ │
│ │ PostgreSQL Pod                               │ │
│ │ • 永続ボリューム (1GB)                        │ │
│ │ • 自動バックアップ                            │ │
│ └──────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────┘

前半編で構築する範囲

┌──────────────────────────────────────────────────┐
│ あなたのPC                                        │
│ • ブラウザ / curl                                │
└─────────────────┬────────────────────────────────┘
                  │ HTTPS
                  ↓
┌──────────────────────────────────────────────────┐
│ OpenShift Cluster                                │
│                                                  │
│ ┌──────────────────────────────────────────────┐ │
│ │ Route (外部公開URL)                          │ │
│ │ https://my-api-app-xxx.apps.xxx.cloud        │ │
│ └─────────────────┬────────────────────────────┘ │
│                   ↓                              │
│ ┌──────────────────────────────────────────────┐ │
│ │ HTTPD Pods (2個)                             │ │
│ │ • Apache HTTP Server 2.4                     │ │
│ │ • 静的コンテンツ配信                          │ │
│ │ • 環境変数でDB接続情報を保持                  │ │
│ └─────────────────┬────────────────────────────┘ │
│                   │ (接続準備のみ)               │
│                   ↓                              │
│ ┌──────────────────────────────────────────────┐ │
│ │ PostgreSQL Pod                               │ │
│ │ • PostgreSQL 13                              │ │
│ │ • データベース: apidb                         │ │
│ │ • ユーザー: apiuser                           │ │
│ │ • 永続ボリューム: 1GB                         │ │
│ └──────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────┘

前半の手順概要

所要時間

ステップ1: TechzoneでOpenShift環境予約      30分 (+ 承認待ち 1-2日)
ステップ2: Openshift上でPostgreSQLデプロイ     5分
ステップ3: Openshift上でLibertyアプリデプロイ  10分

合計: 45分 (承認待ち除く)

ステップ1: OpenShift環境の予約

1.1 IBM TechZoneアカウント作成

TechzoneでOpenshift環境を予約します。
スクリーンショット 2026-01-14 17.23.33.png

ステップ2: PostgreSQLのデプロイ

2.1 OpenShift CLIのインストール

macOS

brew install openshift-cli

2.2 OpenShiftへのログイン

Openshiftへ、ocコマンドを使ってログインします。

oc login --token=sha256~xxxxx --server=https://xxxxx:6443

確認:

oc whoami
# 出力: IAM#your-email@example.com

oc version
# 出力: OpenShift Version: 4.x.x

2.3 プロジェクトの作成

# プロジェクト作成
oc new-project my-api-project

# 確認
oc project
# 出力: Using project "my-api-project"

スクリーンショット 2026-01-14 17.25.14.png
プロジェクト(namespaceと同意)が作成されました!

2.4 PostgreSQLのデプロイ

Openshift上で、PostgreSQLをデプロイしていきます。

# PostgreSQLをデプロイ(永続ボリューム付き)
oc new-app postgresql-persistent \
  -p POSTGRESQL_USER=apiuser \
  -p POSTGRESQL_PASSWORD=SecurePass123! \
  -p POSTGRESQL_DATABASE=apidb \
  -p VOLUME_CAPACITY=1Gi \
  -p POSTGRESQL_VERSION=13-el8

# デプロイ確認(起動まで1-2分)
oc get pods -w
# Ctrl+C で終了

# 起動完了の確認
oc get pods | grep postgresql
# 出力例: postgresql-1-xxxxx   1/1   Running   0   2m

スクリーンショット 2026-01-14 17.26.00.png
デプロイが確認できました。
「PostgreSQLのデプロイ、こんなに簡単に?」と思いIBM Bobに聞いてみたところ、Openshiftには、よく使うアプリケーションのテンプレが事前用意されていて、それを使うとデプロイができるようになっているようです。
ここでは、データベースサーバーを作るように、データベースアプリケーションスタック(複数コンポーネントの塊)をテンプレを使って作成し、DB機能を持たせています。

2.5 接続情報の確認

# Serviceを確認
# Serviceは、Podへのネットワークアクセスを提供する抽象化レイヤ。k8sでいうリソース。
oc get svc postgresql

# 出力例:
# NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
# postgresql   ClusterIP   172.30.113.76    <none>        5432/TCP   2m

接続情報の確認として、Serviceを確認します。Serviceリソースがあることで、Podが再起動してIPアドレスが変わっても、Serviceが固定のDNS名とIPが保たれるのですね!

スクリーンショット 2026-01-14 17.27.05.png

ステップ3: Libertyアプリケーションのデプロイ

3.1 Liberty Operatorのインストール

OpenShift Webコンソールで実行:

  1. OpenShift Webコンソールにログイン
    • URL: メールに記載
  2. 左メニュー "Operators""OperatorHub"
  3. 検索: "Open Liberty"
  4. "Open Liberty Operator" を選択
  5. "Install" をクリック
  6. 設定:
    • Installation Mode: All namespaces
    • Update Channel: stable
  7. "Install" をクリック
  8. インストール完了まで 2-3分 待機

スクリーンショット 2026-01-14 16.35.33.png

3.2 YAMLファイルを使用したデプロイ(推奨)

cat <<EOF | oc apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-api-app
  namespace: my-api-project
  labels:
    app: my-api-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: my-api-app
  template:
    metadata:
      labels:
        app: my-api-app
    spec:
      containers:
      - name: nginx
        image: image-registry.openshift-image-registry.svc:5000/openshift/nginx:latest
        ports:
        - containerPort: 8080
          protocol: TCP
        env:
        - name: DB_HOSTNAME
          value: "postgresql.my-api-project.svc.cluster.local"
        - name: DB_PORT
          value: "5432"
        - name: DB_USERNAME
          value: "apiuser"
        - name: DB_PASSWORD
          value: "SecurePass123!"
        - name: DB_NAME
          value: "apidb"
        resources:
          requests:
            cpu: 100m
            memory: 128Mi
          limits:
            cpu: 200m
            memory: 256Mi
---
apiVersion: v1
kind: Service
metadata:
  name: my-api-app
  namespace: my-api-project
spec:
  selector:
    app: my-api-app
  ports:
  - name: http
    port: 8080
    targetPort: 8080
  type: ClusterIP
---
apiVersion: route.openshift.io/v1
kind: Route
metadata:
  name: my-api-app
  namespace: my-api-project
spec:
  to:
    kind: Service
    name: my-api-app
  port:
    targetPort: http
  tls:
    termination: edge
    insecureEdgeTerminationPolicy: Redirect
EOF

参考: https://github.com/OpenLiberty/open-liberty-operator

3.3 デプロイの確認

# Podの状態を確認
oc get pods

# 出力例:
# NAME                          READY   STATUS    RESTARTS   AGE
# my-api-app-xxxxxxxxxx-xxxxx   1/1     Running   0          2m
# my-api-app-xxxxxxxxxx-xxxxx   1/1     Running   0          2m
# postgresql-1-xxxxx            1/1     Running   0          5m

新たなコンテナが作られました。起動まで 3-5分 かかります。
app=my-api-appで絞って確認できました。
スクリーンショット 2026-01-14 17.31.35.png

3.4 外部URLの取得

## 1.外部URL(RouteのURL)を取得
# RouteのURLを取得
oc get route my-api-app -o jsonpath='{.spec.host}'

# 出力例:
# my-api-app-my-api-project.apps.xxxxx.cloud.ibm.com

## 2.動作確認
# 環境変数に設定
export APP_URL=$(oc get route my-api-app -o jsonpath='{.spec.host}')

# アクセステスト
curl https://$APP_URL

# 期待される出力:
# Nginxのウェルカムページ

このコマンドによって、OpenShift内部のアプリケーションを外部からアクセスできるURLを取得しました。
外部URLをWebブラウザに貼ると、無事テストページが表示されました。
image.png

Routeとは?
OpenshiftでいうRouteとは、外部公開の入口となるリソースです。これがないと、外部からOpenshift内部へアクセスできなくなります。

┌─────────────────────────────────────────────────────────┐
│ あなたのPC(外部)                                       │
│ ブラウザ / curl                                         │
└──────────────────┬──────────────────────────────────────┘
                   │
                   │ ① インターネット経由でアクセス
                   │    https://my-api-app-xxx.apps.xxx.cloud.ibm.com
                   ↓
┌─────────────────────────────────────────────────────────┐
│ OpenShift Cluster(内部)                               │
│                                                         │
│  ┌────────────────────────────────────────────────┐    │
│  │ Route(外部公開の入口)                         │    │
│  │ Host: my-api-app-xxx.apps.xxx.cloud.ibm.com   │    │
│  │ TLS: edge(HTTPS終端)                         │    │
│  └──────────────────┬─────────────────────────────┘    │
│                     │                                   │
│                     │ ② 内部のServiceに転送             │
│                     ↓                                   │
│  ┌────────────────────────────────────────────────┐    │
│  │ Service: my-api-app                            │    │
│  │ Type: ClusterIP                                │    │
│  │ IP: 172.30.xxx.xxx(内部IPアドレス)            │    │
│  │ Port: 8080                                     │    │
│  └──────────────────┬─────────────────────────────┘    │
│                     │                                   │
│                     │ ③ Podに転送                       │
│          ┌──────────┴──────────┐                       │
│          ↓                     ↓                       │
│  ┌──────────────┐      ┌──────────────┐               │
│  │ Pod 1        │      │ Pod 2        │               │
│  │ HTTPD        │      │ HTTPD        │               │
│  │ Port: 8080   │      │ Port: 8080   │               │
│  └──────────────┘      └──────────────┘               │
│                                                         │
└─────────────────────────────────────────────────────────┘

一旦ここまでで、どういった全体像になっているか確認してみます!
以下で、「インターネットからアクセスして、アプリがデータベースを使う」という流れを、OpenShiftのリソースで実現しています。
ブラウザでアクセスすると入り口のRouteにアクセスがいって、Routeから振り分け係のService→実際にアプリけーっションが動く場所であるPodという流れです。

リソース 役割 例え

  • Route:外部からの入口 マンションの玄関
  • Service:振り分け係 受付・ホールスタッフ
  • Pod:実際に働く場所 部屋・厨房
  • PostgreSQL:データ保管 倉庫・図書館
┌─────────────────────────────────────────────────────────────┐
│ 外部(インターネット)                                       │
│ https://my-api-app-xxx.apps.xxx.cloud.ibm.com              │
└──────────────────────┬──────────────────────────────────────┘
                       │
                       ↓
┌─────────────────────────────────────────────────────────────┐
│ OpenShift Cluster                                           │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Namespace: my-api-project                               │ │
│ │                                                         │ │
│ │ ┌─────────────────────────────────────────────────┐    │ │
│ │ │ Route: my-api-app                               │    │ │
│ │ │ • Host: my-api-app-xxx.apps.xxx.cloud           │    │ │
│ │ │ • TLS: edge                                     │    │ │
│ │ └──────────────────┬──────────────────────────────┘    │ │
│ │                    │                                    │ │
│ │                    ↓                                    │ │
│ │ ┌─────────────────────────────────────────────────┐    │ │
│ │ │ Service: my-api-app                             │    │ │
│ │ │ • Type: ClusterIP                               │    │ │
│ │ │ • IP: 172.30.xxx.xxx                            │    │ │
│ │ │ • Port: 8080                                    │    │ │
│ │ │ • Selector: app=my-api-app                      │    │ │
│ │ └──────────────────┬──────────────────────────────┘    │ │
│ │                    │                                    │ │
│ │         ┌──────────┴──────────┐                        │ │
│ │         ↓                     ↓                        │ │
│ │ ┌──────────────┐      ┌──────────────┐                │ │
│ │ │ Pod 1        │      │ Pod 2        │                │ │
│ │ │ HTTPD        │      │ HTTPD        │                │ │
│ │ │ 10.129.x.x   │      │ 10.131.x.x   │                │ │
│ │ └──────┬───────┘      └──────┬───────┘                │ │
│ │        │                     │                         │ │
│ │        │  DB接続(環境変数)  │                         │ │
│ │        └──────────┬──────────┘                         │ │
│ │                   │                                    │ │
│ │                   ↓                                    │ │
│ │ ┌─────────────────────────────────────────────────┐    │ │
│ │ │ Service: postgresql                             │    │ │
│ │ │ • Type: ClusterIP                               │    │ │
│ │ │ • IP: 172.30.113.76                             │    │ │
│ │ │ • Port: 5432                                    │    │ │
│ │ │ • DNS: postgresql.my-api-project.svc.cluster... │    │ │
│ │ └──────────────────┬──────────────────────────────┘    │ │
│ │                    │                                    │ │
│ │                    ↓                                    │ │
│ │ ┌─────────────────────────────────────────────────┐    │ │
│ │ │ Pod: postgresql-1-44f9b                         │    │ │
│ │ │ • PostgreSQL 13                                 │    │ │
│ │ │ • IP: 10.131.0.91                               │    │ │
│ │ │ • Port: 5432                                    │    │ │
│ │ │ • Volume: /var/lib/pgsql/data                   │    │ │
│ │ └──────────────────┬──────────────────────────────┘    │ │
│ │                    │                                    │ │
│ │                    ↓                                    │ │
│ │ ┌─────────────────────────────────────────────────┐    │ │
│ │ │ PersistentVolumeClaim: postgresql               │    │ │
│ │ │ • Size: 1Gi                                     │    │ │
│ │ │ • Status: Bound                                 │    │ │
│ │ └──────────────────┬──────────────────────────────┘    │ │
│ │                    │                                    │ │
│ │                    ↓                                    │ │
│ │ ┌─────────────────────────────────────────────────┐    │ │
│ │ │ PersistentVolume                                │    │ │
│ │ │ • IBM Cloud Block Storage                       │    │ │
│ │ │ • 1GB                                           │    │ │
│ │ └─────────────────────────────────────────────────┘    │ │
│ │                                                         │ │
│ │ ┌─────────────────────────────────────────────────┐    │ │
│ │ │ Secret: postgresql                              │    │ │
│ │ │ • database-user                                 │    │ │
│ │ │ • database-password                             │    │ │
│ │ │ • database-name                                 │    │ │
│ │ └─────────────────────────────────────────────────┘    │ │
│ └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘

🔧 トラブルシューティング

問題1: Podが起動しない

# ログを確認
oc logs <pod-name>

# イベントを確認
oc describe pod <pod-name>

# リソース不足の場合
oc get nodes
oc describe node <node-name>

問題2: ImagePullBackOff エラー

症状:

NAME                          READY   STATUS             RESTARTS   AGE
my-api-app-xxxxxxxxxx-xxxxx   0/1     ImagePullBackOff   0          2m

原因:

  • Docker Hubのレート制限に達した
  • イメージが存在しない

解決方法:

# OpenShift内部レジストリのイメージを使用
# liberty-app.yaml のイメージを以下に変更:
# image: image-registry.openshift-image-registry.svc:5000/openshift/nginx:latest

# または、既存のデプロイメントを削除して再デプロイ
oc delete deployment my-api-app
oc apply -f liberty-app.yaml

image.png
自分はこの問題2のエラーにハマりました。既存のデプロイメントを削除して、再度デプロイしたら直りました。
一時的にErrorが出ているのは、ローリングアップデートで古いpodが削除されているからです。

さいごに

思ったより理解に時間がかかりましたが、Openshiftの理解が深まりました。特に、WebアプリケーションをデプロイするうえでOpenshiftがとる大まかな構成が新しく知れました。

現在はHTTPDのみで、REST APIはまだ実装されていません。次のステップでREST APIアプリケーションを実装する必要があります!

1
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?