さくらのクラウドをTerraformから作る

さくらのクラウドをTerraformから作る

わざわざTerraform使わずにコンパネからポチポチ作れるが、Terraform使ってみたかったしテスト環境とか複数の環境用意するときに手順忘れるので使ってみた。

sacloud.github.io

バージョン

CentOS7
Terraform v0.11.13
Terraform for さくらのクラウド v1.11

インストール

curl -L https://releases.hashicorp.com/terraform/0.11.13/terraform_0.11.13_linux_amd64.zip > ~/terraform/terraform.zip
unzip terraform
echo export PATH=$PATH:~/terraform/ ~/.bash_profile

http://releases.usacloud.jp/terraform/

さくらのクラウド for terraform をterraformのディレクトリに入れる

mkdir sakura
vi sakura 
provider "sakuracloud" {
    token = "[ACCESS_TOKEN]"
    secret = "[ACCESS_TOKEN_SECRET]"
}
terraform init

動く

Initializing provider plugins...

The following providers do not have any version constraints in configuration,
so the latest version was installed.

To prevent automatic upgrades to new major versions that may contain breaking
changes, it is recommended to add version = "..." constraints to the
corresponding provider blocks in configuration, with the constraint strings
suggested below.

* provider.sakuracloud: version = "~> 1.11"

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

qiita.com を参考に進める

環境変数に設定して使うこともできる
export SAKURACLOUD_ACCESS_TOKEN=
export SAKURACLOUD_ACCESS_TOKEN_SECRET=
export SAKURACLOUD_ZONE=tk1v
  • tk1a … 東京第1ゾーン
  • is1a … 石狩第1ゾーン
  • is1b … 石狩第2ゾーン
  • tk1v ... サンドボックス

SAKURACLOUD_ZONEをサンドボックスにすると、料金がかからないで作ったり壊したりできる。ありがたい。

manual.sakura.ad.jp

terraformの基本的なコマンド

terraform init
terraform validate
terraform plan
terraform apply
terraform destroy

  • グラフ化
terraform graph > input.dot
dot -Tpng <(terraform graph) -o dependency.png

参考

Bulk Insertした場合のレスポンスをfilter_pathで整形する

Bulk Insertした場合のレスポンスをfilter_pathで整形する

http://localhost:9200/logs/_bulk?filter_path=

",",".","*","-"を駆使して任意の形のレスポンスデータで返ってくるようにできる

  • filter_pathを指定しないでinsertした場合
{
  "took" : 3,
  "errors" : false,
  "items" : [
    {
      "index" : {
        "_index" : "test-2019-05-10",
        "_type" : "_doc",
        "_id" : "4-gXoWoBgMJV7DS8CVGx",
        "_version" : 1,
        "result" : "created",
        "_shards" : {
          "total" : 1,
          "successful" : 1,
          "failed" : 0
        },
        "_seq_no" : 15,
        "_primary_term" : 1,
        "status" : 201
      }
    },
    {
      "index" : {
        "_index" : "test-2019-05-10",
        "_type" : "_doc",
        "_id" : "5OgXoWoBgMJV7DS8CVGx",
        "_version" : 1,
        "result" : "created",
        "_shards" : {
          "total" : 1,
          "successful" : 1,
          "failed" : 0
        },
        "_seq_no" : 13,
        "_primary_term" : 1,
        "status" : 201
      }
    }
  ]
}

?filter_path=took,itemsとすると "errors"を除いたデータが返ってくる

{
  "took" : 3,
  "items" : [
    {
      "index" : {
        "_index" : "test-2019-05-10",
        "_type" : "_doc",
        "_id" : "4-gXoWoBgMJV7DS8CVGx",
        "_version" : 1,
        "result" : "created",
        "_shards" : {
          "total" : 1,
          "successful" : 1,
          "failed" : 0
        },
        "_seq_no" : 15,
        "_primary_term" : 1,
        "status" : 201
      }
    },
    {
      "index" : {
        "_index" : "test-2019-05-10",
        "_type" : "_doc",
        "_id" : "5OgXoWoBgMJV7DS8CVGx",
        "_version" : 1,
        "result" : "created",
        "_shards" : {
          "total" : 1,
          "successful" : 1,
          "failed" : 0
        },
        "_seq_no" : 13,
        "_primary_term" : 1,
        "status" : 201
      }
    }
  ]
}

?filter_path=items.*._shardsとすると

フィールドの階層をワイルドカードで取得できる

{
  "items": [
    {
      "index": {
        "_shards": {
          "total": 1,
          "successful": 1,
          "failed": 0
        }
      }
    },
    {
      "index": {
        "_shards": {
          "total": 1,
          "successful": 1,
          "failed": 0
        }
      }
    }
  ]
}

