まーぽんって誰がつけたの?

iOS→Scala→インフラなおじさん技術メモ

顧客が本当に欲しかったJenkinsのdatadog監視のやり方

今までのjenkinsジョブ監視の問題点

JenkinsにDatadog plugin入れると自動的にjobのeventが流れてくるので、そのeventのタグを見て監視してました。10分間の間にresult:failureのタグがついたジョブの数が合計1より大きかったらslackに通知するという感じです。

f:id:masato47744:20180605224555p:plain

これの何が問題かというと、10分間たてば何もしなくてもrecoverdになってしまうということです。 なので、バッチがこけたことはわかるけど、recoverdが出てしまって勘違いしてそのままになってしまうこともありえます。

顧客が本当に欲しかったものを手に入れるには

Datadogにはcustom checkというmonitorがあってそれだとjenkinsのjobが失敗したらtrigger、成功したらrecoverという普通にやりたいことができるやつがあるのを発見しました。 あります。ただ、設定してみても、一向にNo Dataで全くひっかからない・・

で、ググりまくってたらこんなのをみっけた。要はjenkins.job.statusというタグをJenkinsのjobの設定画面で毎回書けってことだった。。defaultでいれておいてくれよという感じだがしょうがない😢

serverfault.com

f:id:masato47744:20180605224751p:plain

さらにちょっと注意

そして、さらにこのままだと、Jenkinsのジョブが実行されたブランチごととか実行されたnodeごとにalertが管理されるようになってしまいます。 どういうことかというと、あるAというブランチがBというslave nodeでジョブが実行されて失敗したあと、Cというslave nodeで成功した場合に、alertがrecoverdされないということです。

たいてい、どこのnodeで実行されたとかは関係ないのでjobが成功したらrecoverdされて欲しいわけです。 そこで、jobごとのグルーピングをするために、 Trigger a separate alert for each [ ] reporting your checkというのがこっそり用意されていて、 そこにjobと入れることでどこで実行されようとjob単位でalertしてくれるようになります。

f:id:masato47744:20180605224945p:plain

これで我々は顧客が本当に欲しかったものを手に入れることができました。

f:id:masato47744:20180605225323p:plain

Kubernetes上で動かしているRailsアプリでSentryを使うときにpod名などを表示するようにする

f:id:masato47744:20180509000519p:plain

コンテナからpod名を取得できるようにする

Sentryが実行時にpod名を取得するには、アプリケーションの実行時にpod名を何らかの方法で渡したり取得しにいく必要があります。 で、これをするための仕組みがkubernetesには用意されていてDownward APIというみたいです。

Downward APIはvolumeにマウントする方法と環境変数経由で渡す方法が用意されていて、今回の用途でいうと環境変数で取得できるようにするのが楽です。 やり方は単にk8sのmanifestのenvのところで書いてあげるだけでOKです。

ドキュメントはこちら Expose Pod Information to Containers Through Environment Variables

Deploymentで基本的に管理していると思うので、そこのenvのところでこんな感じで書けばOK。

      env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace

Ravenの設定時にtagを設定する

あとはこんな風に環境変数をtagsで指定してあげるだけでいけちゃいます。

Raven.configure do |config|
  config.dsn = **************************************
  config.tags = {
    pod_name: ENV['POD_NAME'],
    pod_namespace: ENV['POD_NAMESPACE'],
  }
end

様子

f:id:masato47744:20180508235642p:plain

副業先を探しています

副業やってみたいと思っていましたが、同僚が副業先を探しているツイートをしていてすごく強いと思ったのと1件だけインフラまわりのお手伝いで実績ができたので、ぼくもやっていこうと思いブログを書いてみました!

できること

  • 手運用でやってきたクラウド基盤(AWSやGCPなど)のインフラのコード化
  • DatadogやSentryを使った監視環境の整備
  • ECSやKubernetesなどコンテナを使った環境のデプロイ環境の整備
  • サーバーのコンテナ化支援
  • その他全体的な開発フローの改善など

経歴

  • iOSアプリ開発、JavaやPHP、Railsのサーバーアプリケーションの開発などをSIerで2009年〜2015年までやっていました
  • 2015年に転職後、英語学習サービスの立ち上げ時期からiOS開発、そしてScalaでのサーバーアプリケーションの開発をやっていました
  • 2017年から部署全体のAWSやGCPのオペレーションをするエンジニアとしてやってきました
  • 最近はもっぱらterraform書いたりAWSまわりやkubernetsまわりをやっているので、iOS開発歴が一番長かったですが今はもう最新のiOS開発技術にはついていけていません・・・
  • GitHubこのblogQiitaSpeakerDeckにある程度残しています

やりたいこと

  • サーバーのコンテナ化支援などの提案、教育、開発など
  • 開発環境やデプロイフロー、監視環境の整備など
  • インフラコスト軽減の提案、開発など

勤務条件

平日、土日の夜の子供が寝静まったあとの少し空いた時間で作業ができるかできないかという状況です。 子供を寝かしつけにジョインするとすぐに眠くなるし、土日も出かけたりして眠くなるので、週に4時間とれればいい方という感じです。

がっつり何かを開発をするというよりも、なかなか開発メンバーだけでは手が届かないけれどやっておきたいというようなスポット的な案件に向いていると思います。 締め切りはないが後回しになってなかなか解決できないような課題(例えば、開発環境の整理、監視環境の整備、デプロイフローの整備など)の解決することができるかと思います。 あとは、xxxがやりたいけどよく分からないみたいな教育目的のドキュメントやブログなどのアウトプットなどもできます。

