Kubernetesのダッシュボードは無数にありますが、Headlampというオープンソースのダッシュボードが手触りよかったので、備忘録を兼ねて紹介です。
OIDC認証に対応しているのでEKSならCognito連携もできて、Karpenterの状態もプラグインで詳細に追いかけることができます。また、イベントは警告でデフォルトフィルター表示されて、マップビューでクラスター全体のリソース展開状況を見たり、特定のノード、namespaceに絞り込めたり... 運用しててほしい情報が何か考えられている感じなのが気に入りました。
知ったきっかけはKubernetes公式ブログで、Karpenterプラグインの紹介記事を読んで興味を持ちました。公式ブログやXは割と面白いプロダクトを紹介してくれるので、気が向いたらチェックするとよいです。
誰向けのダッシュボード?
ダッシュボードと一口にいっても、対象ユーザーによって求められる機能は異なります。例えばKubernetes管理をするならクラスター全体の状態を把握したい一方で、アプリケーション開発者は自分のアプリケーションに関連するリソースの管理だけに集中したいでしょう。使う人によって欲しい情報の粒度が異なるのはKubernetes運用の地味に難しいところです。
HeadlampはKubernetesのリソース状態を詳細に追いかけたい運用担当者、開発者向けのダッシュボードです。特に以下のようなニーズを持つユーザーに適していると感じます。
- Kubernetesのリソースを視覚的に管理したい開発者
- クラスターの状態をリアルタイムで監視したい運用担当者
- Podのイベントやログを迅速に確認したいエンジニア
- KarpenterやKEDAなどのオートスケーリングツールの状態を詳細に把握したいユーザー
逆に、初心者向けのシンプルなダッシュボードを求めている場合や、特定のアプリケーションの監視に特化したダッシュボードを探している場合には、精細すぎるきらいがあります。
例えばアプリケーションエンジニアに向いたダッシュボード的な存在としてArgoCDがあります。Git Opsデプロイとして有名ですが、それに付随してアプリケーション単位でリソースをまとめてくれます。結果として、ArgoCD Web UIからリソースの正常状態が確認でき、Deploymentのリスタートもできたり、Ingressからsvc経由してDeploymentまでのネットワーク的な図も見られるため、デプロイしたアプリケーション管理に特化したい場合にはこっちが適しています。
Headlampの特徴
Headlampは以下のような特徴を持っています。
- Kubernetes-sigが管理しているオープンソースプロジェクト - kubernetes-sigs/headlamp
- 利用形態を2種類から選択可能
- デスクトップアプリケーションとしての利用
- Kubernetesインクラスターでダッシュボードサーバーとして利用
- プラグインによる拡張性(Karpenterプラグインなど)
- リソースの詳細な表示と管理
- マップビューによるクラスター全体のリソース展開状況の可視化
- OIDC認証のサポート
デスクトップアプリケーション版のHeadlamp
さくっとルックアンドフィールで触りたいならデスクトップアプリケーション版がおすすめです。公式サイトからダウンロードしてインストールするだけで、すぐにKubernetesクラスターに接続して利用できます。
よくあるツール同様、手元の.kube/configを参照して認証してくれるので、割と使い勝手がいいです。
Headlampをインストールする
インストール手順に従って自分のOSに合わせてHeadlampをインストールしましょう。なお、Kubernetes SIGに管理が移行してからアプリ署名ができていないようで、Windows/macOSでは起動時にセキュリティ警告が出る場合もあり自己責任でどうぞとのアナウンスが出ています。
もしバイナリが欲しいなら、リリースページからダウンロードできます。
# Windows
$ winget install headlamp
# macOS
$ brew install --cask --no-quarantine headlamp
# Linux (バイナリ版)
$ ./Headlamp-0.36.0-linux-x64.AppImage
起動してKubernetesクラスターに接続する
起動すると.kube/configに基づいてクラスターを選択できます。認証が取れていないクラスターのステータスはBad Gatewayが表示されます。接続できるときはアクティブ状態になります。

クラスターを選択するとダッシュボードが表示されます。あとは好きにリソースを見たり操作したりできます。ダッシュボード周りのUIはインクラスター版とほぼ同じなので、後述のクイックツアーを参考にしてください。

ちなみに設定を見ると言語やテーマも調整できます。言語選択が日本語、英語に限らないのは、たいていのオープンソースが作者の自国+英語対応なのを考えると使いやすいですね。

