|
| 1 | +# Installing Knative Backstage Plugins |
| 2 | + |
| 3 | +Knative community is planning to provide a set of Backstage plugins for Knative and their respective backends. |
| 4 | +Currently there is one plugin available, the Event Mesh plugin. |
| 5 | + |
| 6 | +## Event Mesh plugin |
| 7 | + |
| 8 | +The Event Mesh plugin is a Backstage plugin that allows you to view and manage Knative Eventing resources. |
| 9 | + |
| 10 | +The Backstage plugin talks to a special backend that runs in the Kubernetes cluster and communicates with the Kubernetes |
| 11 | +API server. |
| 12 | + |
| 13 | +A demo setup for this plugin is available at <https://github.com/aliok/knative-backstage-demo>. |
| 14 | + |
| 15 | +The plugin has 2 distributions: static and dynamic. In this document, we will focus on the static distribution. |
| 16 | +For the dynamic distribution, please see the |
| 17 | +[Dynamic Plugin README file](https://github.com/knative-extensions/backstage-plugins/blob/main/backstage/plugins/knative-event-mesh-backend/README-dynamic.md) |
| 18 | +in the plugin repository. |
| 19 | + |
| 20 | +### Installation |
| 21 | + |
| 22 | +The plugin needs to be installed in the Backstage instance and the backend it talks to needs to be installed in the |
| 23 | +Kubernetes cluster. |
| 24 | + |
| 25 | +#### Plugin backend controller installation |
| 26 | + |
| 27 | +```shell |
| 28 | +VERSION="latest" # or a specific version like knative-v1.15.0 |
| 29 | +kubectl apply -f https://github.com/knative-extensions/backstage-plugins/releases/${VERSION}/download/eventmesh.yaml |
| 30 | +``` |
| 31 | + |
| 32 | +This will install the backend controller in the Kubernetes cluster. The backend's responsibility is to talk to |
| 33 | +the Kubernetes API server and provide the necessary information to the plugin. |
| 34 | + |
| 35 | +#### The Backstage plugin installation |
| 36 | + |
| 37 | +In your Backstage directory, run the following command to install the plugin: |
| 38 | + |
| 39 | +```bash |
| 40 | +VERSION="latest" # or a specific version like 1.15.0 from https://www.npmjs.com/package/@knative-extensions/plugin-knative-event-mesh-backend |
| 41 | +yarn workspace backend add @knative-extensions/plugin-knative-event-mesh-backend@${VERSION} |
| 42 | +``` |
| 43 | + |
| 44 | +Backstage has a legacy backend system that is being replaced with a new system. If you are using the legacy backend |
| 45 | +system, you can follow the instructions below to install the plugin. |
| 46 | + |
| 47 | +To learn more about the new and the legacy backend systems, see the |
| 48 | +[Backstage documentation](https://backstage.io/docs/backend-system/building-backends/migrating/). |
| 49 | + |
| 50 | +!!! info |
| 51 | + We are aware there is a `Backend` term used in both the Kubernetes controller and the Backstage backend system. |
| 52 | + Backstage backend system is different from the Kubernetes controller we've installed before. |
| 53 | + The controller is a Kubernetes controller that runs in the Kubernetes cluster and talks to the Kubernetes API server. |
| 54 | + Backstage backend system is a framework to run backend plugins that talk to data providers, such as the Kubernetes controller mentioned above. |
| 55 | + |
| 56 | +#### Enabling the plugin on the new Backstage backend system |
| 57 | + |
| 58 | +To install on the new backend system, add the following into the `packages/backend/index.ts` file: |
| 59 | + |
| 60 | +```ts |
| 61 | +import { createBackend } from '@backstage/backend-defaults'; |
| 62 | + |
| 63 | +const backend = createBackend(); |
| 64 | + |
| 65 | +// Other plugins/modules |
| 66 | + |
| 67 | +backend.add(import('@knative-extensions/plugin-knative-event-mesh-backend/alpha')); |
| 68 | +``` |
| 69 | + |
| 70 | +!!! warning |
| 71 | + If you have made any changes to the schedule in the `app-config.yaml` file, then restart to apply the changes. |
| 72 | + |
| 73 | +#### Enabling the plugin on the legacy Backstage backend system |
| 74 | + |
| 75 | +Configure the scheduler for the entity provider and enable the processor. Add the following code |
| 76 | +to `packages/backend/src/plugins/catalog.ts` file: |
| 77 | + |
| 78 | +```ts |
| 79 | +import {CatalogClient} from "@backstage/catalog-client"; |
| 80 | +import { |
| 81 | + KnativeEventMeshProcessor, |
| 82 | + KnativeEventMeshProvider |
| 83 | +} from '@knative-extensions/plugin-knative-event-mesh-backend'; |
| 84 | + |
| 85 | +export default async function createPlugin( |
| 86 | + env:PluginEnvironment, |
| 87 | +):Promise<Router> { |
| 88 | + const builder = await CatalogBuilder.create(env); |
| 89 | + |
| 90 | + /* ... other processors and/or providers ... */ |
| 91 | + |
| 92 | + // ADD THESE |
| 93 | + builder.addEntityProvider( |
| 94 | + KnativeEventMeshProvider.fromConfig(env.config, { |
| 95 | + logger: env.logger, |
| 96 | + scheduler: env.scheduler, |
| 97 | + }), |
| 98 | + ); |
| 99 | + const catalogApi = new CatalogClient({ |
| 100 | + discoveryApi: env.discovery, |
| 101 | + }); |
| 102 | + const knativeEventMeshProcessor = new KnativeEventMeshProcessor(catalogApi, env.logger); |
| 103 | + builder.addProcessor(knativeEventMeshProcessor); |
| 104 | + |
| 105 | + /* ... other processors and/or providers ... */ |
| 106 | + |
| 107 | + const {processingEngine, router} = await builder.build(); |
| 108 | + await processingEngine.start(); |
| 109 | + return router; |
| 110 | +} |
| 111 | +``` |
| 112 | + |
| 113 | +### Configuration |
| 114 | + |
| 115 | +!!! info |
| 116 | + **NOTE**: The backend needs to be accessible from the Backstage instance. If you are running the backend without |
| 117 | + exposing it, you can use `kubectl port-forward` to forward the port of the backend service to your local machine |
| 118 | + for testing purposes. |
| 119 | + ```bash |
| 120 | + kubectl port-forward -n knative-eventing svc/eventmesh-backend 8080:8080 |
| 121 | + ``` |
| 122 | + |
| 123 | +The plugin needs to be configured to talk to the backend. It can be configured in the `app-config.yaml` file of the |
| 124 | +Backstage instance and allows configuration of one or multiple providers. |
| 125 | + |
| 126 | +Use a `knativeEventMesh` marker to start configuring the `app-config.yaml` file of Backstage: |
| 127 | + |
| 128 | +```yaml |
| 129 | +catalog: |
| 130 | + providers: |
| 131 | + knativeEventMesh: |
| 132 | + dev: |
| 133 | + token: '${KNATIVE_EVENT_MESH_TOKEN}' # SA token to authenticate to the backend |
| 134 | + baseUrl: '${KNATIVE_EVENT_MESH_BACKEND}' # URL of the backend installed in the cluster |
| 135 | + schedule: # optional; same options as in TaskScheduleDefinition |
| 136 | + # supports cron, ISO duration, "human duration" as used in code |
| 137 | + frequency: { minutes: 1 } |
| 138 | + # supports ISO duration, "human duration" as used in code |
| 139 | + timeout: { minutes: 1 } |
| 140 | +``` |
| 141 | +
|
| 142 | +You can either manually change the placeholders in the `app-config.yaml` file or use environment variables to set the |
| 143 | +values. The environment variables can be set as following before starting the Backstage instance: |
| 144 | + |
| 145 | +```bash |
| 146 | +export KNATIVE_EVENT_MESH_TOKEN=<your-token> |
| 147 | +export KNATIVE_EVENT_MESH_BACKEND=<backend-url> |
| 148 | +``` |
| 149 | + |
| 150 | +The value of `KNATIVE_EVENT_MESH_BACKEND` should be the URL of the backend service. If you are running the backend |
| 151 | +service in the same cluster as the Backstage instance, you can use the service name as the URL such as |
| 152 | +`http://eventmesh-backend.knative-eventing.svc.cluster.local`. |
| 153 | +If the Backstage instance is not running in the same cluster, you can use the external URL of the backend service. |
| 154 | +Or, if you are running the backend without exposing it for testing purposes, you can use `kubectl port-forward` as |
| 155 | +mentioned above. |
| 156 | + |
| 157 | +The value of `KNATIVE_EVENT_MESH_TOKEN` should be a service account token that has the necessary permissions to list |
| 158 | +the Knative Eventing resources in the cluster. The backend will use this token to authenticate to the Kubernetes API |
| 159 | +server. This is required for security reasons as otherwise (if the backend is running with a SA token directly) the |
| 160 | +backend would have full access to the cluster will be returning all resources to anyone who can access the backend. |
| 161 | + |
| 162 | +The token will require the following permissions to work properly: |
| 163 | + |
| 164 | +- `get`, `list` and `watch` permissions for `eventing.knative.dev/brokers`, `eventing.knative.dev/eventtypes` and |
| 165 | + `eventing.knative.dev/triggers` resources |
| 166 | +- `get` permission for all resources to fetch subscribers for triggers |
| 167 | + |
| 168 | +You can create a ClusterRole with the necessary permissions and bind it to the service account token. |
| 169 | + |
| 170 | +An example configuration is as follows: |
| 171 | + |
| 172 | +```yaml |
| 173 | +apiVersion: v1 |
| 174 | +kind: ServiceAccount |
| 175 | +metadata: |
| 176 | + name: my-eventmesh-backend-service-account |
| 177 | + namespace: default |
| 178 | +--- |
| 179 | +apiVersion: rbac.authorization.k8s.io/v1 |
| 180 | +kind: ClusterRole |
| 181 | +metadata: |
| 182 | + name: my-eventmesh-backend-cluster-role |
| 183 | +rules: |
| 184 | + # permissions for eventtypes, brokers and triggers |
| 185 | + - apiGroups: |
| 186 | + - "eventing.knative.dev" |
| 187 | + resources: |
| 188 | + - brokers |
| 189 | + - eventtypes |
| 190 | + - triggers |
| 191 | + verbs: |
| 192 | + - get |
| 193 | + - list |
| 194 | + - watch |
| 195 | + # permissions to get subscribers for triggers |
| 196 | + # as subscribers can be any resource, we need to give access to all resources |
| 197 | + # we fetch subscribers one by one, we only need `get` verb |
| 198 | + - apiGroups: |
| 199 | + - "*" |
| 200 | + resources: |
| 201 | + - "*" |
| 202 | + verbs: |
| 203 | + - get |
| 204 | +--- |
| 205 | +apiVersion: rbac.authorization.k8s.io/v1 |
| 206 | +kind: ClusterRoleBinding |
| 207 | +metadata: |
| 208 | + name: my-eventmesh-backend-cluster-role-binding |
| 209 | +subjects: |
| 210 | + - kind: ServiceAccount |
| 211 | + name: my-eventmesh-backend-service-account |
| 212 | + namespace: default |
| 213 | +roleRef: |
| 214 | + kind: ClusterRole |
| 215 | + name: my-eventmesh-backend-cluster-role |
| 216 | + apiGroup: rbac.authorization.k8s.io |
| 217 | +--- |
| 218 | +apiVersion: v1 |
| 219 | +kind: Secret |
| 220 | +metadata: |
| 221 | + name: my-eventmesh-backend-secret |
| 222 | + namespace: default |
| 223 | + annotations: |
| 224 | + kubernetes.io/service-account.name: my-eventmesh-backend-service-account |
| 225 | +type: kubernetes.io/service-account-token |
| 226 | +``` |
| 227 | +
|
| 228 | +To get the token, you can run the following command: |
| 229 | +
|
| 230 | +```bash |
| 231 | +kubectl get secret my-eventmesh-backend-secret -o jsonpath='{.data.token}' | base64 --decode |
| 232 | +``` |
| 233 | + |
| 234 | +Run a quick check to see if the token works with the Kubernetes API server: |
| 235 | + |
| 236 | +```bash |
| 237 | +export KUBE_API_SERVER_URL=$(kubectl config view --minify --output jsonpath="{.clusters[*].cluster.server}") # e.g. "https://192.168.2.151:16443" |
| 238 | +export KUBE_SA_TOKEN=$(kubectl get secret my-eventmesh-backend-secret -o jsonpath='{.data.token}' | base64 --decode) |
| 239 | +curl -k -H "Authorization: Bearer $KUBE_SA_TOKEN" -X GET "${KUBE_API_SERVER_URL}/apis/eventing.knative.dev/v1/namespaces/default/brokers" |
| 240 | +# Should see the brokers, or nothing if there are no brokers |
| 241 | +# But, should not see an error |
| 242 | +``` |
| 243 | + |
| 244 | +Run a second quick check to see if the token works with the Backstage backend: |
| 245 | + |
| 246 | +```bash |
| 247 | +export KNATIVE_EVENT_MESH_BACKEND=http://localhost:8080 # or the URL of the backend |
| 248 | +export KUBE_SA_TOKEN=$(kubectl get secret my-eventmesh-backend-secret -o jsonpath='{.data.token}' | base64 --decode) |
| 249 | +curl -k -H "Authorization: Bearer $KUBE_SA_TOKEN" -X GET "${KNATIVE_EVENT_MESH_BACKEND}" |
| 250 | +# Should see the response from the backend such as |
| 251 | +# { |
| 252 | +# "brokers" : [...], |
| 253 | +# "eventTypes" : [...] |
| 254 | +#} |
| 255 | +``` |
| 256 | + |
| 257 | +If these quick checks work, you can use the token in the `app-config.yaml` file as the value |
| 258 | +of `KNATIVE_EVENT_MESH_TOKEN`. |
| 259 | + |
| 260 | +### Troubleshooting |
| 261 | + |
| 262 | +When you start your Backstage application, you can see some log lines as follows: |
| 263 | + |
| 264 | +```text |
| 265 | +[1] 2024-01-04T09:38:08.707Z knative-event-mesh-backend info Found 1 knative event mesh provider configs with ids: dev type=plugin |
| 266 | +``` |
| 267 | + |
| 268 | +### Usage |
| 269 | + |
| 270 | +See the [plugin documentation](../../eventing/event-registry/eventmesh-backstage-plugin/) for more information about using the plugin. |
0 commit comments