連絡先

@_mponまたはqqw75pn9[at]gmail.comにご連絡ください。

インスパイア from

Google App EngineがECSやGKEの代わりになるようなコンテナを動かす環境として使えるのだろうか軽く調べた

きっかけ

ECSやGKEを使ってインフラ設定や運用をやってきた中、数年先はコンテナオーケストレーション層の管理はおそらくやらないでいいようになるだろうと思ってた。

ちょうど同じような考え方をこの前のJapan Container Daysで登壇してる方が話していて共感したんだけど、そのときに、AWSのFargateやAzureのAzure Container Instanceが例にあげられていて、ふむ、分かる。と思ってて、でも登壇者の方がGoogle App Engineはあえて外しますと話していて、気になった。 ブログ見返して見たら、それについては触れられていなかったけどそう言っていたのは覚えてるw

toris.io

「VM + コンテナ」は例えば Kubernetes とそれによって管理された VM のクラスターでコンテナを動かすことを、「VM レスコンテナ」は AWS Fargate や Azure Container Instances、Google App Engine FE(の、コンテナイメージをそのまま動かすやつ) などを指しています.

で、あと、そもそもGAE触ったことないのと、GAE/goみたいな事例もタイムラインとかで眺めたこともあったり、Dockerfileも使えるよみたいなのも見たことあったし、もしかして未来はもうきてるのか?って思ってたけど、登壇者の方が外した理由を知りたくてちょっとGAEまわりを現状のECSやGKEの代替となるかという観点で調べてみた

GAEにはStandard環境とFlexible環境がありcustomのDockerfileが使えるのはFlexible環境

試しにGAEやってみる

GCPプロジェクト作ってみてGAEやろうとしてみたら、まずtutorialで何かしら作らないとうんともすんともいわない。無駄にnode.jsのなんかhelloworldをデプロイさせられる。辛く厳しい道。cloudshellというやつで色々チュートリアルをこなさないといけない。マジかこれ。この時点でなんかもう全然期待していたものと違うのではという気になってきた。

f:id:masato47744:20180502124023p:plain

f:id:masato47744:20180502124702p:plain

ひえっ消すにはプロジェクトを消さないといけないらしい

f:id:masato47744:20180502130132p:plain

インスタンス?普通にsshできてしまうVMが立ち上がるみたい

f:id:masato47744:20180502130200p:plain

制限が厳しそう

app.yamlというGAE固有のものを書かないといけないし、portの強制など色々なんかECSやGKEみたいな自由な環境では全然なかった。 結局VMが立ち上がってるみたいだし。VMを意識したくないのに。

マイクロサービスみたいにサービス間通信をするには?

実際試した訳じゃないけど、色々記事をあさってあたりをつけた感じだと、以下のような感じかなと思った。

app.yamlでserviceを複数定義して、

stackoverflow.com

あとは、こんな感じのservice名.アプリ名.appspot.comというドメインで特別なGCP内のルーティングで速い感じで接続できるみたい。

Contracts, Addressing, and APIs for Microservices  |  App Engine standard environment for Python  |  Google Cloud

http://my-app.appspot.com
http://user-service.my-app.appspot.com

あとStandard環境の話だけど、microserivicesをGAEで実現するわかりやすい資料。要は結構どっぷり、GAE固有の概念や設定でやっていくしかなさそうだ。 Microservices Architecture on Google App Engine  |  App Engine standard environment for Python  |  Google Cloud

こちらの記事が分かりやすかったです、ありがとうございます。

qiita.com

これを見ると、networkの設定するってことは要はVMのインスタンスのネットワーク設定をしてるような雰囲気。コンテナが立ち上がると言っても1VMにつき1コンテナという感じなのかな。

app.yaml によるアプリの構成  |  Java の App Engine フレキシブル環境に関するドキュメント  |  Google Cloud

まとめ

GAE/FEをあえて外すと言った登壇者の意図が分かってきました。ちなみに、この記事はGAEをディスりたい訳じゃなく、ECSやGKEの代わりになるかという観点で調べたものなので、初めからGAEに合わせてアプリケーションを開発するという方向でやっていくという選択肢はとてもよいと思っています。VMレスコンテナみたいな文脈で使いたいから調べたけどなんか違うってだけで、GAEは素晴らしいと思います。 そして、GAEのことをまともに使っていない人間が調べた内容なので的が外れている可能性は非常にあるので、そのときはすみません

Japan Container Days v18.04参加してきました

Japan Container Days v18.12

見た内容

f:id:masato47744:20180420081943p:plain

サイバーエージェントにおけるプライベートコンテナ基盤AKEを支える技術

  • 2016年新卒入社すごい @amsy810 アドテクスタジオ
  • 30万リクエスト/sec ぐらいくる
  • Nvdia-Docker 知らない、GPUとか機械学習とかそういう人用のやつ
  • k8s v1.7でProduction Readyになったとのこと、意外と最近だ
  • nginx ingress controllerパフォーマンス出ない
  • AKEは2人で1年でちょこちょこ作ってきたみたい
  • Multi COE
    • マルチコンテナオーケストレーション、Docker Swarm、Kubernetesを使えるようにしてるみたい
  • OpenStack Integration
    • Keystone、Designate、Cinder、Heatみたいなツールがある、知らない世界
    • OpenStack Magnum、Rancher 2.0、Tectonic
    • baremetalじゃなくてVMで作った理由としては詰め込みすぎてマシンが死んだら影響範囲がでかい
  • ロードバランサーの話
  • Ingressの話
  • チューニング
    • Network tuning、カーネルチューニング、ハイパーバイザーチューニング
  • コンテナランタイム
    • docker、cri-o、containerd、rkt

