血と汗となみだを流す

個人の思ったこと、やったことの吐き出し口です。

k8s source code readingに参加しました

k8s source code readingの#0〜2に参加させて頂きました。
k8s source code reading #0 ツイートまとめ

「日本からのコントリビュータがもっと増えるように」という目的で開催されたとのことです。

Kubernetesに強い方々が参加される中、KubernetesでちょっとPodを動かした、Goは触ったこと無いというレベルの俺が参加してみました。

簡単に感想を言うと最高です。
普段触ってるだけでは得られない知識をもらえるし、わからないところは教えてもらえるし。
今後も可能な限り参加したいと思います。

進め方としては「テーマを決めて、テーマごとにグループを作ってコードリーディング」という形式です。
#0 はAPIサーバ
#1, 2 はkubectlをテーマにしてみました。

k8s source code reading #0

API Server関連のコードを読んでみました。
なんとなく「KubernetesはすべてAPIサーバ経由で操作を行う」みたいなことを聞いたことがあったので「じゃあAPIサーバから見てみようかな」くらいの軽い気持ちで選びました。

入り口のコードはここです

どのように読んだらよいかわからず、1行1行調べながら読み進めましたが、結局「CobraというCLIを作れるツールを使っている」程度にしかわかりませんでした。
goをまとも触ったことがないので1行読むにもすごい時間が掛かってしまいます。

発表の前にグループ単位で共通の画面を見ながらコードを読む形式に変わりました。
ここでの説明は正直理解できていなかったですが、「コード全体をざっくり読んで、全体の動きを掴む」ということを学びました。
1行1行じゃ結局先に何があるのか見えないまま、読んでも理解が進まないと思いました。

k8s source code reading #1

今回は一番使うことが多い「kubectl」を選択しました。
発音も「キューブコントロール」と完璧です。

前回の学びの通り「まずざっくり全体を読む」をやってみました。
入り口のコードはここです

ざっくり読んでわかったことは、

  • Cobraでコマンドを生成
  • オプションの形を統一している
  • Goのflagパッケージを追加
  • ログの初期化
  • コマンド実行

こんな感じです。
細かいところはあとで読みます。
まずは全体を理解するのが大事。

一番時間を使ったのは

pflag.CommandLine.SetNormalizeFunc(utilflag.WordSepNormalizeFunc)

というところでオプションの形を変更しているところでした。
"_"のところを"-"にする、みたいな。

でも何で変更しているのか?
それはそのうちわかるかもしれないから飛ばします。

他にざらっと読んで気になったのはalpha.goというやつでした。
「何だこれ、囲碁のやつか?」と思いながら読んでみたところ、 デフォルトでは有効になっていないalpha機能 を登録するコードのようでした。

そこで過去にどのようなalpha機能があったのか、commit履歴を見てみると、

History for pkg/kubectl/cmd/alpha.go - kubernetes/kubernetes · GitHub

diff という機能しかありませんでした。しかもmerge済み。
これからalpha機能ができたらここの履歴が増えていくのかもしれません。

k8s source code reading #2

前回に引き続き「kubectl」を読みました。
気になる単語として「flag」と「profile」があり、一体何してんだ?というところを深くおっていました。

結果として「flag」はKubernetesじゃなくてgoの話でした。

flag - The Go Programming Language

簡単に言うとコマンドラインを作るときのオプションを実装するパッケージでした。
サンプルコードを書いてみて挙動を確認!(完全に理解した)
やはり手を動かすと理解が早いですね。

次に「profile」を調べていましたが時間切れでした。
公式ドキュメントには、

Name of profile to capture. One of (none|cpu|heap|goroutine|threadcreate|block|mutex)

とあるのでコマンド実行時のCPU使用率とか見れるのかな?程度の理解でした。

発表の際にこの旨を伝えるとやはりコマンド実行時のプロファイル情報が取れるとのことでした。
(こういう基礎的なことも教えてもらえるの最高では?)

