Skip to main content

Kubernetes Managed

Visualize Kubernetes resources and monitor changes through queries and alerts.

Installation​

Prerequisites​

Moving from Kubernetes Native?

See the Migration tab for the full cutover sequence, data model differences, and answers to common migration questions.

Before installing the Kubernetes Managed integration, you must have a Kubernetes collector running. For instructions on setting up the Kubernetes collector, see the Kubernetes collector documentation.

Configuration in JupiterOne​

  1. Navigate to the Integrations tab in JupiterOne and select Kubernetes Managed.

  2. Click New Instance to begin configuring your integration and provide the following:

    • The Account Name used to identify the Kubernetes account in JupiterOne. Ingested entities will have this value stored in tag.AccountName when the AccountName toggle is enabled.

    • Description to assist in identifying the integration instance, if desired.

    • When prompted about where should this run, select the Kubernetes collector you created in the prerequisites.

    • Use Default Kubernetes Configuration (optional): Enable when running the integration outside of a Kubernetes cluster, such as on a local machine. When disabled, the integration uses the cluster's built-in in-cluster authentication. Disabled by default.

    • Ingest All Node Images (optional): Enable to ingest every image cached on each node, instead of only the images in use by a running container. Required to ingest images at all if you are not ingesting pods. Disabled by default. See Image ingestion.

  3. Click Create after all values are provided and your instance appears in the list of all your Kubernetes Managed instances.

Data Volume Configuration​

By default, the integration ingests all namespaces in your cluster. Use the options below to limit which namespaces are included.

Data Filtering Options​

FieldDescriptionDefault
Include Specific NamespacesRestrict ingestion to the listed namespaces only. In JupiterOne, separate names with commas; with Helm, see includeNamespaces above. If left empty, all namespaces are ingested (unless exclusions are specified).All namespaces
Exclude Specific NamespacesSkip the listed namespaces during ingestion. Useful for omitting system namespaces such as kube-system. In JupiterOne, separate names with commas; with Helm, see excludeNamespaces above.None

Image ingestion​

By default, kube_image entities are created only for images in use by a running container, and each container is linked to its image with a kube_container USES kube_image relationship. Images are derived from pods, so a cluster that does not ingest pods produces no images.

Enable Ingest All Node Images (ingestAllNodeImages) to also ingest the images cached on each node, whether or not a container is running them, and to relate each node to the images it holds with kube_node HAS kube_image. This is the option to use if you are not ingesting pods and still want image inventory.

FieldDescriptionDefault
Ingest All Node ImagesIngest every image in each node's local image cache in addition to the images in use by a running container.Disabled
kubelet limits how many images a node reports

A node reports its cached images through Node.status.images, which kubelet truncates at --node-status-max-images (default 50, -1 disables the limit) and which only covers images present in that node's local cache. Enabling this option therefore gives a best-effort inventory per node rather than a guaranteed complete one. Set --node-status-max-images=-1 on your kubelets if you need the full list.

RBAC​

The Kubernetes collector installs with a ClusterRole that provides read-only access to Kubernetes resources. The collector has permissions to get, list, and watch the following:

Core Resources:

  • Pods, namespaces, service accounts, config maps, nodes, services, secrets, and events

Application Workloads:

  • Deployments, replica sets, stateful sets, daemon sets, jobs, and cron jobs

Networking:

  • Ingresses and network policies

RBAC and Security:

  • Cluster roles, cluster role bindings, roles, and role bindings
  • Self-subject access reviews and subject access reviews
  • Token reviews

Extensions:

  • All resources in the extensions API group

Integration Management:

  • Integration instance jobs, integration runners, and their status and finalizers (for managing integration workloads)
  • Listing custom resource definitions and certificate signing requests

The collector can't read other custom resources, including IntegrationInstances. To ingest them, grant access as described in Permissions for custom resources.

All permissions are read-only (get, list, watch) and do not allow modification of any cluster resources.

Advanced: Configuring Custom Resource Definitions (CRDs)​

By default, the Kubernetes Managed integration ingests standard Kubernetes resources. However, you can extend the integration to also collect and map Custom Resource Definitions (CRDs) that exist in your cluster. This is particularly useful for capturing custom resources created by operators, such as IntegrationRunners and IntegrationInstanceJobs from the JupiterOne Kubernetes Operator.

