GKE + Istio Addonにmicroservices-demoをデプロイ

GKE上でIstio Addonを使ってIstio入りのk8sを立ち上げて、そこにmicroservices-demoをデプロイしてみた。画面をポチポチしながら。

ひととおり遊んで気が済んだら、明日の夜にはGCPのプロジェクトごと削除すると思う。(追記:削除しました)

https://shop.shiiba.dev/

f:id:bufferings:20190803225404p:plain

## やったことのメモ

  1. VPCを作成
  2. Cloud NATを作成
  3. GKEをIstioつきで作成
  4. microservices-demoをIstioにデプロイ
  5. HTTPSのLoad Balancerを作成

## 1. VPCを作成

VPCを作って、東京リージョンにカスタムサブネットを作成した。デフォルトのVPCは削除しておいた。

f:id:bufferings:20190803230744p:plain

Secondary IP rangesのところは、後でGKEを作ったときにVPC Nativeを選択したら自動で作られた。Pod用とService用みたい。

## 2. Cloud NATを作成

GKEはPrivate Clusterにしようかなと思って。NodeにGlobal IPを持たせないやつ。

なので、外に出ていくのにNATの設定をしておいた。

f:id:bufferings:20190803231028p:plain

なんかCloud NATを作成する画面で、Cloud Routerを作成する必要があった。ルーターとしてではなく、コントロールプレーンとして使ってるみたいなことが書いてあった。

## 3. GKEをIstioつきで作成

'Highly available' テンプレートから作ってみた。Regionalクラスター。各Zone1台ずつにしておいた。んで、Privateクラスターにしておいた。24時間で1000円ぐらい。早く勉強をひとくぎりつけてシャットダウンしなければという気持ちになって良い。

f:id:bufferings:20190803231559p:plain

Istio authはPermissiveで作っといた。mTLSじゃなくても大丈夫なやつ。

f:id:bufferings:20190803231836p:plain

これで、Istio入りのk8sクラスターが立ち上がる。へー。

接続情報を取得して

❯ gcloud config set project [プロジェクトID]
❯ gcloud container clusters get-credentials [クラスター名]

サイドカーの自動Injectionをenabledにしとく。

kubectl label namespace default istio-injection=enabled

