ツナワタリマイライフ

日常ネタから技術ネタ、音楽ネタまで何でも書きます。

AWSのRegion Code(ap-northeast-1とか)をシュっと出すコマンドawsrc

はじめに

記憶力低下に伴い覚えきれないしもう何十回ググったかわからんのでカッとなって作った。

github.com

まぁ全然gistで十分だった。bashです。みんなだいすきpecoです。

gif動画

なんやかんやこういうの作ったことなかったのでttyrecとttygifで作った。

しかしなぜかこうチープになるな。。。

kakakakakku.hatenablog.com

参考

おわりに

本当記憶力の低下がやばい。

「入門監視」の翻訳レビューに参加した

はじめに

でましたね。

入門 監視 ―モダンなモニタリングのためのデザインパターン

入門 監視 ―モダンなモニタリングのためのデザインパターン

本当に良い本です。「監視とはなんぞや」からはじまり、「監視はこうやるな」「監視はこうやれ」という思想が最初の3章までに詰まってます。最初の3章までは開発者すべてのひとが読んだらいいんじゃないかな。それ以降は必要なところをおのおのがつまみ食いしていけばいいと思う。SREになる前に読みたかった本です。(原著は出てたわけだけどね)

本自体の解説はいろんなひとがレビューしてそう(出遅れた!)のでそちらを!翻訳者の松浦さん、付録を執筆されたsongmuさんの記事含めてご紹介。

どうして翻訳レビューをしたのか

翻訳コミュニティyakstで募集がかかったので、読みたい本でもあったし、いい機会だったので参加しました。9月ぐらいだったかな。(なお入りつつもまだ1つも翻訳投稿していない。。。)

yakst.com

英語(原著・一次ソース)を読めというのはごもっともだし、自分もそうしていますが、かといってじゃあ技術書全部英語で読んできたのかっていうともちろんそうでもないし、数多くの翻訳書のおかげでエンジニアとしてスキルアップできたのも事実です。

「教育」に興味があってQuipperで働いているけれど、教育に関連して、そういう底上げができる・広く広げることができる、その両方の特性を持った翻訳という範囲にはずっと昔から興味がありました。コミュニティのリーダーであり、「入門Kubernetes」「SQLパフォーマンス詳解」の訳者である松浦さんはデブサミGitHubのサポートエンジニアとしての発表をしているのを見て知って、魅力的な仕事だなぁと思ったのを覚えています。

入門 Kubernetes

入門 Kubernetes

SQLパフォーマンス詳解

SQLパフォーマンス詳解

翻訳レビューどうだったか

訳者あとがきで名前を載せていただいたのですが、最初の(訳された)原文に比べるとかなり読みやすい日本語になったと思いますし、貢献はできたという自負があります。実際、(おそらく)オライリーの編集者の手が入ったあとの完成版を献本いただき、一通り読み直しましたが違和感なかったです。

ざっとレビューした数を数えたら76個でした。もちろんコメントだけのものもありますし、別の案が採用されたものもあります。あとは意識的に一番にレビューするようにして、なるべく多くの貢献ができるようにしました。数がすべてではありませんが、自分の経験として良いものになりました。

「その文に違和感のある理由」「代替案」「+コメント」という形式でレビューを行いました。実際、日本語を読んで原文も読んでからコメントをするのですが、「正しく訳すこと」と「日本語として読みやすいこと」はまったく別物であることをあらためて実感しました。英語の訳としては正しいけどこの日本語はちょっと、という例がなかなかあり、翻訳の難しいところだなぁと思いました。レビューですら難しかったので、実際に訳すのはもっと難しいですよね。

おわりに

これまで国内になかったタイプの本が翻訳という形で世に出版される瞬間に立ち会えて本当に嬉しいです。

翻訳、興味あるあるいいながら実際にできてないので今年こそは地道に、小さな記事からでもやっていって、貢献していきたいと思います。

2019年

2018年の目標は全然守れてなかったなー。

転職してバタバタのままバタバタだったって感じです。

冬休みちゃんと休んだので2019年はちゃんと生きるようにします。

Engineering

SREとしてもっと「いい感じ」に。学習は英語主体に、スピードが落ちないように、本質をつかむようにやっていく。オライリーSafariをちゃんと元とったって言えるように使う。

