Look back 2018 (2018年の振り返り)

Yuki Nishiwaki
ukinau
Published in
27 min readDec 31, 2018

こういう記事は書いてこなかったのですが、今後のキャリアも考えて、
この1年どういうことに取り組んで来たのか少し振り返ります。

2017年12月に新しい会社に入って、
2018年は、OpenStack含むPrivate Cloudの開発/運用に従事していました。

まず、印象に残っている仕事/技術的な活動を時系列順に羅列してみます。

上半期

OpenStack

  • Neutron ML2 Plugin Driver/Custom Agent 開発
  • parameterized moduleへのパッチ貢献
  • nova/libvirtのblock migrate失敗する問題解析
  • dhcp entryのreloadができない (dnsmasq)問題解析
  • OSSのPatchベースカスタマイゼーション
  • 対外発表 (OpenStack Summit Vancouver 2018)

Managed Kubernetes プロジェクト

  • Managed Kubernetes プロジェクトの立ち上げ
  • Rancherのコードリーディング
  • Kubernetes管理OSSの評価

Private

  • 30日OS自作入門読破

下半期

OpenStack

  • OpenStack NeutronにUpstream Contribute (タイミング起因のバグ)

Managed Kubernetes プロジェクト

  • Rancher 2.0 解析資料の公開/発表
  • Rancher Upstream Contribute (バグフィクス)
  • Docker Machine Upstream Contribute (バグフィクス)
  • Rancher Internal State Monitoring機能のContribution
  • Nginx Ingress Controllerのバグフィクス
  • 一部のノードでContainer Networkが正しく構築されない問題解析
  • Periodic Backupの実装 (coreos/etcd-operator)
  • 対外発表 (Alternative Architecture DOJO Offline #1)
  • 対外発表 (Japan Container Days Keynote)
  • 対外発表 (Japan Container Days RancherLabスポンサーセッション)
  • 対外発表 (Rancher JP Meetup in Seattle)
  • 対外発表 (LINE TechPulse Taiwan 2018)

振り返り

今年は、新しい会社に入り、最初の3ヶ月はとにかくアウトプットを出すことに必死でした。結果として、様々なプロジェクトに参加させていただき幅広い技術に取り組ませていただきました。

上半期は、OpenStackを中心に取り組み、Neutron Plugin開発やOpenStackが依存しているMiddlewareのトラブルシューティングを中心に取り組み。

下半期は、Managed Kubernetes サービス開発プロジェクトの立ち上げ、チームビルディング、人集めから実際の開発まで実施し、サービスの開発に必要な様々なプロセスを経験させていただきました。

この1年は、仕事がとても楽しく、仕事を中心に生活をしてきました。
結果として、通っていたジムもやめ、食事の時間も不規則になり、大分不健康な生活を送ってしまい、体重が15kgぐらい増えてしまいました。

来年

来年は、仕事も引き続き頑張っていきますが、もう少し健康を意識して過ごしたいと思います。

ということで、来年は仕事を頑張りながらも、下記を達成できるように頑張りたいと思います。

  • ジムに通い直す
  • 2018年に太ってしまった15kgの減量
  • 本業とは直接関係のない技術本を5冊以上読む
  • 海外カンファレンスに1回以上登壇する
  • ブログを月に1回は最低でも更新する

ここから先、
各月のアウトプットについて、もう少し詳細にだらだら振り返ってみます

基本的には、自身でいつか振り返るときのために書くメモみたいなものなので暇な人だけ見てください。

2018年1月

OpenStack運用開発の現場に配属されてから1ヶ月になります
チームは、ちょうど新しいネットワークアーキテクチャを採用したクラスタ構築真っ只中でした。

その中で、私が一番最初に担当した業務は、「L3オンリーなデータセンターネットワークをOpenStack Neutronでどのように実現するかを検討/開発する」ということでした。

Neutron ML2 Plugin Driver/Custom Agent 開発

導入予定のアーキテクチャは、メリットだけでなくデメリットも大きかったため、一般的に様々な会社が導入できるものではありません。
そのため、OpenStack Neutronの既存実装では、実現が難しく、Neutronのいくつかの実装を私たちの独自の実装に置き換える必要がありました。
実装の詳細は、OpenStack Summit 2018 Vancouverの発表とブログ記事を見ていただけたらと思います

この業務の難しいポイントは、大きく3つあります。

  1. Neutronの提供している機能と実装の概要をきちんと理解しないと、どのプロセスをどのように置き/書き換えるべきなのかが分からない
  2. ポイント1を得るためには、Neutronの多くの部分の実装を把握するためにコードを読む必要がある
  3. 新しいアーキテクチャ上のエンティティとNeutronの既存エンティティをどのようにマッピングすべきかを自身で考える必要がある

これらのポイントは、Neutronというソフトウェアの”開発者”であれば、当然実施できて当たり前ですが、運用がメインのチームで他にもたくさんのコンポーネント/ソフトウェアを同時に面倒を見る必要がある立場からするとなかなか難易度の高いチャレンジングなタスクだったのではないかと思います。

(Private) 30日OS自作入門読破

この頃は、まだ余裕があったので、年末年始などを使って前から読もうと思ってた「30日でできる!OS自作入門」を1月末ぐらいに読破しました。

タスクスケジューラの実装、カーネルモードとユーザモードの切り替えの実装、システムコールっぽい仕組みの実装、メモリ管理の実装など面白い内容が1冊に凝縮されたとてもいい本でした。

2018年2月

独自AgentとML2 Plugin Driver開発は、1月に完成の目処はついていたので、2月はテストを書いたり、クオリティチェックを中心に取り組んでいました。

parameterized moduleへのパッチ貢献

私は、PythonでUnitテストを書くときに、複数パラメータの試験を1つの関数で実現するために、https://github.com/wolever/parameterized をよく使います。

独自Agentのテストもparameterizedを使っていたのですが、 mock モジュールのpatch class デコレータと併用するときちんと動作しないという不具合がありました。

この問題は、@mock.patch(“os.listdir”)をclassに当て、@parameterized.expand([[1,2], [3,4], [5,6]])を該当classのfunctionに当てると、”os.listdir”を置き換えるMagicMockが3個(本来は1個)も作成されfunctionに渡されるという大変興味深い問題でした。

この問題は、mock.patchとparameterizedの両方の仕様が密接に絡んでいるため、取り組むには、parameterizedの実装を理解するだけではなく、mock.patchがどのようにobjectを差し替えているのかも理解する必要があります。実際に動作を記事にまとめているので興味ある方はご確認ください

Nova/libvirtのblock migrate失敗する問題

独自Agentを導入した環境で、きちんとLive Migrationできるかどうかを確認していた時に、一定の確率でVMのblock migration に失敗することがありました。

この問題、NovaからはLive Migrationが正常に終了しているように見えるけど Migration先でVMがPauseから復帰せずずっとスタックしてしまうというとても厄介なものでした。
止まって欲しくないVMだからLive Migrationするのに、実行したら止まってしまうよというとてもとても恐ろしいバグです。

VMの全てのOperationは、OpenStack Novaのインターフェースを通して実施しているので、まずはNovaの該当コードとNova側で何が起きているのかを把握する必要があります。

Novaに関しては、過去に記事(https://medium.com/uckey/first-step-for-reading-openstack-nova-source-code-280758ff77c9)をまとめている通り、全体像については把握できているので、何か問題が起きた時にざっくりどこらへんのコードを読めばいいかはわかっていました。

コードを読んだ結果、特定の条件下でlibvirtのPython API bindingの特定の関数呼び出しが終了しないことが判明しました。

libvirtの実装をもう少し読み進め、全体像を掴みつつ、ロギングポイントを大量に突っ込みながら問題を特定していくと、livbirtがqemuのイベントが起きた際にビジネスロジックを実施するオペレーションスレッドがビジネスロジック評価中にVMロックをリリースしてしまい、qemuのイベントを取りこぼし、ビジネスロジック評価後にオペレーションスレッドがすでに取りこぼしているイベントを待ち続けるため、特定の関数呼び出しが終了しないということが分かりました。

こちらも記事を書いているので、詳細は下記を見ていただければと思います。https://medium.com/uckey/dont-use-libvirt-3-2-0-which-is-latest-in-official-centos-7-updates-repository-211792f9b5bf

この問題は、私が発見した時には、すでにパッチは出ていたのですが、利用しているバージョンでは該当パッチはまだ入っていませんでした。
また、この問題は、どうやら開発者の方が自分たちで発見し、そのまま直しているようなので利用者/オペレータによるバグレポートなども存在しなかったため、検索エンジンを使って手がかりを探すのも困難でした。

そのため、自分たちで、きちんと問題を特定し、解決するというプロセスの大事さを改めて実感する問題となりました。

2018年3月

3月は、独自Agentもリリースし、特定の大きいタスクというよりは日々の運用業務を中心に取り組んでいました。いくつかのトラブルシューティングの中で今でも覚えてる印象深いものを1つ取り上げてみます

dhcp entryのreloadができない (dnsmasq)

dnsmasqは、OpenStackやその他の様々なプロジェクトで採用されているdhcpサーバ兼dnsサーバです。

私たちが開発しているNeutronの独自Agentもdnsmasqをdhcpサーバとして利用しています。このdnsmasqですが、私たちの利用している機能にとても致命的なバグがありました。

私たちの環境では、dnsmasqのdhcp-hostdirオプションという特定のディレクトリ配下の設定ファイルを全て監視させ、変更があったら自動的にリロードしてくれるような機能を使って、VMの作成/削除に伴ってdhcpエントリの更新をしています。

しかし、運用中に一度過去に使用したIPに対して再度別のMACに対してIPの払い出しができないという現象が起こり、リロードに失敗していることが分かりました。(SIGHUPによる設定ファイルリロードをするも状況は変わらず)

ここで、コードを読み進めていくとdhcp-hostsオプションを指定しないとreloadはされないようになっていることが分かりました(https://github.com/imp/dnsmasq/blob/master/src/option.c#L4464)

最新バージョンでは、すでに修正されているのですが、我々の利用しているバージョンでは、まだ修正されていなかったので、ワークアラウンドとしてdhcp-hostsオプションにdummy fileを合わせて指定することで解決しています

2018年4月

入社から5ヶ月。「組織/チームの状況」、「Private Cloudの構成/設定」などの業務知識がちょうど身についてきた頃になります。これぐらいの時期に、組織を含め運用の課題なども少しずつ見えてきました。

チームの課題整理

自身の環境/業務理解の整理という意味も込めて、この時期ぐらいに一度課題を整理しました。

Private Cloudのリソース数、コンポーネントの種類、チームメンバーという3つの観点全てで、スケールが日々大きくなってきていることから、いくつか取り組まねばならない大きな課題が見えてきました。

  • ドキュメンティング
  • チーム内での課題共有の仕組みづくり
  • システムスケーラビリティの計測方法の確立とチューニング
  • マイクロサービスの運用性の向上 (日々増えるプロセスの可視化、プロセス内部ステートの可視化、サービス間通信の可視化など)
  • 複数のサービスで冗長な機能/実装の共通化
  • OSSに対する運用のしやすいカスタマイゼーション

やるべきことはたくさん見えてきたものの、リソースは限られているので、少しずつ進めているというのが現状です。

来年は、この辺りをきちんと取り組み、成果をだし、対外的にも発表していきたいと思います。

OSSのPatchベースカスタマイゼーション

見えてきた課題の1つに、Forkベースカスタマイゼーションというものがあります。弊社のOpenStackは、Keystone, Nova, Neutronなどコアなコンポーネントに対して、いくつかのカスタマイゼーションを実施しています。

この方法では、特定のバージョン(Commit)をForkしてその上にCommitを積み重ねる形でカスタマイゼーションを実施しています。

しかし、カスタマイゼーションに対する変更もコミットとして管理されるため、下記のような課題がありました。

  • Upstreamに対してどのような変更を行なっているのか、簡単に知ることができない
  • Upstreamに対して変更を提案するときに、別途パッチファイルを作成する必要がある
  • カスタマイゼーションの一部を取り除くの際、関連Commitを全て探しRevertしないといけない

これらの運用の課題を解決するため、ForkベースではなくPatchベースで変更を管理するような提案/実装を実施しました。

Patchベースでは、Upstreamのコードをベースに、意味のある変更単位で1つのPatchとして変更を管理します。

この管理方法では、カスタマイゼーションに対する変更は1つのPatchファイルを再び変更することで実現するため、変更時の手間は増えるもののカスタマイゼーション自身の管理のしやすさは、格段と改善されます。

この方法は、OpenStackだけでなく他のOSSでも利用していて、他のプロジェクトで利用しているRancherもこの方法でカスタマイゼーションを管理しています

RancherのPatchベースカスタマイゼーション

2018年5月

この辺りで、Private CloudでManagedなKubernetesを出して欲しいという要望が強くなり、プロジェクトを立ち上げることになりました。

また、3月ごろまで取り組んでいたNeutron Plugin開発について対外的に発表する機会をいただき新しい会社に入ってからの1つの区切りとなりました。

OpenStack Summit Vancouver 2018の登壇

3月ごろまで取り組んでいた、「L3オンリーなデータセンターネットワークをOpenStack Neutronでどのように実現するかを検討/開発する」に関する発表を実施してきました。

Managed Kubernetes プロジェクトの立ち上げ

もともと1年以上マイクロサービスアーキテクチャを採用した商用Webシステムの開発に携わっていたこともあり、Docker、コンテナなどには割と触れることが多かったものの、Kubernetesについては、まだまだ入門者でした。

また、もう一人のメンバーもKubernetesの経験はなかったため、「複数のKubernetesを管理するための仕組みづくり」は、チームのスキルセットとやるべきことのギャップがとても大きかったと言えるでしょう。

そのような状況だったので、フルスクラッチで開発するというよりは、OSSをベースに自分たちの知識も溜めていきながら、なるべく早くリリースをするという方向性に舵を切りました。

また、リリース速度という観点以外にも、属人化を防ぎやすいという観点とたくさんの有識者の知恵を借りることができるという点も我々がOSSを利用することにした大きな理由です。

たまに要件が少しでも合わないOSSを利用することに、強く反対しソフトウェアを完全に内製したがる人がいますが、内製化は時に闇を産み出してまうこともあります。

流動性の高い数人のチームで、フルスクラッチで書いたシステムは、要件が複雑であれば複雑であるほどメンテナンスが難しいものになってしまうことが多いです。

メンテナンスをよりしやすくすために、下記のようなメトリクス値を上げることが望ましいですが、

  • 該当ソフトウェアのドキュメント量
  • 該当ソフトウェアのインターフェースを利用した運用ツールの量
  • 該当ソフトウェアの実装を理解している人の人数

上記のメトリクスは、多くの場合OSSの方が多くなることが多いです。

もちろん、メンバー固定でそこそこの人数がいる組織であれば、ある程度属人化ならぬ属チーム化しても問題ないのかもしれませんが、少人数で他のタスクと掛け持ちをしているようなチーム構成の場合、Day2以降の運用開発に課題を抱えることが多いので、多少OSSが要件に見合わなくても、内製開発ではなく、OSSをベースとする方が良いというのが私の意見です。

2018年6月

OpenStackについては、引き続き運用メインの業務で日々のトラブルシューティングやドキュメント化の作業が中心でしたが、稼働の半分以上をManaged Kubernetes開発側に費やし始めてきた頃です。

Kubernetes管理OSSの評価

OSSをベースに開発を進めることは決めたものの、具体的なソフトウェアはまだ決まっていなかったため、この頃、下記の2つを検証していました。

  • OpenStack Magnum
  • Rancher 2.X

OpenStack Magnumは開発コミュニティの盛り上がりと方向性が合わなかったため採用を見送り、Rancher 2.Xを採用することにしました。

採用背景は、こちらをみてもらえるといいと思います。https://www.slideshare.net/linecorp/rancher20-managed-kubernetes-service

Rancherのコードリーディング

Rancherの採用を決めてから、Rancherについて学ぶことにしました。

しかし、当時の公開情報はRancherの実装について細かく触れているものがなく、ソースコード以外手がかりがないという状況でした。

そのため6月ぐらいからソースコードを読み進め、7月半ばぐらいを目安にRancherの実装の詳細をドキュメントにまとめました

2018年7月

Managed Kubernetes開発プロジェクトが本格的に走り始め、7月はRancherの解析をメインで進めてました。

Rancher 2.0 Deep Diveに関する発表の実施

7月に、6月から実施しているコードリーディングの結果/動作に関してまとめたレポートを発表/公開しました。

2018年8月

Managed Kubernetes開発の傍で、Private Cloud(OpenStack)の障害対応は引き続き実施していたのですが、この頃、特定のタイミングで生じるOpenStack Neutronのバグに出くわしてしまいました。

OpenStack NeutronにUpstream Contribute (タイミング起因のバグ)

問題の詳細には、ここでは触れませんが、この問題はエラーログが出なかったので、特定にとても苦労しました。

エラーログが出ないため、瞬時に原因を特定することができないので、debugログをベースにコードの評価順序を確かめながら、特定のタイミングで特定の関数が評価されないことを突き止め、原因を特定しました

2018年9月

このあたりで、Rancherのソースコードが一通り読み終わり、RancherをコントロールするためのAPI Serverの開発やRancher自身のバグ修正などに取り組みました。

Rancher Upstream Contribute (バグフィクス)

Docker Machine Upstream Contribute (バグフィクス)

この時期はまだ、バグの修正が中心で機能追加などはできていませんでしたが、バグの修正を通してコードの全体像がきちんと理解できていることを確認できました。

2018年10月

10月頃からある程度本格的にRancherを使い始め、トラブルシューティングをする機会が増えることになります。

Rancher Internal State Monitoring機能のContribution

トラブルシューティングをする機会は増えるものの、Rancherはたくさんの機能が実装されているため、問題が起きた際に、Rancherの内部で今何が起きているのかを把握することは容易ではありません。

トラブルシューティングを少しでも楽にするため、また障害の前兆をきちんと検知するために、Rancherの内部ステートをPrometheusで収集可能な形式で収集できるようにする変更を提案し、Upstreamに取り込まれました。

この変更により、実際にUpstreamでまだ認識されていないバグの発見と修正を実施しています。

Rancher Upstream Contribute (バグフィクス)

Internal State Monitoring以外にも、いくつかのバグフィクスも実施しています。

2018年11月

API Server開発も落ち着き、デプロイ環境の整備などリリース前準備に徹した月でした。リリース前準備で新たなバグを発見するのは、よくあることで、実際に2つの大きい問題に直面しました。

Nginx Ingress Controllerのバグフィクス

Rancherは、自身の動作環境としてKubernetesが必要になります。
我々の環境では、Kubernetes上でIngress Controllerを動かし、その後ろでRancherを動かしていました。

Rancher Internal State Monitoringをしていると、頻繁にWeb Socket Sessionが切れていることに気づき原因を辿っていくと、Ingress ControllerのStatus更新があまりにも頻繁に実施されており、それがリロードを誘発し、WebSocket Sessionがそのタイミングで切れていることがわかりました。

https://github.com/kubernetes/ingress-nginx/pull/3270

一部のノードでContainer Networkが正しく構築されない問題

Rancherで作成されたKubernetesクラスタでContainer Networkがきちんと構築されず、特定のノードから別のノードのContainerに通信できないという問題がありました。

Flannelを使っていたため、Flannel の問題を一番に疑いFlannelの実装を読んでいくとFlannelが内部情報の保存先としてKubernetes ノードのAnnotationを利用していることがわかりました。

また、接続できないノードのAnnotationを確認するとそれらのノードのみFlannelが保存しているはずの内部情報が書き込まれていませんでした。

このことからRancherがAnnotation操作していることを疑い下記のバグを発見/原因特定しレポートしました。

2018年12月

11月に、Managed Kubernetesをβ版として公開することができ、1つの区切りができたところだったので、この月は対外発表を中心に取り組みました。

対外発表

僕らのチームは、まだまだ人が足りていないため、Hiring活動はとても重要な業務の1つです。Hiringがうまくっている会社を見ていると、対外的な活動を多く実施しブランディングに成功しているところが多いように見えます。

僕らも彼らを見習って今後、より力を入れていこうと思います。
12月は、ありがたいことに下記の 5つの機会で発表させていただきました。

  • Alternative Architecture DOJO Offline #1
  • Japan Container Days Keynote
  • Japan Container Days RancherLabスポンサーセッション
  • Rancher JP Meetup in Seattle
  • LINE TechPulse Taiwan 2018

Periodic Backupの実装 (coreos/etcd-operator)

12月は、対外活動だけを実施していた訳ではなく引き続きManaged Kubernetesの追加開発も実施していました。

その中の1つにetcd-operatorを拡張してperiodic backupに対応させるというものがあります。

現在のetcd-operatorは、現在one-shotのsnapshot取得にしか対応しておらず定期的なbackupは、cron jobリソースを使って定期的にEtcdBackup custom resourceを作って実現することが推奨されています。

ただ、この方法はあまりにもめんどくさいので、1年ぐらい前からEtcdBackupの機能拡張の提案と議論がされていました。

https://github.com/coreos/etcd-operator/issues/1841

しかし、実装の提案はされていなかったので今回我々が必要になったタイミングでこの機能を実装し、実装の提案を実施しました。

https://github.com/coreos/etcd-operator/pull/2028

2018年の対外活動/その他

パッチコントリビューション

OpenStack

Etcd Operator

Rancher

Kubernetes

その他

読んだ本

  • 30日でできる! OS自作入門

海外出張

ANA プレミアムポイント 3万2千 (プラチナ届かず・・・)

  • 韓国3回
  • カナダ1回
  • 台湾2回
  • タイ2回
  • ベトナム1回
  • 中国1回
  • アメリカ1回

ブログ

対外発表

--

--