有名テック企業の技術ブログを、ひとつのフィードで。
フィード
34件
はじめに はじめまして、開発本部 kintone アプリ化チームの okarin です。 サイボウズは2025年にエンタープライズ事業者向けに、外部システムの kintone アプリ化という機能をリリースしました。 この機能は、外部システムのデータを kintone のアプリとして扱うことができる機能なのですが、これを実現するためのアーキテクチャが他ではあまり見ない作りになっているので、ここで紹介していきたいと思います。 (本記事では顧客のプライベートネットワーク内にあるシステムをサイボウズ側からの視点で「外部システム」と呼ぶことにします) 技術的な制約 外部システムのデータを kintone で扱うために、はじめに思いつくのは kintone から外部システムにリクエストを送る構成だと思います。 しかしながら、エンタープライズ事業者の現場でこの構成を実現することは難しいです。 外部システムはインターネットから到達できるケースは少なく、プライベートネットワークで動いていることが多いです。仮に kintone からのネットワークリクエストを許可しようとすると、プライベートネットワークに inbound 通信を通すという意思決定が必要になり、セキュリティ面のリスクが増え、顧客の運用コストも大きくなります。このような理由から、kintone 側から取りに行くという発想自体を捨てる必要がありました。 kintone から外部システムへの通信はできない 採用したアーキテクチャ そこで今回は「通信の方向を逆にする」という方式を採用しました。 kintone から顧客のプライベートネットワークに入るのではなく、顧客のプライベートネットワーク内に Agent をおき、Agent から kintone 側に outbound 接続してもらう構成にしました。outbound 接続であれば、顧客のプライベートネットワークに外部から到達可能な経路を作らずに済みます。 アーキテクチャの詳細を以下の図に示します。 採用したアーキテクチャ gRPC の Bidirectional streaming RPC で顧客側にある Agent からサイボウズ側の Proxy に接続することで双方向に通信可能にする kintone 上で操作が行われたら Proxy にリクエストを送信する gRPC の Bidirectional streaming RPC でサイボウズ側の Proxy から顧客側の Agent にリクエストを送信する Agent から Adapter にリクエストを送信する Adapter で外部システム固有の API 呼び出しに変換して API を呼び出す コンポーネント 役割 kintone 外部システムのデータを kintone のアプリとして表示・操作する。 Proxy Agent からの outbound 接続を待ち受ける。接続後は kintone からのリクエストを Agent に転送する。 Agent Proxy へ outbound 接続する。Proxy からのリクエストを Adapter に送信する。 Adapter Agent からのリクエストを外部システム固有の API 呼び出しに変換する。 外部システム Adapter からの API 呼び出しを受け付ける。顧客が運用している業務システムなど。 この仕組みによって、kintone からのリクエストを顧客側にある外部システムに送信することができます。 Agent と Adapter を分けているのは、外部システムごとに異なる API の差異を Adapter に閉じ込めて、 Agent を共通基盤として切り出すためです。Agent は kintone との通信を担う共通部品としてサイボウズが提供し、外部システム固有の変換ロジックだけを Adapter として顧客が開発します。この責務の分割により、外部システムによって Agent 側に変更は原則不要になります。 通信方式の比較 Agent - Proxy 間の双方向通信を実現する方式として、今回は最終的に gRPC の Bidirectional streaming RPC を採用しました。他にもいくつか検討した方式があるため、以下で各方式のメリット・デメリットを詳しく見ていきます。 Bidirectional streaming RPC 今回採用した gRPC の Bidirectional streaming RPC は、HTTP/2 上で双方向ストリーミングを行う通信方式です。一度接続を確立すると、kintone からのリクエストと外部システムからの応答の両方を流せるため、Agent からの outbound 接続一本で双方向通信が成立します。 メリット Protocol Buffers によるスキーマ駆動開発が可能 gRPC を採用することで Protocol Buffers のエコシステムを活用できる。メッセージの仕様を .proto で厳密に定義し、そこから各言語のクライアントコードを生成して SDK として配布できる。これにより、Adapter を開発する顧客は型安全に実装を進められる。 バイナリプロトコルで効率が良い JSON 等のテキスト形式に比べてペイロードが小さく、Agent - Proxy 間の通信コストを抑えられる。 社内に知見がある サイボウズ社内で gRPC を採用しているプロダクトが複数あり、障害対応や運用ノウハウを活かせる。 デメリット 顧客に Adapter の開発負担が生じる gRPC のリクエストを外部システム固有の API 呼び出しに変換する Adapter を、顧客側で開発・運用してもらう必要がある。 SOCKS over SSH SSH のリモートポートフォワーディング(ssh -R)を使い、Agent 側の OpenSSH プロセスを SOCKS5 プロキシとして振る舞わせる方式です。 SOCKS5 は指定された宛先への任意の TCP 接続を中継することができるプロキシで、RFC1928 で定義されています。SSH トンネルと組み合わせることで、通信を暗号化しつつプライベートなシステムへのアクセスを可能にします。 これは Grafana Cloud の Private Data Source Connect (PDC) で採用されている手法で、Grafana Cloud からプライベートネットワーク内のデータソースへ接続するために使われています。 仮にこの方式をサポートした場合は以下のようなアーキテクチャになると想定しています。 SOCKS over SSH を採用した場合のアーキテクチャ Agent が ssh -R オプション(リモートポートフォワーディング)で Proxy に SSH 接続し、Proxy 側にポートを開く kintone から Proxy にリクエストを送信する Proxy が 1. で開いたポートに SOCKS クライアントとして接続する。この通信は SSH トンネルを通って Agent に届く(SOCKS over SSH) Agent の ssh プロセスが SOCKS を終端し、SOCKS リクエストで指定された宛先(外部システム)に TCP 接続してリクエストを転送する メリット 顧客が Adapter を開発する必要がない Agent は L4 の TCP 転送をそのまま中継するだけなので、外部システムごとの変換コンポーネントを顧客が用意しなくてよい。 デメリット 外部システムごとの差異を kintone 側で吸収することになる SOCKS は L4 の TCP 転送しか行わないため、kintone が外部システムの API を直接呼び出すことになる。Grafana のように接続先が標準的なプロトコル(SQL など)であれば成立するが、顧客固有の業務システムが対象の場合は、システムごとの変換ロジックをサイボウズが用意し続けることになり、運用コストが大きい。 開発チームでの SSH サーバーの運用経験が乏しい サイボウズ側で SSH サーバーを運用することになるが、障害発生時の対応に不安が残る。 WebSocket HTTP の Upgrade を使い、1本の TCP 接続の上で双方向のメッセージをやり取りする方式です。 メリット シンプルで広くサポートされている 多くの言語・ミドルウェアが標準で対応しており、双方向通信を比較的少ない実装で実現できる。 デメリット スキーマ駆動の型安全性が標準では得られない WebSocket 自体はフレーミングまでしか規定しないため、メッセージのスキーマ定義は自前で設計することになる。 サーバー間通信では WebSocket の強みを発揮できない WebSocket の最大の利点はブラウザが標準 API として備えている点にあるが、Agent - Proxy 間にブラウザは介在しないため、その恩恵を受けられない。 まとめ 「外部システムのデータを kintone で扱う」という一見シンプルな機能ですが、エンタープライズ事業者のセキュリティ要件と折り合うために、通信の向きを逆にするというアプローチを取りました。こうした制約と向き合いながらシステムを設計することは、エンジニアとしてやりがいがあると思います。 サイボウズでは今プロダクトエンジニアの仲間を増やしているところなので、こうした課題と向き合うプロダクト開発に興味がある方は、ぜひ下記のリンクからご応募ください。 cybozu.co.jp
入社5年、同期3人の振り返り body { font-family: "Hiragino Sans", "Meiryo", sans-serif;} .intro { background: #f5f4f0; border-radius: 8px; padding: 1rem 1.4rem; margin: 1.5rem 0; } dl { margin: 1rem 0; } dt { font-weight: bold; margin-top: 1.2rem; } dd { margin-left: 1.8rem; margin-top: .2rem; } .ref { font-size: .9rem; color: #666; margin-top: 1rem; } .ref a { color: #0073e6; } /* メンバーごとのカラー */ dt.massan { color: #c49000; } /* kintone */ dt.taguchi { color: #3d8fa8; } /* Cybozu */ dt.taku3n { color: #1a4db8; } /* Garoon */ /* 方法①:フォトライフ画像の枠線を消す+中央揃え */ img.hatena-fotolife { border: none; display: block; margin: 0 auto; } こんにちは!2021年にサイボウズへ新卒入社した massan、taguchi、taku3n です。気がつけば入社から5年。同期3人がそろって在籍しているこの機会に、それぞれの5年間を振り返ってみました。 massan kintone拡張基盤チームのQAエンジニアです。着物の勉強をしています。 taguchi PSIRTのプロダクトセキュリティエンジニアです。ラーメンが好きです。 taku3n Garoon開発チームのQAエンジニアです。最近ボードゲームにハマってます。 この記事は、QA として入社して1年経った話のリバイバル記事です。 ※元記事では柔軟な働き方について、現在は実現が難しいものが含まれています。あくまでQA職種の仕事や文化の参考としてご参照ください。 最近はどんな業務をしてる? まずは、現在の業務について紹介します。 massan 主務では、kintoneを拡張する人を支援する基盤づくりのQAをしています。APIやSDK、去年はMCPサーバーの開発にも関わっていました。 兼務も少しあって、kintoneのセキュリティチャンピオン、社外向けの技術交流を促進するQA外部コネクト、QA新卒採用なども担当しています。マネージャーに誘ってもらったり、自分から関わりたいと思って始めたものばかりです。 異なる分野を学び、それらを媒介したり組み合わせて生かしたりするのは自分の性格に合っていると感じます。いろんな業務を通してtaku3nやtaguchiさんをはじめとるする他メンバーとも製品を超えて刺激をもらうことができ、日々の業務のモチベーションになっています。 taguchi 現在はサイボウズ Office、メールワイズ、販売管理システム、cybozu.com共通管理などのセキュリティを担当しています。具体的には、脆弱性診断、外部べンダー対応、バグバウンティ対応を中心に、担当製品のセキュリティに関する業務全般に携わっています。 そのほかにも、PSIRTの新卒採用、情報発信、AIを活用したPSIRT業務・脆弱性診断の効率化にも取り組んでいます。 taku3n 主にGaroonのリリース改善に取り組んでいます。具体的には、リリースとデプロイの分離やプロセス改善を通して、高速で安定したリリースの実現を目指しています。その中で、新しく作り上げるリリースフローのテスト活動も行っています。 その他では、他チームからのGaroonの品質に関する問い合わせ対応、テストアーキテクチャ設計、QA新卒採用、アシスタントマネージャーなどにも取り組んでいます。 3人の所属する組織図概略 ref. サイボウズの QAエンジニアについて / about cybozu QA 5年間でどう変わった? 次に、入社からの5年間でどのような変化があったかを振り返ります。 massan 入社してすぐ、kintoneQAのインプロセス化がそれまで以上に進み、開発チームも担当領域の分割が進みました。kintone全体を見るのではなく、開発チームに所属して自分の担当領域に絞って見るようになったんです。オーナーシップは持てるようになりましたが、その反面、過去の資産に頼れない場面も多くなりました。 そんな中、プロダクトの初期段階から頼ってもらえるQAになるべく、新規立ち上げされたkintone拡張基盤チームに配属されました。立ち上げから1年以上経ちますが、固定化されたテスト実施タスクは少なく、品質戦略の策定、テストフローの整備、テスト資産化など業務は多岐にわたります。 自分のスキルや知識がチームの品質の上限になってしまうので、ISTQBをはじめとする勉強で体系的な知識をつけたり、カンファレンスに行って知見を増やしたりしています。最近は脆弱性周りに気を配ったり、シフトライトの強化を検討したりもしていて、4月はtaguchiさんのいるPSIRTに体験入部してきました。5年も経つと同期同士でも専門性が違ってきて、改めて身近に頼れる同期がいることのありがたさを実感しています。 taguchi 最初は製品の脆弱性診断を中心に担当していましたが、その後、担当製品に関わらずPSIRT全体の診断にも目を向けるようになりました。現在も診断全体の効率化は継続的に進めています。さらに、プロダクト全体のセキュリティを見る立場も担うようになり、業務への関わり方や役割は変化してきました。 また、PSIRTにはプロジェクトを小規模なチームを編成して進められる仕組みがあります。自分がジョインした当時にはなかったのですが、常に複数のプロジェクトが同時並行で進んでおり、最近ではPSIRT業務を支える根幹のひとつになっています。この仕組みのおかげで、セキュリティの技術的な部分だけでなく、PSIRTそのものについて考える機会も増えましたし、オーナーシップを持って進めていく経験にもつながっています。 taku3n 入社当初は、Garoonの膨大な仕様を理解することに必死で、手動テストプロセスやリリースプロセスの基礎を学ぶ毎日でした。その一方で、現場作業を少しでも効率的にするための改善活動を通して、プロセス改善に興味を持ち始めました。 転換点は、3年目にリリース改善チームへ加わったことです。それまでのQAのみのチームから、SWE(ソフトウェアエンジニア)と同じチームで活動するインプロセスな体制に変わり、よりシフトレフトを意識するようになりました。テスト対象もプロダクト単体からリリースの仕組み(CI)に変わり、品質を担保する方法を探りつつ構築していきました。この活動を通して、いかに安全かつ高速に価値を届けるかというプロセスの品質に、強く向き合うことになりました。 現在は、品質の可視化やリリースとデプロイを分離するフィーチャーフラグの導入プロジェクトのリーダーとして、リリース運用の土台からアップデートする効率化に取り組んでいます。5年間の積み重ねを経て、今はより広い視点でプロセス全体を捉え、改善策を提案していけるようになりました。今後も「楽をするための努力」を続けていきたいです! AIとどう向き合ってきた? 5年間の中でも特に大きな変化だったのが、AIの台頭です。QAとしてAIとどう向き合ってきたかを話してみました。 massan ひとりQAでチームの工数も限られる中、AIなくしてはチームの開発が成り立たないレベルになっていると思います。テスト設計など自分がこれまで行ってきた業務をAIに依頼するだけでなく、やりたかったけれど時間や一部スキルが足りずにできなかったことにも手を出せるようになり、チームへの貢献度が上がりました。たとえば、細々したケースの全数テストや、セキュリティアラートを受けた際の影響調査、修正、テストなどに活用しています。 一方で、MCPサーバーの開発ではユーザーのAI利用を助けるような立場にもなり、AI利用の両面を経験しています。 taguchi ここ5年間のAIに関する動きとしては、サイボウズ内でもAI関連機能の開発が進み、それに伴ってPSIRTでもAIに対する診断を内製化する動きがありました。推進を担当したメンバーのおかげで、今ではテスターのほぼ全員がAIに対する診断を行える状態になっており、開発者向けに社内で勉強会を実施するなど、チームとしてAIセキュリティに関する知見も蓄積されています。 脆弱性診断へのAI活用という文脈では、昨年からAIエージェントによる診断も導入しています。開発がますます高速化する中で、PSIRTとしてもそれに追随できるよう、今後さらにAIを活用した診断の自動化を進めていきたいと考えています。 taku3n 4年目にAIを活用したGaroonの新機能開発チームにQAメンバーとしてジョインしたことが大きな転機でした。精度検証やプロンプトチューニングといった、これまでにない領域でのQA活動は手探りの連続でしたが、AIの品質保証プロセスを一から作り上げる経験ができました。 なんで5年経っても3人ともいるの? 最後に、同期3人がそろって5年間在籍し続けている理由を聞いてみました。 massan 正直、転職のモチベーションは増えたり減ったりしてきました。でもプロジェクトが多いので、これまで自分の成長段階それぞれにちょうど良いチームや役割をあてがってもらううちに気づけば5年が過ぎていました。 サイボウズはQA組織が大きいのが特徴で、知見の共有や相談、他チームの事例などに手軽にアクセスできるのが良いところです。その一方で、自分は小さいチームのひとりQAなので「自分が動かないと何も変わらない」という状況もあります。 興味があることを無闇にやらせてもらえるとは感じませんが、自分が稼いできた信頼貯金で新しいことをさせてもらえるだろうという実感はあります。あえてあげるなら、これが大きな理由かもしれません。6年目となる最近はその貯金をちゃんと使って、自律的にチームや事業への貢献を増やす方法を学んでいる段階だと思っています。 taguchi 環境の良さは大きいですね。チームの雰囲気はもちろん、いろんなことに挑戦できる環境や気軽に相談できる場が整っていると感じます。自分としても、興味のある領域に関わらせてもらっている感覚がありますし、新しいツールの導入や「やってみたい」と思ったことをすぐに試せるスピード感もあります。 このあたりの印象は入社した頃からずっと変わっていなくて、会社全体としてそういった雰囲気があります。そうした環境がモチベーションの維持にもつながっていると思います。 taku3n 一番の理由は「今取り組んでいることが面白いから、もっと続けたい!」という思いが強いからです。振り返ってみると、この5年間のうちに何度か所属チームが変わり、向き合う課題もさまざまでした。ちょうどコンフォートゾーンに陥りそうになったタイミングで新しい変化が起き、そのたびに目新しい挑戦がありました。最初は難しくても、やり込んでいくうちにその面白さにハマっていく。そんな刺激的なサイクルに自ら挑みながらも、会社に後押ししてもらえていたと実感します。 また、大きな課題にぶつかって悩んでいるときも、チームとして解決しようと協力してくれる温かいメンバーが周りにいることも大きいです。サイボウズは「チームワークあふれる社会を創る」という理念に共感した人が集まっている組織なので、自然と現場でもチームワークがあふれています。こうした環境があるからこそ、変化を楽しみながら5年間走り続けてこられました!
本記事は、2024年入社のQAエンジニア 3人による振り返りブログの3本目です。 まだ読んでいない方は、ぜひ1本目・2本目もあわせてご覧ください! blog.cybozu.io はじめに こんにちは、GaroonというプロダクトでQAエンジニアをしている reo(@i_moqa)です⛄️ Garoonの開発チームは複数のチームで構成されているのですが、私はその中のYukimiチームに所属しています。 YukimiチームはGaroonで使用しているOSS(オープンソースソフトウェア)の更新や、セキュリティの維持・向上に向けた開発・保守を担当しています。 Yukimiチームの詳細については以下の記事をご参照ください。 blog.cybozu.io 本記事では、新卒1年目から2年目の間で、チーム内外で自分の役割や動き方がどのように変化してきたのかを振り返ります。 チーム内のタスクの変化 新卒1年目から2年目にかけて、最も大きく変わったのはチーム内のタスクの進め方です。 1年目は、スキルトランスファーを受けながら、チーム内で実施されていたタスクを進めることが中心でした。Yukimiチームのタスクは、OSSの更新やセキュリティ対応など影響範囲が広いものが多く、モブプログラミングで進めることも多かったため、進め方や考え方を含めて周囲に支えてもらう場面が多かったと感じています。 2年目に入ってからは、チーム体制がスクラムからカンバン方式へ移行しました。これにより、各メンバーが個別にタスクを進める場面が増え、他メンバーと並行して進めながら、自らレビューや情報共有を行う機会が多くなりました。また、一部のOSSやセキュリティに関わるプロジェクトにおいて、リーダーとして関わるようになりました リーダーとして関わるプロジェクトでは、進捗やタスクの管理に加えて、情報を一から収集・整理し、その結果をもとにステークホルダーと議論し、方針の決定や合意形成まで進める経験をしました。実際にやってみると、自分が関わっていない別プロジェクトをどこまで把握すべきか、どの観点まで見れば十分なのかといった判断を自分で下す必要があり、難しさを感じることも多くありました。 それでも経験を重ねる中で、自分の担当範囲だけでなく、チーム全体の品質や進め方に目を向けられるようになってきました。その結果、リスクの共有や観点の補完といった形でチームに還元できている実感を持てるようになったのは、大きな変化だったと感じています。 (以下の記事で紹介されている取り組みも、そのようなプロジェクトの一つとして、自分がリーダーとして関わったものです) blog.cybozu.io チーム横断活動への関わり 1年目は、自分の担当範囲やチーム内の文脈で考えることが中心でしたが、2年目に入り、徐々にYukimiチーム外の活動にも視野を広げられるようになってきました。 きっかけとなったのは、社内勉強会で井芹 洋輝さんをお招きして実施された「高品質と高スピードを両立させるテストアプローチ」という講演と、その内容を踏まえてGaroonチーム内で行われた勉強会です。 speakerdeck.com この勉強会を通じて、「Garoon全体としてのテストアーキテクチャをどう設計するべきか」という問いが生まれました。これを起点として、Garoon開発内でチームをまたいでアイデアを出し合う場を継続的に設けています。 具体的には、テストレベルごとの責務を整理し直しながら、既存のテストにおける課題を洗い出し、改善に向けた議論を進めています。こうした取り組みに参加する中で、それぞれのPBIごとに実施するテストを積み上げていく視点だけでなく、それらをどのように組み合わせてプロダクト全体の品質を担保するかという課題に向き合うようになりました。 その中で、難しさを感じる場面も多い一方で、全体設計として品質を捉えることの面白さも実感しています。 また、チームを越えて議論することで、それぞれが持っている前提や暗黙知が言語化され、新たな気づきにつながる場面が多いと感じています。このような対話を通じて、品質に対する認識をすり合わせていくこと自体が、プロダクト全体の品質向上につながる重要なプロセスだと考えるようになりました。 セキュリティ領域への広がり 2年目に入り、QAエンジニアとしての役割を意識しつつも、それをチーム全体にどう還元できるかを考えるようになりました。特に、Yukimiチームでは、QAエンジニアとWebエンジニアといった職能を越えて動くことが求められていると感じています。 そのため、自身の担当領域にとどまらず、OSSの脆弱性調査やセキュリティ対応などにも主体的に関わるようになりました。 また、チームとしてもプロダクト全体のセキュリティに目を向けるようになり、役割もOSS対応中心から徐々に広がってきました。そうした流れの中で、その一環としてセキュリティチャンピオン活動に参加し、OWASPなどの基礎知識の学習や、『安全なWebアプリケーションの作り方』の輪読を通じて、体系的に学ぶようになりました。 blog.cybozu.io このような環境の変化を踏まえて、「このチームの中でどう価値を出すか」を改めて考えるようになりました。単に任されたタスクやプロジェクトを進めるだけでなく、チームとして注力している領域に主体的に関わることが重要だと考えるようになりました。 その中で特に意識したのが、OSSの脆弱性対応や情報のキャッチアップです。OSSの新たな脆弱性をいち早く検知し、影響を評価して対応につなげることが求められます。そうした中で、自ら脆弱性を検知し、調査を進めていくようになりました。 また、こうした取り組みと並行して、個人的にもセキュリティ領域の学習に力を入れるようになりました。以前社内CTFに参加した際に、手を動かしながら攻撃や防御の仕組みを理解していくプロセスに面白さを感じていたこともあり、その延長として学習を継続しています。 現在は、TryHackMe を用いたハンズオン形式の学習や社外CTFへの参加、書籍でのインプットなどを通じて、少しずつ知識と経験を積み重ねています。 blog.cybozu.io これらの取り組みを通じて、1年目は脆弱性情報を追うだけで精一杯でしたが、2年目に入り、それらに対してどのように向き合い、どのようにアプローチしていくかの引き出しが少しずつ増えてきたと感じています。また、セキュアサプライチェーン対策など、より実践的な経験を積めるタスクにも挑戦しています。 3年目に向けて この1年は、社内外問わずさまざまなことに挑戦してきました。 2年目は、目の前のタスクをこなすだけでなく、チームやプロジェクト、プロダクト全体に対して価値を出す経験が少しずつ増えてきたと感じています。 一方で、個々の取り組みがまだ点で終わってしまっており、それらをつなげてユーザー・Garoon開発チームのメンバーに価値を届けることが次の課題です。 3年目は、これまでの経験をもとに、個々の取り組みを再現性のある形に整理しながら、チームやプロダクト全体により踏み込んで関わっていきたいと考えています。 おわりに(3人の振り返りブログを通して) 3人それぞれの記事、いかがでしたでしょうか。 同じQAエンジニアという職種でありながら、サイボウズでは所属するチームやプロダクトが異なると、日々の業務内容や直面する課題、成長のかたちもこんなにも違うのだと、改めて実感しています。 これらの記事がQAエンジニアという職種に興味を持っているみなさんや、同じように日々奮闘しているエンジニアのみなさんにとって、少しでも参考になれば幸いです。 これからも3人で切磋琢磨しながら、チームや組織に貢献できるQAエンジニアを目指していきます!
この記事はkintone生成AIチームで連載中のkintone AI リレーブログ 2026 の8本目の記事です。 リレーブログでは生成AIチームのメンバーがAIトピックに限らず、さまざまなことについて発信していきます。 こんにちは! kintone の生成 AI チームでソフトウェアエンジニアをやっている福田です。 以前の記事で生成 AI チームで Kubernetes の基盤を構築してアプリケーションを運用していることをご紹介しました。 アプリケーションを運用する上で、セキュリティは欠かせない要件の 1 つです。 セキュリティと一口に言ってもさまざまな側面での対策が考えられますが、アプリケーションによる通信を無条件で許可するのではなく、必要な経路に絞って許可することは最も基本的な対策のひとつなのではないでしょうか。 Kubernetes ではこのような要件に対応するための仕組みとして NetworkPolicy という仕組みが用意されています。 この記事では EKS Auto Mode 環境で NetworkPolicy をどのように適用しているか、そして、実際に遭遇したハマりどころと解決方法を共有します。 NetworkPolicy の基本 Kubernetes の NetworkPolicy は Pod の通信を IP アドレスとポート単位で制御できる仕組みです。 NetworkPolicy は Namespace 単位のリソースとなっており、1 つの NetworkPolicy リソースを複数の Namespace の Pod に適用することはできません。(ある Namespace の Pod から他の Namespace の Pod への通信を許可することはできます。) 指定方法としては ある Pod が通信できる相手を Pod の selector または CIDR 範囲で指定します。 それぞれの用途としては、クラスタ内の Pod を指定したい場合は Pod の selector、通信元や通信先としてクラスタ外部を指定したい場合は CIDR 範囲で指定することになります。 NetworkPolicy はステートフルに通信を制御するので、通信先の egress が許可されていれば戻りの通信も許可されます。 ただし、通信先の Pod に NetworkPolicy が適用されている場合、その Pod の ingress として通信元の Pod を指定しないと通信ができないので注意が必要です。 Pod に NetworkPolicy が適用されると、その Pod は ingress/egress いずれかが「隔離された」状態になり、許可された通信以外は拒否されるようになります。 例えば、ある Pod に ingress の通信を制御するポリシーが 1 つでも存在すれば、その Pod は許可された経路以外の通信は受け入れなくなります。 egress の場合も同様に、Pod に割り当てられたポリシーが 1 つでも存在すれば、その Pod は許可された経路以外に通信できなくなります。 以下は app-1 namespace の app=hoge というラベルを持った Pod から app-2 namespace の app=fuga というラベルを持った Pod への通信を許可するような NetworkPolicy の例です。 apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-hoge-egress namespace: app-1 spec: egress: - ports: - port: 80 protocol: TCP to: - podSelector: matchLabels: app: fuga podSelector: matchLabels: app: hoge policyTypes: - Egress このポリシーだけを適用した場合、app-2 の app=fuga に ingress ルールが 1 つも適用されていない場合は通信できます。 適用されている場合は以下のルールも追加で適用する必要があります。 apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-fuga-ingress namespace: app-2 spec: ingress: - ports: - port: 80 protocol: TCP from: - podSelector: matchLabels: app: hoge podSelector: matchLabels: app: fuga policyTypes: - Ingress EKS Auto Mode での NetworkPolicy の有効化 Amazon EKS Auto Mode では Amazon VPC CNI(以下 VPC CNI)を使用してネットワークの設定を行う構成になっています。 VPC CNI はデフォルトでは NetworkPolicy が使用できませんが、ConfigMap を作成して NodeClass で有効化することで簡単に有効化できます。 デフォルトで作成される NodeClass では既に有効化されているので、実質的には ConfigMap を 1 つ作成するだけで有効化できます。 apiVersion: v1 kind: ConfigMap metadata: name: amazon-vpc-cni namespace: kube-system data: enable-network-policy-controller: "true" このような ConfigMap を作成することで、NetworkPolicy がデフォルト allow の状態で有効化されます。 デフォルト deny にするには NodeClass の設定を変更する必要があります。デフォルトで作成される NodeClass の設定を変更することはできないようなので NodeClass を自分で定義する必要があり、やや複雑な設定が必要になります。 NetworkPolicy の適用方針 私たちの環境では、デフォルトで全ての ingress と egress の通信を拒否しておき、必要な経路のみで通信を許可する方針で NetworkPolicy を適用しています。 このようにすることで、通信経路を明示的に許可する必要があるため、意図しない通信を防止できます。 一方で、必要な通信経路を全て許可するための NetworkPolicy を定義する必要があるため、運用の手間が増えるのはデメリットです。 このデメリットを軽減するための工夫については後述します。 ハマったところ DNS 解決のために Node 上のプロセスとの通信許可が必要 ある Pod からクラスタ上の他のサービスの名前解決を行うためには、クラスタの CoreDNS と通信する必要があります。EKS Auto Mode では CoreDNS はクラスタ上の Pod としてではなく、ノード上のプロセスとして起動するため、Pod の selector は使用できず、ipBlock を使用して IP アドレス単位のアクセス許可を行う必要があります。 Kubernetes 上で Pod が CoreDNS と通信可能にするためには、kube-system namespace 内の k8s-app: kube-dns というラベルを持った Pod に対してアクセス許可を設定すればよいことが多いです。 しかし、EKS Auto Mode では CoreDNS は Pod としてではなくノード上のプロセスとして起動するため、Pod の selector を使用してアクセス許可を設定することができません。 代わりに、EKS Auto Mode では、CoreDNS はクラスタ CIDR の .10 で終わる IP アドレスに割り当てられる1ため、以下のような ipBlock を指定するルールを適用する必要がありました。 apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-egress-to-coredns namespace: your-namespace spec: egress: - ports: - port: 53 protocol: UDP - port: 53 protocol: TCP to: - ipBlock: cidr: <cluster-cidr>.10/32 podSelector: matchLabels: app: your-app policyTypes<span class="synSpeci