はじめに
記憶力低下に伴い覚えきれないしもう何十回ググったかわからんのでカッとなって作った。
まぁ全然gistで十分だった。bashです。みんなだいすきpecoです。
gif動画
なんやかんやこういうの作ったことなかったのでttyrecとttygifで作った。
しかしなぜかこうチープになるな。。。
参考
おわりに
本当記憶力の低下がやばい。
記憶力低下に伴い覚えきれないしもう何十回ググったかわからんのでカッとなって作った。
まぁ全然gistで十分だった。bashです。みんなだいすきpecoです。
なんやかんやこういうの作ったことなかったのでttyrecとttygifで作った。
しかしなぜかこうチープになるな。。。
参考
本当記憶力の低下がやばい。
でましたね。
本当に良い本です。「監視とはなんぞや」からはじまり、「監視はこうやるな」「監視はこうやれ」という思想が最初の3章までに詰まってます。最初の3章までは開発者すべてのひとが読んだらいいんじゃないかな。それ以降は必要なところをおのおのがつまみ食いしていけばいいと思う。SREになる前に読みたかった本です。(原著は出てたわけだけどね)
本自体の解説はいろんなひとがレビューしてそう(出遅れた!)のでそちらを!翻訳者の松浦さん、付録を執筆されたsongmuさんの記事含めてご紹介。
翻訳コミュニティyakstで募集がかかったので、読みたい本でもあったし、いい機会だったので参加しました。9月ぐらいだったかな。(なお入りつつもまだ1つも翻訳投稿していない。。。)
英語(原著・一次ソース)を読めというのはごもっともだし、自分もそうしていますが、かといってじゃあ技術書全部英語で読んできたのかっていうともちろんそうでもないし、数多くの翻訳書のおかげでエンジニアとしてスキルアップできたのも事実です。
「教育」に興味があってQuipperで働いているけれど、教育に関連して、そういう底上げができる・広く広げることができる、その両方の特性を持った翻訳という範囲にはずっと昔から興味がありました。コミュニティのリーダーであり、「入門Kubernetes」「SQLパフォーマンス詳解」の訳者である松浦さんはデブサミでGitHubのサポートエンジニアとしての発表をしているのを見て知って、魅力的な仕事だなぁと思ったのを覚えています。
訳者あとがきで名前を載せていただいたのですが、最初の(訳された)原文に比べるとかなり読みやすい日本語になったと思いますし、貢献はできたという自負があります。実際、(おそらく)オライリーの編集者の手が入ったあとの完成版を献本いただき、一通り読み直しましたが違和感なかったです。
入門監視 献本いただきました、発売めでたい!名前載ってる〜!一冊は同僚の分です。 pic.twitter.com/IAP4G4xOdC
— 🤔 (@chaspy_) 2019年1月16日
ざっとレビューした数を数えたら76個でした。もちろんコメントだけのものもありますし、別の案が採用されたものもあります。あとは意識的に一番にレビューするようにして、なるべく多くの貢献ができるようにしました。数がすべてではありませんが、自分の経験として良いものになりました。
「その文に違和感のある理由」「代替案」「+コメント」という形式でレビューを行いました。実際、日本語を読んで原文も読んでからコメントをするのですが、「正しく訳すこと」と「日本語として読みやすいこと」はまったく別物であることをあらためて実感しました。英語の訳としては正しいけどこの日本語はちょっと、という例がなかなかあり、翻訳の難しいところだなぁと思いました。レビューですら難しかったので、実際に訳すのはもっと難しいですよね。
これまで国内になかったタイプの本が翻訳という形で世に出版される瞬間に立ち会えて本当に嬉しいです。
翻訳、興味あるあるいいながら実際にできてないので今年こそは地道に、小さな記事からでもやっていって、貢献していきたいと思います。
2018年の目標は全然守れてなかったなー。
転職してバタバタのままバタバタだったって感じです。
冬休みちゃんと休んだので2019年はちゃんと生きるようにします。
SREとしてもっと「いい感じ」に。学習は英語主体に、スピードが落ちないように、本質をつかむようにやっていく。オライリーSafariをちゃんと元とったって言えるように使う。
幸い、日頃の運用業務、他チームからの依頼に加えて、中・長期的な改善、ビッグプロジェクトとやりがいのあるチームにいる。一通りなんでもSREの仕事ができるようになった上で、自分がリードしての改善も月に1つ以上はできるようになる。
今足りてないのは、日常のひとつひとつの動作の効率化なので、それは継続的にメンテナンスする。大きめな/新しめなことを学ぶときは登壇と合わせてアウトプット駆動にする。本を読んで終わりにしなくてちゃんと手を動かすか、まわりに伝える、という学習法にしたい。
今年一番力をいれたい。TOEICを目標にするつもりはないので、定量的な力が出しづらいところ。
とりあえず直近は2月にフィリピンに行くので、最低限の英会話ができるようになること。あとは仕事上の読み書きを調べずに大意を読めるようになること。(特に書きがまだ検索しながらで、チャットでのレスポンスが遅れがち)。海外カンファレンスのキーノートスピーチの英語ぐらいは理解できるようになること。
英語でのプレゼンテーションもやれるようにしたい。
転職してさらに無限に太ったのでなんとかします。3月までにマイナス10kg、以降維持。体脂肪率は13%ぐらい、をいったん適当に目指す。
朝型にして寝酒をやめてジョギングと筋トレを習慣化する。ついでに英語学習と合わせたい。podcastがいいかいな。シャドウイングできる何かとか。
Apple Watchでの活動量リングを毎日つなげるようにする。
マネーフォワード&電子決済で可視化したはいいけどほったらかしでまったく意味をなしてない感じになっていました。
これも週2チェックで習慣化。あと5月頃引っ越したいので5月までに50万溜める。以降も消費ペース、範囲をちゃんと知って、知った上で使うようにする。あんまり年いくら貯金、とかはしたくないけど、いつ指が10本折れて失業してもいいように100万は貯めてみたい。
英語学習のついでだけど、趣味としても海外ドラマ、映画を見ていきたい。Netflix契約した。
次に登山。2年ぐらい前から仲間誘ってやってたんだけど、どうも日程合わせるの難しかったりするので、今年からは単独登山で、月に1度は行く。まずは日帰りから。PCを持たない日を作るのも大事な気がするし。持っていくかもしれないけど。
音楽も変わらず。継続してこれまでと同じペースでやる。
他、(技術)翻訳に興味がある、まずは短い記事から少しずつやっていく。現在進行系で進化中のものの翻訳はやはり難しい。まずは単発の記事、次に更新がかからないようなまとまったドキュメント、といった風にやっていきたい。
旅行。20代のうちに47都道府県行く、という夢がついに叶ってしまった。海外旅行に年に2、3回は行きたいところ。ここ最近よく帰省してたので、しばらくやめて、長期休暇は海外に出ようかな。さすがに全世界制覇は言えない、が、英語学習効果を試すのもかねて、まずは英語圏/英語が通じる国にたくさん行きたい。
あと去年やってたQuoter/Mionthlyの目標、振り返り、途中で死んでしまった。月ごとというのもやっぱりスパンが長い。
数値の簡単な振り返りとして毎週ブログを書いていこうと思います。指針確認と振り返りを短いスパンでやることで習慣が消えないようにするため。
まぁ本当は各分野それぞれゴールが何でそのために何をやっていくとか細かく書いたほうがいいんだけどそれはあとでScrapboxかなんかにまとめようかなあ。
ざっくり言うと「ちゃんと・確実に・しっかり」やって力つけていくぞーって感じの1年にしたいです。よろしくおねがいします。
App Meshも発表されたのでService Meshちゃんと動かしておこう、って感じです。
で、App Meshではなくさくっと動かせそうなGKE(慣れてる)で、親和性も高そうなIstioを試すことにします。
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がいないのが気になりつつ、、、
これが最高便利だなぁと思っていて、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はこんな感じ。
Service MeshといえばObservability。デフォルトでStackDriver logingとtracingと連携できるようですね。
この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していきます。
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の核となる機能であるTraffic Managementを見てみましょう。
あらたなリソースが追加されています。rule configurationを見ていきます。
There are four traffic management configuration resources in Istio: VirtualService, DestinationRule, ServiceEntry, and Gateway:
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したら流す先はこれ、というものみたいですね。
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のような設定を定義してるようですね。
is commonly used to enable requests to services outside of an Istio service mesh.
Istioの外のサービスへのリクエストを許可するためのもの。
これはbookinfoをapplyした時点では存在しなかったのであとで解説を読むとします。
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>
さて、ドキュメントではさらに詳細にひとつひとつのリソースについて説明されているのでそこを見ていきます。
つかれたので一旦ここで終わります。次はBookinfoを動かしたり、Traffic Management設定を実際に変えてみたりしようと思います。
経ってしまったので書く。
半年経ってできることは確かに増えた。作業のスピードも少しは早くなった。理解も少しずつ繋がってきた。
スペシャリティを発揮し、「お前にしかできないことは何よ?」に答えられるようになるまではもう少し時間がかかりそうで、そのためにはまず既存の理解をしっかりしたい。
次は「入社して半年」。既存のことなら任せろ、さらにこのことは俺に任せろ、となっていることを願う。
これは残念ながらまだないな。
この期間での一番の気づきは、「"本質的なことにいかに注力できるか"がエンジニアリングの本質」ということだ。優れたソフトウェアエンジニアは、関心のある作業を行うための効率化、つまり道具の手入れをしっかりしている。僕はこれが明確に足りてなかった。そして少し工夫したりトレーニングすると作業効率は劇的に変わった。うまくgrepしたりファイルを開いたり編集したりとかのそういうアレのこと。
コードの山に対して、見て、動かして、理解する。このプロセスを速く行うための下準備ができていなかったから、時間はかかる、理解ができない、間違う、ということを起こしていたんだと思う。道具をうまく使えていないことを、"理解力がない"と思考停止してはいけない。いつでも立ち戻るのは基本となることなんだなぁと、何度目に思うことだろう。
最近は新しいひとも入ってきた。僕が半年かかった地点まで一ヶ月で到達してもらえるようにオンボーディングを考えている。
精神的につらいときもあったけど、周囲の同僚や友人が👀と気にかけてくれたおかげでなんとか乗り越えた、のか、単に時間が経った、のかよくわからないが、ここまでこられた。
いつまで経ってもソフトウェアエンジニアリングは難しいし、SREがカバーする領域も途方もなく広い。それでも「うまくやる」ことを目指し続けないといけない。技術との向き合い方、コードとの向き合い方、新しいものの学び方。
次は「入社して一年」。何ができるのだろうか。何がしたいと思っているのだろうか。何が楽しいと感じているのだろうか。まだわからないけれど、今より開発者やチームメンバーに(一部の面であれ)頼られる存在になっていたいと思う。
こんばんは。10月の目標振り返りすっとばして今週終われば12月です。
The Site Reliability Workbook: Practical Ways to Implement SRE
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 また次回以降も楽しみです。
ホビープロジェクトでモバイル向けのシンプルなTODOアプリを作ることになりました。TODOといえばWebアプリサンプルのド定番だけど、本当に自分にあった使えるものを作ってきっちり公開まではやろうと思ってます。それは置いておいて、サーバサイドをRailsで書きました。
TODOには写真が添付できると良い、というのが要件にあったので、Active Storageを使うことにします。せっかくRails 5.2を使っているので!
最高のガイドがあるので基本的にこれを読めばいいです。
ただ、調べてもS3にやってみた、という例が多く、今回は気が向いてGoogle Cloud Storageに保存することにしたのでそちらを記事に残しておこうかな、というのが本記事の主旨です。
ちなみに気が向いた理由ですが、アプリの認証をGoogleでやっていて、すでにプロジェクトがあったからです。
参考になりました。ありがとうございます。【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") %>
さて、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作ってバケット作ればいけそうな雰囲気がしますね。
プロジェクトは適当に作ってある前提で、サービスアカウントはIAMと管理->サービスアカウント
ユニークな名前をいれましょう。
作成されたら権限を付与します。閲覧だけでは足りないので編集権限をつけます。
Active Storageがアクセスするためのkeyを作成します。
作成するとダウンロードされます。
Google Cloud Storage JSON API
を有効にしてください。しないとアクセス時に弾かれます。あと、有効になるまで数分かかります。
ちなみに認証情報を作成する、とありますが多分不要です。この目的に適したサービスアカウントがすでに存在します、と言われるので。
バケットは普通にぼちぽち作っていただいて、バケットに権限を与えないと弾かれます。サービスアカウントが常に権限もってるじゃん、って思うんですけどね。
ストレージ->ブラウザでバケットの右側の3点ボックスから権限を編集
で、ここがびっくりなんですが、ストレージ管理者の権限が必要です。強すぎでは、、、と思うんですが、サービスアカウント実態にも確かにこれ相当のものを持たせてるから仕方ないかなと無理やり納得しています。
なんと、ダウンロードしたkeyを見ると中身はそのままstorage.ymlに載せるべき内容がのっています。このままいれればいいですね。
しかし、中身にはprivate_keyが入っており、localで動かすならまだしもコミットはできないので適切に秘匿しなければなりません。
参考になりました。ありがとうございます。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に使い慣れてる人ならわかるとは思いますが、はじめて使うひとの参考になれば幸いです。