Overview​

The CRD configuration allows you to:

  • Define which custom resources to ingest: Specify the CRD resources you want to collect from your cluster
  • Map resource properties: Transform CRD fields into JupiterOne entity properties
  • Create relationships: Define how custom resources relate to other entities in your JupiterOne graph

Configuration File Structure​

The CRD configuration is defined in a YAML file with two main sections: resources and relationships. Both are optional: a file with only resources ingests entities without relationships. This configuration file can be provided when setting up your integration instance.

Managing the Configuration​

Upload the file in the CRD Mapping Configuration field when you create the integration instance, or later from the instance's settings in JupiterOne.

  • Validation: JupiterOne checks the file when you upload it and shows the first problem with its line number, for example line 4, resources[0]._type: "argocd_app" must start with "kube_cr_". The instance can't be saved until the file is valid. Each job checks the file again. If it's invalid, the job fails before collecting anything, and the job log lists the problems with their line numbers (up to 10).
  • Removing the mapping: remove the file from the field and save. The next job skips the custom resource steps, and the custom resource entities and relationships from earlier jobs are removed from your graph.
  • Pausing the mapping: to stop ingesting custom resources without deleting the file, disable the Custom Resources data source on the instance. As with removing the file, the custom resource entities and relationships are removed from your graph until you enable it again. If you set ingestionSources with Helm, set custom-resources: false there instead, because the Helm value replaces changes made in JupiterOne.
  • Size: a mapping can be up to about 900 KB (roughly 30,000 lines). Mappings over 128 KiB (about 4,000 lines) require Integration Operator v0.7.0 or later (operator chart 1.7.0 or later) and graph-kubernetes-managed 3.2.85 or later; if you mirror JupiterOne integration images to a private registry, update your copy first. Such a job can leave one failed pod with argument list too long before the operator runs it again with the mapping passed as a file; this is expected. If you apply the IntegrationInstance resource with kubectl apply, add --server-side.
  • Instances created with Helm or the Integration Operator: the operator applies the instance configuration, including the mapping, only when it creates the instance. After that, change or remove the mapping in JupiterOne; changing the Helm value doesn't update an existing instance. A mapping set any way other than the JupiterOne UI is first checked when a job starts.

Permissions for custom resources​

The collector can read only the JupiterOne operator's IntegrationRunners and IntegrationInstanceJobs. For any other custom resource in your mapping, grant get and list on it to the integration's service account (jupiterone in the jupiterone namespace by default). Without this, the job still succeeds but ingests none of those resources. For example, for the Argo CD example below:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: jupiterone-argocd-read
rules:
- apiGroups: [argoproj.io]
resources: [applications, appprojects]
verbs: [get, list]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: jupiterone-argocd-read
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: jupiterone-argocd-read
subjects:
- kind: ServiceAccount
name: jupiterone
namespace: jupiterone

Resources Section​

The resources section defines which custom resources to ingest and how to map their properties to JupiterOne entities.

Each resource entry contains:

  • name (required): The fully qualified name of the CRD resource type, following the format <plural>.<group>. For example, integrationrunners.integrations.jupiterone.io refers to the IntegrationRunner CRD in the integrations.jupiterone.io API group.

  • version (optional): The API version of the resource. For example, v1 indicates the resource uses version 1 of the API. If not provided, all versions will be ingested.

  • _type (required): The entity type that will be assigned to ingested resources in JupiterOne. This is a custom identifier that you'll use to query and reference these entities. It must start with kube_cr_ (e.g., kube_cr_integration_runner).

  • _class (required): The entity class that categorizes the resource in JupiterOne's data model. All supported entity classes can be found in the JupiterOne Data Model documentation.

  • propertyToFieldMap (required): A mapping that defines how fields from the Kubernetes resource are transformed into JupiterOne entity properties. This is where you specify which Kubernetes resource fields map to which JupiterOne properties.

    • _key (required): Maps to the unique identifier for the entity in JupiterOne. It's recommended to use metadata.uid to ensure uniqueness.
    • Standard properties: Common mappings include:
      • name: Usually maps to metadata.name
      • namespace: Usually maps to metadata.namespace
      • createdOn: Usually maps to metadata.creationTimestamp
    • Custom properties: You can map any field from the resource's spec or status sections to custom properties. For example, accountId: spec.accountId maps the accountId field from the resource's spec to a property called accountId on the JupiterOne entity.