?filter_path=-itemsとすると
itemsのデータを除外したレスポンスが返ってくる

{"took":5,"errors":false}

www.elastic.co

Elasticsearchを使う

CentOS7にインストール

www.elastic.co

バージョン

Elasticsearch 7.0.1
Kibana 7.0.1

データをInsertする

curl -H 'Content-Type:application/json' -XPOST 'localhost:9200/logs/_doc?pretty' -d '
{
  "value": 1000,
  "recorded_at": "2019-05-09 08:00:00"
}'
  • Kibana console
POST logs/_doc
{
  "value": 1000,
  "recorded_at": "2019-05-09 09:10:00"
}

mappings

自動でマッピングもされるが、datetime型のテキストを入れてもtext型でマッピングされてしまう。

{
  "mapping": {
    "properties": {
      "value": {
        "type": "long"
      },
      "recorded_at": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword",
            "ignore_above": 256
          }
        }
      }
    }
  }
}

datetime形式はマッピング定義を事前に作成しておく。

PUT logs
{
  "mappings": {
    "properties": {
      "value": {
        "type": "integer"
      },
      "recorded_at": {
        "type": "date",
        "format": "yyyy-MM-dd HH:mm:ss"
      }
    }
  }
}
  • string text型とkeyword型の違い
    ・text型はAnalyzerによって単語に分割されてインデックスされるので、部分一致で検索できる。
    ・keywordは完全一致で検索される。デフォルトでignore_above: 256 のパラメータが付与され、256文字以上はインデックスされない。

bulk insert

POST logs/_bulk
{"index":{"_index":"logs"}}
{"value":1000,"recorded_at":"2019-05-09 08:00:00"}

AutoIndentで整形するとエラーになるので注意
sora-sakaki.hatenablog.com

curlでbulkinsertする

curl -H 'Content-Type: application/json' -XPOST 'localhost:9200/logs/_bulk?pretty' -d '
{"index":{"_index":"logs"}}
{"value":1000,"recorded_at":"2019-05-09 08:00:00"}
{"index":{"_index":"logs"}}
{"value":1000,"recorded_at":"2019-05-09 08:00:00"}
'

最後の'に注意

{
  "error" : {
    "root_cause" : [
      {
        "type" : "illegal_argument_exception",
        "reason" : "The bulk request must be terminated by a newline [\\n]"
      }
    ],
    "type" : "illegal_argument_exception",
    "reason" : "The bulk request must be terminated by a newline [\\n]"
  },
  "status" : 400
}

phpでGuzzleを使ってelasticsearchにPOSTする

stackoverflow.com

<?php
        $client = new Client();
        $data = null;
        foreach ($logs as $log) {
            $json_data = [
                json_encode(['index' => ['_index' => 'logs']]),
                json_encode(['value' => $log[0], 'recorded_at' => $log[1]])
            ];
            $data[] = join("\n", $json_data);
        }
        $data = implode("\n", $data);
        $client->post('http://localhost:9200/logs/_bulk?pretty',
            [
                'headers' => ['Content-Type' => 'application/json'],
                'body' => $data . "\n"
            ]
        );

大量にデータを入れる場合

・コミットメントの頻度を変更

{
  "index.blocks.read_only_allow_delete": "false",
  "index.priority": "1",
  "index.query.default_field": [
    "*"
  ],
  // 1s → 30sに変更
  "index.refresh_interval": "30s",
  "index.write.wait_for_active_shards": "1",
  "index.number_of_replicas": "1"
}

qiita.com

インデックステンプレート

ログをインデックスする場合に、インデックス名を logs-yyyy-mm-dd といった形で保存したい場合に使う。

logs-*にマッチするインデックスに自動的にマッピングされる

PUT _template/logs
{
  "index_patterns": ["logs-*"],
  "settings": {
    "index.refresh_interval": "30s",
    "number_of_shards": "5",
    "index.number_of_replicas": "0"
  },
  "mappings": {
    "dynamic": false,
    "properties": {
      "value": {
        "type": "integer"
      },
      "recorded_at": {
        "type": "date",
        "format": "yyyy-MM-dd HH:mm:ss"
      }
    }
  }
}

qiita.com www.sambaiz.net

『Ship It! ソフトウェアプロジェクト成功のための達人式ガイドブック』を読んだ

 筆者はよい習慣(プラクティス)を取り入れることで毎日の仕事を改善することができ、しかもそれは社員数4人の規模の会社から筆者が務めるSASのようなグローバル企業でも通用するという。

