ハマった時は # init 0

試したことを書き綴ってます

k8s on windows on KVM

k8s on windows on KVM

KVM上にインストールしたWindows 10 pro の上で、k8s (docker の kubernates機能 or minikube )を起動できるのか検証してみました。

結論から言うと、dockerは無理だった。minikubeはできた。
という結果になりました。

検証環境

  • Hyper-V を有効にできるプロセッサ

  • linux

    • CPU: Intel(R) Xeon(R) CPU E3-1245 V2 @ 3.40GHz
      • 結構古い
      • Intel VT-xIntel EPT がギリギリ使えるプロセッサ
    • Memory: 16GB
  • windows 10 pro を KVM上にインストール
    • memory: 8GB割り当てた

WindowsHyper-Vを有効化

まずは、Hyper-Vを有効にする。

コントロールパネル -> プログラムと機能 -> Windowsの機能の有効化または無効化

で、Hyper-V を有効化して、windowsを再起動する。

docker for windowsk8sを試す

Install Docker Desktop on Windows | Docker Documentation
上記より、dockerをダウンロードしてインストールする

インストールが完了したら再起動の儀式をする。

docker起動

自動起動してくるので起動完了まで待つ。
Hyper-V上に、docker用のVMが作られる。(非常に時間がかかった)

起動してこない場合は、Docker Desktopを実行する。 起動完了すると、タスクバーに、Dockerが確認できる。

f:id:init0:20200306005613p:plain

kubernatesを有効化する

タスクバーのDockerアイコンよりsettingを実行。
kubernatesを有効化する。

いつまでたっても処理が完了せず、ずっと放置していたらタイムアウトしてエラーになった。
どうやらダメらしい。

Hyper-Vの上のdocker VMに接続するが、接続しても真っ黒画面のままで何か動いている気配なし。
Dockerをfactoryリセットして何度か試すが、Dockerすらまともに起動してこない状態になった。
無理そう(無茶そう)なので諦める。

minikube を試す

インストール

以下よりminikube minikube-windows-amd64.exe をダウンロードする。
Releases · kubernetes/minikube · GitHub

以下よりkubectlをダウンロードする。
kubectlのインストールおよびセットアップ - Kubernetes

それぞれのコマンドを任意の場所に配置して、環境変数でPATHを通す。

minikubeの起動

minikube start --vm-driver=hyperv

Hyper-Vを有効にしていても、有効にしろとエラーが出たので、forceをつけて起動した。

minikube start --vm-driver=hyperv --force

Hyper-V 上に、minikubeという名前のVMが自動で作られる。
ちなみに、このVMには、user=docker, password=tcuser でログインできる。

f:id:init0:20200306005725p:plain

VM作成されたが、しばらくするとコマンドはエラーになった・・・
VMが起動してくるのが遅すぎてエラーになった模様??

C:\opt>minikube start --vm-driver=hyperv  --force
* minikube v1.7.3 on Microsoft Windows 10 Pro 10.0.18363 Build 18363
* Using the hyperv driver based on user configuration

! 'hyperv' driver reported an issue: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe Get-WindowsOptionalFeature -FeatureName Microsoft-Hyper-V-All -Online failed:

* Suggestion: Start PowerShell as Administrator, and run: 'Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All'
* Documentation: https://minikube.sigs.k8s.io/docs/reference/drivers/hyperv/

* Creating hyperv VM (CPUs=2, Memory=2000MB, Disk=20000MB) ...
*
X Unable to start VM. Please investigate and run 'minikube delete' if possible: creating host: create host timed out in 120.000000 seconds
*
* minikube is exiting due to an error. If the above message is not useful, open an issue:
  - https://github.com/kubernetes/minikube/issues/new/choose

C:\opt>

一度stopしてからもう一度startしたらいけた。ただし数分待った。希望が見えた。

minikube stop
C:\opt>minikube start --force
* minikube v1.7.3 on Microsoft Windows 10 Pro 10.0.18363 Build 18363
* Using the hyperv driver based on existing profile

! 'hyperv' driver reported an issue: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe Get-WindowsOptionalFeature -FeatureName Microsoft-Hyper-V-All -Online failed:

