🐈

EKS構成を把握するためにNeo4j Desktopを使う

2023/05/01に公開

k8sは運用するコンポーネントが多く、アプリ開発を続けていくうちに全体像が把握しづらくなりそう...という危機感からNeo4jを使ってk8s構成の可視化を試しました。
この記事ではNeo4j Desktopを使ってAmazon EKSを可視化しています。

Neo4j Desktopについて

Download Neo4j Desktopからインストールできます。
以前はneo4jパッケージをインストールしてサーバをローカル起動して...と言う手順が必要でしたが、Neo4j DesktopによってGUIで簡単にNeo4jサーバを起動できるようになりました。

個人的にはその分、プラグインを有効化したりneo4j.confapoc.confの保存ディレクトリを探したり、意外と手間取りました。
今回は名前空間・ポッド・コンテナの構成情報を可視化するため、以下を準備しておきます。

プラグイン有効化

https://neo4j.com/docs/desktop-manual/current/operations/install-plugin/
APOCをインストールしておきます。

コンフィグとデータを管理ディレクトリに配置

Default file locationsを参考にGUIからフォルダを開くと簡単に見つけられます。

  • kubectlで取得したEKS構成情報

    • 取得コマンドはkubectl get namespace -o=jsonkubectl get pod -A -o=json、これらjsonファイルはImportディレクトリに配置します
      $ ll import
      total 1584
      -rw-r--r--@ 1 ts  staff    4203  4 29 14:01 kubectl_namespace.json
      -rw-r--r--@ 1 ts  staff  801081  4 29 14:02 kubectl_pods.json
      
  • apoc.load.json有効化

    • デフォルト無効のためapoc.confを新規作成してConfigurationディレクトリに配置します
      $ cat conf/apoc.conf
      apoc.import.file.enabled=true
      

EKS構成のjsonデータをNeo4jにロード

call apoc.load.json("./kubectl_namespace.json")
yield value
with value
unwind value.items as item
merge (namespace:NameSpace {name: item.metadata.name, status: item.status.phase})

return namespace
;

配列の展開はUNWINDを使いつつ、MERGEでノードを作成します。

call apoc.load.json("./kubectl_pods.json")
yield value
with value
unwind value.items as item
merge (pod:Pod {name: item.metadata.name, namespace: item.metadata.namespace})

with value
unwind value.items as item
match (pod:Pod {name: item.metadata.name})
set pod.application = item.metadata.labels.app

return pod
;

MERGEではnullを許容しない仕様のため、後からSETで属性を追加しています。
ref: https://community.neo4j.com/t/unwind-with-js-driver-yields-cannot-merge-node-using-null-property/15488

最低限のノードを作成したのでrelationを作成します。

match (n:NameSpace)
match (p:Pod)
where p.namespace = n.name
merge (p)-[:IN]->(n)
;

この時点でグラフは次のようになりました。名前空間ごとにどの程度のPodが存在するかわかります。

Pod内で起動しているコンテナをノード追加

Podでは複数コンテナが起動していることが一般的なため、Pod内の各コンテナをノードとして追加します。

call apoc.load.json("./kubectl_pods.json")
yield value
with value
unwind value.items as item
unwind item.spec.containers as c
match (pod:Pod)
where pod.name = item.metadata.name
merge (con:Container {name: c.name, image: c.image})<-[:RUN]-(pod)

return con, pod
;

再帰的な配列の展開をしたい場合はUNWINDを複数宣言すれば済み、上記ではコンテナの配列を展開しつつ既存のPod名と一致するコンテナノードを作成しています。

作成済みのノードに任意の属性を追加

検索用途を考えて、Podにkind属性を追加します。この値はPodのワークロード種別を表しています。
ref: ワークロードのデプロイの概要

call apoc.load.json("./kubectl_pods.json")
yield value
with value
unwind value.items as item
match (pod:Pod {name: item.metadata.name})
set pod.kind = item.metadata.ownerReferences[0].kind
;

クエリ検索いろいろ

全ノード取得

match (n:NameSpace)--(p:Pod)--(c:Container)
return n,p,c
;

ReplicaSetのPod全て

match (n:NameSpace)--(p:Pod)--(c:Container)
where p.kind = "ReplicaSet"
return n,p,c

ECRイメージを使っていないコンテナ

match (n:NameSpace)--(p:Pod)--(c:Container)
where not c.image =~ '.*\.ecr\..*'
return n,p,c
;

今後の課題

まずは内部ツールとして使い始める可能性も有望ですが、Neo4j Desktopは個人利用に限定されているため、チームで使いたい場面ではグラフDBを構築する必要が出てきます。
また、Cypherクエリをチーム内で共有する方法も検討する必要があり、クエリやデータをGitHub管理したい場合はWebアプリを作成することになりそうです。

現段階ではJupyterNotebookでCypherクエリ環境をつくって、チーム開発に対応できないか検証してみたいところです。

参考ページ

Cypher Manual / Clauses
neo4j-graph-examples

Discussion