LoginSignup
8
5

More than 3 years have passed since last update.

kubesprayで構築したk8s環境にTopoLVMを使用してRook Cephのブロックストレージを構築する

Last updated at Posted at 2020-08-13

はじめに

おうちのk8s環境でクラウド環境と同様なストレージサービスを利用したい(まだまだこれから勉強なのですが、とりあえず永続ボリュームがサクッとつくれないと不便だと思っている)ので、Rook Cephの環境を構築しました。
以下の記事には大変お世話になりました。わかってしまえば簡単なことも、自分は結構時間をとってしまったので、誰かのお役に立てればと思い、記事として残します。

TopoLVMによるPVC-basedなRook/Ceph with Pod Topology Spread Constraints
RancherでTopoLVMの動作環境を構築する方法


環境

ESXi6.7

  • vm

    • k8s-master (cpu x2, mem 4GB,HDD System:30GB) x 1台
    • k8s-node1~3(cpu x2, mem 4GB,HDD System:30GB Storage用:50GB) x 3台
    • jumpserver x 1台 (Vagrant, kubespray作業用VM)
  • os

    • k8s-master, k8s-node1~3 Ubuntu20.04LTS
    • jumpserver:CentOS8.2.2004

k8s環境

k8s-storage (1).png

TopoLVMを使用したRook Ceph

k8s-storage-rook (1).png


手順

VMの構築

ベースOSの選定

Ubuntuを使っている記事が多いので、無難にUbuntuにしました。
(VMのディスクサイズをカスタマイズしたかったので自前のboxを作りました)
一応、コマンドを記載しておきます。

OSの更新

apt-get update
apt-get upgrade -y
apt-get dist-upgrade -y

再起動

shutdown -r now

sshの設定

mkdir /home/vagrant/.ssh
chmod 700 /home/vagrant/.ssh
cd /home/vagrant/.ssh 
curl -k -L -o authorized_keys 'https://github.com/hashicorp/vagrant/blob/master/keys/vagrant.pub'
chmod 600 /home/vagrant/.ssh/authorized_keys
chown -R vagrant:vagrant /home/vagrant/.ssh

パスワードなしでsudo可の設定

visodo

以下の行を最終行に追加する
vagrant ALL=(ALL) NOPASSWD: ALL

sshdのUseDNSをnoにしてssh接続を高速化する

vi /etc/ssh/sshd_config

UseDNS no がコメント化されている行があるので先頭の#を外す

軽量化

apt-get clean
apt-get autoremove

