LoginSignup
8
9

More than 3 years have passed since last update.

QNAP の iSCSI Storage を自宅 Kubernetes の PersistentVolume にする

Posted at

概要

kubernetes クラスタで PV(PersistentVolume) 先として QNAP で iSCSI Storage を作成してマウントをしてみる
QNAP はほぼ初心者なので iSCSI の作成から記載していく
作成した iSCSI Storage を PV として登録して、Pod へアタッチできるところまでのテストを実施する

環境

QNAP NAS

  • Model: TS-231P
  • ファームウェアバージョン: 4.4.1.1146

※ TS-253Be-4G でも同じ操作で同じことができることも確認済

自宅 Kubernetes

実行ステップ

実行ステップは下記の通り。

  1. iSCSI ターゲットの作成
  2. LUN の作成
  3. node へ open-iscsi インストール
  4. Secret の作成
  5. PV の作成
  6. StatefulSet でのデプロイメント(PV利用のテスト)

QNAPの設定(1. ~ 2.)
Kubernetes サーバの設定 (3.)
Kubernets リソースの設定・利用・テスト (4. ~ 6.)

1. iSCSI ターゲットの作成

QNAPへWeb管理へログインし、「iSCSI」の設定を開く
「Control Panel」 -> 「Storage & Snapshots」 -> 「iSCSI & Fiber Channel」 -> 「iSCSI」

下記画面まで上記の手順で遷移し、「Create」をクリックする。

スクリーンショット 2020-02-11 14.08.29.png

iSCSIターゲット作成ウィザード

一つ前の画面で「Create」を押すと下記の画面が表示されるので、「Next」をクリックする。

スクリーンショット 2020-02-11 14.11.04.png

iSCSIターゲット作成ウィザード 「設定」

iSCSI ターゲットの設定をします。
ここでは ターゲットの名前を入力します。紐づいて IQN などが作成されます。(最後に確認可能)

スクリーンショット 2020-02-11 14.15.28.png

  1. iSCSI Target Profile: 「Name」 でターゲットの名前を入力
  2. 「Next」をクリック

iSCSIターゲット作成ウィザード 「CHAP」

CHAP 認証のための設定をする。
CHAP 認証は実施しなくても利用可能だが、iSCSI での Secret 利用の試験も兼ねて実施しておく。

  1. 「Use CHAP authentication」へチェックを入れる
  2. 「Username:」へユーザ名を入力
  3. 「Password:」へパスワードを入力 (12-16文字である必要がある)
  4. 「Re-enter Password:」へ再度パスワードを入力
  5. 「Next:」をクリック

スクリーンショット 2020-02-11 14.18.04.png

iSCSIターゲット作成ウィザード 「要約」

これまで入力・設定した内容が最後に要約(Summary)として出力される
IQNをメモして、LUNを作成するのでLUN作成のチェックをしておく。

スクリーンショット 2020-02-11 14.23.28.png

  1. IQN をメモ (後ほど利用する。別途参照は可能)
  2. 「Create an iSCSI LUN and map it to this targe.」をチェックしておく(デフォルトチェックされている)
  3. 「Apply」をクリック

これで iSCSI TARGET の作成までは完了

2. LUN の作成

続いて実際の Volume になる LUN を作成する。
1.の最後に「Create an iSCSI LUN and map it to this targe.」をクリック指定れば LUN 作成画面が自動で開く
(開かない場合は、「iSCSI Storage」 -> 「Create」 -> 「New Block-Based LUN」 で開ける)

下記が LUN 作成画面。ストレージプールがあれば自動で選択されているので、問題なければ「Next」をそのままクリックする。

スクリーンショット 2020-02-11 14.47.18.png

LUN 設定・作成

LUN の設定を実施する。
LUN Name: で名称、LUN Capacity: でサイズを入力して、Nextをクリックする。
スクリーンショット 2020-02-11 14.48.14.png

入力内容で問題なければApplyをクリックして反映させる。
スクリーンショット 2020-02-11 14.50.00.png

完了すれば下記のように作成 Target へ LUN が Mapping された状態であることが確認可能。

スクリーンショット 2020-02-11 14.57.35.png

2つ目以降のLUNの作成/Mapping

2つ目以降のLUNの作成は Create をクリックして New Block-Based LUN をクリックする。
すると、1つ目と同様の画面が開けるので、同様に作成していく。

スクリーンショット 2020-02-11 14.58.11.png

2つ目以降はデフォルトでは LUN が iSCSI Target へ Mapping されないので手動で Mapping する。
Unmapped な LUN を選択し、Actionをクリックして、Edit LUN Mappingをクリックして Mapping画面を開く。

スクリーンショット 2020-02-11 15.00.24.png

Mapping 画面では Map したい iSCSI target を選択して OK をクリックするだけ。

スクリーンショット 2020-02-11 15.02.44.png

PV を試験で3つ作成してみるので、LUN も3つ目を同様に作成しておく。
下記は同様の動作で3つ目も作成したあとの出力例。

