Oracle Cloud Container Engine for Kubernetes(OKE)でGitpodを構築してみる

# はじめに

この記事は[Oracle Cloud Infrastructure #2 Advent Calendar 2020](https://qiita.com/advent-calendar/2020/oci2) の12月7日の記事となります。

この記事では、Oracle Cloud Container Engine for Kubernetes(OKE)を利用してGitpodを構築してみようと思います。

#[Gitpod](https://www.gitpod.io/docs/)とは

一言で言うとGitHubやGitLabなどと統合可能なWebIDE環境です。

GitHub上などではレポジトリからワンクリックでIDE環境として起動できる優れモノです。(UIはVSCodeに非常に近いです)

例えば、GitHub上では以下のようにGitpodのボタン(赤枠部分)があります。（画像は私の適当なレポジトリをスクリーンショットしたものです）
![スクリーンショット 2020-12-06 13.03.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40392/1af1e0a3-4826-e981-a253-302f0899bb21.png)

上記のボタンをクリックすると、以下のようなIDE環境が起動します。
![スクリーンショット 2020-12-06 13.07.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40392/bf16d71f-9bca-768d-6cdc-66df21f3d8e8.png)

Gitpodは、GoogleCloudインフラストラクチャ上の3つの異なるリージョンでホストされている複数のKubernetesクラスターで実行されているようです。

そして、なんとこのGitPodはセルフホスティングもできてしまいます！！！
なんていい時代なんでしょう！！

この記事では、このGitpodをOracle Container Engine for Kubernetes(OKE)上でセルフホスティングしてみたいと思います。

# Oracle Container Engine for Kubernetes(OKE)のプロビジョニング

これについては、いろんな記事を書いて頂いているので、ここでは割愛します。

[公式ハンズオンドキュメント](https://oracle-japan.github.io/paasdocs/documents/containers/common/)が参考になると思います。
※ハンズオンドキュメント手順の2~4あたりがOKEのプロビジョニングに関する手順です。

# Gitpodのインストール

ここからが本題です。

手順としては以下の順に進めていきます。

* helmテンプレートの編集
* TLS証明書作成
* デプロイ
* LoadBalancerとドメインの紐付け

それでは始めていきます。

## helmテンプレートの編集

Gitpodはhelmを利用してインストールします。

手順については、Gitpodの[公式ドキュメント](https://www.gitpod.io/docs/self-hosted/latest/install/install-on-kubernetes/)を参考にします。

まず、[Gitpod self-hosted repository](https://github.com/gitpod-io/self-hosted)をforkします。

forkしたレポジトリをベースにソースコードを編集していきます。

編集するファイルは`values.yaml`です。

編集する内容は以下の項目です。

* ドメイン：この記事では`sample.jp`とします
* OAuthプロバイダーのクレデンシャル(GitHub/GitLabなど)：今回はGitHubを利用します
    * clientId：取得方法は後述します
    * clientSecret：取得方法は後述します

ドメインは書き換えるだけなので、OAuthプロバイダーのクレデンシャルの取得方法を見ていきます。

今回はOAuthプロバイダーとしてGitHubを利用し、[公式ドキュメント](https://www.gitpod.io/docs/self-hosted/latest/install/oauth/)に従って実施していきます。

作成が完了すると、以下のように`Client ID`が表示されます(画像ではセキュリティ上マスクしています)ので、メモしておきます。
![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f34303339322f38366462376632392d363936352d316661652d613933662d6265313833636537353866622e706e67.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40392/cb579a72-0132-e730-82d4-1adbefdb8861.png)


最後にClient secretsを作成します。

`Generate a new client secret`をクリックすると以下のようにsecret(画像ではセキュリティ上マスクしています)が発行されます。
![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f34303339322f34393966303663652d633164622d366339372d643262392d3430663335316266393238352e706e67.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40392/278598db-509e-e5f1-04e2-54fb599500d1.png)


ここからは、`values.yaml`の内容を書き換えていきます。

編集する部分は、`hostname`、`clientId`、`clientSecret`、`settingsUrl`です。
それぞれ以下のように編集します。

* hostname：取得したドメイン名。今回は`sample.jp`を利用します。
* clientId：先ほどGitHubのOAuth Appsから取得した`Client ID`を入力
* clientSecret：先ほどGitHubのOAuth Appsから取得した`clientSecret`を入力
* settingsUrl：先ほどGitHubのOAuth Appsから取得した`Client ID`をURLの最後の部分に設定

※今回はOAuth ProviderをGitHubとした場合なので、その他のOAuth Providerを利用している方は公式ドキュメントの手順を参考に編集してください。

上記で設定した内容を基に書き換えると以下のようになります。(皆さんもご自身の情報で書き換えてください)

```yaml
gitpod:
  # This field must be set to your domain name. Leaving it set to its default value will result in
  # a non-functional installation.
  hostname: sample.jp

  # If you have a static IP that your domain resolves to, set it here.
  # Leaving this field set to its default value is fine. Kubernetes will assign you an IP address
  # during deployment.
  components:
    proxy:
      loadBalancerIP: null

  # Gitpod needs at least one auth provider to allow users to log in.
  # The auth providers below are examples only. Please change/remove them to fit your installation.
  authProviders:
  - id: "Example Github"
    host: "github.com"
    protocol: "https"
    type: "GitHub"
    oauth:
      clientId: "XXXXXXX"
      clientSecret: "XXXXXXX"
      callBackUrl: "https://sample.jp/auth/github/callback"
      settingsUrl: "https://github.com/settings/connections/applications/XXXXXXX"

  # RBAC is enabled by default. If your cluster does not use RBAC, set this flag to false so that
  # we do not attempt to install PodSecurityPolicies and the likes.
  installPodSecurityPolicies: true
```

## TLS証明書作成

Gitpodでは通信をSSL/TLS化する必要があるので、証明書を作成します。
今回はLet's Encryptを利用します。
証明書の作成は[この記事](https://qiita.com/sugimount/items/3f43c55141252f8f2968)を参考にします。

Let's Encrypt証明書が発行できたら、[公式ドキュメント](https://www.gitpod.io/docs/self-hosted/latest/install/https-certs)の手順に沿って証明書をforkしたレポジトリに取り込みます。

これで準備完了なので、いよいよGitpodをOKEにデプロイしていきます。

## デプロイ

デプロイはhelmを利用して行います。

```shell
helm repo add charts.gitpod.io https://charts.gitpod.io
helm dep update
helm upgrade --install $(for i in $(cat configuration.txt); do echo -e "-f $i"; done) gitpod .
```

デプロイには少し時間がかかります。

以下のように表示されれば正常にデプロイできていると思います。

```sh
[opc@oke-client self-hosted]$ helm upgrade --install $(for i in $(cat configuration.txt); do echo -e "-f $i"; done) gitpod .
Release "gitpod" does not exist. Installing it now.
NAME: gitpod
LAST DEPLOYED: Sun Dec  6 09:25:05 2020
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
[opc@oke-client self-hosted]$ 
```

あとは全てのPodが`Running`状態になるまで待ちましょう。

```sh
pod/dashboard-787788b5cc-6rltw           1/1     Running            0          2m4s
pod/image-builder-7d79d7b7bd-gv925       2/2     Running            0          2m4s
pod/messagebus-db89b9b5c-4q9cj           1/1     Running            0          2m4s
pod/minio-6845c586dc-sjwfk               1/1     Running            0          2m4s
pod/mysql-65c5b9f8f9-6h72l               1/1     Running            0          2m4s
pod/node-daemon-68jg6                    1/1     Running            0          2m4s
pod/node-daemon-6xphv                    1/1     Running            0          2m4s
pod/node-daemon-kh4k5                    1/1     Running            0          2m4s
pod/proxy-7d5499dd84-h8sqq               1/1     Running            0          2m4s
pod/registry-548ddd9768-8snzm            1/1     Running            0          2m4s
pod/registry-facade-55b58599df-wtrwj     1/1     Running            0          2m4s
pod/server-7bd598fbb6-d8bks              1/1     Running            0          2m4s
pod/theia-server-5d68fd5b8-vd548         1/1     Running            0          2m4s
pod/ws-manager-6594579447-rrthl          1/1     Running            0          2m4s
pod/ws-manager-bridge-79988d7b6f-886z9   1/1     Running            0          2m4s
pod/ws-manager-node-fmdnl                1/1     Running            0          2m4s
pod/ws-manager-node-g46ct                1/1     Running            0          2m4s
pod/ws-manager-node-gg2pl                1/1     Running            0          2m4s
pod/ws-scheduler-5fbc5d588c-m64bt        1/1     Running            0          2m4s
pod/ws-sync-4dh82                        1/1     Running            0          2m5s
pod/ws-sync-kkh7r                        1/1     Running            0          2m4s
pod/ws-sync-wz6wz                        1/1     Running            0          2m4s
```

## LoadBalancerとドメインの紐付け

全てのPodが`Running`になったら、プロビジョニングされたLoadBalancerとドメインの紐付けをします。

OCI LoadBalancerが既にプロビジョニングされているはずなので、確認します。

```sh
[opc@oke-client ~]$ kubectl get svc proxy
NAME                      TYPE           CLUSTER-IP      EXTERNAL-IP      PORT(S)                                 AGE
service/proxy             LoadBalancer   10.96.204.208   XXX.XXX.XXX.XXX   80:31080/TCP,443:31443/TCP              2m6s
```

次に、OCI LoadBalancerのIPアドレスに対してドメインを紐付けます。

OCIコンソールのDNS管理を開きます。
![スクリーンショット 2020-12-07 11.51.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40392/69ad4108-ec4d-ff78-e9c7-02f44427f342.png)


`ゾーンの管理`をクリックします。
![スクリーンショット 2020-12-07 11.51.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40392/1d6d7d80-dfeb-d2bd-834e-44d5a47ed576.png)


`パブリックゾーン`の`ゾーンの作成`をクリックします。
以下のようにドメイン(今回は`sample.jp`)を入力し、`作成`をクリックします。
![スクリーンショット 2020-12-07 11.51.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40392/b19737e5-357e-ec09-4ae1-8d6dd2543ec1.png)


ゾーンが作成されたら、Aレコードを以下のように追加します。
Gitpodを動作させるためにマルチドメインで紐付けます。
IPアドレスはプロビジョニングしたOCI LoadBalancerのIPアドレスです。(画像のIPアドレスは適当です)
![スクリーンショット 2020-12-07 11.39.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40392/886f8943-aa2a-1ab5-1c72-4c6aba2e7b2b.png)


レコードの追加が完了したら、`変更の公開`をクリックして変更内容を公開します。

最後にドメインを取得した事業者側で、ドメインのネームサーバを変更します。
変更方法はそれぞれの事業者に従ってください。

ネームサーバは作成したゾーン管理にデフォルトで記載されているネームサーバ(タイプが`NS`になっているレコード)です。
今回は以下になります。

* ns1.p68.dns.oraclecloud.net
* ns2.p68.dns.oraclecloud.net.
* ns3.p68.dns.oraclecloud.net.
* ns4.p68.dns.oraclecloud.net.

これで、ロードバランサーのプロビジョニングとドメインとの紐付けは完了です。

実際にドメインが紐付けされるまでには多少時間がかかります。


# 動作確認

ドメインが紐付けされたら、ドメインにアクセスしてみます。

https://sample.jp/

![スクリーンショット 2020-12-07 11.10.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40392/6ad157d7-ecc1-822a-8de2-7e86464c5cf8.png)

このように表示されれば無事にOKE上でGitpodが起動しています。

もしエラーが表示される場合は、OAuth Providerの権限が不足している可能性があるので、構築したGitpod環境からOAuth Providerにログインして`Access Control`から権限付与すると問題なく動作するかと思います。
権限は、以下のような画面で設定できます。
![スクリーンショット 2020-12-07 11.31.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40392/caf6da21-b618-422e-d6e8-2880435e14f9.png)


# まとめ

今回はOKE上にGitpodを構築してみました。ブラウザからIDEを操作できますし、無限の可能性がありそうですね！

もちろん、様々な拡張機能をインストールしてカスタマイズもできるので、ネットさえ接続できる環境があれば、いつでもどこでも自分だけのIDEにアクセスできます！！

今回はテスト用に起動していますが、実際にはDockerレジストリを外部化したり(今回は内部レジストリを利用しています)、独自のMySQLデータベース(今回は組み込み)を構築する形になると思います。

ぜひ、みなさんもOKEでGitpodを構築して遊んでみてください！！

# 参考記事 && Special Thanks!!!

Unleash developer productivity with Gitpod on Oracle Container Engine for Kubernetes
https://blogs.oracle.com/cloud-infrastructure/unleash-developer-productivity-with-gitpod-on-oracle-container-engine-for-kubernetes

Gitpod公式ドキュメント
https://www.gitpod.io/docs/self-hosted/latest/self-hosted/

Oracle Cloud LoadBalancer を Let's Encrypt で無料SSL化
https://qiita.com/sugimount/items/3f43c55141252f8f2968

Oracle Container Engine for Kubernetesハンズオンドキュメント
https://oracle-japan.github.io/paasdocs/documents/containers/common/