kubernetes
Z LabDay 5

自宅サーバを Kubernetes を使って自宅クラスタにしてみた


はじめに

一家に一台 Kubernetes クラスタがある時代がやってきました。Z Lab Advent Calendar 2018 の 1日目 では、@superbrothers がインスタ映えするクラスタの作り方を記事にしていました。そこで今度はより実践的に Kubernetes クラスタで自宅サーバを組もうと思った場合、どのような構成になるかを紹介します。


はじめに その2

最初の会社に入社して、最初のボーナスで買ったのは自宅サーバ用に VIA C3 がオンボードで乗った Mini-ITX のマザーボードだったことを思い出す今日この頃。途中で Transmeta の Efficeon だったり、Pentium M だったり、 Mac mini に移行したり色々移り変わりはあったものの、自宅サーバを始めた頃のデータをそのまま引き継いで今にいたります。

直近の構成は Intel NUC のメモリ 16GB / Ubuntu Trusty のシングルホストで Docker でした。アプリケーション (Docker コンテナ) のデプロイには Ansible を使っていました。この構成で今まで自宅サーバで運用していた諸処の問題が解決するにいたり、 コンテナ素晴らしいな! と認識したものです。そこで今度はそれをクラスターで運用して、さらにコンテナのメリットを享受したくなったのでした。


基本方針


  • 全てを Kubernetes / コンテナで管理する。

  • ネットワークと電源の冗長化は諦める。(それ以外は冗長化する)

ステートフルなアプリケーション、Kubernetes それ自体を含めて Kubernetes で管理したいと思います。クラスタの運用は全て kubectl コマンドで!

と、言っても、自分の技術的な未熟のせいで結局この基本方針の対象外としたものは以下になります。


  • クラスターそれ自体の Manifest の置き場


    • クラスターが壊れた時の復旧ができないので、GitHub のプライベートレポジトリです…。



  • ルーター


    • 自作して kubelet でサービスを管理すれば行けそう。

    • とりあえずルータの監視は Prometheus と連携したい。



  • 自宅ネットワークの DHCP サーバ


    • これも Kubernetes 上に乗っけることは可能なんじゃ?と思わなくもないですが、既存のネットワークをいじるのが面倒なので、ルーター付属のものを使ってます。



  • スイッチングハブ


    • 自作するのも現実的ではないので。



他にもある気がしますが、とりあえず思いつくものは以上。


物理構成

図1.png

Kubernetes クラスタ自体は、Kubernetes のコントロールプレーンを配置するノード 3 台と、通常のワーカーノード 3 台、バックアップ用途の NFS+ZFS 専用ノード 1 台の計 7 台構成です。VM とかは介さず、ベアメタル。

概要は以下。


  • マスターロールノード (Container Linux by CoreOS stable)


    • Minnowboard Turbot

    • WesternDigital SSD Green 120GB



  • ワーカーロールノード (Container Linux by CoreOS stable)


    • ECS Liva Z

    • DDR3 SO-DIMM PC3-12800 16GB (8GB x 2)

    • WesternDigital SSD Blue 250GB

    • INTEL SSD 525 Series mSATA 120GB



  • バックアップロールノード (Ubuntu 18.04)


    • ASRock J3160-ITX

    • DDR3 SO-DIMM PC3-12800 8GB (4GB x 2)

    • WesternDigital SSD Green 120GB

    • WesternDigital Red 6TB x 3

    • WesternDigital Blue 6TB x 3



スクリーンショット 2018-11-30 16.48.11.png


マスターロールノード

そもそも自分がなぜ Kubernetes を自宅で飼ってみようと思ったかというと、きっかけは以下のツイートでした。

ここで使われている SoC が Minnowboard Turbot というボードである、ということを知ると、一瞬考えたのちに、6枚発注してました。結局、後々、他に良いボードがあること や、ワーカーに使うにはいささか貧弱であるということが発覚したため、とりあえずマスターノード用途に使うことにしました。

また、マスターノードは etcd を飼う計画であるため、ストレージには SSD を利用しています

IMG_1831.JPG


ワーカーロールノード

ECS の Liva Z, Pentium N4200 モデル にメモリ 16GB、そして内臓の eMMC で容量に問題が出たため M.2 2242 接続の SSD 120GB を増設して /var/lib/docker にマウントしてあります。また、Rook でデプロイした Ceph の osd を飼うノードを兼任するために、USB 3.0 接続の SSD も追加しました。Ceph を飼うには少し CPU のスペックが足りない感じがしなくはないです。

IMG_1832.JPG


バックアップロールノード

全てのデータを Ceph on Rook on Kubernetes で管理しても良いのですが、このうちどれかが壊れたら全てのデータが飛ぶんじゃないかと言う恐れから、バックアップ用途にディスクをHDD6台, システム用に SSD 1台積んだノードを追加しました。

IMG_5106.JPG

WesternDigital の Red 6TB x3, Blue 6TB x3 で raidz2 の構成で 21TB です。Kubernetes からは NFS で接続します。使っているマザーボードは ASRock の J3160-ITX なので SATA の口が微妙に足りないため PCIe 2.0 to SATA III 3 port のアダプタカードで拡張してあります。


ミドルウェア


Kubernetes

何はともあれ Kubernetes です。自宅クラスターで起動しているプロセスは全て Kubernetes で管理されています。が、この自宅クラスターを管理している Kubernetes 自体も Kubernetes で管理されています。現時点での構成はこんな感じ。

Kubernetes.png

