GAミント至上主義

Web Monomaniacal Developer.

本番環境と開発環境でファビコンの色を変えるとすごい分かりやすい話

環境ごとにファビコンの色を変える小技。
前々職にいたデザイナーさんがやってたのを見てから、使わせてもらってます。

yagishの場合こんな感じ。タブを見ると一瞬で分かる。
f:id:uyamazak:20180814141916p:plain

明らかにヤバい紫のヤギ大根が開発(社内サーバー)
まだできてなさそうな緑のヤギ大根がステージング(Firebase)
白いヤギ大根が本番(Firebase)

ただそれだけのことなんだけど、実際使ってみると「これがデザインの力か」と実感できるはず。
これ開発?本番?と悩む時間が無くなる。
見て一発で分かる、考えたり読まなくていいって大事。

ちなみにyagishではロゴがSVGでVue側で操作できることを活かしてロゴも変えてます
f:id:uyamazak:20180814142145p:plain

実装方法としてはだいたい環境変数で切り替えるんだけど、ただテンプレートでlinkタグをif文で切り替えるか、フレームワーク等によってはプラグインでhead内のタグを管理してるから面倒だったりする。

ノンデザイナーズ・デザインブック [第4版]

ノンデザイナーズ・デザインブック [第4版]

GKEでIngressを使ってService単位でロードバランシングする

以前の下記記事の続きで
uyamazak.hatenablog.com

本番とステージング環境で、管理コストを削減するために

