【新人🐤構築】会津のハッカソンで使われた基盤をAzure k8sを使って構築したよ！

# はじめての きばんこうちく

1月ももう中旬ですが・・・
新年あけましておめでとうございます！

今回は！
**新人になって初めて一人で基盤構築をした話**です！

![KibanOverview.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730983/ceabab4b-8b64-4897-6c36-dcd5b0b0ccb2.jpeg)
↑今回構築した基盤の構成図

## はじめに

ある日

会津若松で行われるハッカソンに基盤を提供して欲しいというお話を頂きました。

👤「学習もかねて基盤構築をやってみましょうか」

ということで・・・
データ連携基盤を構築することになりました～！
(難しそうだけど、頑張ってやってみよう！😅)

### 「わたしたちのウェルビーイングのためのハッカソン」

福島県会津若松市で2018年度から毎年開催されているハッカソンです！

#### 2022年度 開発の例

🐟治療ではない睡眠支援アプリ「スイミーん」眠れぬ時間に投影する「うとうとアクアリウム」
🐱ネコのいまの気持ちがわかる！「どっちなの？」ボタン
👬【助け合いで自分の町を自慢の町に】well-beingなマップを共創するサービス「well-city」
👶赤ちゃんの行動ログで好奇心を見える化できる「赤ちゃん大喜利カメラ」
🌞「わたしとあなたの"ウェル"が、一目で分かる！」～まちの元気を可視化する街路灯～
などなど、個性的で面白い開発が行われていました！

#### ウェルビーイングって？

健康とは、病気でないとか、弱っていないということではなく、
肉体的にも、精神的にも、そして社会的にも、すべてが満たされた状態にあることをいいます。
（日本WHO協会訳）

ざっくりと「健康で仕事もプライベートも充実していて、幸せ」という状態と理解しています🤔

#### ハッカソンって？

一言でいうと「開発をするイベント」です！

他のイベントと違う特徴として
* 参加者同士でチームを結成(チームで参加することも可能)
* 限られた時間の中で開発を行う
* 開発したものについて発表し、競い合う

**<INS>技術力のあるなし関係なく</INS>、様々な背景を持った人と関わることが出来ます！**

ハッカソンの様子
![IMG_7498.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730983/2d34c9ca-6ccd-5fff-cab2-7d1eb9f6a9a1.jpeg)

チーム開発の様子
![IMG_0583.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730983/58472ec3-4043-367d-f070-fe1eb3807e65.jpeg)

夜は焚火を囲んでの団らん
![DSC_0418.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730983/85ece57f-13a3-e956-c2e9-b2e0bda3a743.jpeg)

おさんぽ会（市内散策）
![DSC05566.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730983/073ea152-61cf-e3d4-f614-136ab0f2fbc9.jpeg)