* Suggestion: Start PowerShell as Administrator, and run: 'Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All'
* Documentation: https://minikube.sigs.k8s.io/docs/reference/drivers/hyperv/

* Reconfiguring existing host ...
* Starting existing hyperv VM for "minikube" ...
* Preparing Kubernetes v1.17.3 on Docker 19.03.6 ...
* Launching Kubernetes ...
* Enabling addons: dashboard, default-storageclass, storage-provisioner
* Done! kubectl is now configured to use "minikube"

C:\opt>
C:\opt>minikube status
host: Running
kubelet: Running
apiserver: Running
kubeconfig: Configured

dashboardが見れるか確認。

minikube dashboard

勝手にブラウザが立ち上がり、ダッシュボードが見れた。しかし、描画がすごく遅い。

f:id:init0:20200306005755p:plain

podの起動

C:\opt>kubectl create deployment hello-minikube --image=k8s.gcr.io/echoserver:1.10
deployment.apps/hello-minikube created

C:\opt>kubectl expose deployment hello-minikube --type=NodePort --port=8080
service/hello-minikube exposed

C:\opt>kubectl get pods
NAME                              READY   STATUS    RESTARTS   AGE
hello-minikube-797f975945-2cz52   1/1     Running   0          10h

立ち上がったので、接続してみる。

URLを調べて、ブラウザで接続する。

C:\opt>minikube service hello-minikube --url
http://192.168.187.8:31775

f:id:init0:20200306005823p:plain
image-4

無事接続できた。

まとめ

  • minikubeなら、k8s on windows on KVM ができた。
  • しかし、非常に遅い、重いので実利用には向かない(勉強にも向かない)
    • windows VM の上に、VM でさらにコンテナってそもそも無茶ですが・・・
    • もしかしたらスペシャルマシン上でリッチなwindows VM を立てれば快適なのかもしれない。

AppleWatch WatchKitでHelloWorld

AppleWatch用のHelloWorldを表示するアプリをサクッと作るメモです。

開発環境

Xcodeプロジェクトを作る

まずは、Xcodeでプロジェクトを作ります。

File -> New -> Project から、watchOS を選択してiOS App with WatchKit App を選択します。

f:id:init0:20190901214647p:plain

入力項目を埋めます。 HelloWorldを表示する程度のアプリなので、Notification Scene や、Complicationは不要です。 Unit Testsもしないですが、チェックつけるだけつけておきます。

f:id:init0:20190901215529p:plain

Next で、プロジェクトの保存場所を聞かれるので、好きな場所に作ってプロジェクト作成は完了です。

実装

次に実装します。実装としていますが、ソースは書かないでポチポチするだけです。 xcodeで、WatchKitAppの、interface.storyboardを選択すると、アプリ画面が表示されます。

f:id:init0:20190901220710p:plain

画面上の方のLibraryからLabelを選び、アプリの上にドラッグ&ドロップします。

f:id:init0:20190901220933p:plain

Labelを貼り付けたら、Labelをクリックして、右のツールボックスから、「Attribute inspector」の設定を開き、Textに「HelloWorld」を入力して、実装は完了です。

f:id:init0:20190901222145p:plain

シミュレーターを起動する。

schema、シミュレーターを設定して実行します。実行するとシミュレーター上で作成したアプリのインストールが行われ、アプリが自動的に起動してきます。

たまに、AppleWatch側シミュレーターでアプリインストールが空振りすることがあったので、自動起動してこないときは、もう一度起動してみると良いと思います。

f:id:init0:20190901221917p:plain

f:id:init0:20190901222011p:plain

実機でアプリを起動する(実機にアプリをインストールする)

MacIPhoneをUSBケーブルで接続します。

接続すると、IPhoneとAppleWatch上で、デバイスを信用するか認証が走りますので、承認します。 承認すると、Device and Simurator で、実機が選択できるようになります。 実機を選択して、シミュレーター同様に起動して、完了です。

f:id:init0:20190901222824p:plain

アプリ起動時に、証明書(署名)関連のエラーが出て起動できない場合は、証明書を作成します。