第1章はじめにの「2つの現場」の話で本に引き込まれる

 1つ目の現場はめちゃくちゃでした。コードは不安定で5分おきぐらいにクラッシュする有様でした。大問題はあるということは誰もが知っていたのに、誰もそれらの問題を修正できませんでした。
・・・
 2つ目の現場はもっと洗練されていました。コードに変更が加えられるたびに自動リビルドと自動テストが実施されました。チーム全体は毎日ミーティングをしていましたが、ミーティングは短く、知的で効果的なものでした。プロジェクト一つ一つにマスタープランがあったため、どの機能に取り組むべきかを開発者全員が把握していました。
・・・
 ここで述べた2つの現場が実は全く同じ現場だということです。本書で述べた原理を取り入れたことによってある現場が半年足らずで全く別の姿になったのです。

良い習慣の3つの領域

 良い習慣は、テクニック・インフラ・プロセスの3つに分けられ、これらの具体的な内容が紹介されている。
https://user-images.githubusercontent.com/36433535/57535132-91c11580-737c-11e9-9fff-7aa6debe2c91.png
『Ship It! ソフトウェアプロジェクト成功のための達人式ガイドブック - Jared Richardson』p5より

1. ツールとインフラ

 インフラについてはバージョン管理ツール・CIの構築・バグトラッキングシステムの利用・テスト自動化の導入を勧めている。今でこそGitやCI・CD、xUnitの使用は珍しくはないが、2005年初版のこの本でこれらのツールを使用することを勧めているのはすごい。それ以前の習慣であった、ファイルをコピーしてバージョン管理したり、バグを付箋に貼って管理することの問題を指摘している

2. プロジェクト管理とテクニック

 プロジェクト管理技法について書かれている。ここが一番ためになったし、プログラマならなんとなく思い当たる節があるような話が筆者の経験をもとに散りばめられていておもしろい。

作業リストを作ること

 作業リスト=TODOリストではなく、毎日および毎週の作業計画。「次何をすればいいんですか?」という質問は作業リストを見れば一目瞭然なので無くなる。また重要度の高い作業が明らかになり、目立ちやすい問題が優先されるおそれがなくなる。作業リストはシンプルで構わないし、グループとしてだけではなく個人用のスケジュール管理ツールとしても使える。

取り組むべき作業のリスト毎朝作って各作業に優先度を割り当てます。そして、その日の仕事の終了時にどの作業が完了したか(または完了しなかったか)を確認します。完了できなかった作業がある場合には、その理由を考察し、完了可能な作業を判断する際の見積もりが楽観的すぎたのかあるいは作業時間中に集中を妨げられたことが原因であるのかを検討してください。

作業リストが有効である条件

  • 関係者全員に公開されている
  • 優先度が割り当てられている
  • スケジュールの見積もりが完了している
     作業時間の見積もりについては徐々に向上するものであり、はじめのうちはズレ幅の大きさを細かく気にする必要はない。また見積もりに苦労しているときは、見積もり時間の単位を1時間・1週間・2週間・4週間に限定してあげるというのはいいアイデアだと感じた。
  • 状況に応じて臨時変更できる
  • 測定可能な目標が設定されている
     作業が完了したかどうか判断できないので、成否が明確な目標を設定する。明確な目標が設定できないものは、詳細度が足りないので優先度を下げる。
  • 利用者の目的に合った的確な情報が含まれている

・参考
Painless Software Schedules – Joel on Software
『Joel on Software』やさしいソフトウェアスケジュール - Vapor Trail

 技術主任の話では、技術について理解のないマネージャが非現実的な納期を設定し、スケジュールの遅れについてあれこれ口を出す話(思い当たる節がある人は多いと思う)から、製品とテクノロジについて精通し経営陣と開発チームの仲立ちをする技術主任の重要性が書かれており、CTOの役割と存在について考えさせられた。

3. 曳光弾開発とプロセス

曳光弾(Tracer ammunitation)とは暗闇でも軌跡・弾道がわかるように発光する弾丸のこと。

https://upload.wikimedia.org/wikipedia/commons/thumb/1/18/Tracer_fire_at_MCB_Camp_Pendleton_DM-ST-89-00210.jpg/800px-Tracer_fire_at_MCB_Camp_Pendleton_DM-ST-89-00210.jpg
Corporal C.T. Doll, USMC [Public domain], via Wikimedia Commons

「プロセス」とはなにか?
 プロセスとは、過程や一連の経過を意味するものとして用いられる事が多いが、ここでの「プロセス」はどういう意味なのか。