マイクロサービスアプリケーションとしての機械学習

  • メルカリのひと Takuma Yamaguchi
  • 出品時の画像認識機能をリリース on k8s
  • 畳み込みニューラルネットワークは40年前から出ている、福島さんと言う方
  • 機械学習とかの人材、採用してて思うのは学生で既に実用レベルの人がいるらしいので人材も増えていくだろうとのこと
  • 機械学習だとソースコードと学習モデルの整合性というのがある
  • 学習環境というのがあって大きな計算リソースが必要
  • 機械学習エンジニアはモデルを書くのが得意でAPIやシステムっていうのあまりやらない
  • メルカリの画像認識機能の導入時の話
    • 1サーバで4reqs/sec、100milion/day
    • Workerでは常時25GBメモリ、起動10ふん
    • 機械学習モデルのファイルサイズは15GB
    • モデルは定期的に更新しGPUが必要
    • API(Gunicorn + Django) + Queue + WOrker (TensorFlow)
    • SRE: Dockerfileをください、あとはなんとかします
    • 強い
  • 出品時のカテゴリとか色とかの推測に使っている
    • Appleのキーボードをとったらそれのカテゴリが入っている
    • 色のフィルタリングって実は難しい
  • Mercari画像はS3にあるのとGPUのEC2が使いたいのでAWSで動いていてそれ以外はGCP
  • Queueにいれて、Worker(TensorFlow)が動く、Persistent Volumeから15GBのモデルを読み込んで動く
  • DeployはSpinnakerでやってるのでk8sを意識したことがない
  • こいうのが1週間後に出来上がっている
    • はーすごいね
  • 手動だとモデルとサーバー側のコードで不整合がでてきてしまったみたい、運用の限界があった
  • 機械学習のモデルは頻繁に更新するようだ、モデルの軽量化というのはすごい大変みたい
  • Googleでは1TBのモデルも動いている、なんかよくわからないけどめっちゃでかいんだということが分かった
    • コンテナ化したときにでかいファイル使うっていうのはめっちゃ難しいよね
  • はーほんと事例すごくてすごいっていう気持ちにさせられるけど小さなことからコツコツとやっていこう

Yahoo!JAPANのkubernets-as-a-serviceで開発するアプリケーション開発

  • Yahoo!ズバトク on k8s Masaya Ozawa コマースカンパニー 決済金融統括本部
  • openstackを使っていた
  • concurse ci使っている
  • デプロイ早くなった、まぁパッケージングがDockerになればそりゃ早い
  • 障害時、OpenstackのHypervisorダウンしたら、電話かかってきて、手動でサービスout/inする
    • 復旧作業がいらない
  • ログ調査はSplunkでログ検索やグラフ化、レポート作成
    • これはやらないといけないなー、Datadogでやれるはずなんだけどなかなか後回しになっている・・
  • Worker Nodeの数の最適化、共通機能の切り出し(アプリ的な意味で)、カナリア、feature toggle
    • feature toggleもやりたいなー、大きなbranchを作らないような開発手法にしていきたい

Yahoo!JAPANのKubernetes-as-a-service

  • ゼットラボ株式会社 @superbrothers
    • インフラ基盤技術の調査・研究開発のための子会社
    • 組織的な話だけど、こう言う風に子会社化すれば色々やりやすくなるんだろうなー
  • ゼロダウンタイムのkubernetsのアップグレード
    • nodeのrolling updateみたいなことを実装してる、kopsにも入ってたな、そういうかんじだろう
  • Ingress Controller
    • nghttpx-ingress-lb使ってる
    • ingressホストのDNS自動登録
      • これ作りたい、external-dnsだとwildcardみたいなことができない
  • Automate all the things
    • この画像ってこれだったんや
  • 分散システム基盤としてのKubernetes
  • CRDを作っててこれでclusterの定義とかしてる
  • カスタムコントローラの実装

Kubernets x Paas コンテナアプリケーションのNoOpsへの挑戦

  • Azrureてくのろじースペシャリスト @yokawasa Ventures- > yahoo -> microsoft
  • ReadinessProbeのReadReady、準備OKみたいな意味の方。読むのReadじゃなかった
  • Service Mesh
    • Istio、LINKERD、CONDUIT
      • サーキットブレーカー、スロットリングなど
  • CI/CD、Helmの話、モニタリングとログ収集の話

Custom MetricsとMultiple Metricsを使ってKubernetesのクラスタの強みを最大限活用する

Container Networking Deep dive

  • NTT 市原 裕史
  • CNM(Container Network Model)
  • Container Network Interface(CNI)
  • Linux bridge、veth(ブイイーサと読んでた)、iptables、openVswitch、VPP
  • k8s by kubeadm、docker、flannel、calico
  • flannel
    • vxlan
    • ip rでパケットのルーティング見る
    • veth -> flannel
    • ip nでMac address見る
    • fdb entryというのを見てどのNodeか分かるのでvxlanでカプセリングして投げる
    • workerが追加されるタイミングで1 route、1 arp entry、1 FDB entryが追加される
  • calico
    • BGPを用いてルーティング情報を伝搬可能
    • linux bridgeは使っていない
    • ipatablesでがんばっている
    • calicoの場合1pod 起動毎16ルール増加
    • vethのさきっぽってどういうことじゃい
  • IPIPパケット
    • IPパケットをIPパケットでくるむ、なんかもうよくわからんけどなんとなく分かった
    • トンネリング
  • パフォーマンス改善
    • オフロード機能を適切に設定する、VXLANハードウェアオフロード
    • トンネリングプロトコルを用いない
      • Flannelはhost-gwモード、Calico:ルータへのBGP伝搬
  • DPDKやXDPなどのパケット処理高速化技術を用いる
  • network policy(calico)
  • ipsetというlinuxのipを束ねることができる仕組みを使っている

