Jujuを使用してOracle Cloud Infrastructure上にKubernetes Clusterを構築する

# はじめに

Oracle Cloud Infrastructure(OCI)でKubernetes Clusterを使いたい場合、Oracle Container Engine for Kubernetes(OKE)を使用する方法があります。
しかしながら、これを書いている現時点ではOKEを使用した場合、一部できない事があります。
具体的には、Kubernetesのmasterが見えないのでNodePortに割り当てるポートの範囲をいじれなかったり、GPUインスタンスをworkerとして使用する事ができないという事があります。
こういった事をやりたい場合には、現在のところOCIのComputeを利用して立ち上げたインスタンスの中で、Kuberenetes Clusterを構築する必要があります。
今の所、デプロイツール[Terraform](https://www.terraform.io/)を利用してKubernetes Clusterを立ち上げる方法がOracleから公開されています。

- [OracleのIaaS上にTerraformを使ってKubernetesクラスターを作る](https://qiita.com/hhiroshell/items/a5107a5ed136867602ca)
- [Terraform Installer for Kubernetes on Oracle Cloud Infrastructure](https://github.com/oracle/terraform-kubernetes-installer)

だったらTerraformを使えば良いのかも知れませんが、私はデプロイツールとして[Juju](https://jujucharms.com/)を利用した経験がありました。
そして、Jujuのドキュメントを読む限り、どうもOracle Cloudでも使えそうだったのでやってみたところ、色々とつまづいた部分がありました。
今回は、Jujuを利用してOracle Cloud上にKubernetes Clusterを立ち上げる場合の作業手順をつまづいた部分をふまえて書きます。

使用したJujuのversionは2.5.1です。
一応、Ubuntu 18.04とmacOSの両方で操作しました。

# JujuへのOracle Cloudの登録

現時点で最新のドキュメントは[コレ](https://docs.jujucharms.com/2.5/en/clouds-oci)だと思うので、これに従って作業を進めます。
JuJuでパブリッククラウドを利用する場合にはじめにやるのは、cloudの追加だと思います。
試しにインストール直後のJuJuで登録されているcloudを見ると以下のようになっています。

```shell
$ juju clouds
Cloud           Regions  Default          Type        Description
aws                  15  us-east-1        ec2         Amazon Web Services
aws-china             2  cn-north-1       ec2         Amazon China
aws-gov               1  us-gov-west-1    ec2         Amazon (USA Government)
azure                27  centralus        azure       Microsoft Azure
azure-china           2  chinaeast        azure       Microsoft Azure China
cloudsigma           12  dub              cloudsigma  CloudSigma Cloud
google               18  us-east1         gce         Google Cloud Platform
joyent                6  us-east-1        joyent      Joyent Cloud
oracle                4  us-phoenix-1     oci         Oracle Cloud Infrastructure
oracle-classic        5  uscom-central-1  oracle      Oracle Cloud Infrastructure Classic
rackspace             6  dfw              rackspace   Rackspace Cloud
localhost             1  localhost        lxd         LXD Container Hypervisor
```

oracleとかociが見えるので、OCIは使用できそうです。
ドキュメント(多分古い)によってはjuju add-cloudを実行するとメニューにoracleが出ると書いてありますが、
実際に実行して見ると以下のようになります。

```shell
$ juju add-cloud
Cloud Types
  lxd
  maas
  manual
  openstack
  vsphere

Select cloud type: oracle
Cloud type "oracle" not supported for interactive add-cloud.
```

メニューにはoracleが出ず、cloud typeにoracleを指定しても対話インターフェイスには対応していないと出ます。
ここは、以下のようなyamlファイルを作成してそれを読み込ませる事でcloudを作成しましょう。
使用するregionについては[ここ](https://docs.cloud.oracle.com/iaas/Content/API/Concepts/apiref.htm)や[ここ](https://docs.cloud.oracle.com/iaas/api/#/en/iaas/20160918/)にendpointが載っています。

oracle-cloud.yaml

```yaml
clouds:
  my-oracle-cloud:
    type: oci
    auth-types: [httpsig]
    regions:
      us-ashburn-1:
        endpoint: https://iaas.us-ashburn-1.oraclecloud.com
```

```shell
$ juju add-cloud my-oracle-cloud oracle-cloud.yaml
```

これでcloudへの登録はできました。
次はcloudに対応するcredentialを登録します。

まず、ドキュメントにのっとって以下のコマンドを実行して鍵ファイルを作成します。

```shell
$ mkdir ~/.oci
$ openssl genrsa -out ~/.oci/oci_ssl_key_private.pem -aes128 2048
$ chmod go-rwx ~/.oci/oci_ssl_key_private.pem
$ openssl rsa -pubout -in ~/.oci/oci_ssl_key_private.pem -out ~/.oci/oci_ssl_key_public.pem
$ openssl rsa -pubout -outform DER -in ~/.oci/oci_ssl_key_private.pem | openssl md5 -c
```

最後のコマンドでfingerprintが確認できます。
作成したoci_ssl_key_public.pemの方を、OCIのダッシュボードのUserのメニューからAPI Keyに登録します。
登録後、ダッシュボードからもfingerprintは確認できます。
そして、以下のようなyamlファイルを作成します。
尚、下記の例に載っている秘密鍵については[Oracleのドキュメント](https://docs.jujucharms.com/2.5/en/credentials)に例として載っているものです。

oc-cred.yaml(例)

```yaml
credentials:
  my-oracle-cloud:
    default-region: us-ashburn-1
    my-cracle-cloud-cred:
      auth-type: httpsig
      fingerprint: a3:57:81:9c:d2:d5:af:31:3b:73:1e:2b:a4:ae:96:ee
      key: |
        -----BEGIN RSA PRIVATE KEY-----
        Proc-Type: 4,ENCRYPTED
        DEK-Info: AES-128-CBC,AAAC919B21A2694027DBEB182593FBEC

        MIIEogIBAAKCAQEAoc9jtcvo49FWe3sOhS6c1ExkllNZ61vChsLmMhBCI1vMc8wu
        cMpNmYK1ZA+d2Mm5YWDwn4UrSTzyaFdAIesmRljfbYMGTLznI/nfQMa1hkmplF5Q
        xNPCdzs0afqfnubIyrvCKYfAsRzjCcs7C30n6PzG5WrKxzr1QNvAuvYgjd2oQuSY
        nAhDgdJDkA9UwJFgI1jE8EuoxjkvmyeL76ohe78IEjMzoBBvll/Vd3d8X/hCHt4b
        wkmn3B5+QzXIvYXGhaUoZrmG6V+tsk2H5voJj6TswDB8rqIa1SHbY81wIkMUxbD4
        ScAq8eq2/6ETXcoBULKCjmvyqekJHjT7NngbpwIDAQABAoIBAEEggheIDSK0/UQS
        EZQVYNYqMUo4HjcW5cL/PRvlY1lr92ycQAzxwC4LaArwJi49czn4lKEALp35w++v
        PoboaK1j0/n2BLEaT0YxqmQeFq4INBMdqxCt0tW+pKgLUffZF/RRgiLJGwuufstQ
        W2GSbF/gbgWk6B0sY85JJNebfRrb+qjp5Jz+5t5gNVzOwWWkPYoAKXPd9JHYPFAk
        JCUTloYdf16lBml+nZI7EGojXtHUpdF7KyYRVfXMfxBnaWpVHvoZBk5Vk5qL/boz
        N8W+YahFq9BELavYQ30CZQeWYoD2MaSCWv+WzfkER8YK5Onr+5CSU0lW9dqN6wuv
        LFozUgECgYEAy9vZb+hjn3otkEFvyCGg9wmGIs9Qro3UKJI/mGKQeL7K8sd5WsA6
        mbOkIDbK71ZG+iIfxDXLzRO1ZzPjAX3cReFZ9NFRHngX9xM92UP+icIJkM6m4ImN
        UcaGCZiF0LoKUTAkEw+5rpeudGcgNgaI41RKMUBLyQn5MFo3IAPaO4ECgYEAyzJN
        CqB4e+qJgmc29zKsSfvuofasDTmIMnOZW2ci+tiD/qiH/eJoKHK2F5yGV6/tB2iY
        kFSuzWEwu/Crl7seW6xPY+HYlGLD60ix1aRDEfR48bZqFqlIu7uowI9dp43aOmPU
        1YSgMj8UA+rVqHqrS6IX4iqGbEOuzq0a377qiycCgYA99oUQzsH5J1nSDxG68v3K
        GMr8qacMZ2+lJU7PMqZXDScCxD7Opr8pGME6SW1FciQAw36EVRWtL+BjjhBcw7TA
        SM7e6wCNElO4ddLGxzQHC0N9EFMIzMZ3pK/5arMRznp0Uv2kDZOSzefo2a+gvDu/
        XU9vyOtAIBft6n327TTYAQKBgEE3/OhbRzCmv8oeLNM87XW1qgtMLD72Z1OiLOfc
        e6q90efr2fJQOBQ7dVywvaHpco+9L7Krq4vWlXjdL4ZCCJVuAfFSLPy7kpyzMXkc
        Bvb9W9BiNz3cyd6PxdDTQFhNwbXdE2QQ9IYMHvV+62LvNInLFhVehtS7CKGHiCem
        lItJAoGAdnj8nJRFQCAyIGcYk6bloohXI8ko0KLYbHfQpN9oiZa+5crEMzcFiJnR
        X8rWVPCLZK5gJ56CnP8Iyoqah/hpxTUZoSaJnBb/xa7PCiMq1gBfSF8OYlCsRI0V
        semYTOymUHkZyWGMIhmdn6t1S9sOy2tYjiH6HqumwirxnD5CLDk=
        -----END RSA PRIVATE KEY-----
      region: us-ashburn-1
      pass-phrase: "ChimayBlue"
      tenancy: ocid1.tenancy.oc1..aaaaaaaanoslu5x9e50gvq3mdilr5lzjz4imiwj3ale4s3qyivi5liw6hcia
      user: ocid1.user.oc1..aaaaaaaaizcm5ljvk624qa4ue1i8vx043brrs27656sztwqy5twrplckzghq
```

ocidについては自分のダッシュボードから確認できます。

そして、以下のコマンドを実行してcredentialを登録します。

```shell
$ juju add-credential my-oracle-cloud -f oc-cred.yaml 
Credentials "my-oracle-cloud-cred" added for cloud "my-oracle-cloud".
```

これで準備完了です。

# bootstrapのデプロイ

credentialの登録が正しくできていれば、以下のコマンドでjuju-bootstrapのインスタンスやvcnが自動的に立ち上がります。
$OCID_COMPARTMENTはデプロイを行いたいcompartmentのocidをダッシュボードから取得してください。

```shell
$ juju bootstrap --config compartment-id=$OCID_COMPARTMENT my-oracle-cloud my-oracle-cloud-controller
```

デプロイが完了するまで少しかかります。

# Kubernetes Clusterのデプロイ

ここまで来れば、あとは簡単です。

せっかくなのでjuju guiでjujuのダッシュボードを開いて、そこから操作します。

```shell
$ juju gui
GUI 2.14.0 for model "admin/default" is enabled at:
  https://XXX.XXX.XXX.XXX:17070/gui/u/admin/default
Your login credential is:
  username: admin
  password: XXXXXXXXXXXXXXXXXXXXXXXXX
```

ブラウザでjuju guiコマンドで表示されたURLへアクセスします。
表示されるダッシュボード右上のSearchボックスからKubernetesを検索し、Kubernetes Coreをモデルに追加します。

<img width="1662" alt="スクリーンショット 2019-02-18 17.28.41.png" src="https://qiita-image-store.s3.amazonaws.com/0/226408/d12481f1-b327-e35b-1aae-79670c113062.png">

この状態で、右下のCommit changesボタンをクリックすれば、あとは勝手にKubernetes master x1、worker x1の最小のクラスタが構成されます。

# 問題点

現在、いくつかの問題点を確認しています。

### Kubernetes masterインスタンスのiptablesの設定がおかしい

クラスタ起動直後、Kubernetes masterインスタンスとの通信ができない状態になる現象を確認しています。
ssh以外のポートでの通信ができないので、juju sshでログイン->iptables --flushでポートのブロックを剥がしたら繋がりました。
自動構築後、手動で設定をいじる必要がありそうです。

### GPUインスタンスの自動作成ができない

Jujuのソースコードを見る限り、OCI上でGPUインスタンスを自動生成するインターフェースはあるのですが、
やってみたところ、どうしてもGPUを利用するinstance-type(OCIのComputeのShape)が404 not foundとなり、
その後、Jujuがこちらの操作を受け付けなくなる現象を確認しています。

GPUインスタンスを利用する場合は、以下のようにしてsshを使用して手動でマシンを追加するのが安全そうです。

```shell
$ juju add-machine ssh:user@XXX.XXX.XXX.XXX
```

今回は以上です。