Relationships Section​

The relationships section defines how custom resources relate to other entities in your JupiterOne graph. This allows you to create meaningful connections between resources, such as showing which secrets an IntegrationRunner uses or which runner an IntegrationInstanceJob runs on.

Each relationship entry contains:

  • _class (required): The type of relationship. All supported relationship classes can be found in the JupiterOne Data Model documentation.

  • sourceType (required): The entity type of the source entity in the relationship. This should match the _type you defined in the resources section (e.g., kube_cr_integration_runner).

  • targetType (required): The entity type of the target entity in the relationship. This can be:

    • Another custom resource type you've defined (e.g., kube_cr_integration_instance_job)
    • A standard Kubernetes resource type (e.g., kube_secret, kube_pod, kube_namespace)
  • matchBy (required): Defines how to match the source and target entities to create the relationship. This is a key-value mapping where:

    • The key is a property name on the source entity (e.g., secretName)
    • The value is a property name on the target entity (e.g., name)

    The relationship is created when the source entity's property value matches the target entity's property value. You can specify multiple match conditions, and all must be satisfied (AND logic). For example:

    matchBy:
    secretName: name
    namespace: namespace

    This creates a relationship when both the secretName on the source matches the name on the target, AND the namespace on the source matches the namespace on the target.

    note

    If a property is not defined for either the source or the target, the relationship won't be created. Undefined doesn't match with undefined.

Validation Rules​

A file is rejected when it breaks any of these rules:

  • resources and relationships must be lists (or left blank).
  • Each resource needs name, _type, _class, and propertyToFieldMap with a _key.
  • _type must start with kube_cr_; sourceType and targetType must start with kube_.
  • _class must be a JupiterOne entity class for a resource, or a relationship class for a relationship.
  • Every value in propertyToFieldMap and matchBy must be text (a field path or a property name) or left blank, not a number or a list. _key can't be blank. A blank propertyToFieldMap value maps nothing, and a blank matchBy value means that relationship is never created.
  • propertyToFieldMap keys can't start with _ (other than _key) or be constructor or prototype. Keys are limited to 256 characters and paths to 512.
  • matchBy needs at least one entry.

Unrecognized keys are ignored rather than rejected, so check the spelling of keys such as relationships and version.

Mapped values are stored as text. A field that holds a list, such as spec.dnsNames, is stored as its items joined with commas. A field that holds an object, or a list of objects such as status.conditions, is stored as [object Object], once for each list item; map a single value inside it instead, using an index for list items (for example spec.sources.0.repoURL).

Example Configuration​

Here's a complete example configuration that ingests IntegrationRunners and IntegrationInstanceJobs and creates relationships between them and their associated secrets:

resources:
- name: integrationrunners.integrations.jupiterone.io
version: v1
_type: kube_cr_integration_runner
_class: Process
propertyToFieldMap:
_key: metadata.uid
name: metadata.name
namespace: metadata.namespace
createdOn: metadata.creationTimestamp
accountId: spec.accountId
collectorId: spec.collectorId
collectorPoolId: spec.collectorPoolId
jupiterOneEnvironment: spec.jupiterOneEnvironment
secretAPITokenName: spec.secretAPITokenName
secretName: spec.secretName
syncIntervalSeconds: spec.syncIntervalSeconds

- name: integrationinstancejobs.integrations.jupiterone.io
_type: kube_cr_integration_instance_job
_class: Task
propertyToFieldMap:
_key: metadata.uid
name: metadata.name
namespace: metadata.namespace
createdOn: metadata.creationTimestamp
accountId: spec.accountId
certificateIdentity: spec.certificateIdentity
image: spec.image
integrationDefinitionName: spec.integrationDefinitionName
integrationInstanceId: spec.integrationInstanceId
integrationInstanceJobId: spec.integrationInstanceJobId
integrationRunnerName: spec.integrationRunnerName
secretName: spec.secretName

