Kubernetes
Connect vScope to your Kubernetes cluster by creating a read-only inventory account and adding its token to vScope. Follow these steps with kubectl on any standard Kubernetes cluster, including K3s.
Prerequisites
Section titled “Prerequisites”kubectlconfigured to connect to the cluster.- An administrator account allowed to create namespaces, ServiceAccounts, Secrets, ClusterRoles, and ClusterRoleBindings, and grant the permissions below. The permission checks also require permission to impersonate the ServiceAccount.
- Network access from the vScope server or Discovery Proxy to the Kubernetes API endpoint over HTTPS. Use the endpoint’s configured TCP port, commonly 6443 or 443.
- Bash with
base64, or PowerShell, to retrieve the token.
Confirm that you are working with the intended cluster:
kubectl config current-contextkubectl cluster-infoRun the setup and token retrieval commands using your administrator credentials. The inventory account itself will not be able to read Secrets, including its own token Secret.
1. Create the inventory account and permissions
Section titled “1. Create the inventory account and permissions”Save the following as vscope-inventory.yaml. Use the same names throughout this guide, or change all matching references if these names are already in use.
apiVersion: v1kind: Namespacemetadata: name: vscope-inventory---apiVersion: v1kind: ServiceAccountmetadata: name: vscope-inventory namespace: vscope-inventoryautomountServiceAccountToken: false---apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRolemetadata: name: vscope-inventoryrules: # Core infrastructure - apiGroups: [""] resources: - nodes - namespaces - pods - services - endpoints - persistentvolumeclaims - persistentvolumes - events verbs: ["get", "list", "watch"] # Workloads - apiGroups: ["apps"] resources: ["deployments", "replicasets", "statefulsets", "daemonsets"] verbs: ["get", "list", "watch"] - apiGroups: ["batch"] resources: ["jobs", "cronjobs"] verbs: ["get", "list", "watch"] # Networking - apiGroups: ["networking.k8s.io"] resources: ["ingresses", "ingressclasses", "networkpolicies"] verbs: ["get", "list", "watch"] - apiGroups: ["discovery.k8s.io"] resources: ["endpointslices"] verbs: ["get", "list", "watch"] # Storage and CSI - apiGroups: ["storage.k8s.io"] resources: ["storageclasses", "csidrivers", "csinodes", "volumeattachments"] verbs: ["get", "list", "watch"] - apiGroups: ["snapshot.storage.k8s.io"] resources: ["volumesnapshots", "volumesnapshotcontents", "volumesnapshotclasses"] verbs: ["get", "list", "watch"] # Custom resource definitions (not all custom resource instances) - apiGroups: ["apiextensions.k8s.io"] resources: ["customresourcedefinitions"] verbs: ["get", "list", "watch"]---apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRoleBindingmetadata: name: vscope-inventorysubjects: - kind: ServiceAccount name: vscope-inventory namespace: vscope-inventoryroleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: vscope-inventoryApply the file:
kubectl apply -f vscope-inventory.yamlThis grants read access to the listed resources across all namespaces. It does not grant access to Secrets, ConfigMaps, Pod logs, exec, attach, or port forwarding, or permission to create, change, or delete resources.
Optional: KubeVirt, CDI, and Longhorn
Section titled “Optional: KubeVirt, CDI, and Longhorn”If these extensions are installed and you want to allow access to their metadata, append the relevant rules to the ClusterRole’s rules list, before the --- that starts the ClusterRoleBinding, then apply the file again:
# KubeVirt - apiGroups: ["kubevirt.io"] resources: ["*"] verbs: ["get", "list", "watch"] # CDI / DataVolumes - apiGroups: ["cdi.kubevirt.io"] resources: ["*"] verbs: ["get", "list", "watch"] # Longhorn - apiGroups: ["longhorn.io"] resources: ["*"] verbs: ["get", "list", "watch"]Include only the extension groups you need and keep the core resource list unchanged. These rules grant read access to all resources in the named extension groups. The CSI snapshot rule in the base manifest applies when the snapshot APIs are installed.
2. Create a persistent token
Section titled “2. Create a persistent token”For unattended inventory using a stored bearer token, create a separate file named vscope-inventory-token.yaml:
apiVersion: v1kind: Secretmetadata: name: vscope-inventory-token namespace: vscope-inventory annotations: kubernetes.io/service-account.name: vscope-inventorytype: kubernetes.io/service-account-tokenkubectl apply -f vscope-inventory-token.yamlDo not add a data section. Kubernetes generates the token. Wait for it to be available:
kubectl -n vscope-inventory wait --for=jsonpath='{.data.token}' secret/vscope-inventory-token --timeout=60s3. Verify permissions
Section titled “3. Verify permissions”Run these checks with your administrator credentials. Each should return yes:
kubectl auth can-i --as=system:serviceaccount:vscope-inventory:vscope-inventory list nodeskubectl auth can-i --as=system:serviceaccount:vscope-inventory:vscope-inventory list pods --all-namespaceskubectl auth can-i --as=system:serviceaccount:vscope-inventory:vscope-inventory list deployments.apps --all-namespaceskubectl auth can-i --as=system:serviceaccount:vscope-inventory:vscope-inventory list storageclasses.storage.k8s.ioEach of these should return no:
kubectl auth can-i --as=system:serviceaccount:vscope-inventory:vscope-inventory list secrets --all-namespaceskubectl auth can-i --as=system:serviceaccount:vscope-inventory:vscope-inventory get secrets -n vscope-inventorykubectl auth can-i --as=system:serviceaccount:vscope-inventory:vscope-inventory list configmaps --all-namespaceskubectl auth can-i --as=system:serviceaccount:vscope-inventory:vscope-inventory create pods -n defaultkubectl auth can-i --as=system:serviceaccount:vscope-inventory:vscope-inventory patch deployments.apps -n defaultkubectl auth can-i --as=system:serviceaccount:vscope-inventory:vscope-inventory delete pods -n defaultkubectl auth can-i --as=system:serviceaccount:vscope-inventory:vscope-inventory get pods --subresource=log -n defaultkubectl auth can-i --as=system:serviceaccount:vscope-inventory:vscope-inventory create pods --subresource=exec -n defaultkubectl auth can-i --as=system:serviceaccount:vscope-inventory:vscope-inventory create pods --subresource=attach -n defaultkubectl auth can-i --as=system:serviceaccount:vscope-inventory:vscope-inventory create pods --subresource=portforward -n defaultRepeat namespace-specific checks in namespaces with additional bindings. If an unexpected check returns yes, inspect other RoleBindings and ClusterRoleBindings that grant access to the account or its groups before continuing.
For installed extensions whose optional rules you added, these should return yes:
kubectl auth can-i --as=system:serviceaccount:vscope-inventory:vscope-inventory list virtualmachines.kubevirt.io --all-namespaceskubectl auth can-i --as=system:serviceaccount:vscope-inventory:vscope-inventory list datavolumes.cdi.kubevirt.io --all-namespaceskubectl auth can-i --as=system:serviceaccount:vscope-inventory:vscope-inventory list volumes.longhorn.io --all-namespaces4. Retrieve the endpoint and token
Section titled “4. Retrieve the endpoint and token”Find the API endpoint in your current context:
kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}'Use an HTTPS endpoint reachable from vScope or its Discovery Proxy, such as https://api.example.com:6443. An address like 127.0.0.1 or a local tunnel in your kubeconfig will not work from another machine. For highly available clusters, use the stable API load balancer or virtual IP.
Run the commands for your shell and copy the resulting token for use in vScope.
Bash (Linux or macOS)
Section titled “Bash (Linux or macOS)”kubectl -n vscope-inventory get secret vscope-inventory-token -o jsonpath='{.data.token}' | base64 --decodeprintf '\n'On macOS, use base64 -D instead of base64 --decode if your version does not support the long option.
PowerShell (Windows)
Section titled “PowerShell (Windows)”$tokenBase64 = kubectl -n vscope-inventory get secret vscope-inventory-token -o jsonpath='{.data.token}'[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($tokenBase64))5. Connect vScope and run discovery
Section titled “5. Connect vScope and run discovery”- In vScope, open Discovery > Credentials and add a Kubernetes credential.
- In Base URL, enter the API endpoint from step 4, for example
https://api.example.com:6443. - Leave Authorization Header Name set to
Authorization. - In Authorization Header Value, enter
Bearer <token>, replacing<token>with the token from step 4. Include a space betweenBearerand the token. - If the connection should use a Discovery Proxy, select it in Proxy.
- Under Advanced Settings, enable Accept all server certificates.
- Click Test Credential and save the credential when the test succeeds.
- Run discovery and review the results in Discovery > Summary. If discovery fails, open Log History for details.
For the general discovery workflow, see Adding data sources.
Troubleshooting
Section titled “Troubleshooting”| Symptom | Check |
|---|---|
| Token wait times out | Confirm the ServiceAccount exists and the Secret annotation matches its name. Ask the cluster administrator to check the ServiceAccount token controller and cluster policy. |
401 Unauthorized | Check that Authorization Header Name is Authorization, Authorization Header Value contains Bearer followed by the complete token, and the token Secret and ServiceAccount still exist. Replace expired short-lived tokens if used. |
403 Forbidden for an allowed resource | Check the ClusterRoleBinding’s subject and role name, the resource’s API group, and any optional extension rules. |
| Impersonation is forbidden | Run the auth can-i --as checks with an administrator allowed to impersonate ServiceAccounts. |
| Connection timeout or refusal | Check the endpoint, port, DNS, firewall, and routing from vScope or its Discovery Proxy. |
| Extension API is missing | Check installed APIs with kubectl api-resources. RBAC rules do not install KubeVirt, CDI, Longhorn, or CSI snapshot APIs. |