メニューの Xcode -> Preferences -> Accounts -> 「+」ボタン -> AppleID -> continue
そして、AppleIDを入力。 Manage Certificates をクリックすると証明書を作成できる画面に行くので、証明書を作成します。

f:id:init0:20190901230650p:plain

f:id:init0:20190901230937p:plain

証明書をアプリに設定します。

f:id:init0:20190901231312p:plain

General設定画面を開き、Targets から、iOSアプリ、WatchKitApp、WatchKitExtension の3つの、署名設定で、Teamを設定します。 私は、iOSアプリしか設定せず、Watchアプリにも設定しなければいけないことに気づかず、署名エラーが全然解消できず、ハマりました。

あとは、アプリを起動すれば次はエラーは解消されて、アプリインストールが始まり、起動できるようになるはずです。

以上で、AppleWatchで、HelloWorldを表示する簡単なアプリの実装と起動は完了です。

XcodeのUIがコロコロ変わるので、数年前の情報通りに実装できないのと、
署名周りでハマりました。
これらさえ攻略できれば数分で簡単にHelloWorldくらいは表示できると思います。

fish shell を導入した時のメモ書き

fish3

fishを導入した時のメモ書き。

インストール

brewで簡単にインストールできます

brew install fish

brewでインストールしていると最後に

You will need to add:
  /usr/local/bin/fish
to /etc/shells.

と出るので、 /etc/shells/usr/local/bin/fishを書きます。

デフォルトshellにしたい人は、

chsh -s /usr/local/bin/fish

を実行します。

fishの設定ファイル

bashでいう.bashrcのようなshellの設定ファイルは、

~/.config/fish/conf.dの下に配置するようです。

プラグインマネージャー

fishのプラグインマネージャーはいくつかあるみたいですが、fishermanを使ってみます。

GitHub - jorgebucaran/fisher: A package manager for the fish shell

READMEにしたがって導入していきます。

curl https://git.io/fisher --create-dirs -sLo ~/.config/fish/functions/fisher.fish
fisher -version
fisher version 3.1.1 ~/.config/fish/functions/fisher.fish

3.1.1が入りました。

fisherというコマンドが使えるようになり、fisher addプラグインを追加できます。 githubで公開されているプラグインならなんでもインストールできるようです。

fisher addの後にgitリポジトリ名を指定するとインストールできます。 <https://github.com/jethrokuan/fzf> をインストールしたい場合は、 fisher add jethrokuan/fzf とコマンドを打つとインストールできます。

themeを変える

このサイトにテーマ例が色々載っています。 oh-my-fish/Themes.md at master · oh-my-fish/oh-my-fish · GitHub

cbjohnsonを入れてみました。

fisher add oh-my-fish/theme-cbjohnson

プラグインを入れる

fzf

Ctrl + rでのコマンドの再帰検索が楽になる。

brew install fzf
fisher add jethrokuan/fzf

fish_config

fishの設定ができる便利なコマンド。python3が必要なので事前にインストールしておきます。 コマンドを叩くとブラウザで設定画面が上がってきますのでブラウザで設定変更できるようです。

Macで、USBメモリーにISOイメージを書き込む

Macで、OSインストーラーなどのISOイメージを、USBメモリーに書き込みたい時。

USBメモリMacに挿してから、diskutil list コマンドでデバイス名を確認する。 この例では、/dev/disk2がUSBメモリです。(TOSHIBA製のUSBメモリー使ってます。)

» diskutil list
/dev/disk0 (internal):

...

/dev/disk1 (synthesized):

...

/dev/disk2 (external, physical):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:     FDisk_partition_scheme                        *15.5 GB    disk2
   1:                 DOS_FAT_32 TOSHIBA                 15.5 GB    disk2s1

次に、diskutil eraseDisk コマンドでUSBメモリーをフォーマットします。 第1引数が、フォーマット、第2引数が、任意の名前、第3引数がデバイスです。

diskutil eraseDisk MS-DOS INSTALLER /dev/disk2

補足ですが、使えるフォーマットは以下で調べられます。

» diskutil listFilesystems
Formattable file systems

These file system personalities can be used for erasing and partitioning.
When specifying a personality as a parameter to a verb, case is not considered.
Certain common aliases (also case-insensitive) are listed below as well.