relationships:
- _class: HAS
sourceType: kube_cr_integration_runner
targetType: kube_secret
matchBy:
secretName: name
namespace: namespace

- _class: HAS
sourceType: kube_cr_integration_instance_job
targetType: kube_secret
matchBy:
secretName: name
namespace: namespace

- _class: HAS
sourceType: kube_cr_integration_instance_job
targetType: kube_cr_integration_runner
matchBy:
integrationRunnerName: name
namespace: namespace

Understanding the Example​

Resources Explained:

  1. IntegrationRunner Resource:

    • Ingested as kube_cr_integration_runner entities with class Process
    • Maps standard Kubernetes metadata (uid, name, namespace, creationTimestamp)
    • Maps custom spec fields like accountId, collectorId, and syncIntervalSeconds to entity properties
    • The secretName property is used later to create relationships with secrets
  2. IntegrationInstanceJob Resource:

    • Ingested as kube_cr_integration_instance_job entities with class Task
    • Similar metadata mapping
    • Maps job-specific fields like integrationInstanceId, image, and integrationRunnerName
    • The integrationRunnerName property links jobs to their runners

Relationships Explained:

  1. IntegrationRunner → Secret:

    • Creates a HAS relationship from each IntegrationRunner to the secret it uses
    • Matches when the runner's secretName equals the secret's name AND they're in the same namespace
  2. IntegrationInstanceJob → Secret:

    • Creates a HAS relationship from each IntegrationInstanceJob to its associated secret
    • Uses the same matching logic as above
  3. IntegrationInstanceJob → IntegrationRunner:

    • Creates a HAS relationship showing which runner executes each job
    • Matches when the job's integrationRunnerName equals the runner's name AND they're in the same namespace

More Examples​

Argo CD applications and projects

Ingests Argo CD Application and AppProject resources, and relates each project to the applications that belong to it:

resources:
- name: applications.argoproj.io
_type: kube_cr_argocd_application
_class: Application
propertyToFieldMap:
_key: metadata.uid
name: metadata.name
namespace: metadata.namespace
createdOn: metadata.creationTimestamp
project: spec.project
repoURL: spec.source.repoURL
path: spec.source.path
targetRevision: spec.source.targetRevision
destinationServer: spec.destination.server
destinationNamespace: spec.destination.namespace
syncStatus: status.sync.status
healthStatus: status.health.status

- name: appprojects.argoproj.io
_type: kube_cr_argocd_project
_class: Project
propertyToFieldMap:
_key: metadata.uid
name: metadata.name
namespace: metadata.namespace
createdOn: metadata.creationTimestamp
description: spec.description

relationships:
- _class: HAS
sourceType: kube_cr_argocd_project
targetType: kube_cr_argocd_application
matchBy:
name: project
namespace: namespace

This needs the argoproj.io permissions shown in Permissions for custom resources. If your Applications live outside the Argo CD namespace, remove namespace: namespace from matchBy. Applications with multiple sources use spec.sources instead of spec.source, so map spec.sources.0.repoURL and similar for those.

cert-manager certificates

Ingests cert-manager Certificate resources and relates each certificate to the secret that holds it:

resources:
- name: certificates.cert-manager.io
version: v1
_type: kube_cr_certmanager_certificate
_class: Certificate
propertyToFieldMap:
_key: metadata.uid
name: metadata.name
namespace: metadata.namespace
createdOn: metadata.creationTimestamp
commonName: spec.commonName
dnsNames: spec.dnsNames
secretName: spec.secretName
issuerName: spec.issuerRef.name
issuerKind: spec.issuerRef.kind
notAfter: status.notAfter
renewalTime: status.renewalTime

relationships:
- _class: HAS
sourceType: kube_cr_certmanager_certificate
targetType: kube_secret
matchBy:
secretName: name
namespace: namespace

This needs get and list on certificates in the cert-manager.io group (see Permissions for custom resources), and the relationship needs the Secrets data source enabled.

To find the name of any other custom resource, run kubectl get crds. To see which fields a resource has, run kubectl get <name> -A -o yaml.

Next steps​

Now that your integration instance has been configured, it will begin running on the polling interval you provided, populating data within JupiterOne. Continue on to our Instance management guide to learn more about working with and editing integration instances.