Spinnakerを利用したKubernetesへの継続的デリバリ

Kubernetesのない世界 すべてがサーバーレスになる

  • Shingo Yoshida(Section9/Serverless),Yasuhiro HARA(SUPINF/Serverless)
  • Less Ops, More Code
    • これはそう、実現できればなんでもOK
  • AWS Fargate、Azure Container Instances、
    • Google App Engineはあえて外したとのこと <-どうして?
  • サーバーレスはイベントドリブン用でコンテナはwebのような待ち受けるサービスだよねと
  • マイクロサービスが絡み合う状態 death star
  • iopipe https://www.iopipe.com/
    • Lambdaをラップしてグローバル変数やLambdaの起動ステートといったメトリクスを収集して送るSaas
    • 課金が10倍ぐらいになっちゃう
  • Epsagon

Dockerだけじゃないコンテナruntime徹底比較!

  • Makoto Hasegawa(CyberAgent)
  • ちょっとブースを回っていた
  • rktはロケットと読む
  • CRI-O vs Containerd
  • Containerdの方がパフォーマンス、速度ともによい
  • runCってなに

    Docker(containerd)は、コンテナの管理などを行い、コンテナ生成・実行はrunCが行っている。

  • kata-runtime

  • Storage driver
    • なんじゃろうこれは
  • devicemapper、overlay、overlay2

Istioと共にマイクロサービスに立ち向かえ!

  • Aya Igarashi(Z Lab)
  • James Lewis & Martin Fowlerでバズり始めたとな。知らんかった martinfowler.com
  • Istioはギリシャ語で帆という意味
  • Envoy
    • API経由で設定変更が可能
  • Problem1: ServiceMeshを制御し切れない問題
    • /v1/だったらこっちみたいな柔軟なルーティングができる
    • カナリアリリース、リクエストのミラー
    • proxyはiptablesでいい感じにやるタイプのやつ
  • Problem2: 鍵と証明書の管理を自動化
    • どういう場面で困るんだろうか
    • アプリケーション間で相互通信するときにTLSで通信する
  • Problem3: システム全体像が把握できない
    • 可視化ツールとの連携
    • ZipKin、Prometheus、ServiceGraph、

ブースで聞いた話

  • Rancherの話
    • k8sラッパーかと思ってたけど違かった、が、2.0からはやっぱりラッパーとしてもできる
  • IBM Cloud
    • IBMのpublic cloudがあるというのを知った
    • オンプレ版の場合、メインフレームの上にk8sを構築するとかもできるらしい
  • 教育系の話、会社名を忘れてしまった・・
    • Dockerの教育とかをしてて引き合いは多いとのこと、主に開発寄りの会社が多い、SIerは1年後とか増えてくるのではないか

懇親会で聞いた話

  • デプロイどうしてますか?
    • githubのmergeタイミングでCIが起動してデプロイする。githubが起点になるのであまりCIの方を見に行かない
  • imageのタグ書き換えは?
    • sedでやってますね
    • Helmを入れるのは基盤側としてはまだ難しい、いろんなtemplateを作ることになったりif文増えたり、helmのtemplateの知識を覚えてもらわないといけないし
  • マイクロサービスの単位は?
    • 小さかった、各サービスごとにDBがある、じぶんたちがやってる単位と違かった
  • お話をいろいろ聞かせていただき感謝です。ありがとうございました!! > 懇親会でお話しした方たち

kopsを使ってAWS上にkubernetesを構築したときにIngress Controllerはどれにしようか悩んでいる

GKEで甘えてきました

www.mpon.me

今まではGKE使っててIngress ControllerもGLBCを使ってなんか勝手にやってくれてるなみたいな感じで、 k8sを使う側そんなに気にしてなかったんですが、 EKSもくるということでAWSでやるにはどうすればいいだろうということを考え始めたというのが経緯です。

とりあえずIngressとは?

An Ingress is a collection of rules that allow inbound connections to reach the cluster services.

とある通り、外部からのリクエストを各サービスに振り分けるルールを書くことができます。 なので、外部のクラウドプロバイダ上で立てる場合、Ingressを使った方が無駄なLBをたてずにすむので色々節約になります。

    internet
        |
   [ Ingress ]
   --|-----|--
   [ Services ]

IngressにはIngress Controllerが必要です

Ingress ControllerはIngressというobjectが登録されたときに実際につながるようにする処理をしてくれるcontrollerです。 Kubernetesはこういうcontrollerがいっぱいいて、他のobjectも同じようにobject登録すると、controllerがeventをpollingして見張っていて変化があれば何かをするというアーキテクチャになっています。素晴らしいですね。早く人間を置き換えてくれ

f:id:masato47744:20180410222545p:plain

Ingress Controllerどれにする??