-------------------------------------------------------------------------------
PERSONALITY                     USER VISIBLE NAME
-------------------------------------------------------------------------------
APFS                            APFS
  (or) APFSI
Case-sensitive APFS             APFS (Case-sensitive)
ExFAT                           ExFAT
MS-DOS                          MS-DOS (FAT)
MS-DOS FAT12                    MS-DOS (FAT12)
MS-DOS FAT16                    MS-DOS (FAT16)
MS-DOS FAT32                    MS-DOS (FAT32)
  (or) FAT32
HFS+                            Mac OS Extended
Case-sensitive HFS+             Mac OS Extended (Case-sensitive)
  (or) HFSX
Case-sensitive Journaled HFS+   Mac OS Extended (Case-sensitive, Journaled)
  (or) JHFSX
Journaled HFS+                  Mac OS Extended (Journaled)
  (or) JHFS+
Free Space                      空き領域
  (or) FREE

USBメモリーをunmountします。

diskutil unmountDisk /dev/disk2

最後に、dd でISOイメージをUSBメモリーに書き込みます。 書き込み先を間違えないように注意。

sudo dd if=/tmp/ubuntu-19.04-live-server-amd64.iso of=/dev/disk2 bs=4096

これで少し待てば完了です。

書き込みが終わると、Macのデスクトップ上に突然「マウントできないディスクだ」という感じのエラーが突然でました・・・。マウントしようとした模様です。

spring boot + micrometer.io + prometheusで簡単メトリクス監視

最近、prometheusを使い始めましたので、java(spring boot)でメトリクス収集のスタンダードとなりつつあるmicrometer.ioを調べてみました。


はじめに

micrometer.ioは、javaアプリの性能監視用メトリクスを収集して任意のモニタリングサービスと連携してくれるライブラリです。

prometheusやinfluxDBと連携してとっても簡単に性能モニタリングや性能監視ができます。

連携できるサービスは Spring Boot Reference Guide に記載されています。

micrometer.ioでは、

サーブレット周りのメトリクス(リクエスト数やレスポンスタイム、ステータスコードごとのレスポンス数)、WebFlux、datasource、schedulerなどなどのメトリクスが取得可能です。

spring bootでmicrometerを使う場合は、dependencyにmicrometerを追加するだけで、AutoConfigurationによって諸々Bean生成&AOPされ、コードを一切書かずにメトリクス収集できてしまいます。

使ってみた範囲では、サーブレット周りのメトリクスは、dependency追加だけで収集してくれました。

任意のメソッドの処理速度を測りたい場合は、アノテーション(たぶん@Timed)を付与するだけで取れちゃうそうです。

また、spring boot 2からは、micrometerがbootに統合され、bootでのメトリクス収集のデファクトになっています。


試してみた

各種ソフトウェアのバージョンなど

次のソフトウェアバージョンで試してみました。

  • Java ... java1.8
  • spring boot ... 1.5.10
  • micrometer ... 1.0
  • prometheus ... 2.2.0 rc1

また、お試し用に、簡単なRestサービスを作りサーブレットのメトリクスを取ってみました。


gradleやmavendependency設定

gradleやmavendependencyに以下を追加します。

  • micrometer-spring-legacy
    • spring boot 1.5ではmicrometerを引っ張る必要があります。2.0からは不要かな?
  • micrometer-registry-prometheus
    • prometheusと連携するために追加します。これと次のactuatorを組み合わせてprometheus用のエンドポイントが自動作成されます。
  • spring-boot-starter-actuator
    • prometheus用のエンドポイントはactuatorを利用します。

gradleだと以下のような設定になります。

dependencies {
    compile('org.springframework.boot:spring-boot-starter-actuator')
    compile('org.springframework.boot:spring-boot-starter-web')

    compile('io.micrometer:micrometer-spring-legacy:latest.release')
    compile('io.micrometer:micrometer-registry-prometheus:1.0.0')

    testCompile('org.springframework.boot:spring-boot-starter-test')
}


prometheusエンドポイントの認証設定 (actuatorの認証設定)

application.propertiesやymlで、prometheusエンドポイントの認証設定を行います。

