いろいろあって
いろいろあって、ESXiいじるハメに。 ひどく面倒なので、これで行く、行こう
Creating VMs on ESX using scripts and cobblerlinuxlabrat.wordpress.com
GCE上でAnsibleのチュートリアル準備
GCE上でちょこっとAnsibleを試そうと思ったときに、思いのほか認証周りが面倒だったからメモっておきます。 Ansibleをそもそもまともに使ったことがないのが原因かも。
ansibleのインストール
GCE上のCentOS6でのインストール virtualenvでpython2.7環境で
workon ansibleenv pip install ansible
External IPなしのインスタンス作成
こんなかんじで 節約のため --preemptible で一日インスタンス 外部IPなしは --no-address
gcloud compute \ --project "shaped-infusion-632" instances create "test01" \ --zone "asia-east1-a" \ --machine-type "n1-standard-1" \ --network "default" \ --no-address \ --no-restart-on-failure \ --maintenance-policy "TERMINATE" \ --preemptible \ --scopes "https://www.googleapis.com/auth/devstorage.read_only" "https://www.googleapis.com/auth/logging.write" \ --tags "http-server" "https-server" \ --image "https://www.googleapis.com/compute/v1/projects/centos-cloud/global/images/centos-6-v20150710" \ --boot-disk-type "pd-standard" \ --boot-disk-device-name "test01"
ansibleの疎通確認
ふつうにやってみる
echo "test01" > hosts ansible -i hosts test01 -m ping
うまくいかない
test01 | FAILED => SSH Error: Permission denied (publickey,gssapi-keyex,gssapi-with-mic).
鍵を指定する
echo "test01 ansible_ssh_private_key_file=~/.ssh/google_compute_engine" > hosts ansible -i hosts test01 -m ping
結果はまだダメ
test01 | FAILED => SSH Error: Host key verification failed. while connecting to 相手のIP It is sometimes useful to re-run the command using -vvvv, which prints SSH debug output to help diagnose the issue.
Host Keyがダメっていうから、チェックを環境変数から外す
export ANSIBLE_HOST_KEY_CHECKING=False
これで
ansible -i hosts test01 -m ping
結果が無事帰ってくる
test01 | success >> { "changed": false, "ping": "pong" }
認証周りがこれでクリアするので、あとは普通に使えるかと
AnsibleでのGCEインスタンス立ち上げをあきらめた
AnsibleでGCEインスタンスを立ち上げようと思ったけど、 Preemptibleという横取りという意味の一日以内に落ちるけど、安い、AWSのスポットみたいなの、を指定する設定がなかったので やめました。 遊ぶだけなので、コスパ重視
とは言っても、手元のMacからAPI叩けばいいんですが、 うちでは、Mac mini を使い、外では MacBookAirを使い、家ではMacBookAirは嫁専用機と貸していて タイミングが悪いと、Ubuntuのノートを持ち歩くことになるので GCE上に一番安いインスタンスを一個立ち上げっぱなしにして、そこに他のインスタンスを立ち上げるシェルスクリプトでもおいておくとします。
万人受けするから、CentOS6.X でいいやと思ったら、思ったよりハマりました。 けっきょく、Python2.7を入れて解決したので、手順をメモ
gceの中からインスタンス作成コマンド実行
開発ツール関連のインストール
sudo yum groupinstall "Development Tools" sudo yum install python-devel
pipのインストール
cd /tmp wget https://raw.github.com/pypa/pip/master/contrib/get-pip.py sudo python get-pip.py sudo pip install virtualenv virtualenvwrapper
python2.7のインストール
sudo rpm -ivh http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm sudo rpm -ivh http://dl.iuscommunity.org/pub/ius/stable/CentOS/6/x86_64/ius-release-1.0-11.ius.centos6.noarch.rpm sudo yum install python27 python27-devel python27-setuptools
.bashrc 関連
- .bashrc に追記
if [ -f /usr/bin/virtualenvwrapper.sh ]; then export WORKON_HOME=$HOME/.virtualenvs source /usr/bin/virtualenvwrapper.sh fi
- 読み込み
source ~/.
Virtualenvを作って入る
mkvirtualenv --python=/usr/bin/python2.7 py27
- 抜けるのと入るのだけ
deactivate py27 workon py27
pyopensslをインストールするのに必要なパッケージを入れる
sudo yum install openssl-devel libffi-devel
pyopensslのインストール(py27のvirtualenv環境で)
pip install pyopenssl
GCEの管理コンソール周り
google cloud の管理コンソールのcredentialあたりからp12ファイルを取ってくる 置く
おてもとのPCからの転送コマンド
gcloud compute copy-files hogehogekeyfile.p12 インスタンス名:~/
- CentOS6 のインスタンス上
chmod 600 hogehogekeyfile.p12 export CLOUDSDK_PYTHON_SITEPACKAGES=1 gcloud auth activate-service-account --key-file my_key_file.p12 my_service_account@developer.gserviceaccount.com gcloud config set プロジェクト名
ここまでやると、 google cloud の管理コンソールのコマンドがCentOS6から実行できる
こんなかんじのも打てるようになるよ
gcloud compute --project "プロジェクト名" \ instances create "test01" \ --zone "asia-east1-a" \ --machine-type "n1-standard-1" \ --network "default" \ --no-restart-on-failure --maintenance-policy "TERMINATE" \ --preemptible --scopes "https://www.googleapis.com/auth/devstorage.read_only" "https://www.googleapis.com/auth/logging.write" \ --tags "http-server" "https-server" \ --image "https://www.googleapis.com/compute/v1/projects/centos-cloud/global/images/centos-6-v20150710" \ --boot-disk-type "pd-standard" \ --boot-disk-device-name "test01"
Ansibleに手を出してみる (インストールだけ)
ひさびさに Google Cloud Platform を使おうと思ったら、すべて忘れてしまっていました。 また、手作業するのが面倒なので、Ansible を覚えようと思います。
Chefはなんかそれ自体でめんどくさそうに感じたのでやめました。
前提条件として、VPC まで GCP 上に作った状態でやります。 VPC は、作りっぱでも課金されないし、一回作ったら終わりなので、Ansible でやらなくてもいいかなーと思います。 (お仕事ならやります、たぶん)
インストール
$ git clone git://github.com/ansible/ansible.git --recursive $ cd ./ansible $ source ./hacking/env-setup
pip は入ってるよね
$ sudo pip install paramiko PyYAML Jinja2 httplib2
デフォルトの設定ファイルは /etc/ansible/hosts だけど、ANSIBLE_INVENTORY 環境変数の方が強いみたい。 インベントリーってなんじゃらほい
$ echo "127.0.0.1" > ~/ansible_hosts $ export ANSIBLE_INVENTORY=~/ansible_hosts
でも、とりあえずやっとく
って、ここまでやって、気づいた。 マニュアルの下の方に Mac は sudo pip install ansible って書いてある
さらに OSX Maveriks ならこれ
$ sudo CFLAGS=-Qunused-arguments CPPFLAGS=-Qunused-arguments pip install ansible
環境変数で読んでるだけっぽいから、あとで pip で入れなおす
ここまで書いてて、日本語のすごくわかりやすいブログがあったので、もういいかなってなってきてしまいました。
Solrのjoinとblock joinについて
MySQLの場合
regions
id | name |
---|---|
1 | US |
2 | ASIA |
products
id | name | brand_id_s |
---|---|---|
1 | iPhone | 1 |
2 | iPad | 1 |
3 | Galaxy S3 | 2 |
4 | Galaxy Note | 2 |
5 | one X | 3 |
brands
id | name | region_id_s |
---|---|---|
1 | Apple | 1 |
2 | Samsung | 2 |
3 | HTC | 2 |
products.name が iPad の brands を検索
JOINでこんなかんじ
mysql> SELECT brands.* FROM brands -> INNER JOIN products ON brands.id=products.brand_id_s -> WHERE products.name="iPad"; +------+-------+-------------+ | id | name | region_id_s | +------+-------+-------------+ | 1 | Apple | 1 | +------+-------+-------------+ 1 row in set (0.00 sec) mysql>
products.name が iPad の brands がある region を検索
もうちょい複雑なJOINでこんなかんじ
mysql> SELECT regions.* FROM regions -> INNER JOIN brands ON regions.id=brands.region_id_s -> INNER JOIN products ON brands.id=products.brand_id_s -> WHERE products.name="iPad"; +------+------+ | id | name | +------+------+ | 1 | US | +------+------+ 1 row in set (0.00 sec) mysql>
ここまでは普通です。とは言ってもSQLを普段書かないので、すぐにJOINでこんがらがります。
Solr の JOIN(block joinではない)の場合
brands
id | name |
---|---|
1 | Apple |
2 | Samsung |
3 | HTC |
※ brands に resion_id_s がないのは使わないので付け忘れてました
products
id | name | brand_id_s |
---|---|---|
1 | iPhone | 1 |
2 | iPad | 1 |
3 | Galaxy S3 | 2 |
4 | Galaxy Note | 2 |
5 | one X | 3 |
ただし、それぞれのフィールドごとに_versionが付く
products.name が iPad の brands を検索
/solr/brands/select?q=:&fq={!join from=brand_id_s to=id fromIndex=products}name:iPad
<?xml version="1.0" encoding="UTF-8"?> <response> <lst name="responseHeader"> <int name="status">0</int> <int name="QTime">1</int> <lst name="params"> <str name="indent">true</str> <str name="q">*:*</str> <str name="_">1404925101638</str> <str name="wt">xml</str> <str name="fq">{!join from=brand_id_s to=id fromIndex=products}name:iPad</str> </lst> </lst> <result name="response" numFound="1" start="0"> <doc> <str name="id">1</str> <str name="name">Apple</str> <long name="_version_">1473164065209581568</long></doc> </result> </response>
products.name が iPad の brands がある region を検索
3つ以上のjoinはできない
Solr の BLOCK JOIN の場合
blocks (brandsとproductsをJOINすることを前提として作成)
parents を持つものにのみ _version が付く (区切りがブロック単位)
id | name | type_s |
---|---|---|
1 | Apple | parents |
1 | iPhone | |
2 | iPad |
id | name | type_s |
---|---|---|
2 | Samsung | parents |
3 | Galaxy S3 | |
4 | Galaxy Note |
id | name | type_s |
---|---|---|
3 | HTC | parents |
5 | one X |
products.name が iPad の brands を検索
(iPadのparentsを検索)
/solr/blocks/select?q=:&fq={!parent which=type_s:parent}+name:iPad
<?xml version="1.0" encoding="UTF-8"?> <response> <lst name="responseHeader"> <int name="status">0</int> <int name="QTime">1</int> <lst name="params"> <str name="indent">true</str> <str name="q">*:*</str> <str name="_">1404923918712</str> <str name="wt">xml</str> <str name="fq">{!parent which=type_s:parent}+name:iPad</str> </lst> </lst> <result name="response" numFound="1" start="0"> <doc> <str name="id">1</str> <str name="type_s">parent</str> <str name="name">Apple</str> <long name="_version_">1473164315527741440</long></doc> </result> </response>
wblocks (brandsとproductsとregionsをJOINすることを前提として作成)
grand_parents を持つものにのみ _version が付く (区切りがブロック単位)
id | name | type_s |
---|---|---|
1 | US | grand_parents |
1 | Apple | parents |
1 | iPhone | |
2 | iPad |
id | name | type_s |
---|---|---|
2 | Asia | grand_parents |
2 | Samsung | parents |
3 | Galaxy S3 | |
4 | Galaxy Note | |
3 | HTC | parents |
5 | one X |
products.name が iPad の brands を検索
(iPadのparentsを検索) /solr/blocks/select?q=:&fq={!parent which=type_s:parent}+name:iPad
<?xml version="1.0" encoding="UTF-8"?> <response> <lst name="responseHeader"> <int name="status">0</int> <int name="QTime">0</int> <lst name="params"> <str name="indent">true</str> <str name="q">*:*</str> <str name="_">1404924377347</str> <str name="wt">xml</str> <str name="fq">{!parent which=type_s:parent}+name:iPad</str> </lst> </lst> <result name="response" numFound="1" start="0"> <doc> <str name="id">1</str> <str name="type_s">parent</str> <str name="name">Apple</str></doc> </result> </response>
products.name が iPad の brands がある region を検索
(iPadのgrand_parentsを検索)
/solr/wblocks/select?q=:&fq={!parent which=type_s:grand_parent}+name:iPad
<?xml version="1.0" encoding="UTF-8"?> <response> <lst name="responseHeader"> <int name="status">0</int> <int name="QTime">1</int> <lst name="params"> <str name="indent">true</str> <str name="q">*:*</str> <str name="_">1404924542233</str> <str name="wt">xml</str> <str name="fq">{!parent which=type_s:grand_parent}+name:iPad</str> </lst> </lst> <result name="response" numFound="1" start="0"> <doc> <str name="id">1</str> <str name="type_s">grand_parent</str> <str name="region_s">US</str> <long name="_version_">1473164347482046464</long></doc> </result> </response>
いがいとJOINってできるもんですね(白目)
この blockjoin って cloud datastore でできないかなあというのが本題です。 ちょっとだけ、joinについてまとめてみようと思ったらえらいことになってしまった。
cloud datastoreを使う前にSolrのおさらいをするためにMySQLとSolrを立てる(今回はSolr)
それでは、同様のことをSolrでしてみます。
Solrですが、たぶん、create table 的なことである、add core とかが あまりなじみがなさそうなので、順番に書きます。
コアの作成
cd solr-4.9.0/example/solr cp -pR collection1 products cp -pR collection1 brands cp -pR collection1 blocks cp -pR collection1 wblocks
先ほど、Solrを起動させたので起動状態を表すファイルの削除
rm products/core.properties rm brands/core.properties rm blocks/core.properties rm wblocks/core.properties
コアを有効にする
curl "http://localhost:8983/solr/admin/cores?action=CREATE&name=products&instanceDir=products" curl "http://localhost:8983/solr/admin/cores?action=CREATE&name=brands&instanceDir=brands" curl "http://localhost:8983/solr/admin/cores?action=CREATE&name=blocks&instanceDir=blocks" curl "http://localhost:8983/solr/admin/cores?action=CREATE&name=wblocks&instanceDir=wblocks"
ここから、gistを貼付けていこうを思いましたが、コマンド書いたりすると、(このブログが)長くなるのでxmlを落として Solrの管理画面 の Documents から更新してください。
apt-get install git
git clone https://gist.github.com/yuhiwa/d4731586c1cef2716945
git clone https://gist.github.com/yuhiwa/7e1efdbc094cda199a5f
git clone https://gist.github.com/yuhiwa/98ddfa45e1de36e1db57
git clone https://gist.github.com/yuhiwa/4da8e124925008a90eea
(nested_blocks.xml は wblocksコアです、まぎらしくなってしまった)
(あ、brands_data.xml は brands コアです、そのうち直さなきゃ)
join
wget -q 'http://localhost:8983/solr/brands/select?q=*:*&fq={!join from=brand_id_s to=id fromIndex=products}name:iPad' -O - | head
block join
wget -q 'http://localhost:8983/solr/blocks/select?q=*:*&fq={!parent which=type_s:parent}+name:iPhone' -O - | head
wblock join
wget -q 'http://localhost:8983/solr/wblocks/select?q=*:*&fq={!parent which=type_s:parent}+name:iPhone' -O - | head wget -q 'http://localhost:8983/solr/wblocks/select?q=*:*&fq={!parent which=type_s:grand_parent}+name:iPhone' -O - | head
curlコマンドだと、{}が展開されてしまうので、wget コマンドで書いてます。 Solrの管理画面のfqにfq=の先を入れてしまうのが見やすいです。
解説で次回です。