ということで本題ですが、kopsでKubernetesを構築したときにはまだIngress Controllerはいません。要はなんだっていいんですが、とはいえ有名どころを使いたいしということでちょっと悩んでいます。

まずAWSでIngress Controllerやるならたいていこの3つのどれかかなということころまではググってなんとなく掴みました。

AWS使ってる身としてはALBやACMなどAWSに統合されていてほしい

AWSにはいつかEKSもくるだろうしある程度統合されているような仕組みでIngressをやりたい。 さらにHTTPで振り分けルールといえば当然ALBが思い浮かぶわけです。

ということで、alb-ingress-controllerkube-ingress-aws-controllerというAWSのALBを使ったIngress Controllerで検討することにしました。

alb-ingress-controller

qiita.com

をとても参考にさせてもらいました。ありがとうございます、ありがとうございます。

作り方などはこちらの記事や、walkthroughも公式で用意されててドキュメントも親切で特にはまることなく使うことができました。

Ingressにannotationsを指定することで、ALBを起動するsubnetの指定や、ACMの指定、security groupの指定、ALBのlistener ruleを使った振り分けなどやりたいことはほとんどできて、これが顧客が求めていたものだとなったんですが、ちょっと要件を満たせないものが・・

IngressのHealth check pathがALBごとにしか指定できない

alb-ingress-controllerだとIngressがServiceのNodePortに対してHealth checkをするんですが、そのときのパスがALBごとにしか設定できないのです。 GKEのGLBCだとreadiness probeでできたのでそういうもんだと思ってました・・

Health checks

Currently, all service backends must satisfy either of the following requirements to pass the HTTP(S) health checks sent to it from the GCE loadbalancer:

  • Respond with a 200 on '/'. The content does not matter.
  • Expose an arbitrary URL as a readiness probe on the pods backing the Service.

PRも出てるけど霊圧が感じられない・・

こちらのPRでServiceにannotationを書くことでhealth check pathを指定できる提案がされてますが、ちょっと進捗が芳しくなさそう・・

github.com

OSSに参加しようという気持ちもあるので貢献していこうとも思いましたが、そもそもIngressのhealthcheckを個別に切り替えようという考えが邪悪なのかなという気にもなってきました。

/を全て何も処理せず200を返すようにアプリケーションを調整するのは難しそうなので、普通に各アプリケーション側に/healthzみたいなエンドポイントを作ってもらって200を返すようにしてもらうっていうのも解決策なんですが、インフラ構築側からするとアプリケーションを開発するエンジニアにそんなこと強要したくないなという思いがあります。

kube-ingress-aws-controller

ということでもう一つの候補ですが、kube-ingress-aws-controllerです。

qiita.com

これもこちらのサイトを参考にさせてもらいました、ありがとうございます、ありがとうございます。

kube-ingress-aws-controllerもACMやsubnet指定、security group指定などALBとしての機能は問題なさそうです。 当初kube-ingress-aws-controllerはALBのlistener ruleを使わずに、別途Ingress controllerがさらに必要ということを知り、やめようかと思ったんですが動的にcontrollerで解決するにはAWSにとらわれ過ぎてはいけないのかもしれないという気持ちになってきました。

さらにkopsのaddonとしても紹介されてるし、これが正攻法なのかという気にも・・

さらにさらに、別途必要なIngress ControllerであるSkipper自体も高機能でよさそうという印象です。

kube-ingress-aws-controller + Skipper の組み合わせであれば、alb-ingress-controllerで問題だったIngressからのhealth checkは単にskipperに対して行うだけでOKです。 あとは、Skipperが各Serviceに(NodePortじゃなくてClusterIPでOK)プロキシしてくれます。

まとめ

ここまで色々考えてきましたが、こういうIngress Controllerをどうするかっていうことを考えてくと、もしかして最近勉強会とかでよく連呼されているIstioとかLinkerdとかにいきつくのではないかという気になってきました。ただ、まだそれらがなんなのかちゃんと分かってないので、追いつくにはもう少し時間が必要です。

p12ファイルを証明書と秘密鍵に分割する

p12ファイルって

PKCS#12 個人情報交換ファイルフォーマットというもの。証明書と秘密鍵をセットにできる。iOS開発とかやってるとよく出てくるやつです。

APNsの設定するのにp12を証明書と秘密鍵に分割したい

証明書を取り出すのはkeytoolというJDKに入ってるコマンドでできるみたいです。 秘密鍵はopensslコマンドで取り出せます。

これはsh直下にあるp12を全部証明書と秘密鍵に分割してbase64でstdoutするコードです。こんな感じでできます。ALIASっていうのをとってくるのが微妙にめんどくさい。

#!/bin/bash -e

for f in *.p12; do
  ALIAS=$(keytool -list -v -keystore /$f -storepass "" | grep "Alias" | awk -F: '{print $2;}' | sed -e 's/^\s//g')
  echo $f alias:$ALIAS
  rm -f temp.crt cer.pem key.pem

  keytool -exportcert -keystore /$f \
    -storetype PKCS12 \
    -storepass "" \
    -alias "$ALIAS" \
    -file temp.crt

  openssl x509 -in temp.crt -inform DER -out cer.pem -outform PEM
  echo "* $f base64 cer.pem"
  base64 -w 0 cer.pem && echo
  echo "* $f base64 key.pem"
  openssl pkcs12 -in $f -out key.pem -nodes -clcerts -password pass:""
  base64 -w 0 key.pem && echo
  echo
  echo
done

