WebLogic Server for OKEにアプリケーションをデプロイ

## はじめに
[前回](https://qiita.com/nonkyon/items/ef0fdf27e6f4b83d7e7d)はWebLogicからアプリケーションの抽出を行ってみました。
抽出されたファイルは以下の通りになります
 - アプリケーションそのもののアーカイブ
 - モデルファイル(WebLogic構成のメタデータ)
 - モデル内で利用する変数群をまとめたファイル

これらのファイルと、[WebLogic Server for OKE](https://docs.oracle.com/en/cloud/paas/weblogic-container/index.html)を利用すると、簡単にWebLogicアプリケーションのコンテナ化を行うことができます。

## WebLogic Server for OKEとは？
WebLogicのアプリケーションを簡単にコンテナ化して、k8s上で運用/管理ができるオファリングです。
Jenkinsによる多数のプリセットジョブを通じて運用するのが大きな特徴で、マネージドk8sクラスタの[OKE](https://www.oracle.com/jp/cloud/cloud-native/container-engine-kubernetes/)の上で動作します。
新規アプリケーションのデプロイももちろん可能ですが、基本的には既存アプリケーションの移行が主な用途になります。

## 前提
WebLogic Server for OKEの最新バージョンを利用します。
この記事は以下のようなバージョンの構成を前提としています。
- WebLogic Server for OKE 23.1.1
    - Oracle Linux 7.9
    - WebLogic Server 12.2.1.4
    - Kubernetes 1.24.1

また、WebLogic Server for OKEのプロビジョニングやドメインの作成に関しては完了しているものとします。
※プロビジョニング/ドメインの作成に関しては別の記事でまとめます。

## 基本的な流れ
1. モデルファイルの編集
1. WebLogic Server for OKE環境に各種ファイルをアップロード
1. `UpdateDomain`ジョブの実行

## モデルファイルの編集
まずはWebLogic構成のメタデータであるモデルファイルを編集します。
yaml内の`<>`で囲っている部分は任意のものに適宜読み替えてください。

#### 利用するモデルファイル
[前回](https://qiita.com/nonkyon/items/ef0fdf27e6f4b83d7e7d)取得した`source.yaml`を編集します。
``` source.yaml
domainInfo:
    AdminUserName: '@@PROP:AdminUserName@@'
    AdminPassword: '@@PROP:AdminPassword@@'
topology:
### 中略 ###
resources:
    JDBCSystemResource:
        <データソース名>:
            Target: <サーバ/クラスタ名>
            JdbcResource:
### 中略 ###
appDeployments:
    Application:
        <アプリ名>:
            SourcePath: wlsdeploy/applications/<WAR名>.war
            ModuleType: war
            Target: <サーバ/クラスタ名>
```
#### モデル内、一部フィールドの削除
`domainInfo`フィールドと`topology`フィールドを削除します。
``` source.yaml
resources:
    JDBCSystemResource:
        <データソース名>:
            Target: <サーバ/クラスタ名>
            JdbcResource:
### 中略 ###
appDeployments:
    Application:
        <アプリ名>:
            SourcePath: wlsdeploy/applications/<WAR名>.war
            ModuleType: war
            Target: <サーバ/クラスタ名>
```

#### Targetの編集
`appDeployments` -> `Application` -> `アプリ名` -> `Target`の値を`'<ドメイン名>-cluster'`にします。
**アンダースコアではなくてハイフンなので注意。**
``` source.yaml
resources:
    JDBCSystemResource:
        <データソース名>:
            Target: <サーバ/クラスタ名>
            JdbcResource:
### 中略 ###
appDeployments:
    Application:
        <アプリ名>:
            SourcePath: wlsdeploy/applications/<WAR名>.war
            ModuleType: war
            Target: '<ドメイン名>-cluster' #追加
```

#### JDBC接続情報の編集
Databaseの接続先に変更がある場合などはJDBC URLなどの変更が必要です。
今回はATPに接続してみようと思うので、[ドキュメント](https://docs.oracle.com/en/cloud/paas/weblogic-container/user/create-data-source-atp-database.html)を参考にして記述します。以下は`JDBCDriverParams`フィールドのみを記載しています。
``` (一部) source.yaml
        JDBCDriverParams:
          DriverName: oracle.jdbc.OracleDriver
          URL: '@@SECRET:@@ENV:DOMAIN_UID@@-datasource-secret:url@@'
          PasswordEncrypted: '@@SECRET:@@ENV:DOMAIN_UID@@-datasource-secret:password@@'
          Properties:
            user:
              Value: '@@PROP:JDBC.***DB.user.Value@@' #変更
            javax.net.ssl.keyStore:
              Value: /u01/shared/atp_wallet/keystore.jks #変更
            javax.net.ssl.keyStoreType:
              Value: JKS
            javax.net.ssl.keyStorePassword:
              Value: '@@SECRET:@@ENV:DOMAIN_UID@@-keystore-secret:password@@'
            javax.net.ssl.trustStore:
              Value: /u01/shared/atp_wallet/truststore.jks #変更
            javax.net.ssl.trustStoreType:
              Value: JKS
            javax.net.ssl.trustStorePassword:
              Value: '@@SECRET:@@ENV:DOMAIN_UID@@-keystore-secret:password@@'
            oracle.net.ssl_version:
              Value: '1.2'
            oracle.net.ssl_server_dn_match:
              Value: true
            oracle.net.tns_admin:
              Value: /u01/shared/atp_wallet #変更
            oracle.jdbc.fanEnabled:
              Value: false
```
:::note info
JDBC URLなどの値はSecretから取得します。
Walletのダウンロードと併せて、後ほどSecretの作成は行います。
:::

#### `source.properties`の編集
`source.yaml`内に`'@@PROP:JDBC.<データソース名>.user.Value@@'`といった表記があります。
この書き方は、DBのスキーマなど**モデル内の変数を外に出して管理したい**場合に有用です。

``` (一例) souce.properties
JDBC.<データソース名>.user.Value=DEMO
```
ここでは、DBのスキーマを`DEMO`とした場合の例を記載しています。
`AdminPassword=`など空のままのフィールドがある場合は、使わないので削除してしまっても構いません。

## WebLogic Server for OKE環境に各種ファイルをアップロード
#### 移行ファイル群をファイル・ストレージに配置
移行ファイル群(source.zip/source.yaml/source.properties)をAdmin hostの`/u01/shared/`に配置します。
以下は一例ですが、SCPコマンドを利用する場合です。
```
$ scp -o ProxyCommand="ssh -W %h:%p opc@<Bastion_Instance_Public_IP>" \
source.* opc@<Admin_Instance_Private_IP>:/u01/shared/
```
`<Bastion_Instance_Public_IP>`と`<Admin_Instance_Private_IP>`はOCIの管理コンソールから確認ができます。
Computeインスタンスの一覧、もしくは
開発者サービス -> リソース・マネージャ -> ジョブ -> 対象のジョブ -> 出力 から確認が可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482527/64d2f574-8210-a0b5-555f-0db4546d7165.png)

#### WalletをWebLogic Server for OKEにダウンロード
AdminインスタンスにSSHログインします。`<private_key>`はプロビジョニング時に指定したものを利用してください。
```
$ ssh -i <private_key> opc@<Admin_Instance_Private_IP> \
-o ProxyCommand="ssh -W %h:%p -i <private_key> opc@<Bastion_Instance_Public_IP>"
```
SSHでログインしたら、以下のコマンドを実行してください。`<Walletパスワード>`は任意のもので構いません(後で利用します)。
```
$ python /u01/scripts/utils/download_atp_wallet.shutils/oci_api_utils.py <ATPのOCID>
 <Walletパスワード> /u01/shared/atp_wallet
```

## `UpdateDomain`ジョブの実行
#### DB接続用Secretの作成
アプリケーションをデプロイする前に、DB接続のためのSecretを作成します。
以下のコマンドを実行します。
```
$ kubectl create secret generic <ドメイン名>-datasource-secret \
--from-literal=password=<DBパスワード> \
--from-literal=url=jdbc:oracle:thin:@<ATPの接続サービス名> \
-n <ドメイン名>-ns
```
`<ATPの接続サービス名>`は`demodb_tp`のような表記になるはずです。
```
$ kubectl create secret generic <ドメイン名>-keystore-secret \
--from-literal=password=<Walletパスワード> \
-n <ドメイン名>-ns
```
#### Jenkinsコンソールで`UpdateDomain`の実行
コマンドラインツールを使用して、SOCKSを利用したダイナミックフォワードを行います。
これを行うことで、端末のブラウザからk8sクラスタ内のJenkinsコンソールにアクセスが可能になります。
```
$ ssh -D 1088 -i <SSH鍵> opc@<Bastion InstanceのパブリックIP>
```
SOCKSの利用には、ブラウザ単位でSOCKSの設定ができるFireFoxが非常に便利です。
設定 -> ネットワーク設定 -> 接続設定 で設定画面が開けるので、以下のように設定します。
- `手動でプロキシーを設定する` を選択
- `SOCKSホスト`に`localhost`
- `ポート`にコマンドで指定した`1088`を指定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482527/ca568d68-36a6-fb68-7595-e13d4f146830.png)

SOCKSの設定を行ったFireFoxからJenkinsのコンソールにアクセスします。
URLは`http:///<Internal LBのIP>/jenkins/`です。
`<Internal LBのIP>`はOCIの管理コンソールから確認ができますし、`kubectl`を使った確認も可能です。
`<domain>-internal`の`EXTERNAL-IP`がその値です。
```
$ kubectl get svc -n wlsoke-ingress-nginx
NAME               TYPE           CLUSTER-IP     EXTERNAL-IP       PORT(S)         AGE
<domain>-internal  LoadBalancer   **.**.***.**   <ここの値>          80:*****/TCP    13d
<domain>-external  LoadBalancer   **.**.***.**   ***.***.***.***   443:*****/TCP   13d
```
ユーザ名: admin / パスワード: <ドメイン作成時に指定したパスワード> でログインします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482527/36d0c25a-ffec-33e4-1e92-285410c3d386.png)

`update domain`ジョブから`パラメータ付きビルド`を選択します。
パラメータは以下のように入力し、「ビルド」ボタンをクリックします。
- Domain_Name : ドメイン名
- Archive_Source : Shared File System
- Archive_File_Location : /u01/shared/source.zip
- Domain_Model_Source : Shared File System
- Model_File_Location : /u01/shared/source.yaml
- Variable_Source : Shared File System
- Variable_File_Location : /u01/shared/source.properties
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482527/f9d91b7a-2590-fb37-3901-4c8ac9ca79a7.png)

あとはビルドが完了するのを待ちましょう。

## 環境の確認

アプリケーションはExternal LBのExternal-IPを使ってアクセスができます。
`https://<External-IP>/<context-root>`

#### pod
WebLogicのpodが確認できます。例えば`wke1`という名前のドメインを作っていると以下のようになります。
```
$ kubectl get pod -n wke1-ns
NAME                        READY   STATUS    RESTARTS   AGE
wke1-wke1-adminserver       1/1     Running   0          15h
wke1-wke1-managed-server1   1/1     Running   0          15h
wke1-wke1-managed-server2   1/1     Running   0          15h
```

#### 管理コンソール
`http:///<Internal LBのIP>/<ドメイン名>/console`でWebLogicの管理コンソールにアクセスすることができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482527/8856276a-7673-39d8-8d8e-86a4d4f2501a.png)

## まとめ
今回はWebLogic Server for OKEを使って、Kubernetesなどをあまり意識せずにアプリケーションをコンテナ化することができました。
実際に、Jenkinsのプリセットジョブではふんだんに[WebLogic Kubernetes Toolkit](https://docs.oracle.com/en/middleware/fusion-middleware/weblogic-server/kubernetes_toolkit.html)が使われていますが、それらのツール群もあまり意識する必要がありません。
環境のセットアップ含め、WebLogicのコンテナ化を比較的簡単に実現ができますので、ご興味があればぜひやってみてください。

## 参考資料
https://docs.oracle.com/en/cloud/paas/weblogic-container/index.html
https://apexapps.oracle.com/pls/apex/dbpm/r/livelabs/view-workshop?wid=721