開発プロセスは、開発作業のあらゆる面を結びあわせて一つにまとめあげる紐のようなものです。プロセスは、多様な手法やツール、テクニックを結びつけて、それらがひとまとまりの全体として機能できるようにします。 プロセスとは、製品のビルドを繰り返し可能な方法で実行するために必要な作業を一連の手順でまとめたものです。

と書かれているが、ソフトウェア開発工程のことを指しており、本書ではアジャイル的な開発をイメージするのがわかりやすいと思う。

https://www.publickey1.jp/blog/10/xpfes16.jpg
アジャイル開発の現在・過去・未来 - Publickey

設計

1. チームで設計をする

 最も優れたアーキテクチャは共同作業によって作られる。設計の達人が一人で設計するのではなく、共同で全員の経験を組み合わせて設計をすることで、みんなのシステムの理解度が上がる。

目指すべき目標は、何も考えずにただコードを書けと指示されて疎外感を抱いたことがある多くの開発者たちに同じような思いを二度とさせないことです。

2. インターフェースのスタブを作る

 ただ呼び出し可能な(おそらく?)公開インターフェース(API)だけを作成し、プロジェクト内における各担当の役割と機能を理解させること。

Boolean Login (string userName, string password){
    return true
}

Loginインタフェースの場合、適切な引数と戻り値以外は何も含めないようにする。実際のロジックなどは記述しない。

3. 各層間の呼び出しや応答を可能にする

 他の層からの呼び出しを可能にする。クライアントからの要求に応じて、各層を貫くリクエストとレスポンスを可能にする。

Boolean Login(string userName, string password) {
    realPaswword = getPassword(userName)
    if(realPassword.equals(password)) {
        return true
    }
    return false
}

4. 実機能を持つコードをスタブに追加する

 各インターフェースの背後のロジックを実装する。各チームの合意がない限り、インターフェースは公開しない。

https://user-images.githubusercontent.com/36433535/57563808-64588400-73dd-11e9-9195-104ea2306c11.png
『Ship It! ソフトウェアプロジェクト成功のための達人式ガイドブック - Jared Richardson』p128より

 こうしたように各層間のインターフェースを明確に定義することで、ある層のコードを変更しても他の層に影響を与えることなく、コードが変更できる。


序章でこんな事が書かれている。

 筆者たちの願いは、読者のみなさんが本書で取り上げたアイデアや習慣を、それらを生み出す元になった精神、Pragmatic(実用主義)にのっとって利用してくれることです。読んだ内容を実際に試してみてください。自分の環境で効果のあるものは残し、それ以外のものは捨て去ってください。
・・・
 本を読むだけにとどめず、新しいプログラミング言語を覚えたり別の開発プロセスを研究したりしましょう。学習と読書を進めている間も、そこから得た新しい概念を現在の仕事に応用するための方法を見つけてください。新しい概念を、日々の仕事に取り入れるのです。自分を高めるためにも役立ちます。
・・・
 これらの概念を既存の作業に応用する方法を考え出してください。「新しい概念が応用できなかった」と諦めてしまうほうが簡単でしょうが、最終目標は「これまでとは別の考え方を学ぶこと」なのです。小さな世界から出て暮らしましょう。
・・・
 新しい考え方を鍛えれば、自分がどこで仕事をするかに関係なく役立つでしょう。ほとんどの人は、こういう考え方を決して習得せず、たとえ習得しても、うまく使いこなせるまでには至りません。

 新しいプラクティスを取り入れると書いてあったが、最近はElasticsearchとかPrometheusとか新しいツールやソフトをプライベートで試して実務で使ってみるように心がけている。うまく動くのか、スケジュールに間に合うのかという不安はあるが、ただ覚えたことだけを駆使して仕事をしているより遥かに楽しいことに気づいた。時間がないとか経験がないとかは言い訳にすぎないのだ。

自分自身にとって、また自分のキャリアにとって最も賢い投資の一つは、適切な人々の中に身を置くことです。

『情熱プログラマー』でも一番の下手くそであれ、という似たような言葉があったが、自分にとっての仕事の軸はやはり「優秀な人達と一緒に働きたい」ということだと再認識させられた。大学に行ってようやく気づいたが、周りの環境によって成長速度は大きく変わる。レベルの高い環境にいると、周りの人たちが自分の能力を高めてくれる。ただレベルの高い人たちと一緒に働くためには、自分もその人達のレベルに追いつかなければいけない。新しいことをどんどん実務で取り入れて、スキルを身に着けていきたい。

Ship It! ソフトウェアプロジェクト 成功のための達人式ガイドブック

Ship It! ソフトウェアプロジェクト 成功のための達人式ガイドブック