幸い、日頃の運用業務、他チームからの依頼に加えて、中・長期的な改善、ビッグプロジェクトとやりがいのあるチームにいる。一通りなんでもSREの仕事ができるようになった上で、自分がリードしての改善も月に1つ以上はできるようになる。

今足りてないのは、日常のひとつひとつの動作の効率化なので、それは継続的にメンテナンスする。大きめな/新しめなことを学ぶときは登壇と合わせてアウトプット駆動にする。本を読んで終わりにしなくてちゃんと手を動かすか、まわりに伝える、という学習法にしたい。

English

今年一番力をいれたい。TOEICを目標にするつもりはないので、定量的な力が出しづらいところ。

とりあえず直近は2月にフィリピンに行くので、最低限の英会話ができるようになること。あとは仕事上の読み書きを調べずに大意を読めるようになること。(特に書きがまだ検索しながらで、チャットでのレスポンスが遅れがち)。海外カンファレンスのキーノートスピーチの英語ぐらいは理解できるようになること。

英語でのプレゼンテーションもやれるようにしたい。

Health

転職してさらに無限に太ったのでなんとかします。3月までにマイナス10kg、以降維持。体脂肪率は13%ぐらい、をいったん適当に目指す。

朝型にして寝酒をやめてジョギングと筋トレを習慣化する。ついでに英語学習と合わせたい。podcastがいいかいな。シャドウイングできる何かとか。

Apple Watchでの活動量リングを毎日つなげるようにする。

Money

マネーフォワード&電子決済で可視化したはいいけどほったらかしでまったく意味をなしてない感じになっていました。

これも週2チェックで習慣化。あと5月頃引っ越したいので5月までに50万溜める。以降も消費ペース、範囲をちゃんと知って、知った上で使うようにする。あんまり年いくら貯金、とかはしたくないけど、いつ指が10本折れて失業してもいいように100万は貯めてみたい。

Hobby

英語学習のついでだけど、趣味としても海外ドラマ、映画を見ていきたい。Netflix契約した。

次に登山。2年ぐらい前から仲間誘ってやってたんだけど、どうも日程合わせるの難しかったりするので、今年からは単独登山で、月に1度は行く。まずは日帰りから。PCを持たない日を作るのも大事な気がするし。持っていくかもしれないけど。

音楽も変わらず。継続してこれまでと同じペースでやる。

Other

他、(技術)翻訳に興味がある、まずは短い記事から少しずつやっていく。現在進行系で進化中のものの翻訳はやはり難しい。まずは単発の記事、次に更新がかからないようなまとまったドキュメント、といった風にやっていきたい。

旅行。20代のうちに47都道府県行く、という夢がついに叶ってしまった。海外旅行に年に2、3回は行きたいところ。ここ最近よく帰省してたので、しばらくやめて、長期休暇は海外に出ようかな。さすがに全世界制覇は言えない、が、英語学習効果を試すのもかねて、まずは英語圏/英語が通じる国にたくさん行きたい。

目標とか振り返りとか

あと去年やってたQuoter/Mionthlyの目標、振り返り、途中で死んでしまった。月ごとというのもやっぱりスパンが長い。

数値の簡単な振り返りとして毎週ブログを書いていこうと思います。指針確認と振り返りを短いスパンでやることで習慣が消えないようにするため。

おわりに

まぁ本当は各分野それぞれゴールが何でそのために何をやっていくとか細かく書いたほうがいいんだけどそれはあとでScrapboxかなんかにまとめようかなあ。

ざっくり言うと「ちゃんと・確実に・しっかり」やって力つけていくぞーって感じの1年にしたいです。よろしくおねがいします。

Try "Istio on GKE"(1)公式ドキュメント編

はじめに

App Meshも発表されたのでService Meshちゃんと動かしておこう、って感じです。

で、App Meshではなくさくっと動かせそうなGKE(慣れてる)で、親和性も高そうなIstioを試すことにします。

Istio on GKE

Setup

Istio on GKE  |  Istio on GKE  |  Google Cloud

GKEでクラスタ作成するときのオプションでIstioをデプロイすることができます。とはいっても、Istio自体のdeployはkubectl applyでできるのでそれ自体はあんまり嬉しくないけど、自動でvupとかしてくれるみたいだ。