スクリーンショット 2020-02-11 15.17.30.png

これで、iSCSI Target (QNAP)側の準備は完了

3. node へ iscsiイニシエータのインストール

kubernetes クラスタの node (worker/pod動作ノード) に iscsi のクライアント側である iscsi イニシエータがインストールされてないと利用できないため、
iscsi イニシエータ利用に必要なソフトウェアをインストールする。

手動でインストールを実施する場合は、worker ノードにて、下記コマンドでインストールを実施する(Centos7の場合)

yum install -y iscsi-initiator-utils
systemctl start iscsid.service
systemctl enable iscsid.service

ansibleでインストールを実施する場合は、Role追加例は下記の通り。(Centos7の場合)

ansible/roles/iscsi-initiator/tasks/main.yaml
---
# tasks file for iscsi-initiator

  - name: Install iscsci-initiator
    yum:
      name: "{{ packages }}"
      state: latest
      update_cache: yes
    vars:
      packages:
        - iscsi-initiator-utils
    become: yes
    register: iscsi

  - name: Start and Enable iscsid
    systemd:
      name: iscsid.service
      state: started
      enabled: yes
    become: yes
    when: iscsi.changed

ansible でインストールを実施する場合の、Playbook 例は下記。(既存のプレイブックに workernode(kube-node)対象に上記 role を追加で良い)

playbook_prekubespray_worker.yaml
---
- hosts: kube-node
  become: true
  gather_facts: yes

  roles:
    - iscsi-initiator

iscsid をインストール・起動を実施しない場合のエラー例

iscsid を入れてないと、下記のようなエラーが出てしまうので注意。
※ ある Pod で PV をマウントしたがコンテナ起動時にエラーとなってしまった例

workernodeにiscsi-initiator-utilsがない状態でPV利用時のエラー例.txt
Events:
  Type     Reason                  Age                From                     Message
 Warning  FailedMount             17s (x7 over 48s)  kubelet, k8sworker01   MountVolume.WaitForAttach failed for volume "iscsi-pv01" : executable file not found in $PATH

実行環境が整ったので、次からkubernetes リソースを作成していく

4. Secret の作成

iscsi で chap 認証する為 secret を作成する。

secret には base64 でエンコードしたものを記載するため、username/password を base64 でエンコードしたものを取得する。

cliでのbase64エンコード例.txt
$ echo k8spv | base64
azhzcHYK
$ echo k8spv1234567 | base64
azhzcHYxMjM0NTY3Cg==

下記は iscsi で chap 認証する為の secret 記載例。(上記で base64 エンコードし表示したものを使用する)

iscsi-chap-secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: iscsi-chap-secret
type: "kubernetes.io/iscsi-chap"
data:
  node.session.auth.username: "azhzcHYK"
  node.session.auth.password: "azhzcHYxMjM0NTY3Cg=="

secret を apply する。

$ kubectl apply -f iscsi-chap-secret.yaml 
secret/iscsi-chap-secret created

secret は下記のように確認できる。

$ kubectl describe secret iscsi-chap-secret
Name:         iscsi-chap-secret
Namespace:    default
Labels:       <none>
Annotations:  
Type:         kubernetes.io/iscsi-chap

Data
====
node.session.auth.password:  13 bytes
node.session.auth.username:  6 bytes

PV で chap 認証する secret 設定が完了

5. PV の作成

PersistentVolume リソースを作成する。(下記例(iscsi-pv.yaml)を参照. PVをテストのため3つ用意)

  • spec.iscsi.targetPortal: QNAPのIPアドレスを指定する(3260はデフォルトポート.明記. 192.168.129.241 はローカル環境なので環境に合わせて変更する)
  • spec.iscsi.iqn: iSCSI ターゲット作成時にメモした IQN を指定する
  • spec.iscsi.lun: LUN IDを指定する (何もしてなければ 0 から作成されるので 0,1,2 を指定する)
iscsi-pv.yaml
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: iscsi-pv01
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  storageClassName: standard
  iscsi:
    targetPortal: 192.168.129.241:3260
    iqn: iqn.2004-04.com.qnap:ts-231p:iscsi.k8spv.3c158c
    lun: 0
    readOnly: false
    chapAuthDiscovery: true
    chapAuthSession: true
    secretRef:
      name: iscsi-chap-secret
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: iscsi-pv02
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  storageClassName: standard
  iscsi:
    targetPortal: 192.168.129.241:3260
    iqn: iqn.2004-04.com.qnap:ts-231p:iscsi.k8spv.3c158c
    lun: 1
    readOnly: false
    chapAuthDiscovery: true
    chapAuthSession: true
    secretRef:
      name: iscsi-chap-secret
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: iscsi-pv03
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  storageClassName: standard
  iscsi:
    targetPortal: 192.168.129.241:3260
    iqn: iqn.2004-04.com.qnap:ts-231p:iscsi.k8spv.3c158c
    lun: 2
    readOnly: false
    chapAuthDiscovery: true
    chapAuthSession: true
    secretRef:
      name: iscsi-chap-secret