デフォルトでは認証がかかっていますが、お試しなので、認証を解除しておきます。

actuatorを利用してprometheus用のエンドポイントが作られていますので、以下で認証を解除できます。

endpoints.prometheus.sensitive=false

以上の設定だけで、メトリクスが収集され、prometheus向けのエンドポイントができあがります。

エンドポイントは/prometheusです。


メトリクスを見てみる

ローカルでアプリを動かした場合は、localhost:8080/prometheusに接続するとprometheus向けのメトリクスが参照できます。

次のようなメトリクスが取れます。

サンプルとして、/demo/sleep(ランダムスリープするAPI)と/greeting(hello worldを返却するだけ)を作成しており、何回かアクセスした後に、メトリクスを参照しています。

http_server_requests_seconds_{count,max,sum}がHTTPリクエストのメトリクスです。 その他にもCPUやメモリ、Javaヒープのメトリクスなどなどがデフォルトで取得できます。


prometheusの設定

prometheusで、監視対象として作成したエンドポイント(/prometheus)を追加します。

設定ファイル(prometheus.yml)で以下のような設定を追加すれば完了です。

scrape_configs:
  - job_name: 'spring'
    metrics_path: '/prometheus'
    scrape_interval: 30s
    static_configs:
      - targets: ['localhost:8080']

まとめ

spring boot とmicrometerを組み合わせることで、dependencyの追加と、application.properties/yml の設定だけでコードは一切書かずにメトリクスを取れてしまいます。 めちゃめちゃ簡単です。

micrometer以外では、prometheusオフィシャルのsimpleclientでもうちょっと違うメトリクスが取得できます。用途に合わせてsimpleclientと組み合わせたりして使うとよいとおもいます。 prometheusにはzipkinプラグインがありますので、これも調べたいと思います。

また、WebFluxのメトリクス取得や、scheduler, datasourceのメトリクスがどんなものが取得できるのかも試したいですね。


今回試したサンプルアプリはgithubに登録してあります。
GitHub - ikeda-mk/prometheus-micrometer-demo

AWS API Gateway + lambda で任意のHTTPステータスコードを返却する

API Gateway + lambda で、任意のHTTPステータスコードを返却したい場合、次のことを行えば任意ステータスコードを返却できるようになります。

lambdaが正常終了した場合は、正規表現チェックの対象にならないようなので、lambdaは例外スローする必要があります。

lambda ファンクション作成

まずは、次のようなlambdaファンクションを作成してみます。 名前は、"test_lambda_function"としました

  • パラメータに、key1 または、key2が含まれていないと例外をthrow
  • key2が整数ではない場合、例外throw
# -*- coding: utf-8 -*-
import json
import types

def lambda_handler(event, context):

    print("Received event: " + json.dumps(event, indent=2))
    
    
    if not "key1" in event:
        raise Exception("Parameter error. Missing field 'key1'.")
    if not "key2" in event:
        raise Exception("Parameter error. Missing field 'key2'.")
    if not type(event["key1"]) is types.UnicodeType:
         raise Exception("Parameter error. 'key1' is not a UnicodeType")
         
    try:    
        # key2が整数ではない場合、例外throw
        return 10 + event["key2"]

    except Exception as e:
        raise Exception("Internal error. " + e.message)

API Gateway を作成する。

次のように、先ほど作成したlambdaファンクションを実行するAPI Gateway を作成します。 demoというリソースを作成し、POSTメソッドを作成しています。

f:id:init0:20161127233012p:plain

API Gateway で Method Responseを設定する

Method Responseの設定画面で、HTTPステータスに400(バッドリクエスト)と500(サーバーエラー)を追加します。

f:id:init0:20161127234317p:plain

API Gateway で Integration Responseの設定

Integration Responseの設定画面で、Integration Responseを追加します。 次の2つの設定を追加します。

  • lambdaの例外メッセージに"Parameter error"という文字列が含まれていた場合に、400を返却
  • lambdaの例外メッセージに"Internal error"という文字列が含まれていた場合に、500を返却

f:id:init0:20161127235143p:plain

二つ設定が終わると、以下のようになります。

f:id:init0:20161127235334p:plain