2023年度も開催を予定しているそうなので、**ご興味のある方は参加を検討してみては？**
[2022年度公式ホームページ](https://www.wbhackathon.com/)

### データ連携基盤とは

**スマートシティを実装する上で必要とされている要素**

なるほど？🤔
もう少し詳しく見ていきましょう！

![20220926_Denen_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730983/5006ba93-1732-1dc8-6227-ded6ff784fd8.png)
※デジタル田園都市国家構想のイメージ図

謎の大地にプロペラがついて空を飛んでいるような図なので、
一部では**ラピュタ**と呼ばれています。(バルスが怖いですが・・・)

赤い〇を付けた部分がデータ連携基盤の立ち位置になります。
ざっくり言えば、**データやサービス同士を連携して生活に役立つサービスを創出するための基盤**ということです！

例)防災×介護
位置データや避難所データを組み合わせて避難計画を策定するサービス×介護支援アプリ
→　災害発生時に支援が必要とされる人と支援する人をつなげることでより安全な暮らしを実現！
[参考URL](https://www.city.aizuwakamatsu.fukushima.jp/docs/2013101500018/files/magazine_3.pdf)

利用者からは見えない部分ですが、**新たなサービス創出の根本部分**ということになります！

データ連携基盤を構築する上で、国から***活用が推進されている技術***に***FIWARE***というものがあります！
これはEUで官民が連携し、オープンな場で開発が進められて作られたオープンソースのプラットフォームです！
以下にHPの情報を載せておきます。

https://www.fiware.org/

今回はこのFIWAREを使って基盤構築を進めていきます！

それでは早速作っていきましょう！

↓GitHubのリポジトリ(今回使ったyamlファイルを入れています！)

https://github.com/To-Ki-O/qiita-fiware-construct

## 利用した技術

以下を利用して基盤を構築しました！

* Azure AKS(Azure Kubernetes Service)

ハッカソン終了後も開発を続けるチームがあるという事で、
今後の拡張についても考え、しっかりとKubernetesで構築を行いました！

* FIWARE
    * Orion → データ登録側とデータ利用側の仲介機能(ブローカー機能)
    * MongoDB
    * QuantumLeap → 時系列データの管理と蓄積
    * CrateDB
    * Kong → APIキーによる認証

## 技術についての調査

* Azure AKS
公式のドキュメントやネット上の情報が充実しており、調査は順調に進みました！

* FIWARE
新しい技術ということで、ネット上に情報・事例が少なく・・・
主に公式のドキュメントを参考に構築を進めていきました！
(以下の構築編では公式にも明記されていない仕様に苦しめられたりもしています😭)

## Azure AKS構築

Azure AKSの構築はポータル上から行いました！

① Azureポータルにログイン
② ポータル上部にある検索バーで"Kebernetes サービス"と検索
③ 以下の設定でAKSを構築！

<details>

<summary>設定内容</summary>

サブスクリプション：任意
リソースグループ：任意
クラスター名：任意
地域：任意(私は"Japan East"で作成)
ノードサイズ：Standard A4 v2
スケーリング方法：手動
ノード数：3
※その他の設定はデフォルトで行いました！

</details>

Azureが構築してくれるまで少し時間はかかりましたが、問題なく完了しました！
※CLIからも構築出来ますが、Azure初心者だったので、ポータルから作成しました😋

## Orion,MongoDB,Kongの構築

この3つの構築は以下の記事を参考に構築しました！
ほとんど同じになってしまっているので、技術に明るい方は以下の記事を見た方がわかりやすいかもです😅
[FIWAREと画像処理の連携](https://qiita.com/nmatsui/items/f6fc66f12a365eafaf50)

https://qiita.com/nmatsui/items/f6fc66f12a365eafaf50

ここからはAzure CLIを用いて構築を行っています！

### 下準備

* 以下をインストールしました！
    * [Azure CLI](https://learn.microsoft.com/ja-jp/cli/azure/install-azure-cli)
    * [Kubernetes](https://kubernetes.io/ja/docs/tasks/tools/install-kubectl/)
    * [Helm](https://helm.sh/ja/)

<details>

<summary>① Azureにログイン</summary>

```
azure login --tenant TENANT_NAME
```

</details>

<details>

<summary>② Kubernetesにログイン</summary>

```
az aks get-credentials --resource-group RESOURCE_GROUP_NAME --name AKS_NAME --overwrite-existing
```

</details>

### MongoDB構築

<details>

<summary>① MongoDBはHelmを利用して構築</summary>

```
helm repo add azure-marketplace https://marketplace.azurecr.io/helm/v1/repo
helm repo update
helm install azure-marketplace/mongodb --name-template mongodb -f ./qiita-fiware-construct/MONGO_DB.yaml
```

</details>

「ってあれ・・・？」

「3台中、1台しかデプロイされないんですが・・・😅」

～十数分後～

「3台ともデプロイされている！」

デプロイに時間がかかる場合があるので、待ってみましょう！
先に以下のクラスタの設定をすることで、デプロイされることもあったりしました。

<details>

<summary>② MongoDBのクラスタ設定</summary>

```
kubectl run mongodb-client --rm --tty -i --restart='Never' --image marketplace.azurecr.io/bitnami/mongodb:4.4.15-debian-10-r2 --command -- \
  mongosh admin --host 'mongodb-0.mongodb-headless.default.svc.cluster.local:27017,mongodb-1.mongodb-headless.default.svc.cluster.local:27017,mongodb-2.mongodb-headless.default.svc.cluster.local:27017' \
  --eval 'rs.add("mongodb-1.mongodb-headless.default.svc.cluster.local:27017")'
```

```
kubectl run mongodb-client --rm --tty -i --restart='Never' --image marketplace.azurecr.io/bitnami/mongodb:4.4.15-debian-10-r2 --command -- \
  mongosh admin --host 'mongodb-0.mongodb-headless.default.svc.cluster.local:27017,mongodb-1.mongodb-headless.default.svc.cluster.local:27017,mongodb-2.mongodb-headless.default.svc.cluster.local:27017' \
  --eval 'rs.add("mongodb-2.mongodb-headless.default.svc.cluster.local:27017")'
```

```
kubectl run mongodb-client --rm --tty -i --restart='Never' --image marketplace.azurecr.io/bitnami/mongodb:4.4.15-debian-10-r2 --command -- \
  mongosh admin --host 'mongodb-0.mongodb-headless.default.svc.cluster.local:27017,mongodb-1.mongodb-headless.default.svc.cluster.local:27017,mongodb-2.mongodb-headless.default.svc.cluster.local:27017' \
  --eval 'rs.status().members.map(function(e) {return {name: e.name, stateStr:e.stateStr};})'
```

</details>

OrionとKongはレプリカ数を1にして構築しました！

理由としては以下の2つになります。
* ハッカソンで利用される基盤であり、そこまで高い可用性を求められていなかったため
* リソースを抑えるため

### Orion構築

~~記事としては面白くないけど~~　特に問題なく完了！
※ちなみに、MongoDBのデプロイがうまくいっていないと再起動を繰り返します

<details>

<summary>① Orionをデプロイ</summary>

```
kubectl apply -f ./qiita-fiware-construct/ORION_SERVICE.yaml
kubectl apply -f ./qiita-fiware-construct/ORION_DEPLOYMENT.yaml
```

</details>

### Kong構築

<details>

<summary>① Kongをデプロイ</summary>

```
kubectl create -f https://bit.ly/k4k8s
kubectl -n kong scale deployments.v1.apps/ingress-kong --replicas=1
```

</details>

IPアドレスをそのまま晒すのは微妙だということで、ドメインを取得！

<details>

<summary>② DNS設定</summary>

Azureポータル上で"App Service ドメイン"と検索し、一意のドメイン名を所得！(人生初😋)
※ドメイン1つにつき、11.99米国ドルかかります

</details>

APIキーを使った最低限の認証を設定します！

<details>

<summary>③ Kongの設定</summary>

(i) HTTPS通信とするためにCert-managerをデプロイします。
```
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.8.2/cert-manager.yaml
```

(ii) 基盤を利用しようとする通信がKongを通過するように設定
```
az network dns record-set a add-record --resource-group DNS_RESOURCE_GROUP --zone-name "DOMAIN_NAME" --record-set-name "HOST_NAME" --ipv4-address "KONG_EXTERNAL_IP"
```

(iii) TLS証明書を取得
```
kubectl apply -f ./qiita-fiware-construct/CERTMANAGER_CLUSTERISSURE.yaml
```

(iv) HTTPS通信のみを許可するように設定
```
kubectl apply -f ./qiita-fiware-construct/KONG_INGRESS.yaml
```

(v) APIキーを使って通信する設定
```
kubectl create secret generic kong-keyauth --from-literal=kongCredType=key-auth --from-literal=key=API_KEY
kubectl apply -f ./qiita-fiware-construct/KONG_CONSUMER.yaml
kubectl apply -f ./qiita-fiware-construct/KONG_PLUGINS.yaml
```

(vi) Orionへの通信設定
* 今回は特にAPIに特に制限を設けない
* ホスト名の設定

```
kubectl apply -f ./qiita-fiware-construct/ORION_INGRESS.yaml
```

</details>

## QuantumLeap,CrateDBの構築

### QuantumLeap構築

Orionの構築を参考にしてyamlファイルを作成し、デプロイ

<details>

<summary>Quantumleapをデプロイ</summary>

デプロイを行う
```
kubectl apply -f ./qiita-fiware-construct/QUANTUMLEAP_SERVICE.yaml
kubectl apply -f ./qiita-fiware-construct/QUANTUMLEAP_STATEFULSET.yaml
```

QuantumLeapへの通信設定
* APIはGETのみを許可
* ホスト名を設定

```
kubectl apply -f ./qiita-fiware-construct/QUANTUMLEAP_INGRESS.yaml
```

</details>

### CrateDB構築

ここが最も大変だった構築です😭

「Helmを使って1発構築しちゃおう！」
→ 見つかった使えそうなHelmチャートは2つ！

1つ目　外部から入ることのできるポートを開放してしまうため、今回の構築に合わない

https://artifacthub.io/packages/helm/hmdmph/cratedb

2つ目　デプロイ後、何度も再起動を繰り返す(原因不明)

https://artifacthub.io/packages/helm/crate/crate

2つ目はよく見たら、versionが0.2.0でしたね😅

結局、自分でyamlファイルを書きました(笑)

<details>

<summary>CrateDBをデプロイ</summary>

```
kubectl apply -f ./qiita-fiware-construct/CRATEDB_SERVICE.yaml
kubectl apply -f ./qiita-fiware-construct/CRATEDB_DEPLOYMENT.yaml
```

</details>

CrateDBを複数台で冗長化したかったのですが、クラスター化をする必要がありました。
しかし、クラスター化をするために設定が少々ややこしく、手間がかかってしまいます🤔

今回はハッカソンでの需要と構築の手間を考えて1台の構成で進めることにしました。

## 時系列データを挿入するための設定

QuantumLeapへ時系列データを直接挿入することは基本的にはないようです。
Orionを通じて、データ挿入をするため、以下の設定を行います！

<details>

<summary>OrionへのSubscription設定</summary>

```
curl -v localhost:1026/v2/subscriptions -s -S -H 'Content-Type: application/json' -X POST -d @ ./qiita-fiware-construct/SUBSCRIPTION_SETTING.json
```

</details>

※データの取り出しについての注意事項
QuantumLeapにデータを挿入する際にOrionがデフォルトで"fiware-ServicePath: /"と設定されます！
**fiware-ServicePathを指定せずにデータ取得を試みても、何も見つかりません！**
公式のドキュメントにも明記されておらず、構築に問題があると思い、何度も何度も見直ししていました・・・😪

### 具体的な利用方法についてのマニュアルを作成！

[FIWARE使い方](https://github.com/To-Ki-O/fiware-manual)

## おわりに

今回はチームメンバーに助けて頂くこともありましたが、
基本的には一人で新しく、情報の少ないFIWAREを使った基盤の構築を行いました。

技術以外の部分で学ぶことも多く、とても良い経験となりました！
今年度末にまとめたものを記事として投稿予定ですので、お楽しみに😉
[(今年度末に投稿予定)]()

この記事がデータ連携基盤を活用しようとしている方の助けになれれば幸いです。

ありがとうございました！