またPR情報も教えて頂きました!
https://github.com/kubernetes/kubernetes/pull/68681
(これがすぐ出てくるって凄いのでは・・・)

あとで以下のようなコマンドを打ってみると、

% kubectl get nodes --profile=block -v6

おお、APIの実行時間とか取れる!!

I0222 23:39:13.587949    1396 loader.go:359] Config loaded from file /Users/AnorLondo/.kube/config
I0222 23:39:13.590525    1396 loader.go:359] Config loaded from file /Users/AnorLondo/.kube/config
I0222 23:39:13.656553    1396 round_trippers.go:438] GET https://localhost:6443/api?timeout=32s 200 OK in 61 milliseconds
I0222 23:39:13.661790    1396 round_trippers.go:438] GET https://localhost:6443/apis?timeout=32s 200 OK in 3 milliseconds
I0222 23:39:13.678093    1396 round_trippers.go:438] GET https://localhost:6443/apis/apps/v1?timeout=32s 200 OK in 12 milliseconds
I0222 23:39:13.680703    1396 round_trippers.go:438] GET https://localhost:6443/apis/batch/v1beta1?timeout=32s 200 OK in 15 milliseconds
I0222 23:39:13.709121    1396 round_trippers.go:438] GET https://localhost:6443/apis/authentication.k8s.io/v1?timeout=32s 200 OK in 40 milliseconds
I0222 23:39:13.709204    1396 round_trippers.go:438] GET https://localhost:6443/apis/apps/v1beta1?timeout=32s 200 OK in 42 milliseconds
I0222 23:39:13.709236    1396 round_trippers.go:438] GET https://localhost:6443/api/v1?timeout=32s 200 OK in 43 milliseconds
I0222 23:39:13.709265    1396 round_trippers.go:438] GET https://localhost:6443/apis/apiregistration.k8s.io/v1beta1?timeout=32s 200 OK in 42 milliseconds
I0222 23:39:13.709291    1396 round_trippers.go:438] GET https://localhost:6443/apis/apiregistration.k8s.io/v1?timeout=32s 200 OK in 43 milliseconds
I0222 23:39:13.709321    1396 round_trippers.go:438] GET https://localhost:6443/apis/storage.k8s.io/v1beta1?timeout=32s 200 OK in 41 milliseconds
I0222 23:39:13.709340    1396 round_trippers.go:438] GET https://localhost:6443/apis/extensions/v1beta1?timeout=32s 200 OK in 41 milliseconds
I0222 23:39:13.709346    1396 round_trippers.go:438] GET https://localhost:6443/apis/authentication.k8s.io/v1beta1?timeout=32s 200 OK in 39 milliseconds
I0222 23:39:13.709364    1396 round_trippers.go:438] GET https://localhost:6443/apis/networking.k8s.io/v1?timeout=32s 200 OK in 42 milliseconds
I0222 23:39:13.709382    1396 round_trippers.go:438] GET https://localhost:6443/apis/rbac.authorization.k8s.io/v1?timeout=32s 200 OK in 39 milliseconds
I0222 23:39:13.709381    1396 round_trippers.go:438] GET https://localhost:6443/apis/rbac.authorization.k8s.io/v1beta1?timeout=32s 200 OK in 40 milliseconds
I0222 23:39:13.709400    1396 round_trippers.go:438] GET https://localhost:6443/apis/autoscaling/v1?timeout=32s 200 OK in 39 milliseconds
I0222 23:39:13.709386    1396 round_trippers.go:438] GET https://localhost:6443/apis/admissionregistration.k8s.io/v1beta1?timeout=32s 200 OK in 41 milliseconds
I0222 23:39:13.709415    1396 round_trippers.go:438] GET https://localhost:6443/apis/apiextensions.k8s.io/v1beta1?timeout=32s 200 OK in 40 milliseconds
I0222 23:39:13.709414    1396 round_trippers.go:438] GET https://localhost:6443/apis/storage.k8s.io/v1?timeout=32s 200 OK in 40 milliseconds
I0222 23:39:13.709430    1396 round_trippers.go:438] GET https://localhost:6443/apis/batch/v1?timeout=32s 200 OK in 38 milliseconds
I0222 23:39:13.709435    1396 round_trippers.go:438] GET https://localhost:6443/apis/events.k8s.io/v1beta1?timeout=32s 200 OK in 41 milliseconds
I0222 23:39:13.709430    1396 round_trippers.go:438] GET https://localhost:6443/apis/apps/v1beta2?timeout=32s 200 OK in 43 milliseconds
I0222 23:39:13.709452    1396 round_trippers.go:438] GET https://localhost:6443/apis/authorization.k8s.io/v1?timeout=32s 200 OK in 38 milliseconds
I0222 23:39:13.709458    1396 round_trippers.go:438] GET https://localhost:6443/apis/certificates.k8s.io/v1beta1?timeout=32s 200 OK in 43 milliseconds
I0222 23:39:13.709458    1396 round_trippers.go:438] GET https://localhost:6443/apis/policy/v1beta1?timeout=32s 200 OK in 42 milliseconds
I0222 23:39:13.728220    1396 round_trippers.go:438] GET https://localhost:6443/apis/autoscaling/v2beta1?timeout=32s 200 OK in 57 milliseconds
I0222 23:39:13.728337    1396 round_trippers.go:438] GET https://localhost:6443/apis/authorization.k8s.io/v1beta1?timeout=32s 200 OK in 57 milliseconds
I0222 23:39:13.728729    1396 round_trippers.go:438] GET https://localhost:6443/apis/compose.docker.com/v1beta2?timeout=32s 200 OK in 58 milliseconds
I0222 23:39:13.739549    1396 round_trippers.go:438] GET https://localhost:6443/apis/compose.docker.com/v1beta1?timeout=32s 200 OK in 74 milliseconds
I0222 23:39:13.773700    1396 loader.go:359] Config loaded from file /Users/AnorLondo/.kube/config
I0222 23:39:13.782674    1396 loader.go:359] Config loaded from file /Users/AnorLondo/.kube/config
I0222 23:39:13.795729    1396 round_trippers.go:438] GET https://localhost:6443/api/v1/nodes?limit=500 200 OK in 9 milliseconds
I0222 23:39:13.797695    1396 get.go:563] no kind is registered for the type v1beta1.Table in scheme "k8s.io/kubernetes/pkg/api/legacyscheme/scheme.go:29"
NAME                 STATUS   ROLES    AGE   VERSION
docker-for-desktop   Ready    master   2d    v1.10.11