というようなことをもちろんDockerで実行できるようにしておく

Dockerfile

FROM java

COPY *.p12 /
COPY run.sh run.sh
RUN chmod +x run.sh

CMD ./run.sh

run.shの中身

IMAGE=pem-converter

build:
  docker build -t ${IMAGE} .

create:
  docker run -it ${IMAGE}

Terraformで変数を組み合わせることができるlocal valuesというのが使えるようになってた

Local Valuesがない世界😢

例えば、S3のバケットの名前をnameenvっていう変数を使って"${var.name}-${var.env}"ってしたいとする。

resource "aws_s3_bucket" "b" {
  bucket = "${var.name}-${var.env}"
}

んで、例えば、このbucketの名前を他で使いたいときは、"${aws_s3_bucket.b.id}"ってやればいいんだけど、たまに循環参照が起きて使えないことがある。

例: s3_bucketのpolicyを指定したい -> policyにはs3_bucketから名前をいれたい みたいな場合。鶏が先か卵が先かみたいな感じになっちゃう。🐔

resource "aws_s3_bucket" "b" {
  bucket = "${var.name}-${var.env}"
  policy = "${data.aws_iam_policy_document.s3_policy_cf_bucket.json}"
}

# ↑を作るには↓が必要で、↓を作るには↑が必要

data "aws_iam_policy_document" "p" {
  statement {
    actions   = ["s3:GetObject"]
    resources = ["arn:aws:s3:::${aws_s3_bucket.b.id}/*"]

    principals {
      type        = "AWS"
      identifiers = ["${aws_cloudfront_origin_access_identity.origin_access_identity.iam_arn}"]
    }
  }
}

そういうときは、この"${var.name}-${var.env}"をそこかしこで書かないといけない。これがbucket名を表してるってちょっとわかりにくいので一つのvariableにまとめたいと人は思います。が、variableはそれができないのです!!

# これはできない!!variableはinterpolationをサポートしてない
variable "bucket_name" {
  default = "${var.name}-${var.env}"
}

Local Valuesがある世界💯

www.terraform.io

Local Valuesは簡単にいうと色々組み合わせて好きな名前で値を定義しておけるものです。 こういうsyntaxで値を定義できます。

locals {
  bucket_name = "${var.name}-${var.env}"
}

使うときはこんな感じで、${local.bucket_name}とできる。

resource "aws_s3_bucket" "b" {
  bucket = "${local.bucket_name}"
  policy = "${data.aws_iam_policy_document.s3_policy_cf_bucket.json}"
}

data "aws_iam_policy_document" "s3_policy_cf_bucket" {
  statement {
    actions   = ["s3:GetObject"]
    resources = ["arn:aws:s3:::${local.bucket_name}/*"]

    principals {
      type        = "AWS"
      identifiers = ["${aws_cloudfront_origin_access_identity.origin_access_identity.iam_arn}"]
    }
  }
}

ECSでAWSコンソールに入って見てたような情報をCLIでインタラクティブに見れるやつを作りました

github.com

インタラクティブにECS ServiceにデプロイされてるImageの一覧が見たいとき

こんな感じで$ ecswalk servicesと打つと、jとkで選んだり、/を押してpecoみたいにinteractiveでfilteringして選ぶこともできます。

gif

AWSのコンソールで見たときの情報と、Dockerのimageのタグも出してるから何をデプロイしてるかぱっと確認するのに便利。 こんな感じでサービス名、TaskDefinitionのバージョン、DockerのImage、Tag、DesiredCountとRunning Countを出しています。

➜  ecswalk git:(master) ecswalk services
✔ prod-cluster
Name        TaskDefinition      Image   Tag         Desired Running
nginx       nginx:1             nginx   1.12-alpine     2   2
nginx-proxy nginx:1             nginx   1.12-alpine     2   2
traefik     traefik:1           traefik 1.5.4-alpine    3   3
web-alpine  apache-alpine:1     httpd   2-alpine        2   2
web-apache  apache:1            httpd   2.4.33          3   3

何気にService全件取得するのにもapiでページングがあって再帰的にとってきたり、取得したサービスの詳細をgoroutineで並列で一気にとってきたりとgolangのいい勉強になりました。

インタラクティブにTaskごとのコンテナインスタンスのIPとかの一覧が見たいとき

今度は$ ecswalk tasksを打てばさっきと同じ感じでcluster、serviceを選んで起動しているtask一覧を見ることができます。

gif

これで、画面に潜らなくてもどのコンテナインスタンスで動いてるかとか、Private IPアドレスとかcloudwatch logsのstream名を探すとき用のtask idが見つかります。

➜  ecswalk git:(master) ecswalk tasks
✔ prod-cluster
✔ traefik
TaskId                                  TaskDefinition  Status  EC2Instance     PrivateIp
2daaf40e-2fb7-4716-b89d-4a9569ab29c4    traefik:1   RUNNING i-09fc1243eeedcdaf5 10.0.0.250
40a83588-d460-42ee-808d-119894f21586    traefik:1   RUNNING i-024119cec8db2f0d4 10.0.0.109
71ca28c0-ce70-4229-9165-8ec85153e315    traefik:1   RUNNING i-024119cec8db2f0d4 10.0.0.109

インタラクティブじゃない方法で取得したい場合はget

cluster一覧、service一覧、task一覧が見れます

f:id:masato47744:20180326164610p:plain

インストール方法

goで書いているのでgo getコマンドで使えるようになります。

$ go get -u github.com/mpon/ecswalk

