Flux Plugins brings Flux into Backstage. It is a set of UI pieces you add to your portal. They read Flux resources from your Kubernetes clusters and show them next to each service. You get clear views of Kustomizations, HelmReleases, and the sources that feed them such as GitRepositories, OCIRepositories, and HelmRepositories. The plugin uses the common Kubernetes label in Backstage to map resources to the current entity. That avoids custom wiring.
The plugin offers cards you can place on service pages, plus a Flux runtime page for a cluster wide snapshot. From one screen you can check status, revision, last reconcile, and errors. With the right permissions you can trigger a sync or suspend and resume a resource during incident work. If you use Weave GitOps you can jump from the card to deeper details. Some resources show a verification status when signature checks are set up.
Typical use cases include giving service owners a trusted picture of what is running, helping platform teams monitor many clusters from Backstage, and cutting context switching during triage. It fits teams that already use FluxCD for GitOps and want that data in their developer portal. The result is faster checks and fewer tabs.
Installation Instructions
These instructions apply to self-hosted Backstage only. To use this plugin on Roadie, visit the docs.
Step 1 Install frontend packages
yarn add --cwd packages/app @weaveworksoss/backstage-plugin-flux @backstage/plugin-kubernetes
Step 2 Install the Kubernetes backend
New backend system
yarn add --cwd packages/backend @backstage/plugin-kubernetes-backend @backstage/backend-defaults
Edit packages/backend/src/index.ts
// New backend system
import { createBackend } from '@backstage/backend-defaults';
import { kubernetesPlugin } from '@backstage/plugin-kubernetes-backend';
const backend = createBackend();
backend.add(kubernetesPlugin());
backend.start();
Old backend system
yarn add --cwd packages/backend @backstage/plugin-kubernetes-backend
Create packages/backend/src/plugins/kubernetes.ts
import { createRouter } from '@backstage/plugin-kubernetes-backend';
import { Router } from 'express';
import { PluginEnvironment } from '../types';
export default async function createPlugin(env: PluginEnvironment): Promise<Router> {
return await createRouter({
logger: env.logger,
config: env.config,
discovery: env.discovery,
tokenManager: env.tokenManager,
catalogApi: env.catalogClient,
});
}
Wire it in packages/backend/src/index.ts
import kubernetes from './plugins/kubernetes';
// inside main bootstrap
const kubernetesEnv = useHotMemoize(module, () => createEnv('kubernetes'));
apiRouter.use('/kubernetes', await kubernetes(kubernetesEnv));
Step 3 Configure clusters for the Kubernetes plugin
Edit app-config.yaml
kubernetes:
serviceLocatorMethod:
type: 'multiTenant'
clusterLocatorMethods:
- type: 'config'
clusters:
- url: https://192.168.0.1:8000
name: Default
authProvider: 'serviceAccount'
skipTLSVerify: true
skipMetricsLookup: true
serviceAccountToken: ABC123
caData: LS0tLS1CRUdJTiBDRVJUSUZJQ0...
If you use a ServiceAccount in config you must bind it to the ClusterRole created by Flux
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: backstage-cluster-view-rolebinding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: flux-view-flux-system
subjects:
- kind: ServiceAccount
name: backstage
namespace: flux-system
To enable sync suspend resume buttons grant patch to Flux resources
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: patch-flux-resources
rules:
- apiGroups:
- source.toolkit.fluxcd.io
resources:
- buckets
- helmcharts
- gitrepositories
- helmrepositories
- ocirepositories
verbs:
- patch
- apiGroups:
- kustomize.toolkit.fluxcd.io
resources:
- kustomizations
verbs:
- patch
- apiGroups:
- helm.toolkit.fluxcd.io
resources:
- helmreleases
verbs:
- patch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: backstage-patch-flux-resources-rolebinding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: patch-flux-resources
subjects:
- kind: ServiceAccount
name: backstage
namespace: flux-system
Step 4 Add the Kubernetes tab to your entity pages
Edit packages/app/src/components/catalog/EntityPage.tsx
import React from 'react';
import { EntityLayout } from '@backstage/plugin-catalog';
import { EntityKubernetesContent } from '@backstage/plugin-kubernetes';
const serviceEntityPage = (
<EntityLayout>
{/* other tabs */}
<EntityLayout.Route path="/kubernetes" title="Kubernetes">
<EntityKubernetesContent refreshIntervalMs={30000} />
</EntityLayout.Route>
</EntityLayout>
);
export default serviceEntityPage;
Step 5 Add Flux cards to your entity pages
Edit packages/app/src/components/catalog/EntityPage.tsx
Minimal cards that show deployments and sources
import React from 'react';
import Grid from '@material-ui/core/Grid';
import { EntityLayout } from '@backstage/plugin-catalog';
import {
EntityFluxDeploymentsCard,
EntityFluxSourcesCard,
} from '@weaveworksoss/backstage-plugin-flux';
const overviewContent = (
<Grid container spacing={3} alignItems="stretch">
<Grid item md={6} xs={12}>
<EntityFluxDeploymentsCard />
</Grid>
<Grid item md={6} xs={12}>
<EntityFluxSourcesCard />
</Grid>
</Grid>
);
const serviceEntityPage = (
<EntityLayout>
<EntityLayout.Route path="/" title="Overview">
{overviewContent}
</EntityLayout.Route>
<EntityLayout.Route path="/kubernetes" title="Kubernetes">
{/* keep the Kubernetes tab from the previous step */}
</EntityLayout.Route>
</EntityLayout>
);
export default serviceEntityPage;
Optional per resource cards
import {
EntityFluxHelmReleasesCard,
EntityFluxKustomizationsCard,
EntityFluxGitRepositoriesCard,
EntityFluxOCIRepositoriesCard,
EntityFluxHelmRepositoriesCard,
EntityFluxImagePoliciesCard,
} from '@weaveworksoss/backstage-plugin-flux';
const fluxDetailsContent = (
<Grid container spacing={3} alignItems="stretch">
<Grid item md={12}>
<EntityFluxHelmReleasesCard />
</Grid>
<Grid item md={12}>
<EntityFluxKustomizationsCard />
</Grid>
<Grid item md={12}>
<EntityFluxGitRepositoriesCard />
</Grid>
<Grid item md={12}>
<EntityFluxOCIRepositoriesCard />
</Grid>
<Grid item md={12}>
<EntityFluxHelmRepositoriesCard />
</Grid>
<Grid item md={12}>
<EntityFluxImagePoliciesCard />
</Grid>
</Grid>
);
To simplify a table for small lists set many to false
<Grid item md={4} xs={12}>
<EntityFluxHelmReleasesCard many={false} />
</Grid>
Step 6 Label your catalog entities and Flux resources
Add the Kubernetes id annotation to your Backstage entity
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: carts-service
annotations:
backstage.io/kubernetes-id: carts-service
spec:
type: service
owner: sockshop-team
Label your Flux objects with the same id example for a HelmRelease
apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
name: carts-nginx
namespace: carts
labels:
backstage.io/kubernetes-id: carts-service
spec:
chart:
spec:
chart: nginx
reconcileStrategy: ChartVersion
sourceRef:
kind: HelmRepository
name: podinfo
interval: 1m0s
Step 7 Optional link to Weave GitOps and control actions
Add linking and action control in app-config.yaml
gitops:
baseUrl: https://wego.example.com
Set read only mode to disable sync suspend resume buttons in the UI
gitops:
readOnly: true
Keep cluster names in your Kubernetes config accurate because generated links include the cluster name from the Backstage cluster configuration
Step 8 Add the Flux runtime page and nav item optional
Route in packages/app/src/App.tsx
import React from 'react';
import { FlatRoutes } from '@backstage/core-app-api';
import { Route } from 'react-router';
import { FluxRuntimePage } from '@weaveworksoss/backstage-plugin-flux';
export const routes = (
<FlatRoutes>
{/* other routes */}
<Route path="/flux-runtime" element={<FluxRuntimePage />} />
</FlatRoutes>
);
Nav item in packages/app/src/components/Root/Root.tsx
import React, { PropsWithChildren } from 'react';
import { SidebarPage, Sidebar, SidebarGroup, SidebarItem, SidebarScrollWrapper } from '@backstage/core-components';
import MenuIcon from '@material-ui/icons/Menu';
import { FluxIcon } from '@weaveworksoss/backstage-plugin-flux';
export const Root = ({ children }: PropsWithChildren<{}>) => (
<SidebarPage>
<Sidebar>
<SidebarGroup label="Menu" icon={<MenuIcon />}>
<SidebarScrollWrapper>
<SidebarItem icon={FluxIcon} to="flux-runtime" text="Flux Runtime" />
</SidebarScrollWrapper>
</SidebarGroup>
</Sidebar>
{children}
</SidebarPage>
);
Notes on auth
If you see unauthorized calls to the Kubernetes proxy you likely need user authentication in front of Backstage so requests include a Backstage token. Configure an auth provider in your app to provide tokens for the proxy calls.
Changelog
The Flux plugin has not seen any significant changes since a year ago.
Set up Backstage in minutes with Roadie
Focus on using Backstage, rather than building and maintaining it.