KMC活動ブログ

京大マイコンクラブの活動の様子を紹介します!!

部内サーバーに Kubernetes クラスタを立てました

はむはー!最近計算機には嬉しい気温になってきました。みなさん計算機はいかがお過ごしですか?

先月 Kubernetes クラスタを部内サーバーに構築したので、その話をします。

きっかけ

きっかけは部内 OpenStack クラスタが崩壊したことです。OpenStack かぁ〜立て直すのめんどくさいね〜、って話しているうちに何故か Kubernetes を立てる話が盛り上がり、Kubernetes クラスタを立てることになりました *1

いろいろ検討

Kubernetes を立てると一言で言っても、 Node の立て方や使うコンポーネントYAML の管理方法など決めなければいけないことは多岐に渡ります。

まずは要検討事項をまとめた Issue を作りました。

f:id:nonylene:20211014012556p:plain
数々の要検討事項

大量です。ここから一つ一つ検討していきました。

Node の立て方

Node を立てる、すなわち kubelet のインストールをどうするか、という問題です。

kubelet を自分で入れて Hard way する(腕力派)、kubeadm を使う(公式ドキュメント派)、Rancher を使う(マネージド派)、OpenShift を使う(赤帽派)がありましたが、机上で検討した結果 kubeadm を使うことにしました*2

YAML の管理

Kubernetes では YAML を使ってリソースの定義を行いますが、その定義を何のツールを使って行うか、またどのようにデプロイするかを考える必要があります。

YAML を生成するツール

Kustomize と cdk8s を検討し、Kustomize にしました。

Kustomize を使って構築していると色々機能が欲しくなって高い表現力を持つ cdk8s に手を出してみたのですが、cdk8s は

  • ドキュメントや Issue などのナレッジが少ない
  • TypeScript でオブジェクトを書くより YAML のほうが書きやすい・見やすい
  • 全員が Kubernetes だけでなく TypeScript + cdk8s に慣れる必要があり敷居が高い

といったデメリットがあり、シンプルな Kustomize で我慢やっていくことにしました*3

なお、ingress-nginx など Helm で入れれるものは後述の GitOps ツールを通じて Helm でインストールしています。

デプロイ

レポジトリから実際のクラスタにデプロイする GitOps ツールとして、 FluxCDArgoCD を検討しました。

実際に使ってみた結果、FluxCD は全ての設定を Kubernetes Object として管理できて筋が良いこと、また ArgoCD よりもコンポーネントが少なく軽量で分かりやすいことから FluxCD を使うことにしました。

f:id:nonylene:20211014142245p:plain
Overview

ユーザー管理

多人数で Kubernetes クラスタを触るので、ユーザー管理は必須です。KMC では部員一人一人に UNIX アカウントが発行されているので、それと連携できるようにしました。

Kubernetes には OIDC を通じて認証を行うことができる機能があります。部内に OIDC provider として dex を立ててバックエンドを部内の LDAP に向けるようにし、Kubernetes と連携しました。各々の kubectl が JWT を取得するための設定には kube-login を使っています。

f:id:nonylene:20211014142103p:plain

Event 通知

Kubernetes 上の Event の通知には kubernetes-event-exporter を使っています。柔軟な通知のフィルタリングやルーティングができること、また投稿する JSON も自分で設定できることが Good point でした。

下のような設定で Slack に投稿しています。全て手書き!

      receivers:
        - name: "slack"
          webhook:
            endpoint: "${SLACK_WEBHOOK_URL}"
            layout:
              channel: "#sysop"
              attachments:
                # Type is either Normal or Warning
                - color: '{{ if eq .Type "Normal" }}#326ce5{{ else }}#f4bd0b{{ end }}'
                  blocks:
                    - type: section
                      text:
                        type: mrkdwn
                        # *[{Kind}] {namespace}/{resource}*\n{message}
                        text: "*{{ with .InvolvedObject.Kind }}[{{ . }}] {{ end }}{{ .Namespace }}{{ with .InvolvedObject.Name }}/{{ . }}{{ end }}*\n{{ .Message }}"
                    - type: context
                      elements:
                        - type: mrkdwn
                          text: "*Type:* {{ .Type }} "
                        - type: mrkdwn
                          text: "*Reason:* {{ .Reason }}"
                        - type: mrkdwn
                          text: "*Count:* {{ .Count }}"

f:id:nonylene:20211014125602p:plain

Persistent Volume

多くのクラウドでは Persistent Volume としてブロックストレージが提供されますが、部内サーバーにはそのような環境はありません。ただ、そのために Rook・Ceph といった分散ストレージシステムを管理するのは大変で、もっと気軽な選択肢を探すことになりました。

f:id:nonylene:20211014140447p:plain
渋っている様子

NFS を Persistent Volume として使うのも、オンプレミス環境ではよく聞きます。KMC にも NFS サーバーがあるので検討しましたが、KMC の NFS は HDD で構成されており読み書きが遅かったり、MySQL といった大量に fs に読み書きするプログラムで NFS を使うのはなぁ…となったりでイマイチでした。

そこで、Node に直接 Persitent Volume を置くようなシンプルなものを探した結果、TopoLVM を使うことにしました*4。TopoLVM は Node 上で Logical Volume を切り出し、それを Persistent Volume として提供してくれるものです。本当にシンプルな Logical Volume なので、何が起こっているか分かりやすく、管理もしやすい!

Node 間の Persistent Volume の移動が面倒*5ですが、Node の置き換えはそう起こらないということもあり、妥協することにしました。軽い読み書きやバックアップには既存の NFS を使ってもらうようにしています。


この他にも約2ヶ月に渡る様々な検討と構築を経て、クラウドと比べても不便なく使えるような Kubernetes クラスタを立てることができました :tada:。今の所 Node の突然死といったトラブルもなく平穏に動いています。

f:id:nonylene:20211014021237p:plain

コンテナをバンバン立てたい・部内 Kubernetes クラスタを管理したい方はぜひ KMC に入部してください。ばいきゅー!

*1:OpenStack クラスタは崩壊したままです

*2:Rancher でも良かったけど、ユーザー管理周りで部内の LDAP と相性が悪かった

*3:Kustomize は Kustomzie で辛いところは多々ありますが、分かりやすいし迷わないのは良いと思います

*4:他には local-path-provisioner や OpenEBS 配下の LVM プラグイン、Piraeus といったものがありました。機能とシンプルさのバランスから TopoLVM を選びました。

*5:TopoLVM にそのような機能はないので自分でなんとかする必要がある