Istio on GKE lets you easily manage the installation and upgrade of Istio as part of the GKE cluster lifecycle, automatically upgrading your system to the most recent GKE-supported version of Istio with optimal control plane settings for most needs.

Kubernetesのバージョンは1.10.9、現在のデフォルト。これ以降じゃないとあとででてくるenvoy proxyのauto injectionができないらしい。

$ gcloud container clusters list
NAME          LOCATION           MASTER_VERSION  MASTER_IP     MACHINE_TYPE   NODE_VERSION  NUM_NODES  STATUS
istio-on-gke  asia-northeast1-a  1.10.9-gke.5    35.200.74.23  n1-standard-1  1.10.9-gke.5  5          RUNNING
$ kubectl get service -n istio-system
NAME                       TYPE           CLUSTER-IP      EXTERNAL-IP      PORT(S)                                                                                                                   AGE
istio-citadel              ClusterIP      10.35.243.80    <none>           8060/TCP,9093/TCP                                                                                                         4d
istio-egressgateway        ClusterIP      10.35.250.97    <none>           80/TCP,443/TCP                                                                                                            4d
istio-galley               ClusterIP      10.35.255.181   <none>           443/TCP,9093/TCP                                                                                                          4d
istio-ingressgateway       LoadBalancer   10.35.247.113   35.200.104.141   80:31380/TCP,443:31390/TCP,31400:31400/TCP,15011:32105/TCP,8060:30651/TCP,853:30293/TCP,15030:31022/TCP,15031:31609/TCP   4d
istio-pilot                ClusterIP      10.35.249.186   <none>           15010/TCP,15011/TCP,8080/TCP,9093/TCP                                                                                     4d
istio-policy               ClusterIP      10.35.254.135   <none>           9091/TCP,15004/TCP,9093/TCP                                                                                               4d
istio-sidecar-injector     ClusterIP      10.35.255.211   <none>           443/TCP                                                                                                                   4d
istio-statsd-prom-bridge   ClusterIP      10.35.253.65    <none>           9102/TCP,9125/UDP                                                                                                         4d
istio-telemetry            ClusterIP      10.35.242.127   <none>           9091/TCP,15004/TCP,9093/TCP,42422/TCP                                                                                     4d
prometheus                 ClusterIP      10.35.250.123   <none>           9090/TCP                                                                                                                  4d

grafanaがいないのが気になりつつ、、、

Enabling sidecar injection

これが最高便利だなぁと思っていて、namespaceにこのlabelをつけると、applicationをdeployしたときに自動的にsidecar proxyが注入されます。applicationのyamlに手をいれなくていいというのがいいですね。もちろんistioctlでyamlに手を入れることもできます。

$ kubectl label namespace default istio-injection=enabled

既にbookinfoのsampleをdeploy済なんですが、podを見てみるとちゃんとsidecar proxyもいることがわかります。

$ kb describe po productpage-v1-f8c8fb8-httpw
(snip)
Containers:
  productpage:
    Container ID:   docker://8d322f8e56735d7b02899fe79a900f7b62ea12fd3be7314c1e9fc0a8d900570f
    Image:          istio/examples-bookinfo-productpage-v1:1.8.0
    Image ID:       docker-pullable://istio/examples-bookinfo-productpage-v1@sha256:ed65a39f8b3ec5a7c7973c8e0861b89465998a0617bc0d0c76ce0a97080694a9
    Port:           9080/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Tue, 18 Dec 2018 19:35:20 +0900
    Ready:          True
    Restart Count:  0
    Requests:
      cpu:        100m
    Environment:  <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-q4s8k (ro)
  istio-proxy:
    Container ID:  docker://e882a24ce250b65281b16200ddca51153d888e6e918b2e0ab8d3eefeb1f58418
    Image:         gcr.io/gke-release/istio/proxyv2:1.0.2-gke.0
    Image ID:      docker-pullable://gcr.io/gke-release/istio/proxyv2@sha256:826ef4469e4f1d4cabd0dc846f9b7de6507b54f5f0d0171430fcd3fb6f5132dc
    Port:          <none>
    Host Port:     <none>
    Args:
      proxy
      sidecar
      --configPath
      /etc/istio/proxy
      --binaryPath
      /usr/local/bin/envoy
      --serviceCluster
      productpage
      --drainDuration
      45s
      --parentShutdownDuration
      1m0s
      --discoveryAddress
      istio-pilot.istio-system:15007
      --discoveryRefreshDelay
      1s
      --zipkinAddress
      zipkin.istio-system:9411
      --connectTimeout
      10s
      --statsdUdpAddress
      istio-statsd-prom-bridge.istio-system:9125
      --proxyAdminPort
      15000
      --controlPlaneAuthPolicy
      NONE