ここまでの設定で、任意ステータスコードが返却できる簡単な設定が完了しました。

テストしてみる

デプロイし動作確認してみます。

f:id:init0:20161128003428p:plain f:id:init0:20161128003410p:plain

正常系

正しいJSONパラメータでHTTPのPOSTリクエストを実行し、200が返却されることを確認してみます。

$ curl -d '{"key1": "aaa", "key2": 100}' \
>     -i -H "Content-type: application/json" -X POST \
>     https://l43dvdh5bj.execute-api.ap-northeast-1.amazonaws.com/devel/demo
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 3
Connection: keep-alive

### (中略) ###

110
パラメータエラー(400)を確認

key2を設定していないリクエストを実行し400が返却されることを確認します。

$ curl -d '{"key1": "aaa"}' \
>     -i -H "Content-type: application/json" -X POST \
>     https://l43dvdh5bj.execute-api.ap-northeast-1.amazonaws.com/devel/demo
HTTP/1.1 400 Bad Request
Content-Type: application/json
Content-Length: 219

### (中略) ###

{"stackTrace": [["/var/task/lambda_function.py", 13, "lambda_handler", "raise Exception(\"Parameter error. Missing field 'key2'.\")"]], "errorType": "Exception", "errorMessage": "Parameter error. Missing field 'key1'."}
インターナルサーバーエラー(500)を確認

インターナルサーバーエラーが発生するようにkey2に文字列を入力し、500が返却されることを確認します。

$ curl -d '{"key1": "aaa", "key2": "bbb"}' \
>     -i -H "Content-type: application/json" -X POST \
>     https://l43dvdh5bj.execute-api.ap-northeast-1.amazonaws.com/devel/demo
HTTP/1.1 500 Internal Server Error
Content-Type: application/json

### (中略) ###

{"stackTrace": [["/var/task/lambda_function.py", 21, "lambda_handler", "raise Exception(\"Internal error. \" + e.message)"]], "errorType": "Exception", "errorMessage": "Internal error. unsupported operand type(s) for +: 'int' and 'unicode'"}

レスポンスBodyを修正する。

このままでは、レスポンスのJsonに、スタックトレースがそのまま出力され、かっこ悪いので、レスポンスを編集してみます。

API Gateway の Integration Response で Mapping Template を定義することで修正できます。

デフォルトでは、以下のパラメータがJsonレスポンスに設定されています。 * stackTrace ... スタックトレースがそのまま設定 * errorType ... Exceptionのクラス名(型) * errorMessage ... Exceptionのメッセージ

errorMessageのみ出力するように設定してみます。

f:id:init0:20161128010745p:plain

デプロイし、確認してみます。

lavigne:~ mak$ curl -d '{"key1": "aaa"}' \
>     -i -H "Content-type: application/json" -X POST \
>     https://l43dvdh5bj.execute-api.ap-northeast-1.amazonaws.com/devel/demo
HTTP/1.1 400 Bad Request
Content-Type: application/json
Content-Length: 62

### (中略) ###

{
  "errorMessage": "Parameter error. Missing field 'key2'."
}

openstack havana on ubuntu 13.10 (cinder)

openstackとりまとめページ http://init0.hatenablog.com/entry/2013/10/05/232939

LVMの設定

まずは、cinder用に VGを作成します。

nova 用に、ディスクパーティションを用意できる人用

ディスクに空きパーティションがある人は、一般的な方法で、VGを作成する。

  • vgの名称は、cinder-volumes とする。
    • cinderのデフォルト設定では、「cinder-volumes」を使うため。
# pvcreate /dev/sdb1
# vgcreate  cinder-volumes /dev/sdb1
# vgdisplay 
  --- Volume group ---
  VG Name               cinder-volumes
  System ID             
  Format                lvm2
  Metadata Areas        1
  Metadata Sequence No  1
  VG Access             read/write
  VG Status             resizable
  MAX LV                0
  Cur LV                0
  Open LV               0
  Max PV                0
  Cur PV                1
  Act PV                1
  VG Size               50.00 GiB
  PE Size               4.00 MiB
  Total PE              12799
  Alloc PE / Size       0 / 0   
  Free  PE / Size       12799 / 50.00 GiB
  VG UUID               H14HUP-XwkY-EeQt-tqpT-iNGG-abOt-gmBo2x
   