export HISTSIZE=0
rm -f /home/vagrant/.bash_history
rm -f /root/.bash_history
rm -rf /var/log/*
rm -rf /tmp/*

dd if=/dev/zero of=/tmp/ZERO bs=1M
rm /tmp/ZERO

仮想マシンを停止

shutdown -h now

boxイメージの作成

以下の記事を参照して作成します。
Vagrant box用イメージの作成


VangantでVM構築

VagrantでESXi上に新規にk8s構築用のVMを4台作成します(作業用のVMは別に用意してあります)。

Vagrant実行環境の準備

作業用のVMはCentOS8.2です(もともとあるものを流用)。
以下の手順でVagrant実行環境を準備します。
CentOS8.2にVagrantをインストール

VM構築

各Workerノードにシステムディスクとは別のディスク(50GB)を追加して構築します。
構築後、50GBのディスクが/dev/sdbとして見えることを前提としています。

以下のVagrantファイルを使用して構築しています。
Vagrantfile
config.yaml

vagrant multi sequenceで作成していて一気に構築できるはずなのですが、エラーになるので一個ずつ作成しています。
vagrantはあまり触ったことがないのでここは気にしないでおきます。。。

#/bin/bash
vagrant up k8s-master
vagrant up k8s-node1
vagrant up k8s-node2
vagrant up k8s-node3

kubesprayによるk8sの構築

kubespray実行環境のセットアップ

ここでは、jumpserverにkubesprayの実行環境を構築します。

事前設定

jumpserverのssh公開鍵を各workerノードのauthorized_keysにコピーします。
各workerノードにsshpassをインストールします。

これは、前述の「VM構築」で構築時に設定しました(Vagrantfile参照)。

jumpserverの設定

git clone https://github.com/kubernetes-sigs/kubespray.git

dnf install python38 -y
pip3 install --upgrade pip
cd kubespray
pip3 install -r requirements.txt

k8sの構築

設定

Inventory/Playbookの内容確認を確認し、書き換えます。

IPSの部分は作成するノードすべてのIPアドレスを記載します。

cp -rfp inventory/sample inventory/mycluster
declare -a IPS=(192.168.123.180 192.168.123.181 192.168.123.182 192.168.123.183)
CONFIG_FILE=inventory/mycluster/hosts.yml python3 contrib/inventory_builder/inventory.py ${IPS[@]}

自動生成されたhosts.ymlファイルを以下のように編集します。
デフォルトでは、node1、node2、node3、node4のような名前がホスト名になってしまうため、わかりやすくするためです。
また、Control Plane 1台、Workerノード 3台になるように、設定を見直します。
etcdはControl Planeでのみ起動するようにします。

hosts.yml

all:
  hosts:
    k8s-master:
      ansible_host: 192.168.123.180
      ip: 192.168.123.180
      access_ip: 192.168.123.180
    k8s-node1:
      ansible_host: 192.168.123.181
      ip: 192.168.123.181
      access_ip: 192.168.123.181
    k8s-node2:
      ansible_host: 192.168.123.182
      ip: 192.168.123.182
      access_ip: 192.168.123.182
    k8s-node3:
      ansible_host: 192.168.123.183
      ip: 192.168.123.183
      access_ip: 192.168.123.183
  children:
    kube-master:
      hosts:
        k8s-master:
    kube-node:
      hosts:
        k8s-node1:
        k8s-node2:
        k8s-node3:
    etcd:
      hosts:
        k8s-master:
    k8s-cluster:
      children:
        kube-master:
        kube-node:
    calico-rr:
      hosts: {}

構築

以下のコマンドを実行してk8s環境を構築します。

ansible-playbook -i inventory/mycluster/hosts.yml cluster.yml -b -v --private-key=~/.ssh/id_rsa

TopoLVMの設定

ここからは、kubectlが実行できる環境で実施します(k8s-masterで実施しました)。

TopoLVMのデプロイの手順と比較しながら見てもらえるとわかりやすいと思います。


TopoLVMのインストール

すべてのWorkerノードで以下のシェルを実行し、TopoLVMをインストールします。
(Vagrantファイル内からシェルを実行して一気に構築してしまってもよいかもしれません)

install.sh

#!/bin/bash

# install TopoLVM ★2020/8/12時点でバージョンは0.5.3が最新

echo "TopoLVM install"
pvcreate /dev/sdb
vgcreate datagroup /dev/sdb

mkdir -p /root/lvmd
cd /root/lvmd
wget https://github.com/topolvm/topolvm/releases/download/v0.5.3/lvmd-0.5.3.tar.gz
tar zxvf lvmd-0.5.3.tar.gz
mkdir /opt/sbin
chown root:root lvmd
mv lvmd /opt/sbin/lvmd

git clone --single-branch --branch v0.5.3 https://github.com/topolvm/topolvm.git
sed -i -e 's/^\(\s*volume-group: \).*$/\1datagroup/g' ./topolvm/deploy/lvmd-config/lvmd.yaml
mkdir /etc/topolvm
cp -p ./topolvm/deploy/lvmd-config/lvmd.yaml /etc/topolvm/lvmd.yaml
cp -p ./topolvm/deploy/systemd/lvmd.service /etc/systemd/system/lvmd.service
systemctl enable --now lvmd

echo "TopoLVM installed"

TopoLVMのためのk8sの設定

k8sの設定

cert-managerのデプロイ

kubectl apply --validate=false -f https://github.com/jetstack/cert-manager/releases/download/v0.16.1/cert-manager.yaml

topolvm-system名前空間の作成

git clone --single-branch --branch v0.5.3 https://github.com/topolvm/topolvm.git
kubectl apply -f ./topolvm/deploy/manifests/base/namespace.yaml

topolvm-schedulerの設定ファイルの配備

mkdir -p /etc/kubernetes/topolvm/
cp -p ./topolvm/deploy/scheduler-config/* /etc/kubernetes/topolvm/

topolvm-schedulerの設定

今回は、DaemonSetとしてtopolvm-schedulerを動作させます。
(Deployment and Serviceを使用して動作させることも可能なようです。)

kubectlを実行するサーバ(例:Control plane)でソースをDLします。

dnf install git -y
git clone --single-branch --branch v0.5.3 https://github.com/topolvm/topolvm.git

使用するマニフェストは以下のファイルす。
topolvm/deploy/manifests/overlays/daemonset-scheduler/scheduler.yaml

変更するポイント
・hostNetwork: true
kube-scheduler がhostNetworkを使用していない場合は、hostNetworkの値を変更する必要があります。

わからなかったら以下のコマンドで確認します。

kubectl get pods -n kube-system
kubectl get pod kube-scheduler-xxxxxxx -n kube-system -o yaml

自分の環境では変更しません。

・key: node-role.kubernetes.io/master
control plane ノードに一致するラベルを指定する必要があります。

以下のコマンドを実行して上記ラベルが control planeノードに存在するか確認します。
存在しなければ値を変更する必要があります。

kubectl get node --show-labels

自分の環境では変更しません。

TopoLVM Webhookからシステム名前空間を保護

kubectl label ns kube-system topolvm.cybozu.com/webhook=ignore

TopoLVMのデプロイ

Kustomizeのインストール

公式ではKustomizeを使用してデプロイしているのでそれに従います。
→Kustomizeとは、kubernetesのYAML設定ファイルをパッケージングするツールです。

wget https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh
bash ./install_kustomize.sh
mv kustomize /usr/local/bin/kustomize

kustomizeを使用してTopoLVMをデプロイ

/usr/local/bin/kustomize build ./topolvm/deploy/manifests/overlays/daemonset-scheduler | kubectl apply -f -

node Podの起動を待つ

kubectl get pods -n topolvm-system -l app.kubernetes.io/name=node

cert-managerマニフェストを生成する

kubectl apply -f ./topolvm/deploy/manifests/base/certificates.yaml

TopoLVMのpodが起動していることを確認する

kubectl get pods -n topolvm-system --watch

kube-schedulerの設定

vi /etc/kubernetes/manifests/kube-scheduler.yaml

以下のように編集します。


apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    component: kube-scheduler
    tier: control-plane
  name: kube-scheduler
  namespace: kube-system
spec:
  containers:
  - command:
    - kube-scheduler
    - --authentication-kubeconfig=/etc/kubernetes/scheduler.conf
    - --authorization-kubeconfig=/etc/kubernetes/scheduler.conf
    - --bind-address=0.0.0.0
    - --kubeconfig=/etc/kubernetes/scheduler.conf
    - --leader-elect=true
    - --port=0
    - --config=/var/lib/scheduler/scheduler-config.yaml    #★追加
    image: k8s.gcr.io/kube-scheduler:v1.18.6
    imagePullPolicy: IfNotPresent
    livenessProbe:
      failureThreshold: 8
      httpGet:
        path: /healthz
        port: 10259
        scheme: HTTPS
      initialDelaySeconds: 15
      timeoutSeconds: 15
    name: kube-scheduler
    resources:
      requests:
        cpu: 100m
    volumeMounts:
    - mountPath: /etc/kubernetes/scheduler.conf
      name: kubeconfig
      readOnly: true
    - mountPath: /var/lib/scheduler    #★追加
      name: topolvm-config             #★追加
      readOnly: true                   #★追加
  hostNetwork: true
  priorityClassName: system-cluster-critical
  volumes:
  - hostPath:
      path: /etc/kubernetes/scheduler.conf
      type: FileOrCreate
    name: kubeconfig
  - hostPath:                          #★追加
      path: /etc/kubernetes/topolvm    #★追加
      type: Directory                  #★追加
    name: topolvm-config               #★追加
status: {}

Rook/Cephのデプロイ

参考:https://tenzen.hatenablog.com/entry/2020/07/12/231235
https://qiita.com/MahoTakara/items/a1ed9811c790cd2a0d5f

事前準備

3つのworker nodeがそれぞれ別rackにあることを想定して、各ノードにrackをラベルとして与えます。
それぞれのノードにosd podが分散するように構築してきます。

kubectl label node k8s-node1 topology.rook.io/rack=rackA
kubectl label node k8s-node2 topology.rook.io/rack=rackB
kubectl label node k8s-node3 topology.rook.io/rack=rackC

common operator のデプロイ

「common.yaml」「operator.yaml」をデプロイします。

git clone --single-branch --branch release-1.4 https://github.com/rook/rook.git

Common Resources

kubectl create -f rook/cluster/examples/kubernetes/ceph/common.yaml

Operator

kubectl create -f rook/cluster/examples/kubernetes/ceph/operator.yaml

「cluster-on-pvc.yaml」の編集

OSDの数は6、rackおよびrack内のノードで分散配置するように設定しています。
TopoLVMによるPVC-basedなRook/Ceph with Pod Topology Spread Constraints)の設定ほぼそのままです。
今回は、3rackかつ1ノード/rackで分散されるので各workerノードに2OSD podが起動することになります。

cluster-on-pvc.yaml

apiVersion: ceph.rook.io/v1
kind: CephCluster
metadata:
  name: rook-ceph
  namespace: rook-ceph
spec:
  dataDirHostPath: /var/lib/rook
  mon:
    count: 3
    allowMultiplePerNode: false
    volumeClaimTemplate:
      spec:
        storageClassName: topolvm-provisioner
        resources:
          requests:
            storage: 3Gi
  cephVersion:
    image: ceph/ceph:v15.2.4
    allowUnsupported: false
  skipUpgradeChecks: false
  continueUpgradeAfterChecksEvenIfNotHealthy: false
  mgr:
    modules:
    - name: pg_autoscaler
      enabled: true
  dashboard:
    enabled: true
    ssl: true
  crashCollector:
    disable: false
  storage:
    storageClassDeviceSets:
    - name: topolvm-ssd-cluster
      count: 6
      portable: false
      tuneSlowDeviceClass: true
      encrypted: false
      placement:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: app
                  operator: In
                  values:
                  - rook-ceph-osd
                - key: app
                  operator: In
                  values:
                  - rook-ceph-osd-prepare
              topologyKey: kubernetes.io/hostname
        topologySpreadConstraints:
        # rackで分散配置
        - maxSkew: 1
          topologyKey: topology.rook.io/rack
          whenUnsatisfiable: DoNotSchedule
          labelSelector:
            matchExpressions:
            - key: app
              operator: In
              values:
              - rook-ceph-osd
              - rook-ceph-osd-prepare
        # rack内のnodeで分散配置(今回はrack内にnode1台なので意味はない)
        - maxSkew: 1
          topologyKey: kubernetes.io/hostname
          whenUnsatisfiable: DoNotSchedule
          labelSelector:
            matchExpressions:
            - key: app
              operator: In
              values:
              - rook-ceph-osd
              - rook-ceph-osd-prepare
      resources:
      volumeClaimTemplates:
      - metadata:
          name: data
        spec:
          resources:
            requests:
              storage: 10Gi
          storageClassName: topolvm-provisioner
          volumeMode: Block
          accessModes:
            - ReadWriteOnce
  disruptionManagement:
    managePodBudgets: false
    osdMaintenanceTimeout: 30
    manageMachineDisruptionBudgets: false
    machineDisruptionBudgetNamespace: openshift-machine-api

cluster-on-pvc のデプロイ

kubectl apply -f https://raw.githubusercontent.com/yasubehe/k8s-vagrant/master/k8s-storage/cluster-on-pvc.yaml

CephFSのデプロイ

kubectl apply -f https://raw.githubusercontent.com/yasubehe/k8s-vagrant/master/k8s-ubuntu/rook/filesystem.yaml

Rook toolboxのセットアップ

cephの状態を確認します。

kubectl apply -f ./rook/cluster/examples/kubernetes/ceph/toolbox.yaml

podの起動を確認する(STATUSがRunningになるのを待つ)

root@k8s-master:~# kubectl -n rook-ceph get pod -l "app=rook-ceph-tools"
NAME                              READY   STATUS    RESTARTS   AGE
rook-ceph-tools-7d9467775-xm984   1/1     Running   0          63s
root@k8s-master:~#

ポッドに接続

root@k8s-master:~# kubectl -n rook-ceph exec -it $(kubectl -n rook-ceph get pod -l "app=rook-ceph-tools" -o jsonpath='{.items[0].metadata.name}') bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl kubectl exec [POD] -- [COMMAND] instead.
[root@rook-ceph-tools-7d9467775-xm984 /]#

ceph statusを実行します。
healthがHEALTH_OKになっていることが確認できます。

[root@rook-ceph-tools-7d9467775-xm984 /]# ceph status
  cluster:
    id:     ed6cbc67-9813-439c-9111-d7d3ee19d1ca
    health: HEALTH_OK

  services:
    mon: 3 daemons, quorum a,b,c (age 10m)
    mgr: a(active, since 9m)
    mds: yasubehefs:1 {0=yasubehefs-a=up:active} 1 up:standby-replay
    osd: 6 osds: 6 up (since 9m), 6 in (since 9m)

  task status:
    scrub status:
        mds.yasubehefs-a: idle
        mds.yasubehefs-b: idle

  data:
    pools:   2 pools, 64 pgs
    objects: 22 objects, 2.2 KiB
    usage:   6.0 GiB used, 54 GiB / 60 GiB avail
    pgs:     64 active+clean

  io:
    client:   1.2 KiB/s rd, 2 op/s rd, 0 op/s wr

[root@rook-ceph-tools-7d9467775-xm984 /]#

cephのダッシュボードにアクセスする

参考:ROOK Ceph のブロックストレージを検証したメモ

サービスがClusterIPになっているのでNodePortに変更してアクセスする。

kubectl patch service rook-ceph-mgr-dashboard -n rook-ceph -p '{"spec":{"type":"NodePort"}}'

ポート番号を確認します。

root@k8s-master:~# kubectl -n rook-ceph get service rook-ceph-mgr-dashboard
NAME                      TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
rook-ceph-mgr-dashboard   NodePort   10.233.15.104   <none>        8443:32702/TCP   9h
root@k8s-master:~#

以下のURLでアクセスします。

https://192.168.123.181:32702/

ユーザ:admin
パスワードは以下で取得します。

kubectl -n rook-ceph get secret rook-ceph-dashboard-password -o jsonpath="{['data']['password']}" | base64 --decode && echo

動作確認

ブロックストレージが使えるのか動作を確認してみます。
RancherでTopoLVMの動作環境を構築する方法」ここのサンプルを借用させていただきました。

testpod.yaml

kind: PersistentVolumeClaim         # PersistentVolumeClaimの作成
apiVersion: v1
metadata:
  name: topolvm-pvc
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi                  # 1GiBのボリュームを作る
  storageClassName: topolvm-provisioner  # topoLVMから
---
apiVersion: v1
kind: Pod
metadata:
  name: my-pod
  labels:
    app.kubernetes.io/name: my-pod
spec:
  containers:
  - name: ubuntu
    image: quay.io/cybozu/ubuntu:18.04
    command: ["/usr/local/bin/pause"]
    volumeMounts:
    - mountPath: /test1           # /test1にマウントする
      name: my-volume
  volumes:                        # このボリュームを作って
    - name: my-volume
      persistentVolumeClaim:
        claimName: topolvm-pvc

デプロイします。

root@k8s-master:~# kubectl apply -f testpod.yaml
persistentvolumeclaim/topolvm-pvc created
pod/my-pod created
root@k8s-master:~#

起動を確認します。


root@k8s-master:~# kubectl get pods
NAME     READY   STATUS    RESTARTS   AGE
my-pod   1/1     Running   0          35m
root@k8s-master:~#

1Giのpvcが作られています。

root@k8s-master:~# kubectl get pvc
NAME          STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS          AGE
topolvm-pvc   Bound    pvc-a16fa45e-2ae5-4d99-844c-5207767fe4e8   1Gi        RWO            topolvm-provisioner   43m
root@k8s-master:~#

cephのボリュームがPVで割り当たっています。
ceph自身もPVで作られています。

root@k8s-master:~# kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                                        STORAGECLASS          REASON   AGE
pvc-1a3d8280-a60a-4c48-9abc-d14b1b1d6600   3Gi        RWO            Delete           Bound    rook-ceph/rook-ceph-mon-b                    topolvm-provisioner            10h
pvc-2bdaa2ea-c38d-42cf-904f-ded8a482f975   10Gi       RWO            Delete           Bound    rook-ceph/topolvm-ssd-cluster-data-4-5mvmj   topolvm-provisioner            10h
pvc-313c2cee-86cc-415c-b707-e97e9c1f18c0   10Gi       RWO            Delete           Bound    rook-ceph/topolvm-ssd-cluster-data-0-lfgqp   topolvm-provisioner            10h
pvc-56510718-faef-4950-8c5e-2c3b5754b0fc   3Gi        RWO            Delete           Bound    rook-ceph/rook-ceph-mon-c                    topolvm-provisioner            10h
pvc-67cfbfd3-439d-4ab3-bcb2-e3a060d63038   10Gi       RWO            Delete           Bound    rook-ceph/topolvm-ssd-cluster-data-2-xxdl5   topolvm-provisioner            10h
pvc-7feee616-eee7-497a-a8f7-85907cc40c80   3Gi        RWO            Delete           Bound    rook-ceph/rook-ceph-mon-a                    topolvm-provisioner            10h
pvc-866dc1a3-de63-4046-a120-a13bf1d73e6e   10Gi       RWO            Delete           Bound    rook-ceph/topolvm-ssd-cluster-data-1-9v2bd   topolvm-provisioner            10h
pvc-a16fa45e-2ae5-4d99-844c-5207767fe4e8   1Gi        RWO            Delete           Bound    default/topolvm-pvc                          topolvm-provisioner            44m
pvc-b89bef94-22f4-4a26-ace4-fbad54f2dccd   10Gi       RWO            Delete           Bound    rook-ceph/topolvm-ssd-cluster-data-3-cchh6   topolvm-provisioner            10h
pvc-c1ac3bd5-90d9-4f1b-ad15-f0dc2a551a55   10Gi       RWO            Delete           Bound    rook-ceph/topolvm-ssd-cluster-data-5-qmzxk   topolvm-provisioner            10h
root@k8s-master:~#

乗り込んで、期待通りか確認します。
/test1にマウントされてました。

kubectl exec -it my-pod bash
root@my-pod:/# mount | grep test1
/dev/topolvm/453c2052-eacc-4da1-b9b6-845ba1acd615 on /test1 type xfs (rw,relatime,lazytime,wsync,attr2,inode64,logbufs=8,logbsize=32k,noquota)
root@my-pod:/#

まとめ

おうち環境でも永続ボリュームが作れるようになりました。
kubesprayやKustomizeもただ使っているだけなので徐々に慣れていきたいです。


参考URL

TopoLVMによるPVC-basedなRook/Ceph with Pod Topology Spread Constraints
RancherでTopoLVMの動作環境を構築する方法
kubespray
Deploying TopoLVM

8
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
5