(snip)

productpage containerの他にistio-proxy containerがいる。

istioctlでinjectionしたときのdiffはこんな感じ。

gist.github.com

Enabling Stackdriver tracing and logging

Service MeshといえばObservability。デフォルトでStackDriver logingとtracingと連携できるようですね。

https://storage.googleapis.com/gke-release/istio/release/1.0.3-gke.0/stackdriver/stackdriver-tracing.yaml

このyamlをapplyします。

$ kubectl apply -f stackdriver-tracing.yaml
stackdriver.config.istio.io "tracing-handler" created
tracespan.config.istio.io "stackdriver-span" created
rule.config.istio.io "stackdriver-tracing-rule" created

stackdriver, tracespan, rule というkindが追加されます。tracingの設定もyamlで定義できるのはいいですね。

loggingも同様にapplyしていきます。

https://storage.googleapis.com/gke-release/istio/release/1.0.3-gke.0/stackdriver/stackdriver-logs.yaml

stackdriver, logentry, rule というkindが追加されます。

$ kubectl apply -f stackdriver-logs.yaml
stackdriver.config.istio.io "log-handler" created
logentry.config.istio.io "server-accesslog-stackdriver" created
logentry.config.istio.io "server-tcp-accesslog-stackdriver" created
rule.config.istio.io "stackdriver-log" created
rule.config.istio.io "stackdriver-log-tcp" created

logging, tracingともに有効になったようです。bookinfoアプリをなんとなしリロードするとなんとなし結果が見えます。さて、Googleのドキュメントはここで終わりなので、次はIstioそのものについて見ていきます。

Istio

Istioの核となる機能であるTraffic Managementを見てみましょう。

Istio / Traffic Management

あらたなリソースが追加されています。rule configurationを見ていきます。

Istio / Traffic Management

There are four traffic management configuration resources in Istio: VirtualService, DestinationRule, ServiceEntry, and Gateway:

追加されたリソース

  • VirtualService

    defines the rules that control how requests for a service are routed within an Istio service mesh.

どのようにServiceにroutingするかの設定のようです。見てみましょう。

$ kubectl describe VirtualService bookinfo
Name:         bookinfo
(snip)
API Version:  networking.istio.io/v1alpha3
Kind:         VirtualService
(snip)
Spec:
  Gateways:
    bookinfo-gateway
  Hosts:
    *
  Http:
    Match:
      Uri:
        Exact:  /productpage
      Uri:
        Exact:  /login
      Uri:
        Exact:  /logout
      Uri:
        Prefix:  /api/v1/products
    Route:
      Destination:
        Host:  productpage
        Port:
          Number:  9080
Events:            <none>

GateWayを指定して、そのgatewayからうけたリクエストを見て、pathがmatchしたら流す先はこれ、というものみたいですね。

  • DestinationRule

    configures the set of policies to be applied to a request after VirtualService routing has occurred.

VirtualServiceで受けたあとDestinationへ流すためのRuleSetっぽいですね。見てみましょう。

bookinfoのapplicationにはなかったので、istio-system namespaceにあったものを見てみます。

$ kb describe DestinationRule istio-policy
Name:         istio-policy
Namespace:    istio-system
Labels:       addonmanager.kubernetes.io/mode=Reconcile
              k8s-app=istio
