Azure Container RegistryのDocker Imageを指定してデプロイ
せっかくOpenShiftをAzureにデプロイしているので、Azureのサービスを活用した仕組みを作ってみました。
Azure Container Registryからコンテナイメージを取得するようにしておけば、危険かもしれない野良コンテナを持ち込まれないようにすることも可能になります。 また、社内のコンテナリポジトリで標準化されたコンテナイメージを配布する仕組みがあれば、OpenShift上でもローカルで実行する場合でも環境を統一することができます。
Azure Container Registry に Wildfly イメージを登録
docker hub から wildfly のコンテナイメージを取得して、Azure Container Repository に pushします。
docker pull docker.io/jboss/wildfly docker tag docker.io/jboss/wildfly xxxregistry-on.azurecr.io/komizoregistry/wildfly docker login xxxregistry-on.azurecr.io docker push xxxregistry-on.azurecr.io/komizoregistry/wildfly
OpenShift にアプリケーションをデプロイ
今回デプロイする Wildfly のコンテナイメージは、root ユーザーで実行されるようになっているので、特権コンテナとして実行するための設定と、Azure Container Registry へのアクセスに認証が必要になるのでsの設定も必要です。
プロジェクトの作成
oc new-project extrepo
Secret の作成
Azure Container Registory にアクセスするための認証情報を登録します。 docker login すると、ホームディレクトリの配下に認証情報のファイルが作成れます。 Docker version 1.12.5, build 047e51b/1.12.5 では、~/.docker/config.json ファイルです。
この認証情報を利用して、OpenShift から Azure Container Registry にアクセスするためのSecretを作成します。
oc secrets new external-registry .dockerconfigjson=docker-config.json
特権コンテナの実行を許可
OpenShiftのMasterサーバーで、クラスタ管理者(system:admin)でポリシーを設定します。
oadm policy add-scc-to-group anyuid system:serviceaccounts:extrepo
Secret を設定
oc secrets add serviceaccount/default secrets/external-registry --for=pull
コンテナイメージのpullにsecretが設定されたことを確認します。
$ oc describe serviceaccount/default Name: default Namespace: extrepo Labels: <none> Image pull secrets: default-dockercfg-8tmb3 external-registry Mountable secrets: default-token-miful default-dockercfg-8tmb3 Tokens: default-token-c36r2 default-token-miful
コンテナイメージを指定してデプロイ
アプリケーションをデプロイして、URL でアプリケーションを公開できるようにRouteを作成します。
oc new-app --docker-image=xxxregistry-on.azurecr.io/komizoregistry/wildfly:latest oc expose wildfly
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」が表示されていることを確認します。
OpenShift を活用してデリバリのリードタイムの短縮した事例
The fast-moving monolith: how we sped-up delivery from every three months, to every week – RHD Blog で紹介されている KeyBankでのリードタイム短縮のチャレンジを要約してみました。
リリースサイクルを3ヶ月から1週間へ
ここで紹介されているのは、KeyBankのリリースサイクルが四半期ごとから毎週になったという話です。
リリースサイクルを短縮するにあたっては、WebSphereからTomcatへの移行と、コンテナのランタイムとしてOpenShiftの採用
これらの変革を最重要プロジェクト(The digital channel modernization)の一環として実施
課題
- SLAを満たすようにメンテナンスするにはコストがかかる、典型的なモノリシックなアプリケーション
- 四半期リリースは、コストが高いしリスクも高く、週末の一大イベント (もちろん月曜日にはちゃんと使える状態になっていなくてはならなりません!!)
Motivation
担当者が色々と調べているときに、カンファレンスで Netflixのプレゼンを見て、自分たちよりも2-3倍の規模なのに、リリースに関わるメトリックは自分たちのそれをはるかに超えていることを知りました。 そして、銀行のDigital Channel にはウィークリのリリースは合理的であると考えました。
このプロジェクトでやったこと
- 古いアプリケーションをモダンなモバイルでも利用可能なウェブアプリケーションにすること
- プレゼンテーションレイヤとビジネスロジックレイヤを分離して、CI/CD が実現しやすいアーキテクチャにすること
- 自動化を推し進めてリードタイムを短縮すること
- 時間を浪費していた承認プロセスを削減すること
アプリケーションアーキテクチャ
対象のアプリケーション
かつて流行っていた構成でした。
新しいアーキテクチャ
- AngularJS と Ionic を採用
このプロジェクトを進めていく過程で直面した課題
Ops との戦い
アーキテクチャを変更しJAX-RS を使うためには、JDK1.7が必要でした。しかし、Ops チームはやりたがりません(寝た子は起こすななので)。しかし、 JDK1.6のサポートライフサイクルが半年で終わってしまうとサポートされた環境でシステムを運用したい Ops もやらざるを得なくなりました。
Dev vs Ops
Dev は正しい方法で自分たちのニーズを伝えられず、Opsはシステムがサービスを継続できる状態を保つことが気がかりで、新しいことにチャレンジしたがりません。 この板挟みでモデレートすることに苦労したようです。
必要なプラットフォーム
デリバリチームは、自分で必要なインフラはセルフサービスでプロビジョニングできるべきと悟り、それを実現するにはプライベートなクラウドインフラが必要という結論に達し、それには Kubernetes が最適となりました。
最適なプラットフォームはOpenShift
WebSphere で動いている古いMVCモデルのアプリケーションをモダンな技術に移行することは技術的には問題ありませんでした。しかし、以前として課題は、週次のリリースとインフラのセルフプロビジョニングと普遍のインフラの実現をどうするかということでした。
Opsチームはセルフサービスでプロビジョニングされた環境を保証しなくてはならないので、サポートのあるOpenShiftを採用しました。
自動化の促進
Jenkinsのパイプラインを活用して CI を実現し、QA環境でのテストが終わったらプロダクションにリリースできるようにしました。 しかし、プロダクションに持ち込むために、たくさんの承認プロセスがありましたが、これは時間を浪費する作業だったので、OpenShiftの中だけで済むようなコンポーネントのリリースは、承認プロセスを不要にしました。 ここまで自動化とプロセスの見直しを行いましたが、最後に残った課題は、リグレッションテストの自動化です。手動でのテストでは毎週のリリースには間に合わないので、テストツールを導入して自動化を可能としました。
まとめ
このプロジェクトを実施した結果、毎週のリリース時にサービスを止めることなく、ローリングアップデートが可能となりました。 サービスの提供環境としても、オートスケールの機能も活用して、アクセスが急激に増えた場合にも対応できるようになりました。
OpenShift の導入によって、リリースサイクルの短縮とサービス提供のSLAの向上が両方できた良い事例でした。
Horizontal Pod Autoscaler
Kubernetes Advent Calendar 2016。投稿が遅れてしまいましたが、コンテナを本番サービスで利用する場合にすごく便利ではないかなと思われる Horizontal Pod Autoscaler について紹介します。
Horizontal Pod Autoscalerとは
Horizontal Pod Autoscaler(HPA)はPodに割り当てられた CPU の使用率にしたがって、Pod の数を増減させる仕組みです。この仕組みを使うと Pod として動かしているアプリケーションが高負荷になった場合に、スケールアウトして負荷分散が可能になります。 デフォルトでは 30 秒ごとに負荷状況がチェックされ、スケールアウト/ダウンが実行されます。
ここまでで想像ができるかもしれませんが、CPU の使用率にしたがってPodを増減させるということは、CPU のメトリクスを収集する機能が実装されていなければいけません。Kubernetes では Heapster を使って CPU の使用を収集します。
OpenShift でのメトリクス収集とHPAの仕組み
メトリクス収集の仕組み
OpenShiftでは、Heapsterを使ったメトリクスの収集に加えて、Hawkular Metricsと Cassandra を利用してメトリクスの蓄積と可視化を行っています。 Heapster, Hawkular Metrics, Cassandra もそれぞれコンテナとして OpenShift 上で実行されます。
メトリクス収集の仕組みを有効にしておくと、OpenShift 管理コンソールではCPU, Memory, Network IO の状況を図のような折れ線グラフで参照することが可能になります。
HPA の仕組み
OpenShift は Kubernetes を活用した Container 型のアプリケーションプラットフォームですので、HPA の仕組みも Kubernetes の HPA と同様です。
HPA が Heapster から CPU の利用状況を、Replication Controller から稼働中のレプリカ数を取得します。CPU の使用率が閾値を超えている場合にはレプリカ数を増やし、CPU の使用率が閾値を下回った場合にはレプリカ数を減らします。また、レプリカ数が変更された場合には、 Replication Controller のステータスもアップデートされます。
OpenShift では、CPU、Memory のリソース割り当ては、Pod のデプロイ方式を定義した Deployment Config で行います。例えば、CPU の割り当てが 50m 〜 100m、メモリの割り当てが 100Mi 〜 200Mi の場合には、Deployment Config は次のようになります。
resources: limits: cpu: 100m memory: 200Mi requests: cpu: 50m memory: 100Mi
レプリカ数を 1 〜 4 個、CPU 使用率の閾値を 80% とした場合、HPA は次のようになります。
spec: maxReplicas: 4 minReplicas: 1 scaleTargetRef: apiVersion: extensions/v1beta1 kind: DeploymentConfig name: php targetCPUUtilizationPercentage: 80
OpenShift での設定
OpenShift でメトリクス収集を有効にする場合は、Heapster, Hawkular Metrics, Cassandra をそれぞれデプロイするのではなく、Metrics Deployer という、Metrics収集プラグインをセットアップするためのコンテナに環境設定を任せてしまうことができます。
設定方法を紹介する前に、ちょっとはまったことを...
今回は OpenShift Origin で環境構築をしたので、Kubernetes と Heapster のバージョンの組み合わせには注意が必要でした。
Metrics Deployer は Docker Hub から origin-metrics-deloyer のコンテナイメージ(docker.io/openshift/origin-metrics-deployer)を Pull してきて利用するのですが、latest のイメージだと、Kubernetes と Heapster のAPIバージョンが不一致となってしまい、Metrics 収集機能はりようできるけれでも HPA がちゃんと動作しませんでした。正しい組み合わせは、
Kubernetes | Heapster |
---|---|
ver 1.3 | ver 1.1 |
ver 1.4 | ver 1.2 |
Kubernetes 1.3 で heapster 1.2 を使った場合には、ログ(journal)に以下のように unmarshall できないというエラーメセージが出ていました。
W1214 05:04:48.140190 112006 horizontal.go:99] Failed to reconcile hello: failed to compute desired number of replicas based on CPU utilization for DeploymentConfig/test/hello: failed to get CPU utilization: failed to get CPU consumption and request: failed to unmarshall heapster response: json: cannot unmarshal object into Go value of type []v1alpha1.PodMetrics
メトリクスプラグインの設定
OpenShift Originのインストールは https://docs.openshift.org/latest/install_config/install/advanced_install.html に従って実施します。
メトリクス収集機能は openshift-infra というProjectにデプロイします。
Project : Kubernetes の Namespace を拡張した概念
1. Metrics URL の追加
OpenShift の Master サーバの定義ファイル /etc/origin/master/master-config.yaml
に metricsPublicURL を追加します。
Hawkular のコンテナも他のアプリケーションと同様に OpenShift にデプロイされるので、他のアプリケーションと同様に OpenShift の Route 経由でアクセス可能な URL を指定します。
assetConfig: < 中 略 > metricsPublicURL: "https://hawkular-metrics.192.168.1.1.xip.io/hawkular/metrics" < 中 略 > routingConfig: subdomain: "192.168.1.1.xip.io"
2. Service Account の作成
Metrics 収集のデプロイと実行に必要な Service Accountを作成します。
oc project openshift-infra oc create -f - <<API apiVersion: v1 kind: ServiceAccount metadata: name: metrics-deployer secrets: - name: metrics-deployer API
3. ポリシーの設定
先ほど作成した metrics-deployer、heapster, hawkular 用の Service Account に権限を付与します。
Metrics Deployer 用の Service Account に、openshift-infra プロジェクトの edit 権限を付与します。
oadm policy add-role-to-user \ edit system:serviceaccount:openshift-infra:metrics-deployer
Heapster 用の Service Account に、cluster-reader 権限を付与します。
oadm policy add-cluster-role-to-user \ cluster-reader system:serviceaccount:openshift-infra:heapster
Hawkular 用の Service Account に openshift-infra プロジェクトの view 権限を付与します。
oadm policy add-role-to-user view \ system:serviceaccount:openshift-infra:hawkular \ -n openshift-infra
4. metrics-deployer の secrets を作成
oc secrets new metrics-deployer nothing=/dev/null -n openshift-infra
5. metrics-deployer の準備
kubernetes v1.3 を使っている場合には、heapster の最新版を使ってしまうと、API バージョンが不整合になってしまいます。 そこで、既存のテンプレートを少し修正して利用します。
まず、既存のテンプレートを使って metrics-deployer をデプロイするための yaml ファイルを生成します。ここでは、簡易的にデプロイするために永続化ストレージを使わないオプション USE_PERSISTENT_STORAGE=false
もつけておきます。
oc get templates -n openshift oc process metrics-deployer-template -v HAWKULAR_METRICS_HOSTNAME=hawkular-metrics.192.168.1.1.xip.io -v USE_PERSISTENT_STORAGE=false -n openshift > metrics.yaml
Template : OpenShift にアプリケーションをデプロイするための雛形。OpenShift の Cluster 全体で利用するものは openshift プロジェクトに保持されている。
6. YAML ファイルの編集
生成された metrics.yaml
ファイルを編集します。
IMAGE_VERSION を latest から v1.3.1 に変更します。
{ "name": "IMAGE_VERSION", "value": "v1.3.1" },
利用する metrics-deployer の Image Tag を latest から v1.3.1 に変更します。
"image": "openshift/origin-metrics-deployer:v1.3.1",
7. Metrics プラグインのデプロイ
編集した YAML ファイルを利用して、metrics-deployer をデプロイします。
oc create -f metric.yaml
あとは、気長に待ちましょう。。。
8. アプリケーションの設定
https://github.com/akubicharm/OpenShiftv3HandsOn/blob/master/3.3/autoscale/autoscale.md を参考に、やってみてください。
HPA で CPU の使用率を見ていくと、こんな風に使用率が表示されます。
oc get hpa -n test -w NAME REFERENCE TARGET CURRENT MINPODS MAXPODS AGE php DeploymentConfig/php 10% 0% 1 4 21h NAME REFERENCE TARGET CURRENT MINPODS MAXPODS AGE php DeploymentConfig/php 10% 168% 1 4 21h php DeploymentConfig/php 10% 168% 1 4 21h php DeploymentConfig/php 10% 700% 1 4 21h php DeploymentConfig/php 10% 700% 1 4 21h
終わりに
HPA のような仕組みで簡単にアプリケーションをスケールアウトできるのは、Container & Kubernetes だからこそですね。HPA を設定しておけば、急なアクセス過多になった場合でも滞りなくサービスを持続することができますので、運用の利便性も高くなりますので、ぜひ、試してみてください。
OpenShift Online Next Generationがやってきたー
Red Hatが管理・運営をしているPublicなPaaS環境であるOpenShift Onlineに、待望のOpenShift v3対応のプレビュー版がリリースされました。 環境があったらOpenShift v3 を試してみたい!と考えている方必見です。
利用方法
前提条件
- Github.com のアカウントがあること。
※Github.comのアカウントがない方はまずアカウントを登録しましょう。
利用登録登録
- https://www.openshift.com/devpreview/register.html にアクセスします
Login with GitHub ボタンをクリックします
github.com のアプリケーション認証サイトで認証可能にします
OpenShift Onlineの登録フォームで必要事項を入力して「REGISTER」ボタンをクリックします このとき、Github Username, Github ID はプリセットされています。
あとはアカウント作成完了のメールを待ちましょう
メールに、OpenShift Online (v3 版)のURLがあるのでアクセスしましょう。
アプリケーションをデプロイしよう
利用登録ができたら、早速アプリケーションをデプロイしてみましょう。ここではWebUIを使ったアプリケーションのデプロイ方法をご紹介します。
OpenShiftのクラスタ内では、プロジェクト名が一意である必要があります。もしもすでに他の人が使っている名前を指定すると、こんな風にエラーになります。
OpenShiftは、テンプレートを使って簡単にアプリケーションの実行環境を構築することができます。テンプレートはベースとなるコンテナイメージ、ビルド方式、デプロイ方式などを定義することができます。 ここでは、JBoss EAPのテンプレートを使って、JBoss のサンプルアプリケーションをデプロイします。
https://github.com/jboss-developer/jboss-eap-quickstarts/tree/6.4.x/kitchensink
- 「LOGIN WITH GITHUB」ボタンをクリックしてログイン
2.「New Project」ボタンをクリックして、プロジェクト作成を開始
Nameでプロジェクト名を指定して「Create」ボタンをクリック
テンプレート一覧から「jboss-eap64-openshift:1.3」を選択
Nameにアプリケーション名を入力、「Try it」をクリックして、Git Repository URLのテキストフィールドにGithubのリポジトリを指定 ※アプリケーション名はプロジェクト内で一意であれば良いので、好きな名前をつけましょう。
「Create」ボタンをクリックして、アプリケーションのビルド&デプロイの開始
「Continue to deploy」をクリックして Overview 画面を表示
- デプロイが終わったら、アプリケーションへのリ ンクをクリックしてアプリケーションを利用
FAQ(抜粋)
https://www.openshift.com/devpreview/register.htmlにFAQがありますので、詳細はそちらを参照してください。
- 30日でアカウントは失効しデプロイしたアプリケーションも消滅します。再び利用したい場合は、再度、登録フォームで登録します。
- 1プロジェクトにつき 2GiBメモリ、4CPU Core、 1GiBの永続化ストレージx2 のリソースが利用可能です。
- 2016/6/16 時点で、利用できる言語やミドルウェアは Node.js(0.10)、 PHP(5.5, 5.6)、Python(2.7, 3.3, 3.4)、Ruby(2.0, 2.2)、 Perl(5.16, 5.20), Java(6, 7, 8, EE)とJBoss EAPとJBoss Web Server が利用可能です。 利用できるデータベースは、MongoDB(2.4, 2.6)、MySQL(5.5, 5.6)と PostgreSQL(9.2, 9.4)です。
- コンテナ内のプロセスを root ユーザ(PID=1)で実行するコンテナは、セキュリティの制限により利用できません。
OpenShift Enterprise 3 on Microsoft Azure - RHELインストール編 -
準備するもの
準備
1.Cloud Accessの登録
(1)azureのサブスクリプションの確認
(2)Red Hat Cloud Accessのエンロールを開始
http://www.redhat.com/en/technologies/cloud-computing/cloud-access にアクセスして、Cloud Access の登録をします。 画面左下の "ENROLL" をクリックします。
(3)登録
CloudProviderとMicrosoftSubscriptionNumberを入力します。
|Name|Value| |---|---| |CloudProvicer|Microsoft Azure| |MicrosoftSubscriptionNumber|(3)で確認したazureのサブスクリプション番号| |ProductName|azureで利用するRed Hatのサブスクリプションを選択| |Quantity|導入するサブスクリプションの本数を入力|
(4)登録完了
VDH イメージ
Linux VHD の作成とアップロード | Microsoft Azure に従って、アップロードするイメージの作成。
Kickstartを使いたかったのですが、Hyper-V Manager の使い方がわからないので断念。
(1)KVMイメージをダウンロード
https://access.redhat.com/downloads/content/69/ver=/rhel---7/7.2/x86_64/product-software から、KVM イメージをダウンロードします。
(2)qcow2からvdhの変換
Linux VHD の作成とアップロード | Microsoft Azure に従って guestfish で、root パスワードをchangemeに変更後、VDHへ変換。
virt-install で KVM イメージをインポート
sudo virt-install \ --connect qemu:///system \ --ram 1024 -n rhel_72_azure -r 2048 \ --os-type=linux \ --os-variant=rhel5 \ --disk path=/home/komizo/azure/rhel-guest-image-7.2-20151102.0.x86_64.qcow2,device=disk,bus=virtio,format=qcow2 \ --vcpus=2 \ --vnc \ --noautoconsole \ --import
virsh で仮想OSの起動
virsh -c qemu:///system console rhel_72_azure
Azure CLIのイストール
Azure SDK とツールのダウンロード | Azure からAzure CLI ツールをダウンロード
RHELのVM作成
(1)VDHイメージのアップロード
Linux VHD の作成とアップロード | Microsoft Azure の手順2に従って、イメージをアップロード
azure vm image create rhel-7.2 --location "Japan East" --os Linux rhel-guest-image-7.2-20151102.0.x86_64.vhd
1回目は container がないとエラーになるので、もう一度やったら出来ているっぽい。
azure vm image list
で一覧を表示すると、rhel-7.2 が表示されます。WebUIでは表示されないっぽい。
$ azure vm image list |grep rhel-7.2 data: rhel-7.2 User Linux undefined
(2)仮想OSの作成
azure vm create <仮想マシン名>.cloudapp.net rhel-7.2 --vm-size "Medium" guest --location "Japan East" info: Executing command vm create + Looking up image rhel-7.2 Enter VM 'guest' password:******** ← @Dmin123 Confirm password: ******** + Looking up cloud service info: cloud service <仮想マシン名> not found. + Creating cloud service + Creating VM info: vm create command OK
ここで、location か affinity-group の指定が必要なので、azure vm location list
か azure account affinity-group list
で確認します。
(3) SSH の有効化
仮想OS起動したのに、SSHできないーと悩んでいたら、SSHのエンドポイントがありませんでした。自分で追加する必要があります。
Webコンソールで「仮想マシン(クラッシック) > [仮想サーバ名] > 設定 > エンドポイント」を指定し、エンドポイントに SSH ようの 22 番ポートを指定。
(4)追加ユーザの作成
Webコンソールで「仮想マシン(クラッシック) > [仮想サーバ名] > 設定 > ユーザ」を指定し、ユーザと認証方式を設定します。
(5)ログイン
パスワード認証にした場合は、ユーザと仮想マシンを指定して ssh を実行します。
ssh -l <ユーザ名> <仮想マシン名>.cloudapp.net>
参考
1.Linux VHD の作成とアップロード | Microsoft Azure 2.Create and upload a Linux VHD | Microsoft Azure 3.Use the Azure CLI with Service Management | Microsoft Azure 4.Use SSH on Linux and Mac | Microsoft Azure
Optimizing Twelve-Factor Apps for OpenShift by Red Hat
原文 : Optimizing Twelve-Factor Apps for OpenShift by Red Hat - Red Hat Customer Portal
OpenShift Enterprise by Red Hat は、アプリケーションアーキテクチャ非依存な PaaS 基盤です。さらに、ステートフルな旧来型のアプリケーションも実行することができます。OpenShift Enterpriseは、モダンでステートレスな Twelve-Factor Apps も実行することができます。この文書では、Twelve-Factor Apps のアーキテクチャの最適化とOpenShift Enterprise へのデプロイの方法を紹介します。
Note: Twelve-Factor App は、モダンなクラウド環境にアプリケーションを構築するためのメソドロジーです。詳細は http://12factor.net/ja/ を参照してください。
Factor | Relationship |
---|---|
Codebase - コードベース | バージョン管理されている1つのコードベースと複数のデプロイ。OpenShift Enterpriseは、ソースコードリポジトリからソースコードを取得してアプリケーションのビルドとデプロイが可能。 |
Dependencies - 依存関係 | 依存関係を明示的に宣言し分離。OpenShift Enterprisは、プログラミング言語ごとの依存関係の管理システムの利用が可能。Maven、Java、CPANやその他にも多数のプログラミング言語の依存関係管理システムをサポート。 |
Config - 設定 | 設定を環境変数に格納する。OpenShift Enterpriseは、複数の環境変数の設定方法を提供。 |
Baking Service - バックエンドサービス | バックエンドサービスをアタッチされたリソースとして扱う。OpenShift Enterpriseでは、多数のバックエンドサービスを提供いしている(データベース、メッセージブローカなど)。さらに、外部リソースをアタッチすることも可能。 |
Build, release, run - ビルド、リリース、実行 | ビルド、リリース、実行の3つのステージを厳密に分離する。OpenShift Enterpriseは、厳密にビルド、リリース、実行のステージのコードベースを分離し、サードパーティのデプロイツール統合し、継続的インテグレーション/継続的デリバリ(CI/CD)が可能。 |
Processes - プロセス | アプリケーションを1つもしくは複数のステートレスなプロセスとして実行。OpenShift Enterpriseな、デプロイ可能な単位としてDockerコンテナをネイティブにサポート。Dockerコンテナはステートレスでポータブル。 |
Port binding - ポートバインディング | ポートバインディングを通してサービスを公開。OpenShift Enterpriseは、アプリケーションをポートバインディングによって公開し、サービスを公開可能。サービスな OpenShift 内部での利用も、バックエンドサービスとして外部に公開することも可能。 |
Concurrency - 並行性 | プロセスモデルによってスケールアウト。OpenShift Enterpriseは、手動/自動でアプリケーションをスケールアウトが可能で、真のウェブスケールのアプリケーションのデプロイが可能。 |
Disposability - 廃棄容易性 | 高速な軌道とグレースフルシャットダウンで堅牢性を最大化。コンテナの起動と停止。OpenShift Enterpriseはコンテナを利用し、堅牢なツールの仕組みを活用して、迅速な起動とグレースフルシャットダウンが可能。 |
Dev/prod parity - 開発/本番一致 | 開発、ステージング、本番環境をできるだけ一致させた状態を保つ。OpenShift Enterpriseの中の”環境”は名称が異なるだけ。唯一の本番環境か100ステップの本番環境かに関わらず、インフラもアプリケーションアーキテクチャも変更なし |
Logs - ログ | ログをイベントストリームとして扱う。OpenShift Enterpriseは、アプリケーション開発者が特別な操作をすることなしに、すべてのインスタンスのアプリケーションログデータを集約可能。 |
Admin process - 管理プロセス | 管理タスクを1回限りのプロセスとして実行。OpenShift Enterpriseはデプロイ前後のフックを実行する昨日を提供する。また、同様にcronのようなタスクを”管理/運用タスク”として実行可能。 |
Red Hat は、Twelve-Factor Apps には上記以外にも特徴があると考えている。
Characterristics | Relationship |
---|---|
Microservices - マイクロサービス | 業務として意味のある単位または、ビジネスの価値を提供することができる最小単位でのソフトウェアのビルド方式 |
Self Service Full Stack Infrastructure | OpenShiftは、セルフサービスでアプリケーションの実行環境の取得を可能にする。OS、コンテナ、ストレージ、ネットワーク、ミドルウェア、ソースコード管理/ビルド/デプロイツール |
Support your choice of deployment | OpenShiftは、物理サーバ・仮想サーバ、プライベートクラウド・パブリッククラウドなど、お好きな環境に構築可能! |
Enterprise Ready Containers | OpenShiftで採用しているDockerコンテナは、単に root ユーザ以外でコンテンを実行するだけではなく、SELinuxによってセキュリティを担保。さらに Red Hat は、Docker社以外でDockerの開発に最も貢献している。Red Hat Enterprise Linux が Docker の最適な実行環境となることを目標としている。 |
Immutable Infrastructure | OpenShift は、テストされたアプリケーションのバージョンを本番環境にデプロイできるような機能を提供。この機能により、コードベースのトレーサビリティが向上し、環境の違いによる障害を減らすことが可能。 |
API-Based Collaboration | 複数のサービスやアプリケーションを跨る連携は、公開されバージョン付けられたAPIを通じて利用。Red Hatは、サービスやアプリケーションを WebService、REST、JMSやその他のプロトコルやフォーマットを利用して連携するプロダクトを提供。→JBoss Fuse、JBoss AMQ |
Test Driven Development | Red Hatは、OpenShift/Kubernetesに配備されたアプリケーションをテストするためのMavenのプラグイン(fabric8-arquillian)を提供。fabric8-arquillianは、OpenShift/KubernetesのDockerのクラスタ環境で利用するためのArquillianの拡張。OpenShift/Kubernetesにデプロイされた環境のテストで利用可能。 |
Community Based Innovation | OpenShiftは、Kubernetes、Dockerなどのオープンソースのプロジェクトを活用。これらのプロジェクトへの有力な貢献者でありかつ、これらのプロジェクトの利用者でもある。Red Hatは、より良いソフトウェア開発を牽引している。 |
Continuous Integration and Continuous Deployment | OpenShiftは、CI/CDを実現可能とする Jenkins の Docker イメージを提供。 |