を使いまわし、
/api/* → 本番用Service
/api-staging/* → ステージング用Service
とパスでサービスを分けたいときはIngressが必要だったのでやってみた。

クラスタでよければ、HTTP(S)ロードバランサーの設定だけでクラスタ単位で向けられるのでできる。

Ingressとは

Nianticのゲーム名ではなく、直訳すると「入ること」とか「入場権」的な意味らしい。
ネットワークの文脈だともっといい訳があるかもしんない。
2016年夏ごろにGKEで構築した時は見た覚えがなく、HTTP(S)ロードバランサーの設定でやっていたので、新しめの機能なんだと思う。
今からGKEで構築してドメインSSLを使うならGoogle推奨のやり方となる。

Setting up HTTP Load Balancing with Ingress  |  Kubernetes Engine Tutorials  |  Google Cloud

GKE上でロードバランサーが動くわけではなく、実装はHTTP(S)ロードバランサーで行われている。

それぞれの環境のDeployment, Serviceを作る

今回の主題ではないのでハマりどころ以外はざっくり

以下kcはkubectlのエイリアス

Deploymentは下記二つ

% kc get deploy
NAME                     DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
varuna-django            1         1         1            1           21h
varuna-django-staging    1         1         1            1           21h

それに対するServiceは下記

% kc get service
NAME                     TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
kubernetes               ClusterIP   10.27.240.1     <none>        443/TCP          21h
varuna-django            NodePort    10.27.254.67    <none>        8080:30001/TCP   21h
varuna-django-staging    NodePort    10.27.242.187   <none>        8080:30002/TCP   21h

Ingress用のyamlを書く

公式ドキュメントを参考に振り分けする
ingress.yaml

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: varuna-ingress
spec:
  rules:
  - http:
      paths:
      - path: /*
        backend:
          serviceName: varuna-django
          servicePort: 8080
      - path: /api/*
        backend:
          serviceName: varuna-django
          servicePort: 8080
      - path: /api-staging/*
        backend:
          serviceName: varuna-django-staging
          servicePort: 8080

Deploymentでのヘルスチェック用のパスの設定

IngressのDeploymentに対するヘルスチェックはデフォルトで/、ステータス200になっている。
今回のサービスだと/api/hc的なパスにしていたので、readinessの設定が必要。しばらくハマった。
下記ページでも上がっていた。

github.com
edit deploy でreadinessProbeとついでに同じようなlivenessProbeも設定しておく。

readinessProbeとlivenessProbeについて、それぞれ詳しくは公式ドキュメント
Configure Liveness and Readiness Probes - Kubernetes

kc edit deploy varuna-django
# 適当にいろいろ削った
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  labels:
    run: varuna-django
  name: varuna-django
spec:
  replicas: 1
  selector:
    matchLabels:
      run: varuna-django
  template:
    metadata:
      creationTimestamp: null
      labels:
        run: varuna-django
    spec:
      containers:
      - image: asia.gcr.io/your-project/tag
        livenessProbe:
          failureThreshold: 3
          httpGet:
            path: /api/hc_pdf
            port: 8080
            scheme: HTTP
          initialDelaySeconds: 3
          periodSeconds: 3
          successThreshold: 1
          timeoutSeconds: 3
        name: varuna-django
        ports:
        - containerPort: 8080
          protocol: TCP
        readinessProbe:
          failureThreshold: 3
          httpGet:
            path: /api/hc
            port: 8080
            scheme: HTTP
          initialDelaySeconds: 3
          periodSeconds: 3
          successThreshold: 1
          timeoutSeconds: 3

その他いろいろ

ロードバランサーのIPを静的にするとか、ロードバランサーSSL証明書(Let's Encrypt)の設定をする

Googleが自動でやってくれるのを待ち望んでいるがまだのようなので自分で作ったスクリプトで設置した
自分で作っておいてなんだけど、なかなか設定がめんどくさい。
GitHub - uyamazak/gcp-ssl-auto-renewer: Auto renew SSL Certificates commands on Google Cloud Platform (GCP).

これでクラスタを複数作らずに、サービス単位に振り分けることができた。
GKEというかKubernetesは発展途上なので、時間が空いたら以前やった手順を使わずに、公式ドキュメントを見直した方がよさそう。

コンテナ・ベース・オーケストレーション Docker/Kubernetesで作るクラウド時代のシステム基盤

コンテナ・ベース・オーケストレーション Docker/Kubernetesで作るクラウド時代のシステム基盤

Kubernetes完全ガイド (impress top gear)

Kubernetes完全ガイド (impress top gear)

Docker/Kubernetes 実践コンテナ開発入門

Docker/Kubernetes 実践コンテナ開発入門

個人開発にFirebaseとVue.jsとPWAがおすすめな理由

おかげさまで様々なメディアに取り上げてもらったり、はてブも800超えたりしているyagish。
想像以上の反響の大きさに、勢いがあるうちにもっと良くしようといろいろ施策を考えてます。
が、yagishで使ったVue.js、Firebase、PWAが新規事業だけでなく、個人開発にもすごくいいと感じたので、理由をメモっておきます。
お盆明けぐらいから終業後にまず自分用WEBアプリ作りたい。

rirekisho.yagish.jp

Firebaseの圧倒的低コスト

個人で毎月数千円の固定出費は痛いもの。Firebaseなら低コストで始められ、無料枠と従量性のおかげで忙しくて一時的に開発が止まってそのまま放置しててもお小遣いは安心です。
比較対象はEC2、GCE、GKEやVPSとしています。GAEだとこの点はいい勝負かも。

まずは無料枠で済む

firebase.google.com

fushiroyama.hatenablog.com

この記事にもありますが、Firebaseは無料枠があり、小さなWEBアプリでデータも大きくなければ、ほぼ無料といえる値段で始めることができます。
たとえ大きくなっても他でやるより安い場合が多いですし、困るレベルに利用されたなら、他への載せ替えは余裕だと思います。

ドメインSSLはFirebase Hosting

サービス名とドメインぐらいはちゃんと考えて決めた方がいいとは思いますが、プロトタイプレベルであれば、Firestoreでもらえるサブドメインで問題なく動きます。
しかもSSL証明書も勝手に作成、更新してくれるので、自分でいろいろやる手間が省けます。Let's Encryptでやるにしろ自分で自動化するのは面倒です。
Hostingも開発中なら無料枠で余裕。

DBはFirestore

Firestoreも無料枠超えてからの従量課金なので、使わなければ無料で収まります。ちゃんとしたRDB立てるとなると、Cloud SQLになりますが、これは月5000円程度かかってしまいます。本番利用が推奨されていないmicroなどでも2000円ぐらいはかかるような。GCEやGKEで自分で立てるのはそこまで安くならない上、メンテが面倒すぎて論外です。

サーバーの処理はCloud Functions

サーバー側の処理が必要になったらまずCloud Functionsでなんとかすれば、リクエスト単位の課金なのでよほどの回数、使い方をしなければ安く済みます。
またキャッシュが使えるようなデータであればCache-Controlヘッダーの設定でCDNで返すことができ実行回数が減るので、もっとコストを抑えることができます。

処理に長時間かかったり、動画、ビッグデータなどCPUやメモリを大量に使うようなバッチ処理はプリエンプティブ仮想マシンを使えばいいと思いますが、新規、個人開発でいきなり必要になることはほとんどないと思います

cloud.google.com

これらを活用すれば開発中、公開後アクセスがないうちは月数ドル以下で抑えることが可能です。
が、使い方によっては下記の記事のようにもちろんバカ高くなる可能性もありますので、保証はできません。
無駄な利用は減らし、予算とアラートは必ず設定しましょう。

gigazine.net

圧倒的開発スピード

Vue.jsなどの最新の開発環境と、Firebaseのライブラリを活用して圧倒的スピードで開発できます(個人の感想)

Vue.jsなどの最新のJavaScript開発環境を活用

これは最近活発なnpm、node.js、ライブラリ、フレームワークなどJS界隈のおかげです。

私はVue.jsにしましたがReact、Angularでも状況や好みに合わせて選べば大きな違いにはならないかと思います。

個人的にPythonが読みやすいしコードのブレが減るので好きなんですが、昨今のメリットを考えるとjavascriptを使うほかにないと思います。またES2016とかどんどん便利な機能が追加されているので、JSのストレスはどんどん減っていくと思います。

周りの話を聞くとNuxt.jsがいいよ、と言っている人も多いし、使ってる人も多いんですが、Vue-CLI3でrouter、Vuexなど公式機能は一通り使えるようになるので、私はまだ使わなくてもいいかなという感じがしました。Vue本体の機能を使いこなして不便を感じたら移ろうかな。SSR必須だったり、典型的なWEBサイトであればNuxt.jsの方が楽そうです。

サーバー側のCloud Functionsもjsで

最近Python3も使えるようになったので、それでもいいんですが、やっぱり脳の切り替えや実際の書き換えコストがあるため、同じ言語、パッケージ、ライブラリ等を使って両方書けるのは大きいと思います。

最近Node.js 10が使えるようになったのでasync/awaitも使えます。

デザインフレームワークを活用

デザインフレームワークも充実しており、おなじみのBootstrap,マテリアルデザインなどをVueコンポーネントで使うことができます。

qiita.com

yagishではelement-uiを使い、他の社内システムではVuetify、8月から新しく開発するものはiViewを使用してます。

これらを使うことで、ほとんど自分でCSSを書くことなくレイアウトを組むことができると思います。

ユーザー認証にコード不要

ユーザー認証にはFirebaseのAuthenticationを使い、Google,、FacebookTwitterGitHubなどのソーシャルログインだけにすればログインのフォームUIですら必要ありません。
特に最初はGoogleログインだけにすればアプリ登録も不要なので早いです。
またパスポート不要のメール認証にも対応しており、今後使う予定です。

またDBのFirestoreではその構成単位であるコレクション、ドキュメント単位で上記Authenticationの情報を使ったルールで権限を与えることができるので、アプリ側でいちいちユーザーに権限があるのか、クエリごとにチェックする必要がなく、ルールさえしっかり設計すれば安心してコードを書くことができます。
ルールに沿ってないクエリは実行前にはじかれます。

yagishではuidをつかったコレクション(ディレクトリみたいな感じ)で切り、その下はそのユーザーでしか読み書きできない、というシンプルなルールだけで済んでます。

ユーザーが作ったコンテンツを一般公開したり、ユーザー間で共有、グループ機能などをする場合は結構複雑になってくると思いますが、下記の公式ドキュメントとか参考にいじりまくればなんとかなりそうです。

ユーザーとグループのデータアクセスを保護する  |  Firebase

学習コスト

新しい技術を身に着ける勉強時間を単純にコストとするのに納得がいかないし、Firebaseを学習して損はない。個人的にはコストとは感じないので論外。

[asin:B07F8L6KVS:detail]