顧客が本当に欲しかったJenkinsのdatadog監視のやり方
今までのjenkinsジョブ監視の問題点
JenkinsにDatadog plugin入れると自動的にjobのeventが流れてくるので、そのeventのタグを見て監視してました。10分間
の間にresult:failure
のタグがついたジョブの数が合計1
より大きかったらslackに通知するという感じです。
これの何が問題かというと、10分間たてば何もしなくてもrecoverdになってしまうということです。 なので、バッチがこけたことはわかるけど、recoverdが出てしまって勘違いしてそのままになってしまうこともありえます。
顧客が本当に欲しかったものを手に入れるには
Datadogにはcustom check
というmonitorがあってそれだとjenkinsのjobが失敗したらtrigger、成功したらrecoverという普通にやりたいことができるやつがあるのを発見しました。
あります。ただ、設定してみても、一向にNo Data
で全くひっかからない・・
で、ググりまくってたらこんなのをみっけた。要はjenkins.job.status
というタグをJenkinsのjobの設定画面で毎回書けってことだった。。defaultでいれておいてくれよという感じだがしょうがない😢
さらにちょっと注意
そして、さらにこのままだと、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してくれるようになります。
これで我々は顧客が本当に欲しかったものを手に入れることができました。
Kubernetes上で動かしているRailsアプリでSentryを使うときにpod名などを表示するようにする
コンテナから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
様子
副業先を探しています
副業やってみたいと思っていましたが、同僚が副業先を探しているツイートをしていてすごく強いと思ったのと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やこのblog、Qiita、SpeakerDeckにある程度残しています
やりたいこと
- サーバーのコンテナ化支援などの提案、教育、開発など
- 開発環境やデプロイフロー、監視環境の整備など
- インフラコスト軽減の提案、開発など
勤務条件
平日、土日の夜の子供が寝静まったあとの少し空いた時間で作業ができるかできないかという状況です。 子供を寝かしつけにジョインするとすぐに眠くなるし、土日も出かけたりして眠くなるので、週に4時間とれればいい方という感じです。
がっつり何かを開発をするというよりも、なかなか開発メンバーだけでは手が届かないけれどやっておきたいというようなスポット的な案件に向いていると思います。 締め切りはないが後回しになってなかなか解決できないような課題(例えば、開発環境の整理、監視環境の整備、デプロイフローの整備など)の解決することができるかと思います。 あとは、xxxがやりたいけどよく分からないみたいな教育目的のドキュメントやブログなどのアウトプットなどもできます。
連絡先
@_mponまたはqqw75pn9[at]gmail.comにご連絡ください。
インスパイア from
副業先を探しています。 https://t.co/MTmPXnGHjo
— naoty (@naoty_k) 2018年2月8日
Google App EngineがECSやGKEの代わりになるようなコンテナを動かす環境として使えるのだろうか軽く調べた
きっかけ
ECSやGKEを使ってインフラ設定や運用をやってきた中、数年先はコンテナオーケストレーション層の管理はおそらくやらないでいいようになるだろうと思ってた。
ちょうど同じような考え方をこの前のJapan Container Daysで登壇してる方が話していて共感したんだけど、そのときに、AWSのFargateやAzureのAzure Container Instanceが例にあげられていて、ふむ、分かる。と思ってて、でも登壇者の方がGoogle App Engineはあえて外しますと話していて、気になった。 ブログ見返して見たら、それについては触れられていなかったけどそう言っていたのは覚えてるw
「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環境
- FEと略す。FEについてはこれ
- カスタムのDockerfileでnginxを動かす例
- ざっとこの記事で雰囲気をつかむ
試しにGAEやってみる
GCPプロジェクト作ってみてGAEやろうとしてみたら、まずtutorialで何かしら作らないとうんともすんともいわない。無駄にnode.jsのなんかhelloworldをデプロイさせられる。辛く厳しい道。cloudshellというやつで色々チュートリアルをこなさないといけない。マジかこれ。この時点でなんかもう全然期待していたものと違うのではという気になってきた。
ひえっ消すにはプロジェクトを消さないといけないらしい
インスタンス?普通にsshできてしまうVMが立ち上がるみたい
制限が厳しそう
app.yamlというGAE固有のものを書かないといけないし、portの強制など色々なんかECSやGKEみたいな自由な環境では全然なかった。 結局VMが立ち上がってるみたいだし。VMを意識したくないのに。
マイクロサービスみたいにサービス間通信をするには?
実際試した訳じゃないけど、色々記事をあさってあたりをつけた感じだと、以下のような感じかなと思った。
app.yamlでserviceを複数定義して、
あとは、こんな感じのservice名.アプリ名.appspot.comというドメインで特別なGCP内のルーティングで速い感じで接続できるみたい。
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
こちらの記事が分かりやすかったです、ありがとうございます。
これを見ると、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参加してきました
見た内容
サイバーエージェントにおけるプライベートコンテナ基盤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で作った理由としては詰め込みすぎてマシンが死んだら影響範囲がでかい
- ロードバランサーの話
type:LoadBalancer
はOctavia、MetalLB、CloudProvider Integrationを独自実装- GKE 互換のオンプレコンテナ基盤 AKE (Adtech Container Engine) アーキテクチャ完全公開!
- 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のモデルも動いている、なんかよくわからないけどめっちゃでかいんだということが分かった
- コンテナ化したときにでかいファイル使うっていうのはめっちゃ難しいよね
- はーほんと事例すごくてすごいっていう気持ちにさせられるけど小さなことからコツコツとやっていこう
機械学習の運用ってどんなことしてるのか雰囲気が分かってとても参考になりました #containerdaysjp
— オオシママサト (@_mpon) 2018年4月19日
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の
Read
はReady
、準備OKみたいな意味の方。読むのReadじゃなかった
あーReadinessProbeのReadって Readyの方だったのか、ずっと読むのReadだとおもてた・・ #containerdaysjp
— オオシママサト (@_mpon) 2018年4月19日
- k8sの基本的な機能の紹介の発表だ
- Paas、Serverlessの話かな?
- Open Service Broker APIの話だ
- うーむ、まぁterraformでいいかという気にもなってしまう
- Managed Kubernetesの話、AKS
- サーバレスコンテナサービス、よい、Azureにもあるんだ、これからもっといっぱい出てきそう
- Azure Container Instances 起動は数秒以内
- virtual kubelet GitHub - virtual-kubelet/virtual-kubelet: Virtual Kubelet is an open source Kubernetes kubelet implementation.
ACI(Azure Container Instances)でクラスタを意識せずに立ち上げる、virtual kubeletがいることでk8sのnodeのように見える。なるほど、EKS でFargateって言ってたのも、きっとこういうことか #containerdaysjp
— オオシママサト (@_mpon) 2018年4月19日
- Service Mesh
- Istio、LINKERD、CONDUIT
- サーキットブレーカー、スロットリングなど
- Istio、LINKERD、CONDUIT
- CI/CD、Helmの話、モニタリングとログ収集の話
Custom MetricsとMultiple Metricsを使ってKubernetesのクラスタの強みを最大限活用する
- Kodai Sakabe(Wantedly)
- HPA(Horizontal Pod Auto Scalers)の話
- 124 services, 80+nodes, 3k+ containers
- 閾値ではなく割合でモニタリングする
- resouce metrics
- Heapsterがとってくる標準のやつ
- custom metrics
- google stackdriverならとれる
- AWSユーザーはPrometheusとCustom Metrics API Serverをインストールするみたい
- kopsでやってるんだ
- custom metricsとかはHPAをやりたいときに使えることがあるみたい
- GitHub - kubernetes/kube-state-metrics: Add-on agent to generate and expose cluster-level metrics.とはまた違うのか
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を束ねることができる仕組みを使っている
難しくて知らないことばっかりだったけど、ネットワークの話おもしろかった #containerdaysjp
— オオシママサト (@_mpon) 2018年4月19日
Spinnakerを利用したKubernetesへの継続的デリバリ
- Takashi Mizouchi(AP Communications)
- https://www.slideshare.net/devsumi/15blspinnaker
- spinnakerはヨットの帆という意味
- どっちかというと初学者向け、こういうtweetされてた情報を知りたかった
あんまり触れられてない気がするけど、Spinnaker は最低メモリ要件が地味に大きい (8 GB+、Bakery 含まず) 。気軽に試そうとするとちょっとびっくりするかもしれない。 #containerdaysjp
— チェシャ猫@技術書典4 き-33 (@y_taka_23) 2018年4月19日
Kubernetesのない世界 すべてがサーバーレスになる
- Shingo Yoshida(Section9/Serverless),Yasuhiro HARA(SUPINF/Serverless)
- Less Ops, More Code
- これはそう、実現できればなんでもOK
Less Ops, More Code、これはほんとそう、これを目指してる #containerdaysjp
— オオシママサト (@_mpon) 2018年4月19日
- AWS Fargate、Azure Container Instances、
- Google App Engineはあえて外したとのこと <-どうして?
- サーバーレスはイベントドリブン用でコンテナはwebのような待ち受けるサービスだよねと
- マイクロサービスが絡み合う状態 death star
- iopipe https://www.iopipe.com/
- Lambdaをラップしてグローバル変数やLambdaの起動ステートといったメトリクスを収集して送るSaas
- 課金が10倍ぐらいになっちゃう
- Epsagon
- cloud watch logsに送りつけたものをいい感じに見せるやつ
- いいかも https://www.epsagon.com/
Fargate高いという問題、めっちゃ安くしちゃえばk8sどうこうじゃなく簡単にシェア獲得できるのでは #containerdaysjp
— オオシママサト (@_mpon) 2018年4月19日
Dockerだけじゃないコンテナruntime徹底比較!
- Makoto Hasegawa(CyberAgent)
- ちょっとブースを回っていた
- rktはロケットと読む
CRI-O
vsContainerd
- Containerdの方がパフォーマンス、速度ともによい
runC
ってなにDocker(containerd)は、コンテナの管理などを行い、コンテナ生成・実行はrunCが行っている。
kata-runtime
- Storage driver
- なんじゃろうこれは
- devicemapper、overlay、overlay2
Dockerじゃなんでダメなのか?が分からないので分からない・・ 見えているものが違うんだろうな #containerdaysjp
— オオシママサト (@_mpon) 2018年4月19日
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、
システムの全体像が把握できない、分かる #containerdaysjp
— オオシママサト (@_mpon) 2018年4月19日
ブースで聞いた話
- 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で甘えてきました
今までは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して見張っていて変化があれば何かをするというアーキテクチャになっています。素晴らしいですね。早く人間を置き換えてくれ
Ingress Controllerどれにする??
ということで本題ですが、kopsでKubernetesを構築したときにはまだIngress Controllerはいません。要はなんだっていいんですが、とはいえ有名どころを使いたいしということでちょっと悩んでいます。
まずAWSでIngress Controllerやるならたいていこの3つのどれかかなということころまではググってなんとなく掴みました。
- coreos/alb-ingress-controller
- zalando-incubator/kube-ingress-aws-controller
- kubernetes/ingress-nginx
AWS使ってる身としてはALBやACMなどAWSに統合されていてほしい
AWSにはいつかEKSもくるだろうしある程度統合されているような仕組みでIngressをやりたい。 さらにHTTPで振り分けルールといえば当然ALBが思い浮かぶわけです。
ということで、alb-ingress-controller
かkube-ingress-aws-controller
というAWSのALBを使ったIngress Controllerで検討することにしました。
alb-ingress-controller
をとても参考にさせてもらいました。ありがとうございます、ありがとうございます。
作り方などはこちらの記事や、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を指定できる提案がされてますが、ちょっと進捗が芳しくなさそう・・
OSSに参加しようという気持ちもあるので貢献していこうとも思いましたが、そもそもIngressのhealthcheckを個別に切り替えようという考えが邪悪なのかなという気にもなってきました。
/
を全て何も処理せず200を返すようにアプリケーションを調整するのは難しそうなので、普通に各アプリケーション側に/healthz
みたいなエンドポイントを作ってもらって200を返すようにしてもらうっていうのも解決策なんですが、インフラ構築側からするとアプリケーションを開発するエンジニアにそんなこと強要したくないなという思いがあります。
kube-ingress-aws-controller
ということでもう一つの候補ですが、kube-ingress-aws-controller
です。
これもこちらのサイトを参考にさせてもらいました、ありがとうございます、ありがとうございます。
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のバケットの名前をname
とenv
っていう変数を使って"${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がある世界💯
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でインタラクティブに見れるやつを作りました
インタラクティブにECS ServiceにデプロイされてるImageの一覧が見たいとき
こんな感じで$ ecswalk services
と打つと、jとkで選んだり、/
を押してpecoみたいにinteractiveでfilteringして選ぶこともできます。
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一覧を見ることができます。
これで、画面に潜らなくてもどのコンテナインスタンスで動いてるかとか、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一覧が見れます
インストール方法
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の経験が生かされている- どうせグルーピングする必要性が出てくる
- 階層化は破綻する
pod-template-hash
はDeployment
でReplicaSet
が重複しないようにするためにあったreadinessProbe
が負荷が高まった場合につかえるHorizontal Pod Autoscaler
すごい、これがnativeに組み込まれてるのすごいReplicaSet
とDeployment
の歴史と関係性(自分は学び始めたときはすでにDeploymentがあった)DaemonSet
でさらに特定のノードグルーフにだてけ割り当てることができることDaemonSet
でrolling updateができることSecret Volume
はtmpfs
という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にも金額出てるし、なんか設定が悪いのかなって小一時間悩んでしまった。
こちらの記事に出会った
ありがとうございます。ありがとうございます。
でも、一次情報ってどこに書いてあるんだろう?そういうのってまとまってないものなのかな
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力技
こうする
"${element(concat(aws_instance.hoge.*.id, list("")), 0)}"
- 後ろに空文字のlistを必ずくっつけてあげる
- HCLは複雑なことをするための言語ではないので、こういうのはしょうがない
- countでresourceを作るということは、0 or 1と決めたのはこっちなので関係ない。それすなわちlistのresourceとなるということ
Helmのchartのtemplateではまったところ
Helm とは
templateで書いてるresourceが作られなかった原因
{{- end -}}
の-
がなんなのかよくわからなかった- trimの話だった
- golangのtemplateの話
range
を使った時にresourceが一つしか作られない現象---
で区切らないといけない
re:Inventでコネクテッドカーのworkshop受けてきた
今流行りのコネクテッドカー
https://recruit-mp.qiita.com/_mpon/items/cc5a957f029c3902ddcb と同じようなworkshopというやつで、Deep Dive into the Connected Vehicle Reference Architecture
というやつも受けた。
これも、名前につられてノコノコと参加してきたけど意味不明だったので、後日理解しなおしました。
こんな感じで、実際に自動車走らせてる奴のデータを使ってやってた
実際にやったことの内容
- 位置情報をベースとして携帯に広告を打つ
- 速度超過があったら携帯に知らせる
- ジオフェンシングで領域を出たら携帯に知らせる
このあたりの処理を実際にLambdaのファンクションを登録したりして、動くことを確認していった。ちなみに、ぼくはうまくいかなくて携帯にとんでこなかったけども。
実際の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っぽい。
まとめ
まぁこういう感じでコネクテッドカーは作れるんだなというのが分かった