空きパーティションがない人向け

cinder用に使える空きパーティションがない場合は、ddでファイルを作成し、ループバックマウントして無理やりVGを作成する。

  • 再起動するたびに、losetupしないといけないので、/etc/rc.localに、losetupを記載すると便利。
# dd if=/dev/zero of=/home/cinder01.img bs=1024 count=10000000
# losetup -f /home/cinder01.img
# pvcreate /dev/loop0
  Physical volume "/dev/loop0" successfully created
# vgcreate cinder-volumes /dev/loop0
  Volume group "cinder-volumes" successfully created

DB作成

cinder用にDBを作成します。

  • 事前に、stack@localhost、stack@% というユーザは作成済みです。
  • cinderという名称で、DBを作成
  • stackユーザに、cinder DBを操作する全権限を付与する。
# mysql -u root -p
mysql> CREATE DATABASE cinder;
mysql> GRANT ALL PRIVILEGES ON cinder.* TO 'stack'@'localhost';
mysql> GRANT ALL PRIVILEGES ON cinder.* TO 'stack'@'%';

cinderインストール・設定

インストール

# aptitude install cinder-volume cinder-api cinder-scheduler

設定ファイル変更

  • /etc/cinder/cinder.conf
    • DBへの接続設定を追加する。

以下を追加

[database]
sql_connection = mysql://stack:stack@localhost/cinder
  • /etc/cinder/api-paste.ini
    • keystoneへの接続設定を記載する
# 省略
[filter:authtoken]
paste.filter_factory = keystoneclient.middleware.auth_token:filter_factory
auth_host = 127.0.0.1
auth_port = 35357
auth_protocol = http
admin_tenant_name = service
admin_user = cinder
admin_password = cinder
# 省略

DBにスキーマ登録

# cinder-manage  db sync

keystoneの設定

  • cinderユーザ作成
keystone user-create \
        --name=cinder \
        --pass=cinder \
        --email=cinder@example.com
  • cinderユーザにroleを付与
    • serviceテナントのadminとしてロールを作成。
    • tenant-id, user-id, role-idを事前に調べ、user-role-addの引数で渡す。
# keystone tenant-list | grep service
| 63db5b3fccf04d66b87091d5fbe771b7 | service |   True  |

# keystone user-list | grep cinder
| 300f04f6e9ac442d81ef3ea87fa969c1 |  cinder |   True  |  cinder@example.com |

 # keystone role-list | grep admin
| 58489d413e69439699875718d1407307 |        admin         |

keystone user-role-add \
        --tenant-id 63db5b3fccf04d66b87091d5fbe771b7 \
        --user-id 300f04f6e9ac442d81ef3ea87fa969c1 \
        --role-id 58489d413e69439699875718d1407307
  • REST API バージョン1用のendpointを作成
keystone service-create --name=cinder --type=volume \
  --description="Cinder Volume Service"

# keystone service-list | grep cinder
| 29c2d484d0f64a768423d90c5515b787 |  cinder  |    volume    |      Volume Service      |

keystone endpoint-create \
  --service-id= 29c2d484d0f64a768423d90c5515b787 \
  --publicurl=http://192.168.0.110:8776/v1/%\(tenant_id\)s \
  --internalurl=http://192.168.0.110:8776/v1/%\(tenant_id\)s \
  --adminurl=http://192.168.0.110:8776/v1/%\(tenant_id\)s
  • REST API バージョン2用のendpointを作成
keystone service-create --name=cinderv2 --type=volumev2 \
  --description="Cinder Volume Service V2"

# keystone service-list | grep cinderv2
| a9bbd40f7f9a46debd1f53511fc15d6c | cinderv2 |   volumev2   | Cinder Volume Service V2 |

keystone endpoint-create \
  --service-id=a9bbd40f7f9a46debd1f53511fc15d6c \
  --publicurl=http://192.168.0.110:8776/v2/%\(tenant_id\)s \
  --internalurl=http://192.168.0.110:8776/v2/%\(tenant_id\)s \
  --adminurl=http://192.168.0.110:8776/v2/%\(tenant_id\)s

