OpenShiftのDynamic Storage Provisioning環境の構築 (containerized gluster on azure)
OpenShift 3.4 からDynamic Storage Provisioningが利用可能になったので、GlusterFSを使って試してみました
PersistentVolume(PV) と Persistent Volume Claim(PVC) を利用する仕組みでは、OpenShiftのクラスタ管理者が事前に Persistent Volumeという形でStoragePoolを準備しておき、アプリケーション側の要求(PVC)にマッチするものが関連づけられて、永続化ストレージが利用可能になる仕組みでした。 それに対して、Dynamic Storage Provisioning は、大きくストレージ領域を確保しておいて、必要に応じてボリュームを切り出してアプリケーションに割り当てます。
ホールケーキとピースのケーキみたいなイメージとか、袋菓子と小分包装のお菓子みたいなイメージと勝手に思ってる。。。
OpenShift 3.4 を Azure 上にデプロイ
Master サーバー(InfraNode, etcd も同居) 1台、Node サーバー 3台の構成で GlusterFSコンテナは3台のNodeサーバーにデプロイします。
事前準備
/etc/hosts に各サーバーのFQDNを含むIPアドレスを登録
52.175.xxx.yyy komizo-master.japanwest.cloudapp.azure.com 72.247.116.251 cdn.redhat.com 10.0.1.4 master master.r5xks4ipxxxxxxxxxxxxxxxxxxx.mx.internal.cloudapp.net 10.0.1.5 node01 node01.r5xks4ipxxxxxxxxxxxxxxxxxx.mx.internal.cloudapp.net 10.0.1.6 node02 node02.r5xks4ipxxxxxxxxxxxxxxxxxx.mx.internal.cloudapp.net 10.0.1.7 node03 node03.r5xks4ipxxxxxxxxxxxxxxxxxx.mx.internal.cloudapp.net
必要なパッケージのインストール
USER=`cat rhn-user` PASSWORD=`cat rhn-password` POOL_ID=`cat rhn-poolid` subscription-manager register --username $USER --password $PASSWORD subscription-manager attach --pool=$POOL_ID subscription-manager repos --disable="*" subscription-manager repos \ --enable="rhel-7-server-rpms" \ --enable="rhel-7-server-extras-rpms" \ --enable="rhel-7-server-ose-3.4-rpms" yum -y install wget git net-tools bind-utils iptables-services bridge-utils bash -completion yum -y update yum -y install atomic-openshift-utils yum -y install atomic-openshift-excluder atomic-openshift-docker-excluder atomic-openshift-excluder unexclude yum -y install docker sed -i '/OPTIONS=.*/c\OPTIONS="--selinux-enabled --insecure-registry 172.30.0.0/16"' /etc/sysconfig/docker
Ansible プレイブック実行ユーザーの公開鍵を配置
drwx------. 2 ansible ansible 29 Jan 26 10:29 /home/ansible/.ssh -rw-------. 1 ansible ansible 396 Jan 26 10:29 /home/ansible/.ssh/authorized_keys
Ansible インベントリファイルの準備
サーバーに割り振られたサブネットが、dockerのデフォルトのサブネットと重複するのでosm_cluster_network_cidr
で、dockerのサブネットを指定します。
# Create an OSEv3 group that contains the masters and nodes groups [OSEv3:children] masters nodes # Set variables common for all OSEv3 hosts [OSEv3:vars] # SSH user, this user should allow ssh based auth without requiring a password ansible_ssh_user=ansible # If ansible_ssh_user is not root, ansible_become must be set to true ansible_become=true deployment_type=openshift-enterprise openshift_master_default_subdomain=52.175.xxx.yyy.xip.io osm_cluster_network_cidr=10.128.0.0/14 os_sdn_network_plugin_name=redhat/openshift-ovs-multitenant # uncomment the following to enable htpasswd authentication; defaults to DenyAllPasswordIdentityProvider openshift_master_identity_providers=[{'name': 'htpasswd_auth', 'login': 'true', 'challenge': 'true', 'kind': 'HTPasswdPasswordIdentityProvider', 'filename': '/etc/origin/master/htpasswd'}] # host group for masters [masters] komizo-master.japanwest.cloudapp.azure.com # host group for nodes, includes region info [nodes] komizo-master.japanwest.cloudapp.azure.com openshift_node_labels="{'region': 'infra', 'zone': 'default'}" openshift_public_hostname=komizo-master.japanwest.cloudapp.azure.com openshift_schedulable=true node01 openshift_node_labels="{'region': 'primary', 'zone': 'east'}" node02 openshift_node_labels="{'region': 'primary', 'zone': 'west'}" node03 openshift_node_labels="{'region': 'primary'}"
OpenShift のインストール
ansible-playbook /usr/share/ansible/openshift-ansible/playbooks/byo/config.yml
Containerized Gluster のデプロイ
事前準備
必要なパッケージのインストール
Masterサーバーに必要なパッケージをインストールします。
subscription-manager repos --enable=rh-gluster-3-for-rhel-7-server-rpms yum -y install cns-deploy heketi-client
iptables の編集
以下のルールを /etc/sysconfig/iptables に登録します。
-A OS_FIREWALL_ALLOW -p tcp -m state --state NEW -m tcp --dport 24007 -j ACCEPT -A OS_FIREWALL_ALLOW -p tcp -m state --state NEW -m tcp --dport 24008 -j ACCEPT -A OS_FIREWALL_ALLOW -p tcp -m state --state NEW -m tcp --dport 2222 -j ACCEPT -A OS_FIREWALL_ALLOW -p tcp -m state --state NEW -m multiport --dports 49152:49664 -j ACCEPT
変更を反映します。
systemctl reload iptables iptables -L
GlusterFS用のディスクを追加
3台のNodeサーバーにディスクを追加します。 /dev/sda, /dev/sdb はすでにできているので、新たに追加したボリュームは /dev/sdcになります。
- ボリュームを追加するVirtual Machineを選択
- Disksを選択
- Attach Newでディスクの追加
- 必要なパラメータを設定して「OK」をクリック
※ここで、Locationは同一リソースグループ内のStorageAccountを選択すること!!
GlusterFSのデプロイ
トポロジーファイルの作成
/usr/share/heketi/topology-sample.json をコピーして今回の環境に合うように編集します。
[topology.json]
{ "clusters": [ { "nodes": [ { "node": { "hostnames": { "manage": [ "node01.r5xks4ipxxxxxxxxxxxxxxxxxx.mx.internal.cloudapp.net" ], "storage": [ "10.0.1.5" ] }, "zone": 1 }, "devices": [ "/dev/sdc" ] }, { "node": { "hostnames": { "manage": [ "node02.r5xks4ipxxxxxxxxxxxxxxxxxx.mx.internal.cloudapp.net" ], "storage": [ "10.0.1.6" ] }, "zone": 2 }, "devices": [ "/dev/sdc" ] }, { "node": { "hostnames": { "manage": [ "node03.r5xks4ipxxxxxxxxxxxxxxxxxx.mx.internal.cloudapp.net" ], "storage": [ "10.0.1.7" ] }, "zone": 1 }, "devices": [ "/dev/sdc" ] } ] } ] }
GlusterFSコンテナのデプロイ
GlusterFS のコンテナをデプロイするためのプロジェクトを作成し、特権コンテナとして実行するための権限設定などを行います。
以下の作業はMasterサーバーにてsystem:adminユーザで実行します。
oc new-project storage-project oadm policy add-scc-to-user privileged -z default
コンテナ版のGlusterFSをデプロイします。
cns-deploy -n storage-project -g topology.json
デプロイの実行結果は https://access.redhat.com/documentation/en/red-hat-gluster-storage/3.1/single/container-native-storage-for-openshift-container-platform/#idm140637724619968を参照してください。
※ここで何かエラーがあって、再実行する場合はoc delete all --all
で作成済みPodなどを削除してから再実行します。
Glusterのトポロジを確認します。
export HEKETI_CLI_SERVER=http://heketi-storage-project.52.175.148.91.xip.io heketi-cli topology info
NodeサーバーでVolumeができていることを確認します。
[root@node01 ~]# pvs PV VG Fmt Attr PSize PFree /dev/sdc vg_b3dfc1b27ddc928dfe5dab9855d234d7 lvm2 a-- 9.87g 6.84g
Dynamic Stroge Provisioningの利用
StorageClassの作成
StorageClassとSecretの定義ファイルを作成します。
[glusterfs-storageclass.yaml]
apiVersion: storage.k8s.io/v1beta1 kind: StorageClass metadata: name: gluster-container provisioner: kubernetes.io/glusterfs parameters: resturl: "http://heketi-storage-project.52.175.xxx.yyy.xip.io" restuser: "admin" secretNamespace: "default" secretName: "heketi-secret"
[glusterfs-secret.yaml]
apiVersion: v1 kind: Secret metadata: name: heketi-secret namespace: default data: # base64 encoded password. E.g.: echo -n "mypassword" | base64 key: bXlwYXNzd29yZA== type: kubernetes.io/glusterfs
StorageClassとSecretを作成します。
oc project storage-project oc create -f glusterfs-storageclass.yaml oc create -f glusterfs-secret.yaml
Persistent Storageを利用するアプリケーションのデプロイ
JBoss EAP7 とMySQLを使ったToDoアプリケーションをデプロイします。OpenShiftのインストール時に用意されているテンプレートは、StaticなPersistent Volumeを利用するようになっているので、少し編集してDynamic Persistent Volumeを利用するテンプレートを新しく準備してアプリケーションをデプロイします。
テンプレートの作成
既存の eap70-mysql-persistent-s2i テンプレートをエクスポートします。
oc get templates -n openshift |grep eap70-mysql oc export templates eap70-mysql-persistent-s2i -n openshift -o json > eap70-mysql-storageclass-s2i.json
metadata.nameをeap70-mysql-persistent-s2i
からeap70-mysql-storagclass-s2i
に変更します。
labels.templateをeap70-mysql-persistent-s2i
からeap70-mysql-storagclass-s2i
に変更します。
PersistentVolumeClaimにannotationを追加します。
"metadata": { "name": "eap70-mysql-storageclass-s2i", "creationTimestamp": null, "annotations": { "description": "Application template for EAP 7 MySQL applications with persistent storage built using S2I.", "iconClass": "icon-jboss", "tags": "eap,mysql,javaee,java,database,jboss,xpaas", "version": "1.3.2" } }, >>> 中略 <<< { "apiVersion": "v1", "kind": "PersistentVolumeClaim", "metadata": { "labels": { "application": "${APPLICATION_NAME}" }, "name": "${APPLICATION_NAME}-mysql-claim", "annotations": { "volume.beta.kubernetes.io/storage-class": "gluster-container" } }, "spec": { "accessModes": [ "ReadWriteOnce" ], "resources": { "requests": { "storage": "${VOLUME_CAPACITY}" } } } } >>> 中略 <<< "labels": { "template": "eap70-mysql-storageclass-s2i", "xpaas": "1.3.2" }
テンプレートを登録します。
oc create -f eap70-mysql-storageclass-s2i.json -n openshift
ここで、-n openshift
オプションを指定することで、OpenShiftのユーザー全員がこのテンプレートを利用可能になります。このオプションを指定しない場合は、作業中のプロジェクトのみでこのテンプレートが利用可能になります。
アプリケーションのデプロイ
Secretの準備
[eap7-app-secret.json]
{ "kind": "List", "apiVersion": "v1", "metadata": { "annotations": { "description": "Examples that can be installed into your project to allow you to test the EAP template. You should replace the contents with data that is more appropriate for your deployment." } }, "labels": { "template": "eap7-app-secret" }, "items": [ { "kind": "ServiceAccount", "apiVersion": "v1", "metadata": { "name": "eap7-service-account" }, "secrets": [ { "name": "eap7-app-secret" } ] }, { "kind": "Secret", "apiVersion": "v1", "metadata": { "annotations": { "description": "Default secret file with name 'jboss' and password 'mykeystorepass'" }, "name": "eap7-app-secret" }, "data": { "keystore.jks": "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" } } ] }
CLIの場合
- プロジェクトの作成
oc new-project [プロジェクト名]
- Secretの登録
oc create -f eap7-app-secret.json
- アプリケーションのデプロイ
oc new-app eap70-mysql-storageclass-s2i
WebUIの場合
- プロジェクトの作成
「New Project」ボタンをクリックしてウィザードを開始します。ウィザードの「Name」フィールドにプロジェクト名を入力します。 - Secretの登録
CLIの場合と同様にSecretを作成します。oc create -f eap7-app-secret.json
- テンプレートの選択
カタログから「Java」–> 「Red Hat JBoss EAP」–> 「eap70-mysql-storageclass-s2i」 を選択 - アプリケーションのデプロイ
「Create」ボタンをクリックしてアプリケーションのデプロイを開始します。
アプリケーションのデプロイの確認
oc get route
で接続先URLを確認しブラウザでアクセスします。
ToDoアプリケーションの画面で、「Summary」と「Description」を入力します。
PVの確認
$ oc get pv NAME CAPACITY ACCESSMODES RECLAIMPOLICY STATUS CLAIM REASON AGE pvc-d8621646-e437-11e6-abba-000d3a4075fa 1Gi RWO Delete Bound app/eap-app-mysql-claim 2m $ oc get pvc NAME STATUS VOLUME CAPACITY ACCESSMODES AGE eap-app-mysql-claim Bound pvc-d8621646-e437-11e6-abba-000d3a4075fa 1Gi RWO 4m
Podを再起動して永続化されていることを確認
MySQLのPodを削除し、再起動されるのを待ちます。
$ oc get pods NAME READY STATUS RESTARTS AGE eap-app-1-0etnn 1/1 Running 0 6h eap-app-1-build 0/1 Completed 0 6h eap-app-mysql-1-a16oe 1/1 Running 0 6h $ oc delete pod eap-app-mysql-1-a16oe
MySQLのPodが再起動された、再び ToDo アプリケーションにアクセスし、先ほど入力した「Summary」と「Description」が表示されていることを確認します。