vSphere 6.7 U3 / vSAN 6.7 U3 から、VMware Cloud Native Storage と呼ばれるソリューションが提供されました。
これにより、Kubernetes から vSphere Container Storage Interface(CSI)Driver で利用されているボリュームが確認しやすくなります。
さっそく、ドキュメントをもとに試してみます。
About Getting Started with VMware Cloud Native Storage
今回の環境。
Kubernetes のバージョンは、ドキュメントで利用しているものにしましたが、
Kubernetes の Maser / Worker は個人的に使い慣れている Oracle Linux 7 にしています。
- vCenter Server 6.7 U3 / ESXi 6.7 U3 / vSAN 6.7 U3
- Kubenetes Node OS: Oracle Linux 7
- Master x 1、Worker x3
- ESXi / vSAN 上の VM として作成。
- Kubernetes 1.14.2
VM の設定。
Cloud Native Storage(CNS)を利用する Kubernetes ノードの VM では、
disk.EnableUUID というパラメータを設定しておきます。
vSphere Client から設定可能ですが、今回は PowerCLI で設定しています。
PowerCLI> Get-Folder -Type VM -Name "ol7-k8s-lab-03" | Get-VM | Get-AdvancedSetting -Name disk.EnableUUID | select Entity,Name,Value | sort Entity
Entity Name Value
------ ---- -----
k8s-m-31 disk.EnableUUID TRUE
k8s-w-31 disk.EnableUUID TRUE
k8s-w-32 disk.EnableUUID TRUE
k8s-w-33 disk.EnableUUID TRUE
また、Kubernetes のセットアップで利用する kubeadm の要件を考慮して
VM あたりのリソースは、2 vCPU、メモリ 4GB 以上にしてあります。
PowerCLI> Get-Folder -Type VM -Name "ol7-k8s-lab-03" | Get-VM | select Name,PowerState,NumCPU,MemoryGB | sort Name | ft -AutoSize
Name PowerState NumCpu MemoryGB
---- ---------- ------ --------
k8s-m-31 PoweredOn 2 4
k8s-w-31 PoweredOn 2 4
k8s-w-32 PoweredOn 2 4
k8s-w-33 PoweredOn 2 4
Linux OS の準備。
ドキュメントでは Ubuntu を使用していますが、
今回は、あえて Oracle Linux を使用してみました。
ただし Kubernetes にかかわる kubeadm と Docker は、Oracle Linux むけのものではなく
それぞれのプロダクトの Yum リポジトリを追加して、そこからインストールしています。
Linux OS は ISO インストーラからインストールし、ネットワーク設定を済ませた状態です。
今回は、kubernetes のセットアップからを手動で試しやすいように、
下記のような Ansible Playbook を作成して、OS のセットアップとファイル配布をしています。
GitHub - gowatana/vmware-cns-demo
Kubernetes クラスタ(Master)のセットアップ。
まず、kubeadm で Master ノードをセットアップします。
この環境での Master ノードは 1台のみです。
Master ノードにセットアップする OS に root ユーザでログインします。
Ansible で /root/01_kubeadm/kubeadm-init-master.yml ファイルを配置してあるので、
これをもとに kubeadm init コマンドを実行します。
[root@k8s-m-31 ~]# kubeadm init --config 01_kubeadm/kubeadm-init-master.yml
Master ノードがセットアップされました。
まだ NotReady ですが、このまま進めます。
[root@k8s-m-31 ~]# export KUBECONFIG=/etc/kubernetes/admin.conf
[root@k8s-m-31 ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-m-31 NotReady master 58s v1.14.2
今回は root ユーザのみですすめるので、
再ログイン時に環境変数 KUBECONFIG が設定されるように、.bash_profile にも追記しておきます。
[root@k8s-m-31 ~]# echo 'export KUBECONFIG=/etc/kubernetes/admin.conf' >> /root/.bash_profile
Worker ノードのセットアップで利用する discovery.yml を取得しておきます。
[root@k8s-m-31 ~]# kubectl -n kube-public get configmap cluster-info -o jsonpath='{.data.kubeconfig}' > /etc/kubernetes/discovery.yml
discovery.yml ファイルは、これから Worker ノードにする OS の、/etc/kubernetes/ ディレクトリ配下に
scp などでコピーしておきます。
[root@k8s-m-31 ~]# scp /etc/kubernetes/discovery.yml <Worker Nodeのアドレス>:/etc/kubernetes/
Flannel のセットアップ。
Kubernetes のノード間のネットワークを構成する、Flannel をセットアップしておきます。
[root@k8s-m-31 ~]# kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/bc79dd1505b0c8681ece4de4c0d86c5cd2643275/Documentation/kube-flannel.yml
clusterrole.rbac.authorization.k8s.io/flannel created
clusterrolebinding.rbac.authorization.k8s.io/flannel created
serviceaccount/flannel created
configmap/kube-flannel-cfg created
daemonset.extensions/kube-flannel-ds-amd64 created
daemonset.extensions/kube-flannel-ds-arm64 created
daemonset.extensions/kube-flannel-ds-arm created
daemonset.extensions/kube-flannel-ds-ppc64le created
daemonset.extensions/kube-flannel-ds-s390x created
Kubernetes クラスタ(Worker)のセットアップ。
Worker ノードそれぞれで kubeadm join を実行し、セットアップをすすめます。
Ansible で配置ずみの 01_kubeadm/kubeadm-init-worker.yml ファイルと、
セットアップずみの Master ノードから取得した discovery.yml ファイルを使用しています。
[root@k8s-w-31 ~]# kubeadm join --config 01_kubeadm/kubeadm-init-worker.yml
kubeadm join を実行したノードが追加されたことがわかります。
[root@k8s-m-31 ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-m-31 Ready master 16m v1.14.2
k8s-w-31 Ready <none> 32s v1.14.2
今回は、Master 1台、Worker 3台の構成にしました。
[root@k8s-m-31 ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-m-31 Ready master 18m v1.14.2
k8s-w-31 Ready <none> 2m40s v1.14.2
k8s-w-32 Ready <none> 53s v1.14.2
k8s-w-33 Ready <none> 31s v1.14.2
この時点だと、まだ Worker ノードがコンテナを起動しない状態(NoSchedule)ですが、
このまま次に進みます。
[root@k8s-m-31 ~]# kubectl describe nodes | egrep "Taints:|Name:"
Name: k8s-m-31
Taints: node-role.kubernetes.io/master:NoSchedule
Name: k8s-w-31
Taints: node.cloudprovider.kubernetes.io/uninitialized=true:NoSchedule
Name: k8s-w-32
Taints: node.cloudprovider.kubernetes.io/uninitialized=true:NoSchedule
Name: k8s-w-33
Taints: node.cloudprovider.kubernetes.io/uninitialized=true:NoSchedule
Cloud Provider for vSphere のセットアップ。
Kubernetes と vCenter が連携するための「Kubernetes Cloud Provider for vSphere」をセットアップします。
GitHub - kubernetes/cloud-provider-vsphere: Kubernetes Cloud Provider for vSphere
ここからは、すべて Master ノードで作業します。
今回のデモでは、Cloud Provider で指定する設定ファイルのテンプレートも、Ansible で配布しています。
[root@k8s-m-31 ~]# ls -1 ./02_k8s-csi/
csi-driver-deploy.yaml
csi-driver-rbac.yaml
csi-vsphere.conf
vsphere.conf
このうち、vsphere.conf を環境にあわせて編集します。
- このサンプルファイルは自宅ラボの環境です。
- ユーザー / パスワードは、デモむけに あえて安直なものにしています。
[root@k8s-m-31 ~]# ls ./02_k8s-csi/vsphere.conf
[Global]
insecure-flag = "true"
[VirtualCenter "infra-vc-01.go-lab.jp"]
user = "administrator@vsphere.local"
password = "VMware1!"
port = "443"
datacenters = "infra-dc-01"
[Network]
public-network = "vxw-dvs-30-virtualwire-14-sid-10003-ls-lab-k8s-003"
vsphere.conf ファイルをもとに、cloud-config という ConfigMap を作成します。
この名前は、後続の kubectl apply で指定している YAML ファイルの内容に合わせてあります。
[root@k8s-m-31 ~]# kubectl create configmap cloud-config -n kube-system --from-file ./02_k8s-csi/vsphere.conf
configmap/cloud-config created
そして、GitHub にある YAML ファイルをもとにリソースを準備していきます。
ClusterRole・・・
[root@k8s-m-31 ~]# kubectl apply -f https://raw.githubusercontent.com/kubernetes/cloud-provider-vsphere/master/manifests/controller-manager/cloud-controller-manager-roles.yaml
clusterrole.rbac.authorization.k8s.io/system:cloud-controller-manager created
RoleBinding、ClusterRoleBinding・・・
[root@k8s-m-31 ~]# kubectl apply -f https://raw.githubusercontent.com/kubernetes/cloud-provider-vsphere/master/manifests/controller-manager/cloud-controller-manager-role-bindings.yaml
rolebinding.rbac.authorization.k8s.io/servicecatalog.k8s.io:apiserver-authentication-reader created
clusterrolebinding.rbac.authorization.k8s.io/system:cloud-controller-manager created
ServiceAccount、DaemonSet、Service・・・
[root@k8s-m-31 ~]# kubectl apply -f https://github.com/kubernetes/cloud-provider-vsphere/raw/master/manifests/controller-manager/vsphere-cloud-controller-manager-ds.yaml
serviceaccount/cloud-controller-manager created
daemonset.extensions/vsphere-cloud-controller-manager created
service/vsphere-cloud-controller-manager created
これで、下記のような Pod が起動された状態になります。
[root@k8s-m-31 ~]# kubectl get pods -n kube-system -l k8s-app=vsphere-cloud-controller-manager
NAME READY STATUS RESTARTS AGE
vsphere-cloud-controller-manager-275cj 1/1 Running 0 4m27s
各ノードでは、ProviderID が確認できるようになります。
[root@k8s-m-31 ~]# kubectl describe nodes | egrep "Name:|ProviderID:"
Name: k8s-m-31
ProviderID: vsphere://42362f4f-d91b-4747-9d05-18c4b7287d65
Name: k8s-w-31
ProviderID: vsphere://42362124-8759-dab1-e1c2-2478c6ac8450
Name: k8s-w-32
ProviderID: vsphere://4236fbb9-2e70-1fc3-c87b-9dc574e80623
Name: k8s-w-33
ProviderID: vsphere://4236e12c-841e-5b39-04a6-3e6b80cdc93e
また、Worker ノードの「NoSchedule」も解除されます。
[root@k8s-m-31 ~]# kubectl describe nodes | egrep "Taints:|Name:"
Name: k8s-m-31
Taints: node-role.kubernetes.io/master:NoSchedule
Name: k8s-w-31
Taints: <none>
Name: k8s-w-32
Taints: <none>
Name: k8s-w-33
Taints: <none>
CSI のセットアップ。
Container Storage Interface(CSI)Driver をデプロイします。
下記の3つのファイルを用意します。
- csi-vsphere.conf ※環境に合わせて編集
- csi-driver-rbac.yaml ※今回はドキュメントのまま
- csi-driver-deploy.yaml ※今回はドキュメントのまま
参考ドキュメント: Install the vSphere Container Storage Interface Driver
csi-vsphere.conf ファイルに、vSphere 環境の情報を記載しておきます。
先ほどのファイルと同様、これは私の自宅ラボのものなので、適宜編集します。
[root@k8s-m-31 ~]# cat ./02_k8s-csi/csi-vsphere.conf
[Global]
cluster-id = "infra-cluster-01"
[VirtualCenter "infra-vc-01.go-lab.jp"]
insecure-flag = "true"
user = "administrator@vsphere.local"
password = "VMware1!"
port = "443"
datacenters = "infra-dc-01"
vCenter の情報をもつ secret を作成します。
[root@k8s-m-31 ~]# kubectl create secret generic vsphere-config-secret -n kube-system --from-file=./02_k8s-csi/csi-vsphere.conf
secret/vsphere-config-secret created
vSphere CSI Driver の依存コンポーネントを準備します。
[root@k8s-m-31 ~]# kubectl create -f ./02_k8s-csi/csi-driver-rbac.yaml
serviceaccount/vsphere-csi-controller created
clusterrole.rbac.authorization.k8s.io/vsphere-csi-controller-role created
clusterrolebinding.rbac.authorization.k8s.io/vsphere-csi-controller-binding created
vSphere CSI Driver をデプロイします。
[root@k8s-m-31 ~]# kubectl create -f ./02_k8s-csi/csi-driver-deploy.yaml
statefulset.apps/vsphere-csi-controller created
csidriver.storage.k8s.io/csi.vsphere.vmware.com created
daemonset.apps/vsphere-csi-node created
少し待つと、CSI Driver の Pod がすべて READY になります。
[root@k8s-m-31 ~]# kubectl get pods -n kube-system | egrep "^NAME|vsphere"
NAME READY STATUS RESTARTS AGE
vsphere-cloud-controller-manager-275cj 1/1 Running 0 37m
vsphere-csi-controller-0 5/5 Running 0 2m49s
vsphere-csi-node-4s2df 3/3 Running 0 2m49s
vsphere-csi-node-8sspf 3/3 Running 0 2m49s
vsphere-csi-node-c68fq 3/3 Running 0 2m49s
これで、Worker ノードが CSI Node として利用できる状態になります。
[root@k8s-m-31 ~]# kubectl get csinode
NAME CREATED AT
k8s-w-31 2019-08-27T23:29:37Z
k8s-w-32 2019-08-27T23:29:30Z
k8s-w-33 2019-08-27T23:29:27Z
サンプル アプリケーションのデプロイ。
CSI Driver によるボリュームを使用する、ステートフル アプリケーションをデプロイします。
ここでは、MongoDB をデプロイしますが、これをそのまま何かに利用するということではなく、
ただボリューム(Kubernetes の PVC / PV)の様子を見るデモのために利用します・・・
参考ドキュメント: Deploy a Stateful Application
1. vSphere 側の準備。
vCenter で、「仮想マシン ストレージ ポリシー」を作成しておきます。
今回は、vSAN 環境にデフォルトで作成される「vSAN Default Storage Policy」を利用します。
2. Kubernetes でのアプリケーションのデプロイ。
ここでは、下記のファイルを使用します。
今回のデモでは、これらのファイルも Ansible で Master ノードに配布しています。
[root@k8s-m-31 ~]# ls -1 ./03_demo/
mongodb-key.txt
mongodb-service.yaml
mongodb-statefulset.yaml
mongodb-storageclass.yaml
Kubernetes の StorageClass で、下記を指定します。
provisioner として「csi.vsphere.vmware.com」、
仮想マシン ストレージ ポリシー として「vSAN Default Storage Policy」を指定します。
[root@k8s-m-31 ~]# cat ./03_demo/mongodb-storageclass.yaml
---
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: mongodb-sc
annotations:
storageclass.kubernetes.io/is-default-class: "false"
provisioner: csi.vsphere.vmware.com
parameters:
storagepolicyname: "vSAN Default Storage Policy"
fstype: ext4
StorageClass を作成します。
[root@k8s-m-31 ~]# kubectl create -f ./03_demo/mongodb-storageclass.yaml
storageclass.storage.k8s.io/mongodb-sc created
StorageClassが作成されました。
[root@k8s-m-31 ~]# kubectl get storageclass mongodb-sc
NAME PROVISIONER AGE
mongodb-sc csi.vsphere.vmware.com 51s
Service を作成します。
[root@k8s-m-31 ~]# kubectl create -f ./03_demo/mongodb-service.yaml
service/mongodb-service created
Secret を作成します。
[root@k8s-m-31 ~]# openssl rand -base64 741 > ./03_demo/mongodb-key.txt
[root@k8s-m-31 ~]# kubectl create secret generic shared-bootstrap-data --from-file=internal-auth-mongodb-keyfile=./03_demo/mongodb-key.txt
secret/shared-bootstrap-data created
そして、StatefulSet を作成します。
[root@k8s-m-31 ~]# kubectl create -f ./03_demo/mongodb-statefulset.yaml
statefulset.apps/mongod created
3. vCenter の vSphere Client での確認。
vSphere Client では、クラスタを選択して、
監視 → クラウド ネイティブ ストレージ → コンテナ ボリューム を開くと、Kubernetes のボリュームが確認できます。
アプリケーションのデプロイをまち、
Kubernetes 側で PersistentVolume(PV) / PersistentVolumeClaim(PVC) が作成されたことを確認します。
※表示例は横に長いので、スクリーンショットにしてあります。
[root@k8s-m-31 ~]# kubectl get pv
[root@k8s-m-31 ~]# kubectl get pvc
vSphere Client でも、PV が表示されるようになります。
PV の先頭のアイコンをクリックすると、「Kubernetes オブジェクト」タブで
関連する Kubernetes オブジェクトの情報が表示できます。
「基本」タブでは、PV の配置された vSAN データストア、VMDK の仮想マシン ストレージポリシー、
PV が接続している VM など、vSphere 管理者の視点での情報が表示されます。
PV は、vSAN の仮想ディスクとして作成され、VM に接続されています。
上記のコンテナ ボリューム画面で PV のボリューム名をクリックするか、
監視 → vSAN → 仮想オブジェクト の画面をひらくと、VM に PV が接続されている様子がわかります。
実は以前から Kubernetes にボリュームを提供する機能(Project Hatchway と呼ばれていた)はあったのですが、
vSphere 6.7 u3 からは、今回の例のように vSphere Clinet から「クラウド ボリューム」として
Kubernetes でボリュームとして利用している VMDK が見やすくなりました。
以上、vSphere / vSAN 6.7 U3 の Cloud Native Storage でした。