CloudNative Days Tokyo 2020発表資料。 k8sの各ノードのストレージでCephクラスタを組むにあたり、TopoLVMにより動的にボリュームを切り出した点と、PodTopologySpreadConstraintsによりボリュームを最適に分散配置した点を解説する。
KubernetesでCephクラスタ用のストレージをどう管理するか分割と配置の最適化への取り組みサイボウズ株式会社 森本健司1
View Slide
自己紹介▌森本健司⚫github.com: morimoto-cybozu▌cybozu.comのインフラ開発・運用を8年間担当▌インフラ刷新プロジェクトでKubernetesと出会う⚫手作業のない世界を目指す2
今日紹介する内容▌LVMで動的にボリュームを作成するTopoLVM⚫サイボウズ製のOSS▌ボリュームを最適に分散配置する各種の工夫⚫PodTopologySpreadConstraints⚫kube-schedulerのチューニング3
Cephの紹介▌OSSの分散ストレージシステム⚫スケーラブルで耐障害性をほぼ自動で確保▌意識して分散させるべき構成要素⚫Monitor (Paxosで分散合意)⚫Object Storage Device (OSD)4
5ラック1サーバラック2 ラック3MonMonMonMonitorの配置はanti-affinityでOK!
Rookの紹介▌Kubernetes上でCephを自動運用▌機能例⚫Cephクラスタを宣言どおりに構築⚫CephクラスタからS3互換のバケットを作成6
解決したい課題▌LVMで柔軟にボリュームを作成したい⚫Ceph以外に、MySQL等でも使いたいため▌OSDボリュームを分散配置したい⚫攪乱要因がいろいろあるが、負けずに!⚫例:HDD数台の故障、LVM VGの容量差、ラック間の機材台数の差、...7
8SSDLVSSDLVSSDLVLVMySQLに利用LVMで柔軟にボリュームを作成したい
デバイスをLVMで切り出す▌k8sのストレージドライバTopoLVMを開発⚫PersistentVolumeClaimに対して、各ノードの空き容量を考慮しつつLVを切り出してPVとして渡す▌Rookの「OSD on PVC」方式でストレージを指定⚫OSD Pod作成時にPVCでOSDを要求▌この組み合わせで、宣言的にSSDを分割・統合9
10CephClusterYAMLSSD
OSD11CephClusterYAMLSSD「このノードのこのデバイス」ではなく「このStorageClassでデバイスを確保」という指定
OSD12CephClusterYAML TopoLVMSSDLV宣言に基づきLVを動的に確保
OSD13CephClusterYAML TopoLVMSSDLV宣言に基づきLVを動的に確保
14ラック1zone: rack1host: r1-s1ラック2 ラック3OSDzone: rack1host: r1-s2zone: rack2host: r2-s1zone: rack2host: r2-s2zone: rack3host: r3-s1zone: rack3host: r3-s2OSDOSDOSDOSDOSD OSDOSDOSDボリュームを分散配置したい
PVの配置問題をPodの配置問題に置換▌k8sはPVの配置を直接は管理しない▌PVの配置をPodのスケジューリングに置き換える⚫Podが使うPVCのStorageClassでvolumeBindingMode: WaitForFirstConsumer⚫まずPodのスケジューリング⚫Pod/Nodeが決まったらそれに適したPVをbind15
16CephClusterYAMLSSD
OSD17CephClusterYAMLSSDPodがスケジュールされるまではPVを割り当てなくていいよ
OSD18CephClusterYAMLSSDaffinity, anti-affinityやリソースキャパシティの観点からPodをスケジューリング
OSD19CephClusterYAML TopoLVMSSDLV「どのノードのストレージを使うか」問題を「どのノードにPodを置くか」問題で解決
OSD20CephClusterYAML TopoLVMSSDLV「どのノードのストレージを使うか」問題を「どのノードにPodを置くか」問題で解決
OSD Podを分散配置したい▌anti-affinityでは表現できない⚫1ホストに複数のOSDを配置するので▌pod topology spread constraintsを使う⚫k8s 1.18でbetaとなった新しめの機能⚫ホスト単位/ラック単位/...でpod数の差をmaxSkew以下に抑える21
topologySpreadConstraints▌whenUnsatisfiable: DoNotSchedule (デフォ)⚫まったく均等な機材構成が必須になる⚫例えばあるノードでMySQLのためにVGを使い果たしていて、maxSkewを満たせない → Pod作成エラー▌whenUnsatisfiable: ScheduleAnyway⚫skewを最小に抑えつつ配置続行……のはずだが?22
whenUnsatisfiable: ScheduleAnyway▌想定: まずskew条件を満たすよう配置を試みる、駄目なら優先度を下げる▌→ 実際に配置してみた23
24ラック1zone: rack1host: r1-s1ラック2 ラック3zone: rack1host: r1-s2zone: rack2host: r2-s1zone: rack2host: r2-s2zone: rack3host: r3-s1zone: rack3host: r3-s2skewは満たせるはずなのに……Pod PodPodPodPodPod PodPodPodやや重いPodだがresourceには余裕あり
25ラック1zone: rack1host: r1-s1ラック2 ラック3zone: rack1host: r1-s2zone: rack2host: r2-s1zone: rack2host: r2-s2zone: rack3host: r3-s1zone: rack3host: r3-s2OSDOSDOSDOSDOSDOSDOSDskewは満たせるはずなのに……PodOSDまるでspreadしていない!PodPodPodPodPod PodPodPod
whenUnsatisfiable: ScheduleAnyway▌想定: まずskew条件を満たすよう配置を試みる、駄目なら優先度を下げる▌実際: 満たすかどうか試みず、単にskew条件をスコアリングの数ある条件の一つにしてしまう▌メンテナに確認、「実際の動作が仕様」⚫whenUnsatisfiableを文字どおりに受け取ってはいけない!26
kube-schedulerをチューニング▌skew条件のweightを大きくしてやればいい⚫1.17: scheduling policy (全体で1つ)を調整⚫EvenPodsSpreadPriorityのweightを500に⚫1.18+: scheduling profile (複数可)を調整⚫1.18: PodTopologySpreadのweightを500に⚫1.19: NodeResourcesBalancedAllocation無効化27
kube-schedulerをチューニング1.18設定28apiVersion: kubescheduler.config.k8s.io/v1alpha2kind: KubeSchedulerConfigurationleaderElection:leaderElect: trueclientConnection:kubeconfig: /etc/kubernetes/scheduler.confprofiles:- schedulerName: default-schedulerplugins:score:disabled:- name: PodTopologySpreadenabled:- name: PodTopologySpreadweight: 500
サイボウズが追加したRookの機能▌元々はPodの配置の指示が貧弱だった▌Monitor PodのpodAntiAffinity対応の修正▌OSD PodのtopologySpreadConstraints対応▌OSD podのschedulerName指定対応29
まとめ▌TopoLVMで動的にストレージを分割した▌OSDボリュームを最適に分散配置した⚫Topology spread constraintsを活用⚫攪乱要因に対しkube-schedulerをチューニング⚫→ Cephに限らずPodの分散配置に有効な知見30