下記コマンドで適応する。

$ kubectl apply -f iscsi-pv.yaml 
persistentvolume/iscsi-pv01 created
persistentvolume/iscsi-pv02 created
persistentvolume/iscsi-pv03 created

下記コマンドで PV の状況を確認可能。
STATUS が Available で利用可能となったことが確認できる。

$ kubectl get pv
NAME         CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
iscsi-pv01   10Gi       RWO            Retain           Available           standard                87s
iscsi-pv02   10Gi       RWO            Retain           Available           standard                87s
iscsi-pv03   10Gi       RWO            Retain           Available           standard                87s

PV 設定まで完了し PVCで指定すれば利用可能となった

6. StatefulSet でのデプロイメント(PV利用のテスト)

下記テスト用の StatefulSet でデプロイして PV が利用できることを確認する。

  • テスト用 StatefulSet (test-statefulset.yaml)
    • replica数:3
    • nginxコンテナにvolumeをマウント
    • volumeClaimTemplatesでPVCを作成し、作成したPV(storage: 10Gi/storageClassName: standard)を要求する
test-statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: test-statefulset
spec:
  serviceName: test-statefulset
  replicas: 3
  selector:
    matchLabels:
      app: test-pv-app
  template:
    metadata:
      labels:
        app: test-pv-app
    spec:
      containers:
        - name: nginx-container
          image: nginx:1.12
          ports:
            - containerPort: 80
          volumeMounts:
          - name: www
            mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: www
    spec:
      accessModes:
      - ReadWriteOnce
      resources:
        requests:
          storage: 10Gi
      storageClassName: standard

下記コマンドで適応する。

$ kubectl apply -f test-statefulset-pvc.yaml 
statefulset.apps/test-statefulset created

下記コマンドで PV/PVC/pod 名などの状況を確認可能。
PVが作成時と変わり、STATUS が Bound となり、CLAIM も Bound した PVC 名が表示されることが確認できる。

$ kubectl get pv 
NAME         CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                            STORAGECLASS   REASON   AGE
iscsi-pv01   10Gi       RWO            Retain           Bound    default/www-test-statefulset-0   standard                4m14s
iscsi-pv02   10Gi       RWO            Retain           Bound    default/www-test-statefulset-1   standard                4m14s
iscsi-pv03   10Gi       RWO            Retain           Bound    default/www-test-statefulset-2   standard                4m14s
$ kubectl get pvc
NAME                     STATUS   VOLUME       CAPACITY   ACCESS MODES   STORAGECLASS   AGE
www-test-statefulset-0   Bound    iscsi-pv01   10Gi       RWO            standard       4m57s
www-test-statefulset-1   Bound    iscsi-pv02   10Gi       RWO            standard       3m58s
www-test-statefulset-2   Bound    iscsi-pv03   10Gi       RWO            standard       3m39s
$ kubectl get po -o wide
NAME                 READY   STATUS    RESTARTS   AGE     IP              NODE          NOMINATED NODE   READINESS GATES
test-statefulset-0   1/1     Running   0          4m20s   10.233.92.124   k8sworker02   <none>           <none>
test-statefulset-1   1/1     Running   0          4m10s   10.233.65.66    k8sworker01   <none>           <none>
test-statefulset-2   1/1     Running   0          3m27s   10.233.110.15   k8sworker03   <none>           <none>

Pod への関連 PV/PVC アタッチ状況は describe での Events:Volumes: で確認できる。

$ kubectl describe po test-statefulset-0
〜〜〜
中略
〜〜〜
Volumes:
  www:
    Type:       PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)
    ClaimName:  www-test-statefulset-0
    ReadOnly:   false
〜〜〜
中略
〜〜〜
Events:
  Type    Reason                  Age    From                     Message
  ----    ------                  ----   ----                     -------
  Normal  Scheduled               6m55s  default-scheduler        Successfully assigned default/test-statefulset-0 to k8sworker02
  Normal  SuccessfulAttachVolume  6m55s  attachdetach-controller  AttachVolume.Attach succeeded for volume "iscsi-pv01"
  Normal  Pulled                  6m46s  kubelet, k8sworker02     Container image "nginx:1.12" already present on machine
  Normal  Created                 6m46s  kubelet, k8sworker02     Created container nginx-container
  Normal  Started                 6m46s  kubelet, k8sworker02     Started container nginx-container

おわりに

自宅 Kubernetes クラスタ環境へ QNAP iSCSI による PersistentVolume (PV) の提供を可能にできた。
Dyanamic Provisoner 機能を使いたいが iSCSI/NFS は internal provisoner は未提供
Kubernetes Incubator が iSCSI用のProvisonerを提供しているので、それが使えば便利そうなので今後調べていきたい。

8
9
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
9