ここまで5分くらいかな。Istioつきのk8sがこんなに簡単に作れるなんて。楽だー!(ただし、分かってない

## 4. microservices-demoをIstioにデプロイ

ということで何かを動かしたいなと思って。でも、IstioのBookstoreはちょっと飽きたから、ECマイクロサービスのデモアプリをデプロイしてみることにした。

github.com

Istio用のデプロイ設定もあるので、これをそのままやった。途中までは終わってるので、具体的には(5)から。

https://github.com/GoogleCloudPlatform/microservices-demo#optional-deploying-on-a-istio-installed-gke-cluster

❯ kubectl apply -f ./istio-manifests

このデモアプリのビルドとデプロイにはskaffoldを使ってるので、入れておいた。これも

https://skaffold.dev/

❯ skaffold run --default-repo=gcr.io/[PROJECT_ID]

しばらく待つと、デプロイが完了して動き出した。こんな感じでアクセスできる。

INGRESS_HOST="$(kubectl -n istio-system get service istio-ingressgateway \
   -o jsonpath='{.status.loadBalancer.ingress[0].ip}')"
❯ curl -v "http://$INGRESS_HOST"

だいたい、こういうものは最初は動かないものだと思ってるのでびっくりした。

(∩´∀`)∩ワーイ

## 5. HTTPSのLoad Balancerを作成

ここまでで動いてるから終わりでもいいんだけど。なんとなくLoad Balancerはk8sから作られるものじゃなくて、自分で別でコントロールしたいなと思っている。のでやってみることにした。その方がGCPの機能を柔軟に使えそうだなぁと思って。

なので、IstioのIngress Gatewayから作られるものじゃなくて、自分でもういっこHTTPS LBを作成した。ついでに、Google Managedの証明書を使った。

HTTPSのLBをStatic IPで作成。そのときに証明書はGoogle Managedを選択。んで、shop.shiiba.devのAレコードを登録しといたら、Activeになった。

f:id:bufferings:20190803233949p:plain

LBのバックエンドは、IstioのHTTPのNodePortを使った。

❯ kubectl get -n istio-system svc istio-ingressgateway
NAME                   TYPE           CLUSTER-IP    EXTERNAL-IP      PORT(S)                                                                                                                   AGE
istio-ingressgateway   LoadBalancer   10.12.3.172   xxx.xxx.xxx.xxx   80:31183/TCP,443:32628/TCP,31400:32302/TCP,15011:30717/TCP,8060:32017/TCP,853:30377/TCP,15030:30985/TCP,15031:30336/TCP   10h

ここでいう 31183 。あとは、この通信をFirewallで許可したら動いた。

## 感想

GKEのIstio AddonでIstioが設定されたk8sを作るのはすごく簡単だし、使うのも簡単だなぁという印象。ただ、この中身を理解して、何か問題が起こったときにそれを調査できるようになるのは、なかなか大変そうだなぁ。

あと、個人的には、IstioのIngress GatewayをLBじゃなくてNodePortまでにしておいて、LBはGoogle Cloud Load BalancerをCloud ArmorやCDNつきで動かせたらいいなぁと思うので、そうなるとAddonを使わずに自分でインストールしないといけないのかなぁと思い中。

とりあえず一歩前進かな。寝よう。

パパ。私は、なんのために勉強をしてるの?

定期的に聞かれる質問。

「パパ。私は、なんのために勉強をしてるの?」

それはね、君たちが「どうしてこうなってるのかなぁ?」って思ってることを知ることができるようにするためだよ。

「へーそっか」

それは、宇宙のことかもしれないし、プログラミングのことかもしれないし、日本の昔の文学のことかもしれないね。

「宇宙は考えると怖いから妹に任せようと思うの。私は別のことがいいかな」

そっか。いいね。

世界中で誰も知らないことを君たちは調べることができるんだよ。大学生までは基礎を教えてもらえるから、しっかり勉強をしながら、何を知りたいかを考えておくといいね。

「そっか。じゃあ、小数の割り算、ちょっとがんばろっかな」

うん。いいね。そこ、小数点ずれてるよ。お父さんも勉強しなおして大学院に行くのもいいなー。

 

みたいな話をしながら、こんなんでいいんかな?って思いながら、ま、僕が素直に思ってることだからいっかな。

1ヶ月間夏休みをとってみた

来週の月曜日からお盆休みをはさんで8/23まで休みます。

去年は毎月2日間有給休暇を使うってのをやってたんだけど、今年はまとめて取ることにした。折角なので娘たちの夏休みと揃えた。

海外出身の人がまとめて休暇を取るのはよく見るのだけど、日本人はまだあんまり見ないから、こういうのが普通になると良いなという気持ちもある。

それが普通になると、誰か個人に対する依存度が減っていいかなぁとか。

というのが建前で、メインは、うえの娘が5年生なのでゆっくり一緒に過ごす時間を持っておきたいなという気持ち。家族全員で過ごせるのもだんだん減っていくだろうなと思って。

ちょこちょこ近場で家族旅行にいく予定があるくらいで、特に遠くに行ったりする予定はないので、娘たちとラジオ体操に行ったり、区民プールに行ったり、夏休みの宿題をやったり、一緒にプログラミングをして過ごしたりしようと思う。

僕の夏休みの宿題としては、GCPとかGKEとか触ったり、CKADの勉強をしたりしようかなー。

てことで、今日から1個目の家族旅行なんだけど台風。まいっか。

Cypressというブラウザテストツールのアーキテクチャと気をつける点と使いどころ #seleniumjp

E2E Test Automation Day 2019 with Selenium (Osaka)に参加してきました。

seleniumjp.connpass.com

色んな話が聞けて、色んな人とお話ができて、楽しかったー!

## Cypress

僕は、Lightning TalkでCypressのことを紹介しました。最初はGebのことを紹介しようかなと思ったんですけど、Groovyのことをお話する人がいるってことでCypressに変更しました。勉強会のタイトルに「with Seleinum」ってあるけどSeleniumを使ってないCypressを紹介するので少しドキドキしてました。

Cypressは独自のアーキテクチャーで、自分たちがやりたいことを実現させてるのが面白いところです。

f:id:bufferings:20190721082318p:plain

CypressがProxyとなって、テストスペックを対象アプリケーションと同じドメインに見せかけることで、Same-origin policyを超えてDOMやLocal Storageなどに直接アクセスできるようになってます。強引!(そういえば X-Frame-Options: deny になってたらどうなるんだろう?そこも書き換えてるんかな?)

Seleniumでできないことを実現させる引き換えに強い制約があります。

  • 1つのテストケースで複数のスーパードメインの操作ができない
  • 複数タブ・ウィンドウを操作できない

この辺の割り切りが素敵です。プロダクトオーナーと話をしてみたいな。

なので、Cypressの強みと弱みを理解して、自分が実現したいことに対してSeleniumとCypressをうまく使い分けることができると良いんじゃないかなと思います。個人的にはend-to-endというよりは、SPAのクライアント側のテストに使うと良さそうなんじゃないかなぁと思ってます。Chromium以外のブラウザ対応に関しては、今年中か来年早くには出てくるんじゃないかと想像してます。「Firefoxで動いた」みたいなのもGithubのIssue上でちょくちょく見かけるし。

Cypressを使ってみようかなと思って、一通りドキュメントを読んだあとに、このDominic Elmさんのセッションを見て勉強しました。とても分かりやすいのでおすすめです。

Dominic Elm - Cypress: The future of E2E testing

youtu.be

## 真面目さと情熱

スタッフのみなさん、お疲れ様でした。

主催者のKimさんは会社の後輩なんですけど。彼の人柄と真面目さと情熱が伝わってきて、すごいなぁと尊敬しかありませんでした。それと、Kimさんのマネージャーも、Kimさんの実現したいことをできるだけ実現できるように、と影で色々な雑用をやってKimさんをサポートしていました。良い関係の二人だなって見てました。お疲れ様でした!今後も楽しみにしてます。

知らない技術は怖い

AよりB、CよりD

今後の方向性を決める判断の中で「Aという技術ではなくBを採用する方がが良さそうです」とか「既存システムのCは良くないからやめてDを使うようにしましょう」とか。最近、何人か全然別の人からそういう話を聞く機会があった。

AよりBが良さそう?

「僕はAの方が良いと思うんですけど、Bの方が良さそうだと思う理由を知りたいです」って聞くと「Aはこういう部分に問題があると思います」って言われて話が噛み合わなくて、しばらく話をして気づいた。

この人、Aを触らずに想像だけで喋ってるんだ。ってことに。なので、実際に動かして見せてあげると「あぁ、それならAの方が良いですね」ってなった。

「興味があるだけなんですけど、僕も知らない技術だったので少しドキュメントを読んで実際に触ってみて機能を確認してからAの方が良いなと思ったのですが、どうして触らずに想像だけでAは問題があるって断言したんですか?」って聞くと「知らない技術だったので触ったらどれくらい時間がかかるか分からなかったからです」って話で、そっかーってなった。

CはやめてDにする?

もう一つの方は「Cが今使われてるってことは、僕はそこに理由があると思っているので、その理由を確認したいなと思っているんです。その理由が『その当時はCが良いと思ってたんだけど今ならもう使わないな』だったらDにしても良いと思います。だけど、Cに今も有効な理由があるならそこの議論をしたいです」って聞いたら「Cという技術はシステムを複雑にしてるだけなので、Dの方がシンプルで良いです」って言うので、Cを採用した過去の経緯をチェックしてみたら、やっぱりCは今も十分メリットがありそう。

そのあたりを説明しながら掘り下げてみて気づいたのが、この人はCを知らないから使うのをやめたいってことか。

「いちどCを実際に触ってみませんか?」って時間を渡してみたら「実際に触ったらCはめっちゃシンプルで良いですね。これならCを使うべきです!」って言ってくれて、へーなるほど。ってなった。

知らない技術は怖い

「知らない」ってだけで、自分の想像で捉えたり、複雑なものだと思い込んだりして、「これは良くないものだ」と断言してしまうんだなぁという学び。

今後の開発に大きな影響を与える決断なんだから、知らない場合は少しぐらい実際に触ってみようとするはずだし、もし触ることができてなかったら「知らない」って言ってくれるはずだし、相手が「これはこういう理由でイケてない」って断言してるんだったら十分な裏付けがあるんだろう、って考えは危ないなぁって思った。

実際は「単に自分はそれを知らないからイケてないと思っている」「知らない技術だから調べるのも怖い」ってことも普通にあるんだなって。そして、断言してしまう。

だから、その裏付けまで踏み込んで確認しておきたいし、そういう人たちが知らない技術を怖がらないように調べ方や学習方法を伝えていけたらいいし、知らないことを知らないって自然と言えるような場を作れたらいいなって思った。

 

 

Page ObjectじゃなくてApp Actionsを使おうというCypressのブログ記事

を読んだ。僕はGebでPage Objectを作るのが結構好きなので、このブログ記事の主張の理由を知りたくて読んだ。そして納得した。

www.cypress.io

## Cypress

Cypressについては今朝書いた。

bufferings.hatenablog.com

CypressでもPage Objectを使えはするんだけど、Page ObjectよりもApp Actions(自分たちが名付けた手法)の方が良いよ!という主張。

## Page Object Pattern

Page Object Patternについては、この辺か

martinfowler.com

この辺かな

https://www.seleniumhq.org/docs/06_test_design_considerations.jsp#page-object-design-pattern

## 言ってること

Page Objectの問題は

  • メンテナンスが大変
  • テスト対象も状態を持っているのに、別の状態を持ち込んでしまう
  • 条件分岐をテストに持ち込んでしまう(これはCypressの主張的にはアンチパターン
  • UI経由で操作をするので遅い

ということで、Cypressは Application Actions という手法を提案

  • アプリケーションの状態を変更するのにUIを経由せずに、JSの関数を作ってそれを使うようにする

そうすることで

  • メンテナンスするPage Objectレイヤーがなくなる
  • 条件分岐がなくなる
  • UIを経由しないので操作が速い

となるよと。

## 感想

  • CypressがターゲットにしてるのはSPAだなと再確認。メリットやデメリットの話がSPA前提になっている。
  • SPAの場合、Page Objectを使わない方が良いというのは分かる。Pageとリクエストが一対一に対応していない場合が多いだろうから。
  • SPAは状態をクライアント側で持つので、CypressがJSを直接操作できるという強みが活かせる
  • テスト対象の状態を用意するために、UIを操作して状態を更新するのではなく、直接JSを操作して状態を用意することができるので速い

Cypressならではの強みを活かした主張だなぁという感じ。で、Cypressを使う場合にはそれに従っておいたら良いのかなと思った。ただ、実際に業務で使ったことがあるわけじゃないので、今は頭の中だけの話。

一方でこういうところに気をつける必要がありそう

  • テストとテスト対象が強く結びついてしまう。テストのためだけに状態を更新できるようにしないといけないかもしれない。
  • end-to-endテストなのに、仕様じゃなくて実装のことを理解して作らないといけない。
  • UIからの操作ではたどり着かない状況を裏側で作りだして、そこに対してテストをしてしまう、といった意味のないテストをしてしまうかもしれない

これも頭の中だけの話。

## 結局Page Objectはどうなの?

で、結局Page Objectはどうなの?というところだけど

  • SPAじゃない場合
    • Page Objectを使って良いと思う。十分メリットがある。
    • CypressでもPage Objectは使えるけど、Cypressを使うならCypress流の方(Page Objectを使わない方)が良いかなとは思う。
  • SPAの場合は
    • Cypressを使う場合は、Page Objectは使わずに、内部状態を直接更新する関数を使う方が良さそうに思った
    • Seleniumを使う場合も、Page Objectじゃなくて良さそうかな。状態をUI経由で更新する関数を用意したら良いのかな。

面白かったー。

Cypressという癖のあるフロントエンドテストツールが面白そう

f:id:bufferings:20190713081853p:plain

## Cypress

最近、Cypressというフロントエンドテストツールを触ってみてる。ブラウザを操作して色々できる。end-to-endのテストがメインではあるかな。

www.cypress.io

コードはこんな感じ ( Writing Your First Test | Cypress Documentation より) 。読みやすい。

describe('My First Test', function() {
  it('Gets, types and asserts', function() {
    cy.visit('https://example.cypress.io')

    cy.contains('type').click()

    // Should be on a new URL which includes '/commands/actions'
    cy.url().should('include', '/commands/actions')

    // Get an input, type into it and verify that the value has been updated
    cy.get('.action-email')
      .type('fake@email.com')
      .should('have.value', 'fake@email.com')
  })
})

これだけで、waitやリトライやタイムアウトも組み込まれてる。

## 仕組み

CypressはSeleniumを使ってない。Seleniumと違ってリモートAPIで操作するのではなくて、直接JavaScriptでDOMを操作してる。面白い。

実際は、iframeで対象ページを読み込んで操作してる。なので same-origin policy を乗り越えるために裏側でごにょっとしてる。詳しくは Web Security | Cypress Documentation に書かれてる。面白い。

## 利点

利点としては

  • リモート操作じゃないから速い
  • UI経由で操作しなくても直接JavaScriptでモデルを触ったりできる

といったものや、他にも

  • wait・リトライ・タイムアウトが組み込まれてるのでテストを書くことに集中できる
  • All-In-Oneになってるからワンコマンドで環境準備ができる
  • DOMのスナップショット機能があるからテストのステップごとにどういう状況だったかを後で確認することができる
  • デバッグができる
  • APIのMockや、ObjectのSpyやStubを簡単に作ることができる

というところがある。便利。内部的には mocha, chai, sinon といったフレームワーク・ライブラリーを使ってる。

## 制約

その分制約も色々あるから注意しておきたい。

  • 1つのテストケースの中では1つのスーパードメインしか対応してない
  • 複数タブや複数ブラウザのテストはできない
  • 今の所Chromeしかサポートされてない

## 有償サービス:Cypress Dashboard

Cypress自体はOSSで無償で利用できる。んで、Cypress Dashboardというサービスが、有償の機能として提供されている。これ、便利そう。

Cypress自体にテストの録画や、失敗したときのスクリーンショットを撮る機能があるんだけど、このCypress Dashboardはテストの結果やその動画などの過去ログを管理してくれる。「このテストが失敗した」ってときに動画を見たりどの処理でエラーになったのかが分かるのは便利そう。

www.cypress.io

個人で使う分には無料のSeedプランで大丈夫かな。OSS用の無料プランもある。

https://www.cypress.io/pricing

## こだわり

公式ドキュメントを一通り読んでみたんだけど、end-to-endのテストに対するこだわりがしっかりあって、それを実現するために色々な制約を受け入れて割り切っている、という感じ。良い。

## 自分の感想

スピードが速いのは素晴らしいんだけど、それだけだとSeleniumじゃなくてCypressを使う強い動機には、僕はならないなと思った。Seleniumだと複数ブラウザに対応してるし、ユーザー操作を再現できるし、あんまりトリックがないし。安心。

だけど、SPAとかみたいにクライアント側で色々やるアプリケーションだと、その裏側をJSで直接簡単に操作したり、DOMのイベントを直接Listenしたりできるのは便利そう。なので、Cypressを使うならそういうところかなと思った。

ということで、LTで、元々はGebの話でもしようかと思ってたんだけど、Cypressの紹介をすることにした。(๑•̀ㅂ•́)و✧

seleniumjp.connpass.com