パパエンジニアのポエム

奥さんと娘ちゃんへの愛が止まらない

ElixirライブラリをHexに公開してみた③ LINE Pay編

Elixirのライブラリ公開シリーズ第3弾

LINE Payとは

line.me

LINEでお金のやりとりをするスマホのおサイフサービスとのこと。

ドキュメント

技術サポート : LINE Pay Merchant

はっきり言ってしまうのは憚れるがかなり読みづらいドキュメントだった。 韓国語の翻訳版なのかもなーと思ったり。

ソースコード

GitHubソースコードはこちら

github.com

公開

#!/bin/sh

ENV=dev

# get dependencies
MIX_ENV=$ENV mix deps.get

# build
MIX_ENV=$ENV mix compile

# publish hex
MIX_ENV=$ENV mix hex.publish

無事Hexに公開されました。

hex.pm

ElixirライブラリをHexに公開してみた② Paidy編

Elixirのライブラリ公開シリーズ第2弾

Paidyとは

paidy.com

事前登録不要・クレジットカード不要・早い・安心・支払いが便利なカンタン決済サービスです。

ドキュメント

paidy.com

JavaScriptのドキュメントで一部必須項目が間違っていたので注意。
どこだか忘れてしまった笑。

ソースコード

GitHubソースコードはこちら

github.com

公開

#!/bin/sh

ENV=dev

# get dependencies
MIX_ENV=$ENV mix deps.get

# build
MIX_ENV=$ENV mix compile

# publish hex
MIX_ENV=$ENV mix hex.publish

無事Hexに公開されました。

hex.pm

ElixirライブラリをHexに公開してみた① PAY.JP編

Elixirのライブラリ公開シリーズ第1弾

Hex

Hex は Elixir, Erlang 向けのパッケージ管理ツールです。
ruby で言うところの rubygems、node.js で言うところの npm です。
Hexの使い方は省きます。

PAY.JPとは

pay.jp
クレカの決済代行サービスです。
業務上決済機能を実装することになったので、そのタイミングで公開しました。

ドキュメント

PAY.JP API リファレンス

大変読みやすく、まったく詰まることなく実装できました。
ありがたや。

ソースコード

GitHubソースコードはこちら
GitHub - yuki-toida/ex_payjp

公開

#!/bin/sh

ENV=dev

# get dependencies
MIX_ENV=$ENV mix deps.get

# build
MIX_ENV=$ENV mix compile

# publish hex
MIX_ENV=$ENV mix hex.publish

無事Hexに公開されました。
hex.pm

GCEとCloudSQLとDockerでmetabase

metabaseってなんぞ?

データ可視化OSSです OSSのデータ可視化ツール「Metabase」が超使いやすい ちょっとつかってみた感じ、すこぶる良いです データ分析は全部こいつにぶん投げるのがとてもよさそう

GCE(Container-Optimized OS)作成

インスタンスの作成と設定  |  Container-Optimized OS  |  Google Cloud * コンソールのブートディスクからContainer-Optimized OSを選択する * CloudSQLに接続可能なサービスアカウントCloudSQLClientを作成し設定する(詳細省略) * HTTP/HTTPSを開ける

ユーザー定義bridgeネットワーク作成

metanetというbridgeネットワークを作成し各コンテナの起動時に指定する これで同一ネットワーク内でコンテナを起動できる

docker network create -d bridge metanet

CloudSQLへのプロキシコンテナ作成

Cloud SQL Proxy Docker イメージを使用して MySQL クライアントを接続する  |  Cloud SQL for MySQL  |  Google Cloud

docker pull gcr.io/cloudsql-docker/gce-proxy:1.11

PAY.JP API リファレンス

docker run --name cloud_sql_proxy --net=metanet -d \
-v /mnt/stateful_partition/cloudsql:/cloudsql \
-p 3306:3306 \
gcr.io/cloudsql-docker/gce-proxy:1.11 /cloud_sql_proxy \
-instances=planet-pluto-dev:asia-northeast1:mysql-dev=tcp:0.0.0.0:3306

ここでのポイントはポートをホストのローカル127.0.0.1でバインドする必要がないこと metanet経由のコンテナ間通信を行い、ポート3306でCloudSQLにプロキシ接続する あとは--net=metanet を指定するのを忘れないこと

metabase コンテナ作成

docker run -d -p 80:3000 --name metabase --net=metanet metabase/metabase

同じように--net=metanet を指定する

PINGで疎通確認

これで、metanet内ではコンテナ名で名前解決可能になる コンテナ内からPINGで疎通確認

docker exec -it metabase /bin/bash
ping cloud_sql_proxy

疎通できていたらmetabaseからMySQLをDBに設定

HOST : cloud_sql_proxy
PORT : 3306

で接続できるはず

おまけ

ちなみに最初は docker-compose を使って接続していた ただContainer-Optimized OSにdocker-compose をインストールするのが手間なので、オススメしない Running Docker Compose with Docker  |  Google Cloud Platform Community  |  Google Cloud 一応そのときのdocker-compose.ymlを貼っとく

version: '2'
services:
cloud_sql_proxy:
image: gcr.io/cloudsql-docker/gce-proxy:1.11
container_name: cloud_sql_proxy
command:
- "/cloud_sql_proxy"
- "-instances=planet-pluto-dev:asia-northeast1:mysql-dev=tcp:0.0.0.0:3306"
volumes:
- /mnt/stateful_partition/cloudsql:/cloudsql
ports:
- "3306:3306"
metabase:
image: metabase/metabase
container_name: metabase
volumes:
- /mnt/stateful_partition/tmp:/tmp
environment:
- "MB_DB_FILE=/mnt/stateful_partition/metabase.db"
ports:
- "80:3000"