すみません、図を描いてて気づきました。Docker と kubeletsystemd で管理されてますね。それ以外だと etcdStatic podkube-apiserver がマスターロールノード上で DaemonSet で起動、HAProxy/Keepalived で冗長化されています。kube-controller-managerkube-schedulerCoreDNS といったどこで起動してても構わないプロセスは Deployment としてデプロイされています。

ちなみにデプロイ方法は、自前のスクリプト です。

kube-system はこちら。

$ k get pod -n kube-system

NAME READY STATUS RESTARTS AGE
coredns-7fbd6fbf45-6f5xf 1/1 Running 0 2d5h
coredns-7fbd6fbf45-bbt6d 1/1 Running 0 9d
etcd-192.168.1.111 1/1 Running 0 42d
etcd-192.168.1.112 1/1 Running 0 42d
etcd-192.168.1.113 1/1 Running 0 42d
kube-apiserver-ncfxr 1/1 Running 0 42d
kube-apiserver-t5p87 1/1 Running 0 42d
kube-apiserver-whsf9 1/1 Running 0 42d
kube-controller-manager-68cd59c45f-2h9kt 1/1 Running 1 42d
kube-controller-manager-68cd59c45f-cjzxv 1/1 Running 0 42d
kube-dns-autoscaler-65659d5f76-sk4tt 1/1 Running 0 2d5h
kube-flannel-ds-d25kd 1/1 Running 0 14d
kube-flannel-ds-hbnzw 1/1 Running 0 14d
kube-flannel-ds-mp4g9 1/1 Running 1 14d
kube-flannel-ds-ssw24 1/1 Running 0 14d
kube-flannel-ds-zb6ht 1/1 Running 0 14d
kube-flannel-ds-zftd5 1/1 Running 0 14d
kube-flannel-ds-zhgpl 1/1 Running 0 14d
kube-keepalived-4jg94 2/2 Running 0 42d
kube-keepalived-5ppxx 2/2 Running 0 42d
kube-keepalived-db7v6 2/2 Running 0 42d
kube-proxy-8kwqp 1/1 Running 1 14d
kube-proxy-d4b6r 1/1 Running 0 42d
kube-proxy-frj2n 1/1 Running 0 42d
kube-proxy-h8j2t 1/1 Running 0 42d
kube-proxy-n855q 1/1 Running 0 42d
kube-proxy-sn57r 1/1 Running 0 42d
kube-proxy-sp2pm 1/1 Running 0 42d
kube-scheduler-76798585f7-7z6hg 1/1 Running 1 42d
kube-scheduler-76798585f7-bd7bj 1/1 Running 0 42d
pod-checkpointer-9l4n2 1/1 Running 0 42d
pod-checkpointer-9l4n2-192.168.1.113 1/1 Running 0 42d
pod-checkpointer-bcmsr 1/1 Running 0 42d
pod-checkpointer-bcmsr-192.168.1.112 1/1 Running 0 42d
pod-checkpointer-qqk68 1/1 Running 0 42d
pod-checkpointer-qqk68-192.168.1.111 1/1 Running 0 42d


Ceph

CephRook でデプロイしてます。もう、だんだん面倒になって来たので簡単に cluster manifest を載せます。

---

apiVersion: ceph.rook.io/v1beta1
kind: Cluster
metadata:
name: rook-ceph
namespace: rook-ceph
spec:
dashboard:
enabled: true
placement:
osd:
tolerations:
- effect: NoSchedule
operator: Exists
dataDirHostPath: /var/lib/rook-ceph
serviceAccount: rook-ceph-cluster
mon:
count: 3
allowMultiplePerNode: true
network:
# toggle to use hostNetwork
hostNetwork: false
storage:
useAllNodes: false
useAllDevices: false
storeConfig:
storeType: bluestore
databaseSizeMB: 1024
journalSizeMB: 1024
nodes:
- name: "192.168.1.131"
resources:
limits:
cpu: "500m"
memory: "2048Mi"
requests:
cpu: "500m"
memory: "1024Mi"
devices:
- name: "sdb"
- name: "192.168.1.133"
resources:
limits:
cpu: "500m"
memory: "2048Mi"
requests:
cpu: "500m"
memory: "1024Mi"
devices:
- name: "sdb"
- name: "192.168.1.132"
resources:
limits:
cpu: "500m"
memory: "2048Mi"
requests:
cpu: "500m"
memory: "1024Mi"
devices:
- name: "sdb"

最初、resources.limits.memory1024Mi で運用していたのですが、妙に不安定で、2048Mi にしてからなんとか安定した感じです。ちゃんとリソースプランニングしないとダメですな!

あと、Rook のログを見てて思ったのだが、device の名前はもしかしたら /dev/disk/by-id/ とかでも指定できそうであった。


NFS

gcr.io/google_containers/volume-nfs:0.8 のコンテナイメージを利用。バックアップロールのノードにディスク六本まとめた raidz2 構成のストレージをマウントした DaemonSet を起動しています。

バックアップ方法は、


  1. 毎晩 Ceph のファイルシステムから rsync する CronJob を起動。

  2. 手作業で zfs snapshot


おわりに

とりあえずこんなな感じで、自宅でまあまあ安定して運用できる Kubernetes クラスタの作り方を紹介しました。実際に CephC の字もわからないで運用始めると、安定どころかデータをクラッシュしまくるので、だれか Ceph の運用方法教えてください。


このエントリは、弊社 Z Lab のメンバーによる Z Lab Advent Calendar 2018 の5日目として業務時間中に書きました。6日目は @ysakashita の担当です。