インクラスター版のHeadlamp
インクラスター版はKubernetesクラスター内にHeadlampサーバーをデプロイして利用します。利用者各自がHeadlampをインストールせずとも利用できるので、チームでKubernetesクラスターを管理・利用している場合に便利です。
インクラスターを紹介するにあたり、HeadlampはOIDC認証が使えるのは重要なポイントです。1EKSならEKS OIDC Provider ConfigurationでCognito連携させれば、Cognitoに登録したユーザー・グループでOIDC認証が利用できます。
OIDC認証のEKS構成時の要点は次の通りです。Headlampに限らず、Cognito連携ではだいたいこの流れです。
- Cognitoユーザープール・アプリクライアントを作成し、Headlampの接続URLを元にリダイレクトURIを設定
- Cognitoドメインを設定 (必要ならCognito IdPも)
- EKSクラスターのOIDCプロバイダーにCognitoユーザープールを紐づけ、Cognitoからemail/groups属性を取得可能に
- HelmでHeadlampをデプロイ、values.yamlでoidc.configでOIDC設定
- ClusterRoleBindingでKubernetes権限とCognitoグループ・Cognitoユーザーを紐づけ
- Headlampにサインイン時、Cognito認証画面が表示されてHeadlampからKubernetes操作
Pulumiで構成する例
以下は公式のCognito OIDCドキュメントをベースに、PulumiでEKSクラスターとCognito連携のOIDC認証を構成する例です。Terraformも同様なので、参考にしてください。2
Cognitoユーザープールとアプリクライアントを作成する
Pulumi C#でCognitoユーザープールとアプリクライアントを作成するコード例を示します。ユーザープールはemail属性をユーザー名として利用し、セルフサインアップを許可しています。MFAはTOTPアプリを利用する設定です。
using Pulumi;
using Pulumi.Aws.Cognito;
using Pulumi.Aws.Cognito.Inputs;
namespace MyCognitoApp;
var name = "my-cognito";
var opt = new CustomResourceOptions { Parent = this };
var userPoolName = "my-cognito-userpool";
var callBackUrls = new[] { "http://localhost:8080/oidc-callback" };
var defaultRedirectUri = "http://localhost:8080/oidc-callback";
var users = ["foo@example.com"];
var userPool = new UserPool($"{name}-userpool", new()
{
Name = userPoolName,
UsernameAttributes = [usernameAttribute],
AutoVerifiedAttributes = ["email"],
UserAttributeUpdateSettings = new UserPoolUserAttributeUpdateSettingsArgs
{
AttributesRequireVerificationBeforeUpdates = ["email"]
},
VerificationMessageTemplate = new UserPoolVerificationMessageTemplateArgs
{
DefaultEmailOption = "CONFIRM_WITH_CODE",
EmailMessage = "Verification Code is {####}",
EmailSubject = $"Your verification code for cognito userpool {userPoolName}",
SmsMessage = "Your verification code is {####}",
},
AdminCreateUserConfig = new UserPoolAdminCreateUserConfigArgs
{
AllowAdminCreateUserOnly = false,
InviteMessageTemplate = new UserPoolAdminCreateUserConfigInviteMessageTemplateArgs
{
EmailSubject = $"Your temporary password for cognito {userPoolName}",
EmailMessage = "Your username is {username} and temporary password is {####}.",
SmsMessage = "Your username is {username} and temporary password is {####}.",
},
},
UsernameConfiguration = new UserPoolUsernameConfigurationArgs
{
CaseSensitive = false,
},
MfaConfiguration = "ON",
AccountRecoverySetting = new UserPoolAccountRecoverySettingArgs
{
RecoveryMechanisms = [new UserPoolAccountRecoverySettingRecoveryMechanismArgs
{
Name = "verified_email",
Priority = 1,
}],
},
SoftwareTokenMfaConfiguration = new UserPoolSoftwareTokenMfaConfigurationArgs
{
Enabled = true,
},
}, opt);
var cognitoDomain = new UserPoolDomain($"{name}-domain", new()
{
Domain = $"{name}-auth-cysharpdev",
UserPoolId = userPool.Id,
}, opt);
var userGroup = new UserGroup($"{name}-group-admin", new()
{
Name = "admin",
UserPoolId = userPool.Id,
Description = "Created by Pulumi",
Precedence = 10,
}, opt);
foreadch (var item in users)
{
var user = new User($"{name}-user-{item}", new()
{
Username = item,
UserPoolId = userPool.Id,
DesiredDeliveryMediums = ["EMAIL"],
Enabled = true,
ForceAliasCreation = true,
TemporaryPassword = "TEMPORARYPassword!!!!9999999",
Attributes = new InputMap<string>
{
["email"] = item,
},
}, new CustomResourceOptions { Parent = this, IgnoreChanges = ["attributes[\"email_verified\"]"]});
_ = new UserInGroup($"{name}-useringroup-{item}-admin", new()
{
UserPoolId = userPool.Id,
GroupName = userGroup.Name,
Username = user.Username,
}, opt);
}
var client = new UserPoolClient($"{name}-client-eks", new()
{
Name = item.Name,
AllowedOauthFlowsUserPoolClient = true,
AllowedOauthFlows = ["code"],
AllowedOauthScopes = ["email", "openid", "profile"],
CallbackUrls = callBackUrls,
DefaultRedirectUri = defaultRedirectUri,
LogoutUrls = [],
UserPoolId = userPool.Id,
SupportedIdentityProviders = ["COGNITO"],
GenerateSecret = true,
}, opt);
EKSクラスターにOIDCプロバイダーを紐づける
EKSのOIDCプロバイダーをCognitoユーザープールに紐づけるコード例を示します。EKSクラスターを作成するコードはよくあるので割愛します。
ちなみにEKSクラスターのOIDCプロバイダーはEKSクラスターがReady状態になってからじゃないと設定できません。depends_onはリソースの作成を待つだけで、クラスターのReady状態を待つわけではないので使えないため、EKSクラスターの作成部分をPulumi Componentクラスに分離してクラスター完了まで待つのがオススメです。TerraformならModule分離すると、同様にクラスター完了まで待ってくれます。
var name = "automode";
var eksCluster = new Cluster($"{name}-cluster", new ClusterArgs
{
}, opt);
_ = new IdentityProviderConfig($"{name}-idp-config-cognito", new()
{
ClusterName = eksCluster.Name,
Oidc = new IdentityProviderConfigOidcArgs
{
IdentityProviderConfigName = "cognito-idp",
ClientId = client.Id,
IssuerUrl = userPool.Endpoint.Apply(x => $"https://{x}"),
UsernameClaim = "email",
GroupsClaim = "cognito:groups",
GroupsPrefix = "gid:",
},
}, opt);
HeadlampをHelmでデプロイする
EKSとCognitoのOIDC連携ができたら、HelmでHeadlampをデプロイします。HelmチャートはArtifact Hubで公開されています。values.yamlにはCognito連携のOIDC設定を指定しておくとよいでしょう。
helm repo add headlamp https://kubernetes-sigs.github.io/headlamp/
helm repo update
helm upgrade --install headlamp headlamp/headlamp --version 0.37.0 -n kube-system -f ./values.yaml
以下はvalues.yamlの例です。簡単のためCognitoのclientID、clientSecretを直書きしていますが、Secrets ManagerなどにいれてExternal Secrets Operatorで参照するほうがおすすめです。
config:
inCluster: true
baseURL: ""
oidc:
clientID: "CognitoUserPoolに作ったクライアントのclient IDを指定"
clientSecret: "CognitoUserPoolに作ったクライアントのclient secretを指定"
issuerURL: "CognitoユーザープールのURLを指定 (https://cognito-idp.{region}.amazonaws.com/{userPoolId})"
scopes: "openid,profile,email"
callbackURL: "http://localhost:8080/oidc-callback"
インストールすると、Headlampサーバーが起動します。HeadlampのサービスタイプがClusterIPの場合、helmコマンドの実行時にkubectl port-forwardでローカルの8080ポートに転送してアクセスする案内が標準出力に出るので、http://localhost:8080でクラスター起動しているHeadlampにアクセスしてみましょう。
export POD_NAME=$(kubectl get pods --namespace {{ include "headlamp.namespace" . }} -l "app.kubernetes.io/name={{ include "headlamp.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
export CONTAINER_PORT=$(kubectl get pod --namespace {{ include "headlamp.namespace" . }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
echo "Visit http://127.0.0.1:8080 to use your application"
kubectl --namespace {{ include "headlamp.namespace" . }} port-forward $POD_NAME 8080:$CONTAINER_POR
Headlampにアクセスできるユーザー・グループと権限の紐づけ
ClusterRoleBingingで、OIDC認証したユーザー(UserClaim)やグループ(GroupsClaim)とKubernetesの権限を紐づけます。
kubectl apply -f headlamp-clusterrolebinding.yaml
例えば次のような設定にすると、foo@example.comユーザーがKubernetesのcluster-admin権限を持ってHeadlampにログインできます。
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: headlamp-admin-user-clusterrolebinding
subjects:
- kind: User
name: foo@example.com
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: cluster-admin
apiGroup: rbac.authorization.k8s.io
あるいは次のような設定にすると、Cognito Groupadminに所属するユーザーがKubernetesのcluster-admin権限を持てます。
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: headlamp-admin-user-clusterrolebinding
subjects:
- kind: Group
name: gid:admin
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: cluster-admin
apiGroup: rbac.authorization.k8s.io
Headlampクイックツアー
さくっとHeadlampのUIを見てみましょう。未認証だとログイン画面が表示されるので、Signinを選んでログインします。Cognito連携しているならCognitoのログイン画面が出ます。

サインインすると、デスクトップ版同様にダッシュボードが表示されます。左ペインにリソースなどの選択、右ペインに詳細が表示されます。トップページがイベント、かつ警告フィルターされているのよくわかってる感じあります。Kubernetes運用で一番欲しい情報はこれですからね。PodがPendingならイベントですぐ知りたいあるあるです。

Namespace一覧、Node一覧も見やすいです。まぁ、Nodeが100台とかあるときりがないですがしょうがない。Taintsが出ているのは地味に便利です。kubectlでいい感じに拾うの、実はだるいんですよね。


他のダッシュボードと違うのがマップビューです。ノード、Namespaceなどで絞り込んだり、全展開してリソースを表示したりできます。イベント的に警告があると黄色マーカーがつくのもわかりやすいです。とはいえ、意外と正常でも警告イベントは出る、っていうのもありがちなので割り切りも必要です。

リソースを選択すると、右ペインに詳細が表示されます。おおむねkubectl describe相当の情報が見られます。下にスクロールするとリソースのイベントも見られますし、右上アイコンからログを見たり、シェルをつないだりもできます。

ワークロードにはPodやDeployment、StatefulSet、DaemonSet、Jobなどよくあるリソースがまとめて表示されます。この辺りはEKSクラスターのUIも同じなので見慣れている人も多いでしょう。

きりがないので端折ります。Secretsは目玉アイコンをクリックするとbase64デコードされた値が見られます。kubectlで-o jsonpathとかで取り出すの地味に面倒なので、地味に便利です。

CRDは他ダッシュボードより圧倒的に完成度が高いです。CRDであってもいい感じにデータを表示してくれます。プラグインを入れてなくても、YAMLで表示とか決まったカラムだけ出す、みたいな限定的な表示に収まっていないのはすごいです。

Pluginsで機能拡張
Headlampの最大の特徴はPluginsによる機能拡張です。アーキテクチャの図にあるように、プラグインの実体はNodeアプリケーションです。
インクラスター版は、プラグインをクラスター内部で動作させる必要があるため、Helmのvalues.yamlでプラグインを指定します。

デスクトップ版は、先に紹介したPlugin Catalogから好きなプラグインを選んでインストールできます。必要なら適当にPluginリポジトリをクローン、ローカルでnpm startもできます。

デスクトップ版のプラグイン管理
デスクトップ版は、Plugin Catalogから好きなプラグインを選んでインストールできます。デフォルトでapp-catalog、plugin-catalog、prometheusプラグインが登録されているのでいい感じに選べる感じです。プラグインのインストールはインクラスターに比べると格段に楽です。デスクトップ版なので、各自で好きなプラグインを利用できるのも使いやすいポイントです。

インストールしたプラグインはPlugin CatalogのInstalledタブから確認できます。

例えばKarpenterプラグインを入れると、Karpenterで管理しているNodePoolやEC2NodeClassをHeadlampから確認できます。プラグインの詳細は後ほど。

インクラスター版のプラグイン管理
インクラスター版は、Helmのvalues.yamlでプラグインをインストールするのがGit履歴でも管理しやすくおすすめです。公式サイトのPluginページを見ると、Helm Valuesでプラグインを指定する方法が紹介されています。ちなみに、Pluginだけ別ファイルにしてHelm実行時にcatして割り当てる方法も載っていますが、ここではvalues.yamlに直接書き込む方法を紹介します。
利用できるプラグインは、Artifact HubにてHeadlamp Pluginカテゴリで公開されています。3 例えば、Karpenterプラグイン、KEDAプラグイン、Trivyプラグイン、AI Assistantプラグインを導入してみましょう。
ちなみに、config.watchPlugins: trueを指定しないとプラグイン認識しないので注意してください。私はこれに気づかず時間を使いました。設定キー名からそんな挙動だって思わなくないですか。
config:
watchPlugins: true
pluginsManager:
enabled: true
configContent: |
plugins:
- name: karpenter
source: https://artifacthub.io/packages/headlamp/headlamp-plugins/headlamp_karpenter
version: 0.1.0
- name: keda
source: https://artifacthub.io/packages/headlamp/headlamp-plugins/headlamp_keda
version: 0.1.1-beta
- name: trivy
source: https://artifacthub.io/packages/headlamp/headlamp-trivy/headlamp_trivy
version: 0.3.1
- name: ai-assistant
source: https://artifacthub.io/packages/headlamp/headlamp-plugins/headlamp_ai_assistant
version: 0.1.0-alpha
installOptions:
parallel: true
maxConcurrent: 2
baseImage: node:lts-alpine
version: latest
securityContext:
runAsNonRoot: false
readOnlyRootFilesystem: false
runAsUser: 0
helmインストールすると、Headlamp Podにサイドカーコンテナheadlamp-pluginが生えて、プラグインがインストールされます。
headlamp-78d487fbd8-597zf headlamp-plugin 5 packages are looking for funding
headlamp-78d487fbd8-597zf headlamp-plugin run `npm fund` for details
headlamp-78d487fbd8-597zf headlamp-plugin npm notice
headlamp-78d487fbd8-597zf headlamp-plugin npm notice New patch version of npm available! 11.6.1 -> 11.6.2
headlamp-78d487fbd8-597zf headlamp-plugin npm notice Changelog: https://github.com/npm/cli/releases/tag/v11.6.2
headlamp-78d487fbd8-597zf headlamp-plugin npm notice To update run: npm install -g npm@11.6.2
headlamp-78d487fbd8-597zf headlamp-plugin npm notice
headlamp-78d487fbd8-597zf headlamp-plugin Installed headlamp-plugin successfully.
headlamp-78d487fbd8-597zf headlamp-plugin Installing plugins from config...
headlamp-78d487fbd8-597zf headlamp {"level":"info","duration_ms":"2.45","source":"/headlamp/backend/cmd/headlamp.go","line":1390,"time":"2025-10-29T09:37:08Z","message":"Request completed successfully"}
headlamp-78d487fbd8-597zf headlamp-plugin
headlamp-78d487fbd8-597zf headlamp-plugin plugins:
headlamp-78d487fbd8-597zf headlamp {"level":"info","duration_ms":"12.84","source":"/headlamp/backend/cmd/headlamp.go","line":1390,"time":"2025-10-29T09:37:08Z","message":"Request completed successfully"}
headlamp-78d487fbd8-597zf headlamp-plugin - name: karpenter
headlamp-78d487fbd8-597zf headlamp {"level":"info","duration_ms":"9.28","source":"/headlamp/backend/cmd/headlamp.go","line":1390,"time":"2025-10-29T09:37:09Z","message":"Request completed successfully"}
headlamp-78d487fbd8-597zf headlamp-plugin source: https://artifacthub.io/packages/headlamp/headlamp-plugins/headlamp_karpenter
headlamp-78d487fbd8-597zf headlamp-plugin version: 0.1.0
headlamp-78d487fbd8-597zf headlamp-plugin - name: keda
headlamp-78d487fbd8-597zf headlamp-plugin source: https://artifacthub.io/packages/headlamp/headlamp-plugins/headlamp_keda
headlamp-78d487fbd8-597zf headlamp-plugin version: 0.1.1-beta
headlamp-78d487fbd8-597zf headlamp-plugin - name: trivy
headlamp-78d487fbd8-597zf headlamp-plugin source: https://artifacthub.io/packages/headlamp/headlamp-trivy/headlamp_trivy
headlamp-78d487fbd8-597zf headlamp-plugin version: 0.3.1
headlamp-78d487fbd8-597zf headlamp-plugin - name: ai-assistant
headlamp-78d487fbd8-597zf headlamp-plugin source: https://artifacthub.io/packages/headlamp/headlamp-plugins/headlamp_ai_assistant
headlamp-78d487fbd8-597zf headlamp-plugin version: 0.1.0-alpha
headlamp-78d487fbd8-597zf headlamp-plugin installOptions:
headlamp-78d487fbd8-597zf headlamp-plugin parallel: true
headlamp-78d487fbd8-597zf headlamp-plugin maxConcurrent: 2
headlamp-78d487fbd8-597zf headlamp-plugin info: Installing plugins from config: /config/plugin.yml
headlamp-78d487fbd8-597zf headlamp-plugin 1 of 4 (karpenter): info: Installing plugin karpenter
headlamp-78d487fbd8-597zf headlamp-plugin 1 of 4 (karpenter): info: Fetching Plugin Metadata
headlamp-78d487fbd8-597zf headlamp-plugin 2 of 4 (keda): info: Installing plugin keda
headlamp-78d487fbd8-597zf headlamp-plugin 2 of 4 (keda): info: Fetching Plugin Metadata
headlamp-78d487fbd8-597zf headlamp-plugin 2 of 4 (keda): info: Plugin Metadata Fetched
headlamp-78d487fbd8-597zf headlamp-plugin 2 of 4 (keda): info: Downloading Plugin
headlamp-78d487fbd8-597zf headlamp-plugin 1 of 4 (karpenter): info: Plugin Metadata Fetched
headlamp-78d487fbd8-597zf headlamp-plugin 1 of 4 (karpenter): info: Downloading Plugin
headlamp-78d487fbd8-597zf headlamp-plugin 1 of 4 (karpenter): info: Plugin Downloaded
headlamp-78d487fbd8-597zf headlamp-plugin 1 of 4 (karpenter): info: Extracting Plugin
headlamp-78d487fbd8-597zf headlamp-plugin 2 of 4 (keda): info: Plugin Downloaded
headlamp-78d487fbd8-597zf headlamp-plugin 2 of 4 (keda): info: Extracting Plugin
headlamp-78d487fbd8-597zf headlamp-plugin 2 of 4 (keda): info: Plugin Extracted
headlamp-78d487fbd8-597zf headlamp-plugin Moved directory from /tmp/headlamp-plugin-temp-iMEOnN/headlamp_keda to /headlamp/plugins/headlamp_keda
headlamp-78d487fbd8-597zf headlamp-plugin 2 of 4 (keda): success: Plugin Installed
headlamp-78d487fbd8-597zf headlamp-plugin 2 of 4 (keda): success: Plugin installed successfully
headlamp-78d487fbd8-597zf headlamp-plugin 1 of 4 (karpenter): info: Plugin Extracted
headlamp-78d487fbd8-597zf headlamp-plugin Moved directory from /tmp/headlamp-plugin-temp-ApkBDO/headlamp_karpenter to /headlamp/plugins/headlamp_karpenter
headlamp-78d487fbd8-597zf headlamp-plugin 1 of 4 (karpenter): success: Plugin Installed
headlamp-78d487fbd8-597zf headlamp-plugin 1 of 4 (karpenter): success: Plugin installed successfully
headlamp-78d487fbd8-597zf headlamp-plugin 3 of 4 (trivy): info: Installing plugin trivy
headlamp-78d487fbd8-597zf headlamp-plugin 3 of 4 (trivy): info: Fetching Plugin Metadata
headlamp-78d487fbd8-597zf headlamp-plugin 4 of 4 (ai-assistant): info: Installing plugin ai-assistant
headlamp-78d487fbd8-597zf headlamp-plugin 4 of 4 (ai-assistant): info: Fetching Plugin Metadata
headlamp-78d487fbd8-597zf headlamp-plugin 3 of 4 (trivy): info: Plugin Metadata Fetched
headlamp-78d487fbd8-597zf headlamp-plugin 3 of 4 (trivy): info: Downloading Plugin
headlamp-78d487fbd8-597zf headlamp-plugin 4 of 4 (ai-assistant): info: Plugin Metadata Fetched
headlamp-78d487fbd8-597zf headlamp-plugin 4 of 4 (ai-assistant): info: Downloading Plugin
headlamp-78d487fbd8-597zf headlamp-plugin 3 of 4 (trivy): info: Plugin Downloaded
headlamp-78d487fbd8-597zf headlamp-plugin 3 of 4 (trivy): info: Extracting Plugin
headlamp-78d487fbd8-597zf headlamp-plugin 4 of 4 (ai-assistant): info: Plugin Downloaded
headlamp-78d487fbd8-597zf headlamp-plugin 4 of 4 (ai-assistant): info: Extracting Plugin
headlamp-78d487fbd8-597zf headlamp-plugin 3 of 4 (trivy): info: Plugin Extracted
headlamp-78d487fbd8-597zf headlamp-plugin Moved directory from /tmp/headlamp-plugin-temp-NlAooa/headlamp_trivy to /headlamp/plugins/headlamp_trivy
headlamp-78d487fbd8-597zf headlamp-plugin 3 of 4 (trivy): success: Plugin Installed
headlamp-78d487fbd8-597zf headlamp-plugin 3 of 4 (trivy): success: Plugin installed successfully
headlamp-78d487fbd8-597zf headlamp-plugin 4 of 4 (ai-assistant): info: Plugin Extracted
headlamp-78d487fbd8-597zf headlamp-plugin Moved directory from /tmp/headlamp-plugin-temp-FlcHCb/headlamp_ai_assistant to /headlamp/plugins/headlamp_ai_assistant
headlamp-78d487fbd8-597zf headlamp-plugin 4 of 4 (ai-assistant): success: Plugin Installed
headlamp-78d487fbd8-597zf headlamp-plugin 4 of 4 (ai-assistant): success: Plugin installed successfully
headlamp-78d487fbd8-597zf headlamp-plugin info: Bulk installation completed: {"total":4,"failed":0,"skipped":0,"successful":4}
headlamp-78d487fbd8-597zf headlamp-plugin Watching /config/plugin.yml for changes...
Headlampでプラグインを確認する
Headlampにプラグインをインストールすると、UIに変化が現れます。例えばKarpenter、Keda、Trivyプラグインをインストールすると左ペインにメニューが追加されます。

導入しているプラグインは、Headlampの設定画面からも確認できます。Helm values.yamlで指定したプラグインが導入できたかはここを見るのがオススメです。

Karpenterプラグイン
Karpenterプラグインを使うと、Karpenterで管理しているNodePoolやEC2NodeClassをHeadlampから確認できます。Karpenterでスケーリングしているノードの状態を詳細に把握できるのは便利です。
ただ、EKS AutomodeはEC2NodeClassではなくNodeClassを使うため、HeadlampのKarpenterプラグインではNodeClassは表示されません。プラグインリポジトリ的には対応している的な文言なので、将来的に対応されそうです。気長に待ちましょう。

Kubernetesを運用していて割とほしいのが、クラスター全体のCPU、メモリに対してどれぐらい使っているかです。これはHeadlampのClusterトップページで表示されないので弱いなぁと感じるのですが、KarpenterプラグインのNode Poolから、NodePoolごとにCPU、メモリ使用率が表示されるので便利です。

運用していて気になるのが「ちゃんとPodはスケールアウトできているか」です。これを確認するにはKubernetesイベントの「Pending Podイベント」を見る必要があるのですがイベントって流れるんですよね。でも、Karpenterプラグインを入れるとPending PodsタブでPodの状態をリアルタイムで把握できます。これは本当に便利です。この気持ち、伝わってほしい。

Scaling ViewでNode Claimを見られるので、Karpenterでスケーリングしているノードの状態を詳細に把握できます。Zoneが出ているあたりがわかってる感じあります。

KEDAプラグイン
KEDAプラグインを使うと、KEDAのスケーリング設定であるScaledObjectやTriggerAuthenticationリソースをHeadlampから確認できます。ネームスペース横断でスケール対象を一括確認できるのは結構便利です。KEDAはZero to Scale4ができることもあって、複数ネームスペースにアプリケーションやDeploymentが分散していても漏れにくくなるのは運用してて嬉しいポイントです。

ScaledObjectの対象Podやトリガーが確認できるのも便利です。KEDAのスケール条件って実はちょいちょい触るわりに、詳細を把握していないとkubectlから読み解くのも難しい代表です。UIでいい感じに見られるのは助かりますよね。


MapにもScaledObjectが表示されるので、KEDAでスケーリングしているアプリケーションの分布も把握できます。

AI Assistantプラグイン
AI Assistantプラグインを使うと、そのKubernetesクラスターについてAIを使ったサポートを受けられます。プラグインをインストールすると、右上にAIアイコンが表示され、チャット形式でKubernetesに関する質問ができる感じです。ローカル環境にKubernetes MCPを使って聞く方法も広く使われつつありますが、Headlampに組み込まれているというのはAI統制的には悪くないアプローチに思えます。


AIの一覧はよくある感じです。OpenAIのモデルはGPT-4.1などでちょっと古いです。Azure OpenAIも選択できるので、企業としても使いやすい余地があります。


軽くやり取りをしてみましょう。
チャットは英語だけでなく日本語も行けます。例えば以下のような質問で英語同様の回答が返ってきていることがわかります。
さて、質問の回答はKubernetes管理者ならある程度なるほどとなる情報です。ちなみにtaintが... という部分は適切で、この時のEKSクラスターはsystemノードのみが起動していたので、taintが原因でスケジューリングされなかったことがわかります。
ただ、肝心の質問に対する回答としてはちょっと足りなくもあります。この時Podが起動しない原因は、Podが期待するnodeSelector: arm64を満たすノードに相当するNodeがないためです。Podを起動できるようにするには、KarpenterでNodePoolとしてarm64ノードを追加する必要があります。このAI回答から、どうすればいいかまで一直線にたどり着くのは難しいですが、モデルが少し古いのと、ファンクションコーリングが浅いあたり、今後のチューニングに期待です。
User
Why my nginx deployment'pod won't be running?
AI Assistant
Based on the reported warnings for your main cluster, here are several reasons why your nginx deployment pod (nginx-698f5c6f78) isn’t running:
Service Account Not Found:
The deployment is trying to use service account test-app in the default namespace, but it does not exist. You’ll see an error like:
pods "nginx-698f5c6f78-" is forbidden: error looking up service account default/test-app: serviceaccount "test-app" not found
Node Scheduling Problems:
No suitable nodes are available for pod scheduling. Specifically:
0/1 nodes are available: 1 node(s) had untolerated taint {CriticalAddonsOnly: }. no new claims to deallocate...
Your only node, i-0647b9224fd6861a2, has a taint discouraging regular pods from being scheduled unless they tolerate it.
Image Filesystem Capacity Issues:
There’s a warning indicating invalid capacity (0) on the image filesystem. This can prevent pods from starting due to lack of space.
To resolve these issues, you should:
Create the test-app service account in the default namespace, or change your nginx deployment to use an existing service account.
Either remove or add a toleration for the {CriticalAddonsOnly:} taint in your pod spec.
Check node disk/volume availability.
You
nginx Deploymentのpodが起動してこないのはなぜですか?
AI Assistant
main クラスターの警告から、nginx Deployment の Pod が起動しない主な理由は以下の通りです。
ServiceAccount が存在しない
Pod 起動時「pods "nginx-698f5c6f78-" is forbidden: error looking up service account default/test-app: serviceaccount "test-app" not found」というエラーが出ています。これは、Deployment で指定している test-app サービスアカウントが default namespace に存在しないためです。
ノードに taint がありスケジューリングできない
「0/1 nodes are available: 1 node(s) had untolerated taint {CriticalAddonsOnly: }」という警告があり、ノード i-0647b9224fd6861a2 に taint が付いているため、Pod がスケジュールされません。Pod の spec に tolerations を追加する必要があります。
image filesystem 容量が無効
「invalid capacity 0 on image filesystem」という警告があり、ノードのディスク容量不足または設定が正しくない可能性があります。
この3つが主な原因です。対応策としては:
test-app サービスアカウントを作成するか、Deployment の serviceAccount 名を修正
Pod の spec に taint を許容する tolerations を追加
ノードのディスク容量を確認し、必要であればリソース追加

調査だけでなく簡単な操作もできます。例えば、チャットからPodを削除させたり、Deploymentをリスタートさせることもできるのは怖さと便利さが入り混じっています。Get以外の操作をすると確認プロンプトが出ますが、結果がでないあたりもファンクションコールが足りない感じもあります。
You
Pod inflate-68c59b845-2phjgをterminateしてください。


この辺りの挙動はai assistantプラグインの実装を見るといいでしょう。AI Assistantはkubectlのようなコマンドを実行するのではなく、Kubernetes APIを直接叩いて情報を取得しています。例えば、DeleteやUpdateなどの操作でプロンプト制御していることもわかります。
ベースプロンプトから、AIアシスタントでどのようなユーザー体験をさせたいのかがわかります。デスクトップ版ではマルチクラスター管理していることも想定していることもわかります。
AI Assistantの難点として、チャット履歴が残りません。つまり、Headlampのウェブページをリロードすると履歴が吹き飛びます、ひどい。細かな挙動やモデル更新、履歴保持など気になるところはあるので今後のアップデートに期待しつつも、MCPサーバーでローカルからKubernetes APIを叩いて情報を取得するよりも始めやすい感じはあります。
まとめ
割と細かいところまでKubernetesリソースを追いかけられるダッシュボードとしてHeadlampは優秀で好きです。特にプラグインによる拡張性が高く、KarpenterやKEDAなどのオートスケーリングツールの状態を詳細に把握できるのは便利です。
OIDC認証もHelmで完結できるのは割とちゃんと叩かれている感じがして好印象です。EKSでCognito連携しているなら、Headlampを使うことでKubernetesリソースの管理がより効率的になるでしょう。
kubectlでわかるも大事、ArgoCDでアプリケーションデプロイを管理できるのも大事、DatadogでKubernetesクラスター状態がわかるのも大事、でもHeadlampでそこにあるKubernetesクラスターを詳細に追いかけられるのも大事、という感じで、HeadlampはKubernetes管理の選択肢として十分に価値があります。
参考