概要
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
- kubernetes: v1.16.3
- 詳細はkubesprayでのインストールで記載した環境 (intel nuc + ESXi + centos7 + kubespray)
実行ステップ
実行ステップは下記の通り。
- iSCSI ターゲットの作成
- LUN の作成
- node へ open-iscsi インストール
- Secret の作成
- PV の作成
- StatefulSet でのデプロイメント(PV利用のテスト)
QNAPの設定(1. ~ 2.)
Kubernetes サーバの設定 (3.)
Kubernets リソースの設定・利用・テスト (4. ~ 6.)
1. iSCSI ターゲットの作成
QNAPへWeb管理へログインし、「iSCSI」の設定を開く
「Control Panel」 -> 「Storage & Snapshots」 -> 「iSCSI & Fiber Channel」 -> 「iSCSI」
下記画面まで上記の手順で遷移し、「Create」をクリックする。
iSCSIターゲット作成ウィザード
一つ前の画面で「Create」を押すと下記の画面が表示されるので、「Next」をクリックする。
iSCSIターゲット作成ウィザード 「設定」
iSCSI ターゲットの設定をします。
ここでは ターゲットの名前を入力します。紐づいて IQN などが作成されます。(最後に確認可能)
- iSCSI Target Profile: 「Name」 でターゲットの名前を入力
- 「Next」をクリック
iSCSIターゲット作成ウィザード 「CHAP」
CHAP 認証のための設定をする。
CHAP 認証は実施しなくても利用可能だが、iSCSI での Secret 利用の試験も兼ねて実施しておく。
- 「Use CHAP authentication」へチェックを入れる
- 「Username:」へユーザ名を入力
- 「Password:」へパスワードを入力 (12-16文字である必要がある)
- 「Re-enter Password:」へ再度パスワードを入力
- 「Next:」をクリック
iSCSIターゲット作成ウィザード 「要約」
これまで入力・設定した内容が最後に要約(Summary)として出力される
IQNをメモして、LUNを作成するのでLUN作成のチェックをしておく。
- IQN をメモ (後ほど利用する。別途参照は可能)
- 「Create an iSCSI LUN and map it to this targe.」をチェックしておく(デフォルトチェックされている)
- 「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」をそのままクリックする。
LUN 設定・作成
LUN の設定を実施する。
LUN Name: で名称、LUN Capacity: でサイズを入力して、Nextをクリックする。
完了すれば下記のように作成 Target へ LUN が Mapping された状態であることが確認可能。
2つ目以降のLUNの作成/Mapping
2つ目以降のLUNの作成は Create をクリックして New Block-Based LUN をクリックする。
すると、1つ目と同様の画面が開けるので、同様に作成していく。
2つ目以降はデフォルトでは LUN が iSCSI Target へ Mapping されないので手動で Mapping する。
Unmapped な LUN を選択し、Actionをクリックして、Edit LUN Mappingをクリックして Mapping画面を開く。
Mapping 画面では Map したい iSCSI target を選択して OK をクリックするだけ。
PV を試験で3つ作成してみるので、LUN も3つ目を同様に作成しておく。
下記は同様の動作で3つ目も作成したあとの出力例。
これで、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の場合)
---
# 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 を追加で良い)
---
- hosts: kube-node
become: true
gather_facts: yes
roles:
- iscsi-initiator
iscsid をインストール・起動を実施しない場合のエラー例
iscsid を入れてないと、下記のようなエラーが出てしまうので注意。
※ ある Pod で PV をマウントしたがコンテナ起動時にエラーとなってしまった例
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 でエンコードしたものを取得する。
$ echo k8spv | base64
azhzcHYK
$ echo k8spv1234567 | base64
azhzcHYxMjM0NTY3Cg==
下記は iscsi で chap 認証する為の secret 記載例。(上記で base64 エンコードし表示したものを使用する)
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 を指定する)
---
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)を要求する
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を提供しているので、それが使えば便利そうなので今後調べていきたい。