cinderの再起動

service cinder-api restart
service cinder-volume restart
service cinder-scheduler restart

動作確認

cinderコマンドを使い、volumeを作成・削除する。

# cinder create --display-name vol01 1
# cinder list
+--------------------------------------+-----------+--------------+------+-------------+----------+-------------+
|                  ID                  |   Status  | Display Name | Size | Volume Type | Bootable | Attached to |
+--------------------------------------+-----------+--------------+------+-------------+----------+-------------+
| 521c6a82-0aac-4418-a6b4-b458353c6039 | available |    vol01     |  1   |     None    |  false   |             |
+--------------------------------------+-----------+--------------+------+-------------+----------+-------------+

# cinder delete vol01

novaのVMインスタンスにvolumeをアタッチする。

VM起動
nova boot --image ubuntu13.04-qcow2  --flavor 2 --key-name default vm01
volume作成 + アタッチ
nova volume-create --display-name vol01 1

# nova volume-list | grep vol01 | awk '{ print $2 }'
1e3534f0-e3c4-4147-82ec-c2cd9a86bd8f

nova volume-attach vm01 1e3534f0-e3c4-4147-82ec-c2cd9a86bd8f  /dev/vdb
VM上でアタッチされたボリュームを使用する
root@vm01:~# fdisk -l /dev/vdb

Disk /dev/vdb: 1073 MB, 1073741824 bytes
16 heads, 63 sectors/track, 2080 cylinders, total 2097152 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000

Disk /dev/vdb doesn't contain a valid partition table




root@vm01:~# fdisk /dev/vdb
Device contains neither a valid DOS partition table, nor Sun, SGI or OSF disklabel
Building a new DOS disklabel with disk identifier 0xcc49baf5.
Changes will remain in memory only, until you decide to write them.
After that, of course, the previous content won't be recoverable.

Warning: invalid flag 0x0000 of partition table 4 will be corrected by w(rite)

Command (m for help): n
Partition type:
   p   primary (0 primary, 0 extended, 4 free)
   e   extended
Select (default p): p
Partition number (1-4, default 1): 
Using default value 1
First sector (2048-2097151, default 2048): 
Using default value 2048
Last sector, +sectors or +size{K,M,G} (2048-2097151, default 2097151): 
Using default value 2097151

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.
Syncing disks.
root@vm01:~# mkfs.ext4 /dev/vdb1 
mke2fs 1.42.5 (29-Jul-2012)
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
Stride=0 blocks, Stripe width=0 blocks
65536 inodes, 261888 blocks
13094 blocks (5.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=268435456
8 block groups
32768 blocks per group, 32768 fragments per group
8192 inodes per group
Superblock backups stored on blocks: 
    32768, 98304, 163840, 229376

Allocating group tables: done                            
Writing inode tables: done                            
Creating journal (4096 blocks): done
Writing superblocks and filesystem accounting information: done
root@vm01:~# mount /dev/vdb1 /mnt/
  • ファイルを作成する。
root@vm01:~# ls /mnt/
lost+found
root@vm01:~# echo "HELLO" > /mnt/hello.txt
  • アンマウントする。
root@vm01:~# umount /mnt 
root@vm01:~# 
volumeデタッチ
nova volume-detach  vm01 1e3534f0-e3c4-4147-82ec-c2cd9a86bd8f
別のVMに作成済みvolumeをアタッチする
# nova boot --image ubuntu13.04-qcow2  --flavor 2 --key-name default vm02
# nova volume-attach vm02 `nova volume-list | grep vol01 | awk '{ print $2 }'` /dev/vdb
VM上でファイルシステムをマウント
  • マウントし、別VMで作成したファイルが存在するか確認
ubuntu@vm02:~$ mount /dev/vdb
vdb   vdb1  
ubuntu@vm02:~$ mount /dev/vdb1 /mnt/
mount: only root can do that
ubuntu@vm02:~$ sudo su - 
root@vm02:~# mount /dev/vdb1 /mnt/
root@vm02:~# ls /mnt/
hello.txt  lost+found
root@vm02:~# cat /mnt/hello.txt 
HELLO