Red Hat OpenShift Dev SpacesとGitLabを使用してプライベートな開発環境をサクッと構築する

Red Hatでサポートをしている石川と申します。本記事は、OpenShift Advent Calendar 2022 の11日目です。

# はじめに

開発をしていると、メンバー間のローカル環境の差異が問題になり、開発環境を統一できたらなあ〜と考えたことありますよね。私はあります。そんな時、クラウドIDEの存在を知って、「夢のようなツールだなあ」と感じたものです。

OpenShiftにはクラウドIDEの機能があります。今回はそんなRed Hat OpenShift Dev Spacesを触ってみたいと思います。

# Red Hat OpenShift Dev Spacesとは

Red Hat OpenShift Dev Spacesは、ブラウザベースの統合開発環境(IDE)です。以前Red Hat CodeReady Workspacesと呼ばれていた製品が名前を変え、Operatorとしてリリースされたものですが、さらに元を辿ると[Eclipse Che](https://www.eclipse.org/che/docs/stable/overview/introduction-to-eclipse-che/)というオープンソースプロジェクトをベースとしています。 `CheCluster` というAPI名などにその痕跡が見られます。

Operatorとなったことで、OpenShiftを利用しているユーザーであれば誰でもすぐに利用を開始できるようになりました。Red Hat OpenShift Dev Spacesを使う利点は大まかに以下のようなものです。

- あらかじめ定義された設定でワークスペースを作成するため、オンボーディングを高速にできるとともに、個々の開発者の開発環境を統一することができる
- Gitからクローンされるソースコードはブラウザからアクセスするワークスペース上で管理されるため、ローカル環境への複製が不要となる
- Visual Studio Code 拡張と互換性があり、VSCodeユーザーでも利用しやすい

このエントリでは、AWS上にOCPとGitLabをセットアップし、開発環境の構築を行ってみます。

# 大まかな流れ

- Operatorをインストールする
- CheClusterを作成する
- GitLabを構築する
- ワークスペースを作成する

# 環境

Red Hat OpenShift Container Platform 4.11.18
Red Hat OpenShift Dev Spaces 3.2
GitLab EE 15.6

# Operatorをインストールする

まずはDev Spaces Operatorをインストールします。インストール方法はシンプルで、 OperatorHubからRed Hat OpenShift Dev Spacesをインストールし、任意のnamespaceに `CheCluster` インスタンスを作成します。

![Screenshot from 2022-12-08 16-44-17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2959561/c64633d2-8bc8-3915-1e53-6a094a6de99b.png)

今回はdevspacesというnamespaceに`CheCluster` をインストールします。とりあえずデフォルト設定で作成します。

![Screenshot from 2022-12-11 17-35-48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2959561/0a3f2b7e-8c4b-bc11-7d10-bab2a9836407.png)

インストールしたnamespaceに以下のようなPodが作成されて来ます。

~~~
$ oc get pod -n devspaces
NAME                                   READY   STATUS    RESTARTS   AGE
che-gateway-68464f7f4c-p7m6w           4/4     Running   0          7m7s
devfile-registry-77c6d9fd7d-r6jt5      1/1     Running   0          7m36s
devspaces-74cfbfffbc-kdnv9             1/1     Running   0          7m1s
devspaces-dashboard-5959f6977f-8fmf7   1/1     Running   0          7m12s
plugin-registry-64fd7db55b-2ngkd       1/1     Running   0          7m18s
postgres-7f68cdb88d-xkssr              1/1     Running   0          8m12s
~~~

Red Hat OpenShift Dev Spacesのアーキテクチャは以下のようになっています。機能の根幹であるワークスペースの作成を担当するdevspaces Podは特に重要で、ワークスペースの作成がうまくいかない時などにはログを見てデバッグが必要な場合があります。

![devspaces-deployments-interacting-with-devworkspace.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2959561/20e988fd-3d78-9146-6017-3783f2a8548e.png)


# GitLabを構築する

[GitLabの公式ドキュメント](https://about.gitlab.com/install/)のインストール手順に従ってインストールします。今回は簡易的にAWSのEC2上に構築しますが、ネットワークに制限のある環境のGitサーバーでもOKです。

余談ですが、Red HatのOperator Catalogには最近Disconnected Infrastructure Featuresというフィルタが追加され、そのOperatorが非接続インストールに対応しているかどうかが判断できるようになりました。Red Hat OpenShift Dev Spacesも非接続インストールに対応しています。

https://catalog.redhat.com/software/operators/search?p=1&badges_and_features=Disconnected

なおGitLabはインストール時にLet's Encryptを利用して自動的に証明書がセットされるため、今回は問題となりませんでしたが、自己署名証明書を使用する環境ではワークスペースの作成時にリポジトリへのアクセスが失敗になる可能性があります。

そのような場合、以下のようにConfigMapにCA証明書をセットして `CheCluster` で信頼済み証明書として設定する手順が必要になります。

~~~
$ oc create configmap che-git-self-signed-cert \
  --from-file=ca.crt=<path_to_certificate> \  
  --from-literal=githost=<host:port> -n devspaces 

$ oc label configmap che-git-self-signed-cert \
  app.kubernetes.io/part-of=che.eclipse.org -n devspaces

$ oc edit checluster
spec:
  devEnvironments:
    trustedCerts:
      gitTrustedCertsConfigMapName: che-git-self-signed-cert
~~~

今回はGitLab上にdevspaces-sampleというリポジトリを作成します。Publicなリポジトリであれば認証情報の設定は不要ですが、Privateなリポジトリでは以下マニュアルの設定が必要となります。

https://access.redhat.com/documentation/en-us/red_hat_openshift_dev_spaces/3.2/html/user_guide/using-credentials-and-configurations-in-workspaces#using-git-credentials

簡単にソースコードを用意して、GitLabにpushします。Node.jsのExpressにしてみました。

~~~
$ mkdir devspaces-sample && cd devspaces-sample
$ npm init
$ npm install express --save
$ cat <<EOF> app.js
var express = require("express");
var app = express();

var server = app.listen(3000, function(){
    console.log("Ready");
});
app.get("/hello", function(req, res, next){
    res.send("Hello OpenShift!!");
});
EOF

$ git init 
$ git remote add origin https://shishika-gitlab-test.jp.apacshift.support/shishika/devspaces-sample.git
$ git branch -M advent-calendar
$ git add .
$ git commit -m "initial commit"
$ git push -uf origin advent-calendar
~~~

# ワークスペースを作成する

いよいよワークスペースを作成します。ブラウザから `	
https://devspaces.apps.<cluster name>.<base domain>` にアクセスします。

![Screenshot from 2022-12-12 04-34-08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2959561/7523158b-3a4e-d44d-477c-fc340bade4a5.png)

ワークスペースは "Import from Git" にGitリポジトリまたはWebサーバー上に公開されたDevfileのURLを指定して起動します。

Devfileとは、開発環境を抽象化して定義するファイルです。ソースコード、ランタイム、リモート作成するリポジトリや、コードを実行・ビルド・デバッグするために必要なコマンドを予めYAML形式で記述しておき、環境をまたいでも同一の開発環境を再現することが可能です。

また、Gitリポジトリにアクセスした際、ルートから `devfile.yaml` または `.devfile.yaml` を検出して読み込んでくれる、とあります。

早速先ほどのリポジトリにDevfileを作成します。Devfileは様々な設定が可能ですが、今回は最低限projectsの指定のみのDevfileとします。

~~~
schemaVersion: 2.1.0
metadata:
  name: nodejs
  version: 1.0.0
projects:
  - name: devspaces-sample
    git:
      remotes:
        origin: https://shishika-gitlab-test.jp.apacshift.support/shishika/devspaces-sample.git
      checkoutFrom:
        revision: advent-calendar 
~~~

GitリポジトリのURLを指定して "Create & Open" をクリックします。が、エラーとなってしまいました。

![Screenshot from 2022-12-12 02-38-06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2959561/1e6848f4-f39b-74d3-8648-2dc55e85c5d5.png)

devspaces Podのログを見ても、それらしいログは出力されていません。

~~~
$ oc logs devspaces-74cfbfffbc-kdnv9 -f
2022-12-11 09:18:16,476[nio-8080-exec-7]  [WARN ] [o.e.c.s.oauth.EmbeddedOAuthAPI 167]  - Unsupported OAuth provider github 
2022-12-11 09:18:16,477[nio-8080-exec-7]  [WARN ] [o.e.c.s.oauth.EmbeddedOAuthAPI 167]  - Unsupported OAuth provider bitbucket 
2022-12-11 09:18:17,708[nio-8080-exec-9]  [WARN ] [o.e.c.s.oauth.EmbeddedOAuthAPI 167]  - Unsupported OAuth provider github 
2022-12-11 09:18:17,708[nio-8080-exec-9]  [WARN ] [o.e.c.s.oauth.EmbeddedOAuthAPI 167]  - Unsupported OAuth provider bitbucket 
2022-12-11 09:18:18,403[nio-8080-exec-1]  [WARN ] [o.e.c.s.oauth.EmbeddedOAuthAPI 167]  - Unsupported OAuth provider github 
2022-12-11 09:18:18,404[nio-8080-exec-1]  [WARN ] [o.e.c.s.oauth.EmbeddedOAuthAPI 167]  - Unsupported OAuth provider bitbucket
~~~

こういう時は、 `CheCluster` を編集してcheServerをデバッグモードに変更します。証明書がうまく読み込めていないときなど、デバッグモードにすると原因がわかる場合があります。

~~~
$ oc edit checluster
spec:
  components:
    cheServer:
      debug: true
      logLevel: DEBUG
~~~

devspaces Podが再作成されます。

~~~
$ oc get pod
NAME                                   READY   STATUS    RESTARTS   AGE
devspaces-74cfbfffbc-kdnv9             1/1     Running             0          3s
devspaces-b778f9747-bbvgz              1/1     Terminating         0          10m
~~~

再度 "Create & Open" をクリックします。やはり同じエラーになってしまいます。

devspaces Podのログには以下のようなエラーが出ています。

~~~
2022-12-11 19:46:46,746[nio-8080-exec-4]  [DEBUG] [s.n.w.p.http.HttpURLConnection 141]  - sun.net.www.MessageHeader@6d63dad424 pairs: {null: HTTP/1.1 200 OK}{Server: nginx}{Date: Sun, 11 Dec 2022 19:46:46 GMT}{Content-Type: text/html; charset=utf-8}{Transfer-Encoding: chunked}{Connection: keep-alive}{Vary: Accept-Encoding}{Cache-Control: max-age=0, private, must-revalidate}{Content-Security-Policy: }{Etag: W/"f5921b1b99c851018b1ea99c19c1b06b"}{Permissions-Policy: interest-cohort=()}{Pragma: no-cache}{Set-Cookie: event_filter=all; path=/; Secure; SameSite=None}{Set-Cookie: _gitlab_session=83dbdd78d86b315af196f2ab9d28f3e3; path=/; expires=Sun, 11 Dec 2022 21:46:46 GMT; secure; HttpOnly; SameSite=None}{X-Content-Type-Options: nosniff}{X-Download-Options: noopen}{X-Frame-Options: SAMEORIGIN}{X-Permitted-Cross-Domain-Policies: none}{X-Request-Id: 01GM1BKGKTCX20HCAPD8M2H74H}{X-Runtime: 0.220917}{X-Ua-Compatible: IE=edge}{X-Xss-Protection: 1; mode=block}{Strict-Transport-Security: max-age=63072000}{Referrer-Policy: strict-origin-when-cross-origin}
2022-12-11 19:46:46,749[nio-8080-exec-4]  [DEBUG] [o.e.c.i.m.DefaultMethodInvoker 178]  - null
java.lang.reflect.InvocationTargetException: null
	at jdk.internal.reflect.GeneratedMethodAccessor160.invoke(Unknown Source)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
...
Caused by: org.eclipse.che.api.core.BadRequestException: Error occurred during creation a workspace from devfile located at `https://shishika-gitlab-test.jp.apacshift.support/shishika/devspaces-sample.git`. Cause: Neither of `apiVersion` or `schemaVersion` found. This is not a valid devfile.
	at org.eclipse.che.api.factory.server.ApiExceptionMapper.toApiException(ApiExceptionMapper.java:60)
	at org.eclipse.che.api.factory.server.urlfactory.URLFactoryBuilder.createFactoryFromDevfile(URLFactoryBuilder.java:141)
	at org.eclipse.che.api.factory.server.DefaultFactoryParameterResolver.createFactory(DefaultFactoryParameterResolver.java:89)
	at org.eclipse.che.api.factory.server.FactoryService.resolveFactory(FactoryService.java:104)
	... 46 common frames omitted
~~~

実はself-managedなGitLabやBitbucketはrawファイルの取得がうまくできないため、リポジトリのURLを指定するとうまくいかないようです。この場合、Devfileのraw URLを直接指定すればいい、とあります(他に良い方法ご存知の方は是非教えてください...)。

https://access.redhat.com/solutions/6974282

Devfileのraw URLを直接指定してみます。raw URLはGitLab上でファイルを開いて "Open raw" をクリックすると表示できます。

ワークスペースが起動し、ソースコードがクローンされていることが確認できました。

![Screenshot from 2022-12-12 05-01-25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2959561/e8bfc680-3842-74e4-461b-27750e3b9291.png)

# まとめ

Red Hat OpenShift Dev Spacesのインストールからワークスペースの起動までを見てきました。サクッと構築と言うわりには少し回り道をしてしまいましたが、ちょっとだけサポートっぽさも出せたので結果オーライとします(?)。

以上です。