GKE で Let's Encrypt (ワイルドカード編)

まえがき

cert-manager は使わないです。
理由は、kube-lego で時間を無駄にしてしまったから。
これから kubernetes がどう変わっていくかわからないのと、
シンプルでプリミティブなシステムが好きなので、公式の方法で行いました。
なので、 3ヶ月に1回手動対応 です。

certbot インストール

brew install certbot

certbot 実行

sudo certbot certonly --manual \
  --preferred-challenges dns-01 \
  --server https://acme-v02.api.letsencrypt.org/directory \
  -m hoge@fuga.com \
  -d sample.com \
  -d *.sample.com

こんな感じで、メインドメインワイルドカードサブドメインを引数に渡し実行。

DNSにTXTレコード追加

-------------------------------------------------------------------------------
Please deploy a DNS TXT record under the name
_acme-challenge.sample.com with the following value:

lgfkjaldfjlasdkgjjakdflasjflaslasdjf

Before continuing, verify the record is deployed.
-------------------------------------------------------------------------------

↑の値をTXTレコードに追加します。

DNS名:_acme-challenge.sample.com 値:lgfkjaldfjlasdkgjjakdflasjflaslasdjf

追加したら、Enter を押す。 登録前に押すとこけます。
あと、DNSにメインドメイン以外のAレコードがあるとこけました(ちょっとハマった)

tls用の Secret 作成

↑で作成された証明書を元にSecret作成

sudo kubectl create secret tls tls-certs \
  --key /etc/letsencrypt/live/sample.com/privkey.pem \
  --cert /etc/letsencrypt/live/sample.com/fullchain.pem

IngressでSecretを参照

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ing-dev
spec:
  tls:
  - secretName: tls-certs
  backend:
    serviceName: svc-dev
    servicePort: 80

↑みたいに tls-certs を追加する。
Ingress デプロイ後、2,3分間 経過すると反映されてます。
サブドメインDNSに登録しワイルドカードが聞いているか確認してみましょう。

まとめ

公式のやり方でサクッと対応できました。
3ヶ月に1回の更新もシェルスクリプトで対応できそうです。
cert-manager に対応して、破壊的変更リスクとバグリスクを抱えるより、
3ヶ月に1回の更新コストをとったという感じです。

Container-Optimized OS で Redisをホストする

GCE(Container-Optimized OS)作成

インスタンスの作成と設定  |  Container-Optimized OS  |  Google Cloud

コンソールのブートディスクからContainer-Optimized OSを選択する
後は、任意でポチポチやるだけ

f:id:yuki-toida:20180319160931p:plain

Redis コンテナ起動

コンテナ名を redis-master
コンテナイメージを redis:4-alpine
ポートを 6379
永続化(AOF)フォルダを /home/redis/data
とすると、下記コマンドでRedisコンテナ起動

docker run --name redis-master -p 6379:6379 -v /home/redis/data:/data -d redis:4-alpine redis-server --appendonly yes

GCE の startup script 設定

再起動時に redis-master コンテナを起動するようにする
インスタンスredis-master-dev とすると、下記コマンドで設定完了
sh gcloud compute instances add-metadata redis-master-dev --metadata startup-script='#! /bin/bash docker start redis-master'

コンテナ環境前提でGCEを使う場合 Container-Optimized OS 入れとけばおkです
コンテナ最高すぎる

GKE LBで、Ingressを使ってTLS/SSL対応する

追記

kube-legoがオワコンになったのでこの記事もオワコンになりました
GitHub - jetstack/kube-lego: Automatically request certificates for Kubernetes Ingress resources from Let's Encrypt

kube-legoのセットアップ

Kubernetes Ingress リソースを使って GCP上にHTTPSロードバランサを構築する

kube-legoを使う
github.com

コンテナクラスタは作成されている前提で進める
yuki-toida.hatenablog.com

kube-lego をクローンする

git clone https://github.com/jetstack/kube-lego.git

lego 作業フォルダに移動

cd kube-lego/examples/gce/lego/

configmap.yamlを編集して、lego.email を適切に設定する

kube-legoのリソースを作成する

kube-lego/examples/gce/lego/配下にあるリソースを作成する

kubectl create -f ./

namespace "kube-lego" created
configmap "kube-lego" created
deployment "kube-lego" created

kube-legonamespace に作成されているか確認する

kubectl get deployment,replicaset,pod,configmap --namespace kube-lego

Ingressリソースを作成する

DeploymentやServiceは作成されているものとする

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress-dev
  annotations:
    kubernetes.io/ingress.global-static-ip-name: "ingress-dev-ip"
    kubernetes.io/ingress.class: "gce"
    kubernetes.io/tls-acme: "true"
spec:
  tls:
  - hosts:
    - sample.com
    - sub.sample.com
    secretName: ingress-dev-tls
  rules:
  - host: sample.com
    http:
      paths:
      - path:
        backend:
          serviceName: service-dev
          servicePort: 80
  - host: sub.sample.com
    http:
      paths:
      - path:
        backend:
          serviceName: service-dev
          servicePort: 80

ここで注意することは、
kubernetes.io/ingress.allow-http: "false"アノテーションを入れないこと、HTTPで認証を行っているので失敗する

作成後、ロードバランサーの疎通と認証が通るまで15分くらい時間かかる
kube-legoのログをみながら認証が通ったか確認する

kubectl logs -f --namespace kube-lego $(kubectl get pod --namespace kube-lego -l app=kube-lego -o name)

認証が通ったらhttps://ドメインで疎通確認