なるほど、これはいつか使うことになりそう。
挙動がわかったので、次回もう一度profile周りを読んでみよう。

まとめ

Kubernetesはアプリからインフラまでいろんなことを学べる良い題材だと思います。
まだインフラ初めて2年の若輩者ですが、Kubernetesを通じていろんなことを学んでいきたいと思います。

PHPフレームワーク Laravel Webアプリケーション開発を読んでハマったところ

概要

第一章 3.登録画面を作る

  • 一通りコーディングして、ユーザ登録フォームは表示できたんだけど、値を入力して「送信」するとエラー
[2019-02-04 15:39:17] local.ERROR: SQLSTATE[HY000] [2002] Connection refused {"exception":"[object] (PDOException(code: 2002): SQLSTATE[HY000] [2002] Connection refused at /var/www/vendor/laravel/framework/src/Illuminate/Database/Connectors/Connector.php:67)

原因

  • .env が間違ってた
[正]
DB_HOST=mysql

[誤]
DB_HOST=127.0.0.1

経緯

  • migrate(php artisan migrate)をコンテナ内で実行せずに、ローカルPCで実行しようと「DB_HOST=127.0.0.1」としていた(手抜き)
  • 「DB_HOST」を変えないままだったので、Laravelが動いているコンテナからMySQLのコンテナが見えなくなってしまっていた。

まとめ

  • 横着せずにちゃんとやろう

KubenetesのapiVersionに指定する項目について調べた

概要

  • KubernetesでPodとかReplicaSetをyamlで作るときの apiVersion の書き方が気になったので調べた

たとえば

  • Podの時
apiVersion: v1
  • ReplicaSetの時
apiVersion: apps/v1
apiVersion: extensions/v1beta1

気になった点

  • Podは何でv1だけで良いのか?

調べた結果

  • KubernetesAPIcoreとかappsとかのグループに分かれている。
  • coreはレガシーグループと呼ばれ、
    • RESTのPATHは/api/v1配下にある
    • apiVersionの指定はapiVersion: v1になる
    • Podはcoreグループ
  • その他のグループ(appsとかextensionsとか)は、
    • RESTのPATHは/apis/[グループ名]/[バージョン番号]配下にある
    • apiVersionの指定はapiVersion: [グループ名]/[バージョン番号]になる
    • ReplicaSetはappsグループ、Ingressはextensionsグループ
  • 参考

まとめ

  • coreグループのAPIのみ、apiVersion: v1という形式になる
  • 他グループのAPIapiVersion: [グループ名]/[バージョン番号]になる

インフラエンジニアのためのAPI Gateway入門〜API Gatewayがわからないからわかったところだけ伝える〜

この記事は #インフラ勉強会 Advent Calendar 19日目(12/19)の記事です!

adventar.org

概要

  • AWSのマネージドサービス「API Gateway」についての記事になります。
  • サービスの内容について書こうと思いましたが思った以上に奥が深く、すべてを把握することが出来なかったため、「どんなものか」をふわっと伝える内容になります。
  • ※完全に筆者の主観で書いているため、認識の齟齬や間違いが含まれている可能性がありますのでご了承ください。

内容

  • API Gatewayの使い所
  • 他のマネージドサービスと違うところ

API Gatewayの公式ページ


API Gatewayの使い所

  • Lambdaの前段として
    • AWSサービスと組み合わせて使う場合は主にLambdaとの組み合わせになるかと思います
    • LambdaはREST APIのような形式で実行できないため、Lambdaを実行するためのAPIとして使われることが多いようです
      • 2018年11月のバージョンアップで、ALB(Application Load Balancer)のbackendにLambdaが指定できるようになりました
      • 既存のendpointがALBで一部のPATHのみLambda、のようなことができるようになりました
  • APIの抽象化として
  • backendのリファクタリングをしたいが、APIの呼び元からの実行形式を変えたくない場合など、API Gatewayを挟んで抽象化しておくことができます
  • レスポンスのキャッシュ機能
    • backendからのレスポンスをAPI Gatewayがキャッシュすることができるため、backendの負荷を減らすとともに応答速度の向上が見込めます
    • ただしキャッシュするデータ量によってコミット料金が掛かるのでキャッシュするデータと料金の兼ね合いになるかと思います

他のマネージドサービスと違うところ

  • バージョン管理と環境別デプロイ
    • 「ステージ」という機能があり、API Gateway単体でバージョン管理や環境別デプロイが実施できます
    • AWSアカウントで環境を分けてたりする場合、API Gatewayだけどうしたもんかと悩むなど・・・
  • 性能の制限を設定できる
  • APIキー毎にキャパシティの制限が掛けられます。
    • 例えば外部に提供するAPIを、無料/有料で使用できるキャパシティを変えるなど
    • ↑実際やっているという例を聞いたこと無いけど・・・
  • SDKの自動生成機能
  • 言語固有の方法でAPIを実行するときのSDKを生成する機能があります。
  • 一部のメソッドで対応していない言語有り(ANYメソッドでRubyのSDKは出力できない)

まとめ

  • SDK周りがまだ不安定ですが、REST APIとして使う分にはとても良い
  • APIを提供する機能だけでなく、横も縦も幅広い機能です。正直全部理解できる気がしない。がんばる

API Gatewayをはじめよう⑦(ANYメソッドでRubyのSDKは出力できない)

この記事は何?

  • API GatewaySDKRubyで生成しようとしてエラーになり、ハマった記録です。
  • ※2018/10/31現在

ハマったポイント

  • 作成したリソースをデプロイし、SDKの生成をしようとしたらエラーとなった。
  • 公式ドキュメントを見てもどこにも記載がなかったのでAWSのサポートに聞いた
  • サポートに聞いたところ「ANYメソッドではRubySDKは対応していない」とのことだった
  • GETやPOSTメソッドならSDK生成できた
  • Javascript Androidなど他のプラットフォームは出力できた

発生する条件

  • メソッドを「ANY」で作成する
  • ステージにデプロイし、SDKの生成でプラットフォームをRubyにする

発生する現象

  • 以下のエラーが出て、SDKが出力されない
Generation failed during BUILD stage: no operations found for the service

f:id:Anorlondo448:20181014232444p:plain

結果

  • ANYメソッドがサポートされるまで待つか、GET/POSTなどのメソッド単位でリソースを作成するしか今はなさそう

前回までの記事

API Gatewayをはじめよう⑥(メソッドリクエスト(Method Request):APIキー/使用量プラン)

この記事は何?

  • API Gatewayのメソッド(Method)で、メソッドリクエスト(Method Request)で設定する項目と、使用量プランについて調べた結果のまとめです
  • メソッドリクエストだけでも内容がいっぱい詰まっているので、その中のAPIキー部分を書いています
  • APIキー使用量プランと関連づいているので、使用量プランについても書いています

APIキーと使用量プランとは?

  • API キーを使用する使用量プランの作成と使用
  • APIキーはユーザ認証に使う物では無い
  • 使用量プランと合わせて、APIキーごとのリクエストの制限を行う
    • このキーはこの制限まで、こっちのキーはこの制限まで、みたいな使い方
  • 使用量プランとは
    • APIキー毎に「1秒あたりのリクエスト数はこれだけ」「一定期間内のリクエスト数はこれだけ」などを設定する
    • たとえば、Aプランはここまで使えて、Bプランはここまで使える、みたいなパターンが作れる

APIキー

作成

  • 左ペインのAPIキーから[アクション]-[APIキーの作成]で作成できる f:id:Anorlondo448:20181030220126p:plain
  • 名前説明を入力する
  • 自動生成カスタム(自分で入力)を選ぶ f:id:Anorlondo448:20181030220153p:plain
  • これで生成完了する
  • APIキー 表示でキーの文字列が表示できる f:id:Anorlondo448:20181030220220p:plain

編集

  • 名前説明を入力する
  • APIキーの有効/無効を切り替えできる

プランに関連付ける

  • 使用量プランを作成しておく必要がある

使用量プラン

生成したAPIキーを実際使ってみる

  • メソッドリクエストのAPIキーの必要性をtrueにする f:id:Anorlondo448:20181030220454p:plain
  • ステージにデプロイする
  • APIキー無しでアクセスしてみる
$ curl https://xxxxxxxx.execute-api.us-east-1.amazonaws.com/dev/postlambda
{"message":"Forbidden"}
  • APIキーを付けてアクセスしてみる
$ curl https://xxxxxxxx.execute-api.us-east-1.amazonaws.com/dev/postlambda  --header 'x-api-key:xxxxxxxxyyyyyyyyzzzzzzzzaaaaaaaabbbbbbbb'
{"statusCode":200,"body":"\"Hello Elastic!\""}

次回

  • 認証周りを少しずつでも理解する!

前回までの記事

SendGrid Send With Confidence Tourに参加しました

この記事は何?

Eメールはオワコン?

  • メールの利用自体は増え続けている
  • メールによるコミュニケーションが好まれている
    • デジタルコミュニケーションに必須
    • 最も普及しているデジタルID
    • あらゆるWebサービスのIDとして利用されている
      • ECサイトSNSの登録時はメールアドレスがほぼ必須
    • 一般消費者がセキュアに利用可能
    • 非常に高いROI
  • 用途は変化したがメールは生き続け、サービス提供の上で必須なものとなっている

難しいメール配信

  • 正当なメールの20%が受信トレイに到達していないという調査結果がある

メール戦略

  • EメールはどのチャネルよりもROIが高い
    • $1投資で$38のリターンがある
  • 送られる時間、件名の長さ、絵文字の使用などの違いによる効果を知ることが大事
  • 近年メールを送る件数は減っている
    • 対象をしぼってメールを送ることで開封率やクリック率をあげる
  • 誰が購読者であるかを理解することにより、戦略を建てる
    • 女性が多い、モバイルが多い、など
  • よく寝られた戦略をもってメールを送信する必要がある
    • Subject Line(件名)
    • Copy(コンテンツ)
    • Image(画像)

Subject Line(件名)

  • 最初に購読者の目に入る物
  • これが購読者の心に響かないと行けない
    • ディスカウントだったり、質問だったり、続きが気になるようなもの
    • 懸命にいくつの単語を含めるのがよいか
      • 7単語 が平均的(英単語で?)
      • 4単語が最もengagementが高い
  • モバイル機器で長い件名は不利
  • 絵文字は?
    • 何を提供しているかがわかりやすい
    • 受信箱の中で目立たないといけない
    • 差別化はできるけど、受信箱の中で目障りになってしまうかもしれない
    • 受信箱に正しく表示されるのかテストが必要
  • 件名にFirst Nameを使ってもengagementは上がらない
    • 「◯◯さんにオススメ!」みたいなやつ
  • First Name以上の何らかの惹きつけるものが必要

Copy(コンテンツ)

  • 統一的なトーンを使う
  • ユーモアなど、購読者に響くものを使う
    • あえて砕けた表現をつかって、限定的な層を狙うなど
  • 誰かを排除するようなトーンは使わない
  • いろいろなデバイスで受信されるので、デバイスにあった表示方法
  • メールに商品情報を載せてしまって、商品購入までのステップを減らす

Image(画像)

  • 多くの画像を入れすぎないようにする
  • たくさん画像を載せるのでなく、メールの内容に合うものを入れよう

メール送信者と受信者の関係の構築

  • 受信者が送信者をどう考えているか?を考える
  • Eメールの開封率やクリック率が低い場合は、受信者との関係を見直さないといけない
  • SendGrid側で実績や数値などのレポートを作成している
  • 信頼関係を増すには「特別感があるか」など、購読者第一を考える
  • コンプライアンスも重要
    • 地域性による規制
    • 日本でもメール送信の同意が必要であり、解約方法も明示的でないといけない。

SendGridについて

  • 74,000以上のユーザが利用している
  • 毎月450億通以上のメールを送信しており、送信件数は増加の一方である
  • SendGridの支部は日本に無いが、株式会社構造計画研究所が代理店をやっている
    • 日本語Webサイト/ドキュメント/サポート/日本円決済などの日本向けサポート
  • SendGrid社がTwilioによる買収されるが、SendGridのサポートに変化はない
  • 毎年ベンチマークレポートを出している
    • 近年メールを送る件数は減っている
    • 対象をしぼってメールを送ることで開封率やクリック率があがる

SendGridの始め方

  • サイトアクセスし、アカウント作成する
    • 悪用されるのを防ぐために、アカウント作成の前に審査がある
  • 無料で12,000/月送信可能で、ほぼすべての機能が使える
プライバシーポリシー