YellowfinをEKSのKubernetesでクラスター化してスティッキーセッションで動かす

# はじめに
YellowfinをKubernetesでクラスター化する際に公式wikiの[ロードバランシングを使用したKubernetesへの導入](https://wiki.yellowfin.co.jp/pages/viewpage.action?pageId=22708294)のページあたりを見て進めようと思ったのですが、ロードバランサーにTraefikを使っていたり、マニフェストの書き方がよくわからなかったりしたので、AWSのEKSを使ってどうにかYellowfinを動かせないか試してみたメモがこちらになります。

# 前準備
## kubectlのインストール
kubernetesを動かすための標準のコマンドをインストールします。これはAWSでkubernetesを動かさなくても必要です。
AWS公式のリンクですが、ここを参考にkubectlをインストールします。
[kubectl のインストールまたは更新](https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/install-kubectl.html)
公式にも書いてありますが、Amazon EKS クラスターコントロールプレーンとのマイナーバージョンの相違が 1 つ以内である kubectl バージョンを使用する必要があります。例えば、1.22 kubectl クライアントは Kubernetes、1.21、1.22 および 1.23 クラスターで動作します。

## eksctlのインストール
これはAWSのEKSでクラスターを作成する際に必要なコマンドをインストールします。
ここも公式のリンクを参考にインストールしていきます。
[eksctl のインストールまたは更新](https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/eksctl.html)

## リポジトリDBの作成
アプリ側はコンテナのイメージを使用しますが、リポジトリDBは事前にDBサーバーに設定しておく必要があります。そのため、一度はDBサーバーにリポジトリDBを構築するためにをYellowfinをインストールしなければなりません。[Yellowfinインストール手順](https://support.yellowfin.co.jp/hc/ja/articles/360001025428-Yellowfin%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E6%89%8B%E9%A0%86)を参考にインストールします。その後ファイルを展開するために一度起動し、終了させて準備OKです。
このインストール時に指定したリポジトリDBの設定を後のマニフェスト上に書くことになるので、Yellowfinインストールフォルダ/appserver/webApps/ROOT/WEB-INF/web.xmlの中のDBに関する部分をメモしておきます。


# とにかくクラスターを作成
[Amazon EKS の開始方法 – eksctl](https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/getting-started-eksctl.html)からクラスターを作成します。この時点で権限が足りない場合(ロールを作る必要があるかも)やkubeconfigを作成しなければならない場合は[クラスターへの IAM ユーザーおよびロールアクセスを有効にする](https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/add-user-role.html)や[Amazon EKS クラスターの kubeconfig ファイルを作成または更新する](https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/create-kubeconfig.html)などを参考にしてみてください。
他にもAWSCLIv2が必要だったような気がしますが、すみません、試行し始めて長くなっていたので覚えていません。。必要そうであれば[ここ](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/getting-started-install.html)を参考に入れてください。

# AWS Load Balancer Controller アドオンのインストール
Ingressを作成する際に、AWSのアプリケーションロードバランサーを使用したいので、AWSではアドオンとして提供されている[このアドオン](https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/aws-load-balancer-controller.html)をインストールします。これがなければAWSのロードバランサーが使えないらしく、存在を知らなかったらなかなかたどり着けなかったなという感じです。他のAzureやGoogleのクラスターではわかりませんが、AWSのクラスターでは必須の設定と言えそうです。

# マニフェストファイル
一番伝えたい情報がここです。とはいえ、重要な部分はIngressのannotationsの部分だけです。自分で試していてできなかった頃はアドオンを知らなかったことと、このスティッキーセッションを可能にするannotationの書き方がわからず苦戦していました。。
公式には、[ここのサイトの部分](https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.4/guide/ingress/annotations/#custom-attributes)に小さく載っていて、やっと記述を見つけることができました。
AWS以外の環境だとこの記述相当の設定を追加すればスティッキーセッションが可能なんじゃないかと思います。公式ではTraefikというリバースプロキシを使っていましたが、全く詳しくないためALBでの設定にしました。

```yaml:annotation.yaml
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-group-attributes: stickiness.enabled=true
    alb.ingress.kubernetes.io/target-type: ip
```

そして全てをひっくるめたマニフェストファイルがこちらです。
DeploymentのDBの設定部分は前にメモしたweb.xmlからそのまま引っ張ってきてください。その他アプリケーションの負荷によってはメモリやタスクの数などの調整をします。


```yaml:cluster.yml
---
### Yellowfin Cluster Service ###
apiVersion: v1
kind: Service
metadata:
  name: yellowfin-cluster
spec:
  type: NodePort
  ports:
    - protocol: TCP
      name: web
      port: 80
      targetPort: 8080
  selector:
    app: yellowfin-cluster
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: yellowfin-cluster-ingress-alb-instance
  annotations:
    kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-group-attributes: stickiness.enabled=true
    alb.ingress.kubernetes.io/target-type: ip
spec:
  rules:
    - http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: yellowfin-cluster
                port:
                  number: 80
---
### Yellowfin Cluster Deployment ###
kind: Deployment
apiVersion: apps/v1
metadata:
  namespace: default
  name: yellowfin-cluster
  labels:
    app: yellowfin-cluster

spec:
  replicas: 2
  selector:
    matchLabels:
      app: yellowfin-cluster
  template:
    metadata:
      labels:
        app: yellowfin-cluster
    spec:
      containers:
        - env:
          - name: APP_MEMORY
            value: "6144"
          - name: CLUSTER_PORT
            value: "7800"
          - name: JDBC_CLASS_NAME
            value: org.postgresql.Driver
          - name: JDBC_CONN_ENCRYPTED
            value: "false"
          - name: JDBC_CONN_PASS
            value: password
          - name: JDBC_CONN_URL
            value: jdbc:postgresql://test.jp:5432/yellowfinDB
          - name: JDBC_CONN_USER
            value: yellowfin
          - name: NODE_BACKGROUND_TASKS
            value: REPORT_BROADCAST_BROADCASTTASK,REPORT_BROADCAST_MIREPORTTASK,FILTER_CACHE,SOURCE_FILTER_REFRESH,SOURCE_FILTER_UPDATE_REMINDER,THIRD_PARTY_AUTORUN,ORGREF_CODE_REFRESH,ETL_PROCESS_TASK,SIGNALS_DCR_TASK,SIGNALS_ANALYSIS_TASK,SIGNALS_CLEANUP_TASK,COMPOSITE_VIEW_REFRESH,SIGNALS_CORRELATION_TASK
          - name: NODE_PARALLEL_TASKS
            value: 4,4,4,4,4,4,4,4,4,4,4,4,4
          name: yellowfin-cluster
          image: yellowfinbi/yellowfin-app-only:9.7.0
          ports:
            - name: web
              containerPort: 8080

---
```

# ログについて
このままの設定では、起動後のYellowfinログ等が消えてしまいかねないので、AWSの公式的にはFluentdを使用してログをどこかに退避させる運用をおすすめしていました。ただ、私はまだ検証できていません。YellowfinとしてはElastic Cloudを推しているらしいです。

# バージョンアップについて
コンテナ側についてはimageのバージョンを変えてあげればよいのですが、DBはDBで対象のバージョンを一致させて上げてあげないと正常な操作はできません。そのため、DBのほうはこれまで通りのアップデートファイルを使用して、DBのみのバージョンアップをする必要があります。公式のwikiだと[このページ](https://wiki.yellowfin.co.jp/pages/viewpage.action?pageId=2294334)になります。

```sh:DBverup.sh
java -jar yellowfin-20200701-update.jar -silent option.upgrade=database jdbcUser=Yellowfin_DB_Admin jdbcPassword=Yellowfin_DB_PASSWORD jdbcURL=jdbc:mysql://TARGET_DATABASE:3306/yellowfin

```

# 終わりに
なかなかKubernetesによる運用に疎かったせいかクラスターで動かすのもかなり遠回りしてしまった気がします。ただ、AWS上での構築ですがひとつ例ができたことはよかったのですが、きっとKubernetes詳しい方はもっと細かい設定を追加できるんだろうなと思います。ベストプラクティスがあったらぜひ教えていただきたいです！