@amsy810's Blog ~Kubernetes / Cloud Native / Docker / etc~ 2023-12-01T08:58:52+09:00 masaya_aoyama Hatena::Blog hatenablog://blog/10257846132677499988 Gateway API の現在地 〜これまでとこれから〜 hatenablog://entry/6801883189063041233 2023-12-01T08:58:52+09:00 2023-12-01T16:17:40+09:00 Kubernetes Advent Calendar 2023の 1 日目の記事です。今年は約 1 ヶ月前に GA した Gateway API の現在地、将来的に Gateway API がどう発展していきそうかについてお話ししたいと思います。 <p>この記事は <a href="https://qiita.com/advent-calendar/2023/kubernetes">Kubernetes Advent Calendar 2023</a> の 1 日目の記事です。</p> <p>こんにちは。<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%B5%A5%A4%A5%D0%A1%BC%A5%A8%A1%BC%A5%B8%A5%A7%A5%F3%A5%C8">サイバーエージェント</a>の青山(<a href="https://twitter.com/amsy810">@amsy810</a>)です。</p> <p>2017 年から 12/1 の初日に記事を書き始め、早いもので 7 年目になりました。</p> <p>2020/2021 年の、おうち <a class="keyword" href="https://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> のために Synology <a class="keyword" href="https://d.hatena.ne.jp/keyword/CSI">CSI</a> に追加実装をしたりした話もネタとして面白いのでぜひ見てみてください。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Famsy810.hateblo.jp%2Fentry%2F2021%2F12%2F01%2F061430" title="おうち Kubernetes に最適な Synology 公式の CSI Driver がリリースされた話と Cloning / Snapshot feature deep dive - @amsy810&#39;s Blog" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://amsy810.hateblo.jp/entry/2021/12/01/061430">amsy810.hateblo.jp</a></cite></p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Famsy810.hateblo.jp%2Fentry%2F2020%2F12%2F01%2F080000" title="おうち Kubernetes 向けに Synology CSI Driver に VolumeExpansion を実装した話 - @amsy810&#39;s Blog" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://amsy810.hateblo.jp/entry/2020/12/01/080000">amsy810.hateblo.jp</a></cite></p> <p>今年は約 1 ヶ月前に GA した <a class="keyword" href="https://d.hatena.ne.jp/keyword/Gateway">Gateway</a> <a class="keyword" href="https://d.hatena.ne.jp/keyword/API">API</a> の現在地、将来的に <a class="keyword" href="https://d.hatena.ne.jp/keyword/Gateway">Gateway</a> <a class="keyword" href="https://d.hatena.ne.jp/keyword/API">API</a> がどう発展していきそうかについてお話ししたいと思います。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/masaya_aoyama/20231201/20231201090247.png" width="1200" height="630" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p> <h1 id="Gateway-API-の-GA-Release"><a class="keyword" href="https://d.hatena.ne.jp/keyword/Gateway">Gateway</a> <a class="keyword" href="https://d.hatena.ne.jp/keyword/API">API</a> の GA Release</h1> <p><a class="keyword" href="https://d.hatena.ne.jp/keyword/Gateway">Gateway</a> <a class="keyword" href="https://d.hatena.ne.jp/keyword/API">API</a> はこの記事執筆時点 12/1 の約一ヶ月前の <a href="https://kubernetes.io/blog/2023/10/31/gateway-api-ga/">2023/10/31 に v1.0.0 で GA リリース</a>されました。</p> <p>GKE を利用しているユーザーは、もっと前に GA していたはずと思った方もいらっしゃるかもしれませんが、GA したものが異なります。 GKE では <a class="keyword" href="https://d.hatena.ne.jp/keyword/Gateway">Gateway</a> <a class="keyword" href="https://d.hatena.ne.jp/keyword/API">API</a> をサポートする GKE <a class="keyword" href="https://d.hatena.ne.jp/keyword/Gateway">Gateway</a> Controller が提供されており、GKE <a class="keyword" href="https://d.hatena.ne.jp/keyword/Gateway">Gateway</a> Controller 自体は、<a class="keyword" href="https://d.hatena.ne.jp/keyword/API">API</a> の GA よりもいち早く <a href="https://cloud.google.com/kubernetes-engine/docs/release-notes#November_09_2022">2022/11 に GA</a> しています。</p> <p>今回 GA したのは <a class="keyword" href="https://d.hatena.ne.jp/keyword/Gateway">Gateway</a> <a class="keyword" href="https://d.hatena.ne.jp/keyword/API">API</a>(<a class="keyword" href="https://d.hatena.ne.jp/keyword/Gateway">Gateway</a> / HTTPRoute / etc などのリソース)の方で、これにより基本的な仕様は大まかに固まったということになります。</p> <h1 id="Gateway-API-とは"><a class="keyword" href="https://d.hatena.ne.jp/keyword/Gateway">Gateway</a> <a class="keyword" href="https://d.hatena.ne.jp/keyword/API">API</a> とは?</h1> <p><a class="keyword" href="https://d.hatena.ne.jp/keyword/Gateway">Gateway</a> <a class="keyword" href="https://d.hatena.ne.jp/keyword/API">API</a> では、<a class="keyword" href="https://d.hatena.ne.jp/keyword/Ingress">Ingress</a> で生じていた課題を解決することができるようになっています。 例えば、インフラ提供者・<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>運用者・アプリケーション開発者のそれぞれで、<a class="keyword" href="https://d.hatena.ne.jp/keyword/Ingress">Ingress</a> で設定を行いたい責務が異なります。<a class="keyword" href="https://d.hatena.ne.jp/keyword/Ingress">Ingress</a> では<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>運用者とアプリケーション開発者の関心事に対する設定を単一の <a class="keyword" href="https://d.hatena.ne.jp/keyword/Ingress">Ingress</a> リソースで行っていましたが、<a class="keyword" href="https://d.hatena.ne.jp/keyword/Gateway">Gateway</a> <a class="keyword" href="https://d.hatena.ne.jp/keyword/API">API</a> では <a class="keyword" href="https://d.hatena.ne.jp/keyword/Gateway">Gateway</a>・XXXRoute(HTTPRoute や TCPRoute)の複数のリソースで設定を行います。また、Namespace を跨いだ委譲なども可能な仕組みになっています。</p> <ul> <li>インフラ提供者 <ul> <li>利用可能な <a class="keyword" href="https://d.hatena.ne.jp/keyword/Gateway">Gateway</a> 実装の設定(インストール)</li> </ul> </li> <li><a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>運用者 <ul> <li>バーチャルホストの設定</li> <li>IP Address の設定</li> <li><a class="keyword" href="https://d.hatena.ne.jp/keyword/SSL">SSL</a>/<a class="keyword" href="https://d.hatena.ne.jp/keyword/TLS">TLS</a> の設定</li> </ul> </li> <li>アプリケーション開発者 <ul> <li>パスベースのルーティング設定(特定のパス > 特定の Service)</li> <li>加重ルーティングの設定</li> </ul> </li> </ul> <p>ここでは <a class="keyword" href="https://d.hatena.ne.jp/keyword/Gateway">Gateway</a> <a class="keyword" href="https://d.hatena.ne.jp/keyword/API">API</a> の詳細については詳しくは説明しませんが、興味のある方は<a href="https://gateway-api.sigs.k8s.io/concepts/api-overview/">公式サイトのIntroduction</a>を読んでみてください。</p> <p><img src="https://gateway-api.sigs.k8s.io/images/api-model.png" alt="Gateway API Overview" /></p> <h1 id="Gateway-API-のこれまでの歩み"><a class="keyword" href="https://d.hatena.ne.jp/keyword/Gateway">Gateway</a> <a class="keyword" href="https://d.hatena.ne.jp/keyword/API">API</a> のこれまでの歩み</h1> <p><a class="keyword" href="https://d.hatena.ne.jp/keyword/Ingress">Ingress</a> に生じていた課題の精査、<a class="keyword" href="https://d.hatena.ne.jp/keyword/Gateway">Gateway</a> <a class="keyword" href="https://d.hatena.ne.jp/keyword/API">API</a> が <a class="keyword" href="https://d.hatena.ne.jp/keyword/Ingress">Ingress</a> v2 として設計が始まった背景、そして現在の <a class="keyword" href="https://d.hatena.ne.jp/keyword/Gateway">Gateway</a> <a class="keyword" href="https://d.hatena.ne.jp/keyword/API">API</a> の設計に至るまでの経緯については、KubeCon + CloudNativeCon NA 2023 の「<a href="https://youtu.be/V3Vu_FWb4l4">Gateway API: The Most Collaborative API in Kubernetes History Is GA - Rob Scott, Google &amp; Nick Young, Isovalent</a>」でもまとめられているので、<a class="keyword" href="https://d.hatena.ne.jp/keyword/Gateway">Gateway</a> <a class="keyword" href="https://d.hatena.ne.jp/keyword/API">API</a> の 4 年の Upstream の歴史について興味のある方は見てみると楽しめると思います。</p> <p>なお、最初期は <a class="keyword" href="https://d.hatena.ne.jp/keyword/Ingress">Ingress</a> v2 として始まった <a class="keyword" href="https://d.hatena.ne.jp/keyword/Gateway">Gateway</a> <a class="keyword" href="https://d.hatena.ne.jp/keyword/API">API</a> プロジェクトですが、<a class="keyword" href="https://d.hatena.ne.jp/keyword/Ingress">Ingress</a> 自体は今後も利用可能で、<a href="https://gateway-api.sigs.k8s.io/faq/#frequently-asked-questions-faq">非推奨にする計画は現時点ではありません</a>。<a class="keyword" href="https://d.hatena.ne.jp/keyword/Ingress">Ingress</a> は HTTP エンドポイントを公開するシンプルな仕組みとして残り続け、<a class="keyword" href="https://d.hatena.ne.jp/keyword/Gateway">Gateway</a> <a class="keyword" href="https://d.hatena.ne.jp/keyword/API">API</a> は汎用的で高機能な仕組みとして提供される予定です。これは KubeCon などでも幾度となくメッセージとして伝えられていたものなので、現時点での信憑性はかなり高いものでしょう。</p> <h1 id="現時点で-Gateway-API-に対応している実装">現時点で <a class="keyword" href="https://d.hatena.ne.jp/keyword/Gateway">Gateway</a> <a class="keyword" href="https://d.hatena.ne.jp/keyword/API">API</a> に対応している実装</h1> <p><a class="keyword" href="https://d.hatena.ne.jp/keyword/Gateway">Gateway</a> <a class="keyword" href="https://d.hatena.ne.jp/keyword/API">API</a> が利用できる環境は<a href="https://gateway-api.sigs.k8s.io/implementations/">公式サイト</a>で公開されており、記事執筆時点でもかなり多くの実装が行われています。 <a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%D1%A5%D6%A5%EA%A5%C3%A5%AF%A5%AF%A5%E9%A5%A6%A5%C9">パブリッククラウド</a>環境の場合は、GKE は GA ステータスとなっていますが、EKS や <a class="keyword" href="https://d.hatena.ne.jp/keyword/AKS">AKS</a> は <a class="keyword" href="https://d.hatena.ne.jp/keyword/preview">preview</a> や alpha ステータスとなっているため、利用には注意が必要です。</p> <p>オンプレミス環境や<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%D1%A5%D6%A5%EA%A5%C3%A5%AF%A5%AF%A5%E9%A5%A6%A5%C9">パブリッククラウド</a>にセルフデプロイする場合の選択肢としては、「Contour(beta)」「Envoy <a class="keyword" href="https://d.hatena.ne.jp/keyword/Gateway">Gateway</a>(beta)」「Cilium(beta)」などが適しています。Cilium は CNI Plugin のため、別の CNI Plugin を利用している <a class="keyword" href="https://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> <a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>では追加でインストールして利用することなどもできないため注意してください。</p> <p>また、<a class="keyword" href="https://d.hatena.ne.jp/keyword/Gateway">Gateway</a> <a class="keyword" href="https://d.hatena.ne.jp/keyword/API">API</a> は、Service Mesh でも利用できるようになっています。Service Mesh における <a class="keyword" href="https://d.hatena.ne.jp/keyword/Gateway">Gateway</a> <a class="keyword" href="https://d.hatena.ne.jp/keyword/API">API</a> 実装は、<a href="https://gateway-api.sigs.k8s.io/concepts/gamma/">GAMMA (Gateway API for Mesh Management and Administration)</a> initiative によって進められており、 v0.8.0 の時点で Experimental なステータスです。 そのため、やや Too much な構成としてはサービスメッシュ実装でもある「Istio(beta)」も選択肢としては挙げられます。</p> <p>一方で、<a class="keyword" href="https://d.hatena.ne.jp/keyword/Ingress">Ingress</a> 実装として最もメジャーとも言える「<a class="keyword" href="https://d.hatena.ne.jp/keyword/ingress">ingress</a>-nginx」の <a class="keyword" href="https://d.hatena.ne.jp/keyword/Gateway">Gateway</a> <a class="keyword" href="https://d.hatena.ne.jp/keyword/API">API</a> 対応はされないのでしょうか?</p> <h1 id="ingress-nginx-の-Gateway-API-対応について"><a class="keyword" href="https://d.hatena.ne.jp/keyword/ingress">ingress</a>-nginx の <a class="keyword" href="https://d.hatena.ne.jp/keyword/Gateway">Gateway</a> <a class="keyword" href="https://d.hatena.ne.jp/keyword/API">API</a> 対応について</h1> <p><code>kubernetes/ingress-nginx</code> の <a class="keyword" href="https://d.hatena.ne.jp/keyword/Gateway">Gateway</a> <a class="keyword" href="https://d.hatena.ne.jp/keyword/API">API</a> については、2021年ごろに <a href="https://github.com/kubernetes/ingress-nginx/issues/7517">Issue #7517</a> が建てられ始め、<a class="keyword" href="https://d.hatena.ne.jp/keyword/Gateway">Gateway</a> <a class="keyword" href="https://d.hatena.ne.jp/keyword/API">API</a> の仕様成熟に伴い、実装に向かっています。 <code>kubernetes/gateway-nginx</code> のように新しい<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%EA%A5%DD%A5%B8%A5%C8%A5%EA">リポジトリ</a>で新しいものを実装するのではなく、同一<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%EA%A5%DD%A5%B8%A5%C8%A5%EA">リポジトリ</a>で両サポートする方向で実装が進められているため、将来的にはバージョンアップすることで<a class="keyword" href="https://d.hatena.ne.jp/keyword/Ingress">Ingress</a>と<a class="keyword" href="https://d.hatena.ne.jp/keyword/Gateway">Gateway</a> <a class="keyword" href="https://d.hatena.ne.jp/keyword/API">API</a>の両方が利用できるようになっていきそうです。</p> <p>また、先日のKubeConであった「<a href="https://youtu.be/B-pdIFeyh0c?t=1285">What's Happening with Ingress-Nginx! - James Strong, Chainguard &amp; Ricardo Katz, VMware</a>」のセッションでも、2024 年の計画として <a class="keyword" href="https://d.hatena.ne.jp/keyword/Gateway">Gateway</a> <a class="keyword" href="https://d.hatena.ne.jp/keyword/API">API</a> への対応について言及されています。 Issueやセッションを見るとわかるのですが、<a class="keyword" href="https://d.hatena.ne.jp/keyword/ingress">ingress</a>-nginxプロジェクトでは現在 <a class="keyword" href="https://d.hatena.ne.jp/keyword/Gateway">Gateway</a> <a class="keyword" href="https://d.hatena.ne.jp/keyword/API">API</a> 実装の前段として、大幅な実装変更の前に優先度の高い「利用されていない機能の削除・<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%EA%A5%D5%A5%A1%A5%AF%A5%BF%A5%EA%A5%F3%A5%B0">リファクタリング</a>」・セキュリティ対策のための「Controlplane(<a class="keyword" href="https://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> Controller) と Dataplane(Nginx)の分離」などが進められています。そのため、<a class="keyword" href="https://d.hatena.ne.jp/keyword/Gateway">Gateway</a> <a class="keyword" href="https://d.hatena.ne.jp/keyword/API">API</a> 対応の実装が少し遅くなっている状況のようです。</p> <h1 id="Gateway-API-に関する機能強化-Gateway-Enhancement-ProposalsGEPs"><a class="keyword" href="https://d.hatena.ne.jp/keyword/Gateway">Gateway</a> <a class="keyword" href="https://d.hatena.ne.jp/keyword/API">API</a> に関する機能強化 <a class="keyword" href="https://d.hatena.ne.jp/keyword/Gateway">Gateway</a> Enhancement Proposals(GEPs)</h1> <p><a class="keyword" href="https://d.hatena.ne.jp/keyword/Gateway">Gateway</a> <a class="keyword" href="https://d.hatena.ne.jp/keyword/API">API</a> に関する機能強化は、<a href="https://github.com/kubernetes-sigs/gateway-api/tree/main/geps">Gateway Enhancement Proposals(GEPs)</a>によって管理されています。 <a class="keyword" href="https://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> に対する機能強化提案 <a class="keyword" href="https://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> Enhancement Proposals(KEPs)と類似したフローで管理されています。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/masaya_aoyama/20231201/20231201030949.png" width="317" height="890" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p> <p>将来的に追加が検討されている Experimental な GEPs には、下記のようなものが存在します。Experimental ステータスな GEPs はいくつかの実装がすでに用意されていることもあります。</p> <ul> <li><a href="https://github.com/kubernetes-sigs/gateway-api/blob/main/geps/gep-1016.md">GEP-1016</a>(Status = Experimental) <ul> <li>GRPCRoute の追加</li> </ul> </li> <li><a href="https://github.com/kubernetes-sigs/gateway-api/blob/main/geps/gep-1651.md">GEP-1651</a>(Status = Provisional) <ul> <li><a class="keyword" href="https://d.hatena.ne.jp/keyword/Gateway">Gateway</a> で利用される IP アドレスの接続性の設定</li> <li>インターネット経由でのパブリックアクセス、<a class="keyword" href="https://d.hatena.ne.jp/keyword/VPC">VPC</a> などプライベートアクセス、<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>内のみでのアクセスなどを指定し、特定のスコープのみで接続できるように設定可能にする</li> </ul> </li> <li><a href="https://github.com/kubernetes-sigs/gateway-api/blob/main/geps/gep-1742.md">GEP-1742</a>(Status = Experimental) <ul> <li>HTTPRoute での timeout 設定の追加</li> </ul> </li> <li><a href="https://github.com/kubernetes-sigs/gateway-api/blob/main/geps/gep-1867.md">GEP-1867</a>(Status = Experimental) <ul> <li><a class="keyword" href="https://d.hatena.ne.jp/keyword/Gateway">Gateway</a> 単位でのベンダー固有設定をできるようにする</li> <li>現在は GatewayClass でベンダー固有の設定(利用するタイプ・方式・バージョンなど)ができるようになっているが、GatewayClass はインフラ提供者が管理するものなため、<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>運用者が設定変更できる <a class="keyword" href="https://d.hatena.ne.jp/keyword/Gateway">Gateway</a> リソースのフィールドにもベンダー固有設定を行うことができるフィールドを用意する</li> </ul> </li> <li><a href="https://github.com/kubernetes-sigs/gateway-api/blob/main/geps/gep-2162.md">GEP-2162</a>(Status = Experimental) <ul> <li><a class="keyword" href="https://d.hatena.ne.jp/keyword/Gateway">Gateway</a> Controller がサポートしている機能セットを GatewayClass で列挙可能にする</li> </ul> </li> </ul> <h1 id="Service-の-Gateway-API-への統合案">Service の <a class="keyword" href="https://d.hatena.ne.jp/keyword/Gateway">Gateway</a> <a class="keyword" href="https://d.hatena.ne.jp/keyword/API">API</a> への統合案</h1> <p><a class="keyword" href="https://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> の共同創設者であり、現在もコアメンテナーを務める Tim Hockin 氏が KubeCon + CloudNativeCon NA 2023 で講演した LT 「<a href="https://youtu.be/Oslwx3hj2Eg">Lightning Talk: Why Service Is the Worst API in Kubernetes, &amp; What We’re Doing About It</a>」では、Service リソースの問題点と、<a class="keyword" href="https://d.hatena.ne.jp/keyword/Gateway">Gateway</a> <a class="keyword" href="https://d.hatena.ne.jp/keyword/API">API</a> を利用した変更案を紹介していました。 現状の Service リソースはさまざまな拡張が行われた結果、非常に多くの機能を持っており、かつ重要なコア <a class="keyword" href="https://d.hatena.ne.jp/keyword/API">API</a> のため影響度が高く、改修が困難な状況になってしまっています。 Tim のこのセッションでは、Service を Pod をひとまとめにする抽象的な概念にする部分のみに機能を絞り、ClusterIP や LoadBalancer などの Pod に対する接続性を用意する部分は <a class="keyword" href="https://d.hatena.ne.jp/keyword/Gateway">Gateway</a> <a class="keyword" href="https://d.hatena.ne.jp/keyword/API">API</a> で担うといった変更案をア<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%A4%A5%C7%A5%A2">イデア</a>として語られています。</p> <p><a class="keyword" href="https://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> を初めて触った時に、Service と <a class="keyword" href="https://d.hatena.ne.jp/keyword/Ingress">Ingress</a> や Service と <a class="keyword" href="https://d.hatena.ne.jp/keyword/Gateway">Gateway</a> <a class="keyword" href="https://d.hatena.ne.jp/keyword/API">API</a> をみて、<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%ED%A1%BC%A5%C9%A5%D0%A5%E9%A5%F3%A5%B5%A1%BC">ロードバランサー</a>を制御する <a class="keyword" href="https://d.hatena.ne.jp/keyword/API">API</a> が 2 通りあり違和感を感じた方もいらっしゃるかと思います。 この改修が入ることによって、Service は Pod を抽象的にまとめるもの・<a class="keyword" href="https://d.hatena.ne.jp/keyword/Gateway">Gateway</a> <a class="keyword" href="https://d.hatena.ne.jp/keyword/API">API</a> は接続性を担うものと責務の分離がされるとよりわかりやすいと感じる方もいるかと思います。</p> <p>今回のセッションではいちア<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%A4%A5%C7%A5%A2">イデア</a>として語られていただけなので今後の方向性が確定しているわけではありませんが、<a class="keyword" href="https://d.hatena.ne.jp/keyword/Gateway">Gateway</a> <a class="keyword" href="https://d.hatena.ne.jp/keyword/API">API</a> を通じて、また数年かけて最古の <a class="keyword" href="https://d.hatena.ne.jp/keyword/API">API</a> の一つである Service の改修が進んでいくことも楽しみです。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/masaya_aoyama/20231201/20231201030251.png" width="1200" height="673" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p> <h1 id="まとめと今後">まとめと今後</h1> <p>弊社では<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%D7%A5%E9%A5%A4%A5%D9%A1%BC%A5%C8%A5%AF%A5%E9%A5%A6%A5%C9">プライベートクラウド</a>上に独自の <a class="keyword" href="https://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> as a Service の AKE を提供しており、独自の <a class="keyword" href="https://d.hatena.ne.jp/keyword/Ingress">Ingress</a> Cont¥roller や Cloud Controller Manager を実装しています。そして <a class="keyword" href="https://d.hatena.ne.jp/keyword/Gateway">Gateway</a> <a class="keyword" href="https://d.hatena.ne.jp/keyword/API">API</a> の GA に伴い、じきに <a class="keyword" href="https://d.hatena.ne.jp/keyword/Gateway">Gateway</a> Controller の実装も検討しています。今後は上記のような実装に関わりそうな GEPs のフィールド変更などを適切にウォッチしていくため、続報や実装時にはまた改めてブログにでもまとめさせていただきます。 なお、こうした仕事にご興味がある方がいらっしゃれば、ぜひ<a href="https://hrmos.co/pages/cyberagent-group/jobs/CIU0001">採用サイト</a>を覗いてみてください。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/masaya_aoyama/20231201/20231201031313.png" width="273" height="308" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p> <h1 id="参考-Gateway-API-関連の便利ツール">参考: <a class="keyword" href="https://d.hatena.ne.jp/keyword/Gateway">Gateway</a> <a class="keyword" href="https://d.hatena.ne.jp/keyword/API">API</a> 関連の便利ツール</h1> <ul> <li><a href="https://github.com/kubernetes-sigs/gateway-api/tree/main/gwctl">gwctl</a> <ul> <li><a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>ー内に存在するポリシー<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%D0%A5%A4%A5%F3%A5%C7%A5%A3%A5%F3%A5%B0">バインディング</a>を考慮しながら <a class="keyword" href="https://d.hatena.ne.jp/keyword/Gateway">Gateway</a> <a class="keyword" href="https://d.hatena.ne.jp/keyword/API">API</a> 関連のリソースを表示する kubectl <a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%D7%A5%E9%A5%B0%A5%A4%A5%F3">プラグイン</a></li> <li><a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%B9%A5%BF%A5%F3%A5%C9%A5%A2%A5%ED%A5%F3">スタンドアロン</a>バイナリ、ライブラリとしても利用かのう</li> </ul> </li> <li><a href="https://github.com/kubernetes-sigs/ingress2gateway">ingress2gateway</a> <ul> <li><a class="keyword" href="https://d.hatena.ne.jp/keyword/Ingress">Ingress</a> リソースを <a class="keyword" href="https://d.hatena.ne.jp/keyword/Gateway">Gateway</a> / HTTPRoute リソースに変換する <a class="keyword" href="https://d.hatena.ne.jp/keyword/CLI">CLI</a> ツール</li> </ul> </li> </ul> masaya_aoyama OpenClarity プロジェクトの KubeClarity で始めるお手軽 SBOM/脆弱性管理 hatenablog://entry/4207112889940662508 2022-12-02T12:22:09+09:00 2023-08-17T13:30:49+09:00 OpenClarity プロジェクトと KubeClarity を用いた SBOM 管理 この記事は Kubernetes Advent Calendar 2022 の 2 日目の記事です。 こんにちは。 サイバーエージェント CIU(CyberAgent group Infrastructure Unit)で KaaS 基盤のプロダクトオーナーを務めている青山です。 採用もしているので、ご興味のある方はぜひ Twitter DM などいただければと思います。 今回の Advent Calendar は、去年の KubeCon で印象に残っていた APIClarity の兄弟プロダクトである、… <h1 id="OpenClarity-プロジェクトと-KubeClarity-を用いた-SBOM-管理">OpenClarity プロジェクトと KubeClarity を用いた SBOM 管理</h1> <p>この記事は <a href="https://qiita.com/advent-calendar/2022/kubernetes">Kubernetes Advent Calendar 2022</a> の 2 日目の記事です。</p> <p>こんにちは。 <a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%B5%A5%A4%A5%D0%A1%BC%A5%A8%A1%BC%A5%B8%A5%A7%A5%F3%A5%C8">サイバーエージェント</a> CIU(<a class="keyword" href="https://d.hatena.ne.jp/keyword/CyberAgent">CyberAgent</a> group Infrastructure Unit)で KaaS 基盤のプロダクトオーナーを務めている青山です。 採用もしているので、ご興味のある方はぜひ <a class="keyword" href="https://d.hatena.ne.jp/keyword/Twitter">Twitter</a> DM などいただければと思います。</p> <p>今回の Advent Calendar は、去年の KubeCon で印象に残っていた APIClarity の兄弟プロダクトである、KubeClarity について紹介しようと思います。 (2020/2021 に引き続き<a href="https://amsy810.hateblo.jp/entry/2021/12/01/061430">おうちKubernetesでCSIガチネタ</a>したかったのですが、時間が取れず…)</p> <h1 id="APIClarity-との出会い">APIClarity との出会い</h1> <p>APIClarity は <a class="keyword" href="https://d.hatena.ne.jp/keyword/API">API</a> リク<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>トをキャプチャ・分析し、OpenAPI Schema の再生成・Zombie <a class="keyword" href="https://d.hatena.ne.jp/keyword/API">API</a> の検知・Shadow <a class="keyword" href="https://d.hatena.ne.jp/keyword/API">API</a> の検知などを行うプロダクトです。これにより、<a class="keyword" href="https://d.hatena.ne.jp/keyword/%C0%F8%BA%DF%C5%AA">潜在的</a>なリスクを特定したり、Observability の手助けをすることができます。</p> <p>去年参加した KubeCon + CloudNativeCon NA 2021で知り、<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%A2%A1%BC%A5%AD%A5%C6%A5%AF%A5%C1%A5%E3">アーキテクチャ</a>が面白かったので記憶に残っていました。</p> <p>APIClarityでは、Istio で構成されたサービスメッシュ上の各 Envoy Proxy 内で、Proxy-WASM を利用して実装された WASM のプログラムを動作させ、<a class="keyword" href="https://d.hatena.ne.jp/keyword/API">API</a>リク<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>トを収集します。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/masaya_aoyama/20221129/20221129020919.png" width="1200" height="542" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p> <p>APIClarity について興味がある方は、詳細について下記を参照してみてください。</p> <p><a href="https://speakerdeck.com/masayaaoyama/techfeed-conference-2022-ebpf-wasm-amsy810?slide=9">ebpf&#x3068;WASM&#x306B;&#x601D;&#x3044;&#x3092;&#x99B3;&#x305B;&#x308B;2022 / techfeed-conference-2022-ebpf-wasm-amsy810 - Speaker Deck</a></p> <h1 id="OpenClarity-プロジェクト">OpenClarity プロジェクト</h1> <p><a href="https://openclarity.io/">OpenClarity</a> は、セキュリティや Observability のための <a class="keyword" href="https://d.hatena.ne.jp/keyword/OSS">OSS</a> ツール群を開発するプロジェクトです。 APIClarity も OpenClarity プロジェクトが公開するプロダクトの一つです。 <a class="keyword" href="https://d.hatena.ne.jp/keyword/Cisco">Cisco</a> がリードしています。</p> <p>今年の KubeCon + CloudNativeCon NA 2022 では、(おそらくスポンサーの)<a class="keyword" href="https://d.hatena.ne.jp/keyword/Keynote">Keynote</a> で OpenClarity について紹介されていました。</p> <p>現段階では下記の 3 種類のプロダクトが公開されています。</p> <ul> <li>APIClarity</li> <li>KubeClarity</li> <li>FunctionClarity</li> </ul> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/masaya_aoyama/20221129/20221129021043.png" width="1120" height="459" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p> <h1 id="KubeClarity">KubeClarity</h1> <p>今回紹介する KubeClarity は下記の 3 つのことを実施することができます。 また、現状内部で利用されているスキャナー類は Syft/Grype/Dockle ですが、別のプロダクトの利用も視野に入れているようです。</p> <ul> <li>SBOM(Software Bill Of Materials)の生成 <ul> <li>Content Analyzer: <strong>Syft</strong></li> </ul> </li> <li><a class="keyword" href="https://d.hatena.ne.jp/keyword/%C0%C8%BC%E5%C0%AD">脆弱性</a>スキャン <ul> <li><a class="keyword" href="https://d.hatena.ne.jp/keyword/Vulnerability">Vulnerability</a> Scanner: <strong>Grype</strong></li> </ul> </li> <li>CIS Docker Benchmark のテスト <ul> <li>Banchmarker: <strong>Dockle</strong></li> </ul> </li> </ul> <h2 id="コンテナイメージのスキャン">コンテナイメージのスキャン</h2> <p>コンテナイメージのスキャン・解析は<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>上で実行されているイメージ単位で Job リソースが作成されて実施されます。 Job リソースが作成されると、内部では下記の2つの Scanner が動作します。 Syft/Grype/Dockle はそれぞれ Go の <a class="keyword" href="https://d.hatena.ne.jp/keyword/SDK">SDK</a> が提供されているため、それを用いてスキャン・解析を行っています。</p> <ul> <li><a href="https://github.com/openclarity/kubeclarity/blob/7f3d166ad4feb0bda93138e6c4e4fe12b6c360a5/runtime_k8s_scanner/pkg/scanner/scanner.go#L71">https://github.com/openclarity/kubeclarity/blob/7f3d166ad4feb0bda93138e6c4e4fe12b6c360a5/runtime_k8s_scanner/pkg/scanner/scanner.go#L71</a></li> <li><a href="https://github.com/openclarity/kubeclarity/blob/7f3d166ad4feb0bda93138e6c4e4fe12b6c360a5/cis_docker_benchmark_scanner/pkg/scanner/run.go#L74">https://github.com/openclarity/kubeclarity/blob/7f3d166ad4feb0bda93138e6c4e4fe12b6c360a5/cis_docker_benchmark_scanner/pkg/scanner/run.go#L74</a></li> </ul> <p>現状デプロイされるJobは実際にコンテナイメージを持っているノードに明示的にスケジューリングし、そのノード上のイメージを利用するなどは行っていません。 <a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>上にデプロイされているイメージを再利用したスキャンの仕組みを実装することは以前から考えていたので、そのあたりの機能がKubeClarityにも入ると良さそうだなと考えています。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/masaya_aoyama/20221129/20221129021118.png" width="1200" height="552" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p> <h2 id="Syft-と-Grype-による脆弱性スキャンの高速化">Syft と Grype による<a class="keyword" href="https://d.hatena.ne.jp/keyword/%C0%C8%BC%E5%C0%AD">脆弱性</a>スキャンの高速化</h2> <p>Syft はコンテナイメージ単位でインストールされたパッケージ類のリストである SBOM を生成します。 Grype は Syft が生成した SBOM を用いて<a class="keyword" href="https://d.hatena.ne.jp/keyword/%C0%C8%BC%E5%C0%AD">脆弱性</a>の有無を検査することができるため、再度コンテナイメージをスキャンするのと比較して、高速に<a class="keyword" href="https://d.hatena.ne.jp/keyword/%C0%C8%BC%E5%C0%AD">脆弱性</a>スキャンを実施することが可能です。</p> <p>実際に runtime_<a class="keyword" href="https://d.hatena.ne.jp/keyword/k8s">k8s</a>_scanner の<a href="https://github.com/openclarity/kubeclarity/blob/7f3d166ad4feb0bda93138e6c4e4fe12b6c360a5/runtime_k8s_scanner/pkg/scanner/scanner.go#L77">実行部分</a>を確認すると、SBOM DB からデータの取得を試み、結果を利用しています。</p> <h2 id="KubeClarity-におけるデータ">KubeClarity におけるデータ</h2> <p>KubeClarity では、データを 4 つに分類して管理しています。</p> <ul> <li><strong>Application</strong>: 実行されているPod(実際にはDeploymentなどの粒度)</li> <li><strong>Application Resource</strong>: コンテナイメージ</li> <li><strong>Package</strong>: 利用しているパッケージ(<a class="keyword" href="https://d.hatena.ne.jp/keyword/rpm">rpm</a> や <a class="keyword" href="https://d.hatena.ne.jp/keyword/deb">deb</a> などの OS 系 / npm や gomod などの言語系)</li> <li><strong><a class="keyword" href="https://d.hatena.ne.jp/keyword/Vulnerability">Vulnerability</a></strong>: <a class="keyword" href="https://d.hatena.ne.jp/keyword/%C0%C8%BC%E5%C0%AD">脆弱性</a>情報</li> </ul> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/masaya_aoyama/20221129/20221129040732.png" width="796" height="316" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p> <h2 id="WebUI">WebUI</h2> <p>Web UI は使いやすく作られており、<a class="keyword" href="https://d.hatena.ne.jp/keyword/%C0%C8%BC%E5%C0%AD">脆弱性</a>対応のはじめの一歩や簡易的に実現する手段としても重宝できそうです。</p> <p>UI からは Pod・コンテナイメージ・パッケージ・<a class="keyword" href="https://d.hatena.ne.jp/keyword/%C0%C8%BC%E5%C0%AD">脆弱性</a>情報(CVE)それぞれの情報で検索をかけることが可能になっています。 運用を考えた際生じる、下記のようなオペレーションが可能です。</p> <ul> <li>特定の CVE に紐づくコンテナイメージの一覧を取得</li> <li>特定のバージョン以下のパッケージを利用しているコンテナイメージ一覧を取得</li> <li>特定の CVE に紐づく Pod 一覧(現在<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>で起動しているもの)を取得</li> <li>特定のパッケージを利用している Pod 一覧(現在<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>で起動しているもの)を取得</li> </ul> <p>KubeClarityの導入は非常に簡単かつ環境に影響を与えないため、一度<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>にデプロイしてスキャンを実施し、</p> <ul> <li><a class="keyword" href="https://d.hatena.ne.jp/keyword/%C0%C8%BC%E5%C0%AD">脆弱性</a>が多いDeployumentの確認</li> <li>修正可能な<a class="keyword" href="https://d.hatena.ne.jp/keyword/%C0%C8%BC%E5%C0%AD">脆弱性</a>の確認</li> </ul> <p>などを行って、定期的に単発で対応するといったことにも可能です。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/masaya_aoyama/20221202/20221202112342.png" width="1200" height="619" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p> <p>また、特定の<a class="keyword" href="https://d.hatena.ne.jp/keyword/%C0%C8%BC%E5%C0%AD">脆弱性</a>が出たタイミングで導入してスキャンし、一覧を習得した上で、特定の<a class="keyword" href="https://d.hatena.ne.jp/keyword/%C0%C8%BC%E5%C0%AD">脆弱性</a>を持ってしまっているDeploymentを洗い出すといったことにも利用可能です。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/masaya_aoyama/20221202/20221202113200.png" width="1200" height="697" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p> <p>もちろん CVE に関する情報も確認することができます。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/masaya_aoyama/20221202/20221202113352.png" width="1139" height="686" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span> <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/masaya_aoyama/20221202/20221202113349.png" width="1133" height="523" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p> <p>SBOM の情報と紐付けて、それらのパッケージがどの程度実行しているPodから使われているか、コンテナイメージに含んでいるかなどを確認することもできます。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/masaya_aoyama/20221202/20221202112717.png" width="1200" height="576" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p> <p>Dockle も有効にしてスキャンしている場合には、Dockerfile で修正したほうが良い箇所も確認できます。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/masaya_aoyama/20221202/20221202121421.png" width="1200" height="603" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p> <p>他にも、様々な形で情報を表示することが可能です。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/masaya_aoyama/20221202/20221202112059.png" width="1200" height="618" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/masaya_aoyama/20221202/20221202102548.png" width="1200" height="640" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p> <h1 id="まとめ">まとめ</h1> <p>今回は比較的用意に SBOM や<a class="keyword" href="https://d.hatena.ne.jp/keyword/%C0%C8%BC%E5%C0%AD">脆弱性</a>管理を行うことができる KubeClarity について紹介しました。 OpenClarity Project では、あったら嬉しいプロダクト開発がされている印象なので、今後もウォッチしていきたいですね。</p> <p>ちなみに 3-shake さんのイベントでこのあたりをデモ付きで紹介する予定なので、よければご参加ください :)</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2F3-shake.connpass.com%2Fevent%2F267080%2F" title="3-shake SRE Tech Talk 2022 クリスマス直前会! (2022/12/15 19:00〜)" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://3-shake.connpass.com/event/267080/">3-shake.connpass.com</a></cite></p> masaya_aoyama おうち Kubernetes に最適な Synology 公式の CSI Driver がリリースされた話と Cloning / Snapshot feature deep dive hatenablog://entry/13574176438037908111 2021-12-01T06:14:30+09:00 2021-12-01T06:15:54+09:00 こんにちは。青山(@amsy810)です。 この記事は、Kubernetes Advent Calendar 2021 の 1日目の記事です。 いよいよ今年もアドベントカレンダーの季節が始まりました。今年も1ヶ月間わいわいしていきましょう! Agenda 2021-08-31 にリリースされた Synology 公式の CSI Driver の紹介 CSI Driver に実装された Cloning と Snapshot Feature の実装深堀り おうち Kubernetes 今回はかわいい下駄箱 DC に佇む、箱物ストレージの Synology に新たな CSI Driver を適用して… <p>こんにちは。青山(<a href="https://twitter.com/amsy810">@amsy810</a>)です。</p> <p>この記事は、<a href="https://qiita.com/advent-calendar/2021/kubernetes">Kubernetes Advent Calendar 2021</a> の 1日目の記事です。</p> <p>いよいよ今年も<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%C9%A5%D9%A5%F3%A5%C8%A5%AB%A5%EC%A5%F3%A5%C0%A1%BC">アドベントカレンダー</a>の季節が始まりました。今年も1ヶ月間わいわいしていきましょう!</p> <h1>Agenda</h1> <ul> <li>2021-08-31 にリリースされた Synology 公式の <a class="keyword" href="http://d.hatena.ne.jp/keyword/CSI">CSI</a> Driver の紹介</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/CSI">CSI</a> Driver に実装された Cloning と Snapshot Feature の実装深堀り</li> </ul> <h1>おうち <a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a></h1> <p>今回はかわいい下駄箱 DC に佇む、箱物ストレージの Synology に新たな <a class="keyword" href="http://d.hatena.ne.jp/keyword/CSI">CSI</a> Driver を適用していきます。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/masaya_aoyama/20201130/20201130210026.jpg" alt="f:id:masaya_aoyama:20201130210026j:plain" width="1200" height="900" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p> <h1>去年の jparklab/synology-<a class="keyword" href="http://d.hatena.ne.jp/keyword/csi">csi</a> <a class="keyword" href="http://d.hatena.ne.jp/keyword/CSI">CSI</a> Driver に機能実装した話</h1> <p>去年はおうち<a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a>向けのストレージを Synology に刷新したのもあって、jparklab/synology-<a class="keyword" href="http://d.hatena.ne.jp/keyword/csi">csi</a> という有志によって作られた <strong>非公式の</strong> Synology <a class="keyword" href="http://d.hatena.ne.jp/keyword/CSI">CSI</a> Driverに対して、PVCと<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D5%A5%A1%A5%A4%A5%EB%A5%B7%A5%B9%A5%C6%A5%E0">ファイルシステム</a>の動的なリサイズを行う <a href="https://github.com/jparklab/synology-csi/pull/46">VolumeExpansion の機能を実装</a>しつつ、様々な <a class="keyword" href="http://d.hatena.ne.jp/keyword/CSI">CSI</a> Driver での内部実装の紹介する話をしました。</p> <ul> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/CSI">CSI</a>ではどうやってブロックデ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A5%A4%A5%B9">バイス</a>の拡張を検知しているか</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/CSI">CSI</a>ではどうやって<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D5%A5%A1%A5%A4%A5%EB%A5%B7%A5%B9%A5%C6%A5%E0">ファイルシステム</a>もPod再起動なしに動的に拡張されているか</li> <li>Controller PluginとNode Pluginの役割分担</li> </ul> <p>といった詳細な話が気になる方は、ぜひ去年のも見てみてください。</p> <p>また、<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSI">CSI</a> とは何かといった話や、<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSI">CSI</a> Driver の大枠の仕組みについては去年の記事を見てみてください。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Famsy810.hateblo.jp%2Fentry%2F2020%2F12%2F01%2F080000" title="おうち Kubernetes 向けに Synology CSI Driver に VolumeExpansion を実装した話 - @amsy810&#39;s Blog" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://amsy810.hateblo.jp/entry/2020/12/01/080000">amsy810.hateblo.jp</a></cite></p> <h1>Synology 公式の <a class="keyword" href="http://d.hatena.ne.jp/keyword/CSI">CSI</a> Driver</h1> <p>今年は VolumeSnapshot あたりを実装しつつ、内部実装を紹介する話でもしようかなぁと思っていました。 しかし、2021-08-31 に <strong>Synology 公式</strong> の <a class="keyword" href="http://d.hatena.ne.jp/keyword/CSI">CSI</a> Driver(SynologyOpenSource/synology-<a class="keyword" href="http://d.hatena.ne.jp/keyword/csi">csi</a>)がリリースされていました。しかも Cloning や Snapshot featureにも対応。</p> <ul> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Access">Access</a> Modes: Read/Write Multiple <a class="keyword" href="http://d.hatena.ne.jp/keyword/Pods">Pods</a></li> <li>Cloning</li> <li>Expansion</li> <li>Snapshot</li> </ul> <p>そこで今回は公式の Synology <a class="keyword" href="http://d.hatena.ne.jp/keyword/CSI">CSI</a> Driver について紹介しようかと思います。</p> <h1>SynologyOpenSource/synology-<a class="keyword" href="http://d.hatena.ne.jp/keyword/csi">csi</a> の概要</h1> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/masaya_aoyama/20211130/20211130033952.png" alt="f:id:masaya_aoyama:20211130033952p:plain" width="1200" height="629" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p> <p>公式の Synology <a class="keyword" href="http://d.hatena.ne.jp/keyword/CSI">CSI</a> Driver では、事前に <a class="keyword" href="http://d.hatena.ne.jp/keyword/NAS">NAS</a> 側に複数の HDD/<a class="keyword" href="http://d.hatena.ne.jp/keyword/SSD">SSD</a> を束ねたストレージプールを定義し、Synology Volume を作成しておきます。 StorageClass は Synology Volume 単位で定義できるようになっているため、HDDと<a class="keyword" href="http://d.hatena.ne.jp/keyword/SSD">SSD</a>混在環境であれば、一つの筐体でも性能差のある複数の StorageClass を提供することができます。</p> <pre class="code lang-yaml" data-lang="yaml" data-unlink><span class="synIdentifier">apiVersion</span><span class="synSpecial">:</span> storage.k8s.io/v1 <span class="synIdentifier">kind</span><span class="synSpecial">:</span> StorageClass <span class="synIdentifier">metadata</span><span class="synSpecial">:</span> <span class="synIdentifier">name</span><span class="synSpecial">:</span> synology-iscsi-storage <span class="synIdentifier">parameters</span><span class="synSpecial">:</span> <span class="synIdentifier">location</span><span class="synSpecial">:</span> <span class="synConstant">'/volume1'</span> <span class="synIdentifier">fsType</span><span class="synSpecial">:</span> <span class="synConstant">'ext4'</span> <span class="synIdentifier">dsm</span><span class="synSpecial">:</span> <span class="synConstant">'xxx.xxx.xxx.xxx'</span> <span class="synIdentifier">reclaimPolicy</span><span class="synSpecial">:</span> Delete </pre> <p>その後、StorageClass を利用して Dynamic Provisioning されると、PV の単位で LUN が払い出されていきます。 そして、払い出された LUN は <a class="keyword" href="http://d.hatena.ne.jp/keyword/iSCSI">iSCSI</a> 経由でアタッチされ、ReadWriteOnceな状態で利用していきます。</p> <h1>Requirements 周りの話</h1> <h2><a class="keyword" href="http://d.hatena.ne.jp/keyword/DSM">DSM</a> の Requirements</h2> <p>Synology の <a class="keyword" href="http://d.hatena.ne.jp/keyword/NAS">NAS</a> には、<a class="keyword" href="http://d.hatena.ne.jp/keyword/DSM">DSM</a>(DiskStation Manager)という<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A5%DA%A5%EC%A1%BC%A5%C6%A5%A3%A5%F3%A5%B0%A5%B7%A5%B9%A5%C6%A5%E0">オペレーティングシステム</a>(兼 <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>)が搭載されています。 公式の SynologyOpenSource/synology-<a class="keyword" href="http://d.hatena.ne.jp/keyword/csi">csi</a> を利用するには、<a href="https://www.synology.com/ja-jp/releaseNote/DSM">2021年7月ごろにリリース</a> された<a class="keyword" href="http://d.hatena.ne.jp/keyword/DSM">DSM</a> 7.0系以降が必要です。</p> <h2><a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> の Requirements と v1.22 への対応</h2> <p>また、公式にサポートがアナウンスされている <a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> version は v1.19 までになっています。 私の <a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> 環境は最新の v1.22 ですが、下記の対応をすることで v1.22 でも動作確認済みです。</p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/CSI">CSI</a> attacher(external-attacher)が v2.1 系で古いため、VolumeAttachment リソースの <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a> Version が存在しない v1beta1 を参照している</p> <pre class="code" data-lang="" data-unlink>I1125 17:11:55.649047 1 reflector.go:188] Listing and watching *v1beta1.VolumeAttachment from k8s.io/client-go/informers/factory.go:135 E1125 17:11:55.650747 1 reflector.go:156] k8s.io/client-go/informers/factory.go:135: Failed to list *v1beta1.VolumeAttachment: the server could not find the requested resource</pre> <p><strong>=> 対応: <a class="keyword" href="http://d.hatena.ne.jp/keyword/CSI">CSI</a> attacher のバージョンを上げる(v2.1.0 > v3.3.0)</strong></p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/CSI">CSI</a> attacher v3.x 系から <a href="https://github.com/kubernetes-csi/external-attacher/commit/99562861df919f0220dd0a6a254d1864aa4c7abb">attach を行う reconcile 時にも volumeattachment/status patch リクエストが送られるようになり</a>、権限不足でエラーを返す</p> <pre class="code" data-lang="" data-unlink>I1125 17:19:16.077875 1 controller.go:208] Started VA processing &#34;csi-daee6d88cfec18e000fbc38dfa5326a180e73dd47bf62a63eca30a435852cdae&#34; I1125 17:19:16.077894 1 trivial_handler.go:53] Trivial sync[csi-daee6d88cfec18e000fbc38dfa5326a180e73dd47bf62a63eca30a435852cdae] started I1125 17:19:16.077914 1 util.go:38] Marking as attached &#34;csi-daee6d88cfec18e000fbc38dfa5326a180e73dd47bf62a63eca30a435852cdae&#34; W1125 17:19:16.083865 1 trivial_handler.go:57] Error saving VolumeAttachment csi-daee6d88cfec18e000fbc38dfa5326a180e73dd47bf62a63eca30a435852cdae as attached: volumeattachments.storage.k8s.io &#34;csi-daee6d88cfec18e000fbc38dfa5326a180e73dd47bf62a63eca30a435852cdae&#34; is forbidden: User &#34;system:serviceaccount: synology-csi:csi-controller-sa&#34; cannot patch resource &#34;volumeattachments/status&#34; in API group &#34;storage.k8s.io&#34; at the cluster scope</pre> <p><strong>=> 対応: volumeattachment/status への RBAC の権限を追加する</strong></p> <p>※ Status フィールド自体は <a href="https://github.com/kubernetes/api/blob/33e331166f19a8bbb7033171ece8d3a6d5c16f3c/storage/v1beta1/types.go#L192-L217">v1beta1</a> からももともと<a href="https://github.com/kubernetes/api/blob/33e331166f19a8bbb7033171ece8d3a6d5c16f3c/storage/v1beta1/types.go#L192-L217">利用</a>されていたため、そもそもvolumeattachment/status への権限は必要そう。<a href="https://github.com/SynologyOpenSource/synology-csi/pull/9">PR</a> も出されているのでいずれ修正予定。</p> <pre class="code lang-yaml" data-lang="yaml" data-unlink><span class="synComment"># kustomization.yaml</span> <span class="synIdentifier">patches</span><span class="synSpecial">:</span> <span class="synStatement">- </span>./patches.yaml <span class="synIdentifier">patchesJson6902</span><span class="synSpecial">:</span> <span class="synStatement">- </span><span class="synIdentifier">target</span><span class="synSpecial">:</span> <span class="synIdentifier">group</span><span class="synSpecial">:</span> rbac.authorization.k8s.io <span class="synIdentifier">version</span><span class="synSpecial">:</span> v1 <span class="synIdentifier">kind</span><span class="synSpecial">:</span> ClusterRole <span class="synIdentifier">name</span><span class="synSpecial">:</span> synology-csi-controller-role <span class="synIdentifier">patch</span><span class="synSpecial">:</span> |- <span class="synStatement">- </span><span class="synIdentifier">op</span><span class="synSpecial">:</span> add <span class="synIdentifier">path</span><span class="synSpecial">:</span> /rules/0 <span class="synIdentifier">value</span><span class="synSpecial">:</span> <span class="synSpecial">{</span><span class="synConstant">&quot;apiGroups&quot;</span><span class="synSpecial">:</span> <span class="synSpecial">[</span><span class="synConstant">&quot;storage.k8s.io&quot;</span><span class="synSpecial">]</span>, <span class="synConstant">&quot;resources&quot;</span><span class="synSpecial">:</span> <span class="synSpecial">[</span><span class="synConstant">&quot;volumeattachments/status&quot;</span><span class="synSpecial">]</span>, <span class="synConstant">&quot;verbs&quot;</span><span class="synSpecial">:</span> <span class="synSpecial">[</span><span class="synConstant">&quot;get&quot;</span>, <span class="synConstant">&quot;list&quot;</span>, <span class="synConstant">&quot;watch&quot;</span>, <span class="synConstant">&quot;update&quot;</span>, <span class="synConstant">&quot;patch&quot;</span><span class="synSpecial">]}</span> </pre> <pre class="code lang-yaml" data-lang="yaml" data-unlink><span class="synComment"># ./patches.yaml</span> <span class="synIdentifier">apiVersion</span><span class="synSpecial">:</span> apps/v1 <span class="synIdentifier">kind</span><span class="synSpecial">:</span> StatefulSet <span class="synIdentifier">metadata</span><span class="synSpecial">:</span> <span class="synIdentifier">name</span><span class="synSpecial">:</span> synology-csi-controller <span class="synIdentifier">namespace</span><span class="synSpecial">:</span> synology-csi <span class="synIdentifier">spec</span><span class="synSpecial">:</span> <span class="synIdentifier">template</span><span class="synSpecial">:</span> <span class="synIdentifier">spec</span><span class="synSpecial">:</span> <span class="synIdentifier">containers</span><span class="synSpecial">:</span> <span class="synStatement">- </span><span class="synIdentifier">name</span><span class="synSpecial">:</span> csi-attacher <span class="synIdentifier">image</span><span class="synSpecial">:</span> k8s.gcr.io/sig-storage/csi-attacher:v3.3.0 </pre> <h1>Volume の Cloning と Snapshot</h1> <p>SynologyOpenSource/synology-<a class="keyword" href="http://d.hatena.ne.jp/keyword/csi">csi</a> では、Cloning と Snapshot をサポートしています。</p> <p><strong>PVC 作成時に spec.dataSource に複製元 PVC を指定して、複製元の PVC をクローンして PVC 作成する</strong></p> <pre class="code lang-yaml" data-lang="yaml" data-unlink><span class="synIdentifier">kind</span><span class="synSpecial">:</span> PersistentVolumeClaim <span class="synIdentifier">spec</span><span class="synSpecial">:</span> <span class="synIdentifier">dataSource</span><span class="synSpecial">:</span> <span class="synIdentifier">kind</span><span class="synSpecial">:</span> PersistentVolumeClaim <span class="synIdentifier">name</span><span class="synSpecial">:</span> sample-pvc-dynamic </pre> <p><strong>PVC 作成時に spec.dataSource に Snapshot リソースを指定して、PVCを作成する</strong></p> <pre class="code lang-yaml" data-lang="yaml" data-unlink><span class="synIdentifier">kind</span><span class="synSpecial">:</span> VolumeSnapshot <span class="synIdentifier">metadata</span><span class="synSpecial">:</span> <span class="synIdentifier">name</span><span class="synSpecial">:</span> sample-volumesnapshot <span class="synIdentifier">spec</span><span class="synSpecial">:</span> <span class="synIdentifier">source</span><span class="synSpecial">:</span> <span class="synIdentifier">persistentVolumeClaimName</span><span class="synSpecial">:</span> sample-pvc <span class="synPreProc">---</span> <span class="synIdentifier">kind</span><span class="synSpecial">:</span> PersistentVolumeClaim <span class="synIdentifier">metadata</span><span class="synSpecial">:</span> <span class="synIdentifier">name</span><span class="synSpecial">:</span> sample-pvc-restored <span class="synIdentifier">spec</span><span class="synSpecial">:</span> <span class="synIdentifier">dataSource</span><span class="synSpecial">:</span> <span class="synIdentifier">kind</span><span class="synSpecial">:</span> VolumeSnapshot <span class="synIdentifier">name</span><span class="synSpecial">:</span> sample-volumesnapshot </pre> <p>今回はせっかくなので SynologyOpenSource/synology-<a class="keyword" href="http://d.hatena.ne.jp/keyword/csi">csi</a> を例に、<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSI">CSI</a> Driver の Cloning と Snapshot の実装を少し深ぼって紹介したいと思います。</p> <h2>Cloning の実装</h2> <p>Cloning の場合、PVCに指定された spec.dataSource の PVC の情報を元に、新たな PVC を作成します。 そのため、<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSI">CSI</a> Driver の Controller Plugin 側の CreateVolume() 関数に手を加えて実装していきます。 例えば SynologyOpenSource/synology-<a class="keyword" href="http://d.hatena.ne.jp/keyword/csi">csi</a> では、spec.dataSource に PVC が指定されていた場合には、その PVC の LUN を元に PV を生成するようになっています。</p> <pre class="code lang-go" data-lang="go" data-unlink><span class="synStatement">func</span> (cs *controllerServer) CreateVolume(ctx context.Context, req *csi.CreateVolumeRequest) (*csi.CreateVolumeResponse, <span class="synType">error</span>) { ...(省略)... <span class="synStatement">if</span> volContentSrc != <span class="synStatement">nil</span> { <span class="synStatement">if</span> srcVolume := volContentSrc.GetVolume(); srcVolume != <span class="synStatement">nil</span> { srcVolumeId = srcVolume.VolumeId } <span class="synStatement">else</span> { <span class="synStatement">return</span> <span class="synStatement">nil</span>, status.Errorf(codes.InvalidArgument, <span class="synConstant">&quot;Invalid volume content source&quot;</span>) } } ...(省略)... spec := &amp;models.CreateK8sVolumeSpec{ ...(省略)... SourceVolumeId: srcVolumeId, } lunInfo, dsmIp, err := cs.dsmService.CreateVolume(spec) ...(省略)... } <span class="synStatement">func</span> (service *DsmService) CreateVolume(spec *models.CreateK8sVolumeSpec) (webapi.LunInfo, <span class="synType">string</span>, <span class="synType">error</span>) { <span class="synStatement">if</span> spec.SourceVolumeId != <span class="synConstant">&quot;&quot;</span> { <span class="synComment">/* Create volume by exists volume (Clone) */</span> k8sVolume := service.GetVolume(spec.SourceVolumeId) <span class="synStatement">if</span> k8sVolume == <span class="synStatement">nil</span> { <span class="synStatement">return</span> webapi.LunInfo{}, <span class="synConstant">&quot;&quot;</span>, status.Errorf(codes.NotFound, fmt.Sprintf(<span class="synConstant">&quot;No such volume id: %s&quot;</span>, spec.SourceVolumeId)) } dsm, err := service.GetDsm(k8sVolume.DsmIp) <span class="synStatement">if</span> err != <span class="synStatement">nil</span> { <span class="synStatement">return</span> webapi.LunInfo{}, <span class="synConstant">&quot;&quot;</span>, status.Errorf(codes.Internal, fmt.Sprintf(<span class="synConstant">&quot;Failed to get DSM[%s]&quot;</span>, k8sVolume.DsmIp)) } lunInfo, err := service.createVolumeByVolume(dsm, spec, k8sVolume.Lun) <span class="synStatement">return</span> lunInfo, dsm.Ip, err } ...(省略)... } </pre> <p><a href="https://github.com/SynologyOpenSource/synology-csi/blob/release-v1.0.0/pkg/driver/controllerserver.go#L104-L133">synology-csi/controllerserver.go at release-v1.0.0 &middot; SynologyOpenSource/synology-csi &middot; GitHub</a></p> <p><a href="https://github.com/SynologyOpenSource/synology-csi/blob/release-v1.0.0/pkg/dsm/service/dsm.go#L375-L400">synology-csi/dsm.go at release-v1.0.0 &middot; SynologyOpenSource/synology-csi &middot; GitHub</a></p> <h2>Snapshot の実装</h2> <p>Snapshot の実装は、大きく分けて Snapshot と Restore の 2 つのパートに分かれています。</p> <h3>Snapshot</h3> <p>VolumeSnapshot リソースでスナップショットを管理する機能を実装するには、<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSI">CSI</a> Driver の Controller Plugin 側に CreateSnapshot()・DeleteSnapshot()・ListSnapshot() の 3 つの関数を実装する必要があります。ストレージバックエンド側でボリュームやスナップショットを生成すればよいため、Node Plugin 側の実装はありません。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgithub.com%2Fcontainer-storage-interface%2Fspec%2Fblob%2Fmaster%2Fspec.md" title="spec/spec.md at master · container-storage-interface/spec" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://github.com/container-storage-interface/spec/blob/master/spec.md">github.com</a></cite></p> <p>例えば SynologyOpenSource/synology-<a class="keyword" href="http://d.hatena.ne.jp/keyword/csi">csi</a> では、CreateSnapshot()関数で VolumeSnapshotリソースに指定されている PVC の情報を元に、LUNに対してスナップショットを生成しています。</p> <p><a href="https://github.com/SynologyOpenSource/synology-csi/blob/release-v1.0.0/pkg/driver/controllerserver.go#L291-L464">synology-csi/controllerserver.go at release-v1.0.0 &middot; SynologyOpenSource/synology-csi &middot; GitHub</a></p> <h3>Restore</h3> <p>Restore 部分は、Cloning と同様に spec.volumeSource に Snapshot が指定された場合の処理を実装することを意味します。 そのため、<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSI">CSI</a> Driver の Controller Plugin 側の CreateVolume 関数に手を加えていきます。 例えば SynologyOpenSource/synology-<a class="keyword" href="http://d.hatena.ne.jp/keyword/csi">csi</a> では、spec.dataSource に VolumeSnapshot リソースが指定されていた場合には、その VolumeSnapshot が紐付いているスナップショットを元に PV を生成するようになっています。</p> <pre class="code lang-go" data-lang="go" data-unlink><span class="synStatement">func</span> (cs *controllerServer) CreateVolume(ctx context.Context, req *csi.CreateVolumeRequest) (*csi.CreateVolumeResponse, <span class="synType">error</span>) { ...(省略)... <span class="synStatement">if</span> volContentSrc != <span class="synStatement">nil</span> { <span class="synStatement">if</span> srcSnapshot := volContentSrc.GetSnapshot(); srcSnapshot != <span class="synStatement">nil</span> { srcSnapshotId = srcSnapshot.SnapshotId } <span class="synStatement">else</span> <span class="synStatement">if</span> srcVolume := volContentSrc.GetVolume(); srcVolume != <span class="synStatement">nil</span> { srcVolumeId = srcVolume.VolumeId } <span class="synStatement">else</span> { <span class="synStatement">return</span> <span class="synStatement">nil</span>, status.Errorf(codes.InvalidArgument, <span class="synConstant">&quot;Invalid volume content source&quot;</span>) } } ...(省略)... spec := &amp;models.CreateK8sVolumeSpec{ ...(省略)... SourceSnapshotId: srcSnapshotId, SourceVolumeId: srcVolumeId, } lunInfo, dsmIp, err := cs.dsmService.CreateVolume(spec) ...(省略)... } <span class="synStatement">func</span> (service *DsmService) CreateVolume(spec *models.CreateK8sVolumeSpec) (webapi.LunInfo, <span class="synType">string</span>, <span class="synType">error</span>) { <span class="synStatement">if</span> spec.SourceSnapshotId != <span class="synConstant">&quot;&quot;</span> { <span class="synComment">/* Create volume by snapshot */</span> <span class="synStatement">for</span> _, dsm := <span class="synStatement">range</span> service.dsms { snapshotInfo, err := dsm.SnapshotGet(spec.SourceSnapshotId) <span class="synStatement">if</span> err != <span class="synStatement">nil</span> { <span class="synStatement">continue</span> } lunInfo, err := service.createVolumeBySnapshot(dsm, spec, snapshotInfo) <span class="synStatement">return</span> lunInfo, dsm.Ip, err } <span class="synStatement">return</span> webapi.LunInfo{}, <span class="synConstant">&quot;&quot;</span>, status.Errorf(codes.NotFound, fmt.Sprintf(<span class="synConstant">&quot;No such snapshot id: %s&quot;</span>, spec.SourceSnapshotId)) } ...(省略)... } </pre> <p><a href="https://github.com/SynologyOpenSource/synology-csi/blob/release-v1.0.0/pkg/driver/controllerserver.go#L104-L133">synology-csi/controllerserver.go at release-v1.0.0 &middot; SynologyOpenSource/synology-csi &middot; GitHub</a></p> <p><a href="https://github.com/SynologyOpenSource/synology-csi/blob/release-v1.0.0/pkg/dsm/service/dsm.go#L375-L400">synology-csi/dsm.go at release-v1.0.0 &middot; SynologyOpenSource/synology-csi &middot; GitHub</a></p> <h2>実装関連の参考情報</h2> <ul> <li><p><a class="keyword" href="http://d.hatena.ne.jp/keyword/DSM">DSM</a> <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a> 操作関連の関数</p> <ul> <li><a href="https://github.com/SynologyOpenSource/synology-csi/tree/main/pkg/dsm/webapi">synology-csi/pkg/dsm/webapi at main &middot; SynologyOpenSource/synology-csi &middot; GitHub</a></li> </ul> </li> <li><p>Controller Server</p> <ul> <li><a href="https://github.com/SynologyOpenSource/synology-csi/blob/main/pkg/driver/controllerserver.go">synology-csi/controllerserver.go at main &middot; SynologyOpenSource/synology-csi &middot; GitHub</a></li> </ul> </li> <li><p>Node Server</p> <ul> <li><a href="https://github.com/SynologyOpenSource/synology-csi/blob/main/pkg/driver/nodeserver.go">synology-csi/nodeserver.go at main &middot; SynologyOpenSource/synology-csi &middot; GitHub</a></li> </ul> </li> </ul> <h1>Future work</h1> <p>今回公開された Synology <a class="keyword" href="http://d.hatena.ne.jp/keyword/CSI">CSI</a> Driver でサポートしているのは SAN 向けの機能です。 NetApp Trident のように ReadWriteMany 向けの Dynamic Provisioning も Synology の Shared folder の機能を使いつつ実装できると、更に<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E6%A1%BC%A5%B9%A5%B1%A1%BC%A5%B9">ユースケース</a>が広がりそうですね。</p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BD%A1%BC%A5%B9%A5%B3%A1%BC%A5%C9">ソースコード</a>を見てる範囲では、Shared folder 用の <a class="keyword" href="http://d.hatena.ne.jp/keyword/DSM">DSM</a> <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a> を操作する関数は用意されているが使われていない状態だったので、将来的にはサポートされるかもしれません。 12月に手が空けば、実装しつつ、別日の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%C9%A5%D9%A5%F3%A5%C8%A5%AB%A5%EC%A5%F3%A5%C0%A1%BC">アドベントカレンダー</a>でも書こうかと思います。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgithub.com%2FSynologyOpenSource%2Fsynology-csi%2Fblob%2Frelease-v1.0.0%2Fpkg%2Fdsm%2Fwebapi%2Fshare.go" title="synology-csi/share.go at release-v1.0.0 · SynologyOpenSource/synology-csi" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://github.com/SynologyOpenSource/synology-csi/blob/release-v1.0.0/pkg/dsm/webapi/share.go">github.com</a></cite></p> <h1>まとめ</h1> <p>あんまり特出して書くことがない程度には完成度が高い状態でした。 Synology <a class="keyword" href="http://d.hatena.ne.jp/keyword/CSI">CSI</a> Driver を利用することで、箱物ストレージを簡単に得ることができるのでロマンがあります。</p> <p>また、Stateful なアプリケーションを <a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> で運用していく場合、Snapshot の <a class="keyword" href="http://d.hatena.ne.jp/keyword/CSI">CSI</a> Features を利用したくなったり、エコシステムによってはこの機能自体が必要なケースも出てくるかと思います。その点では、今回公開された公式の Synology <a class="keyword" href="http://d.hatena.ne.jp/keyword/CSI">CSI</a> Driver は多くの機能がサポートされているため、検証用途にはとても十分です。</p> <p>余談ですが、<a href="https://www.synology.com/ja-jp/products/series/enthusiast">Synology の公式サイト</a>には、「個人向け」「中小企業向け」以外にも、「<strong>IT 愛好家</strong>」向けの項目があって好感が持てます。いわゆる <strong>逸般の誤家庭</strong> 向けってやつですね。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/masaya_aoyama/20201201/20201201085133.png" alt="f:id:masaya_aoyama:20201201085133p:plain" width="719" height="275" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p> <p><strong>逸般の誤家庭</strong> な皆さん、年末年始は Synology <a class="keyword" href="http://d.hatena.ne.jp/keyword/CSI">CSI</a> Driver を整備して、ぜひ楽しんでみてはいかがでしょうか。</p> <p>以上、青山(<a href="https://twitter.com/amsy810">@amsy810</a>)からでした〜</p> masaya_aoyama おうち Kubernetes 向けに Synology CSI Driver に VolumeExpansion を実装した話 hatenablog://entry/26006613658787663 2020-12-01T08:00:00+09:00 2020-12-01T09:00:31+09:00 こんにちは。 青山(amsy810 )です。 この記事は Kubernetes Advent Calendar の 1 日目の記事です。 いよいよアドベントカレンダーが始まりましたね。1か月間わいわいしていきましょう! どこかの誰かに実装系の記事のほうが面白いよねってフリをされたので、今年は Synology CSI Driver に VolumeExpansion を実装しつつ、内部実装の紹介 をします。 VolumeExpansion は 1日あれば実装が終わるくらいの規模感でした。 おうち Kubernetes みなさんのおうちの Kubernetes はどこにありますか? ちなみに私は… <p>こんにちは。 青山(<a href="https://twitter.com/amsy810">amsy810</a> )です。</p> <p>この記事は <a href="https://qiita.com/advent-calendar/2020/kubernetes">Kubernetes Advent Calendar</a> の 1 日目の記事です。</p> <p>いよいよ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%C9%A5%D9%A5%F3%A5%C8%A5%AB%A5%EC%A5%F3%A5%C0%A1%BC">アドベントカレンダー</a>が始まりましたね。1か月間わいわいしていきましょう!</p> <p>どこかの誰かに実装系の記事のほうが面白いよねってフリをされたので、今年は <strong>Synology <a class="keyword" href="http://d.hatena.ne.jp/keyword/CSI">CSI</a> Driver に <a href="https://github.com/jparklab/synology-csi/pull/46">VolumeExpansion を実装</a>しつつ、内部実装の紹介</strong> をします。 VolumeExpansion は 1日あれば実装が終わるくらいの規模感でした。</p> <h1>おうち <a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a></h1> <p>みなさんのおうちの <a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> はどこにありますか? ちなみに私は下駄箱にあります。下駄箱DC。上流スイッチもここに集約されています。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/masaya_aoyama/20201130/20201130210026.jpg" alt="f:id:masaya_aoyama:20201130210026j:plain" title="" class="hatena-fotolife" itemprop="image"></span></p> <p>そして皆さんストレージはどうしてますか? hostPath や Local PV で我慢してる人がいたり、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Longhorn">Longhorn</a> や Rook/Ceph で分散ストレージを組んでいる人もいるかと思います。 我が家では Synology の <a class="keyword" href="http://d.hatena.ne.jp/keyword/NAS">NAS</a> をストレージバックエンドとして使っています。つまり、自宅に安価に箱物ストレージがある気分に浸れるのです。 (写真で青色 LED が光っているのが筐体です。オールフラッシュかつ、<a class="keyword" href="http://d.hatena.ne.jp/keyword/UPS">UPS</a> につないで可愛がってます。)</p> <p>余談ですが、<a href="https://www.synology.com/ja-jp/products/series/enthusiast">Synology の公式サイト</a>には、「個人向け」「中小企業向け」以外にも、「<strong>IT 愛好家</strong>」向けの項目があって好感が持てます。いわゆる <strong>逸般の誤家庭</strong> 向けってやつですね。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/masaya_aoyama/20201201/20201201085133.png" alt="f:id:masaya_aoyama:20201201085133p:plain" title="" class="hatena-fotolife" itemprop="image"></span></p> <h1>Synology <a class="keyword" href="http://d.hatena.ne.jp/keyword/CSI">CSI</a> Driver</h1> <p>昨今はコンテナオーケストレーターとストレージ機器の連携には、<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSI">CSI</a>(Container Storage Interface)を介して行われるのが一般的です。 有志によって Synology の <a class="keyword" href="http://d.hatena.ne.jp/keyword/NAS">NAS</a> 向けの <a class="keyword" href="http://d.hatena.ne.jp/keyword/CSI">CSI</a> Driver が公開されています。つまり、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> から Synology の <a class="keyword" href="http://d.hatena.ne.jp/keyword/NAS">NAS</a> をバックエンドとして利用することができるようになっています。なお、<a class="keyword" href="http://d.hatena.ne.jp/keyword/iSCSI">iSCSI</a> でのブロックデ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A5%A4%A5%B9">バイス</a>のボリュームマウントに対応しています。ReadWriteMany で利用したい場合は、別途 <a class="keyword" href="http://d.hatena.ne.jp/keyword/NFS">NFS</a> マウントなどを検討してください。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgithub.com%2Fjparklab%2Fsynology-csi" title="jparklab/synology-csi" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://github.com/jparklab/synology-csi">github.com</a></cite></p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/CSI">CSI</a> の Document にも、Sample Drivers として取り上げられています。この Driver は Synology 社に公式サポートされているものではなく、非公式な Driver なので商用での利用などは注意したほうが良いでしょう。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fkubernetes-csi.github.io%2Fdocs%2Fdrivers.html" title="Drivers - Kubernetes CSI Developer Documentation" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://kubernetes-csi.github.io/docs/drivers.html">kubernetes-csi.github.io</a></cite></p> <p>Synology <a class="keyword" href="http://d.hatena.ne.jp/keyword/CSI">CSI</a> Driver では、Synology の Volume(複数の物理 Disk を束ねた StoragePool を論理的に切り出したもの)単位で StorageClass を切って使うようになっています。そのため、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> 向けと自宅向けに分けて使うこともできます。</p> <pre class="code YAML" data-lang="YAML" data-unlink>apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: annotations: # set this to false if you do not want this storage class to be default storageclass.kubernetes.io/is-default-class: &#34;true&#34; name: synology-iscsi-storage provisioner: csi.synology.com parameters: location: &#39;/volume1&#39; # ここに Kubernetes 向けに切った Volume を指定する type: &#39;BLUN&#39; reclaimPolicy: Retain allowVolumeExpansion: true</pre> <h1><a class="keyword" href="http://d.hatena.ne.jp/keyword/CSI">CSI</a> Driver ことはじめ</h1> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/CSI">CSI</a> Driver では <code>Controller Plugin</code> と <code>Node Plugin</code> の 2 つの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%DD%A1%BC%A5%CD%A5%F3%A5%C8">コンポーネント</a>があります。Controller Plugin はコンテナオーケストレーターで 1 つ、Node Plugin は各ノードに 1 つ起動します。<a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> の場合は、Controller Plugin は StatefulSet、Node Plugin は DaemonSet で起動させることが多くなっています。Controller Plugin はどこで実行可能な処理を、Node Plugin は各ノード上で直接実行する必要があるマウントなどの処理を担当します。</p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/CSI">CSI</a> には仕様があり、ボリューム作成時やアタッチ時のライフサイクルや、RPCで呼ばれる関数が取り決められています。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgithub.com%2Fcontainer-storage-interface%2Fspec%2Fblob%2Fmaster%2Fspec.md" title="container-storage-interface/spec" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://github.com/container-storage-interface/spec/blob/master/spec.md">github.com</a></cite></p> <p>例えば、Volume が Dynamic Provisioning でデプロイされ、Pod が起動する際の最低限の実装は下記のとおりです。リク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>トが発行されると、<code>CreateVolume()</code> によりボリュームが作成されます。その後、<code>ControllerPublishVolume()</code> によりノードに対してボリュームをアタッチし、<code>NodePublishVolume()</code> によりノードでアタッチされたボリュームをマウントする流れになっています。削除する際には、逆の順番で行われていきます。</p> <p>CreateVolume() は Controller Plugin 側で処理を行います。ControllerPublishVolume() と NodePublishVolume() はそれぞれ Controller Plugin と Node Plugin 用に用意されており、それぞれで実行します。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/masaya_aoyama/20201201/20201201055115.png" alt="f:id:masaya_aoyama:20201201055115p:plain" title="" class="hatena-fotolife" itemprop="image"></span></p> <p>(なお、いくつかの <a class="keyword" href="http://d.hatena.ne.jp/keyword/CSI">CSI</a> Driver の実装を眺めてみましたが、実際に各関数で行われている処理は Driver によってまちまちだったので注意が必要そうです。ボリュームをノードで使えるようにするまでに、Controller側での処理とNode側での処理の2つがあると考えておくと良いでしょう。)</p> <p>Synology <a class="keyword" href="http://d.hatena.ne.jp/keyword/CSI">CSI</a> Driver では、Dynamic Provisioningされた Volume は LUN として払い出されます。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/masaya_aoyama/20201201/20201201070310.png" alt="f:id:masaya_aoyama:20201201070310p:plain" title="" class="hatena-fotolife" itemprop="image"></span></p> <h1>VolumeExpansion の実装について</h1> <p>さて、本題です。 ボリューム拡張には、<code>ControllerExpandVolume()</code> と <code>NodeExpandVolume()</code> の 2つの Interface を利用します。Synology <a class="keyword" href="http://d.hatena.ne.jp/keyword/CSI">CSI</a> Driver ではこれら2つの関数が用意されていないため、実装する必要があります。</p> <p>大まかには、ControllerExpandVolume() ではストレージバックエンドにボリューム自体の拡張を行うリク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>トを行い、NodeExpandVolume() ではアタッチされたボリュームの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D5%A5%A1%A5%A4%A5%EB%A5%B7%A5%B9%A5%C6%A5%E0">ファイルシステム</a>の拡張を行います。</p> <p>Synology <a class="keyword" href="http://d.hatena.ne.jp/keyword/CSI">CSI</a> Driver の場合、ControllerExpandVolume() では Synology の <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a> を叩いて LUN の拡張を行います。 <a href="https://github.com/jparklab/synology-csi/pull/46/files#diff-80793083e0532aa32cf03aecc5ee3efefced14c5b0d7af3ca7cfc0b03e2b9af8R58-R124">https://github.com/jparklab/synology-csi/pull/46/files#diff-80793083e0532aa32cf03aecc5ee3efefced14c5b0d7af3ca7cfc0b03e2b9af8R58-R124</a></p> <p>この実装のみを入れた状態で LUN を 10GB から 15GB に拡張後にノード側でブロックデ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A5%A4%A5%B9">バイス</a>の情報を見てみると、拡張された値になっていません。</p> <pre class="code" data-lang="" data-unlink>root@k8s1:/# fdisk -l | grep sdb Disk /dev/sdb: 10 GiB, 10737418240 bytes, 20971520 sectors</pre> <p>ただ LUN を拡張しただけではブロックデ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A5%A4%A5%B9">バイス</a>の拡張を検知できていないため、NodeExpandVolume() で <a href="https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/7/html/storage_administration_guide/online-iscsi-resizing">rescan</a> パスに対して書き込みを行い検知するようにします。こういった各ノード上で実行しなければならない処理のために、Controller Plugin と Node Plugin は別れています。 <a href="https://github.com/jparklab/synology-csi/pull/46/files#diff-4ff8ed7064d3ab0eae29d29d061a7a0799a0b630a9a5c76d6ab2bb333bef7124R307-R332">https://github.com/jparklab/synology-csi/pull/46/files#diff-4ff8ed7064d3ab0eae29d29d061a7a0799a0b630a9a5c76d6ab2bb333bef7124R307-R332</a></p> <p>OpenStack Cinder <a class="keyword" href="http://d.hatena.ne.jp/keyword/CSI">CSI</a> などでも rescan パスに対して<a href="https://github.com/kubernetes/cloud-provider-openstack/blob/2493d936afe901a63066e4506dcfa716f1d96dc9/pkg/util/blockdevice/blockdevice_linux.go#L111">書き込み</a>を行い、変更を検知する実装になっています。</p> <pre class="code" data-lang="" data-unlink># 手動で実行した場合の例 root@k8s1:/# echo 1 &gt; /sys/block/sdb/device/rescan root@k8s1:/# fdisk -l | grep sdb Disk /dev/sdb: 15 GiB, 16106127360 bytes, 31457280 sectors</pre> <p>ブロックデ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A5%A4%A5%B9">バイス</a>拡張後には、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D5%A5%A1%A5%A4%A5%EB%A5%B7%A5%B9%A5%C6%A5%E0">ファイルシステム</a>の拡張を行う必要があります。これも NodeExpandVolume() 側で行います。 <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D5%A5%A1%A5%A4%A5%EB%A5%B7%A5%B9%A5%C6%A5%E0">ファイルシステム</a>の拡張には、"<a class="keyword" href="http://d.hatena.ne.jp/keyword/k8s">k8s</a>.io/<a class="keyword" href="http://d.hatena.ne.jp/keyword/kubernetes">kubernetes</a>/pkg/util/resizefs" パッケージが利用できます。 <a href="https://github.com/jparklab/synology-csi/pull/46/files#diff-4ff8ed7064d3ab0eae29d29d061a7a0799a0b630a9a5c76d6ab2bb333bef7124R334-R338">https://github.com/jparklab/synology-csi/pull/46/files#diff-4ff8ed7064d3ab0eae29d29d061a7a0799a0b630a9a5c76d6ab2bb333bef7124R334-R338</a></p> <p>このパッケージでは、内部的には resize2fs や xfs_growfs をコマンド実行で呼び出しているだけなので、Node Plugin のプログラムを実行する環境にはこれらのコマンドが必要です。 <a href="https://github.com/kubernetes/kubernetes/blob/master/pkg/util/resizefs/resizefs_linux.go#L29">https://github.com/kubernetes/kubernetes/blob/master/pkg/util/resizefs/resizefs_linux.go#L29</a></p> <p>なお、このパッケージを使わずに、resize2fs や xfs_growfs を直接使っている <a class="keyword" href="http://d.hatena.ne.jp/keyword/CSI">CSI</a> 実装もありました。 思ったよりかは愚直な実装なのは少し意外でした。</p> <p>今回のように Controller Plugin の処理のあとに Node Plugin 側でも Rescan や Filesystem の拡張などの処理が必要な場合、ControllerExpandVolumeResponse を返す際に NodeExpansionRequired=true で返してあげてください。 <a href="https://github.com/jparklab/synology-csi/pull/46/files#diff-80793083e0532aa32cf03aecc5ee3efefced14c5b0d7af3ca7cfc0b03e2b9af8R121-R124">https://github.com/jparklab/synology-csi/pull/46/files#diff-80793083e0532aa32cf03aecc5ee3efefced14c5b0d7af3ca7cfc0b03e2b9af8R121-R124</a></p> <p>これだけでは実は動きません。最後に、この <a class="keyword" href="http://d.hatena.ne.jp/keyword/CSI">CSI</a> が VolumeExpansion に対応していることを示すように、Capabilities として登録しておく必要があります。</p> <p><a href="https://github.com/jparklab/synology-csi/pull/46/files#diff-e8a7e777d80a14b455bdbf7aae3f28ad8082ffa0a06579e11cc1af741b5f98f7R95">https://github.com/jparklab/synology-csi/pull/46/files#diff-e8a7e777d80a14b455bdbf7aae3f28ad8082ffa0a06579e11cc1af741b5f98f7R95</a> <a href="https://github.com/jparklab/synology-csi/pull/46/files#diff-4ff8ed7064d3ab0eae29d29d061a7a0799a0b630a9a5c76d6ab2bb333bef7124R369-R388">https://github.com/jparklab/synology-csi/pull/46/files#diff-4ff8ed7064d3ab0eae29d29d061a7a0799a0b630a9a5c76d6ab2bb333bef7124R369-R388</a></p> <h1>Synology <a class="keyword" href="http://d.hatena.ne.jp/keyword/CSI">CSI</a> Driver の TODO</h1> <p>VolumeExpansion の後といえば、Snapshot の実装もしたいなと思っています。 Synology は Snapshot にも対応しているため、<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSI">CSI</a> 側に実装をいれることで使えるようになる見込みです。</p> <p>また、現在は <a class="keyword" href="http://d.hatena.ne.jp/keyword/iSCSI">iSCSI</a> を使った ReadWriteOnce なマウントのみサポートしていますが、共有フォルダ機能を使って ReadWriteMany な Dynamic Provisioning もサポートしたいなとも思っています。</p> <p>また、今回の実装とは関係ありませんが、Synology <a class="keyword" href="http://d.hatena.ne.jp/keyword/CSI">CSI</a> Driver を見ていていくつか修正したほうが良さそうな点がありました。 1つ目に、<a class="keyword" href="http://d.hatena.ne.jp/keyword/iSCSI">iSCSI</a> Target が消えないときがあるようなのでその辺りも考慮した実装にする必要があります。 2つ目に、各 <a class="keyword" href="http://d.hatena.ne.jp/keyword/csi">csi</a>-provisioner や <a class="keyword" href="http://d.hatena.ne.jp/keyword/csi">csi</a>-resizer 単位で Pod が作られているため、sidecar をまとめた Pod にしたほうが良さそうです。</p> <p>この辺りも暇を見つけて実装できたらと思います。</p> <h1>まとめ</h1> <p>今回は <a class="keyword" href="http://d.hatena.ne.jp/keyword/CSI">CSI</a> の VolumeExpansion の実装について紹介しましたがいかがでしたか?</p> <p>また、おうち <a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> がある方は、Synology の <a class="keyword" href="http://d.hatena.ne.jp/keyword/NAS">NAS</a> と Synology <a class="keyword" href="http://d.hatena.ne.jp/keyword/CSI">CSI</a> Driver を使って、更に快適な環境にしてみてはいかがでしょうか?</p> <h1>参考:Synology <a class="keyword" href="http://d.hatena.ne.jp/keyword/NAS">NAS</a> について</h1> <p>Synology の <a class="keyword" href="http://d.hatena.ne.jp/keyword/NAS">NAS</a> は、<a class="keyword" href="http://d.hatena.ne.jp/keyword/NFS">NFS</a> や CIFS など様々な<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D7%A5%ED%A5%C8%A5%B3%A5%EB">プロトコル</a>をしゃべることができます。 我が家ではメディア系のファイルや PDF ファイルなどが保存されており、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Mac">Mac</a>・<a class="keyword" href="http://d.hatena.ne.jp/keyword/iPad">iPad</a>・<a class="keyword" href="http://d.hatena.ne.jp/keyword/iPhone">iPhone</a> などからいつでもアクセスできるようにしてあります。</p> <p>また、Synology の <a class="keyword" href="http://d.hatena.ne.jp/keyword/NAS">NAS</a> には、10G <a class="keyword" href="http://d.hatena.ne.jp/keyword/NIC">NIC</a> がついたモデルとついていないモデルの 2 つがあります。 私が購入した DS620Slim は 10G <a class="keyword" href="http://d.hatena.ne.jp/keyword/NIC">NIC</a> がついていないモデルで、1G * 2 の <a class="keyword" href="http://d.hatena.ne.jp/keyword/NIC">NIC</a> がついています。250 MB/s 程度までしか<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%EB%A1%BC%A5%D7%A5%C3%A5%C8">スループット</a>はでませんが、DS620Slim はその名の通りかなりコンパクトな筐体に 2.5 inch disk が 6 本まで刺さるので、かなり集約率は高い筐体です。 対向の Switch 側が対応していれば Bonding にも対応しているようですが、今回はそれぞれが影響しあわないように「おうち <a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> が <a class="keyword" href="http://d.hatena.ne.jp/keyword/CSI">CSI</a> 経由で使う <a class="keyword" href="http://d.hatena.ne.jp/keyword/NIC">NIC</a>」と「<a class="keyword" href="http://d.hatena.ne.jp/keyword/NFS">NFS</a> などで各種デ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A5%A4%A5%B9">バイス</a>から接続する <a class="keyword" href="http://d.hatena.ne.jp/keyword/NIC">NIC</a>」 で分けています。</p> <p>また、Synology 独自の <a class="keyword" href="http://d.hatena.ne.jp/keyword/RAID">RAID</a> (Synology Hybrid <a class="keyword" href="http://d.hatena.ne.jp/keyword/RAID">RAID</a>)では 1本〜6本まで順に増やしていくことが可能なため、スモールスタートするにはうってつけです。 またディスクサイズが揃っていなくてもチャンクに分割することで最大限ディスクを使えるような仕組みになっています。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.synology.com%2Fen-uk%2Fknowledgebase%2FDSM%2Ftutorial%2FStorage%2FWhat_is_Synology_Hybrid_RAID_SHR" title="DiskStation Manager - Knowledge Base | Synology Inc." class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://www.synology.com/en-uk/knowledgebase/DSM/tutorial/Storage/What_is_Synology_Hybrid_RAID_SHR">www.synology.com</a></cite></p> <h1>参考:Synology <a class="keyword" href="http://d.hatena.ne.jp/keyword/CSI">CSI</a> Driver の <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a> について</h1> <p>Synology <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a> に接続するためのコードは Synology <a class="keyword" href="http://d.hatena.ne.jp/keyword/CSI">CSI</a> Driver の pkg/synology/<a class="keyword" href="http://d.hatena.ne.jp/keyword/api">api</a>/ 以下にLUN、Target、Volume を操作するための <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a> が用意されています。ここでいう Volume は Synology の Volume(/Volume1 など)を指しています。</p> <ul> <li><a href="https://github.com/jparklab/synology-csi/blob/master/pkg/synology/api/iscsi/lun.go">pkg/synology/api/iscsi/lun</a></li> <li><a href="https://github.com/jparklab/synology-csi/blob/master/pkg/synology/api/iscsi/target.go">pkg/synology/api/iscsi/target</a></li> <li><a href="https://github.com/jparklab/synology-csi/blob/master/pkg/synology/api/storage/volume.go">pkg/synology/api/storage/volume</a></li> </ul> <p>なお、現状の Synology <a class="keyword" href="http://d.hatena.ne.jp/keyword/CSI">CSI</a> Driver に必要な部分しか実装されていないため、ボリューム拡張用に <a href="https://github.com/jparklab/synology-csi/pull/46/files#diff-5a37ab95b39ee25c626cd176f23debaa96e82ad3d64c28cab039c5e0f849d3f3R223-R235">LUN API に Update() 関数</a>を生やしています。</p> masaya_aoyama Kubernetesにおけるマルチクラスタ関連手法の分類 hatenablog://entry/26006613585609781 2020-06-17T09:00:00+09:00 2020-06-17T19:11:04+09:00 こんにちは。青山(amsy810)です。 Kubernetesには複数のクラスタを扱うための技術がいくつかあります。 今回は幾つかのパターンに分けて紹介していきたいと思います。 また、将来的にこうなったら面白いかもという話をするために、すぐにプロダクション利用できない話やWebサービスでは使わないような話も含まれています。 【目次】 複数クラスタを利用する理由 複数クラスタを管理するパターン GitOpsで複数クラスタを管理するパターン 複数のKubernetesクラスタをFederateするパターン Virtual kubeletパターン マルチクラスタ時のロードバランサの扱い LoadBa… <p>こんにちは。青山(<a href="https://twitter.com/amsy810">amsy810</a>)です。</p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a>には複数の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>を扱うための技術がいくつかあります。 今回は幾つかのパターンに分けて紹介していきたいと思います。 また、将来的にこうなったら面白いかもという話をするために、すぐにプロダクション利用できない話や<a class="keyword" href="http://d.hatena.ne.jp/keyword/Web%A5%B5%A1%BC%A5%D3%A5%B9">Webサービス</a>では使わないような話も含まれています。</p> <p>【目次】</p> <ul> <li>複数<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>を利用する理由</li> <li>複数<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>を管理するパターン <ol> <li> GitOpsで複数<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>を管理するパターン</li> <li> 複数の<a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>をFederateするパターン</li> <li> Virtual kubeletパターン</li> </ol> </li> <li>マルチ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>時のロードバランサの扱い <ol> <li> LoadBalancer の機能を利用して分散する</li> <li> <a class="keyword" href="http://d.hatena.ne.jp/keyword/DNS">DNS</a> を利用して分散する</li> <li> Multi Cluster にまたがる Service Mesh を利用して転送する</li> </ol> </li> <li>マルチ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>でPod Networkを繋ぐ</li> <li>ストレージの扱い</li> <li>マルチテ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%CA%A5%F3%A5%B7%A1%BC%B4%D8">ナンシー関</a>連の技術</li> <li>超個体型データセンターへの応用</li> </ul> <h1>複数<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>を利用する理由</h1> <p>複数<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>で構成するには下記のような理由があるのではないでしょうか。 何がしたいかによっては、選択できる手法も限られてくるでしょう。</p> <ul> <li>耐障害性、信頼性向上、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%B6%A5%B9%A5%BF%A5%EA%A5%AB%A5%D0%A5%EA">ディザスタリカバリ</a></li> <li>マルチ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%A6%A5%C9">クラウド</a>・ハイブリッド<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%A6%A5%C9">クラウド</a>対応</li> <li>ジオロケーションによるパフォーマンス問題の解消</li> <li>機密データのローカリティを確保する</li> <li>In-place <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>アップグレードを避ける</li> <li>スケーラビリティの確保</li> <li>エッジ・フォグ環境に適用する</li> </ul> <p>北山さんがマルチ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>のメリット・デメリットでおすすめの<a href="https://learnk8s.io/how-many-clusters">記事</a>をツイートしていたので、こちらもメモしておきます。</p> <h1>複数<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>を管理するパターン</h1> <p>複数<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>を管理する方法は主に3つあります。</p> <h2>1. GitOpsで複数<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>を管理するパターン</h2> <p>GitOpsでは、Git<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%DD%A5%B8%A5%C8%A5%EA">リポジトリ</a>に保存された<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%CB%A5%D5%A5%A7%A5%B9%A5%C8">マニフェスト</a>ファイルを<a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>に対して同期することで<a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>の管理を行います。 この時に、同じ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%DD%A5%B8%A5%C8%A5%EA">リポジトリ</a>を参照することで同等の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>を作成することができます。 また、ArgoCD では Kustomize や Helm と連携することができるため、レプリカ数や一部の設定を変更したり、一部のマイクロサービスだけデプロイするといった選択をすることも可能です。</p> <p>現状プロダクションで利用するとなると、GitOpsで複数の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>に対して<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%CB%A5%D5%A5%A7%A5%B9%A5%C8">マニフェスト</a>を適用する方法を取ることが多いでしょう。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/masaya_aoyama/20200616/20200616235216.png" alt="f:id:masaya_aoyama:20200616235216p:plain" title="f:id:masaya_aoyama:20200616235216p:plain" class="hatena-fotolife" itemprop="image"></span></p> <h2>2. 複数の<a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>をFederateするパターン</h2> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a>には、複数の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>を束ねて管理する <a href="https://github.com/kubernetes-sigs/kubefed">Federation v2</a> の開発が <a href="https://github.com/kubernetes/community/tree/master/sig-multicluster">SIG-MultiClsuter</a> によって進められています。 Federation v2では、マネジメント<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>が複数のターゲット<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>を管理する形になります。 マネジメント<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>に対して、FederatedDeploymentやFederatedServiceなどのリソースを作成すると、複数のターゲット<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>にDeploymentやServiceが作成されるようになっています。 また、CustomResoruceなどもFederetadXXXとして扱うことができるようになっています。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/masaya_aoyama/20200617/20200617000243.png" alt="f:id:masaya_aoyama:20200617000243p:plain" title="f:id:masaya_aoyama:20200617000243p:plain" class="hatena-fotolife" itemprop="image"></span></p> <p>Federationでも、FederatedDeploymentなどの定義時に<a href="https://github.com/kubernetes-sigs/kubefed/blob/master/docs/userguide.md#overrides:title">特定のフィールドにパッチを当てる</a>ことができます。 また、<a href="https://github.com/kubernetes-sigs/kubefed/blob/master/docs/userguide.md#using-cluster-selector">ClusterSelector</a>を使用して特定の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>のみにデプロイすることも可能です。</p> <pre class="code YAML" data-lang="YAML" data-unlink>kind: FederatedDeployment spec: overrides: - clusterName: cluster1 clusterOverrides: - path: &#34;/spec/replicas&#34; value: 5 - clusterName: cluster2 clusterOverrides: - path: &#34;/spec/template/spec/containers/0/image&#34; value: &#34;nginx:1.17.0-alpine&#34;</pre> <p>他にも、複数の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>横断でレプリカ数を維持するようなスケジューリングを行う<a href="https://github.com/kubernetes-sigs/kubefed/blob/master/docs/userguide.md#replicaschedulingpreference">ReplicaSchedulingPreference</a>などの機能もあります。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>横断でDeploymentを柔軟に展開したい場合には利用すると良いでしょう。</p> <pre class="code YAML" data-lang="YAML" data-unlink>apiVersion: scheduling.kubefed.io/v1alpha1 kind: ReplicaSchedulingPreference metadata: name: test-deployment spec: targetKind: FederatedDeployment totalReplicas: 9 clusters: A: weight: 1 B: weight: 2</pre> <h2>3. Virtual kubeletパターン</h2> <p>Virtual kubeletは<a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a>に仮想ノードを登録し、その仮想ノード上割り当てられたPodは「<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>外にあるコンピューティングプール」で起動する仕組みを提供します。 コンピューティングプールは、一般的にServerlessなCaaSサービスが多いですが、他にもエッジ環境におけるノードや別のコンピューティング<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>のケースもあります。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/masaya_aoyama/20200617/20200617004850.png" alt="f:id:masaya_aoyama:20200617004850p:plain" title="f:id:masaya_aoyama:20200617004850p:plain" class="hatena-fotolife" itemprop="image"></span></p> <p>Virtual kubeletで扱えるコンピューティングプールには、<a href="https://virtual-kubelet.io/docs/providers/">さまざまなプロバイダー</a>が提供されています。 大きく分けると3種類でしょうか。</p> <ul> <li><p>Serverless CaaSバックエンド向け</p> <ul> <li>Azure Container Instances</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/AWS">AWS</a> Fargate</li> </ul> </li> <li><p>別コンピューティング<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>向け</p> <ul> <li>Admiralty Multi-Cluster Scheduler</li> <li>HashiCorp <a class="keyword" href="http://d.hatena.ne.jp/keyword/Nomad">Nomad</a></li> </ul> </li> <li><p>エッジ環境・単一ノード向け</p> <ul> <li><a href="https://github.com/Azure/iot-edge-virtual-kubelet-provider">Azure IoT Edge Connector</a></li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> CRI</li> </ul> </li> </ul> <p>Serverless CaaS バックエンド向けのプロバイダでは、無尽蔵なコンピューティングプール上に迅速にPodをオフロードして起動するような使い方ができたり、メインで使うことで<a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a>ノードを管理する必要がなくなります。 なお、<a class="keyword" href="http://d.hatena.ne.jp/keyword/AWS">AWS</a> Fargateプロバイダーは、EKS on Fargateでは使われていません。</p> <p>別コンピューティング<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>向けのプロバイダでは、Serverless CaaSの代わりに、HashiCorp <a class="keyword" href="http://d.hatena.ne.jp/keyword/Nomad">Nomad</a>や別の<a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>(Admiraltyの場合)などのコンピューティング<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>に対してPodをオフロードすることができます。 Admiralty Multi-clsuter scheduler はその名の通り、複数の<a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>に対してスケジューリングする用途でも使うことができます。</p> <p>エッジ環境や単一ノード向けのプロバイダでは、Virtual Nodeに割り当てられたPodはエッジ環境上の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>で起動します。 <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%A6%A5%C9">クラウド</a>上に起動している<a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> Masterから、エッジ環境のノード郡を管理できるようになります。</p> <p>これらのソリューションはいくつかしか試せていませんが、全てにおいて「通常Nodeで起動したPod」と「Virtual kubeletで起動したPod」の間のPod Networkが適切に接続されたままになるのかが気になるところです。</p> <h1>マルチ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>時のロードバランサの扱い</h1> <p>マルチ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>環境では、ロードバランサなどのサービスを提供するエンドポイントを払い出す方法が大きく分けて3種類あるでしょう。</p> <h2>1. LoadBalancer の機能を利用して分散する</h2> <p><a href="https://cloud.google.com/kubernetes-engine/docs/concepts/ingress-for-anthos">Anthos の Multi Cluster Service / Ingress</a> では、同一<a class="keyword" href="http://d.hatena.ne.jp/keyword/IP%A5%A2%A5%C9%A5%EC%A5%B9">IPアドレス</a>を利用して複数リージョンにまたがる複数の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>に対してリク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>トを転送することができます。なので、米国と日本でマルチ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>構成を組み、リク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>ト元の地理に応じて最適な<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>に転送することができます。マルチリージョンでマルチ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>構成をするにあたって、この機能は便利だなという気持ちになります。</p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/CyberAgent">CyberAgent</a> の AKE でも、単一のVIPを使って複数の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>上に展開されるServiceや<a class="keyword" href="http://d.hatena.ne.jp/keyword/Ingress">Ingress</a>に利用できるようになっています。主に<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>間移行をゼロダウンタイムで行えるようにすることが目的です。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/masaya_aoyama/20200617/20200617004501.png" alt="f:id:masaya_aoyama:20200617004501p:plain" title="f:id:masaya_aoyama:20200617004501p:plain" class="hatena-fotolife" itemprop="image"></span></p> <h2>2. <a class="keyword" href="http://d.hatena.ne.jp/keyword/DNS">DNS</a> を利用して分散する</h2> <p>上記のような環境が利用できない場合は、<a class="keyword" href="http://d.hatena.ne.jp/keyword/DNS">DNS</a> Round Robin で構成するのが一般的でしょう。 Federation v2の場合は ExternalDNSと連携するようになっており、作成されたLoadBalancer Service と <a class="keyword" href="http://d.hatena.ne.jp/keyword/Ingress">Ingress</a> リソースが払い出す複数のVIPを自動的に<a class="keyword" href="http://d.hatena.ne.jp/keyword/DNS">DNS</a>に登録する、<a href="https://github.com/kubernetes-sigs/kubefed/blob/master/docs/userguide.md#multi-cluster-service-dns">Multi-Cluster Service DNS</a> と <a href="https://github.com/kubernetes-sigs/kubefed/blob/master/docs/userguide.md#multi-cluster-ingress-dns">Multi-Cluster Ingress DNS</a> の機能が提供されています。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/masaya_aoyama/20200617/20200617004522.png" alt="f:id:masaya_aoyama:20200617004522p:plain" title="f:id:masaya_aoyama:20200617004522p:plain" class="hatena-fotolife" itemprop="image"></span></p> <h2>3. Multi Cluster にまたがる Service Mesh を利用して転送する</h2> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>間の距離がある程度近い場合は、特定の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>でリク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>トを受けて隣の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>にリク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>トを転送するようにするのも良いでしょう。 Istio では<a href="https://istio.io/latest/docs/setup/install/multicluster/shared/">Multi Cluster Service Mesh</a>の機能が用意されており、複数の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>にまたがってリク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>トを分散させることができます。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/masaya_aoyama/20200617/20200617012818.png" alt="f:id:masaya_aoyama:20200617012818p:plain" title="f:id:masaya_aoyama:20200617012818p:plain" class="hatena-fotolife" itemprop="image"></span></p> <h1>マルチ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>でPod Networkを繋ぐ</h1> <p>マルチ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>でPod Networkを構成するには、Submarinerを利用することができます。 Submarinerでは、相互接続するすべての<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>のノード1台以上の<a class="keyword" href="http://d.hatena.ne.jp/keyword/Gateway">Gateway</a>用のAgent(Submariner <a class="keyword" href="http://d.hatena.ne.jp/keyword/Gateway">Gateway</a> Engine)を展開し、この<a class="keyword" href="http://d.hatena.ne.jp/keyword/Gateway">Gateway</a> Agent間で<a class="keyword" href="http://d.hatena.ne.jp/keyword/IPSec">IPSec</a>トンネルが張られるようになっています。 また、すべてのノードにはRoute Agentが展開されており、これにより<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>を跨いだPod間通信ができるようになっています。</p> <p><a href="https://github.com/submariner-io/submariner/raw/master/docs/img/architecture.jpg" class="http-image"><img src="https://github.com/submariner-io/submariner/raw/master/docs/img/architecture.jpg" class="http-image" alt="https://github.com/submariner-io/submariner/raw/master/docs/img/architecture.jpg"></a></p> <p>またSubmarinerでは、複数の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>で利用される<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>内<a class="keyword" href="http://d.hatena.ne.jp/keyword/DNS">DNS</a>のSuffix(cluster.local)は異なるものを指定し、ClusterIPのCIDRも別のものを指定します。 そのため、特定の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>から別の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>のServiceに対してリク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>トが送れるように、双方の<a class="keyword" href="http://d.hatena.ne.jp/keyword/DNS">DNS</a>サーバに対してクエリをかけられるようにしておく必要があります。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/masaya_aoyama/20200617/20200617015203.png" alt="f:id:masaya_aoyama:20200617015203p:plain" title="f:id:masaya_aoyama:20200617015203p:plain" class="hatena-fotolife" itemprop="image"></span></p> <h1>ストレージの扱い</h1> <p>マルチ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>・マルチテナント環境におけるストレージの扱いですが、VolumeSnapshotの機能が導入されることである程度<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>間移行はしやすくなるかもしれません。 一方で、<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSI">CSI</a> Driver間での<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%A4%A5%B0%A5%EC%A1%BC%A5%B7%A5%E7%A5%F3">マイグレーション</a>などは現状はスコープ外のため、同一<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSI">CSI</a> Driver、すなわち同一のストレージバックエンドに限れば、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>間でPersistentVolumeの移行もしやすくなるかもしれません。 マルチ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>の理由にもよりますが、同一<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%A6%A5%C9">クラウド</a>でマルチ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>構成であれば、シームレスな移行も夢では無いかと思います。</p> <h1>マルチテ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%CA%A5%F3%A5%B7%A1%BC%B4%D8">ナンシー関</a>連の技術</h1> <p>マルチ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>ーと類似したものとして、マルチテナンシーの考え方もあります。 <a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a>コミュニティにも、<a href="https://github.com/kubernetes/community/tree/master/sig-multicluster">SIG-MultiClsuter</a> と <a href="https://github.com/kubernetes/community/tree/master/wg-multitenancy">Multi-Tenancy WG</a> の 2 種類があります。</p> <p>下記に Virtual Cluster や Hierarchical Namespace の incubating project のDesign Docsや実装が公開されています。 <a href="https://github.com/kubernetes-sigs/multi-tenancy">GitHub - kubernetes-sigs/multi-tenancy: A working place for multi-tenancy related proposals and prototypes.</a></p> <p>また、Hierarchical Namespace Controller については、以前検証した結果をブログにまとめてあるのでご興味があれば参考にしてみてください。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Famsy810.hateblo.jp%2Fentry%2F2019%2F12%2F01%2F230822" title=" Hierarchical Namespace で Namespace を階層構造に管理してオブジェクトを伝搬させる - @amsy810&#39;s Blog" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://amsy810.hateblo.jp/entry/2019/12/01/230822">amsy810.hateblo.jp</a></cite></p> <p>また先週末の KubeFest でぞえとろさんがちらっと話題に出してた、<a class="keyword" href="http://d.hatena.ne.jp/keyword/kiosk">kiosk</a>やloft あたりも気になっています。 この辺りも時間があれば調べて、マルチ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>編もまとめるかもしれません。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgithub.com%2Floft-sh%2Floft" title="loft-sh/loft" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://github.com/loft-sh/loft">github.com</a></cite> <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgithub.com%2Fkiosk-sh%2Fkiosk" title="kiosk-sh/kiosk" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://github.com/kiosk-sh/kiosk">github.com</a></cite></p> <h1>超個体型データセンターへの応用</h1> <p>客員研究員として参加している<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A4%B5%A4%AF%A4%E9%A5%A4%A5%F3%A5%BF%A1%BC%A5%CD%A5%C3%A5%C8">さくらインターネット</a>研究所では、ビジョンとして「超個体型データセンター」を掲げています。 私の理解でざっくりと説明すると、「中小規模のデータセンター」や「エッジ・フォグ環境」などが相互に<a class="keyword" href="http://d.hatena.ne.jp/keyword/%CD%AD%B5%A1">有機</a>的に接続され、自律分散的に協調動作するだろうというビジョンです。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fresearch.sakura.ad.jp%2F2019%2F02%2F22%2Fconcept-vision-2019%2F" title="超個体型データセンターを目指す当研究所のビジョン" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://research.sakura.ad.jp/2019/02/22/concept-vision-2019/">research.sakura.ad.jp</a></cite></p> <p>今回は備忘録的に<a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a>におけるマルチ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>周りの技術の分類や手法をまとめてみました。 ベースの技術として<a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a>を使うべきというわけではありませんが、技術検証やPoCなどでは<a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a>やCRD/Controllerによる拡張性を利用できると良いかと思っています。</p> <p>今回紹介したマルチ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>関連の技術を組み合わせることで、少しそれらしいものはできるかもしれませんが、超個体的(相互に<a class="keyword" href="http://d.hatena.ne.jp/keyword/%CD%AD%B5%A1">有機</a>的に接続され、自立分散的に協調動作)というよりかは、中央集権的な手法が多いと感じています。</p> <p>そのため理想としては、各<a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>を作成後にAgentを各<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>にデプロイするだけで、Agentが相互に情報を交換しあうことで最適なワークロードの配置を行ってくれるような、超個体的な<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>を作れると面白いのかなと思っています。 <a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a>の場合には、このAgentの実装はCustom Controllerを実装すればよいので、あとはロジックをどうするかをもう少し明確に考える必要があると思っています。 ロジックやメトリクスがPlugableにできるように設計できれば、最初は局所解に陥るような単純なものでも良いのかもしれません。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/masaya_aoyama/20200617/20200617025904.png" alt="f:id:masaya_aoyama:20200617025904p:plain" title="f:id:masaya_aoyama:20200617025904p:plain" class="hatena-fotolife" itemprop="image"></span></p> <p>おしまい。 <a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>: <a href="https://twitter.com/amsy810">amsy810</a></p> masaya_aoyama Flexispotで最大サイズの昇降机を自作した話 hatenablog://entry/26006613552553999 2020-04-19T14:24:30+09:00 2020-04-19T14:29:41+09:00 こんにちは。 青山(amsy810)です。 皆さん在宅勤務が長引いて大変な日々をお過ごしでしょうか。 かくいう私も仕事場所を作ってたんですが、長期かつ運動もしなくなる状況では耐えられなかったため昇降デスクを作ることにしました。 最大サイズで作った例が見当たらなかったので、まとめておきます。 最近の昇降デスクはかなり安くなってるのですね。 出来上がりはこんな感じです。 【自宅環境整備週末日記②】はい、できました!(途中経過全然載せられなかった)昇降すると123cmまであがるので在宅疲れの軽減に期待。自分で作ると32インチのモニター二枚置いても広々な規格外サイズ作れて良い。週末もいろんな意味でアー… <p>こんにちは。 青山(<a href="https://twitter.com/amsy810">amsy810</a>)です。</p> <p>皆さん在宅勤務が長引いて大変な日々をお過ごしでしょうか。 かくいう私も仕事場所を作ってたんですが、長期かつ運動もしなくなる状況では耐えられなかったため昇降デスクを作ることにしました。 最大サイズで作った例が見当たらなかったので、まとめておきます。</p> <p>最近の昇降デスクはかなり安くなってるのですね。 出来上がりはこんな感じです。</p> <p><blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">【自宅環境整備週末日記②】<br>はい、できました!(途中経過全然載せられなかった)<br>昇降すると123cmまであがるので在宅疲れの軽減に期待。<br>自分で作ると32インチのモニター二枚置いても広々な規格外サイズ作れて良い。<br>週末もいろんな意味でアーキテクト、インフラエンジニアしてました。 <a href="https://t.co/Eb6s1uSdYC">pic.twitter.com/Eb6s1uSdYC</a></p>&mdash; MasayaAoyama(青山 真也) (@amsy810) <a href="https://twitter.com/amsy810/status/1251508000659046401?ref_src=twsrc%5Etfw">2020年4月18日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <h1>どの昇降デスクを選んだのか</h1> <p>今回選んだのは <a href="https://flexispot.jp/height-adjustable-desks/e3.html">Flexispot の E3 シリーズ</a>です。 デスクの脚だけでも売っていて、天板は自由に選択することが可能です。</p> <p>天板の最大サイズは <b>200cm x 80cm</b>、<b>合計100kg</b>まで耐えられるようです。 (ページによって80kgと書いてあるところもあるので、どちらが正しいのかは微妙) また、昇降高も60cm-123cmなのでかなり幅広く対応できます。</p> <p><a href="https://flexispot.jp/media/catalog/layer/cache/x560/e/3/e3b-s.jpg" class="http-image"><img src="https://flexispot.jp/media/catalog/layer/cache/x560/e/3/e3b-s.jpg" class="http-image" alt="https://flexispot.jp/media/catalog/layer/cache/x560/e/3/e3b-s.jpg"></a></p> <p>この脚自体が35kgくらいあるので、なかなかしっかりしています。 個人差はあるでしょうが、この高性能な脚だけで5万を切るのはなかなか安いなと思っています。 私自身中学時代からゲームばっかりしてたので、その頃から腰痛とは付き合ってますし。</p> <h1>木材の購入</h1> <p>次に木材の選定ですが、やはり目指すは最大サイズです。 でかいホームセンターなどでよく売られているお手頃な一般的な木材の多くは、大きくても 180cm x 60cm とかが多いイメージです。 <a class="keyword" href="http://d.hatena.ne.jp/keyword/%CB%AD%BD%A7">豊洲</a>のビバホームでもこのくらいのサイズが最大のようでした。</p> <p>そのため、このサイズの木材に関しては無垢材(横接ぎ材)や集積材などから切り出してもらうしかありません。</p> <p>今回は下記で木材を発注しました。 4/10に入金して4/17には到着したので、納期も5営業日程度とかなりスピーディーでした。</p> <p><a href="http://sakuma-mokuzai.com">http://sakuma-mokuzai.com</a></p> <p>今回は木材は<b>ベイマツ集積材(米松)</b>にしました。 一番風合いが自然だなと思ったのと直感です。</p> <p>長く使うならウォルナットの無垢材に奮発しようと思っていたんですが、こちらは納期が2-3週間かかり、かつ今回はGWも跨ぐとのことだったので見送りました。 一時しのぎでベイマツ集積材にしたのですが、後述するオイルフィニッシュの出来が良かったのでこのままでも良いかなと思っています。 <a href="https://shop.woodworks-marutoku.com">https://shop.woodworks-marutoku.com</a></p> <h1>強度と耐荷重について</h1> <p>机を作るに当たって一番気にしなければならないのは強度です。 200cm x 80cm ともなると、2cm程度の板だと流石に心許ないでしょう。 今回は 4cm の厚さで作りました。 4cmくらいあると結構しっかりしている感じですが、見た目的には3cmくらいの気分です。</p> <p>200cm x 80cm x 4cm の米松の木材となると、大体45kgくらいの重さになります。 4.5cmか悩んだのですが、一人で持てる重さを考えて4cmにしたというのもあります。</p> <p>ちなみにこのサイズであれば、多少力持ちであれば一人で倉庫からピックアップして車に積んで、台車を使えば家に運び込むこともできます。<b>(個人の見解です)</b></p> <p>現時点で床への重さは35kg(脚)+45kg(板)です。 床に対する耐荷重はここに人や椅子、モニタやモニタアームなどが加わります。 気になる方は床への耐荷重も調べておくと良いかもしれません。 調べた感じだと1m<sup>2</sup>あたり180kgまで耐えられるようなので、大丈夫かなと判断しました。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=http%3A%2F%2Fwww.jsca.or.jp%2Fvol5%2Fp4_4_tec_terms%2F200506%2F20050623.php" title="『荷重』- 積載荷重:日本建築構造技術者協会" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="http://www.jsca.or.jp/vol5/p4_4_tec_terms/200506/20050623.php">www.jsca.or.jp</a></cite></p> <p>机自体の耐荷重は45kgだけなので、55kg分はモニターなどで利用することが可能です。</p> <h1>加工について</h1> <p>佐久間木材さんの場合糸面取りは無料でやってくれます。 それ以外の加工はヤスリとかを買って自分でやれば30分くらいで終わるのでおすすめです。 納品された時点で木材自体は240-400番台のヤスリでヤスリがけされていたような感じがするので、そのまま使っても大丈夫な気がします。 ただし糸面取りだけだと角が結構痛いので、多少の加工はしておいたほうが良いと思います。</p> <p><a href="https://www.amazon.co.jp/exec/obidos/ASIN/B0065CKQ2E/hatena-blog-22/">NT(エヌティー) ドレッサー 中目 L-30P</a></p> <p><a href="https://www.amazon.co.jp/exec/obidos/ASIN/B07DXKQSRS/hatena-blog-22/">NESHEXST ハンドサンダー サンドペーパー ヤスリ ホルダー 紙やすり</a></p> <h1>オイルフィニッシュについて</h1> <p>今回は塗装ではなく、オイルフィニッシュを行いました。 塗装ってムラができやすいのでかなり真面目にやらないとダメなんですよね… その点オイルフィニッシュであれば刷毛と<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AD%A5%E0%A5%EF%A5%A4%A5%D7">キムワイプ</a>さえあればどうにかなります。</p> <p>手順としても、下記のステップを踏むだけなので比較的簡単です。 塗る作業についても、サラダ油くらいのオイルを木に染み込ませて木の防御をする感じなので、ムラは出づらく楽チンでした。 私は片面塗り終わった後、もう片面は1時間位たってすぐにひっくり返して塗り始めまてしまいましたが、大丈夫そうでした。 ちなみに片面しか塗らないのは、湿気の吸い具合にむらが出て木の反りの原因になるとのことなので、両面塗りは必須です。</p> <ul> <li>400番でヤスリがけをする</li> <li>たっぷり片面を塗る</li> <li>30分待つ</li> <li>二度塗りする</li> <li>600番の耐水ペーパーで濡れたままヤスリがけ</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AD%A5%E0%A5%EF%A5%A4%A5%D7">キムワイプ</a>で水分を完全に拭き取る(可燃性なので廃棄に注意)</li> <li>12-24時間放置</li> </ul> <p>オイルフィニッシュは着色されたやつもあります。 今回はウォルナット調のものを利用しましたが、木目がいい感じに出てくれてよかったです。</p> <p><blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">【自宅環境整備週末日記①】<br>さて、スタート地点となる2000mm x 800mm x 40mm の板を人気のない夜中に倉庫からピックアップしました(コロナ対策)<br>からのワトコオイルを塗りました。<br>ウォルナット無垢材は納期が長かったので、一時凌ぎで松の集積材+着色オイルにしたんですが、思ったよりいい感じ。 <a href="https://t.co/md98MRxHfS">pic.twitter.com/md98MRxHfS</a></p>&mdash; MasayaAoyama(青山 真也) (@amsy810) <a href="https://twitter.com/amsy810/status/1251216393397297152?ref_src=twsrc%5Etfw">2020年4月17日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p><a href="https://www.amazon.co.jp/exec/obidos/ASIN/B00GWBQTLU/hatena-blog-22/">ワトコオイル ダークウォルナット W-13 1L</a> <a href="https://www.amazon.co.jp/exec/obidos/ASIN/B004MXIQLQ/hatena-blog-22/">ハンディ・クラウン 差し口ベロ 40mm</a></p> <h1>組み立てについて</h1> <p>脚のパーツは簡単に組み立てられます。 脚を180cmに広げた状態でも一人でも持ち上げられます。</p> <p>木材と脚はネジでつなげますが、木材を付けた脚を一人でひっくり返すのは正直難しいと思います。 なので今回は木材を脚の上に載せた状態でネジ止めをしました。 今回は木材自体が重いのもあってか、この状態でもネジ止めができました。 ネジ止めするときも昇降して高い位置にしておけば、下からでも作業がしやすかったです。</p> <h1>感想</h1> <p>スタンディング、思ったより最高です。意外と疲れないんですね。 ただ思ったより足裏は痛くなるので、たしかに下に敷く厚手のマットは必要だなぁという気持ちになりました。</p> <h1>その他のWFH環境</h1> <table> <thead> <tr> <th> 品目 </th> <th> 商品名 </th> <th> オススメ理由 </th> </tr> </thead> <tbody> <tr> <td>椅子</td> <td><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A1%BC%A5%ED%A5%F3%A5%C1%A5%A7%A5%A2">アーロンチェア</a></td> <td>12年保証?があるので月額換算すれば安い。というか腰痛すぎて高校生のときに貯金で買いました。</td> </tr> <tr> <td>モニター</td> <td><a href="https://www.philips.co.jp/c-p/328P6VUBREB_11/brilliance-lcd-monitor-with-usb-c-dock">328P6AUBREB/11</a></td> <td>32インチ4Kくらいがちょうどいい。type-C 接続可</td> </tr> <tr> <td> モニターアーム </td> <td> エルゴトロン </td> <td> デザインよし</td> </tr> <tr> <td>キーボード</td> <td><a class="keyword" href="http://d.hatena.ne.jp/keyword/REALFORCE">REALFORCE</a></td> <td>自作したいけど、今は慣れ親しんだコレで…</td> </tr> <tr> <td>マウス</td> <td>MX Master</td> <td>言わずとしれた定番</td> </tr> <tr> <td>マウスパッド</td> <td>steelseriaesのやつ</td> <td>さらさら</td> </tr> <tr> <td> ウェブカメラ </td> <td> <a class="keyword" href="http://d.hatena.ne.jp/keyword/Logicool">Logicool</a> c922 </td> <td> 画質よし</td> </tr> <tr> <td> マイク </td> <td> MPM-1000U </td> <td> <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%B9%A5%D1">コスパ</a>よし</td> </tr> <tr> <td><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A5%C3%A5%C8%A5%DE%A5%F3">オットマン</a></td> <td><a href="https://www.amazon.co.jp/dp/B07RWDLCN2?ref=ppx_pop_mob_ap_share">Amazonで適当に</a></td> <td><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%B9%A5%D1">コスパ</a>良し</td> </tr> </tbody> </table> <p>後は配線周りを工夫して、モニタの片側を<a class="keyword" href="http://d.hatena.ne.jp/keyword/iPad">iPad</a>で利用したりなどもできるようにしています。</p> <p>あと、椅子の下にはなにか敷いたほうがいいです。長い間使ってると床を結構傷つけます。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%CB%A5%C8%A5%EA">ニトリ</a>のタイルマットが結構オススメで、汚れても交換簡単、安い、厚みがあるので安心です。</p> <h1>まとめ</h1> <p>備忘録+メモ書き的な感じなので乱文ですが、まとめておきました。 引き続きひきこもるぞ。</p> masaya_aoyama Conftest で CI 時に Rego で記述したテストを行う hatenablog://entry/26006613526189723 2020-04-03T12:49:13+09:00 2020-04-03T12:52:59+09:00 Conftest で CI 時に Rego を用いたテストを行う こんにちは。青山(@amsy810)です。 実は少しだけ PLAID さんでお手伝いをしており、CI に Conftest を組み込んで Kubernetes マニフェストのポリシーチェックを行うようにしたので、その時の備忘録を書いておきます。 PLAID さんでも GKE を基盤として選定して開発しています。 Conftest とは? Conftest は Rego 言語で記述したポリシーを用いて、JSON や YAML などがポリシーに合致しているかをチェックする OSS です。 今回は Kubernetes のマニフェスト… <h1>Conftest で CI 時に Rego を用いたテストを行う</h1> <p>こんにちは。青山(<a href="https://twitter.com/amsy810">@amsy810</a>)です。 実は少しだけ <a href="https://plaid.co.jp/">PLAID</a> さんでお手伝いをしており、CI に Conftest を組み込んで <a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%CB%A5%D5%A5%A7%A5%B9%A5%C8">マニフェスト</a>のポリシーチェックを行うようにしたので、その時の備忘録を書いておきます。 <a class="keyword" href="http://d.hatena.ne.jp/keyword/PLAID">PLAID</a> さんでも <a href="https://tech.plaid.co.jp/tag/kubernetes/">GKE を基盤として選定して開発</a>しています。</p> <h1>Conftest とは?</h1> <p>Conftest は Rego 言語で記述したポリシーを用いて、<a class="keyword" href="http://d.hatena.ne.jp/keyword/JSON">JSON</a> や <a class="keyword" href="http://d.hatena.ne.jp/keyword/YAML">YAML</a> などがポリシーに合致しているかをチェックする <a class="keyword" href="http://d.hatena.ne.jp/keyword/OSS">OSS</a> です。 今回は <a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%CB%A5%D5%A5%A7%A5%B9%A5%C8">マニフェスト</a>がポリシーに合致しているかどうかを判別するために利用します。</p> <p>例えば下記の例では、Deployment や StatefulSet などの Workloads リソースの Selector や起動してくる Pod のラベルに app ラベルが付与されるかをチェックしています。このように、比較的記述しやすい言語を利用してポリシーを定義していくことが可能です。</p> <pre class="code" data-lang="" data-unlink>deny[msg] { input.kind == workload_resources[_] not (input.spec.selector.matchLabels.app == input.spec.template.metadata.labels.app) msg = sprintf(&#34;Pod Template 及び Selector には app ラベルを付与してください(spec.template.metadata.labels.app、spec.selector.matchLabels.app): [Resource=%s, Name=%s, Selector=%v, Labels=%v]&#34;, [input.kind, input.metadata.name, input.spec.selector.matchLabels, input.spec.template.metadata.labels]) }</pre> <p>ポリシーチェックの実行は下記のコマンドを実行するだけなため、容易に CI に組み込むことが可能です。</p> <pre class="code" data-lang="" data-unlink># サンプルは https://github.com/MasayaAoyama/conftest-demo に配置してあります conftest test --policy ./policy --input yaml manifests/*</pre> <p>Rego 言語については OPA の公式サイトを見てください。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.openpolicyagent.org%2Fdocs%2Flatest%2Fpolicy-language%2F" title="Policy Language" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://www.openpolicyagent.org/docs/latest/policy-language/">www.openpolicyagent.org</a></cite></p> <p>Built-in Function については下記の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BD%A1%BC%A5%B9%A5%B3%A1%BC%A5%C9">ソースコード</a>も参考になります。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgithub.com%2Fopen-policy-agent%2Fopa%2Fblob%2Fmaster%2Fast%2Fbuiltins.go" title="open-policy-agent/opa" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://github.com/open-policy-agent/opa/blob/master/ast/builtins.go">github.com</a></cite></p> <h1>OpenPolicyAgent / <a class="keyword" href="http://d.hatena.ne.jp/keyword/Gatekeeper">Gatekeeper</a> との違い</h1> <p>類似プロダクトとして、OpenPolicyAgent / <a class="keyword" href="http://d.hatena.ne.jp/keyword/Gatekeeper">Gatekeeper</a> もありますね。 <a class="keyword" href="http://d.hatena.ne.jp/keyword/Gatekeeper">Gatekeeper</a> を利用したポリシーチェックでは、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> に<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%CB%A5%D5%A5%A7%A5%B9%A5%C8">マニフェスト</a>が登録する際に AdmissionWebhook の ValidatingWebhook が実行されるタイミングで評価されます。そのため、Mutating されたあとの状態のチェックも行うことが可能です。</p> <p>GitOps の場合は<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%CB%A5%D5%A5%A7%A5%B9%A5%C8">マニフェスト</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%DD%A5%B8%A5%C8%A5%EA">リポジトリ</a>の状態が<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>の状態と同じ状態になるように構成します。<a class="keyword" href="http://d.hatena.ne.jp/keyword/Gatekeeper">Gatekeeper</a> を利用していて GitOps などを行っている場合には、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%CB%A5%D5%A5%A7%A5%B9%A5%C8">マニフェスト</a>の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%DD%A5%B8%A5%C8%A5%EA">リポジトリ</a>に対してコミットした後、実際に<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>に反映する際に失敗して初めてポリシーに違反していることが確認できます。</p> <p>一方で Conftest の場合には、CI の際にチェックすることが可能です。そのため、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%CB%A5%D5%A5%A7%A5%B9%A5%C8">マニフェスト</a>が適切かどうかは<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%DD%A5%B8%A5%C8%A5%EA">リポジトリ</a>にコミットする前、すなわち<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%CB%A5%D5%A5%A7%A5%B9%A5%C8">マニフェスト</a>ファイルに対する更新時にもチェックするようにしましょう。</p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Gatekeeper">Gatekeeper</a> も<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>への登録時に安全に防ぐようにし、GitOps などを行っている場合には Conftest で CI でも前倒しして事前にチェックするように 2 段構えにすると良いと思います。</p> <p>余談ですが、<a class="keyword" href="http://d.hatena.ne.jp/keyword/GCP">GCP</a> の Anthos Config Management で提供されている Anthos Policy Controller も <a class="keyword" href="http://d.hatena.ne.jp/keyword/Gatekeeper">Gatekeeper</a> を利用しているようです。 <a href="https://cloud.google.com/anthos-config-management/docs/concepts/policy-controller">https://cloud.google.com/anthos-config-management/docs/concepts/policy-controller</a></p> <h1>設定しているポリシーについて</h1> <p>下記のようなポリシーを設定しています。一部は PodSecurityPolicy でも設定可能ですが、<a class="keyword" href="http://d.hatena.ne.jp/keyword/PSP">PSP</a> も <a class="keyword" href="http://d.hatena.ne.jp/keyword/Gatekeeper">Gatekeeper</a> 同様 <a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a> 登録時にチェックが行われるため、Conftest でもチェックすることに意味はあるでしょう。</p> <ul> <li>単一リソース内でのチェック <ul> <li>特権コンテナの利用制限</li> <li>各種リソースや Selector に特定のラベルが付与されているかのチェック</li> <li>コンテナのイメージタグの制限</li> <li>TerminationGracePeriodSeconds の設定時間が既定値以下かのチェック</li> <li>Resource Requests が設定されているかのチェック</li> <li>Limits/Requests の差のチェック</li> <li>Probe の failureThreshold などの設定値が既定値の範囲内かのチェック</li> <li>Inter-pod anti-affinity が設定されているかのチェック</li> <li>hostPath 利用時に Readonly になっているかのチェック</li> <li>Service の ClusterIP が静的に設定されていないかのチェック</li> <li>Ephemeral Storage の利用上限設定がされているかのチェック</li> <li>etc</li> </ul> </li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>全体での横断チェック <ul> <li>ラベルがバッティングしていないか</li> </ul> </li> <li>etc</li> </ul> <h1><a class="keyword" href="http://d.hatena.ne.jp/keyword/Gatekeeper">Gatekeeper</a> とのポリシーファイルの違い</h1> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Gatekeeper">Gatekeeper</a> の場合には、現在既に <a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> に登録されているデータを <code>data.inventory</code> から参照することが可能です。</p> <pre class="code" data-lang="" data-unlink>クラスタオブジェクトの場合: data.inventory.cluster[&lt;groupVersion&gt;][&lt;kind&gt;][&lt;name&gt;] (例: data.inventory.cluster[&#34;v1&#34;].Namespace[&#34;gatekeeper&#34;]) Namespace オブジェクトの場合: data.inventory.namespace[&lt;namespace&gt;][groupVersion][&lt;kind&gt;][&lt;name&gt;] (例:data.inventory.namespace[&#34;gatekeeper&#34;][&#34;v1&#34;][&#34;Pod&#34;][&#34;gatekeeper-controller-manager-d4c98b788-j7d92&#34;])</pre> <p>これを利用すると、下記のように既に登録されている <a class="keyword" href="http://d.hatena.ne.jp/keyword/Ingress">Ingress</a> リソースの host 名と衝突していないかといったチェックも行うことができます。</p> <pre class="code" data-lang="" data-unlink># https://github.com/open-policy-agent/gatekeeper/blob/master/library/general/uniqueingresshost/src.rego package k8suniqueingresshost identical(obj, review) { obj.metadata.namespace == review.object.metadata.namespace obj.metadata.name == review.object.metadata.name } violation[{&#34;msg&#34;: msg}] { input.review.kind.kind == &#34;Ingress&#34; re_match(&#34;^(extensions|networking.k8s.io)$&#34;, input.review.kind.group) host := input.review.object.spec.rules[_].host # 既にクラスタに登録されているデータを参照 other := data.inventory.namespace[ns][otherapiversion][&#34;Ingress&#34;][name] re_match(&#34;^(extensions|networking.k8s.io)/.+$&#34;, otherapiversion) other.spec.rules[_].host == host not identical(other, input.review) msg := sprintf(&#34;ingress host conflicts with an existing ingress &lt;%v&gt;&#34;, [host]) }</pre> <h1>Conftest による横断のチェック</h1> <p>さて、本ブログ記事で一番お伝えしておきたい内容です。 実際マイクロサービスが複雑化してくると、Conftest の段階で「Deployment に対して PodDisruptionBudget が設定されているか」「Service の Selector にマッチする Deployment 等が存在するか」「横断でラベルがバッティングしていないかのチェック」といった横断的なチェックを<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B5%A1%B3%A3%C5%AA">機械的</a>に行わなければ予期せぬ障害が発生するかもしれません。</p> <p>Conftest でも <code>--combine</code> オプションをつけることで複数のファイルをロードして横断でチェックすることが可能です。</p> <pre class="code" data-lang="" data-unlink>conftest test --policy ./policy --input yaml ./manifests/* --combine</pre> <p>このとき、conftest にはリソース自体が入ってくるのではなく、「ファイル」「リソース」の配列で入ってくるため注意してください。なお、ひとつのファイルに単一リソースしか書かれていない場合は、「ファイル」の配列の後にそのままリソースが入ってきてしまい、ファイルによって構造が変わってきてしまいます。そのため、一つのファイルに単一のリソースしかない場合でも <code>---</code> を 1 つ目のリソースの後に明示的に記載するようにしましょう。</p> <pre class="code" data-lang="" data-unlink>deny[msg] { files := input[_] resources := files[_] other_files := input[_] other_resources := other_files[_] resources.kind == workload_resources[_] other_resources.kind == workload_resources[_] resources.spec.template.metadata.labels == other_resources.spec.template.metadata.labels resources.metadata.name != other_resources.metadata.name msg = sprintf(&#34;リソースのラベルが衝突しています: [%s/%s &lt;=&gt; %s/%s]&#34;, [resources.kind, resources.metadata.name, other_resources.kind, other_resources.metadata.name]) }</pre> <h1>まとめ</h1> <p>Conftest は非常に手軽に CI に<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%CB%A5%D5%A5%A7%A5%B9%A5%C8">マニフェスト</a>のチェックを導入できるためおすすめです。また、OPA のポリシーファイルを使い回しやすいため、OPA と合わせて利用する際もそこまでコストを掛けずに利用することが可能です。ぜひセキュリティや組織ポリシーの徹底のためにも、OPA / <a class="keyword" href="http://d.hatena.ne.jp/keyword/Gatekeeper">Gatekeeper</a> と合わせて Conftest の利用を検討してみてください。</p> <p>今回利用したサンプルファイル類は下記に上げています。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgithub.com%2FMasayaAoyama%2Fconftest-demo" title="MasayaAoyama/conftest-demo" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://github.com/MasayaAoyama/conftest-demo">github.com</a></cite></p> masaya_aoyama EKS on Fargate:virtual-kubelet の違い + Network/LB 周りの調査 hatenablog://entry/26006613476069044 2019-12-04T15:16:42+09:00 2019-12-04T18:34:01+09:00 EKS on Fargate こんにちは。 サイバーエージェントの青山(@amsy810)です。 この記事は Kubernetes3 Advent Calendar の 4日目の記事です(EKS #2 にもクロスポストしています)。 re:Invent で EKS 関連の何かしらの発表がされることを見越して Advent Calendar を埋めたので、書くネタが見つかってホッとしています。 KubeCon 会期中に 「Managed Worker Node for EKS」 がリリースされ歓喜の声が上がりましたが、今回は re:Invent で 「EKS on Fargate」 がリリースさ… <h1>EKS on Fargate</h1> <p>こんにちは。 <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B5%A5%A4%A5%D0%A1%BC%A5%A8%A1%BC%A5%B8%A5%A7%A5%F3%A5%C8">サイバーエージェント</a>の青山(@amsy810)です。</p> <p>この記事は <a href="https://qiita.com/advent-calendar/2019/kubernetes3">Kubernetes3 Advent Calendar</a> の 4日目の記事です(<a href="https://qiita.com/advent-calendar/2019/amazon-eks-2">EKS #2</a> にも<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%ED%A5%B9%A5%DD%A5%B9%A5%C8">クロスポスト</a>しています)。 re:Invent で EKS 関連の何かしらの発表がされることを見越して Advent Calendar を埋めたので、書くネタが見つかってホッとしています。</p> <p>KubeCon 会期中に 「<strong>Managed Worker Node for EKS</strong>」 がリリースされ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B4%BF%B4%EE">歓喜</a>の声が上がりましたが、今回は re:Invent で 「<strong>EKS on Fargate</strong>」 がリリースされ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B4%BF%B4%EE">歓喜</a>の声が上がっているようです。 今回は EKS on Fargate の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A1%BC%A5%AD%A5%C6%A5%AF%A5%C1%A5%E3">アーキテクチャ</a>を見ていきたいと思います。virtual-kubelet と近いと思ってますが果たして。 (EKS on Fargate の詳細な記事はプロの誰かが書くと思うので、私は主に virtual-kubelet との対比と、大好きなネットワーク周りの軸でかければと思います。)</p> <h1>EKS on Fargate とは?</h1> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/masaya_aoyama/20191204/20191204151318.png" alt="f:id:masaya_aoyama:20191204151318p:plain" title="f:id:masaya_aoyama:20191204151318p:plain" class="hatena-fotolife" itemprop="image"></span></p> <p>EKS on Fargate は 12/3 PST にリリースされた、<a class="keyword" href="http://d.hatena.ne.jp/keyword/AWS">AWS</a> Fargate をバックエンドとして、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> Pod を起動することができる機能です。Fargate がいることにより、<strong>EC2<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>を管理する必要がなくなります</strong>。よしなにやっておいてほしい人からすると嬉しいのではないでしょうか。 <a href="https://aws.amazon.com/jp/blogs/aws/amazon-eks-on-aws-fargate-now-generally-available/">https://aws.amazon.com/jp/blogs/aws/amazon-eks-on-aws-fargate-now-generally-available/</a></p> <p>ご存知の方もいるかと思いますが、ここまで聞くと類似プロダクトとして、<a class="keyword" href="http://d.hatena.ne.jp/keyword/OSS">OSS</a> で開発が進められている <strong>virtual-kubelet</strong>(<a href="https://github.com/virtual-kubelet/virtual-kubelet">https://github.com/virtual-kubelet/virtual-kubelet</a>) のようにも聞こえますね。virtual-kubelet は、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> の Node として1台の仮想的なノードを追加しておきます。その仮想ノードの後ろには、膨大なコンピューティングリソースを持ったコンテナ実<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B9%D4%B4%F0">行基</a>盤(プール)のようなものが待ち構えており、その仮想ノードにスケジューリングされた Pod はそのリモートノード上で Pod が実行されるようになります。代表的な実装例としては、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Microsoft">Microsoft</a> Azure の ACI などでしょうか。</p> <p><figure class="figure-image figure-image-fotolife" title="virtual-kubeletの概要"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/masaya_aoyama/20191204/20191204131908.png" alt="f:id:masaya_aoyama:20191204131908p:plain" title="f:id:masaya_aoyama:20191204131908p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>virtual-kubeletの概要</figcaption></figure> 参考:<a href="https://raw.githubusercontent.com/virtual-kubelet/virtual-kubelet/release-1.2/website/static/img/diagram.svg">https://raw.githubusercontent.com/virtual-kubelet/virtual-kubelet/release-1.2/website/static/img/diagram.svg</a></p> <p><strong><span style="color: #d32f2f">virtual-kubelet のプロバイダーの中に <a class="keyword" href="http://d.hatena.ne.jp/keyword/AWS">AWS</a> Fargate Provider もあるのを把握していたため、これが EKS on Fargate だと思っていましたが、どうやら違うようです</span></strong>。 <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%DD%A5%B8%A5%C8%A5%EA">リポジトリ</a>(<a href="https://github.com/virtual-kubelet/aws-fargate">https://github.com/virtual-kubelet/aws-fargate</a>)をみても、半年〜1年程度更新がないため、virtual-kubelet 経由のものよりかは、EKS on Fargate を使っていくべきでしょう。</p> <h1>EKS on Fargate の検証</h1> <p>検証環境は下記のとおりです。</p> <ul> <li>eksctl: 0.11.0-rc.0</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a>: v1.14.8-eks</li> </ul> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>の構築時に --fargate オプションを利用することで構築可能です。リリース時点から <strong>ap-northeast-1</strong> でもデプロイ可能でした。</p> <pre class="code" data-lang="" data-unlink>$ eksctl create cluster --name amsy810-cluster --region ap-northeast-1 --fargate</pre> <p>しばらくすると、EKS <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>の構築が完了します。初期段階では coredns だけ起動している状態なため、2 Pod だけが立ち上がっている状態です。</p> <pre class="code" data-lang="" data-unlink># (一部アウトプットを省略) $ kubectl get pods -A -o wide NAME READY STATUS IP NODE coredns-6d75bbbf58-5jn27 1/1 Running 192.168.129.12 fargate-ip-192-168-129-12.ap-northeast-1.compute.internal coredns-6d75bbbf58-96nbt 1/1 Running 192.168.166.59 fargate-ip-192-168-166-59.ap-northeast-1.compute.internal</pre> <p>ノードの状態を見てみると 下記の通り 2 台だけ起動している状態です。</p> <pre class="code" data-lang="" data-unlink># (一部アウトプットを省略) $ kubectl get node -o wide NAME STATUS ROLES VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME fargate-ip-192-168-129-12.ap-northeast-1.compute.internal Ready &lt;none&gt; v1.14.8-eks 192-168-129-12 &lt;none&gt; Amazon Linux 2 4.14.152-127.182.amzn2.x86_64 containerd://1.3.0 fargate-ip-192-168-166-59.ap-northeast-1.compute.internal Ready &lt;none&gt; v1.14.8-eks 192-168-166-59 &lt;none&gt; Amazon Linux 2 4.14.152-127.182.amzn2.x86_64 containerd://1.3.0</pre> <p>EKS on Fargate では、<strong><span style="color: #d32f2f">virtual-kubelet とは異なり Pod 1つにつき 1 Node が展開される</span></strong> ような形になっています。virtual-kubelet の場合には、「kubectl get node」した際に、1 つの大きな 仮想 Node だけが存在しており、その仮想 Node 上で複数の Pod が起動するような形になるため、異なるポイントです。また、Fargate Node の IP と Pod の IP は同じになっています。他にも、各 Node の Pod Capacity が 1 になっていたり、「eks.amazonaws.com/compute-type=fargate:NoSchedule」 taints も付与されていました。</p> <p>なお、当然ですが下記のような 2 Container in 1 Pod な Pod も、1 つの Fargate Node にデプロイされます。</p> <pre class="code" data-lang="" data-unlink>cat &lt;&lt; _EOF_ | kubectl apply -f - apiVersion: v1 kind: Pod metadata: name: sample-2pod spec: containers: - name: nginx-container image: nginx:1.12 - name: redis-container image: redis:3.2 _EOF_</pre> <pre class="code" data-lang="" data-unlink># (一部アウトプットを省略) $ kubectl get pods sample-2pod -o wide NAME READY STATUS IP NODE sample-2pod 2/2 Running 192.168.151.223 fargate-ip-192-168-151-223.ap-northeast-1.compute.internal</pre> <h1>Fargate で起動する Pod の選択</h1> <p>EKS on Fargate では、通常ノードではなく Fargate で起動する Pod を設定しておきます。例えば、<strong>eksctl で作られる<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>のデフォルト</strong> では default namespace と kube-system namespace にスケジューリングされる Pod は Fargate 側で実行されるようになっています。そのため、事前に条件を設定していない Namespace や Pod Selector にマッチしていない Pod の場合には、Fargate 側で実行されない点だけ注意が必要です。現状だとすべての Namespace という設定はできなさそうですが、いずれ対応されるんじゃないかなと思います(12/4 18:00 追記:既に Tori さんから <a href="https://github.com/aws/containers-roadmap/issues/621">Issue</a> 化されていると教えていただきました!流石!)。設定は EKS の管理画面または「<a class="keyword" href="http://d.hatena.ne.jp/keyword/aws">aws</a> eks create-fargate-profile」コマンドから設定可能です。</p> <p><figure class="figure-image figure-image-fotolife" title="Fargate profile"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/masaya_aoyama/20191204/20191204135043.png" alt="f:id:masaya_aoyama:20191204135043p:plain" title="f:id:masaya_aoyama:20191204135043p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>Fargate profile</figcaption></figure></p> <p>ちなみに少し細かい話です。最初は MutatingWebhook 等で scheduling Policy(nodeAffinity、taints 等)を書き換えてるのかと思っていましたが、そもそも default scheduler を利用していないようです。Pod 登録時に該当するものは spec.schedulerName だけ Mutating して後は独自スケジューラにまかせているんだと思います。</p> <pre class="code" data-lang="" data-unlink>$ kubectl get pods sample-2pod -o jsonpath=&#34;{.spec.schedulerName}&#34; fargate-scheduler</pre> <h1>EKS on Fargate の起動時間</h1> <p>EKS on Fargate での Pod の起動時間は大体 45-50 sec 程度でした(数回のみの施行)。ノードを増やしていくことと比較すると、かなり早くコンテナを起動できるといえます。この点は virtual-kubelet の利点の一つである、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>外の warmpool で起動させる部分と同じような形です。</p> <h1>initContainer と emptyDir の使用</h1> <p>ちょっと発展的に initContainer や emptyDir を使用してみましたが、こちらも問題なく動作するようです。基本的に後述する注意点以外は普通の <a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> だなぁという使用感なのかと思います。</p> <pre class="code" data-lang="" data-unlink>cat &lt;&lt; _EOF_ | kubectl apply -f - apiVersion: v1 kind: Pod metadata: name: sample-initcontainer spec: initContainers: - name: output-1 image: centos:6 command: [&#39;sh&#39;, &#39;-c&#39;, &#39;sleep 20; echo 1st &gt; /usr/share/nginx/html/index.html&#39;] volumeMounts: - name: html-volume mountPath: /usr/share/nginx/html/ - name: output-2 image: centos:6 command: [&#39;sh&#39;, &#39;-c&#39;, &#39;sleep 10; echo 2nd &gt;&gt; /usr/share/nginx/html/index.html&#39;] volumeMounts: - name: html-volume mountPath: /usr/share/nginx/html/ containers: - name: nginx-container image: nginx:1.12 volumeMounts: - name: html-volume mountPath: /usr/share/nginx/html/ volumes: - name: html-volume emptyDir: {} _EOF_</pre> <h1>kubectl exec による任意のコマンド実行と kubectl port-forward</h1> <p>Fargate ではコンテナ内の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%D0%A5%C3%A5%B0">デバッグ</a>がしづらいみたいな話をよく耳にします。kubectl exec も出来ないのだろうかと不安になりましたが、kubectl exec は通常通りできるようです。これはもはやほぼ <a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> ですね。</p> <pre class="code" data-lang="" data-unlink>$ kubectl exec -it sample-initcontainer -- cat /usr/share/nginx/html/index.html 1st 2nd</pre> <p>同様に kubectl port-forward や logs なんかも動きます。kubelet が Fargate 側にいそうな霊圧を感じますね。</p> <pre class="code" data-lang="" data-unlink>$ kubectl port-forward sample-2pod 30080:80 $ kubectl logs sample-2pod -c nginx-container</pre> <h1>現状の注意点</h1> <p>現状では、<a href="https://aws.amazon.com/jp/blogs/aws/amazon-eks-on-aws-fargate-now-generally-available/">ここ</a> にかかれている通り、下記の制約があるようです。まだファーストリリースなので、下記の要件で合わない方は <a class="keyword" href="http://d.hatena.ne.jp/keyword/AWS">AWS</a> の早い機能追加に期待というところですね。</p> <ul> <li>ポッドごとに最大 4 vCPU 30 Gb Memory の制約</li> <li>永続ボリュームまたは<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D5%A5%A1%A5%A4%A5%EB%A5%B7%A5%B9%A5%C6%A5%E0">ファイルシステム</a>を必要とするステートフルワークロードは非サポート</li> <li>DaemonSet、Privileged Pod、HostNetwork、HostPort などは利用不可</li> <li>使用可能な<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%ED%A1%BC%A5%C9%A5%D0%A5%E9%A5%F3%A5%B5%A1%BC">ロードバランサー</a>は、Application Load Balancer のみ</li> </ul> <h1>ALB <a class="keyword" href="http://d.hatena.ne.jp/keyword/Ingress">Ingress</a></h1> <p>EKS on Fargate で払い出される Pod の IP Address 帯は Subnet のものになっているため、従来どおり ALB から疎通可能なのでしょう(Container-native Load Balancing となる type: ip 前提)。一方で "type: LoadBalancer" Service も仕組み的には kube-proxy(の <a class="keyword" href="http://d.hatena.ne.jp/keyword/iptables">iptables</a> 等) で DNAT されているだけなので、遠くない将来にいずれ実現されるんじゃないかなと思います。</p> <p>または、通常 Node が一台以上あれば、 LB からそのノードに転送された後、kube-proxy が Pod 宛に DNAT して Fargate 側に転送されて上手くいくのでは…?という気もしているので、実験してみましょう(偏るという話は置いておいて)。</p> <h1>更に NodeGroup を追加してハイブリット構成にしてみる(type: LB も試してみる)</h1> <p>というわけで、まず NodeGroup を追加します。</p> <pre class="code" data-lang="" data-unlink>$ eksctl create nodegroup --cluster amsy810-cluster </pre> <p>するとノードの一覧はこんな感じになります。</p> <pre class="code" data-lang="" data-unlink>$ kubectl delete pod --all $ kubectl get node NAME STATUS ROLES AGE VERSION fargate-ip-192-168-129-12.ap-northeast-1.compute.internal Ready &lt;none&gt; 3h35m v1.14.8-eks fargate-ip-192-168-166-59.ap-northeast-1.compute.internal Ready &lt;none&gt; 3h33m v1.14.8-eks ip-192-168-6-3.ap-northeast-1.compute.internal Ready &lt;none&gt; 5m29s v1.14.7-eks-1861c5 ip-192-168-72-240.ap-northeast-1.compute.internal Ready &lt;none&gt; 5m29s v1.14.7-eks-1861c5</pre> <p>試しに "type: LoadBalancer" Service と Deployment をデプロイしてみましょう。</p> <pre class="code" data-lang="" data-unlink>$ kubectl apply -f https://raw.githubusercontent.com/MasayaAoyama/kubernetes-perfect-guide/master/samples/chapter06/sample-deployment.yaml $ kubectl apply -f https://raw.githubusercontent.com/MasayaAoyama/kubernetes-perfect-guide/master/samples/chapter06/sample-lb.yaml $ kubectl get pods -o wide NAME READY STATUS IP NODE sample-deployment-6cd85bd5f-4hwtt 1/1 Running 192.168.100.80 fargate-ip-192-168-100-80.ap sample-deployment-6cd85bd5f-pkn6b 1/1 Running 192.168.153.79 fargate-ip-192-168-153-79.ap sample-deployment-6cd85bd5f-xktr6 1/1 Running 192.168.130.33 fargate-ip-192-168-130-33.ap $ kubectl describe svc sample-lb | grep Endpoints Endpoints: 192.168.100.80:80,192.168.130.33:80,192.168.153.79:80</pre> <p>結論として、やはり読みどおり "type: LoadBalancer" も Worker Node があれば動くには動くようです。内部の実装上は、LB から Worker Node に転送された後、kube-proxy が DNAT で 各 Pod 宛に通信を転送するだけなので、Fargate Node まで <a class="keyword" href="http://d.hatena.ne.jp/keyword/VPC">VPC</a> 経由で疎通する仕組み上、疎通しているのだと思います。Fargate がどこにあるか次第ですが、Hop数自体は <a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> の Node またぎと同等なので、そこまでレイテンシは乗らないんじゃないかなと思っています。この仕組だと、Fargate + 通常 WorkerNode 両方に振り分けることもできそうですね。<strong>この方法がサポート対象な方法なのかは分かりません。</strong></p> <pre class="code" data-lang="" data-unlink>$ kubectl get svc sample-lb NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE sample-lb LoadBalancer 10.100.69.184 xxx-yyy.ap-northeast-1.elb.amazonaws.com 8080:30082/TCP 5m15s $ curl -I http://xxx-yyy.ap-northeast-1.elb.amazonaws.com:8080 HTTP/1.1 200 OK Server: nginx/1.12.2</pre> <p>なお、同様に ClusterIP も Pod 宛に転送されるだけなので、通常通り動きます。上手く出来ていますね。</p> <h1>まとめ</h1> <p>EKS on Fargate では、virtual-kubelet とは異なる形で実装されました。virtual-kubelet を実装しようとするとベンダー毎の違いがかなり大きいはずなので、なかなか皆で足並みを揃えて進めるのは難しかったのではないかなと思います。また、virtual-kubelet の kubelet バージョン(<a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a> バージョン)の追従という心配もなくなり、<a class="keyword" href="http://d.hatena.ne.jp/keyword/AWS">AWS</a> におまかせできるという大きなメリットもあります。</p> <p>EKS on Fargate を少し触った所感では、Warmpool された <a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> Node が後ろに待機していてくれるイメージに近いので、より PaaS っぽく <a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> を使いやすくなるんじゃないかと思います(周辺エコシステムや CI/CD 等の整備は必要ですが)。</p> <p>また、EKS は拡張性が高い反面、手放しで利用するには少しハードルがありましたが、最近は様々な機能開発で簡単に使う手段も増えてきて導入ハードルが下がってきたなと印象です。<a class="keyword" href="http://d.hatena.ne.jp/keyword/AWS">AWS</a> Container Roadmap(<a href="https://github.com/aws/containers-roadmap">https://github.com/aws/containers-roadmap</a>)にも <a href="https://github.com/aws/containers-roadmap/issues?utf8=%E2%9C%93&amp;q=is%3Aissue+is%3Aopen+managed">Managed</a> 系の Issue がたくさん上がっているので、拡張性を重視した使い方はもちろんですが、利便性の高い使い方も今後も増えていくのではないでしょうか。</p> <p>(いろんな <a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A1%BC%A5%AD%A5%C6%A5%AF%A5%C1%A5%E3">アーキテクチャ</a>が出てきて楽しいぞ)</p> <h1>Fargate profile なくても動くのでは…?と言われたので試しました(12/4 16:50 追記)</h1> <p><blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">ということは、Fargate Profile 作らなくても直接 schedulerName: fargate-scheduler を指定すれば Pod が立ち上がるのでは…?</p>&mdash; チェシャ猫 (@y_taka_23) <a href="https://twitter.com/y_taka_23/status/1202131314389872641?ref_src=twsrc%5Etfw">2019年12月4日</a></blockquote><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></p> <p>ちゃんと Scheduler の方で Profile も見ているようですね。なんか悪いこと(抜け道探し)してる気分になってきました。</p> <pre class="code" data-lang="" data-unlink>$ kubectl create ns newone $ cat &lt;&lt; _EOF_ | kubectl apply -f - apiVersion: v1 kind: Pod metadata: name: sample-pod-manual-fargate namespace: newone spec: schedulerName: fargate-scheduler containers: - name: nginx-container image: nginx:1.12 _EOF_ $ kubectl describe pods sample-pod-manual-fargate -n newone Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning FailedScheduling &lt;unknown&gt; fargate-scheduler Misconfigured Fargate Profile: pod does not have profile label eks.amazonaws.com/fargate-profile $ cat &lt;&lt; _EOF_ | kubectl apply -f - apiVersion: v1 kind: Pod metadata: name: sample-pod-manual-fargate namespace: newone labels: eks.amazonaws.com/fargate-profile: fp-default spec: schedulerName: fargate-scheduler containers: - name: nginx-container image: nginx:1.12 _EOF_ $ kubectl describe pods sample-pod-manual-fargate -n newone Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning FailedScheduling &lt;unknown&gt; fargate-scheduler Misconfigured Fargate Profile: pod&#39;s namespace does not match the ones listed in fargate profile fp-default</pre> <h1>何が嬉しいのか考えてみた(追記:随時更新します)</h1> <ul> <li>ノードの種別管理とかは不要になり、ピッタリなサイズでサービスを提供できる(4core? 8core? とか)</li> <li>ノイ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B8%A1%BC">ジー</a>ネイバーの影響も受けにくい(Fargate 側では集約しているので、そこの影響はあるかも)</li> <li>Pod単位でノードがいるので、通常のノードでぴったりにしようとした際に発生するオートスケーラのスケールインの影響みたいなものを受けない</li> </ul> masaya_aoyama Hierarchical Namespace で Namespace を階層構造に管理してオブジェクトを伝搬させる hatenablog://entry/26006613474679256 2019-12-01T23:08:22+09:00 2019-12-12T10:16:59+09:00 (12/4 11:00 requiredChild について追記) こんにちは。CyberAgent の青山(@amsy810)です。 この記事は Advent Calendar 1日目の記事です。 毎回なぜ一日目にしてしまったんだろうかと後悔します。 今回は、KubeCon + CloudNativeCon NA 2019 で併設実施された Kubernetes Contributors Summit で聞いて気になっていた、Kubernetes Multi-tenancy WG で開発が進められている、Hierarchical Namespace のお話をします。 一言で言うならば、これは… <p>(12/4 11:00 requiredChild について追記)</p> <p>こんにちは。<a class="keyword" href="http://d.hatena.ne.jp/keyword/CyberAgent">CyberAgent</a> の青山(@amsy810)です。</p> <p>この記事は Advent Calendar 1日目の記事です。 毎回なぜ一日目にしてしまったんだろうかと後悔します。</p> <p>今回は、<strong>KubeCon + CloudNativeCon NA 2019</strong> で併設実施された <strong><a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> Contributors Summit</strong> で聞いて気になっていた、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> Multi-tenancy WG で開発が進められている、<strong>Hierarchical Namespace</strong> のお話をします。</p> <p>一言で言うならば、これは <strong>「Namespace に階層構造の概念を取り入れて、ポリシーやSecretなどのリソースを伝搬させる仕組み」</strong> です。 マイクロサービスチームや組織構造の都合上、同じオブジェクト(ConfigMap, Namespace, ResourceQuota, LimitRange, NetworkPolicy)を登録しておきたいケースは多々あると思います。 また、RBAC の設定を伝搬させることで、下位のチームに権限移譲の設定を上手く扱うことも可能です。</p> <h1>事前準備</h1> <p>事前準備として kubectl と kustomize をインストールしておいてください。 また、今回は下記のバージョンで実施しました。</p> <ul> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a>: v1.16.0</li> <li>Kustomize: v3.4.0</li> <li>Hierarchical Namespace Controller: 7db19627f5d21a7a368beaa9d7b9be177d5bb26a (Git commit hash)</li> </ul> <h1>Hierarchical Namespace Controller (HNC)のインストール</h1> <p>Hierarchical Namespace Controller は Multi-tenancy WG の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%DD%A5%B8%A5%C8%A5%EA">リポジトリ</a>の中に<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8">ディレクト</a>リが切られ、開発が進められています。 なお、Hierarchical Namespace Controller は現状まだ "very early software" と言われている通り、PoC 相当の Controller です。</p> <p><a href="https://twitter.com/aludwin/status/1196520861554991104?s=20">https://twitter.com/aludwin/status/1196520861554991104?s=20</a></p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BD%A1%BC%A5%B9%A5%B3%A1%BC%A5%C9">ソースコード</a>を落としてきて、make deploy することで<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>にインストールする事が可能です。今回は、 <strong>masayaaoyama/hnc-controller:7db1962</strong> にビルドしたイメージを公開してあります。</p> <pre class="code" data-lang="" data-unlink>cd git clone https://github.com/kubernetes-sigs/multi-tenancy.git # curl -o https://raw.githubusercontent.com/kubernetes-sigs/multi-tenancy/master/incubator/hnc/hack/hnc.yaml cd multi-tenancy/incubator/hnc IMG=masayaaoyama/hnc-controller:$(git rev-parse --short HEAD) GOPATH=~/go make deploy</pre> <h1>階層化された Namespace の作成</h1> <p>Namespace を作成します。今回は特定のプロジェクトの Namespace (sample-project)を起点として、3階層で構成されている構造を作り出します。</p> <p>root の Namespace を作成したら、それぞれに親子関係を作るため、 <strong>kubectl hnc</strong> コマンドを実行します。なお、このコマンドは kubectl plugins が <strong>make deploy</strong> した際にインストールされています。 実質的には後で説明する <strong>HierarchyConfiguration</strong> リソースの操作をしているだけです。</p> <pre class="code" data-lang="" data-unlink>kubectl hnc set sample-project --requiredChild team-a kubectl hnc set sample-project --requiredChild team-b kubectl hnc set team-a --requiredChild team-a-service1 kubectl hnc set team-a --requiredChild team-a-service2 kubectl hnc set team-b --requiredChild team-b-service1 kubectl hnc set team-b --requiredChild team-b-service2 kubectl hnc set team-b --requiredChild team-b-service3</pre> <p>作成したあとに、Namespace の階層構造を確認してみると、下記のとおりです。 正しく3層の構造が出来ていることが確認できます。</p> <pre class="code" data-lang="" data-unlink>$ kubectl hnc tree --all-namespaces cert-manager default docker hnc-system kube-node-lease kube-public kube-system sample-project ├── team-a │ ├── team-a-service1 │ └── team-a-service2 └── team-b ├── team-b-service1 ├── team-b-service2 └── team-b-service3</pre> <p><code>--requiredChild</code> を指定して作成した Namespace が消された場合、reconcile されて再度 Namespace が作成されます。また、「kubectl hnc set team-a --parent sample-project」というコマンドで、この Namespace 作成の reconcile を無効化した状態で階層構造を作ることも可能です。</p> <pre class="code" data-lang="" data-unlink>$ kubectl delete ns team-a namespace &#34;team-a&#34; deleted $ kubectl hnc tree sample-project sample-project ├── team-a │ ├── team-a-service1 │ └── team-a-service2 └── team-b ├── team-b-service1 ├── team-b-service2 └── team-b-service3</pre> <h1>ポリシーの伝搬の確認</h1> <p>今回は、ConfigMap リソースを作成し、正しくオブジェクトが伝搬していることを確認します。 <strong>sample-project</strong> 直下に作成した <strong>web-config</strong> オブジェクトは 8 つの Namespace(伝搬したのは 7 つ)に作られているのに対し、<strong>team-a</strong> 直下に作成した <strong>web-config2</strong> オブジェクトは 3 つの Namespace(伝搬したのは 2 つ)に作られています。</p> <pre class="code" data-lang="" data-unlink>$ kubectl -n sample-project create configmap web-config --from-literal=connection.max=100 $ kubectl -n team-a create configmap web-config2 --from-literal=connection.max=200 # 並び順は見やすいように変えています $ kubectl get configmap -A | grep &#34;web-config &#34; sample-project web-config 1 57s team-a web-config 1 57s team-a-service1 web-config 1 57s team-a-service2 web-config 1 57s team-b web-config 1 57s team-b-service1 web-config 1 57s team-b-service2 web-config 1 57s team-b-service3 web-config 1 56s team-a web-config2 1 42s team-a-service1 web-config2 1 42s team-a-service2 web-config2 1 42s</pre> <p>ポリシー系のオブジェクトのみ親から子へ Sync される様になっています。</p> <p>伝搬対象のオブジェクトは、下記の 7 種類です。 <a href="https://github.com/kubernetes-sigs/multi-tenancy/blob/master/incubator/hnc/pkg/config/gvk.go#L14">https://github.com/kubernetes-sigs/multi-tenancy/blob/master/incubator/hnc/pkg/config/gvk.go#L14</a></p> <pre class="code" data-lang="" data-unlink>var GVKs = []schema.GroupVersionKind{ {Group: &#34;&#34;, Version: &#34;v1&#34;, Kind: &#34;Secret&#34;}, {Group: &#34;rbac.authorization.k8s.io&#34;, Version: &#34;v1&#34;, Kind: &#34;Role&#34;}, {Group: &#34;rbac.authorization.k8s.io&#34;, Version: &#34;v1&#34;, Kind: &#34;RoleBinding&#34;}, {Group: &#34;networking.k8s.io&#34;, Version: &#34;v1&#34;, Kind: &#34;NetworkPolicy&#34;}, {Group: &#34;&#34;, Version: &#34;v1&#34;, Kind: &#34;ResourceQuota&#34;}, {Group: &#34;&#34;, Version: &#34;v1&#34;, Kind: &#34;LimitRange&#34;}, {Group: &#34;&#34;, Version: &#34;v1&#34;, Kind: &#34;ConfigMap&#34;}, }</pre> <p>なお、"type: <a class="keyword" href="http://d.hatena.ne.jp/keyword/kubernetes">kubernetes</a>.io/service-account-token" の Secret は除外されています。 <a href="https://github.com/kubernetes-sigs/multi-tenancy/blob/7db19627f5d21a7a368beaa9d7b9be177d5bb26a/incubator/hnc/pkg/controllers/object_controller.go#L303-L326">https://github.com/kubernetes-sigs/multi-tenancy/blob/7db19627f5d21a7a368beaa9d7b9be177d5bb26a/incubator/hnc/pkg/controllers/object_controller.go#L303-L326</a></p> <p>個人的には ServiceAccount も sync してほしい気がしますが、何かしらの理由があるのでしょう。</p> <h1>階層構造の仕組み</h1> <p>階層構造は <strong>HierarchyConfiguration</strong> リソースを利用して実現しています。 このリソースには、 <strong>spec.parent</strong> と <strong>spec.requiredChildren</strong> のフィールドが用意されており、<strong>kubectl hnc set team-a --requiredChild team-a-service1</strong> および <strong>kubectl hnc set team-a --requiredChild team-a-service2</strong> コマンドを実行すると、 <strong>team-a</strong> Namespace に <strong>hierarchy</strong> という名前の <strong>HierarchyConfiguration</strong> リソースが作成されます。 また、status にはその Namespace の子 Namespace が追加されるようになっています。</p> <pre class="code" data-lang="" data-unlink>$ kubectl get hierarchyconfigurations -n team-a hierarchy -o yaml apiVersion: hnc.x-k8s.io/v1alpha1 kind: HierarchyConfiguration metadata: creationTimestamp: &#34;2019-11-30T16:27:49Z&#34; generation: 5 name: hierarchy namespace: team-a resourceVersion: &#34;20753&#34; selfLink: /apis/hnc.x-k8s.io/v1alpha1/namespaces/team-a/hierarchyconfigurations/hierarchy uid: 29a4e049-85fa-4e95-adb3-3826a6fe1255 spec: parent: sample-project requiredChildren: - team-a-service1 - team-a-service2 status: children: - team-a-service1 - team-a-service2</pre> <p>なお、子 Namespace にコピーされたオブジェクトには、コピー元の親 Namespace 名がラベルとして付与されています( <strong>hnc.x-<a class="keyword" href="http://d.hatena.ne.jp/keyword/k8s">k8s</a>.io/inheritedFrom</strong> )。</p> <pre class="code" data-lang="" data-unlink>$ kubectl -n team-a-service1 get configmap web-config2 -o yaml apiVersion: v1 kind: ConfigMap metadata: annotations: labels: hnc.x-k8s.io/inheritedFrom: team-a data: connection.max: &#34;100&#34;</pre> <p>なお、<strong>sample-project</strong> から伝搬されている <strong>web-config</strong> team-a のデータを消した場合は、team-a 配下の Namespace の <strong>web-config</strong> オブジェクトがすべて削除されます。</p> <pre class="code" data-lang="" data-unlink>$ kubectl delete configmap web-config -n team-a configmap &#34;web-config&#34; deleted $ kubectl get configmap -A | grep &#34;web-config &#34; sample-project web-config 1 48m team-b-service1 web-config 1 48m team-b-service2 web-config 1 48m team-b-service3 web-config 1 48m team-b web-config 1 48m</pre> <p>プロポーザルには「HNCによって伝播されるオブジェクトは、変更または削除できない」と書いてありましたが、現状は削除可能になっています。 現状では、子の Namespace に登録されているリソースを削除できてしまうので削除すると、復元されないので注意してください。将来的には ValidationWebhook などが入るのだと思います。</p> <p>なお、親 Namespace のオブジェクトを削除した場合は、子 Namespace のオブジェクトも<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BA%C6%B5%A2">再帰</a>的に削除していきます。</p> <h1>もう少し DeepDive</h1> <p>Hierarchical Namespace Controller (HNC)は大きく分けて下記の 2 つの Controller( <strong>Hierarchy Controller</strong> , <strong>Object Controller</strong> )から構成されています。 kube-controller-manager と同じような構成ですね。</p> <ul> <li>Hierarchy Controller <ul> <li>HierarchyConfiguration から Namespace の階層構造を status に書き込む</li> <li>同様に Labels の付与なども行っている</li> </ul> </li> <li>Object Controller <ul> <li>親 Namespace のオブジェクトを子 Namespace にコピーするコントローラ</li> </ul> </li> </ul> <h2>Hierarchy Controller</h2> <p>reconcile 関数はこの辺りから。 <a href="https://github.com/kubernetes-sigs/multi-tenancy/blob/master/incubator/hnc/pkg/controllers/hierarchy_controller.go#L104">https://github.com/kubernetes-sigs/multi-tenancy/blob/master/incubator/hnc/pkg/controllers/hierarchy_controller.go#L104</a></p> <p>実際に Label を付与したり、status を更新する処理は下記のあたりから呼び出されています。(書き込みは別途) <a href="https://github.com/kubernetes-sigs/multi-tenancy/blob/master/incubator/hnc/pkg/controllers/hierarchy_controller.go#L149">https://github.com/kubernetes-sigs/multi-tenancy/blob/master/incubator/hnc/pkg/controllers/hierarchy_controller.go#L149</a></p> <h2>Object Controller</h2> <p>Recncile 関数はこの辺りから。 <a href="https://github.com/kubernetes-sigs/multi-tenancy/blob/7db19627f5d21a7a368beaa9d7b9be177d5bb26a/incubator/hnc/pkg/controllers/object_controller.go#L51">https://github.com/kubernetes-sigs/multi-tenancy/blob/7db19627f5d21a7a368beaa9d7b9be177d5bb26a/incubator/hnc/pkg/controllers/object_controller.go#L51</a></p> <p>オブジェクトをコピーしてるのはこの辺り。(inst オブジェクトを dests[] namespaces にコピー) <a href="https://github.com/kubernetes-sigs/multi-tenancy/blob/7db19627f5d21a7a368beaa9d7b9be177d5bb26a/incubator/hnc/pkg/controllers/object_controller.go#L217-L252">https://github.com/kubernetes-sigs/multi-tenancy/blob/7db19627f5d21a7a368beaa9d7b9be177d5bb26a/incubator/hnc/pkg/controllers/object_controller.go#L217-L252</a></p> <h1><a class="keyword" href="http://d.hatena.ne.jp/keyword/GCP">GCP</a> の Anthos でも階層構造の伝搬の仕組みがあるらしい?</h1> <p>また、Anthos Config Management にも同様に階層構造に伝搬するように、Git<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%DD%A5%B8%A5%C8%A5%EA">リポジトリ</a>内で階層構造を作って同様のことをしているようです。(Anthos 触ってみたい)</p> <blockquote><p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a>’s Anthos Config Management (<a class="keyword" href="http://d.hatena.ne.jp/keyword/ACM">ACM</a>) supports a similar model to this proposal by modelling a namespace hierarchy in the filesystem of a monolithic Git repo, and copies objects from parent namespaces to child namespaces in a <a class="keyword" href="http://d.hatena.ne.jp/keyword/K8s">K8s</a> apiserver. By contrast, the Hierarchical Namespace Controller (HNC) operates entirely within a <a class="keyword" href="http://d.hatena.ne.jp/keyword/K8s">K8s</a> apiserver and makes use of CRDs in the namespaces to express hierarchy.<a class="keyword" href="http://d.hatena.ne.jp/keyword/ACM">ACM</a> may allow the use of HNC in the future if it becomes sufficiently mature.</p></blockquote> <h1>より詳しく知りたい方は</h1> <p>これ以上の詳細は下記の Design Docs に載っています。興味のある方はぜひ見てみてください。 (12/1 が過ぎてしまうので、この辺りで…) <a href="https://docs.google.com/document/d/10MZfFfbQMm33CBboMq2bfrEtXkJQQT4-UH4DDXZRrKY/edit#">https://docs.google.com/document/d/10MZfFfbQMm33CBboMq2bfrEtXkJQQT4-UH4DDXZRrKY/edit#</a></p> masaya_aoyama Kubernetes は辛いのか? hatenablog://entry/17680117127006278933 2019-04-03T07:18:58+09:00 2019-04-03T14:47:02+09:00 こんにちは。 @amsy810 です。 下記のブログが出てから『Kubernetes は運用しきれない』と耳にすることが多くなってきたので、雰囲気で曲解されて Kubernetes is difficult とならないよう、マネージドでシンプルに使うだけなら難しくないよと伝えるために書きました。 Kubernetes がいいよと伝えるためではありません。 yakst.com TL;DR 上記のブログについては概ね同意見です。 辛いのは自前で Kubernetes クラスタの管理自体を行う場合です。 GKE などのマネージド Kubernetes サービスを利用するケースでは、Kubernete… <p>こんにちは。 <a href="https://twitter.com/amsy810">@amsy810</a> です。</p> <p>下記のブログが出てから『<a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> は運用しきれない』と耳にすることが多くなってきたので、雰囲気で曲解されて <a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> is difficult とならないよう、マネージドでシンプルに使うだけなら難しくないよと伝えるために書きました。</p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> がいいよと伝えるためではありません。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fyakst.com%2Fja%2Fposts%2F5455" title="多分あなたにKubernetesは必要ない | Yakst" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://yakst.com/ja/posts/5455">yakst.com</a></cite></p> <h1>TL;DR</h1> <p>上記のブログについては概ね同意見です。</p> <p>辛いのは自前で <a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>の管理自体を行う場合です。</p> <p>GKE などのマネージド <a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> サービスを利用するケースでは、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> の管理は殆ど必要がなくなります。</p> <p>例えば GKE の場合には、自動<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>アップグレード・自動<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>スケーリングなどが用意されています。他にも自動ノードプロビジョニング機能(CPU・メモリ・<a class="keyword" href="http://d.hatena.ne.jp/keyword/GPU">GPU</a> の割り当て要求に従って、良い感じのノードを自動で<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>に追加・削除する)を利用すると <strong>ノードの管理ですら必要なくなり</strong> 、抽象度の高い(利便性の高い)基盤として利用することが可能です。</p> <p>また、アプリケーション開発者として <a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> を利用するだけなら実際は非常にシンプルに利用することが可能です。</p> <p><strong>マネージド <a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> を使えるなら、開発者として利用するだけなのでそこまで難しくありません。</strong></p> <h1>前提条件</h1> <p><strong>コンテナを利用するべきかや、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Nomad">Nomad</a>・ECS・<a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> といったオーケストレータ(あるいは Fargate など)を利用するべきか否かというところについては述べません。この辺りが必要な方向けに書いています。なんだかんだ <a class="keyword" href="http://d.hatena.ne.jp/keyword/VM">VM</a> のワークロードが必要というケースも多々あるでしょう。また、PaaS も良いと思います。あくまでコンテナオーケストレータだけの話をしています。</strong></p> <p>この前提は、再現性・管理性・復元力・可観測性・自動化・<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C1%C2%B7%EB%B9%E7">疎結合</a>性といった特性を組織が享受できる状態か(享受したい状態か)どうかによって異なります。</p> <p>なお、すでに<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%A6%A5%C9">クラウド</a>を利用している組織で新規プロジェクトの技術選定なのだとしたら、ステートフルなものはマネージドサービスを利用しつつステートレスなアプリケーションに利用していくことは障壁も少なくおすすめです。</p> <h1>どのオーケストレータを選択すべきか</h1> <p>国内では選択したオーケストレーターを今後も長く使っていくケースが非常に多くなるかと思います。</p> <p>海外では大規模な<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%A6%A5%C9">クラウド</a>間の移行やプラットフォームの移行をやってのけるケースも多々あるため、その気概があるなら正直何から始めてもいいと思います。</p> <p>日本にはなかなか真似できない部分ですね。</p> <p>なるべく塩漬けにしたい場合には、「拡張性がある」「コミュニティが活発」「エコシステムが豊富」といったあたりの長く利用できるかどうか、やりたいことが増えた際に<a class="keyword" href="http://d.hatena.ne.jp/keyword/%CB%E2%B2%FE%C2%A4">魔改造</a>しないで済むかどうかという点を考慮すべきだと思います。</p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/OSS">OSS</a> だと下火になった際の影響が大きいため、選択肢がいくつかある際は個人的にはこういったところを重視しています。</p> <p>ECS などのマネージドサービスに関しては、今後もあまり心配はないと思います。</p> <p>ただ忘れないで欲しいのが、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> であっても <strong>アプリケーション開発者から見ると「シンプルにも利用可能」</strong> であるという点です(あとで紹介します)。</p> <p>でも流石に PaaS の利便性には勝てないとは思います。あくまでオーケストレータを純粋に比較した場合です。</p> <h1>オンプレで <a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> を選択するべきか?</h1> <p><strong>オンプレ上で</strong> <a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> をやろうとするのであれば、少なくとも少人数で選択することはオススメしません。</p> <p>やるとしてもサポート付きの商用 <a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%B9%A5%C8%A5%EA%A5%D3%A5%E5%A1%BC%A5%B7%A5%E7%A5%F3">ディストリビューション</a>を利用するか、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> を専門に面倒をみるチームが必要でしょう。</p> <p>trivago さんのケースでも 4 人チームでオンプレ上に構築して利用するというものだったので、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> はかなりオーバーだと思います。</p> <h1>利用者としての <a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a></h1> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> を利用するということは、 <strong><a class="keyword" href="http://d.hatena.ne.jp/keyword/GCP">GCP</a>・<a class="keyword" href="http://d.hatena.ne.jp/keyword/AWS">AWS</a>・Azure といった<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D1%A5%D6%A5%EA%A5%C3%A5%AF%A5%AF%A5%E9%A5%A6%A5%C9">パブリッククラウド</a>を利用するのと近しいもの</strong> だと考えています。</p> <p>そのため、当然<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D1%A5%D6%A5%EA%A5%C3%A5%AF%A5%AF%A5%E9%A5%A6%A5%C9">パブリッククラウド</a>自体を自前で構築して運用することを少人数で成し遂げることは困難です(例:OpenStack)。</p> <p>一方で利用者から見ると<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D1%A5%D6%A5%EA%A5%C3%A5%AF%A5%AF%A5%E9%A5%A6%A5%C9">パブリッククラウド</a>は非常に便利かつ高機能ですね。</p> <p>そのためアプリケーション開発者がどの環境でやるのが一番楽かという面では、マネージド <a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> サービスを利用するのが一番だと思います。</p> <p><strong>管理された <a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> 上でコンテナを起動させる場合、コンテナを起動させてくれる抽象度の高いマネージドサービスと余り差はない</strong> と思います。</p> <p>例えば、シンプルに利用するだけであれば <a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> でも 下記のように Deployment リソース(コンテナを起動する)と Service リソース(ロードバランサ)の2つだけを使っても達成できます。</p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D1%A5%D6%A5%EA%A5%C3%A5%AF%A5%AF%A5%E9%A5%A6%A5%C9">パブリッククラウド</a>でも全ての機能を把握して選択することはないのと同様に、そのほかのリソース(機能)に関してはやりたいことが出来た際にやり方を調べれば良いと思います。その時にできることがたくさんあった方が良いとは思います。</p> <pre class="code lang-yaml" data-lang="yaml" data-unlink><span class="synPreProc">---</span> <span class="synIdentifier">apiVersion</span><span class="synSpecial">:</span> apps/v1 <span class="synIdentifier">kind</span><span class="synSpecial">:</span> Deployment <span class="synIdentifier">metadata</span><span class="synSpecial">:</span> <span class="synIdentifier">name</span><span class="synSpecial">:</span> sample-deployment <span class="synIdentifier">spec</span><span class="synSpecial">:</span> <span class="synIdentifier">replicas</span><span class="synSpecial">:</span> <span class="synConstant">3</span> <span class="synIdentifier">selector</span><span class="synSpecial">:</span> <span class="synIdentifier">matchLabels</span><span class="synSpecial">:</span> <span class="synIdentifier">app</span><span class="synSpecial">:</span> sample-app <span class="synIdentifier">template</span><span class="synSpecial">:</span> <span class="synIdentifier">metadata</span><span class="synSpecial">:</span> <span class="synIdentifier">labels</span><span class="synSpecial">:</span> <span class="synIdentifier">app</span><span class="synSpecial">:</span> sample-app <span class="synIdentifier">spec</span><span class="synSpecial">:</span> <span class="synIdentifier">containers</span><span class="synSpecial">:</span> <span class="synStatement">- </span><span class="synIdentifier">name</span><span class="synSpecial">:</span> nginx-container <span class="synIdentifier">image</span><span class="synSpecial">:</span> nginx:1.13 <span class="synIdentifier">ports</span><span class="synSpecial">:</span> <span class="synStatement">- </span><span class="synIdentifier">containerPort</span><span class="synSpecial">:</span> <span class="synConstant">80</span> <span class="synPreProc">---</span> <span class="synIdentifier">apiVersion</span><span class="synSpecial">:</span> v1 <span class="synIdentifier">kind</span><span class="synSpecial">:</span> Service <span class="synIdentifier">metadata</span><span class="synSpecial">:</span> <span class="synIdentifier">name</span><span class="synSpecial">:</span> sample-lb <span class="synIdentifier">spec</span><span class="synSpecial">:</span> <span class="synIdentifier">type</span><span class="synSpecial">:</span> LoadBalancer <span class="synIdentifier">ports</span><span class="synSpecial">:</span> <span class="synStatement">- </span><span class="synIdentifier">name</span><span class="synSpecial">:</span> <span class="synConstant">&quot;http-port&quot;</span> <span class="synIdentifier">protocol</span><span class="synSpecial">:</span> <span class="synConstant">&quot;TCP&quot;</span> <span class="synIdentifier">port</span><span class="synSpecial">:</span> <span class="synConstant">80</span> <span class="synIdentifier">selector</span><span class="synSpecial">:</span> <span class="synIdentifier">app</span><span class="synSpecial">:</span> sample-app </pre> <p>なおCI/CD では、上記の様な<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%CB%A5%D5%A5%A7%A5%B9%A5%C8">マニフェスト</a>のボイラープレートを作って使い回すことが可能です。</p> <h1><a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> を採択する規模は?</h1> <p>規模が大きい方が得られる恩恵は大きくなりますが、小さい規模でも恩恵は大きいと思います。</p> <p>ただし、小さい規模の場合は人員も少ないため、そこを担当できる(したい)エンジニアがいるかという点につきますね。</p> <h1><a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> は抽象度の高い環境を提供できるか?</h1> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> も HorizontalPodAutoscaler・ClusterAutoscaler や Knative などを利用することにより、PaaS のような抽象度の高い(利便性の高い)環境を提供することは可能です。</p> <p>いわゆる Fargate に近しい何かも設定次第では実現できます。</p> <h1><a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> へ移行するべきか?</h1> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Nomad">Nomad</a>・ECS・<a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> など様々なコンテナオーケストレータが存在します。</p> <p>ECS・<a class="keyword" href="http://d.hatena.ne.jp/keyword/Nomad">Nomad</a> のいずれも足りない機能を補う様にアップデートを重ねてきており、徐々に <a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> にしか無かった機能が実装されてきています。</p> <p>そのため、すでに ECS や <a class="keyword" href="http://d.hatena.ne.jp/keyword/Nomad">Nomad</a> で稼働している場合には <a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> に移行するメリットは大きくないと思います。</p> <p>既存のレガシーな環境から移行するべきかという点についても同等なのですが、もし今後もシステムが改修され続けていく状況で移行コストをかけられる様であれば移行も選択肢の一つです。</p> <p>主軸としては移行しなければ開発効率が上がらないかどうかが判断材料ですね。</p> <h1>(余談)オンプレ上で <a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> をやると良いところ</h1> <p>基本的にオンプレ上で Database as a Service や Queue as a Service などを実現するのは運用コストや仕組みづくりが大変です。</p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> の周辺エコシステムを利用することでマネージドサービスを <a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> 上で展開することも可能になってきています(<a class="keyword" href="http://d.hatena.ne.jp/keyword/mysql">mysql</a>-operator、Vitess、NATS など)。</p> <p>そのため、オンプレ上での <a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> には<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D7%A5%E9%A5%A4%A5%D9%A1%BC%A5%C8%A5%AF%A5%E9%A5%A6%A5%C9">プライベートクラウド</a>の充実という可能性も感じています。</p> <h1>まとめ</h1> <p>技術選定は組織ごとに好みがあると思うので、あくまでも個人の見解です。</p> <p>何を選択するにせよ、様々な情報を元に適切に判断すれば良いと思います。</p> <p>雰囲気で曲解されて <a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> is difficult とならないよう、あくまで <a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> の苦手意識がなくなるためだけに、一意見として書いてみました。</p> <h1>まとめのまとめ(心の声)</h1> <p>(<a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a>、いいよ。)</p> <h1>追記 (4/3 15:00)</h1> <p>何度も言いますが、どの環境を使っても良いと思います。コードを書いたら良い感じにしてくれるのが目的です。PaaS でも ECS でも <a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> でもアプリケーション開発者<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A4%AB%A4%E9%A4%B7">からし</a>たらなんでも良いでしょう。</p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> も頑張って CI/CD 整備や<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%CB%A5%D5%A5%A7%A5%B9%A5%C8">マニフェスト</a>を書く人がいることによって PaaS の様にして利用しています。</p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> は本当に素の Platform なので、ちゃんとした CI/CD がないとアプリケーション開発に集中できる環境を提供するという目的は達成できません。そのため、あくまでもインフラや SRE にある程度知見のあるメンバーは必要でしょう。</p> <p>環境を整備すると PaaS も <a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> も <a class="keyword" href="http://d.hatena.ne.jp/keyword/Nomad">Nomad</a> も ECS もいちアプリケーション開発者からすると透過的なのが良い形だと思います。</p> <p>正直単純にオーケストレータを利用する範囲であれば、その学習コストよりもその周辺の考えなきゃいけないこの方が辛いです。</p> <p>また、どのオーケストレータを選択しても従来の <a class="keyword" href="http://d.hatena.ne.jp/keyword/VM">VM</a> で環境を作った時にはいずれも近しい程度の学習コストはかかると思っていた方が良いです。</p> masaya_aoyama さくらインターネット研究所 に 客員研究員 としてジョインしました。 hatenablog://entry/17680117126995689950 2019-03-25T08:38:06+09:00 2019-03-25T08:42:47+09:00 こんにちは。amsy810です。 春といえば新しいことを始める時期ですね。 4/1 より さくらインターネット研究所 さんに 客員研究員 としてジョインしました。 新しい経験もしてみたいと思い下記のようなツイートをしたところ、ありがたいことにお誘いを頂いたため新しい挑戦を始めることになりました。 せっかく Portfolio 作ったのと、新しいことを初めてみたくなったので、副業等を探しはじめてみました。(もしスキルセット的にお手伝いできることがあればご連絡ください。)https://t.co/pookSVvJX4 https://t.co/u629B3VP1r— MasayaAoyama(青山… <p>こんにちは。<a href="https://twitter.com/amsy810">amsy810</a>です。</p> <p>春といえば新しいことを始める時期ですね。</p> <p>4/1 より <strong><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A4%B5%A4%AF%A4%E9%A5%A4%A5%F3%A5%BF%A1%BC%A5%CD%A5%C3%A5%C8">さくらインターネット</a>研究所 さんに 客員研究員 としてジョイン</strong>しました。</p> <p>新しい経験もしてみたいと思い下記のようなツイートをしたところ、ありがたいことにお誘いを頂いたため新しい挑戦を始めることになりました。</p> <p><blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">せっかく Portfolio 作ったのと、新しいことを初めてみたくなったので、副業等を探しはじめてみました。<br>(もしスキルセット的にお手伝いできることがあればご連絡ください。)<a href="https://t.co/pookSVvJX4">https://t.co/pookSVvJX4</a> <a href="https://t.co/u629B3VP1r">https://t.co/u629B3VP1r</a></p>&mdash; MasayaAoyama(青山 真也) (@amsy810) <a href="https://twitter.com/amsy810/status/1095114330679341056?ref_src=twsrc%5Etfw">2019年2月12日</a></blockquote><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></p> <p><a href="https://twitter.com/matsumotory">まつもとりーさん</a>からDMで連絡があったのですが、予想外なお話だったので最初は驚きました。 普段からまつもとりーさんのブログなどはウォッチしていたので、お話をいただいた時点で面白そうだなというのは明白でした。</p> <p>ご存知の方も多いかと思いますが、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A4%B5%A4%AF%A4%E9%A5%A4%A5%F3%A5%BF%A1%BC%A5%CD%A5%C3%A5%C8">さくらインターネット</a>研究所さんでは「<a href="https://research.sakura.ad.jp/2019/02/22/concept-vision-2019">超個体型データセンター</a>」についての研究を行なっております。 私もこの辺りのお話に携わらせていただく予定です。</p> <p><figure class="figure-image figure-image-fotolife" title="さくらインターネット研究所 中長期ビジョン"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/masaya_aoyama/20190322/20190322022125.png" alt="f:id:masaya_aoyama:20190322022125p:plain" title="f:id:masaya_aoyama:20190322022125p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A4%B5%A4%AF%A4%E9%A5%A4%A5%F3%A5%BF%A1%BC%A5%CD%A5%C3%A5%C8">さくらインターネット</a>研究所 中長期ビジョン</figcaption></figure></p> <p>詳しくは所長の鷲北さんがまとめています。他にもまつもとりーさんや <a href="https://research.sakura.ad.jp/about/">研究所のみなさま</a> がまとめた記事もたくさんあるので、探してみてください。(エキスパートのみなさまとお仕事をするのは緊張します。)</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fresearch.sakura.ad.jp%2F2019%2F02%2F22%2Fconcept-vision-2019" title="超個体型データセンターを目指す当研究所のビジョン" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://research.sakura.ad.jp/2019/02/22/concept-vision-2019">research.sakura.ad.jp</a></cite></p> <p>数年後に期待されるであろう技術を考えることや、大規模な<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%A6%A5%C9">クラウド</a>事業者の向かう方向性に触れられるのは楽しみです。 最近では "Cloud Native" が広まってきましたが、次のプラットフォームになるようなコアコンセプトなどを考えていけたらと思っております。</p> <p>また、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A4%B5%A4%AF%A4%E9%A5%A4%A5%F3%A5%BF%A1%BC%A5%CD%A5%C3%A5%C8">さくらインターネット</a>さんも <a href="https://www.sakura.ad.jp/information/pressreleases/2018/06/27/90224/">CNCF(Cloud Native Computing Foundation)にシルバーメンバーとして参加</a>しています。</p> <p>再びですが、<strong> <a class="keyword" href="http://d.hatena.ne.jp/keyword/CyberAgent">CyberAgent</a> を退職するわけではありません。</strong> しっかりとメリハリをつけて本業も頑張りつつ、新しい経験を通じて CA でも引き続き頑張ります。</p> masaya_aoyama クリエーションラインに 技術アドバイザー としてジョインしました。 hatenablog://entry/17680117126995657086 2019-03-22T08:04:48+09:00 2019-03-25T23:17:57+09:00 こんにちは。amsy810です。 春といえば新しいことを始める時期ですね。 3/18 より クリエーションラインさんに 技術アドバイザー としてジョインしました。 今とは異なる要件で新しい経験もしてみたいと思い下記のようなツイートをしたところ、ありがたいことにお誘いを頂いたため新しい挑戦を始めることになりました。 主に Kubernetes やコンテナ関連のお仕事をさせていただく予定です。 せっかく Portfolio 作ったのと、新しいことを初めてみたくなったので、副業等を探しはじめてみました。(もしスキルセット的にお手伝いできることがあればご連絡ください。)https://t.co/poo… <p>こんにちは。<a href="https://twitter.com/amsy810">amsy810</a>です。</p> <p>春といえば新しいことを始める時期ですね。</p> <p>3/18 より <strong>クリエーションラインさんに 技術アドバイザー としてジョイン</strong>しました。 <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/masaya_aoyama/20190325/20190325231512.png" alt="f:id:masaya_aoyama:20190325231512p:plain" title="f:id:masaya_aoyama:20190325231512p:plain" class="hatena-fotolife" itemprop="image"></span></p> <p>今とは異なる要件で新しい経験もしてみたいと思い下記のようなツイートをしたところ、ありがたいことにお誘いを頂いたため新しい挑戦を始めることになりました。</p> <p>主に <a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> やコンテナ関連のお仕事をさせていただく予定です。</p> <p><blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">せっかく Portfolio 作ったのと、新しいことを初めてみたくなったので、副業等を探しはじめてみました。<br>(もしスキルセット的にお手伝いできることがあればご連絡ください。)<a href="https://t.co/pookSVvJX4">https://t.co/pookSVvJX4</a> <a href="https://t.co/u629B3VP1r">https://t.co/u629B3VP1r</a></p>&mdash; MasayaAoyama(青山 真也) (@amsy810) <a href="https://twitter.com/amsy810/status/1095114330679341056?ref_src=twsrc%5Etfw">2019年2月12日</a></blockquote><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></p> <p>私自身、技術が好きでこの業界に入ってきたほどなので、色々なことが楽しみです。</p> <p>クリエーションラインさんは CNCF が提供する <a href="https://www.creationline.com/lab/20290">日本で最初の KCSP (Kubernetes Certified Service Providers)</a> で、CNCF 公式の<a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a>ト<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EC%A1%BC%A5%CB%A5%F3">レーニン</a>グの提供を含む、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a>やコンテナ関連の事業を展開しています。</p> <p>具体的な内容についてお話しできないことも多々ありますが、普段中々経験できない業界だったりするので、とても良い経験ができそうだなとワクワクしています。</p> <p><strong>なお、<a class="keyword" href="http://d.hatena.ne.jp/keyword/CyberAgent">CyberAgent</a> を退職するわけではありません。</strong></p> <p>しっかりとメリハリをつけて本業も頑張りつつ、新しい考え方を学んで CA でも引き続き頑張ります。</p> <p>なお、新しいことを始める話には続きがあり…数日後にまたご報告させていただきます。</p> masaya_aoyama 【Kubernetes】GKEのBackendConfigとNetwork Endpoint Groups(NEGs) hatenablog://entry/10257846132679469098 2018-12-06T04:09:19+09:00 2019-03-24T17:49:03+09:00 この記事はAdvent Calendar 1日目の記事になります。 (Japan Container Days v18.12の運営やshowKsやセッション資料の作成に追われ、遅れてしまい申し訳ありません。) こんにちは。 @amsy810 です。 GKE では、最近ネットワークに関する便利な機能追加が多く行われており、この記事ではそれらについて紹介したいと思います。 主に下記の2つについて紹介します。 BackendConfig Resource Network Endpoint Groups (NEGs) BackendConfig Resource BackendConfig Resou… <p>この記事はAdvent Calendar 1日目の記事になります。</p> <p>(<a href="https://containerdays.jp/">Japan Container Days v18.12</a>の運営やshowKsやセッション資料の作成に追われ、遅れてしまい申し訳ありません。)</p> <p>こんにちは。 <a href="https://twitter.com/amsy810">@amsy810</a> です。</p> <p>GKE では、最近ネットワークに関する便利な機能追加が多く行われており、この記事ではそれらについて紹介したいと思います。 主に下記の2つについて紹介します。</p> <ul> <li>BackendConfig Resource</li> <li>Network Endpoint Groups (NEGs)</li> </ul> <h1>BackendConfig Resource</h1> <p><strong>BackendConfig</strong> Resource は GKE でのみ利用可能な CRD(Custom Resource Definition)で、HTTP/<a class="keyword" href="http://d.hatena.ne.jp/keyword/HTTPS">HTTPS</a> Load Balancing(<a class="keyword" href="http://d.hatena.ne.jp/keyword/Ingress">Ingress</a> Resource)をする際に、下記の機能を付随して利用することが可能になります。</p> <ul> <li>Cloud Content Delivery Network (Cloud <a class="keyword" href="http://d.hatena.ne.jp/keyword/CDN">CDN</a>)</li> <li>Cloud Armor</li> <li>Cloud Identity-Aware Proxy (Cloud IAP)</li> <li>Timeout, Connection draining timeout, Session affinity</li> </ul> <p>もう少しいうと、GCE用の<a class="keyword" href="http://d.hatena.ne.jp/keyword/Ingress">Ingress</a> ControllerがこのBackendConfigリソースをみて、連携を行なっているようです。<a class="keyword" href="http://d.hatena.ne.jp/keyword/Ingress">Ingress</a> ResourceのSpecは一般化されたリソースのためこのような記述をすることができず、もしできるとしてもAnnotationsで設定することになってしまうと思います。 そのため、BackendConfigとして実装する道を辿ったのだと思います。 現時点ではBackendConfigはGKE用のリソースとなっています。 実際の処理部分は下記のあたりです。</p> <p><a href="https://github.com/kubernetes/ingress-gce/tree/v1.4.0/pkg/backends/features">ingress-gce/pkg/backends/features at v1.4.0 &middot; kubernetes/ingress-gce &middot; GitHub</a></p> <p>なお、BackendConfigのリソースは、下記のリンク先にある構造体を持っています。</p> <p><a href="https://github.com/kubernetes/ingress-gce/blob/v1.4.0/pkg/apis/backendconfig/v1beta1/types.go#L38-L45">ingress-gce/types.go at v1.4.0 &middot; kubernetes/ingress-gce &middot; GitHub</a></p> <p>全部埋めた状態だとこんな感じですね。</p> <pre class="code lang-yaml" data-lang="yaml" data-unlink><span class="synIdentifier">apiVersion</span><span class="synSpecial">:</span> cloud.google.com/v1beta1 <span class="synIdentifier">kind</span><span class="synSpecial">:</span> BackendConfig <span class="synIdentifier">metadata</span><span class="synSpecial">:</span> <span class="synIdentifier">name</span><span class="synSpecial">:</span> sample-backend-config <span class="synIdentifier">namespace</span><span class="synSpecial">:</span> default <span class="synIdentifier">spec</span><span class="synSpecial">:</span> <span class="synIdentifier">iap</span><span class="synSpecial">:</span> <span class="synIdentifier">enabled</span><span class="synSpecial">:</span> <span class="synConstant">true</span> <span class="synIdentifier">oauthclientCredentials</span><span class="synSpecial">:</span> <span class="synIdentifier">secretName</span><span class="synSpecial">:</span> my_secret <span class="synComment"> # Secret で clientID と clientSecret を指定する場合は不要</span> <span class="synComment"> # clientID: my_client_id</span> <span class="synComment"> # clientSecret: my_client_secret</span> <span class="synIdentifier">cdn</span><span class="synSpecial">:</span> <span class="synIdentifier">enabled</span><span class="synSpecial">:</span> <span class="synConstant">true</span> <span class="synIdentifier">cachePolicy</span><span class="synSpecial">:</span> <span class="synIdentifier">includeHost</span><span class="synSpecial">:</span> <span class="synConstant">true</span> <span class="synIdentifier">includeProtocol</span><span class="synSpecial">:</span> <span class="synConstant">true</span> <span class="synIdentifier">includeQueryString</span><span class="synSpecial">:</span> <span class="synConstant">false</span> <span class="synIdentifier">QueryStringBlacklist</span><span class="synSpecial">:</span> <span class="synStatement">- </span><span class="synConstant">&quot;&quot;</span> <span class="synIdentifier">QueryStringWhitelist</span><span class="synSpecial">:</span> <span class="synStatement">- </span><span class="synConstant">&quot;&quot;</span> <span class="synIdentifier">securityPolicy</span><span class="synSpecial">:</span> <span class="synIdentifier">name</span><span class="synSpecial">:</span> my_policy <span class="synIdentifier">timeoutSec</span><span class="synSpecial">:</span> <span class="synConstant">40</span> <span class="synIdentifier">connectionDraining</span><span class="synSpecial">:</span> <span class="synIdentifier">drainingTimeoutSec</span><span class="synSpecial">:</span> <span class="synConstant">60</span> <span class="synIdentifier">sessionAffinity</span><span class="synSpecial">:</span> <span class="synIdentifier">affinityType</span><span class="synSpecial">:</span> <span class="synConstant">&quot;GENERATED_COOKIE&quot;</span> <span class="synIdentifier">affinityCookieTtlSec</span><span class="synSpecial">:</span> <span class="synConstant">50</span> </pre> <p>ちなみにCloud IAPとCloud <a class="keyword" href="http://d.hatena.ne.jp/keyword/CDN">CDN</a>を両方とも1つのBackendConfigに設定することはできません。 また、作成したBackendConfigは、ServiceのAnnotationsに <em>beta.cloud.<a class="keyword" href="http://d.hatena.ne.jp/keyword/google">google</a>.com/backend-config</em> を記述することで利用します。 <a class="keyword" href="http://d.hatena.ne.jp/keyword/Ingress">Ingress</a> ResourceのAnnotationsに設定するイメージでしたが、Serviceの方に設定するんですね。 おそらく、複数の<a class="keyword" href="http://d.hatena.ne.jp/keyword/Ingress">Ingress</a> ObjectからServiceのNodePortを指定することができるため<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B2%BC%CE%AE">下流</a>の方で設定をかけたかったか、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Ingress">Ingress</a> ControllerはService Objectの情報を元に動作する(NEGsはServiceのNodePortに送られるのではなく、Serviceに紐付くPodのIPをDiscoveryしている)思想で作られたのかなと思っています。</p> <pre class="code lang-yaml" data-lang="yaml" data-unlink><span class="synIdentifier">apiVersion</span><span class="synSpecial">:</span> v1 <span class="synIdentifier">kind</span><span class="synSpecial">:</span> Service <span class="synIdentifier">metadata</span><span class="synSpecial">:</span> <span class="synIdentifier">annotations</span><span class="synSpecial">:</span> <span class="synIdentifier">beta.cloud.google.com/backend-config</span><span class="synSpecial">:</span> <span class="synConstant">'{&quot;ports&quot;: {&quot;http&quot;:&quot;config-http&quot;, &quot;http2&quot; :&quot;config-http2&quot;}, &quot;default&quot;: &quot;config-default&quot;}'</span> <span class="synIdentifier">name</span><span class="synSpecial">:</span> my-service <span class="synIdentifier">spec</span><span class="synSpecial">:</span> <span class="synIdentifier">type</span><span class="synSpecial">:</span> NodePort <span class="synIdentifier">ports</span><span class="synSpecial">:</span> <span class="synStatement">- </span><span class="synIdentifier">name</span><span class="synSpecial">:</span> http <span class="synIdentifier">protocol</span><span class="synSpecial">:</span> TCP <span class="synIdentifier">port</span><span class="synSpecial">:</span> <span class="synConstant">80</span> <span class="synIdentifier">targetPort</span><span class="synSpecial">:</span> <span class="synConstant">8080</span> <span class="synStatement">- </span><span class="synIdentifier">name</span><span class="synSpecial">:</span> http2 <span class="synIdentifier">protocol</span><span class="synSpecial">:</span> TCP <span class="synIdentifier">port</span><span class="synSpecial">:</span> <span class="synConstant">443</span> <span class="synIdentifier">targetPort</span><span class="synSpecial">:</span> <span class="synConstant">8080</span> <span class="synStatement">- </span><span class="synIdentifier">name</span><span class="synSpecial">:</span> http3 <span class="synIdentifier">protocol</span><span class="synSpecial">:</span> TCP <span class="synIdentifier">port</span><span class="synSpecial">:</span> <span class="synConstant">49152</span> <span class="synIdentifier">targetPort</span><span class="synSpecial">:</span> <span class="synConstant">49152</span> </pre> <h2>Cloud Armor</h2> <p>Cloud Armorは、DDOS対策・IP Addressの Allow/Deny・Geo-based <a class="keyword" href="http://d.hatena.ne.jp/keyword/Access">Access</a> Controlをはじめとした様々なセキュリティ機能を利用することができます。</p> <p>現状では事前に gcloud beta compute security-policies rules create コマンドでポリシーを作成しておき、そのポリシーを使うことを明示的にBackendConfigリソースに指定してあげる必要があります。</p> <p>例えば、事前にポリシーとルールを作成し、</p> <pre class="code" data-lang="" data-unlink>$ gcloud beta compute security-policies create sample-policy $ gcloud beta compute security-policies rules create 1000 \ --security-policy sample-policy \ --description &#34;Deny traffic from 192.0.2.0/24.&#34; \ --src-ip-ranges &#34;192.0.2.0/24&#34; \ --action &#34;deny-404&#34;</pre> <p>下記のようなBackendConfigを作るような形になっています。</p> <pre class="code lang-yaml" data-lang="yaml" data-unlink><span class="synIdentifier">apiVersion</span><span class="synSpecial">:</span> cloud.google.com/v1beta1 <span class="synIdentifier">kind</span><span class="synSpecial">:</span> BackendConfig <span class="synIdentifier">metadata</span><span class="synSpecial">:</span> <span class="synIdentifier">name</span><span class="synSpecial">:</span> sample-backend-config <span class="synIdentifier">namespace</span><span class="synSpecial">:</span> default <span class="synIdentifier">spec</span><span class="synSpecial">:</span> <span class="synIdentifier">securityPolicy</span><span class="synSpecial">:</span> <span class="synIdentifier">name</span><span class="synSpecial">:</span> sample-policy </pre> <p>現状では<a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a>の世界で設定を完結できないようになっていますが、この辺りは下記のようにいずれ<a class="keyword" href="http://d.hatena.ne.jp/keyword/K8s">K8s</a>の世界で管理できるようになってくるのではないでしょうか。</p> <pre class="code lang-yaml" data-lang="yaml" data-unlink><span class="synIdentifier">apiVersion</span><span class="synSpecial">:</span> cloud.google.com/v1beta1 <span class="synIdentifier">kind</span><span class="synSpecial">:</span> BackendConfig <span class="synIdentifier">metadata</span><span class="synSpecial">:</span> <span class="synIdentifier">name</span><span class="synSpecial">:</span> sample-backend-config <span class="synIdentifier">namespace</span><span class="synSpecial">:</span> default <span class="synIdentifier">spec</span><span class="synSpecial">:</span> <span class="synIdentifier">securityPolicy</span><span class="synSpecial">:</span> <span class="synStatement">- </span><span class="synIdentifier">srcIPRange</span><span class="synSpecial">:</span> 192.0.2.0/24 <span class="synIdentifier">action</span><span class="synSpecial">:</span> deny-404 <span class="synIdentifier">priority</span><span class="synSpecial">:</span> <span class="synConstant">1000</span> </pre> <p><a href="https://cloud.google.com/kubernetes-engine/docs/how-to/cloud-armor-backendconfig">Configuring Cloud Armor &nbsp;|&nbsp; Kubernetes Engine &nbsp;|&nbsp; Google Cloud</a></p> <h2>Cloud IAP (Identity-Aware Proxy)</h2> <p>Cloud IAPは、<a class="keyword" href="http://d.hatena.ne.jp/keyword/GCP">GCP</a>(GKE)上にデプロイされたアプリへの<a class="keyword" href="http://d.hatena.ne.jp/keyword/Access">Access</a> Controlを行うサービスです。 事前にClient IDとClient SecretのデータをSecretに登録しておきます。</p> <pre class="code lang-yaml" data-lang="yaml" data-unlink><span class="synIdentifier">apiVersion</span><span class="synSpecial">:</span> v1 <span class="synIdentifier">kind</span><span class="synSpecial">:</span> Secret <span class="synIdentifier">metadata</span><span class="synSpecial">:</span> <span class="synIdentifier">name</span><span class="synSpecial">:</span> sample-db-auth <span class="synIdentifier">type</span><span class="synSpecial">:</span> Opaque <span class="synIdentifier">data</span><span class="synSpecial">:</span> <span class="synIdentifier">client_id</span><span class="synSpecial">:</span> XXXXXXX <span class="synIdentifier">client_secret</span><span class="synSpecial">:</span> XXXXXXX </pre> <p>Cloud IAPの設定項目としては、Client IDとClient Secret になります。Secret経由で渡している場合には、Secret名を指定すれば問題ありません。</p> <pre class="code lang-yaml" data-lang="yaml" data-unlink><span class="synIdentifier">apiVersion</span><span class="synSpecial">:</span> cloud.google.com/v1beta1 <span class="synIdentifier">kind</span><span class="synSpecial">:</span> BackendConfig <span class="synIdentifier">metadata</span><span class="synSpecial">:</span> <span class="synIdentifier">name</span><span class="synSpecial">:</span> sample-backend-config <span class="synIdentifier">namespace</span><span class="synSpecial">:</span> default <span class="synIdentifier">spec</span><span class="synSpecial">:</span> <span class="synIdentifier">iap</span><span class="synSpecial">:</span> <span class="synIdentifier">enabled</span><span class="synSpecial">:</span> <span class="synConstant">true</span> <span class="synIdentifier">oauthclientCredentials</span><span class="synSpecial">:</span> <span class="synIdentifier">secretName</span><span class="synSpecial">:</span> my_secret <span class="synComment"> # Secret で clientID と clientSecret を指定する場合は不要</span> <span class="synComment"> # clientID: my_client_id</span> <span class="synComment"> # clientSecret: my_client_secret</span> </pre> <h2>Cloud <a class="keyword" href="http://d.hatena.ne.jp/keyword/CDN">CDN</a> (Content Delivery Network)</h2> <p>Cloud <a class="keyword" href="http://d.hatena.ne.jp/keyword/CDN">CDN</a>は、<a class="keyword" href="http://d.hatena.ne.jp/keyword/GCP">GCP</a>の<a class="keyword" href="http://d.hatena.ne.jp/keyword/CDN">CDN</a>です。 設定項目としてはキャッシュポリシーに関わるものがあります。</p> <pre class="code lang-yaml" data-lang="yaml" data-unlink><span class="synIdentifier">apiVersion</span><span class="synSpecial">:</span> cloud.google.com/v1beta1 <span class="synIdentifier">kind</span><span class="synSpecial">:</span> BackendConfig <span class="synIdentifier">metadata</span><span class="synSpecial">:</span> <span class="synIdentifier">name</span><span class="synSpecial">:</span> sample-backend-config <span class="synIdentifier">namespace</span><span class="synSpecial">:</span> default <span class="synIdentifier">spec</span><span class="synSpecial">:</span> <span class="synIdentifier">cdn</span><span class="synSpecial">:</span> <span class="synIdentifier">enabled</span><span class="synSpecial">:</span> <span class="synConstant">true</span> <span class="synIdentifier">cachePolicy</span><span class="synSpecial">:</span> <span class="synIdentifier">includeHost</span><span class="synSpecial">:</span> <span class="synConstant">true</span> <span class="synIdentifier">includeProtocol</span><span class="synSpecial">:</span> <span class="synConstant">true</span> <span class="synIdentifier">includeQueryString</span><span class="synSpecial">:</span> <span class="synConstant">false</span> <span class="synIdentifier">QueryStringBlacklist</span><span class="synSpecial">:</span> <span class="synStatement">- </span><span class="synConstant">&quot;&quot;</span> <span class="synIdentifier">QueryStringWhitelist</span><span class="synSpecial">:</span> <span class="synStatement">- </span><span class="synConstant">&quot;&quot;</span> </pre> <h2>そのほかの設定</h2> <p>そのほかにも<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BF%A5%A4%A5%E0%A5%A2%A5%A6%A5%C8">タイムアウト</a>の設定や、セッションアフィニティの設定などを行うことも可能です。</p> <pre class="code lang-yaml" data-lang="yaml" data-unlink><span class="synIdentifier">apiVersion</span><span class="synSpecial">:</span> cloud.google.com/v1beta1 <span class="synIdentifier">kind</span><span class="synSpecial">:</span> BackendConfig <span class="synIdentifier">metadata</span><span class="synSpecial">:</span> <span class="synIdentifier">name</span><span class="synSpecial">:</span> sample-backend-config <span class="synIdentifier">namespace</span><span class="synSpecial">:</span> default <span class="synIdentifier">spec</span><span class="synSpecial">:</span> <span class="synIdentifier">timeoutSec</span><span class="synSpecial">:</span> <span class="synConstant">40</span> <span class="synIdentifier">connectionDraining</span><span class="synSpecial">:</span> <span class="synIdentifier">drainingTimeoutSec</span><span class="synSpecial">:</span> <span class="synConstant">60</span> <span class="synIdentifier">sessionAffinity</span><span class="synSpecial">:</span> <span class="synIdentifier">affinityType</span><span class="synSpecial">:</span> <span class="synConstant">&quot;GENERATED_COOKIE&quot;</span> <span class="synIdentifier">affinityCookieTtlSec</span><span class="synSpecial">:</span> <span class="synConstant">50</span> </pre> <h2>注意事項・参考資料</h2> <p>現在はまだ beta リリースなため、<a class="keyword" href="http://d.hatena.ne.jp/keyword/SLA">SLA</a>が担保されていなかったり、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B8%E5%CA%FD%B8%DF%B4%B9">後方互換</a>のない変更が行われる可能性があるため注意してください。</p> <p><a href="https://cloud.google.com/kubernetes-engine/docs/concepts/backendconfig">BackendConfig custom resource &nbsp;|&nbsp; Kubernetes Engine &nbsp;|&nbsp; Google Cloud</a></p> <h1>Network Endpoint Groups (NEGs)</h1> <p>NEGsは、IPとPortのペアをネットワークエンドポイントとしてLoadBalancerの設定に利用するものです。 NEGsとPod Nativeなネットワーク(CalicoなどでPod Network / Internal Network に対して<a class="keyword" href="http://d.hatena.ne.jp/keyword/VM">VM</a> Networkから疎通性がある構成)を利用することで、LoadBalancerから直接Podまでリク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>トを受けることができます。</p> <p>通常はこのように、LoadBalancerから<a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> Nodeに対してリク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>トが送られると、Node上に到達した後に、再度負荷分散(2段階ロードバランシング)が行われます。 NodeからPodへのロードバランシング(kube-proxyの担当範囲)は、<a href="https://kubernetes.io/docs/concepts/services-networking/service/">usermode・iptables・ipvs</a>と3つのモードがありますが、いずれの場合にも一定の負荷・レイテンシの微増・分散のばらつきが生じます。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/masaya_aoyama/20181206/20181206035829.png" alt="f:id:masaya_aoyama:20181206035829p:plain" title="f:id:masaya_aoyama:20181206035829p:plain" class="hatena-fotolife" itemprop="image"></span></p> <p>一方でNEGsを利用することで、直接Pod宛てに負荷分散を行うことができるため、これらの問題を低減することが可能です。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/masaya_aoyama/20181206/20181206035824.png" alt="f:id:masaya_aoyama:20181206035824p:plain" title="f:id:masaya_aoyama:20181206035824p:plain" class="hatena-fotolife" itemprop="image"></span></p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/AWS">AWS</a>の場合には、<a class="keyword" href="http://d.hatena.ne.jp/keyword/aws">aws</a>-<a class="keyword" href="http://d.hatena.ne.jp/keyword/vpc">vpc</a>-cni-<a class="keyword" href="http://d.hatena.ne.jp/keyword/k8s">k8s</a>とalb-<a class="keyword" href="http://d.hatena.ne.jp/keyword/ingress">ingress</a>-controllerを使うと同様のことが実現できるそうです。(未検証)</p> <p><a href="https://cloud.google.com/kubernetes-engine/docs/how-to/container-native-load-balancing">Using container-native load balancing &nbsp;|&nbsp; Kubernetes Engine &nbsp;|&nbsp; Google Cloud</a></p> <p>また、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Ingress">Ingress</a>の実装の違いについては下記を参考にしてみてください。</p> <p><iframe id="talk_frame_471981" src="//speakerdeck.com/player/1ab43e5213ce4f92a5d7eb5268ea4a2a" width="710" height="399" style="border:0; padding:0; margin:0; background:transparent;" frameborder="0" allowtransparency="true" allowfullscreen="allowfullscreen" mozallowfullscreen="true" webkitallowfullscreen="true"></iframe><cite class="hatena-citation"><a href="https://speakerdeck.com/masayaaoyama/containersig-fall-2018-ingress-gke-neg">speakerdeck.com</a></cite></p> <p>(あ、こんなところに<a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> 本...)</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.amazon.co.jp%2Fdp%2F4295004804" title="Kubernetes完全ガイド (impress top gear) | 青山 真也 |本 | 通販 | Amazon" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://www.amazon.co.jp/dp/4295004804">www.amazon.co.jp</a></cite></p> masaya_aoyama testpage 2 hatenablog://entry/26006613591274251 2018-01-02T00:00:00+09:00 2020-06-29T01:42:05+09:00 this is testpage 2 <p>this is testpage 2</p> masaya_aoyama testpage 1 hatenablog://entry/26006613591274149 2018-01-01T00:00:00+09:00 2020-06-29T01:41:34+09:00 this is testpage 1 <p>this is testpage 1</p> masaya_aoyama