各platformごとのビルドとか依存関係の固定とかの仕組みはまだ分かってないので手付かずです。おいおい調べながらやっていくつもりです。

AWSのシークレット情報の渡し方について

ecswalkはgo-aws-sdk-v2(いつのまにかv2が出てた)を使っているので、環境変数やaws configure経由でシークレットが供給されます。 direnvやenvchainなど環境変数切り替えについてはいつものAWS_ACCESS_KEY_IDのような環境変数が使えるし、aws configureの設定も見に行ってくれます。

ただ、普段実務でAWSを使っている人は色々なAWSアカウントに対して操作することがあると思います。 そんなあなたは、コマンドを実行しているディレクトリ配下に、.ecswalk.yamlを置いて以下のように設定するだけでOKです。

profile: your-profile

cobraとviperを使って雛形をもとに作成しているので、こういう設定系もいい感じに作ることができました。

まとめ

goっぽいやり方まだまだ習得できてないのであれですが、今年はインフラ関連のツールやミドルウェアを作れるようになっていきたいと思っているので、まずはその第一歩です。goでcli作り始めるにあたって適当に自分で始めたあとにこの本を買いまいした。goっぽさとかgoの空気感とかざっくり全体感を把握するのにオススメです。

最後に参考にさせてもらった記事、ありがとうございます:bow:ありがとうございます:bow:

GOPATHどうしようかなと調べてて何気に今までghqも使ってこなかったのでこの機会に入れてみたけどgo関係なくさっさとghq入れてればよかった・・・

入門Kubernetesはk8sを触ったことがない人や機能を使いこなしてない人にオススメだと思った

k8s(頭のkとお尻のsを抜いてuberneteが8文字だから略してk8s、Internationalizationのi18nみたいな感じ)、の作者が基本的な機能を説明してくれる本です。正直公式documentと同じようなことが書いてある部分が多いっちゃ多いんですが、

  • 日本語で読める
  • ざっくりこんな機能があるんだー、こんなことができるんだーというのを知れる
  • Kubernetesオブジェクトがなんでこういう単位で分かれてるのかという考えが知れる
  • さっと読み終わる薄さがちょうどいい
  • k8sやってみてるけど、まだまだ機能を使いこなしてないなという人には、へぇーこんなことできるんだと知るきっかけになる
  • 例えばECSしか触ったことがない人が、えっこれってk8sならこれでできちゃうの!?みたいなことを知れる

といったあたりでオススメだと思いました。

個人的には特に、14章の実用的なアプリケーションのデプロイがとてもよいと思いました!!

Parse(あのParse.comのParseです。死んだと思ってましたがOSSになってたようです)と、Parseが使うmongoDB、blogのplatformのGhostと、Redisをk8s上でデプロイするというものです。 いい感じにk8sの機能を網羅することになるので、どんなことができるか雰囲気がわかりやすいです。k8s触ってみたいんですが題材は何がいいですかねーと言われたときはこれをオススメしようと思いました。

本を読んで初めて知ったこと

業務でもk8sを触ってはいますが、kubernetesのことを勉強し始めたのは1年ぐらい前なので、まだまだ知らないこともありました。

  • heptio-kubernetesの存在
  • kubectl logs -cでコンテナがえらべること
  • podは鯨の群れという意味だった(Dockerが鯨だからそこからきてる)
  • 宣言的設定が自己回復のキモであることを改めて認識した
  • serviceとかpodとかのことをkubernetesオブジェクトと呼ぶこと
  • Labelの仕組みは巨大な複雑なアプリケーションを動かしてきたGoogleの経験が生かされている
    1. どうせグルーピングする必要性が出てくる
    2. 階層化は破綻する
  • pod-template-hashDeploymentReplicaSetが重複しないようにするためにあった
  • readinessProbeが負荷が高まった場合につかえる
  • Horizontal Pod Autoscalerすごい、これがnativeに組み込まれてるのすごい
  • ReplicaSetDeploymentの歴史と関係性(自分は学び始めたときはすでにDeploymentがあった)
  • DaemonSetでさらに特定のノードグルーフにだてけ割り当てることができること
  • DaemonSetでrolling updateができること
  • Secret VolumetmpfsというRAMディスクに保存すること
  • Serviceにtype:ExternalNameがあること(外部のDNSレコードへAliasを貼るみたいなことができる)

誤植っぽいところ??

P192のという小見出しの部分がもしかしたら、Liveness Probeの間違いかもしれません。 小見出しには13.3.5 最後のポイント: Readiness Probeと書いてありますが本文やサンプルコードはLiveness Probeとなっています。

13.3.5 最後のポイント: Readiness Probe

...

MongoDBを構成するコンテナにLiveness Probeを追加することです。

...

まとめ

オススメです! ★★★★★

ap-northeast-1dでは起動できるインスタンスタイプが限定されている

spot instanceをリクエストするとbad-parametersと言われてしまう

c3.xlargeのインスタンスをone-timeのspot requestをしようと思っても以下のようなエラーが出て失敗する。

bad-parameters: Your Spot request failed due to bad parameters. Spot request cannot be fulfilled due to invalid availability zone.

普通にpricing historyにも金額出てるし、なんか設定が悪いのかなって小一時間悩んでしまった。

f:id:masato47744:20180321233747p:plain

こちらの記事に出会った

ありがとうございます。ありがとうございます。

support.serverworks.co.jp

でも、一次情報ってどこに書いてあるんだろう?そういうのってまとまってないものなのかな

