はむはー!最近計算機には嬉しい気温になってきました。みなさん計算機はいかがお過ごしですか?
先月 Kubernetes クラスタを部内サーバーに構築したので、その話をします。
きっかけ
きっかけは部内 OpenStack クラスタが崩壊したことです。OpenStack かぁ〜立て直すのめんどくさいね〜、って話しているうちに何故か Kubernetes を立てる話が盛り上がり、Kubernetes クラスタを立てることになりました *1。
いろいろ検討
Kubernetes を立てると一言で言っても、 Node の立て方や使うコンポーネント、YAML の管理方法など決めなければいけないことは多岐に渡ります。
まずは要検討事項をまとめた Issue を作りました。
大量です。ここから一つ一つ検討していきました。
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 ツールとして、 FluxCD と ArgoCD を検討しました。
実際に使ってみた結果、FluxCD は全ての設定を Kubernetes Object として管理できて筋が良いこと、また ArgoCD よりもコンポーネントが少なく軽量で分かりやすいことから FluxCD を使うことにしました。
ユーザー管理
多人数で Kubernetes クラスタを触るので、ユーザー管理は必須です。KMC では部員一人一人に UNIX アカウントが発行されているので、それと連携できるようにしました。
Kubernetes には OIDC を通じて認証を行うことができる機能があります。部内に OIDC provider として dex を立ててバックエンドを部内の LDAP に向けるようにし、Kubernetes と連携しました。各々の kubectl が JWT を取得するための設定には kube-login を使っています。
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 }}"
Persistent Volume
多くのクラウドでは Persistent Volume としてブロックストレージが提供されますが、部内サーバーにはそのような環境はありません。ただ、そのために Rook・Ceph といった分散ストレージシステムを管理するのは大変で、もっと気軽な選択肢を探すことになりました。
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 の突然死といったトラブルもなく平穏に動いています。
コンテナをバンバン立てたい・部内 Kubernetes クラスタを管理したい方はぜひ KMC に入部してください。ばいきゅー!