Annotations:  kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"networking.istio.io/v1alpha3","kind":"DestinationRule","metadata":{"annotations":{},"labels":{"addonmanager.kubernetes.io/mode":"Reconci...
API Version:  networking.istio.io/v1alpha3
Kind:         DestinationRule
(snip)
Spec:
  Host:  istio-policy.istio-system.svc.cluster.local
  Traffic Policy:
    Connection Pool:
      Http:
        Http 2 Max Requests:          10000
        Max Requests Per Connection:  10000
Events:                               <none>

trrafic policy -> connection pool -> http とほって、max requestのような設定を定義してるようですね。

  • ServiceEntry

    is commonly used to enable requests to services outside of an Istio service mesh.

Istioの外のサービスへのリクエストを許可するためのもの。

これはbookinfoをapplyした時点では存在しなかったのであとで解説を読むとします。

  • Gateway

    configures a load balancer for HTTP/TCP traffic, most commonly operating at the edge of the mesh to enable ingress traffic for an application.

applicationが一番最初にトラフィックをうけるLoad Balancerの設定。

$ kb describe gateway bookinfo-gateway
(snip)
Kind:         Gateway
(snip)
Spec:
  Selector:
    Istio:  ingressgateway
  Servers:
    Hosts:
      *
    Port:
      Name:      http
      Number:    80
      Protocol:  HTTP
Events:          <none>

さて、ドキュメントではさらに詳細にひとつひとつのリソースについて説明されているのでそこを見ていきます。

VirtualService

  • Virtual Serviceはrequestを流すdestinationを複数定義でき、weightによって割合を決めることができる
  • timeoutやretryも設定できる。timeoutのdefaultは15sec
  • fault injectionもできる。何%の割合で、遅延を何秒間発生させたり、httpで400を返すさせたりできる
  • requestを受けるsourceをlabelで限定できる
  • rule/conditionは上のものが優先して適用されます。これは重要です。

DestinationRule

  • VirtualServiceのあとに適用されるrule
  • maxConnectionsを100とかに設定してそれを越えたら接続を切るcircuit breakerの設定ができる
  • rule適用はVirtualService、DestinationRuleのhost、subsetの順で適用されるかどうかが検討される

ServiceEntry

  • 外部サービスと接続するためのentry(そのまんま)

Gateway

おわりに

つかれたので一旦ここで終わります。次はBookinfoを動かしたり、Traffic Management設定を実際に変えてみたりしようと思います。

参考

入社して半年

blog.chaspy.me

経ってしまったので書く。

半年経ってできることは確かに増えた。作業のスピードも少しは早くなった。理解も少しずつ繋がってきた。

スペシャリティを発揮し、「お前にしかできないことは何よ?」に答えられるようになるまではもう少し時間がかかりそうで、そのためにはまず既存の理解をしっかりしたい。

次は「入社して半年」。既存のことなら任せろ、さらにこのことは俺に任せろ、となっていることを願う。

これは残念ながらまだないな。

この期間での一番の気づきは、「"本質的なことにいかに注力できるか"がエンジニアリングの本質」ということだ。優れたソフトウェアエンジニアは、関心のある作業を行うための効率化、つまり道具の手入れをしっかりしている。僕はこれが明確に足りてなかった。そして少し工夫したりトレーニングすると作業効率は劇的に変わった。うまくgrepしたりファイルを開いたり編集したりとかのそういうアレのこと。

コードの山に対して、見て、動かして、理解する。このプロセスを速く行うための下準備ができていなかったから、時間はかかる、理解ができない、間違う、ということを起こしていたんだと思う。道具をうまく使えていないことを、"理解力がない"と思考停止してはいけない。いつでも立ち戻るのは基本となることなんだなぁと、何度目に思うことだろう。

最近は新しいひとも入ってきた。僕が半年かかった地点まで一ヶ月で到達してもらえるようにオンボーディングを考えている。

精神的につらいときもあったけど、周囲の同僚や友人が👀と気にかけてくれたおかげでなんとか乗り越えた、のか、単に時間が経った、のかよくわからないが、ここまでこられた。

いつまで経ってもソフトウェアエンジニアリングは難しいし、SREがカバーする領域も途方もなく広い。それでも「うまくやる」ことを目指し続けないといけない。技術との向き合い方、コードとの向き合い方、新しいものの学び方。

次は「入社して一年」。何ができるのだろうか。何がしたいと思っているのだろうか。何が楽しいと感じているのだろうか。まだわからないけれど、今より開発者やチームメンバーに(一部の面であれ)頼られる存在になっていたいと思う。

SRE Lounge#6で「The Site Reliability Workbook」について登壇してきました

はじめに

こんばんは。10月の目標振り返りすっとばして今週終われば12月です。

登壇してきました

sre-lounge.connpass.com

The Site Reliability Workbook: Practical Ways to Implement SRE

The Site Reliability Workbook: Practical Ways to Implement SRE

  • 作者: Betsy Beyer,Niall Richard Murphy,David K. Rensin,Kent Kawahara,Stephen Thorne
  • 出版社/メーカー: O'Reilly Media
  • 発売日: 2018/08/04
  • メディア: ペーパーバック
  • この商品を含むブログを見る

SRE lounge、もともとはユーザベースがはじめたクローズドなSREの勉強会をopenにしたものだそうです。

かくかくしかじか、スタディストの北野さん(@katsuhisa__)とお知り合いだったこと、彼がオープンになってこの会のオーガナイザーをやっていたこともあり、出させろ!とゴネたところださせていただきました。

嘘です。#5のときに一般公募していたので申し込んだのですがタイミングが遅く間に合わなかったので今回チャンスをいただいた次第であります。

なんで登壇したの

"時期"かなぁ、としか言えなくって、転職して、もうすぐ半年なろうとしているところで、時期、かなぁ、とだけしかないです。

なんでこのテーマなの

これまでの発表も、今回の他の発表も、"会社"としてのSREの事例を紹介するケースがほとんどです。もとの勉強会の発端も、最初のSRE bookでSREが定義されたが、それは各社それぞれ違うので、事例を持ち寄って知見を交換しよう、というものだったようです。

Quipper SREとしてももちろん積み重ねてきたものはあるのですが、僕が入ったときには基本的な仕組みはできており、安定しています。それを僕が話すのはなにか違うなぁと思いました。僕があらたになにかしてきたわけではないし、自分がやってきてないことを語れないなと。

そういうわけで、入社して"できること"がなかなか増えない僕がQuipper SREとして喋れることはない、だけれでも、発表する"時期"だとすれば、僕ができることは読書でした。ちょうどWorkbookが出て、気にはなっていたのですが、これを機会に”登壇駆動読書”をしたわけです。

英語技術書を読むということ

実は英語の技術書を読んだことがほぼなくて、読む体験をしてみたい、という挑戦もありました。

結果、最初の2章ぐらいまで読んだところで、これは通読は無理だ、と早々に悟りました。これは読み方を考えないといけないぞ、と。

主催の北野さんにこのテーマでいいかな?と相談しつつ、読み方をどうするか考えた結果、まず全体感を捉えて、各章の最初と最後を読むことで大意をつかみ、それでかつ読みたいところを読もう、という風にしました。Workbookは豊富なケーススタディがウリ、ということで、Quipperのケーススタディもまぜればいい感じになるのでは?と。

結果としてQuipperのSREにふれることはほぼなく、Workbookの概要紹介と本の読み方、が主題になってしまったのですが、それはそれでよかったのかなと思っています。

技術を学ぶということ

実は少し前に上司との1on1で、表面的にしか見ていないように見える、技術の本質的なところを掴みましょう、というアドバイスを受けました。そのときに新しい技術を学ぶときにはまず入門書で全体感を掴んで深掘りしていくとか、なぜその技術が出てきたかの理由を考える、というヒントももらいました。

時間は有限で、すべての技術をじっくり時間をかけて学んでいくことはできないから、効率よくいかないと、とも。

このときのアドバイスと、たまたま思い出して読んだ"読んでない本について堂々と語る方法"をヒントに、今回の発表を無事まとめることができました。

読んでいない本について堂々と語る方法 (ちくま学芸文庫)

読んでいない本について堂々と語る方法 (ちくま学芸文庫)

本というのは「読んだ」瞬間から限りなく「読んでない」に近づいていく。「読んだ」も「読んでない」も明確に定義ができない。

この本自体の是非、受け取り方はともかく、「読んでない本でも堂々と語ってもいいんだよ」という考えと、本は世界の大きな図書館のうちの1冊に過ぎず、教養とは物事と物事のつながりを理解していることだ、というメッセージが自分には響きました。これって技術の話と同じでは?と。

なぜその本が出てきて、それはどんなメッセージを発するもので、他の本とはどういう関係にあるのか。 なぜその技術が出てきて、それはどんな課題を解決するもので、他の技術とはどういう関係にあるのか。

そういうわけで、「読んでない本について堂々と語る」をまさに実践したというオチで締めるとともに、技術の学び方、技術書の読み方についての考えがあらたまった大きな機会になりました。

これから技術書を読むときの型

  • その本の立ち位置は?
  • その本のゴールは?
  • その本の概要は?
  • その本の結論は?

をつかんだ上で、自分が興味をもったトピックだけを読む、ことをしばらくは実践しようと思います。もちろん、英語日本語問わず。

おわりに

前後が会社でのSRE実践というスタンダードな形で発表をしていた中、ちょっと変わったテーマで話せて面白かったのではないかなぁと思います。誰か一部のひとにでも響いてくれればいいなぁと思っていたんですが、Twitterの感想を見ているとよかった、とか、Workbook読もうと思った、と言ってくれてるひとがいて、無事目標達成できたかなと思います。

Workbookについては既に読んだところと、これから読んでみようかなーっていうところを軽くメモしてブログにアップしていこうと思います。

原理原則を知っていることと、実際に自分ができることは違う。次は手を動かして、技術よりの発表をしたいと思います。主催の北野さん、会場スポンサーのFOLIOさん、当日お会いしたみなさん、ありがとうございました。

懇親会では面白い出会いが多かったw また次回以降も楽しみです。

Active StorageでGoogle Cloud Storageに画像を保存する

はじめに

ホビープロジェクトでモバイル向けのシンプルなTODOアプリを作ることになりました。TODOといえばWebアプリサンプルのド定番だけど、本当に自分にあった使えるものを作ってきっちり公開まではやろうと思ってます。それは置いておいて、サーバサイドをRailsで書きました。

TODOには写真が添付できると良い、というのが要件にあったので、Active Storageを使うことにします。せっかくRails 5.2を使っているので!

Active Storageとは

最高のガイドがあるので基本的にこれを読めばいいです。

railsguides.jp

ただ、調べてもS3にやってみた、という例が多く、今回は気が向いてGoogle Cloud Storageに保存することにしたのでそちらを記事に残しておこうかな、というのが本記事の主旨です。

ちなみに気が向いた理由ですが、アプリの認証をGoogleでやっていて、すでにプロジェクトがあったからです。

Active Storageを使う準備

参考になりました。ありがとうございます。【Rails 5.2】 Active Storageの使い方 - Qiita

Gemfileに必要なドライバをインストールしておきましょう。

gem "google-cloud-storage", "~> 1.3", require: false

bundle

そしてActive Storage用のテーブルを生成するためのmigrationを行う必要があります。これは内部的に使われているようで、実際は触らずに使えます。

$ rails active_storage:install
$ rails db:migrate

画像を持たせるmodelにhas_one_attached :imageを追加。今回はTask modelに持たせました。key名はimageでもphotoでもお好きなものを。

app/models/task.rb

class Task < ApplicationRecord
  belongs_to :user
  belongs_to :tag
  has_one_attached :image

# (skip)
end

デフォルトでconfig/storage.ymlはdiskになっているので、development環境でこの時点でファイルのアップロードができます。templateはerbでやりました。form_forで受けて画像を添付したいリソースのcreate actionを行うときに、file fieldでファイルをアップロードして、先ほどmodelで入力したkey名をparamにのせてあげます。これだけでできます。すごい。

<%= form_for @task,:url => {:action => :create} do |f| %>
  <p>
  <%= f.label :name %>
  <%= f.text_field :name %>
  </p>

  <%= f.file_field :image %>

  <%= f.submit %>

(root)/storage以下にファイルがアップロードされるでしょう。config/storage.ymlにすでにこのように書いてあるからですね。

  5 local:
  6   service: Disk
  7   root: <%= Rails.root.join("storage") %>

Google Cloud Storageを使う準備

さて、Rails guideを見るにconfig/storage.ymlに以下を埋める必要がありそうです。

google:
  service: GCS
  keyfile: {
    type: "service_account",
    project_id: "",
    private_key_id: "",
    private_key: "",
    client_email: "",
    client_id: "",
    auth_uri: "https://accounts.google.com/o/oauth2/auth",
    token_uri: "https://accounts.google.com/o/oauth2/token",
    auth_provider_x509_cert_url: "https://www.googleapis.com/oauth2/v1/certs",
    client_x509_cert_url: ""
  }
  project: ""
  bucket: ""

service_accountを作ってproject作ってバケット作ればいけそうな雰囲気がしますね。

Service Account作る

プロジェクトは適当に作ってある前提で、サービスアカウントはIAMと管理->サービスアカウント

ユニークな名前をいれましょう。

f:id:take_she12:20181111174935p:plain

作成されたら権限を付与します。閲覧だけでは足りないので編集権限をつけます。

f:id:take_she12:20181111174944p:plain

Active Storageがアクセスするためのkeyを作成します。

f:id:take_she12:20181111174954p:plain

作成するとダウンロードされます。

APIを有効にする

Google Cloud Storage JSON APIを有効にしてください。しないとアクセス時に弾かれます。あと、有効になるまで数分かかります。

https://console.cloud.google.com/apis/api/storage-api.googleapis.com/overview?project=simple-todo-kamoshare

ちなみに認証情報を作成する、とありますが多分不要です。この目的に適したサービスアカウントがすでに存在します、と言われるので。

f:id:take_she12:20181111175449p:plain

バケットに権限を与える

バケットは普通にぼちぽち作っていただいて、バケットに権限を与えないと弾かれます。サービスアカウントが常に権限もってるじゃん、って思うんですけどね。

ストレージ->ブラウザでバケットの右側の3点ボックスから権限を編集

f:id:take_she12:20181111175819p:plain

で、ここがびっくりなんですが、ストレージ管理者の権限が必要です。強すぎでは、、、と思うんですが、サービスアカウント実態にも確かにこれ相当のものを持たせてるから仕方ないかなと無理やり納得しています。

f:id:take_she12:20181111175939p:plain

Storage.ymlにダウンロードしたkey情報を反映

なんと、ダウンロードしたkeyを見ると中身はそのままstorage.ymlに載せるべき内容がのっています。このままいれればいいですね。

しかし、中身にはprivate_keyが入っており、localで動かすならまだしもコミットはできないので適切に秘匿しなければなりません。

Encrypted Credential

参考になりました。ありがとうございます。secrets.ymlや環境変数をRails 5.2のEncrypted Credentialsに移行する - Qiita

editorで開きます。

$ EDITOR=vim bin/rails credentials:edit
  1 # aws:
  2 #   access_key_id: 123
  3 #   secret_access_key: 345
  4
  5 # Used as the base secret for all MessageVerifiers in Rails, including the one protecting co    okies.
  6 secret_key_base: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  7
  8 private_key_id: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  9 private_key: xxxxxxxxxxxxxxxxxxxxxxxxx

こんな感じで追加してあげます。config/master.keyは秘密鍵になるので絶対に漏らさない/なくさないようにしましょう。(.gitignoreで無視されるようになっています)

最終的なconfig/storage.ymlはこんな感じになります。

google:
  service: GCS
  keyfile: {
    type: "service_account",
    project_id: "simple-todo-project",
    private_key_id: <%= Rails.application.credentials.private_key_id %>,
    private_key: <%= Rails.application.credentials.private_key %>,
    client_email: "active-storage-sample@simple-todo-project.iam.gserviceaccount.com",
    client_id: "1111111111111111111111",
    auth_uri: "https://accounts.google.com/o/oauth2/auth",
    token_uri: "https://oauth2.googleapis.com/token",
    auth_provider_x509_cert_url: "https://www.googleapis.com/oauth2/v1/certs",
    client_x509_cert_url: "https://www.googleapis.com/robot/v1/metadata/x509/active-storage-sample%40simple-todo-project.iam.gserviceaccount.com"
  }
  project: "simple-todo-project"
  bucket: "simple-todo-project"

生成されたconfig/credentials.yml.encはコミットしても大丈夫です。

最後にdevelopmentでもgoogle cloud storageを使うように変更しましょう。

config/environments/development.rb

-  config.active_storage.service = :local
+  config.active_storage.service = :google

おわりに

Active Storage、model側にカラムを追加することなく画像を持たせることができてとても便利だと思いました。ちゃんとリソースを削除すれば画像も削除されます。

GCPのプロジェクト、サービスアカウント、APIに使い慣れてる人ならわかるとは思いますが、はじめて使うひとの参考になれば幸いです。