AWS Route53を使ってDNS-01でLet's Encryptの証明書を取得する

DNS-01方式

HTTPを利用して認証する場合に、IP制限や社内のみの通信などの制限をしている環境においてはLet's Encrypt側からの通信が届かないので認証できません。そこでDNSのTXTレコードで認証するDNS-01のタイプがあります。

こちらのサイトの説明がわかりやすかったです。

Let's EncryptのDNS-01を使用して無料のSSL証明書をWebサーバなしで取得する -- ぺけみさお

公式のcertbotが対応した

先ほどの記事執筆時点では以下のように書いてありましたが、

現在、Let’s Encrypt公式のletsencryptコマンドは、DNSによる認証をサポートしていません。 GitHubでプルリクエストはされていますが、まだマージされていません。

現在はマージされ使えるようになっていました!!

Dockerでcertbotを動かして生成する

こういうとき便利、Docker

Dockerfileはこんな感じで

FROM certbot/certbot

RUN pip install certbot-dns-route53

COPY run.sh run.sh
RUN chmod +x run.sh

ENTRYPOINT ["/opt/certbot/run.sh"]

中身のrun.sh

#!/bin/sh

certbot certonly -n --agree-tos \
  --email <your email address> \
  --dns-route53 -d ${DOMAIN}

実行コマンドはこう

$ DOMAIN=<yourdomain.example.com>
$ docker run -e AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID \
  -e AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY \
  -e DOMAIN=$DOMAIN \
  -v $PWD:/etc/letsencrypt dns-certbot

これでカレントディレクトリ配下に$PWD/live/${DOMAIN}/private.pem$PWD/live/${DOMAIN}/fullchain.pemが生成されます。

Terraformのoutputで空になるかもしれないlistでindexで値を取得したいときのハック

true or falseで作られないかもしれないresourceの値を取得したい

例えばこのようにneed_instanceみたいなBooleanで作るか作らないかを決めるみたいなresourceがあったときに

variable "need_instance" {
  default = false
}
resource "aws_instance" "hoge" {
  count = "${var.need_instance  ? 1 : 0}"
  ...
}

outputで一つ目のinstance_idが欲しいというときに

output "instance_id" {
  value = "${aws_instance.hoge.id}"
}

need_instance = falseだとここでエラーになってしまう。

workaround力技

github.com

こうする

 "${element(concat(aws_instance.hoge.*.id, list("")), 0)}"
  • 後ろに空文字のlistを必ずくっつけてあげる
  • HCLは複雑なことをするための言語ではないので、こういうのはしょうがない
  • countでresourceを作るということは、0 or 1と決めたのはこっちなので関係ない。それすなわちlistのresourceとなるということ

Helmのchartのtemplateではまったところ

Helm とは

helm.sh

templateで書いてるresourceが作られなかった原因

re:Inventでコネクテッドカーのworkshop受けてきた

今流行りのコネクテッドカー

https://recruit-mp.qiita.com/_mpon/items/cc5a957f029c3902ddcb と同じようなworkshopというやつで、Deep Dive into the Connected Vehicle Reference Architectureというやつも受けた。 これも、名前につられてノコノコと参加してきたけど意味不明だったので、後日理解しなおしました。

こんな感じで、実際に自動車走らせてる奴のデータを使ってやってた

f:id:masato47744:20180125010158p:plain

実際にやったことの内容

  1. 位置情報をベースとして携帯に広告を打つ
  2. 速度超過があったら携帯に知らせる
  3. ジオフェンシングで領域を出たら携帯に知らせる

このあたりの処理を実際にLambdaのファンクションを登録したりして、動くことを確認していった。ちなみに、ぼくはうまくいかなくて携帯にとんでこなかったけども。

f:id:masato47744:20180125010215p:plain

実際のhands onページは生きてるみたいなので、やろうと思えばきっとできる気がします。でも、車がもう走ってないか・・

AWS GreenGrassという存在を知った

これが自動車側にいるやつです。GreenGrass Coreというのを動かして、デーモン的に自動車のどっかで動いてるはず。

最新 IoT デザインパターン AWS IoT と AWS Greengrass を用いた構築パターンが理解するのに分かりやすかった。

すごくざっくりいうと、まぁAWS GreenGrassはfluentdみたいなもんだなーって思った。自動車側の計測機器とGreenGrassがMQTTなりで通信して、GreenGrassが必要ならデータをバッファリングしてAWSサービスに投げる。多分バッファしないことももちろんできそう。

で、このGreenGrass Coreがデータを受け取ったときの処理自体をそこにLambdaをデプロイすることで処理がかけてしまうというのがポイント。普通だったら、どうやってやるんだろう、自動車一台一台にデプロイするの、こういう仕組みないと超大変ではという気がする。

AWS IoTがデータを受けとる

最初はこのAWS IoTというサービスが、自動車側にいるのかと思ってた。でも違う。 GreenGrassが投げてきたデータをAWS IoTが受ける。この部分はMQTTとかHTTPSとかwebsocketとかでやりとりする。 IoTルールエンジンというやつで、sqlライクにデータをフィルタリングして、他のawsのサービスに投げたりしてメール通知したり、さらに分析したりとか色々なことができるっていうルーター的な役割というのかな。 なんなら、これもfluentdっぽいっちゃfluentdっぽい。

f:id:masato47744:20180125010233p:plain

まとめ

まぁこういう感じでコネクテッドカーは作れるんだなというのが分かった