Added chart versions:

confluent/confluent-for-kubernetes:
    - 0.1033.3
  jenkins/jenkins:
    - 5.5.0
  kubecost/cost-analyzer:
    - 2.3.4
  new-relic/nri-bundle:
    - 5.0.88
  speedscale/speedscale-operator:
    - 2.2.231
  traefik/traefik:
    - 30.0.2
pull/1059/head
github-actions[bot] 2024-07-31 00:42:36 +00:00
parent fda730d53a
commit dbdc6e8273
886 changed files with 177156 additions and 3 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,23 @@
annotations:
catalog.cattle.io/certified: partner
catalog.cattle.io/display-name: Confluent for Kubernetes
catalog.cattle.io/kube-version: '>=1.15-0'
catalog.cattle.io/release-name: confluent-for-kubernetes
apiVersion: v1
appVersion: 2.9.0
description: A Helm chart to deploy Confluent for Kubernetes
home: https://www.confluent.io/
icon: file://assets/icons/confluent-for-kubernetes.png
keywords:
- Confluent
- Confluent Operator
- Confluent Platform
- CFK
kubeVersion: '>=1.15-0'
maintainers:
- email: operator@confluent.io
name: Confluent Operator
name: confluent-for-kubernetes
sources:
- https://docs.confluent.io/current/index.html
version: 0.1033.3

View File

@ -0,0 +1,72 @@
Confluent for Kubernetes
==================================================================
Confluent for Kubernetes (CFK) is a cloud-native control plane for deploying and managing Confluent in your private cloud environment. It provides standard and simple interface to customize, deploy, and manage Confluent Platform through declarative API.
Confluent for Kubernetes runs on Kubernetes, the runtime for private cloud architectures.
NOTE: Confluent for Kubernetes is the next generation of Confluent Operator. For Confluent Operator 1.x documentation, see [Confluent Operator 1](https://docs.confluent.io/operator/1.7.0/overview.html), or use the version picker to browse to a specific version of the documentation.
See [Introducing Confluent for Kubernetes](https://www.confluent.io/blog/confluent-for-kubernetes-offers-cloud-native-kafka-automation/) for an overview.
The following shows the high-level architecture of Confluent for Kubernetes and Confluent Platform in Kubernetes.
[![_images/co-architecture.png](https://docs.confluent.io/operator/current/_images/co-architecture.png)](_images/co-architecture.png)
Features
---------------------------------------------------
The following are summaries of the main, notable features of Confluent for Kubernetes.
#### Cloud Native Declarative API
* Declarative Kubernetes-native API approach to configure, deploy, and manage Confluent Platform components (Apache KafkaB., Connect workers, ksqlDB, Schema Registry, Confluent Control Center) and resources (topics, rolebindings) through Infrastructure as Code (IaC).
* Provides built-in automation for cloud-native security best practices:
* Complete granular RBAC, authentication and TLS network encryption
* Auto-generated certificates
* Support for credential management systems, such as Hashicorp Vault, to inject sensitive configurations in memory to Confluent deployments
* Provides server properties, JVM, and Log4j configuration overrides for customization of all Confluent Platform components.
#### Upgrades
* Provides automated rolling updates for configuration changes.
* Provides automated rolling upgrades with no impact to Kafka availability.
#### Scaling
* Provides single command, automated scaling and reliability checks of Confluent Platform.
#### Resiliency
* Restores a Kafka pod with the same Kafka broker ID, configuration, and persistent storage volumes if a failure occurs.
* Provides automated rack awareness to spread replicas of a partition across different racks (or zones), improving availability of Kafka brokers and limiting the risk of data loss.
#### Scheduling
* Supports Kubernetes labels and annotations to provide useful context to DevOps teams and ecosystem tooling.
* Supports Kubernetes tolerations and pod/node affinity for efficient resource utilization and pod placement.
#### Monitoring
* Supports metrics aggregation using JMX/Jolokia.
* Supports aggregated metrics export to Prometheus.
Licensing
-----------------------------------------------------
You can use Confluent for Kubernetes and Confluent Control Center for a 30-day trial period without a license key.
After 30 days, Confluent for Kubernetes and Control Center require a license key. Confluent issues keys to subscribers, along with providing [enterprise-level support](https://www.confluent.io/subscription/) for Confluent components and Confluent for Kubernetes.
If you are a subscriber, contact Confluent Support at [support@confluent.io](mailto:support@confluent.io) for more information.
See [Update Confluent Platform License](co-license.html#co-license-key) if you have received a key for Confluent for Kubernetes.
© Copyright 2021 , Confluent, Inc. [Privacy Policy](https://www.confluent.io/confluent-privacy-statement/) | [Terms & Conditions](https://www.confluent.io/terms-of-use/). Apache, Apache Kafka, Kafka and the Kafka logo are trademarks of the [Apache Software Foundation](http://www.apache.org/). All other trademarks, servicemarks, and copyrights are the property of their respective owners.
[Please report any inaccuracies on this page or suggest an edit.](mailto:docs@confluent.io)

View File

@ -0,0 +1,3 @@
##Confluent For Kubernetes
With Confluent for Kubernetes, Confluent brings a cloud-native experience for data in motion workloads in on-premises environments. Based on our expertise and learnings from operating over 5,000 clusters in Confluent Cloud, Confluent for Kubernetes offers an opinionated deployment of Confluent Platform that enhances the platformb's elasticity, ease of operations, and resiliency.

View File

@ -0,0 +1,883 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.15.0
name: clusterlinks.platform.confluent.io
spec:
group: platform.confluent.io
names:
categories:
- all
- confluent-platform
- confluent
kind: ClusterLink
listKind: ClusterLinkList
plural: clusterlinks
shortNames:
- cl
- clusterlink
- clink
singular: clusterlink
scope: Namespaced
versions:
- additionalPrinterColumns:
- jsonPath: .status.clusterLinkID
name: ID
type: string
- jsonPath: .status.state
name: Status
type: string
- jsonPath: .status.destinationKafkaClusterID
name: DestClusterID
type: string
- jsonPath: .status.sourceKafkaClusterID
name: SrcClusterID
type: string
- jsonPath: .status.numMirrorTopics
name: MirrorTopicCount
type: string
- jsonPath: .metadata.creationTimestamp
name: Age
type: date
name: v1beta1
schema:
openAPIV3Schema:
description: ClusterLink is the schema for the ClusterLink API.
properties:
apiVersion:
description: |-
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
type: string
kind:
description: |-
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
metadata:
type: object
spec:
description: spec defines the desired state of the cluster link.
properties:
aclFilters:
description: |-
aclFilters specify the list of ACLs to be migrated from the source cluster to the
destination cluster.
items:
description: |-
AclFilter defines the configuration for the ACLs filter. This follows the same pattern as defined in the
cluster linking documentation. More info:
https://docs.confluent.io/platform/current/multi-dc-deployments/cluster-linking/security.html#cluster-link-acls-migrate
properties:
accessFilter:
description: AclSyncAccessFilter defines the access filter for
ACLs.
properties:
host:
description: |-
host is the host for which operations can be coming from.
The default value is `*` that matches all hosts.
type: string
operation:
description: |-
operation specifies the operation type of the filter. It can be `ANY` or operations
based on resource type defined in the following Confluent documentation:
https://docs.confluent.io/platform/current/kafka/authorization.html#acl-operations
type: string
permissionType:
description: permissionType is the permission type of the
filter. Valid options are `any`, `allow`, and `deny`.
enum:
- any
- allow
- deny
type: string
principal:
description: |-
principal is the name of the principal.
The default value is `*`.
type: string
required:
- operation
- permissionType
type: object
resourceFilter:
description: AclSyncResourceFilter specifies the resource filter
for ACLs.
properties:
name:
description: |-
name is the name of the resource associated with this filter.
The default value is `*`.
type: string
patternType:
description: patternType is the pattern of the resource.
Valid options are `prefixed`, `literal`, `any`, and `match`.
enum:
- prefixed
- literal
- any
- match
type: string
resourceType:
description: resourceType is the type of the filter. Valid
options are `any`, `cluster`, `group`, `topic`, `transactionId`,
and `delegationToken`.
enum:
- any
- cluster
- group
- topic
- transcationId
- delegationToken
type: string
required:
- patternType
- resourceType
type: object
required:
- accessFilter
- resourceFilter
type: object
type: array
configs:
additionalProperties:
type: string
description: |-
configs is a map of string key and value pairs. It specifies additional configurations for the cluster link.
More info: https://docs.confluent.io/platform/current/multi-dc-deployments/cluster-linking/configs.html
type: object
x-kubernetes-map-type: granular
consumerGroupFilters:
description: |-
consumerGroupFilters specify a list of consumer groups to be migrated from
the source cluster to the destination cluster.
items:
description: ClusterLinkOptionsFilter defines the scheme for a filter
properties:
filterType:
description: filterType specifies the filter type. Valid options
are `INCLUDE` and `EXCLUDE`.
enum:
- INCLUDE
- EXCLUDE
type: string
name:
description: name is the resource name associated with this
filter.
type: string
patternType:
description: patternType is the pattern of the resource. Valid
options are `PREFIXED` and `LITERAL`.
enum:
- PREFIXED
- LITERAL
type: string
required:
- filterType
- name
- patternType
type: object
type: array
destinationKafkaCluster:
description: destinationKafkaCluster specifies the destination Kafka
cluster and its REST API configuration.
properties:
authentication:
description: authentication specifies the authentication for the
Kafka cluster.
properties:
jaasConfig:
description: jaasConfig specifies the Kafka client-side JaaS
configuration.
properties:
secretRef:
description: |-
secretRef references the secret containing the required credentials.
More info: https://docs.confluent.io/operator/current/co-authenticate.html
maxLength: 30
minLength: 1
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
type: string
required:
- secretRef
type: object
jaasConfigPassThrough:
description: jaasConfigPassThrough specifies another way to
provide the Kafka client-side JaaS configuration.
properties:
directoryPathInContainer:
description: |-
directoryPathInContainer specifies the directory path in the container where required credentials are mounted.
More info: https://docs.confluent.io/operator/current/co-authenticate.html
minLength: 1
type: string
secretRef:
description: |-
secretRef references the secret containing the required credentials for authentication.
More info: https://docs.confluent.io/operator/current/co-authenticate.html
maxLength: 30
minLength: 1
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
type: string
type: object
oauthSettings:
description: |-
oauthSettings specifies the OAuth settings.
This needs to passed with the authentication type `oauth`.
properties:
audience:
description: audience specifies the audience claim in
the JWT payload.
minLength: 1
type: string
expectedIssuer:
description: expectedIssuer specifies the expected issuer
in the JWT payload.
minLength: 1
type: string
groupsClaimName:
description: groupsClaimName specifies the name of claim
in token for identifying the groups of subject in the
JWT payload.
minLength: 1
type: string
jwksEndpointUri:
description: |-
jwksEndpointUri specifies the uri for the JSON Web Key Set (JWKS).
It is used to get set of keys containing the public keys used to verify any JWT issued by the IdP's Authorization Server.
minLength: 1
type: string
loginConnectTimeoutMs:
description: LoginConnectTimeoutMs sets connect timeout
with IDP in ms
format: int32
type: integer
loginReadTimeoutMs:
description: LoginReadTimeoutMs sets read timeout with
IDP in ms
format: int32
type: integer
loginRetryBackoffMaxMs:
description: LoginRetryBackoffMaxMs sets max retry backoff
with IDP in ms
format: int32
type: integer
loginRetryBackoffMs:
description: LoginRetryBackoffMs sets retry backoff with
IDP in ms
format: int32
type: integer
scope:
description: |-
scope is optional and required only when your identity provider doesn't have
a default scope or your groups claim is linked to a scope.
minLength: 1
type: string
subClaimName:
description: subClaimName specifies name of claim in JWT
to use for the subject.
minLength: 1
type: string
tokenEndpointUri:
description: |-
tokenBaseEndpointUri specifies the base uri for token endpoint.
This is required for OAuth for inter broker communication along with
clientId & clientSecret in JassConfig or JassConfigPassthrough
minLength: 1
type: string
type: object
oauthbearer:
description: |-
oauthbearer is the authentication mechanism to provider principals.
Only supported in RBAC deployment.
properties:
directoryPathInContainer:
description: |-
directoryPathInContainer specifies the directory path in the container
where the credential is mounted.
minLength: 1
type: string
secretRef:
description: |-
secretRef specifies the name of the secret that contains the credential.
More info: https://docs.confluent.io/operator/current/co-authenticate.html#bearer-authentication
maxLength: 30
minLength: 1
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
type: string
type: object
type:
description: |-
type specifies the Kafka client authentication type.
Valid options are `plain`, `oauthbearer`, `digest`, `mtls` and `oauth`.
enum:
- plain
- oauthbearer
- digest
- mtls
- oauth
type: string
required:
- type
type: object
bootstrapEndpoint:
description: |-
bootstrapEndpoint specifies the bootstrap endpoint for the Kafka cluster.
When `spec.sourceInitiatedLink.linkMode` is configured as `Source`, this is required for
`spec.destinationKafkaCluster` and not required for `spec.sourceKafkaCluster`.
For other cluster links this is required for `spec.sourceKafkaCluster` and not required for
`spec.destinationKafkaCluster`.
minLength: 1
pattern: .+:[0-9]+
type: string
clusterID:
description: |-
clusterID specifies the id of the Kafka cluster.
If clusterID is defined for the Kafka cluster, it takes precedence over using the REST API
for getting the cluster ID.
minLength: 1
type: string
kafkaRestClassRef:
description: |-
kafkaRestClassRef references the KafkaRestClass application resource which
defines the Kafka REST API connection information.
When `spec.sourceInitiatedLink.linkMode` is configured as `Source`, this is required for
`spec.sourceKafkaCluster` and optional for `spec.destinationKafkaCluster` if `spec.clusterID` is set.
For other cluster links this is required for 'spec.destinationKafkaCluster` and optional for
`spec.sourceKafkaCluster` if the `spec.clusterID` is set.
properties:
name:
description: name specifies the name of the KafkaRestClass
application resource.
minLength: 1
type: string
namespace:
description: namespace specifies the namespace of the KafkaRestClass.
type: string
required:
- name
type: object
tls:
description: tls specifies the client-side TLS configuration for
the Kafka cluster.
properties:
directoryPathInContainer:
description: |-
directoryPathInContainer contains the directory path in the container where
`fullchain.pem`, `privkey.pem`, `cacerts.pem` or `tls.crt`, `tls.key`, `ca.crt` keys are mounted.
minLength: 1
type: string
enabled:
description: enabled specifies whether to enable the TLS configuration
for the cluster link. The default value is `false`.
type: boolean
keyPassword:
description: |-
keyPassword references the secret containing the SSL key password if the private key passed
in the secretRef above is encrypted.
properties:
secretRef:
description: |-
secretRef references the name of the secret containing the JKS password.
More info: https://docs.confluent.io/operator/current/co-network-encryption.html#configure-user-provided-tls-certificates
maxLength: 30
minLength: 1
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
type: string
required:
- secretRef
type: object
secretRef:
description: |-
secretRef references the secret containing the certificates.
More info: https://docs.confluent.io/operator/current/co-network-encryption.html
maxLength: 63
minLength: 1
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
type: string
required:
- enabled
type: object
type: object
mirrorTopicOptions:
description: mirrorTopicOptions specify configuration options for
mirror topics.
properties:
autoCreateTopics:
description: |-
autoCreateTopics specifies configurations for the cluster link to
automatically create mirror topics on the destination cluster for topics that exist on the source cluster based on defined filters.
More info: https://docs.confluent.io/platform/current/multi-dc-deployments/cluster-linking/mirror-topics-cp.html#auto-create-mirror-topics
properties:
enabled:
description: |-
enabled specifies whether to auto-create mirror topics based on topics on the source cluster.
When set to “true”, mirror topics will be auto-created. Setting this option to “false” disables mirror topic creation and clears any existing filters.
type: boolean
topicFilters:
description: topicFilter contains an array of filters to apply
to indicate which topics should be mirrored.
items:
description: ClusterLinkOptionsFilter defines the scheme
for a filter
properties:
filterType:
description: filterType specifies the filter type. Valid
options are `INCLUDE` and `EXCLUDE`.
enum:
- INCLUDE
- EXCLUDE
type: string
name:
description: name is the resource name associated with
this filter.
type: string
patternType:
description: patternType is the pattern of the resource.
Valid options are `PREFIXED` and `LITERAL`.
enum:
- PREFIXED
- LITERAL
type: string
required:
- filterType
- name
- patternType
type: object
type: array
type: object
prefix:
description: |-
prefix specifies prefix for the mirror topics of the cluster link.
If configured, the valid mirror topic name should be defined with `<prefix><sourceTopicName>` format
which mirrors the topic name of the format `<sourceTopicName>` from source cluster.
When auto-create is enabled and the prefix is configured then the topics created on the destination will automatically contain the prefix.
Otherwise, `spec.mirrorTopic.name` should be defined with `<prefix><sourceTopicName>` format.
maxLength: 255
minLength: 1
pattern: ^[a-zA-Z0-9\._\-]*$
type: string
type: object
mirrorTopics:
description: mirrorTopics specify the mirror topics under this cluster
link.
items:
description: MirrorTopic defines the mirror topic configuration.
properties:
configs:
additionalProperties:
type: string
description: configs is a map of string key and value pairs.
It specifies any additional configuration or configuration
overrides for the mirror topic.
type: object
x-kubernetes-map-type: granular
name:
description: |-
name is the mirror topic name. If the sourceTopicName is not configured,
we assume that the sourceTopicName is the same as mirrorTopicName,
so a topic with the exact same name must exist on the source cluster and
no topic with this name should exist on the destination cluster.
When `spec.mirrorTopicOptions.prefix: <prefix>` is configured for the cluster link,
the name has to be of the format `<prefix><sourceTopicName>`.
maxLength: 255
minLength: 1
pattern: ^[a-zA-Z0-9\._\-]*$
type: string
replicationFactor:
description: |-
replicationFactor specifies the replication factor for the mirror topic on the destination cluster.
If this is not configured, mirror topic will inherit the broker `default.replication.factor` configuration.
format: int32
type: integer
sourceTopicName:
description: |-
sourceTopicName is topic name on the source cluster that will be mirrored to the destination cluster.
When `spec.mirrorTopicOptions.prefix: <prefix>` is not configured, you should not configure this field.
If it is configured, a topic with the exact same name must exist on the source cluster.
maxLength: 255
minLength: 1
pattern: ^[a-zA-Z0-9\._\-]*$
type: string
state:
description: |-
state specifies the desired state for this mirror topic. Valid options are
`ACTIVE`, `FAILOVER`, `PAUSE`, and `PROMOTE`. The default value is `ACTIVE`.
enum:
- PAUSE
- PROMOTE
- FAILOVER
- ACTIVE
type: string
required:
- name
type: object
type: array
name:
description: |-
name specifies the cluster link name. If not configured, then ClusterLink CR name is used
as the cluster link name.
maxLength: 255
minLength: 1
pattern: ^[a-zA-Z0-9\._\-]*$
type: string
sourceInitiatedLink:
description: sourceInitiatedLink specify configs for source initiated
cluster links.
properties:
linkMode:
description: linkMode specifies if this source initiated cluster
link is in Source or Destination mode.
enum:
- Source
- Destination
- Bidirectional
type: string
required:
- linkMode
type: object
sourceKafkaCluster:
description: sourceKafkaCluster specifies the source Kafka cluster
and its REST API configuration.
properties:
authentication:
description: authentication specifies the authentication for the
Kafka cluster.
properties:
jaasConfig:
description: jaasConfig specifies the Kafka client-side JaaS
configuration.
properties:
secretRef:
description: |-
secretRef references the secret containing the required credentials.
More info: https://docs.confluent.io/operator/current/co-authenticate.html
maxLength: 30
minLength: 1
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
type: string
required:
- secretRef
type: object
jaasConfigPassThrough:
description: jaasConfigPassThrough specifies another way to
provide the Kafka client-side JaaS configuration.
properties:
directoryPathInContainer:
description: |-
directoryPathInContainer specifies the directory path in the container where required credentials are mounted.
More info: https://docs.confluent.io/operator/current/co-authenticate.html
minLength: 1
type: string
secretRef:
description: |-
secretRef references the secret containing the required credentials for authentication.
More info: https://docs.confluent.io/operator/current/co-authenticate.html
maxLength: 30
minLength: 1
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
type: string
type: object
oauthSettings:
description: |-
oauthSettings specifies the OAuth settings.
This needs to passed with the authentication type `oauth`.
properties:
audience:
description: audience specifies the audience claim in
the JWT payload.
minLength: 1
type: string
expectedIssuer:
description: expectedIssuer specifies the expected issuer
in the JWT payload.
minLength: 1
type: string
groupsClaimName:
description: groupsClaimName specifies the name of claim
in token for identifying the groups of subject in the
JWT payload.
minLength: 1
type: string
jwksEndpointUri:
description: |-
jwksEndpointUri specifies the uri for the JSON Web Key Set (JWKS).
It is used to get set of keys containing the public keys used to verify any JWT issued by the IdP's Authorization Server.
minLength: 1
type: string
loginConnectTimeoutMs:
description: LoginConnectTimeoutMs sets connect timeout
with IDP in ms
format: int32
type: integer
loginReadTimeoutMs:
description: LoginReadTimeoutMs sets read timeout with
IDP in ms
format: int32
type: integer
loginRetryBackoffMaxMs:
description: LoginRetryBackoffMaxMs sets max retry backoff
with IDP in ms
format: int32
type: integer
loginRetryBackoffMs:
description: LoginRetryBackoffMs sets retry backoff with
IDP in ms
format: int32
type: integer
scope:
description: |-
scope is optional and required only when your identity provider doesn't have
a default scope or your groups claim is linked to a scope.
minLength: 1
type: string
subClaimName:
description: subClaimName specifies name of claim in JWT
to use for the subject.
minLength: 1
type: string
tokenEndpointUri:
description: |-
tokenBaseEndpointUri specifies the base uri for token endpoint.
This is required for OAuth for inter broker communication along with
clientId & clientSecret in JassConfig or JassConfigPassthrough
minLength: 1
type: string
type: object
oauthbearer:
description: |-
oauthbearer is the authentication mechanism to provider principals.
Only supported in RBAC deployment.
properties:
directoryPathInContainer:
description: |-
directoryPathInContainer specifies the directory path in the container
where the credential is mounted.
minLength: 1
type: string
secretRef:
description: |-
secretRef specifies the name of the secret that contains the credential.
More info: https://docs.confluent.io/operator/current/co-authenticate.html#bearer-authentication
maxLength: 30
minLength: 1
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
type: string
type: object
type:
description: |-
type specifies the Kafka client authentication type.
Valid options are `plain`, `oauthbearer`, `digest`, `mtls` and `oauth`.
enum:
- plain
- oauthbearer
- digest
- mtls
- oauth
type: string
required:
- type
type: object
bootstrapEndpoint:
description: |-
bootstrapEndpoint specifies the bootstrap endpoint for the Kafka cluster.
When `spec.sourceInitiatedLink.linkMode` is configured as `Source`, this is required for
`spec.destinationKafkaCluster` and not required for `spec.sourceKafkaCluster`.
For other cluster links this is required for `spec.sourceKafkaCluster` and not required for
`spec.destinationKafkaCluster`.
minLength: 1
pattern: .+:[0-9]+
type: string
clusterID:
description: |-
clusterID specifies the id of the Kafka cluster.
If clusterID is defined for the Kafka cluster, it takes precedence over using the REST API
for getting the cluster ID.
minLength: 1
type: string
kafkaRestClassRef:
description: |-
kafkaRestClassRef references the KafkaRestClass application resource which
defines the Kafka REST API connection information.
When `spec.sourceInitiatedLink.linkMode` is configured as `Source`, this is required for
`spec.sourceKafkaCluster` and optional for `spec.destinationKafkaCluster` if `spec.clusterID` is set.
For other cluster links this is required for 'spec.destinationKafkaCluster` and optional for
`spec.sourceKafkaCluster` if the `spec.clusterID` is set.
properties:
name:
description: name specifies the name of the KafkaRestClass
application resource.
minLength: 1
type: string
namespace:
description: namespace specifies the namespace of the KafkaRestClass.
type: string
required:
- name
type: object
tls:
description: tls specifies the client-side TLS configuration for
the Kafka cluster.
properties:
directoryPathInContainer:
description: |-
directoryPathInContainer contains the directory path in the container where
`fullchain.pem`, `privkey.pem`, `cacerts.pem` or `tls.crt`, `tls.key`, `ca.crt` keys are mounted.
minLength: 1
type: string
enabled:
description: enabled specifies whether to enable the TLS configuration
for the cluster link. The default value is `false`.
type: boolean
keyPassword:
description: |-
keyPassword references the secret containing the SSL key password if the private key passed
in the secretRef above is encrypted.
properties:
secretRef:
description: |-
secretRef references the name of the secret containing the JKS password.
More info: https://docs.confluent.io/operator/current/co-network-encryption.html#configure-user-provided-tls-certificates
maxLength: 30
minLength: 1
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
type: string
required:
- secretRef
type: object
secretRef:
description: |-
secretRef references the secret containing the certificates.
More info: https://docs.confluent.io/operator/current/co-network-encryption.html
maxLength: 63
minLength: 1
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
type: string
required:
- enabled
type: object
type: object
required:
- destinationKafkaCluster
- sourceKafkaCluster
type: object
status:
description: status defines the observed state of the cluster link.
properties:
appState:
default: Unknown
description: appState is the current state of the cluster link application.
enum:
- Unknown
- Created
- Failed
- Deleted
type: string
clusterLinkID:
description: clusterLinkID is the id of the cluster link.
type: string
clusterLinkName:
description: clusterLinkName is the name of the cluster link.
type: string
conditions:
description: conditions are the latest available observations of the
cluster link's state.
items:
description: Condition represent the latest available observations
of the current state.
properties:
lastProbeTime:
description: lastProbeTime shows the last time the condition
was evaluated.
format: date-time
type: string
lastTransitionTime:
description: lastTransitionTime shows the last time the condition
was transitioned from one status to another.
format: date-time
type: string
message:
description: message shows a human-readable message with details
about the transition.
type: string
reason:
description: reason shows the reason for the last transition
of the condition.
type: string
status:
description: status shows the status of the condition, one of
`True`, `False`, or `Unknown`.
type: string
type:
description: type shows the condition type.
type: string
type: object
type: array
destinationKafkaClusterID:
description: destinationKafkaClusterID is the ID of the destination
Kafka cluster.
type: string
kafkaCluster:
description: 'kafkaCluster is the Kafka cluster this cluster link
belongs to. The format is: `<Kafka namespace>/<Kafka name>`'
type: string
mirrorTopics:
additionalProperties:
description: |-
MirrorTopicStatus specifies the status reported for each mirror topic as part of
the cluster link status.
properties:
observedGeneration:
description: observedGeneration is the most recent generation
observed for this Confluent component.
format: int64
type: integer
replicationFactor:
description: replicationFactor specifies the replication factor
for the mirror topic on the destination cluster.
format: int32
type: integer
sourceTopicName:
description: sourceTopicName is the name of the topic being
mirrored on the source cluster.
type: string
status:
description: |-
status is the status of the mirror topic.
It can be `ACTIVE`, `FAILED`, `PAUSED`, `STOPPED`, and `PENDING_STOPPED`.
type: string
type: object
description: mirrorTopics is a map of mirror topic name to its status
type: object
x-kubernetes-map-type: granular
numMirrorTopics:
description: numMirrorTopics is the number of mirror topics for the
cluster link.
type: integer
observedGeneration:
description: observedGeneration is the most recent generation observed
for this Confluent component.
format: int64
type: integer
sourceKafkaClusterID:
description: sourceKafkaClusterID is the ID of the source Kafka cluster.
type: string
state:
description: state is the current state of the cluster link.
type: string
type: object
required:
- spec
type: object
served: true
storage: true
subresources:
status: {}

View File

@ -0,0 +1,296 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.15.0
name: confluentrolebindings.platform.confluent.io
spec:
group: platform.confluent.io
names:
categories:
- all
- confluent-platform
- confluent
kind: ConfluentRolebinding
listKind: ConfluentRolebindingList
plural: confluentrolebindings
shortNames:
- cfrb
- confluentrolebinding
singular: confluentrolebinding
scope: Namespaced
versions:
- additionalPrinterColumns:
- jsonPath: .status.state
name: Status
type: string
- jsonPath: .status.kafkaClusterID
name: KafkaClusterID
type: string
- jsonPath: .status.principal
name: Principal
type: string
- jsonPath: .status.role
name: Role
type: string
- jsonPath: .status.kafkaRestClass
name: KafkaRestClass
type: string
- jsonPath: .metadata.creationTimestamp
name: Age
type: date
- jsonPath: .status.kafkaCluster
name: KafkaCluster
priority: 1
type: string
- jsonPath: .status.clusterRegistryName
name: ClusterRegistryName
priority: 1
type: string
name: v1beta1
schema:
openAPIV3Schema:
description: ConfluentRolebinding is the schema for the ConfluentRolebinding
API.
properties:
apiVersion:
description: |-
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
type: string
kind:
description: |-
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
metadata:
type: object
spec:
description: spec defines the desired state of the ConfluentRolebinding.
properties:
clustersScopeByIds:
description: clustersScopeByIds specify the scope of the Confluent
component cluster(s) via cluster id(s).
properties:
connectClusterId:
description: connectClusterId specifies the Connect cluster id.
minLength: 1
type: string
kafkaClusterId:
description: kafkaClusterId specifies the id of the Kafka cluster
id.
minLength: 1
type: string
ksqlClusterId:
description: ksqlClusterId specifies the ksqlDB cluster id.
minLength: 1
type: string
schemaRegistryClusterId:
description: schemaRegistryClusterId specifies the Schema Registry
cluster id.
minLength: 1
type: string
type: object
clustersScopeByRegistryName:
description: clustersScopeByRegistryName specifies the unique cluster
name you registered in the cluster registry.
minLength: 1
type: string
kafkaRestClassRef:
description: kafkaRestClassRef references the KafkaRestClass that
defines the Kafka REST API connection information.
properties:
name:
description: name specifies the name of the KafkaRestClass application
resource.
minLength: 1
type: string
namespace:
description: namespace specifies the namespace of the KafkaRestClass.
type: string
required:
- name
type: object
principal:
description: RolebindingPrincipal defines the principal(user/group)
the rolebinding belongs to.
properties:
name:
description: name specifies the name of the principal.
minLength: 1
type: string
type:
description: type specifies the type of the principal. Valid options
are `user` and `group`.
enum:
- user
- group
type: string
required:
- name
- type
type: object
resourcePatterns:
description: resourcePatterns specify the qualified resources associated
with this rolebinding.
items:
description: ResourcePattern specifies the qualified resource info
associated with this rolebinding.
properties:
name:
description: name specifies the name of the resource associated
with this rolebinding.
minLength: 1
type: string
patternType:
description: |-
patternType specifies the pattern of the resource. Valid options are
`PREFIXED` or `LITERAL`. The default value is `LITERAL`.
enum:
- PREFIXED
- LITERAL
type: string
resourceType:
description: |-
resourceType refers to the type of the resource.
Valid options are `Topic`, `Group`, `Subject`, `KsqlCluster`, `Cluster`, `TransactionalId`, etc.
minLength: 1
type: string
required:
- name
- resourceType
type: object
type: array
role:
description: role specifies the name of the role.
minLength: 1
type: string
required:
- principal
- role
type: object
status:
description: status is the observed state of the ConfluentRolebinding.
properties:
appState:
default: Unknown
description: appState is the current state of the rolebinding application.
enum:
- Unknown
- Created
- Failed
- Deleted
type: string
clusterRegistryName:
description: clusterRegistryName is the cluster registry name the
rolebinding associated with.
type: string
conditions:
description: conditions are the latest available observations of the
rolebinding's state.
items:
description: Condition represent the latest available observations
of the current state.
properties:
lastProbeTime:
description: lastProbeTime shows the last time the condition
was evaluated.
format: date-time
type: string
lastTransitionTime:
description: lastTransitionTime shows the last time the condition
was transitioned from one status to another.
format: date-time
type: string
message:
description: message shows a human-readable message with details
about the transition.
type: string
reason:
description: reason shows the reason for the last transition
of the condition.
type: string
status:
description: status shows the status of the condition, one of
`True`, `False`, or `Unknown`.
type: string
type:
description: type shows the condition type.
type: string
type: object
type: array
kafkaCluster:
description: 'kafkaCluster is the Kafka cluster the rolebinding belongs
to. The format is: `<Kafka namespace>/<Kafka name>`.'
type: string
kafkaClusterID:
description: kafkaClusterID is the id of the Kafka cluster.
type: string
kafkaRestClass:
description: 'kafkaRestClass is the kafkaRestClass this rolebinding
uses. The format is: `<kafkaRestClass namespace>/<kafkaRestClass
name>`.'
type: string
mdsEndpoint:
description: mdsEndpoint is the MDS endpoint.
type: string
observedGeneration:
description: observedGeneration is the most recent generation observed
for this Confluent component.
format: int64
type: integer
principal:
description: 'principal is the principal the rolebinding belongs to.
The format is: `<principal type>:<principal name>`.'
type: string
resourcePatterns:
description: resourcePatterns are the resource patterns this rolebinding
is associated with.
items:
description: ResourcePattern specifies the qualified resource info
associated with this rolebinding.
properties:
name:
description: name specifies the name of the resource associated
with this rolebinding.
minLength: 1
type: string
patternType:
description: |-
patternType specifies the pattern of the resource. Valid options are
`PREFIXED` or `LITERAL`. The default value is `LITERAL`.
enum:
- PREFIXED
- LITERAL
type: string
resourceType:
description: |-
resourceType refers to the type of the resource.
Valid options are `Topic`, `Group`, `Subject`, `KsqlCluster`, `Cluster`, `TransactionalId`, etc.
minLength: 1
type: string
required:
- name
- resourceType
type: object
type: array
role:
description: role is the role this rolebinding is associated with.
type: string
state:
description: state is the state of this rolebinding.
type: string
type: object
required:
- spec
type: object
served: true
storage: true
subresources:
status: {}

View File

@ -0,0 +1,496 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.15.0
name: connectors.platform.confluent.io
spec:
group: platform.confluent.io
names:
categories:
- all
- confluent-platform
- confluent
kind: Connector
listKind: ConnectorList
plural: connectors
shortNames:
- ctr
- connector
singular: connector
scope: Namespaced
versions:
- additionalPrinterColumns:
- jsonPath: .status.state
name: Status
type: string
- jsonPath: .status.connectorState
name: ConnectorStatus
type: string
- jsonPath: .status.tasksReady
name: Tasks-Ready
type: string
- jsonPath: .metadata.creationTimestamp
name: Age
type: date
- jsonPath: .status.connectRestEndpoint
name: ConnectEndpoint
priority: 1
type: string
- jsonPath: .status.failedTasksCount
name: Tasks-Failed
priority: 1
type: string
- jsonPath: .status.workerID
name: WorkerID
priority: 1
type: string
- jsonPath: .status.restartPolicy.type
name: RestartPolicy
priority: 1
type: string
- jsonPath: .status.kafkaClusterID
name: KafkaClusterID
priority: 1
type: string
name: v1beta1
schema:
openAPIV3Schema:
description: Connector is the schema for the Connector API.
properties:
apiVersion:
description: |-
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
type: string
kind:
description: |-
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
metadata:
type: object
spec:
description: spec defines the desired state of the Connector.
properties:
class:
description: |-
class specifies the class name of the connector.
The Connect cluster displays the supported class names in its status.
minLength: 1
type: string
configs:
additionalProperties:
type: string
description: configs is a map of string key and value pairs. It specifies
the additional configurations for the connector.
type: object
x-kubernetes-map-type: granular
connectClusterRef:
description: connectClusterRef references the CFK managed Connect
cluster.
properties:
name:
description: name specifies the name of the Confluent Platform
component cluster.
type: string
namespace:
description: namespace specifies the namespace where the Confluent
Platform component cluster is running.
type: string
required:
- name
type: object
connectRest:
description: connectRest specifies the Connect REST API connection
configuration.
properties:
authentication:
description: authentication specifies the REST API authentication
mechanism.
properties:
basic:
description: basic specifies the basic authentication settings
for the REST API client.
properties:
debug:
description: debug enables the basic authentication debug
logs for JaaS configuration.
type: boolean
directoryPathInContainer:
description: |-
directoryPathInContainer allows to pass the basic credential through a directory path in the container.
More info: https://docs.confluent.io/operator/current/co-authenticate.html#basic-authentication
minLength: 1
type: string
restrictedRoles:
description: |-
restrictedRoles specify the restricted roles on the server side only.
Changes will be only reflected in Control Center.
This configuration is ignored on the client side configuration.
items:
type: string
minItems: 1
type: array
roles:
description: |-
roles specify the roles on the server side only.
This configuration is ignored on the client side configuration.
items:
type: string
type: array
secretRef:
description: |-
secretRef defines secret reference to pass the required credentials.
More info: https://docs.confluent.io/operator/current/co-authenticate.html#basic-authentication
maxLength: 30
minLength: 1
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
type: string
type: object
bearer:
description: bearer specifies the bearer authentication settings
for the REST API client.
properties:
directoryPathInContainer:
description: |-
directoryPathInContainer specifies the directory path in the container
where the credential is mounted.
minLength: 1
type: string
secretRef:
description: |-
secretRef specifies the name of the secret that contains the credential.
More info: https://docs.confluent.io/operator/current/co-authenticate.html#bearer-authentication
maxLength: 30
minLength: 1
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
type: string
type: object
oauth:
description: oauth specifies the OAuth authentication settings
for the REST API client.
properties:
configuration:
description: configuration specifies the OAuth server
settings.
properties:
audience:
description: audience specifies the audience claim
in the JWT payload.
minLength: 1
type: string
expectedIssuer:
description: expectedIssuer specifies the expected
issuer in the JWT payload.
minLength: 1
type: string
groupsClaimName:
description: groupsClaimName specifies the name of
claim in token for identifying the groups of subject
in the JWT payload.
minLength: 1
type: string
jwksEndpointUri:
description: |-
jwksEndpointUri specifies the uri for the JSON Web Key Set (JWKS).
It is used to get set of keys containing the public keys used to verify any JWT issued by the IdP's Authorization Server.
minLength: 1
type: string
loginConnectTimeoutMs:
description: LoginConnectTimeoutMs sets connect timeout
with IDP in ms
format: int32
type: integer
loginReadTimeoutMs:
description: LoginReadTimeoutMs sets read timeout
with IDP in ms
format: int32
type: integer
loginRetryBackoffMaxMs:
description: LoginRetryBackoffMaxMs sets max retry
backoff with IDP in ms
format: int32
type: integer
loginRetryBackoffMs:
description: LoginRetryBackoffMs sets retry backoff
with IDP in ms
format: int32
type: integer
scope:
description: |-
scope is optional and required only when your identity provider doesn't have
a default scope or your groups claim is linked to a scope.
minLength: 1
type: string
subClaimName:
description: subClaimName specifies name of claim
in JWT to use for the subject.
minLength: 1
type: string
tokenEndpointUri:
description: |-
tokenBaseEndpointUri specifies the base uri for token endpoint.
This is required for OAuth for inter broker communication along with
clientId & clientSecret in JassConfig or JassConfigPassthrough
minLength: 1
type: string
type: object
directoryPathInContainer:
description: directoryPathInContainer allows to pass the
basic credential through a directory path in the container.
minLength: 1
type: string
secretRef:
description: secretRef defines secret reference to pass
the required credentials.
maxLength: 30
minLength: 1
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
type: string
required:
- configuration
type: object
type:
description: type specifies the REST API authentication type.
Valid options are `basic`, `bearer`, `mtls` and `oauth`.
enum:
- basic
- bearer
- mtls
- oauth
type: string
required:
- type
type: object
endpoint:
description: endpoint specifies where Confluent REST API is running.
minLength: 1
pattern: ^https?://.*
type: string
kafkaClusterID:
description: |-
kafkaClusterID specifies the id of Kafka cluster.
It takes precedence over using the Kafka REST API to get the cluster id.
minLength: 1
type: string
tls:
description: "tls specifies the custom TLS structure for the application
resources,\n\t// e.g. connector, topic, schema, of the Confluent
Platform components.\n\t// +optional"
properties:
directoryPathInContainer:
description: |-
directoryPathInContainer contains the directory path in the container where
`keystore.jks`, `truststore.jks`, `jksPassword.txt` keys are mounted.
minLength: 1
type: string
jksPassword:
description: jksPassword specifies the secret name that contains
the JKS password.
properties:
secretRef:
description: |-
secretRef references the name of the secret containing the JKS password.
More info: https://docs.confluent.io/operator/current/co-network-encryption.html#configure-user-provided-tls-certificates
maxLength: 30
minLength: 1
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
type: string
required:
- secretRef
type: object
secretRef:
description: |-
secretRef specifies the secret name that contains the certificates.
More info about certificates key/value format: https://docs.confluent.io/operator/current/co-network-encryption.html#configure-user-provided-tls-certificates
maxLength: 63
minLength: 1
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
type: string
type: object
type: object
name:
description: |-
name specifies the connector name. If not configured,
the Connector CR name is used as the connector name.
maxLength: 255
minLength: 1
pattern: ^[a-zA-Z0-9\._\-]*$
type: string
restartPolicy:
description: restartPolicy specifies the policy to restart failed
tasks of the connector.
properties:
maxRetry:
description: maxRetry specifies the max number of tries to restart
failed tasks when the `restartPolicy` type is `OnFailure`. The
default value is `10`.
format: int32
minimum: 1
type: integer
type:
description: |-
type specifies the policy type to restart connector tasks. Valid options are `OnFailure` and `Never`.
Default value is `OnFailure`, which means it will restart automatically when a task fails if the `maxRetry` value is not reached.
enum:
- OnFailure
- Never
type: string
required:
- type
type: object
taskMax:
description: |-
taskMax specifies the maximum number of tasks for the connector. It must be greater than 0.
The connector may create fewer tasks if it cannot achieve this level of parallelism.
format: int32
minimum: 1
type: integer
required:
- class
- taskMax
type: object
status:
description: status defines the observed state of the Connector.
properties:
appState:
default: Unknown
description: appState is the current state of the connector application.
enum:
- Unknown
- Created
- Failed
- Deleted
type: string
conditions:
description: conditions are the latest available observations of the
connector state.
items:
description: Condition represent the latest available observations
of the current state.
properties:
lastProbeTime:
description: lastProbeTime shows the last time the condition
was evaluated.
format: date-time
type: string
lastTransitionTime:
description: lastTransitionTime shows the last time the condition
was transitioned from one status to another.
format: date-time
type: string
message:
description: message shows a human-readable message with details
about the transition.
type: string
reason:
description: reason shows the reason for the last transition
of the condition.
type: string
status:
description: status shows the status of the condition, one of
`True`, `False`, or `Unknown`.
type: string
type:
description: type shows the condition type.
type: string
type: object
type: array
connectRestEndpoint:
description: connectRestEndpoint is the REST endpoint of the Connect
cluster.
type: string
connectorState:
description: connectorState is the status of the connector instance.
type: string
failedTasks:
additionalProperties:
description: TaskStatus defines the connector task status.
properties:
id:
description: Id is the id of the task.
format: int32
type: integer
retryCount:
description: retryCount is the number of retry attempts to restart
the failed task.
format: int32
type: integer
workerID:
description: workerID is the workerId for the task.
type: string
required:
- id
type: object
description: |-
failedTasks is the map of connector tasks in the `FAILED` state.
Error messages of failed tasks are logged in the CFK logs as `INFO`.
You can also get the error message via Connect REST API calls.
type: object
x-kubernetes-map-type: granular
failedTasksCount:
description: failedTasksCount is the number of failed tasks.
format: int32
type: integer
kafkaClusterID:
description: kafkaClusterID is the Kafka cluster id the connector
belongs to.
type: string
observedGeneration:
description: observedGeneration is the most recent generation observed
for this Confluent component.
format: int64
type: integer
restartPolicy:
description: restartPolicy is the policy to restart failed tasks of
the connector.
properties:
maxRetry:
description: maxRetry specifies the max number of tries to restart
failed tasks when the `restartPolicy` type is `OnFailure`. The
default value is `10`.
format: int32
minimum: 1
type: integer
type:
description: |-
type specifies the policy type to restart connector tasks. Valid options are `OnFailure` and `Never`.
Default value is `OnFailure`, which means it will restart automatically when a task fails if the `maxRetry` value is not reached.
enum:
- OnFailure
- Never
type: string
required:
- type
type: object
state:
description: state is the custom resource state of the connector.
This is not the connector state, which can be `CREATED`, `ERROR`,
etc.
type: string
tasksReady:
description: |-
tasksReady is the number of running tasks based on `taskMax`.
The value is in the following format: `<number of running tasks>/<taskMax>`
type: string
trace:
description: trace is the error trace message for the connector instance.
type: string
workerID:
description: workerID is the workerId of the connector instance.
type: string
type: object
required:
- spec
type: object
served: true
storage: true
subresources:
status: {}

View File

@ -0,0 +1,557 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.15.0
name: kafkarestclasses.platform.confluent.io
spec:
group: platform.confluent.io
names:
categories:
- all
- confluent-platform
- confluent
kind: KafkaRestClass
listKind: KafkaRestClassList
plural: kafkarestclasses
shortNames:
- krc
- kafkarestclass
singular: kafkarestclass
scope: Namespaced
versions:
- additionalPrinterColumns:
- jsonPath: .metadata.creationTimestamp
name: Age
type: date
name: v1beta1
schema:
openAPIV3Schema:
description: KafkaRestClass is the schema for the Kafka REST API.
properties:
apiVersion:
description: |-
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
type: string
kind:
description: |-
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
metadata:
type: object
spec:
description: spec defines the desired state of the KafkaRestClass.
properties:
kafkaClusterRef:
description: kafkaClusterRef specifies the name of the Kafka cluster.
properties:
name:
description: name specifies the name of the Confluent Platform
component cluster.
type: string
namespace:
description: namespace specifies the namespace where the Confluent
Platform component cluster is running.
type: string
required:
- name
type: object
kafkaRest:
description: kafkaRest specifies the Kafka REST API configuration.
properties:
authentication:
description: authentication specifies the REST API authentication
mechanism.
properties:
basic:
description: basic specifies the basic authentication settings
for the REST API client.
properties:
debug:
description: debug enables the basic authentication debug
logs for JaaS configuration.
type: boolean
directoryPathInContainer:
description: |-
directoryPathInContainer allows to pass the basic credential through a directory path in the container.
More info: https://docs.confluent.io/operator/current/co-authenticate.html#basic-authentication
minLength: 1
type: string
restrictedRoles:
description: |-
restrictedRoles specify the restricted roles on the server side only.
Changes will be only reflected in Control Center.
This configuration is ignored on the client side configuration.
items:
type: string
minItems: 1
type: array
roles:
description: |-
roles specify the roles on the server side only.
This configuration is ignored on the client side configuration.
items:
type: string
type: array
secretRef:
description: |-
secretRef defines secret reference to pass the required credentials.
More info: https://docs.confluent.io/operator/current/co-authenticate.html#basic-authentication
maxLength: 30
minLength: 1
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
type: string
type: object
bearer:
description: bearer specifies the bearer authentication settings
for the REST API client.
properties:
directoryPathInContainer:
description: |-
directoryPathInContainer specifies the directory path in the container
where the credential is mounted.
minLength: 1
type: string
secretRef:
description: |-
secretRef specifies the name of the secret that contains the credential.
More info: https://docs.confluent.io/operator/current/co-authenticate.html#bearer-authentication
maxLength: 30
minLength: 1
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
type: string
type: object
oauth:
description: oauth specifies the OAuth authentication settings
for the REST API client.
properties:
configuration:
description: configuration specifies the OAuth server
settings.
properties:
audience:
description: audience specifies the audience claim
in the JWT payload.
minLength: 1
type: string
expectedIssuer:
description: expectedIssuer specifies the expected
issuer in the JWT payload.
minLength: 1
type: string
groupsClaimName:
description: groupsClaimName specifies the name of
claim in token for identifying the groups of subject
in the JWT payload.
minLength: 1
type: string
jwksEndpointUri:
description: |-
jwksEndpointUri specifies the uri for the JSON Web Key Set (JWKS).
It is used to get set of keys containing the public keys used to verify any JWT issued by the IdP's Authorization Server.
minLength: 1
type: string
loginConnectTimeoutMs:
description: LoginConnectTimeoutMs sets connect timeout
with IDP in ms
format: int32
type: integer
loginReadTimeoutMs:
description: LoginReadTimeoutMs sets read timeout
with IDP in ms
format: int32
type: integer
loginRetryBackoffMaxMs:
description: LoginRetryBackoffMaxMs sets max retry
backoff with IDP in ms
format: int32
type: integer
loginRetryBackoffMs:
description: LoginRetryBackoffMs sets retry backoff
with IDP in ms
format: int32
type: integer
scope:
description: |-
scope is optional and required only when your identity provider doesn't have
a default scope or your groups claim is linked to a scope.
minLength: 1
type: string
subClaimName:
description: subClaimName specifies name of claim
in JWT to use for the subject.
minLength: 1
type: string
tokenEndpointUri:
description: |-
tokenBaseEndpointUri specifies the base uri for token endpoint.
This is required for OAuth for inter broker communication along with
clientId & clientSecret in JassConfig or JassConfigPassthrough
minLength: 1
type: string
type: object
directoryPathInContainer:
description: directoryPathInContainer allows to pass the
basic credential through a directory path in the container.
minLength: 1
type: string
secretRef:
description: secretRef defines secret reference to pass
the required credentials.
maxLength: 30
minLength: 1
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
type: string
required:
- configuration
type: object
type:
description: type specifies the REST API authentication type.
Valid options are `basic`, `bearer`, `mtls` and `oauth`.
enum:
- basic
- bearer
- mtls
- oauth
type: string
required:
- type
type: object
endpoint:
description: endpoint specifies where Confluent REST API is running.
minLength: 1
pattern: ^https?://.*
type: string
kafkaClusterID:
description: |-
kafkaClusterID specifies the id of Kafka cluster.
It takes precedence over using the Kafka REST API to get the cluster id.
minLength: 1
type: string
tls:
description: "tls specifies the custom TLS structure for the application
resources,\n\t// e.g. connector, topic, schema, of the Confluent
Platform components.\n\t// +optional"
properties:
directoryPathInContainer:
description: |-
directoryPathInContainer contains the directory path in the container where
`keystore.jks`, `truststore.jks`, `jksPassword.txt` keys are mounted.
minLength: 1
type: string
jksPassword:
description: jksPassword specifies the secret name that contains
the JKS password.
properties:
secretRef:
description: |-
secretRef references the name of the secret containing the JKS password.
More info: https://docs.confluent.io/operator/current/co-network-encryption.html#configure-user-provided-tls-certificates
maxLength: 30
minLength: 1
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
type: string
required:
- secretRef
type: object
secretRef:
description: |-
secretRef specifies the secret name that contains the certificates.
More info about certificates key/value format: https://docs.confluent.io/operator/current/co-network-encryption.html#configure-user-provided-tls-certificates
maxLength: 63
minLength: 1
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
type: string
type: object
type: object
secondaryKafkaClusterRef:
description: secondaryKafkaClusterRef specifies the name of the secondary
Kafka cluster when using centralized RBAC.
properties:
name:
description: name specifies the name of the Confluent Platform
component cluster.
type: string
namespace:
description: namespace specifies the namespace where the Confluent
Platform component cluster is running.
type: string
required:
- name
type: object
secondaryKafkaRest:
description: secondaryKafkaRest specifies the secondary Kafka REST
API configuration when using centralized RBAC.
properties:
authentication:
description: authentication specifies the REST API authentication
mechanism.
properties:
basic:
description: basic specifies the basic authentication settings
for the REST API client.
properties:
debug:
description: debug enables the basic authentication debug
logs for JaaS configuration.
type: boolean
directoryPathInContainer:
description: |-
directoryPathInContainer allows to pass the basic credential through a directory path in the container.
More info: https://docs.confluent.io/operator/current/co-authenticate.html#basic-authentication
minLength: 1
type: string
restrictedRoles:
description: |-
restrictedRoles specify the restricted roles on the server side only.
Changes will be only reflected in Control Center.
This configuration is ignored on the client side configuration.
items:
type: string
minItems: 1
type: array
roles:
description: |-
roles specify the roles on the server side only.
This configuration is ignored on the client side configuration.
items:
type: string
type: array
secretRef:
description: |-
secretRef defines secret reference to pass the required credentials.
More info: https://docs.confluent.io/operator/current/co-authenticate.html#basic-authentication
maxLength: 30
minLength: 1
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
type: string
type: object
bearer:
description: bearer specifies the bearer authentication settings
for the REST API client.
properties:
directoryPathInContainer:
description: |-
directoryPathInContainer specifies the directory path in the container
where the credential is mounted.
minLength: 1
type: string
secretRef:
description: |-
secretRef specifies the name of the secret that contains the credential.
More info: https://docs.confluent.io/operator/current/co-authenticate.html#bearer-authentication
maxLength: 30
minLength: 1
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
type: string
type: object
oauth:
description: oauth specifies the OAuth authentication settings
for the REST API client.
properties:
configuration:
description: configuration specifies the OAuth server
settings.
properties:
audience:
description: audience specifies the audience claim
in the JWT payload.
minLength: 1
type: string
expectedIssuer:
description: expectedIssuer specifies the expected
issuer in the JWT payload.
minLength: 1
type: string
groupsClaimName:
description: groupsClaimName specifies the name of
claim in token for identifying the groups of subject
in the JWT payload.
minLength: 1
type: string
jwksEndpointUri:
description: |-
jwksEndpointUri specifies the uri for the JSON Web Key Set (JWKS).
It is used to get set of keys containing the public keys used to verify any JWT issued by the IdP's Authorization Server.
minLength: 1
type: string
loginConnectTimeoutMs:
description: LoginConnectTimeoutMs sets connect timeout
with IDP in ms
format: int32
type: integer
loginReadTimeoutMs:
description: LoginReadTimeoutMs sets read timeout
with IDP in ms
format: int32
type: integer
loginRetryBackoffMaxMs:
description: LoginRetryBackoffMaxMs sets max retry
backoff with IDP in ms
format: int32
type: integer
loginRetryBackoffMs:
description: LoginRetryBackoffMs sets retry backoff
with IDP in ms
format: int32
type: integer
scope:
description: |-
scope is optional and required only when your identity provider doesn't have
a default scope or your groups claim is linked to a scope.
minLength: 1
type: string
subClaimName:
description: subClaimName specifies name of claim
in JWT to use for the subject.
minLength: 1
type: string
tokenEndpointUri:
description: |-
tokenBaseEndpointUri specifies the base uri for token endpoint.
This is required for OAuth for inter broker communication along with
clientId & clientSecret in JassConfig or JassConfigPassthrough
minLength: 1
type: string
type: object
directoryPathInContainer:
description: directoryPathInContainer allows to pass the
basic credential through a directory path in the container.
minLength: 1
type: string
secretRef:
description: secretRef defines secret reference to pass
the required credentials.
maxLength: 30
minLength: 1
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
type: string
required:
- configuration
type: object
type:
description: type specifies the REST API authentication type.
Valid options are `basic`, `bearer`, `mtls` and `oauth`.
enum:
- basic
- bearer
- mtls
- oauth
type: string
required:
- type
type: object
endpoint:
description: endpoint specifies where Confluent REST API is running.
minLength: 1
pattern: ^https?://.*
type: string
kafkaClusterID:
description: |-
kafkaClusterID specifies the id of Kafka cluster.
It takes precedence over using the Kafka REST API to get the cluster id.
minLength: 1
type: string
tls:
description: "tls specifies the custom TLS structure for the application
resources,\n\t// e.g. connector, topic, schema, of the Confluent
Platform components.\n\t// +optional"
properties:
directoryPathInContainer:
description: |-
directoryPathInContainer contains the directory path in the container where
`keystore.jks`, `truststore.jks`, `jksPassword.txt` keys are mounted.
minLength: 1
type: string
jksPassword:
description: jksPassword specifies the secret name that contains
the JKS password.
properties:
secretRef:
description: |-
secretRef references the name of the secret containing the JKS password.
More info: https://docs.confluent.io/operator/current/co-network-encryption.html#configure-user-provided-tls-certificates
maxLength: 30
minLength: 1
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
type: string
required:
- secretRef
type: object
secretRef:
description: |-
secretRef specifies the secret name that contains the certificates.
More info about certificates key/value format: https://docs.confluent.io/operator/current/co-network-encryption.html#configure-user-provided-tls-certificates
maxLength: 63
minLength: 1
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
type: string
type: object
type: object
type: object
status:
description: status defines the observed state of the KafkaRestClass.
properties:
conditions:
description: conditions are the latest available observed state of
the kafkaRestClass.
items:
description: Condition represent the latest available observations
of the current state.
properties:
lastProbeTime:
description: lastProbeTime shows the last time the condition
was evaluated.
format: date-time
type: string
lastTransitionTime:
description: lastTransitionTime shows the last time the condition
was transitioned from one status to another.
format: date-time
type: string
message:
description: message shows a human-readable message with details
about the transition.
type: string
reason:
description: reason shows the reason for the last transition
of the condition.
type: string
status:
description: status shows the status of the condition, one of
`True`, `False`, or `Unknown`.
type: string
type:
description: type shows the condition type.
type: string
type: object
type: array
endpoint:
description: endpoint specifies the Kafka REST API / MDS endpoint.
type: string
kafkaClusterID:
description: |-
kafkaClusterID specifies the id of the Kafka cluster.
If using centralized RBAC and kafkaRestClass is for the secondary Kafka cluster, it will be the cluster id of the secondary Kafka cluster.
type: string
observedGeneration:
description: observedGeneration is the most recent generation observed
for this Confluent component.
format: int64
type: integer
type: object
required:
- spec
type: object
served: true
storage: true
subresources:
status: {}

View File

@ -0,0 +1,410 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.15.0
name: kafkatopics.platform.confluent.io
spec:
group: platform.confluent.io
names:
categories:
- all
- confluent-platform
- confluent
kind: KafkaTopic
listKind: KafkaTopicList
plural: kafkatopics
shortNames:
- kt
- topic
singular: kafkatopic
scope: Namespaced
versions:
- additionalPrinterColumns:
- jsonPath: .status.replicas
name: Replicas
type: string
- jsonPath: .status.partitionCount
name: Partition
type: string
- jsonPath: .status.state
name: Status
type: string
- jsonPath: .status.kafkaClusterID
name: ClusterID
type: string
- jsonPath: .metadata.creationTimestamp
name: Age
type: date
- jsonPath: .status.kafkaCluster
name: KafkaCluster
priority: 1
type: string
name: v1beta1
schema:
openAPIV3Schema:
description: KafkaTopic is the schema for the Kafka Topic API.
properties:
apiVersion:
description: |-
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
type: string
kind:
description: |-
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
metadata:
type: object
spec:
description: spec defines the desired state of the KafkaTopic.
properties:
configs:
additionalProperties:
type: string
description: |-
configs is a map of string key and value pairs that are used to pass the configuration settings for the topic.
More info: https://docs.confluent.io/current/installation/configuration/topic-configs.html.
type: object
x-kubernetes-map-type: granular
kafkaClusterRef:
description: kafkaClusterRef specifies the name of the Kafka cluster.
properties:
name:
description: name specifies the name of the Confluent Platform
component cluster.
type: string
namespace:
description: namespace specifies the namespace where the Confluent
Platform component cluster is running.
type: string
required:
- name
type: object
kafkaRest:
description: kafkaRest specifies the Kafka REST API configuration.
properties:
authentication:
description: authentication specifies the REST API authentication
mechanism.
properties:
basic:
description: basic specifies the basic authentication settings
for the REST API client.
properties:
debug:
description: debug enables the basic authentication debug
logs for JaaS configuration.
type: boolean
directoryPathInContainer:
description: |-
directoryPathInContainer allows to pass the basic credential through a directory path in the container.
More info: https://docs.confluent.io/operator/current/co-authenticate.html#basic-authentication
minLength: 1
type: string
restrictedRoles:
description: |-
restrictedRoles specify the restricted roles on the server side only.
Changes will be only reflected in Control Center.
This configuration is ignored on the client side configuration.
items:
type: string
minItems: 1
type: array
roles:
description: |-
roles specify the roles on the server side only.
This configuration is ignored on the client side configuration.
items:
type: string
type: array
secretRef:
description: |-
secretRef defines secret reference to pass the required credentials.
More info: https://docs.confluent.io/operator/current/co-authenticate.html#basic-authentication
maxLength: 30
minLength: 1
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
type: string
type: object
bearer:
description: bearer specifies the bearer authentication settings
for the REST API client.
properties:
directoryPathInContainer:
description: |-
directoryPathInContainer specifies the directory path in the container
where the credential is mounted.
minLength: 1
type: string
secretRef:
description: |-
secretRef specifies the name of the secret that contains the credential.
More info: https://docs.confluent.io/operator/current/co-authenticate.html#bearer-authentication
maxLength: 30
minLength: 1
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
type: string
type: object
oauth:
description: oauth specifies the OAuth authentication settings
for the REST API client.
properties:
configuration:
description: configuration specifies the OAuth server
settings.
properties:
audience:
description: audience specifies the audience claim
in the JWT payload.
minLength: 1
type: string
expectedIssuer:
description: expectedIssuer specifies the expected
issuer in the JWT payload.
minLength: 1
type: string
groupsClaimName:
description: groupsClaimName specifies the name of
claim in token for identifying the groups of subject
in the JWT payload.
minLength: 1
type: string
jwksEndpointUri:
description: |-
jwksEndpointUri specifies the uri for the JSON Web Key Set (JWKS).
It is used to get set of keys containing the public keys used to verify any JWT issued by the IdP's Authorization Server.
minLength: 1
type: string
loginConnectTimeoutMs:
description: LoginConnectTimeoutMs sets connect timeout
with IDP in ms
format: int32
type: integer
loginReadTimeoutMs:
description: LoginReadTimeoutMs sets read timeout
with IDP in ms
format: int32
type: integer
loginRetryBackoffMaxMs:
description: LoginRetryBackoffMaxMs sets max retry
backoff with IDP in ms
format: int32
type: integer
loginRetryBackoffMs:
description: LoginRetryBackoffMs sets retry backoff
with IDP in ms
format: int32
type: integer
scope:
description: |-
scope is optional and required only when your identity provider doesn't have
a default scope or your groups claim is linked to a scope.
minLength: 1
type: string
subClaimName:
description: subClaimName specifies name of claim
in JWT to use for the subject.
minLength: 1
type: string
tokenEndpointUri:
description: |-
tokenBaseEndpointUri specifies the base uri for token endpoint.
This is required for OAuth for inter broker communication along with
clientId & clientSecret in JassConfig or JassConfigPassthrough
minLength: 1
type: string
type: object
directoryPathInContainer:
description: directoryPathInContainer allows to pass the
basic credential through a directory path in the container.
minLength: 1
type: string
secretRef:
description: secretRef defines secret reference to pass
the required credentials.
maxLength: 30
minLength: 1
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
type: string
required:
- configuration
type: object
type:
description: type specifies the REST API authentication type.
Valid options are `basic`, `bearer`, `mtls` and `oauth`.
enum:
- basic
- bearer
- mtls
- oauth
type: string
required:
- type
type: object
endpoint:
description: endpoint specifies where Confluent REST API is running.
minLength: 1
pattern: ^https?://.*
type: string
kafkaClusterID:
description: |-
kafkaClusterID specifies the id of Kafka cluster.
It takes precedence over using the Kafka REST API to get the cluster id.
minLength: 1
type: string
tls:
description: "tls specifies the custom TLS structure for the application
resources,\n\t// e.g. connector, topic, schema, of the Confluent
Platform components.\n\t// +optional"
properties:
directoryPathInContainer:
description: |-
directoryPathInContainer contains the directory path in the container where
`keystore.jks`, `truststore.jks`, `jksPassword.txt` keys are mounted.
minLength: 1
type: string
jksPassword:
description: jksPassword specifies the secret name that contains
the JKS password.
properties:
secretRef:
description: |-
secretRef references the name of the secret containing the JKS password.
More info: https://docs.confluent.io/operator/current/co-network-encryption.html#configure-user-provided-tls-certificates
maxLength: 30
minLength: 1
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
type: string
required:
- secretRef
type: object
secretRef:
description: |-
secretRef specifies the secret name that contains the certificates.
More info about certificates key/value format: https://docs.confluent.io/operator/current/co-network-encryption.html#configure-user-provided-tls-certificates
maxLength: 63
minLength: 1
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
type: string
type: object
type: object
kafkaRestClassRef:
description: kafkaRestClassRef references the KafkaRestClass which
defines Kafka REST API connection information.
properties:
name:
description: name specifies the name of the KafkaRestClass application
resource.
minLength: 1
type: string
namespace:
description: namespace specifies the namespace of the KafkaRestClass.
type: string
required:
- name
type: object
name:
description: |-
name specifies the topic name. If not configured, the KafkaTopic CR name is used
as the topic name.
maxLength: 255
minLength: 1
pattern: ^[a-zA-Z0-9\._\-]*$
type: string
partitionCount:
description: |-
partitionCount specifies the number of partitions for the topic.
If not configured, it will be defaulted to the partition count that Kafka REST V3 API supports.
format: int32
type: integer
replicas:
description: |-
replicas specifies the replication factor for the topic.
If not configured, it will be defaulted to the replication factor that Kafka REST V3 API supports.
format: int32
type: integer
type: object
status:
description: status defines the observed state of the KafkaTopic.
properties:
appState:
default: Unknown
description: appState is the current state of the topic application.
enum:
- Unknown
- Created
- Failed
- Deleted
type: string
conditions:
description: conditions are the latest available observed states of
the topic.
items:
description: Condition represent the latest available observations
of the current state.
properties:
lastProbeTime:
description: lastProbeTime shows the last time the condition
was evaluated.
format: date-time
type: string
lastTransitionTime:
description: lastTransitionTime shows the last time the condition
was transitioned from one status to another.
format: date-time
type: string
message:
description: message shows a human-readable message with details
about the transition.
type: string
reason:
description: reason shows the reason for the last transition
of the condition.
type: string
status:
description: status shows the status of the condition, one of
`True`, `False`, or `Unknown`.
type: string
type:
description: type shows the condition type.
type: string
type: object
type: array
kafkaCluster:
type: string
kafkaClusterID:
description: kafkaClusterID is the id of the Kafka cluster.
type: string
kafkaRestEndpoint:
description: kafkaRestEndpoint is the endpoint of the Kafka REST API.
type: string
observedGeneration:
description: observedGeneration is the most recent generation observed
for this Confluent component.
format: int64
type: integer
partitionCount:
description: partitionCount is the partition count of the topic.
format: int32
type: integer
replicas:
description: replicas is the replication factor of the topic.
format: int32
type: integer
state:
description: state is the state of the topic.
type: string
type: object
type: object
served: true
storage: true
subresources:
status: {}

View File

@ -0,0 +1,180 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.15.0
name: kraftmigrationjobs.platform.confluent.io
spec:
group: platform.confluent.io
names:
categories:
- all
- confluent-platform
- confluent
kind: KRaftMigrationJob
listKind: KRaftMigrationJobList
plural: kraftmigrationjobs
shortNames:
- kraftmigrationjob
- kmj
singular: kraftmigrationjob
scope: Namespaced
versions:
- additionalPrinterColumns:
- jsonPath: .status.phase
name: Status
type: string
- jsonPath: .metadata.creationTimestamp
name: Age
type: date
name: v1beta1
schema:
openAPIV3Schema:
description: KRaftMigrationJob is the schema for the KRaftMigrationJob API.
properties:
apiVersion:
description: |-
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
type: string
kind:
description: |-
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
metadata:
type: object
spec:
description: spec defines the desired state of the KRaftMigrationJob.
properties:
dependencies:
description: dependencies specify the Kafka Broker, Zookeeper and
KRaft Controllers.
properties:
kRaftController:
description: |-
kRaftController specifies the dependency configuration for the KRaftController cluster.
You cannot configure both zookeeper and kRaftController dependencies.
properties:
name:
description: name specifies the name of the Confluent Platform
component cluster.
type: string
namespace:
description: namespace specifies the namespace where the Confluent
Platform component cluster is running.
type: string
required:
- name
type: object
kafka:
description: kafka defines the Kafka dependency configurations.
properties:
name:
description: name specifies the name of the Confluent Platform
component cluster.
type: string
namespace:
description: namespace specifies the namespace where the Confluent
Platform component cluster is running.
type: string
required:
- name
type: object
zookeeper:
description: zookeeper specifies the dependency configuration
for Zookeeper.
properties:
name:
description: name specifies the name of the Confluent Platform
component cluster.
type: string
namespace:
description: namespace specifies the namespace where the Confluent
Platform component cluster is running.
type: string
required:
- name
type: object
required:
- kRaftController
- kafka
- zookeeper
type: object
required:
- dependencies
type: object
status:
description: status defines the observed state of the KRaftMigrationJob.
properties:
conditions:
description: conditions represents the latest available observations
of the kraft migration job.
items:
description: Condition represent the latest available observations
of the current state.
properties:
lastProbeTime:
description: lastProbeTime shows the last time the condition
was evaluated.
format: date-time
type: string
lastTransitionTime:
description: lastTransitionTime shows the last time the condition
was transitioned from one status to another.
format: date-time
type: string
message:
description: message shows a human-readable message with details
about the transition.
type: string
reason:
description: reason shows the reason for the last transition
of the condition.
type: string
status:
description: status shows the status of the condition, one of
`True`, `False`, or `Unknown`.
type: string
type:
description: type shows the condition type.
type: string
type: object
type: array
kafkaClusterId:
description: clusterId is the clusterId for migrating cluster
type: string
phase:
description: phase is the state of the kraft migration job.
type: string
subPhase:
description: subPhase is the state of the kraft migration job.
type: string
zkEndpointWithNode:
description: |-
zkEndpointWithNode is the zkEndpoint with node fetched from kafka
<host:port>/<zkNodeID>
type: string
required:
- kafkaClusterId
- phase
- subPhase
- zkEndpointWithNode
type: object
required:
- spec
type: object
served: true
storage: true
subresources:
scale:
labelSelectorPath: .status.selector
specReplicasPath: .spec.replicas
statusReplicasPath: .status.replicas
status: {}

View File

@ -0,0 +1,688 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.15.0
name: schemaexporters.platform.confluent.io
spec:
group: platform.confluent.io
names:
categories:
- all
- confluent-platform
- confluent
kind: SchemaExporter
listKind: SchemaExporterList
plural: schemaexporters
shortNames:
- se
- schemaexporter
singular: schemaexporter
scope: Namespaced
versions:
- additionalPrinterColumns:
- jsonPath: .status.contextName
name: ContextName
type: string
- jsonPath: .status.exporterStatus
name: ExporterStatus
type: string
- jsonPath: .status.state
name: Status
type: string
- jsonPath: .metadata.creationTimestamp
name: Age
type: date
- jsonPath: .status.sourceSchemaRegistry.endpoint
name: SourceSchemaRegistryEndpoint
priority: 1
type: string
- jsonPath: .status.destinationSchemaRegistry.endpoint
name: DestinationSchemaRegistryEndpoint
priority: 1
type: string
name: v1beta1
schema:
openAPIV3Schema:
description: SchemaExporter is the schema for the SchemaExporter API.
properties:
apiVersion:
description: |-
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
type: string
kind:
description: |-
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
metadata:
type: object
spec:
description: spec defines the desired state of the schema exporter.
properties:
configs:
additionalProperties:
type: string
description: |-
configs is a map of string key and value pairs. It specifies additional configurations for the schema exporter. More info:
https://docs.confluent.io/platform/current/schema-registry/schema-linking-cp.html#create-a-configuration-file-for-the-exporter
type: object
x-kubernetes-map-type: granular
contextName:
description: |-
contextName specifies the custom context name in the destination Schema Registry cluster where the
schemas will be exported. If this is defined, contextType will be ignored. If this is not defined,
schemas will be exported to context in destination based on contextType.
type: string
contextType:
description: |-
contextType specifies the type of context created in the destination Schema Registry cluster of
the schema exporter.
Valid options are `AUTO` and `NONE`.
The default value is `AUTO`.
enum:
- AUTO
- NONE
type: string
destinationCluster:
description: |-
destinationCluster specifies the destination Schema Registry cluster. If this is not defined,
sourceCluster is chosen as the destination and the schema exporter will be exporting
schemas across contexts within the sourceCluster.
Schema exporter should be enabled in Schema Registry cluster CR with `spec.enableSchemaExporter`.
properties:
schemaRegistryClusterRef:
description: schemaRegistryClusterRef references the CFK-managed
Schema Registry cluster.
properties:
name:
description: name specifies the name of the Confluent Platform
component cluster.
type: string
namespace:
description: namespace specifies the namespace where the Confluent
Platform component cluster is running.
type: string
required:
- name
type: object
schemaRegistryRest:
description: schemaRegistryRest specifies the Schema Registry
REST API configuration.
properties:
authentication:
description: authentication specifies the REST API authentication
mechanism.
properties:
basic:
description: basic specifies the basic authentication
settings for the REST API client.
properties:
debug:
description: debug enables the basic authentication
debug logs for JaaS configuration.
type: boolean
directoryPathInContainer:
description: |-
directoryPathInContainer allows to pass the basic credential through a directory path in the container.
More info: https://docs.confluent.io/operator/current/co-authenticate.html#basic-authentication
minLength: 1
type: string
restrictedRoles:
description: |-
restrictedRoles specify the restricted roles on the server side only.
Changes will be only reflected in Control Center.
This configuration is ignored on the client side configuration.
items:
type: string
minItems: 1
type: array
roles:
description: |-
roles specify the roles on the server side only.
This configuration is ignored on the client side configuration.
items:
type: string
type: array
secretRef:
description: |-
secretRef defines secret reference to pass the required credentials.
More info: https://docs.confluent.io/operator/current/co-authenticate.html#basic-authentication
maxLength: 30
minLength: 1
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
type: string
type: object
bearer:
description: bearer specifies the bearer authentication
settings for the REST API client.
properties:
directoryPathInContainer:
description: |-
directoryPathInContainer specifies the directory path in the container
where the credential is mounted.
minLength: 1
type: string
secretRef:
description: |-
secretRef specifies the name of the secret that contains the credential.
More info: https://docs.confluent.io/operator/current/co-authenticate.html#bearer-authentication
maxLength: 30
minLength: 1
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
type: string
type: object
oauth:
description: oauth specifies the OAuth authentication
settings for the REST API client.
properties:
configuration:
description: configuration specifies the OAuth server
settings.
properties:
audience:
description: audience specifies the audience claim
in the JWT payload.
minLength: 1
type: string
expectedIssuer:
description: expectedIssuer specifies the expected
issuer in the JWT payload.
minLength: 1
type: string
groupsClaimName:
description: groupsClaimName specifies the name
of claim in token for identifying the groups
of subject in the JWT payload.
minLength: 1
type: string
jwksEndpointUri:
description: |-
jwksEndpointUri specifies the uri for the JSON Web Key Set (JWKS).
It is used to get set of keys containing the public keys used to verify any JWT issued by the IdP's Authorization Server.
minLength: 1
type: string
loginConnectTimeoutMs:
description: LoginConnectTimeoutMs sets connect
timeout with IDP in ms
format: int32
type: integer
loginReadTimeoutMs:
description: LoginReadTimeoutMs sets read timeout
with IDP in ms
format: int32
type: integer
loginRetryBackoffMaxMs:
description: LoginRetryBackoffMaxMs sets max retry
backoff with IDP in ms
format: int32
type: integer
loginRetryBackoffMs:
description: LoginRetryBackoffMs sets retry backoff
with IDP in ms
format: int32
type: integer
scope:
description: |-
scope is optional and required only when your identity provider doesn't have
a default scope or your groups claim is linked to a scope.
minLength: 1
type: string
subClaimName:
description: subClaimName specifies name of claim
in JWT to use for the subject.
minLength: 1
type: string
tokenEndpointUri:
description: |-
tokenBaseEndpointUri specifies the base uri for token endpoint.
This is required for OAuth for inter broker communication along with
clientId & clientSecret in JassConfig or JassConfigPassthrough
minLength: 1
type: string
type: object
directoryPathInContainer:
description: directoryPathInContainer allows to pass
the basic credential through a directory path in
the container.
minLength: 1
type: string
secretRef:
description: secretRef defines secret reference to
pass the required credentials.
maxLength: 30
minLength: 1
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
type: string
required:
- configuration
type: object
type:
description: type specifies the REST API authentication
type. Valid options are `basic`, `bearer`, `mtls` and
`oauth`.
enum:
- basic
- bearer
- mtls
- oauth
type: string
required:
- type
type: object
endpoint:
description: endpoint specifies where Confluent REST API is
running.
minLength: 1
pattern: ^https?://.*
type: string
kafkaClusterID:
description: |-
kafkaClusterID specifies the id of Kafka cluster.
It takes precedence over using the Kafka REST API to get the cluster id.
minLength: 1
type: string
tls:
description: "tls specifies the custom TLS structure for the
application resources,\n\t// e.g. connector, topic, schema,
of the Confluent Platform components.\n\t// +optional"
properties:
directoryPathInContainer:
description: |-
directoryPathInContainer contains the directory path in the container where
`keystore.jks`, `truststore.jks`, `jksPassword.txt` keys are mounted.
minLength: 1
type: string
jksPassword:
description: jksPassword specifies the secret name that
contains the JKS password.
properties:
secretRef:
description: |-
secretRef references the name of the secret containing the JKS password.
More info: https://docs.confluent.io/operator/current/co-network-encryption.html#configure-user-provided-tls-certificates
maxLength: 30
minLength: 1
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
type: string
required:
- secretRef
type: object
secretRef:
description: |-
secretRef specifies the secret name that contains the certificates.
More info about certificates key/value format: https://docs.confluent.io/operator/current/co-network-encryption.html#configure-user-provided-tls-certificates
maxLength: 63
minLength: 1
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
type: string
type: object
type: object
type: object
sourceCluster:
description: |-
sourceCluster specifies the source Schema Registry cluster. Schema exporter will be set
up in the source cluster. If this is not defined, controller will try to auto discover Schema Registry
in the namespace of the schema exporter. If it cannot discover a Schema Registry cluster or more than
one Schema Registry clusters are found, controller will return error.
Schema exporter should be enabled in Schema Registry cluster CR with `spec.enableSchemaExporter`.
properties:
schemaRegistryClusterRef:
description: schemaRegistryClusterRef references the CFK-managed
Schema Registry cluster.
properties:
name:
description: name specifies the name of the Confluent Platform
component cluster.
type: string
namespace:
description: namespace specifies the namespace where the Confluent
Platform component cluster is running.
type: string
required:
- name
type: object
schemaRegistryRest:
description: schemaRegistryRest specifies the Schema Registry
REST API configuration.
properties:
authentication:
description: authentication specifies the REST API authentication
mechanism.
properties:
basic:
description: basic specifies the basic authentication
settings for the REST API client.
properties:
debug:
description: debug enables the basic authentication
debug logs for JaaS configuration.
type: boolean
directoryPathInContainer:
description: |-
directoryPathInContainer allows to pass the basic credential through a directory path in the container.
More info: https://docs.confluent.io/operator/current/co-authenticate.html#basic-authentication
minLength: 1
type: string
restrictedRoles:
description: |-
restrictedRoles specify the restricted roles on the server side only.
Changes will be only reflected in Control Center.
This configuration is ignored on the client side configuration.
items:
type: string
minItems: 1
type: array
roles:
description: |-
roles specify the roles on the server side only.
This configuration is ignored on the client side configuration.
items:
type: string
type: array
secretRef:
description: |-
secretRef defines secret reference to pass the required credentials.
More info: https://docs.confluent.io/operator/current/co-authenticate.html#basic-authentication
maxLength: 30
minLength: 1
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
type: string
type: object
bearer:
description: bearer specifies the bearer authentication
settings for the REST API client.
properties:
directoryPathInContainer:
description: |-
directoryPathInContainer specifies the directory path in the container
where the credential is mounted.
minLength: 1
type: string
secretRef:
description: |-
secretRef specifies the name of the secret that contains the credential.
More info: https://docs.confluent.io/operator/current/co-authenticate.html#bearer-authentication
maxLength: 30
minLength: 1
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
type: string
type: object
oauth:
description: oauth specifies the OAuth authentication
settings for the REST API client.
properties:
configuration:
description: configuration specifies the OAuth server
settings.
properties:
audience:
description: audience specifies the audience claim
in the JWT payload.
minLength: 1
type: string
expectedIssuer:
description: expectedIssuer specifies the expected
issuer in the JWT payload.
minLength: 1
type: string
groupsClaimName:
description: groupsClaimName specifies the name
of claim in token for identifying the groups
of subject in the JWT payload.
minLength: 1
type: string
jwksEndpointUri:
description: |-
jwksEndpointUri specifies the uri for the JSON Web Key Set (JWKS).
It is used to get set of keys containing the public keys used to verify any JWT issued by the IdP's Authorization Server.
minLength: 1
type: string
loginConnectTimeoutMs:
description: LoginConnectTimeoutMs sets connect
timeout with IDP in ms
format: int32
type: integer
loginReadTimeoutMs:
description: LoginReadTimeoutMs sets read timeout
with IDP in ms
format: int32
type: integer
loginRetryBackoffMaxMs:
description: LoginRetryBackoffMaxMs sets max retry
backoff with IDP in ms
format: int32
type: integer
loginRetryBackoffMs:
description: LoginRetryBackoffMs sets retry backoff
with IDP in ms
format: int32
type: integer
scope:
description: |-
scope is optional and required only when your identity provider doesn't have
a default scope or your groups claim is linked to a scope.
minLength: 1
type: string
subClaimName:
description: subClaimName specifies name of claim
in JWT to use for the subject.
minLength: 1
type: string
tokenEndpointUri:
description: |-
tokenBaseEndpointUri specifies the base uri for token endpoint.
This is required for OAuth for inter broker communication along with
clientId & clientSecret in JassConfig or JassConfigPassthrough
minLength: 1
type: string
type: object
directoryPathInContainer:
description: directoryPathInContainer allows to pass
the basic credential through a directory path in
the container.
minLength: 1
type: string
secretRef:
description: secretRef defines secret reference to
pass the required credentials.
maxLength: 30
minLength: 1
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
type: string
required:
- configuration
type: object
type:
description: type specifies the REST API authentication
type. Valid options are `basic`, `bearer`, `mtls` and
`oauth`.
enum:
- basic
- bearer
- mtls
- oauth
type: string
required:
- type
type: object
endpoint:
description: endpoint specifies where Confluent REST API is
running.
minLength: 1
pattern: ^https?://.*
type: string
kafkaClusterID:
description: |-
kafkaClusterID specifies the id of Kafka cluster.
It takes precedence over using the Kafka REST API to get the cluster id.
minLength: 1
type: string
tls:
description: "tls specifies the custom TLS structure for the
application resources,\n\t// e.g. connector, topic, schema,
of the Confluent Platform components.\n\t// +optional"
properties:
directoryPathInContainer:
description: |-
directoryPathInContainer contains the directory path in the container where
`keystore.jks`, `truststore.jks`, `jksPassword.txt` keys are mounted.
minLength: 1
type: string
jksPassword:
description: jksPassword specifies the secret name that
contains the JKS password.
properties:
secretRef:
description: |-
secretRef references the name of the secret containing the JKS password.
More info: https://docs.confluent.io/operator/current/co-network-encryption.html#configure-user-provided-tls-certificates
maxLength: 30
minLength: 1
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
type: string
required:
- secretRef
type: object
secretRef:
description: |-
secretRef specifies the secret name that contains the certificates.
More info about certificates key/value format: https://docs.confluent.io/operator/current/co-network-encryption.html#configure-user-provided-tls-certificates
maxLength: 63
minLength: 1
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
type: string
type: object
type: object
type: object
subjectRenameFormat:
description: |-
subjectRenameFormat specifies the rename format for the subjects exported to the destination.
For example, if the value is `my-${subject}`, subjects at destination will become `my-firstSubject`
where `firstSubject` is the original subject name.
type: string
subjects:
description: |-
subjects specifies the list of subjects to be exported by schema exporter.
The default value is `["*"]`. This indicates all subjects in the default context.
items:
type: string
type: array
type: object
status:
description: status defines the observed state of the schema exporter.
properties:
appState:
default: Unknown
description: appState is the current state of the schema exporter
application.
enum:
- Unknown
- Created
- Failed
- Deleted
type: string
conditions:
description: conditions are the latest available observations of the
schema exporter's state.
items:
description: Condition represent the latest available observations
of the current state.
properties:
lastProbeTime:
description: lastProbeTime shows the last time the condition
was evaluated.
format: date-time
type: string
lastTransitionTime:
description: lastTransitionTime shows the last time the condition
was transitioned from one status to another.
format: date-time
type: string
message:
description: message shows a human-readable message with details
about the transition.
type: string
reason:
description: reason shows the reason for the last transition
of the condition.
type: string
status:
description: status shows the status of the condition, one of
`True`, `False`, or `Unknown`.
type: string
type:
description: type shows the condition type.
type: string
type: object
type: array
contextName:
description: |-
contextName shows the name of the context in the destination Schema Registry cluster
where the schemas will be exported.
type: string
contextType:
description: contextType is the contextType of the schema exporter.
type: string
destinationSchemaRegistry:
description: |-
destinationSchemaRegistry shows the destination Schema Registry endpoint, authentication type
and if it is using TLS.
properties:
authenticationType:
description: authenticationType is the authentication method used
for Schema Registry.
type: string
endpoint:
description: endpoint is the Schema Registry REST endpoint.
type: string
tls:
description: tls shows whether the Schema Registry is using TLS.
type: boolean
type: object
exporterStatus:
description: exporterStatus is the status of the schema exporter.
type: string
observedGeneration:
description: observedGeneration is the most recent generation observed
for this Confluent component.
format: int64
type: integer
sourceSchemaRegistry:
description: |-
sourceSchemaRegistry shows the source Schema Registry endpoint, authentication type
and if it is using TLS.
properties:
authenticationType:
description: authenticationType is the authentication method used
for Schema Registry.
type: string
endpoint:
description: endpoint is the Schema Registry REST endpoint.
type: string
tls:
description: tls shows whether the Schema Registry is using TLS.
type: boolean
type: object
state:
description: state is the current state of the schema exporter.
type: string
subjects:
description: subjects is the list of subjects exported by the schema
exporter.
items:
type: string
type: array
type: object
type: object
served: true
storage: true
subresources:
status: {}

View File

@ -0,0 +1,590 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.15.0
name: schemas.platform.confluent.io
spec:
group: platform.confluent.io
names:
categories:
- all
- confluent-platform
- confluent
kind: Schema
listKind: SchemaList
plural: schemas
shortNames:
- schema
singular: schema
scope: Namespaced
versions:
- additionalPrinterColumns:
- jsonPath: .status.format
name: Format
type: string
- jsonPath: .status.id
name: ID
type: string
- jsonPath: .status.version
name: Version
type: string
- jsonPath: .status.phase
name: Status
type: string
- jsonPath: .metadata.creationTimestamp
name: Age
type: date
- jsonPath: .status.schemaRegistryEndpoint
name: SchemaRegistryEndpoint
priority: 1
type: string
name: v1beta1
schema:
openAPIV3Schema:
properties:
apiVersion:
description: |-
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
type: string
kind:
description: |-
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
metadata:
type: object
spec:
description: spec defines the desired state of the Schema.
properties:
compatibilityLevel:
description: |-
compatibilityLevel specifies the compatibility level requirement for the schema under the specified subject.
Valid options are `BACKWARD`, `BACKWARD_TRANSITIVE`, `FORWARD`, `FORWARD_TRANSITIVE`, `FULL`, `FULL_TRANSITIVE` and `NONE`.
more info: https://docs.confluent.io/platform/current/schema-registry/avro.html#schema-evolution-and-compatibility
enum:
- BACKWARD
- BACKWARD_TRANSITIVE
- FORWARD
- FORWARD_TRANSITIVE
- FULL
- FULL_TRANSITIVE
- NONE
type: string
data:
description: data defines the data required to create the schema.
properties:
configRef:
description: configRef is the name of the Kubernetes ConfigMap
resource containing the schema.
minLength: 1
type: string
format:
description: format is the format type of the encoded schema.
Valid options are `avro`, `json`, and `protobuf`.
enum:
- avro
- json
- protobuf
minLength: 1
type: string
required:
- configRef
- format
type: object
mode:
description: |-
Mode specifies the schema registry mode for the schemas under the specified subject.
Valid options are `IMPORT`, `READONLY`, `READWRITE`.
enum:
- IMPORT
- READONLY
- READWRITE
type: string
name:
description: |-
name specifies the subject name of schema. If not configured, the Schema CR name is used
as the subject name.
maxLength: 255
minLength: 1
pattern: ^[^\\]*$
type: string
normalize:
description: |-
Normalize specifies whether to normalize the schema at the time of registering to schema registry.
more info: https://docs.confluent.io/platform/current/schema-registry/fundamentals/serdes-develop/index.html#schema-normalization
type: boolean
schemaReferences:
description: schemaReferences defines the schema references in the
schema data.
items:
description: SchemaReference is the schema to be used as a reference
for the new schema.
properties:
avro:
description: avro is the data for the referenced Avro schema.
properties:
avro:
description: name is the fully qualified name of the referenced
Avro schema.
minLength: 1
type: string
required:
- avro
type: object
format:
description: format is the format type of the referenced schema.
Valid options are `avro`, `json`, and `protobuf`.
enum:
- avro
- json
- protobuf
minLength: 1
type: string
json:
description: json is the data for the referenced JSON schema.
properties:
url:
description: url is the referenced JSON schema url.
minLength: 1
type: string
required:
- url
type: object
protobuf:
description: protobuf is the data for the referenced Protobuf
schema.
properties:
file:
description: file is the file name of the referenced Protobuf
schema.
minLength: 1
type: string
required:
- file
type: object
subject:
description: subject is the subject name for the referenced
schema through the configRef.
minLength: 1
type: string
version:
description: version is the version type of the referenced schema.
format: int32
type: integer
required:
- format
- subject
- version
type: object
type: array
schemaRegistryClusterRef:
description: schemaRegistryClusterRef references the CFK-managed Schema
Registry cluster.
properties:
name:
description: name specifies the name of the Confluent Platform
component cluster.
type: string
namespace:
description: namespace specifies the namespace where the Confluent
Platform component cluster is running.
type: string
required:
- name
type: object
schemaRegistryRest:
description: schemaRegistryRest specifies the Schema Registry REST
API configuration.
properties:
authentication:
description: authentication specifies the REST API authentication
mechanism.
properties:
basic:
description: basic specifies the basic authentication settings
for the REST API client.
properties:
debug:
description: debug enables the basic authentication debug
logs for JaaS configuration.
type: boolean
directoryPathInContainer:
description: |-
directoryPathInContainer allows to pass the basic credential through a directory path in the container.
More info: https://docs.confluent.io/operator/current/co-authenticate.html#basic-authentication
minLength: 1
type: string
restrictedRoles:
description: |-
restrictedRoles specify the restricted roles on the server side only.
Changes will be only reflected in Control Center.
This configuration is ignored on the client side configuration.
items:
type: string
minItems: 1
type: array
roles:
description: |-
roles specify the roles on the server side only.
This configuration is ignored on the client side configuration.
items:
type: string
type: array
secretRef:
description: |-
secretRef defines secret reference to pass the required credentials.
More info: https://docs.confluent.io/operator/current/co-authenticate.html#basic-authentication
maxLength: 30
minLength: 1
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
type: string
type: object
bearer:
description: bearer specifies the bearer authentication settings
for the REST API client.
properties:
directoryPathInContainer:
description: |-
directoryPathInContainer specifies the directory path in the container
where the credential is mounted.
minLength: 1
type: string
secretRef:
description: |-
secretRef specifies the name of the secret that contains the credential.
More info: https://docs.confluent.io/operator/current/co-authenticate.html#bearer-authentication
maxLength: 30
minLength: 1
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
type: string
type: object
oauth:
description: oauth specifies the OAuth authentication settings
for the REST API client.
properties:
configuration:
description: configuration specifies the OAuth server
settings.
properties:
audience:
description: audience specifies the audience claim
in the JWT payload.
minLength: 1
type: string
expectedIssuer:
description: expectedIssuer specifies the expected
issuer in the JWT payload.
minLength: 1
type: string
groupsClaimName:
description: groupsClaimName specifies the name of
claim in token for identifying the groups of subject
in the JWT payload.
minLength: 1
type: string
jwksEndpointUri:
description: |-
jwksEndpointUri specifies the uri for the JSON Web Key Set (JWKS).
It is used to get set of keys containing the public keys used to verify any JWT issued by the IdP's Authorization Server.
minLength: 1
type: string
loginConnectTimeoutMs:
description: LoginConnectTimeoutMs sets connect timeout
with IDP in ms
format: int32
type: integer
loginReadTimeoutMs:
description: LoginReadTimeoutMs sets read timeout
with IDP in ms
format: int32
type: integer
loginRetryBackoffMaxMs:
description: LoginRetryBackoffMaxMs sets max retry
backoff with IDP in ms
format: int32
type: integer
loginRetryBackoffMs:
description: LoginRetryBackoffMs sets retry backoff
with IDP in ms
format: int32
type: integer
scope:
description: |-
scope is optional and required only when your identity provider doesn't have
a default scope or your groups claim is linked to a scope.
minLength: 1
type: string
subClaimName:
description: subClaimName specifies name of claim
in JWT to use for the subject.
minLength: 1
type: string
tokenEndpointUri:
description: |-
tokenBaseEndpointUri specifies the base uri for token endpoint.
This is required for OAuth for inter broker communication along with
clientId & clientSecret in JassConfig or JassConfigPassthrough
minLength: 1
type: string
type: object
directoryPathInContainer:
description: directoryPathInContainer allows to pass the
basic credential through a directory path in the container.
minLength: 1
type: string
secretRef:
description: secretRef defines secret reference to pass
the required credentials.
maxLength: 30
minLength: 1
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
type: string
required:
- configuration
type: object
type:
description: type specifies the REST API authentication type.
Valid options are `basic`, `bearer`, `mtls` and `oauth`.
enum:
- basic
- bearer
- mtls
- oauth
type: string
required:
- type
type: object
endpoint:
description: endpoint specifies where Confluent REST API is running.
minLength: 1
pattern: ^https?://.*
type: string
kafkaClusterID:
description: |-
kafkaClusterID specifies the id of Kafka cluster.
It takes precedence over using the Kafka REST API to get the cluster id.
minLength: 1
type: string
tls:
description: "tls specifies the custom TLS structure for the application
resources,\n\t// e.g. connector, topic, schema, of the Confluent
Platform components.\n\t// +optional"
properties:
directoryPathInContainer:
description: |-
directoryPathInContainer contains the directory path in the container where
`keystore.jks`, `truststore.jks`, `jksPassword.txt` keys are mounted.
minLength: 1
type: string
jksPassword:
description: jksPassword specifies the secret name that contains
the JKS password.
properties:
secretRef:
description: |-
secretRef references the name of the secret containing the JKS password.
More info: https://docs.confluent.io/operator/current/co-network-encryption.html#configure-user-provided-tls-certificates
maxLength: 30
minLength: 1
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
type: string
required:
- secretRef
type: object
secretRef:
description: |-
secretRef specifies the secret name that contains the certificates.
More info about certificates key/value format: https://docs.confluent.io/operator/current/co-network-encryption.html#configure-user-provided-tls-certificates
maxLength: 63
minLength: 1
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
type: string
type: object
type: object
required:
- data
type: object
status:
description: status defines the observed state of the Schema.
properties:
appState:
default: Unknown
description: appState is the current state of the Schema application.
enum:
- Unknown
- Created
- Failed
- Deleted
type: string
compatibilityLevel:
description: compatibilityLevel specifies the compatibility level
of the schema under the subject.
type: string
conditions:
description: conditions are the latest available observed state of
the schema.
items:
description: Condition represent the latest available observations
of the current state.
properties:
lastProbeTime:
description: lastProbeTime shows the last time the condition
was evaluated.
format: date-time
type: string
lastTransitionTime:
description: lastTransitionTime shows the last time the condition
was transitioned from one status to another.
format: date-time
type: string
message:
description: message shows a human-readable message with details
about the transition.
type: string
reason:
description: reason shows the reason for the last transition
of the condition.
type: string
status:
description: status shows the status of the condition, one of
`True`, `False`, or `Unknown`.
type: string
type:
description: type shows the condition type.
type: string
type: object
type: array
deletedVersions:
description: deletedVersions are the successfully hard deleted versions
for the subject.
items:
format: int32
type: integer
type: array
format:
description: format is the format of the latest schema for the subject.
type: string
id:
description: id is the id of the latest schema for the subject.
format: int32
type: integer
mode:
description: Mode specifies the operating mode of schema under the
subject.
type: string
normalize:
description: Normalize specifies whether schema has been normalized
at the time of registering.
type: boolean
observedGeneration:
description: observedGeneration is the most recent generation observed
for this Confluent component.
format: int64
type: integer
schemaReferences:
description: schemaReferences are the schema references for the subject.
items:
description: SchemaReference is the schema to be used as a reference
for the new schema.
properties:
avro:
description: avro is the data for the referenced Avro schema.
properties:
avro:
description: name is the fully qualified name of the referenced
Avro schema.
minLength: 1
type: string
required:
- avro
type: object
format:
description: format is the format type of the referenced schema.
Valid options are `avro`, `json`, and `protobuf`.
enum:
- avro
- json
- protobuf
minLength: 1
type: string
json:
description: json is the data for the referenced JSON schema.
properties:
url:
description: url is the referenced JSON schema url.
minLength: 1
type: string
required:
- url
type: object
protobuf:
description: protobuf is the data for the referenced Protobuf
schema.
properties:
file:
description: file is the file name of the referenced Protobuf
schema.
minLength: 1
type: string
required:
- file
type: object
subject:
description: subject is the subject name for the referenced
schema through the configRef.
minLength: 1
type: string
version:
description: version is the version type of the referenced schema.
format: int32
type: integer
required:
- format
- subject
- version
type: object
type: array
schemaRegistryAuthenticationType:
description: schemaRegistryAuthenticationType is the authentication
method used.
type: string
schemaRegistryEndpoint:
description: schemaRegistryEndpoint is the Schema Registry REST endpoint.
type: string
schemaRegistryTLS:
description: schemaRegistryTLS shows whether the Schema Registry is
using TLS.
type: boolean
softDeletedVersions:
description: softDeletedVersions are the successfully soft deleted
versions for the subject.
items:
format: int32
type: integer
type: array
state:
description: state is the state of the Schema CR.
type: string
subject:
description: subject is the subject of the schema.
type: string
version:
description: version is the version of the latest schema for the subject.
format: int32
type: integer
type: object
required:
- spec
type: object
served: true
storage: true
subresources:
status: {}

View File

@ -0,0 +1,4 @@
The Confluent Operator
The Confluent Operator brings the component (Confluent Services) specific controllers for kubernetes by providing components specific Custom Resource
Definition (CRD) as well as managing other Confluent Platform services

View File

@ -0,0 +1,42 @@
{{/* vim: set filetype=mustache: */}}
{{/*
Expand the name of the chart.
*/}}
{{- define "confluent-operator.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
*/}}
{{- define "confluent-operator.fullname" -}}
{{- if .Values.fullnameOverride -}}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- $name := default .Chart.Name .Values.nameOverride -}}
{{- if contains $name .Release.Name -}}
{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{/*
Create the name of the service account to use
*/}}
{{- define "confluent-operator.service-account" -}}
{{- if .Values.serviceAccount.create -}}
{{ default (include "confluent-operator.name" .) .Values.serviceAccount.name }}
{{- else -}}
{{ default "default" .Values.serviceAccount.name }}
{{- end -}}
{{- end -}}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "confluent-operator.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
{{- end -}}

View File

@ -0,0 +1,172 @@
{{- if .Values.rbac }}
{{- $clusterRole := or (not .Values.namespaced) (.Values.kRaftEnabled) (gt (len .Values.namespaceList) 0)}}
apiVersion: rbac.authorization.k8s.io/v1
{{- if not $clusterRole }}
kind: Role
{{- else }}
kind: ClusterRole
{{- end }}
metadata:
labels:
app: {{ include "confluent-operator.name" . }}
app.kubernetes.io/name: {{ include "confluent-operator.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
app.kubernetes.io/component: "confluent-operator"
helm.sh/chart: {{ include "confluent-operator.chart" . }}
name: {{ .Values.name }}
{{- if not $clusterRole }}
namespace: {{ .Release.Namespace }}
{{- end }}
rules:
- apiGroups:
- platform.confluent.io
resources:
- '*'
verbs:
- '*'
- apiGroups:
- policy
resources:
- poddisruptionbudgets
verbs:
- get
- list
- watch
- create
- update
- patch
- delete
{{- if .Values.clusterRole.openshift }}
- apiGroups:
- route.openshift.io
resources:
- routes
- routes/custom-host
verbs:
- get
- list
- watch
- create
- update
- patch
- delete
{{- end }}
- apiGroups:
- apps
resources:
- statefulsets
- statefulsets/scale
- statefulsets/status
verbs:
- get
- list
- watch
- create
- update
- patch
- delete
- apiGroups:
- apps
resources:
- deployments
verbs:
- get
- apiGroups:
- ""
resources:
- configmaps
- persistentvolumeclaims
- persistentvolumes
- secrets
- secrets/finalizers
- pods
- services
verbs:
- get
- list
- watch
- create
- update
- patch
- delete
{{- if gt (int (.Values.replicas)) 1 }}
- apiGroups:
- coordination.k8s.io
resources:
- leases
verbs:
- create
- get
- update
{{- end }}
- apiGroups:
- ""
resources:
- events
verbs:
- create
- patch
- apiGroups:
- networking.k8s.io
resources:
- ingresses
- ingresses/status
verbs:
- get
- list
- watch
- create
- update
- patch
- delete
- apiGroups:
- ""
resources:
- namespaces
verbs:
- get
{{- if $clusterRole }}
- list
- watch
{{- end }}
{{- if .Values.webhooks.enabled }}
# Webhook configurations are cluster scoped
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
app: {{ include "confluent-operator.name" . }}
app.kubernetes.io/name: {{ include "confluent-operator.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
app.kubernetes.io/component: "confluent-operator"
helm.sh/chart: {{ include "confluent-operator.chart" . }}
name: {{ .Values.name }}-webhook-{{ .Release.Namespace }}
rules:
- apiGroups:
- admissionregistration.k8s.io
resources:
- validatingwebhookconfigurations
verbs:
- get
- update
- apiGroups:
- ""
resources:
- persistentvolumes
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- namespaces
verbs:
- get
- list
- watch
{{- end }}
{{- end }}

View File

@ -0,0 +1,56 @@
{{- if .Values.rbac }}
{{- $clusterRoleBinding := or (not .Values.namespaced) (.Values.kRaftEnabled) (gt (len .Values.namespaceList) 0)}}
{{- if not $clusterRoleBinding }}
kind: RoleBinding
{{- else }}
kind: ClusterRoleBinding
{{- end }}
apiVersion: rbac.authorization.k8s.io/v1
metadata:
labels:
app: {{ include "confluent-operator.name" . }}
app.kubernetes.io/name: {{ include "confluent-operator.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
app.kubernetes.io/component: "confluent-operator"
helm.sh/chart: {{ include "confluent-operator.chart" . }}
name: {{ .Values.name }}
{{- if not $clusterRoleBinding }}
namespace: {{ .Release.Namespace }}
{{- end }}
subjects:
- kind: ServiceAccount
name: {{ template "confluent-operator.service-account" . }}
namespace: {{ .Release.Namespace }}
roleRef:
{{- if not $clusterRoleBinding }}
kind: Role
{{- else }}
kind: ClusterRole
{{- end }}
name: {{ .Values.name }}
apiGroup: rbac.authorization.k8s.io
# Webhook configurations are cluster scoped
{{- if and (.Values.webhooks.enabled) }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
labels:
app: {{ include "confluent-operator.name" . }}
app.kubernetes.io/name: {{ include "confluent-operator.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
app.kubernetes.io/component: "confluent-operator"
helm.sh/chart: {{ include "confluent-operator.chart" . }}
name: {{ .Values.name }}-webhook-{{ .Release.Namespace }}
subjects:
- kind: ServiceAccount
name: {{ template "confluent-operator.service-account" . }}
namespace: {{ .Release.Namespace }}
roleRef:
kind: ClusterRole
name: {{ .Values.name }}-webhook-{{ .Release.Namespace }}
apiGroup: rbac.authorization.k8s.io
{{- end }}
{{- end }}

View File

@ -0,0 +1,238 @@
{{- $_ := required "Namespace is required" .Release.Namespace }}
{{- $_ := required "Name of operator is required." .Values.name }}
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: {{ include "confluent-operator.name" . }}
app.kubernetes.io/name: {{ include "confluent-operator.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
app.kubernetes.io/component: "confluent-operator"
helm.sh/chart: {{ include "confluent-operator.chart" . }}
version: {{ .Values.image.tag }}
name: {{ .Values.name }}
namespace: {{ .Release.Namespace }}
spec:
replicas: {{ .Values.replicas }}
selector:
matchLabels:
app.kubernetes.io/name: "confluent-operator"
app.kubernetes.io/instance: {{ .Release.Name }}
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
type: RollingUpdate
template:
metadata:
annotations:
{{- range $key, $value := .Values.pod.annotations }}
{{ $key }}: {{ $value | quote }}
{{- end }}
labels:
app: "confluent-operator"
app.kubernetes.io/name: "confluent-operator"
app.kubernetes.io/instance: {{ .Release.Name }}
confluent-platform: "true"
version: {{ .Values.image.tag }}
{{- range $key, $value := .Values.pod.labels }}
{{ $key }}: {{ $value | quote }}
{{- end }}
spec:
{{- if not (empty $.Values.affinity) }}
affinity:
{{ toYaml .Values.affinity | trim | indent 8 }}
{{- end }}
{{- if not (empty $.Values.tolerations) }}
tolerations:
{{ toYaml .Values.tolerations | trim | indent 6 }}
{{- end }}
{{- if .Values.podSecurity.enabled }}
securityContext:
{{ toYaml .Values.podSecurity.securityContext | indent 8 }}
{{- end }}
containers:
- args:
- --debug={{.Values.debug}}
- --fipsmode={{.Values.fipsmode}}
- --kraftClusterIdRecovery={{.Values.kRaftEnabled}}
{{- if gt (int (.Values.replicas)) 1 }}
- --enable-leader-election
{{- end }}
{{- if .Values.namespaced }}
{{- if empty .Values.namespaceList }}
- --namespaces={{ .Release.Namespace }}
{{- else}}
{{- $ns := "" }}
{{- range $i, $v := .Values.namespaceList }}
{{- $ns = printf "%s,%s" $ns (trim $v) }}
{{- end }}
- --namespaces={{ substr 1 (len $ns) $ns }}
{{- end }}
{{- end }}
name: {{ .Values.name }}
image: {{ .Values.image.registry }}/{{ .Values.image.repository }}:{{.Values.image.tag }}
imagePullPolicy: {{ .Values.image.pullPolicy }}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
readinessProbe:
httpGet:
port: 8080
path: /readyz
livenessProbe:
httpGet:
port: 8080
path: /healthz
resources:
{{ toYaml .Values.resources | trim | indent 10 }}
env:
- name: NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: NODEIP
valueFrom:
fieldRef:
fieldPath: status.hostIP
- name: DD_ENTITY_ID
valueFrom:
fieldRef:
fieldPath: metadata.uid
- name: DEPLOYMENT_NAME
value: {{ .Values.name }}
- name: CONFLUENT_SERVICE_ACCOUNT_NAME
value: {{ template "confluent-operator.service-account" . }}
{{- if .Values.numDay2Worker }}
- name: DEFAULT_DAY2_WORKER
value: "{{ .Values.numDay2Worker }}"
{{- end }}
{{- if .Values.managedCerts.enabled }}
{{- if and (empty .Values.managedCerts.caCertificate.secretRef) (empty .Values.managedCerts.caCertificate.directoryPathInContainer) }}
{{- $_ := required "secretRef or directoryPathInContainer must be configured when managedCerts is enabled" .Values.managedCerts.secretRef }}
{{- end }}
{{- if ge (.Values.managedCerts.renewBeforeInDays) (.Values.managedCerts.certDurationInDays) }}
{{- $_ := required "managedCerts.certDurationInDays for managed certs should be greater than managedCerts.renewBeforeInDays" "" }}
{{- end }}
{{- if .Values.managedCerts.certDurationInDays }}
- name: CONFLUENT_MANAGED_CERTS_DURATION_DAYS
value: "{{ .Values.managedCerts.certDurationInDays }}"
{{- end }}
{{- if .Values.managedCerts.renewBeforeInDays }}
- name: CONFLUENT_MANAGED_CERTS_RENEW_BEFORE_DAYS
value: "{{ .Values.managedCerts.renewBeforeInDays }}"
{{- end }}
{{- if .Values.managedCerts.sans }}
{{- if not (regexMatch "[ -~]" .Values.managedCerts.sans) }}
{{- $_ := required "invalid characters in managedCerts.sans. Only first 128 ASCII characters are allowed" "" }}
{{- end }}
- name: CONFLUENT_MANAGED_CERTS_SANS
value: "{{ .Values.managedCerts.sans }}"
{{- end }}
{{- if .Values.managedCerts.caCertificate.secretRef }}
- name: CONFLUENT_MANAGED_CERTS_SECRET_NAME
value: {{ .Values.managedCerts.caCertificate.secretRef }}
{{- end }}
{{- if .Values.managedCerts.caCertificate.directoryPathInContainer }}
- name: CONFLUENT_MANAGED_CERTS_DIRECTORY_PATH
value: {{ .Values.managedCerts.caCertificate.directoryPathInContainer }}
{{- end }}
{{- end }}
{{- if .Values.licenseSecretRef }}
- name: CONFLUENT_LICENSE_SECRET_NAME
value: {{ .Values.licenseSecretRef }}
{{- else if .Values.license.secretRef }}
- name: CONFLUENT_LICENSE_SECRET_NAME
value: {{ .Values.license.secretRef }}
{{- end }}
{{- if .Values.license.directoryPathInContainer }}
- name: CONFLUENT_LICENSE_DIRECTORY_PATH
value: {{ .Values.license.directoryPathInContainer }}
{{- end }}
{{- if or (.Values.telemetry.enabled) (.Values.telemetry.operator.enabled) }}
{{- if and (empty .Values.telemetry.secretRef) (empty .Values.telemetry.directoryPathInContainer) }}
{{- $_ := required "secretRef or directoryPathInContainer must be configured when telemetry is enabled" .Values.telemetry.secretRef }}
{{- end }}
- name: CP_TELEMETRY_ENABLED
value: {{ quote .Values.telemetry.enabled }}
- name: OPERATOR_TELEMETRY_ENABLED
value: {{ quote .Values.telemetry.operator.enabled }}
{{- if .Values.telemetry.secretRef }}
- name: CONFLUENT_TELEMETRY_SECRET_NAME
value: {{ .Values.telemetry.secretRef }}
{{- end }}
{{- if .Values.telemetry.directoryPathInContainer }}
- name: CONFLUENT_TELEMETRY_DIRECTORY_PATH
value: {{ .Values.telemetry.directoryPathInContainer }}
{{- end }}
{{- if .Values.telemetry.proxy.enabled }}
- name: CONFLUENT_TELEMETRY_PROXY_ENABLED
value: "true"
{{- end }}
{{- if .Values.telemetry.proxy.credentialRequired }}
- name: CONFLUENT_TELEMETRY_PROXY_CREDENTIAL_REQUIRED
value: "true"
{{- end }}
{{- end }}
{{- if .Values.webhooks.enabled }}
{{- if and (empty .Values.webhooks.tls.secretRef) (empty .Values.webhooks.tls.directoryPathInContainer) }}
{{- $_ := required "secretRef or directoryPathInContainer must be configured when webhooks are enabled" .Values.webhooks.tls.secretRef }}
{{- end }}
{{- if .Values.webhooks.tls.secretRef }}
- name: CONFLUENT_WEBHOOKS_SECRET_NAME
value: {{ .Values.webhooks.tls.secretRef }}
{{- end }}
{{- if .Values.webhooks.tls.directoryPathInContainer }}
- name: CONFLUENT_WEBHOOKS_DIRECTORY_PATH
value: {{ .Values.webhooks.tls.directoryPathInContainer }}
{{- end }}
- name: CONFLUENT_WEBHOOKS_PORT
value: {{ quote .Values.webhooks.port }}
{{- end }}
{{- if .Values.containerSecurity.enabled }}
securityContext:
{{ toYaml .Values.containerSecurity.securityContext | indent 10 }}
{{- end }}
{{- if or (not (empty .Values.mountedVolumes.volumeMounts)) (and (.Values.webhooks.enabled) (.Values.webhooks.tls.secretRef)) }}
volumeMounts:
{{- end }}
{{- if not (empty .Values.mountedVolumes.volumeMounts) }}
{{- range .Values.mountedVolumes.volumeMounts }}
{{- if and ($.Values.webhooks.enabled) (or (eq .mountPath "/mnt/sslcerts/webhook") (eq .name "webhook-certs")) }}
{{- $_ := fail "mount path \"/mnt/sslcerts/webhook\" and name \"webhook-certs\" are reserved for webhooks" }}
{{- end }}
- {{ toYaml . | indent 12 | trim }}
{{- end }}
{{- end }}
{{- if and (.Values.webhooks.enabled) (.Values.webhooks.tls.secretRef) }}
- mountPath: /mnt/sslcerts/webhook
name: webhook-certs
readOnly: true
{{- end }}
{{- if or (not (empty .Values.mountedVolumes.volumes)) (and (.Values.webhooks.enabled) (.Values.webhooks.tls.secretRef)) }}
volumes:
{{- end }}
{{- if not (empty .Values.mountedVolumes.volumes ) }}
{{- range .Values.mountedVolumes.volumes }}
{{- if and ($.Values.webhooks.enabled) (eq .name "webhook-certs") }}
{{- $_ := fail "name \"webhook-certs\" is reserved for webhooks" }}
{{- end }}
- {{ toYaml . | indent 10 | trim }}
{{- end }}
{{- end }}
{{- if and (.Values.webhooks.enabled) (.Values.webhooks.tls.secretRef) }}
- name: webhook-certs
secret:
defaultMode: 420
secretName: {{ .Values.webhooks.tls.secretRef }}
{{- end }}
{{- if and .Values.imagePullSecretRef (not .Values.serviceAccount.create) }}
imagePullSecrets:
- name: {{ .Values.imagePullSecretRef }}
{{- end }}
serviceAccountName: {{ template "confluent-operator.service-account" . }}
{{- if .Values.priorityClassName }}
priorityClassName: {{ .Values.priorityClassName | quote }}
{{- end }}
restartPolicy: Always
terminationGracePeriodSeconds: {{ .Values.terminationGracePeriodSeconds }}

View File

@ -0,0 +1,19 @@
{{- if not .Values.licenseSecretRef }}
apiVersion: v1
kind: Secret
metadata:
labels:
app: {{ include "confluent-operator.name" . }}
app.kubernetes.io/name: {{ include "confluent-operator.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
app.kubernetes.io/component: "confluent-operator"
helm.sh/chart: {{ include "confluent-operator.chart" . }}
namespace: {{ .Release.Namespace }}
name: confluent-operator-licensing
type: Opaque
data:
{{- if .Values.licenseKey }}
license.txt: {{ .Values.licenseKey | b64enc }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,28 @@
apiVersion: v1
kind: Service
metadata:
labels:
app: {{ include "confluent-operator.name" . }}
app.kubernetes.io/name: {{ include "confluent-operator.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
app.kubernetes.io/component: "confluent-operator"
helm.sh/chart: {{ include "confluent-operator.chart" . }}
name: confluent-operator
namespace: {{ .Release.Namespace }}
spec:
ports:
- name: http-metric
port: 7778
protocol: TCP
targetPort: 7778
{{- if (.Values.webhooks.enabled) }}
- name: webhook
port: {{ .Values.webhooks.port }}
protocol: TCP
targetPort: {{ .Values.webhooks.port }}
{{- end }}
selector:
app: "confluent-operator"
app.kubernetes.io/name: "confluent-operator"
type: ClusterIP

View File

@ -0,0 +1,18 @@
{{- if .Values.serviceAccount.create -}}
apiVersion: v1
{{- if .Values.imagePullSecretRef }}
imagePullSecrets:
- name: {{ .Values.imagePullSecretRef }}
{{- end }}
kind: ServiceAccount
metadata:
labels:
app: {{ include "confluent-operator.name" . }}
app.kubernetes.io/name: {{ include "confluent-operator.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
app.kubernetes.io/component: "confluent-operator"
helm.sh/chart: {{ include "confluent-operator.chart" . }}
name: {{ template "confluent-operator.service-account" . }}
namespace: {{ .Release.Namespace }}
{{- end }}

View File

@ -0,0 +1,184 @@
{{- if (.Values.webhooks.enabled) }}
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
labels:
app: {{ include "confluent-operator.name" . }}
app.kubernetes.io/name: {{ include "confluent-operator.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
app.kubernetes.io/component: "confluent-operator"
helm.sh/chart: {{ include "confluent-operator.chart" . }}
name: confluent-operator-{{ .Release.Namespace }}.webhook.platform.confluent.io
webhooks:
- admissionReviewVersions:
- v1beta1
clientConfig:
service:
name: confluent-operator
namespace: {{ .Release.Namespace }}
path: /confluent-operator/validate
port: {{ .Values.webhooks.port }}
failurePolicy: Fail
name: cfk-resources.webhooks.platform.confluent.io
namespaceSelector:
matchExpressions:
- key: confluent-operator.webhooks.platform.confluent.io/disable
operator: NotIn
values: [ "true" ]
{{- if .Values.namespaced }}
- key: kubernetes.io/metadata.name
operator: In
values:
{{- if empty .Values.namespaceList }}
- {{ .Release.Namespace }}
{{- else }}
{{- range $i, $v := .Values.namespaceList }}
- {{ trim $v }}
{{- end }}
{{- end }}
{{- end }}
objectSelector:
matchExpressions:
- key: confluent-operator.webhooks.platform.confluent.io/disable
operator: NotIn
values: [ "true" ]
rules:
- apiGroups:
- platform.confluent.io
apiVersions:
- v1beta1
operations:
- UPDATE
- DELETE
resources:
- zookeepers
- kafkas
- kraftcontrollers
- ksqldbs
- controlcenters
scope: Namespaced
sideEffects: None
timeoutSeconds: 10
- admissionReviewVersions:
- v1beta1
clientConfig:
service:
name: confluent-operator
namespace: {{ .Release.Namespace }}
path: /confluent-operator/validate
port: {{ .Values.webhooks.port }}
failurePolicy: Fail
name: core-resources.webhooks.platform.confluent.io
namespaceSelector:
matchExpressions:
- key: confluent-operator.webhooks.platform.confluent.io/disable
operator: NotIn
values: [ "true" ]
{{- if .Values.namespaced }}
- key: kubernetes.io/metadata.name
operator: In
values:
{{- if empty .Values.namespaceList }}
- {{ .Release.Namespace }}
{{- else }}
{{- range $i, $v := .Values.namespaceList }}
- {{ trim $v }}
{{- end }}
{{- end }}
{{- end }}
objectSelector:
matchLabels:
confluent-platform: "true"
rules:
- apiGroups:
- apps
apiVersions:
- v1
operations:
- DELETE
resources:
- statefulsets
scope: Namespaced
sideEffects: None
timeoutSeconds: 10
- admissionReviewVersions:
- v1beta1
clientConfig:
service:
name: confluent-operator
namespace: {{ .Release.Namespace }}
path: /confluent-operator/validate
port: {{ .Values.webhooks.port }}
failurePolicy: Fail
name: kafka-pods.webhooks.platform.confluent.io
namespaceSelector:
matchExpressions:
- key: confluent-operator.webhooks.platform.confluent.io/disable
operator: NotIn
values: [ "true" ]
{{- if .Values.namespaced }}
- key: kubernetes.io/metadata.name
operator: In
values:
{{- if empty .Values.namespaceList }}
- {{ .Release.Namespace }}
{{- else }}
{{- range $i, $v := .Values.namespaceList }}
- {{ trim $v }}
{{- end }}
{{- end }}
{{- end }}
objectSelector:
matchLabels:
confluent-platform: "true"
platform.confluent.io/type: kafka
rules:
- apiGroups:
- ""
apiVersions:
- v1
operations:
- DELETE
resources:
- pods
scope: Namespaced
sideEffects: None
timeoutSeconds: 30
- admissionReviewVersions:
- v1beta1
clientConfig:
service:
name: confluent-operator
namespace: {{ .Release.Namespace }}
path: /confluent-operator/validate
port: {{ .Values.webhooks.port }}
failurePolicy: Fail
name: evictions.webhooks.platform.confluent.io
namespaceSelector:
matchExpressions:
{{- if .Values.namespaced }}
- key: kubernetes.io/metadata.name
operator: In
values:
{{- if empty .Values.namespaceList }}
- {{ .Release.Namespace }}
{{- else }}
{{- range $i, $v := .Values.namespaceList }}
- {{ trim $v }}
{{- end }}
{{- end }}
{{- end }}
rules:
- apiGroups:
- ""
apiVersions:
- v1
operations:
- CREATE
resources:
- pods/eviction
scope: Namespaced
sideEffects: None
timeoutSeconds: 30
{{- end }}

View File

@ -0,0 +1,269 @@
## Confluent operator name
##
name: confluent-operator
##
## license Key
##
licenseKey: ""
##
## Load license either from the secret or through directoryPath.
## This will take precedence over licenseKey field.
##
license:
##
## The license secret reference name is injected through
## CONFLUENT_LICENSE_SECRET_NAME environment variable.
## The expected key: license.txt. license.txt contains raw license data.
## For backward compatibility, licenseSecretRef field takes precedence if configured.
secretRef: ""
## The directoryPathInContainer value is injected through
## CONFLUENT_LICENSE_DIRECTORY_PATH environment variable.
## The expected key: license.txt. license.txt file must have value in pattern `license=<replace_with_key>`.
##
## This configuration takes precedence over license.secretRef or licenseSecretRef field.
##
directoryPathInContainer: ""
##
## AutoGenerated certificates configuration.
## We will continue using older model of reading CA from secret "ca-pair-sslcerts" unless
## managedCerts.enabled is set to true.
##
managedCerts:
##
## Denotes whether CFK managed certs are configured with helm values. If this is set to true
## values below will be used for auto-generated certificates and will cause a cluster roll
## first time after this is enabled.
##
enabled: false
##
## CA certificate pair for AutoGenerated certificates in this CFK operator deployment.
##
caCertificate:
##
## CA pair secret reference name is injected through
## CONFLUENT_MANAGED_CERTS_SECRET_NAME environment variable.
## The expected keys are tls.crt and tls.key for CA Certificate and CA Certificate Key
## respectively.
##
secretRef: ""
## The directoryPathInContainer value for CA pair certificates are injected through
## CONFLUENT_MANAGED_CERTS_DIRECTORY_PATH environment variable.
## The expected files are tls.crt and tls.key for CA Certificate and CA Certificate Key
## respectively.
##
directoryPathInContainer: ""
##
## Validity for Auto-generated certificates is injected through
## CONFLUENT_MANAGED_CERTS_DURATION_DAYS environment variable.
##
certDurationInDays: 60
##
## Renewal time for Auto-generated certificates is injected through
## CONFLUENT_MANAGED_CERTS_RENEW_BEFORE_DAYS environment variable.
##
renewBeforeInDays: 30
##
## SANs to be added for all auto-generated certificates generated by this
## CFK operator. This is injected through CONFLUENT_MANAGED_CERTS_SANS
## environment variable.
## Use this for adding wild card SANs. Modifying this will trigger regeneration of
## certs for all CP clusters managed by the CFK operator.
##
sans: ""
###
## Image pull secret
imagePullSecretRef: confluent-registry
## Confluent Operator Image Information
##
image:
registry: docker.io
repository: confluentinc/confluent-operator
pullPolicy: IfNotPresent
tag: "0.1033.3"
###
## Priority class for Confluent Operator pod
priorityClassName: ""
## Number of pods for Operator
## Enables leader election if more than one replica
replicas: 1
## Confluent Operator Cluster Access
## If true, operator only creates roles/rolebinding for the release namespace
## Otherwise, it has cluster access with clusterrole/clusterrrolebinding
namespaced: true
### list of namespaces to watch by operator
### This field only takes in effect if `namespaced=true`. By default, it will only watch the release namespace
### Otherwise, it will watch specified namespaces. If watching only release namespace, do not specify this field
namespaceList: []
## Confluent Operator Pod Resources
##
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 100m
memory: 256Mi
## Pod termination grace-period
##
terminationGracePeriodSeconds: 30
## Enable debugging
##
debug: false
## Enable Fips Mode
##
fipsmode: false
## Set number of day2 workers
##
numDay2Worker: ""
##
## Configure affinity,
## More information here https://kubernetes.io/docs/concepts/configuration/assign-pod-node/
##
affinity: {}
## Example for nodeAffinity, configure as required.
##affinity:
## nodeAffinity:
## requiredDuringSchedulingIgnoredDuringExecution:
## nodeSelectorTerms:
## - matchExpressions:
## - key: "node-role.kubernetes.io/compute"
## operator: In
## values:
## - "true"
##
## Configure tolerations
## https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/
##
tolerations: []
##
##tolerations:
##- key: "dedicated"
## operator: "Equal"
## value: "operator"
## effect: "NoSchedule"
## Pod Security Context
##
podSecurity:
enabled: true
securityContext:
fsGroup: 1001
runAsUser: 1001
runAsNonRoot: true
## Container Security Context
## Container security context overrides security context defined at pod level.
## For example following container security context would override the
## default PodSecurityContext defined above
##
## securityContext:
## runAsUser: 2001
## runAsNonRoot: false
##
## Refer to this documentation on how configure security context for container
## https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-containerh
##
containerSecurity:
enabled: false
securityContext: {}
##
## ServiceAccount
## If enabled it will create, otherwise it will
## not create
##
serviceAccount:
create: true
name: ""
## Enable Kubernetes RBAC
## When set to true, it will create a proper role/rolebinding or cluster/clusterrolebinding based on namespaced field.
## If a user doesn't have permission to create role/rolebinding then they can disable rbac field and
## create required resources out of band to be used by the Operator. In this case, follow the
## templates/clusterrole.yaml and templates/clusterrolebiding.yaml to create proper required resources.
rbac: true
## Enable extra Kubernetes API groups in role/clusterrole resource
## When set to true, it will add apiGroups to role/clusterrole for OpenShift route resource
clusterRole:
openshift: true
###
### Confluent Telemetry Report configuration
## The secretRef contains following data,
## telemetry.txt: |-
## api.key=<api_key>
## api.secret=<api_secret>
## proxy.url=<proxy_url> # only required if proxy is enabled
## proxy.username=<proxy_username> # only required if proxy requires credential
## proxy.password=<proxy_password>
##
telemetry:
operator:
enabled: false
enabled: false
proxy:
enabled: false
credentialRequired: false
secretRef: ""
## To use directoryPathInContainer, need to make sure
## you mount telemetry.txt in the path you provided here in each pod
directoryPathInContainer: ""
## In case of KRaft, we need to preserve the KRaft ClusterID in PV annotation
## for disaster recovery case. Enabling this ensures we create proper ClusterRoles
## to be able to set this annotation in PersistentVolumes.
kRaftEnabled: false
###
### Webhooks configuration
## To enable webhooks, it requires TLS certificates to set up webhook server,
## which used for secure communication between webhook server and kubernetes api server.
## Please provide the TLS keys and certificates with format as mentioned in this doc:
## https://docs.confluent.io/operator/current/co-network-encryption.html#provide-tls-keys-and-certificates-in-pem-format.
## The certificate must have the Subject Alternative Name (SAN) of the form: confluent-operator.<namespace>.svc
webhooks:
enabled: false
port: 8443
tls:
secretRef: ""
directoryPathInContainer: ""
##
## Pod annotations/labels configurations
##
pod:
annotations:
prometheus.io/path: "/metrics"
prometheus.io/port: "7778"
prometheus.io/scrape: "true"
labels: {}
# labels:
# key: "value"
##
## Load license from the secret reference
## +Deprecated, use license.secretRef instead.
##
licenseSecretRef: ""
##
## Volumes to mount on CFK operator
## Refer to the Kubernetes volume/volumeMounts format: https://kubernetes.io/docs/concepts/storage/volumes/
##
## Example with a PVC.
## mountedVolumes:
## volumes:
## - name: custom-volume
## persistentVolumeClaim:
## claimName: pvc-test
## volumeMounts:
## - name: custom-volume
## mountPath: /mnt/<path_of_your_choice>
##
mountedVolumes:
volumes: []
volumeMounts: []

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,54 @@
annotations:
artifacthub.io/category: integration-delivery
artifacthub.io/changes: |
- Introduce capability of set skipTlsVerify and usageRestricted flags in additionalClouds
artifacthub.io/images: |
- name: jenkins
image: docker.io/jenkins/jenkins:2.452.3-jdk17
- name: k8s-sidecar
image: docker.io/kiwigrid/k8s-sidecar:1.27.5
- name: inbound-agent
image: jenkins/inbound-agent:3256.v88a_f6e922152-1
artifacthub.io/license: Apache-2.0
artifacthub.io/links: |
- name: Chart Source
url: https://github.com/jenkinsci/helm-charts/tree/main/charts/jenkins
- name: Jenkins
url: https://www.jenkins.io/
- name: support
url: https://github.com/jenkinsci/helm-charts/issues
catalog.cattle.io/certified: partner
catalog.cattle.io/display-name: Jenkins
catalog.cattle.io/kube-version: '>=1.14-0'
catalog.cattle.io/release-name: jenkins
apiVersion: v2
appVersion: 2.452.3
description: 'Jenkins - Build great things at any scale! As the leading open source
automation server, Jenkins provides over 1800 plugins to support building, deploying
and automating any project. '
home: https://www.jenkins.io/
icon: file://assets/icons/jenkins.svg
keywords:
- jenkins
- ci
- devops
kubeVersion: '>=1.14-0'
maintainers:
- email: maor.friedman@redhat.com
name: maorfr
- email: mail@torstenwalter.de
name: torstenwalter
- email: garridomota@gmail.com
name: mogaal
- email: wmcdona89@gmail.com
name: wmcdona89
- email: timjacomb1@gmail.com
name: timja
name: jenkins
sources:
- https://github.com/jenkinsci/jenkins
- https://github.com/jenkinsci/docker-inbound-agent
- https://github.com/maorfr/kube-tasks
- https://github.com/jenkinsci/configuration-as-code-plugin
type: application
version: 5.5.0

View File

@ -0,0 +1,706 @@
# Jenkins
[![Artifact Hub](https://img.shields.io/endpoint?url=https://artifacthub.io/badge/repository/jenkins)](https://artifacthub.io/packages/helm/jenkinsci/jenkins)
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
[![Releases downloads](https://img.shields.io/github/downloads/jenkinsci/helm-charts/total.svg)](https://github.com/jenkinsci/helm-charts/releases)
[![Join the chat at https://app.gitter.im/#/room/#jenkins-ci:matrix.org](https://badges.gitter.im/badge.svg)](https://app.gitter.im/#/room/#jenkins-ci:matrix.org)
[Jenkins](https://www.jenkins.io/) is the leading open source automation server, Jenkins provides over 1800 plugins to support building, deploying and automating any project.
This chart installs a Jenkins server which spawns agents on [Kubernetes](http://kubernetes.io) utilizing the [Jenkins Kubernetes plugin](https://plugins.jenkins.io/kubernetes/).
Inspired by the awesome work of [Carlos Sanchez](https://github.com/carlossg).
## Get Repository Info
```console
helm repo add jenkins https://charts.jenkins.io
helm repo update
```
_See [`helm repo`](https://helm.sh/docs/helm/helm_repo/) for command documentation._
## Install Chart
```console
# Helm 3
$ helm install [RELEASE_NAME] jenkins/jenkins [flags]
```
_See [configuration](#configuration) below._
_See [helm install](https://helm.sh/docs/helm/helm_install/) for command documentation._
## Uninstall Chart
```console
# Helm 3
$ helm uninstall [RELEASE_NAME]
```
This removes all the Kubernetes components associated with the chart and deletes the release.
_See [helm uninstall](https://helm.sh/docs/helm/helm_uninstall/) for command documentation._
## Upgrade Chart
```console
# Helm 3
$ helm upgrade [RELEASE_NAME] jenkins/jenkins [flags]
```
_See [helm upgrade](https://helm.sh/docs/helm/helm_upgrade/) for command documentation._
Visit the chart's [CHANGELOG](https://github.com/jenkinsci/helm-charts/blob/main/charts/jenkins/CHANGELOG.md) to view the chart's release history.
For migration between major version check [migration guide](#migration-guide).
## Building weekly releases
The default charts target Long-Term-Support (LTS) releases of Jenkins.
To use other versions the easiest way is to update the image tag to the version you want.
You can also rebuild the chart if you want the `appVersion` field to match.
## Configuration
See [Customizing the Chart Before Installing](https://helm.sh/docs/intro/using_helm/#customizing-the-chart-before-installing).
To see all configurable options with detailed comments, visit the chart's [values.yaml](https://github.com/jenkinsci/helm-charts/blob/main/charts/jenkins/values.yaml), or run these configuration commands:
```console
# Helm 3
$ helm show values jenkins/jenkins
```
For a summary of all configurable options, see [VALUES_SUMMARY.md](https://github.com/jenkinsci/helm-charts/blob/main/charts/jenkins/VALUES_SUMMARY.md).
### Configure Security Realm and Authorization Strategy
This chart configured a `securityRealm` and `authorizationStrategy` as shown below:
```yaml
controller:
JCasC:
securityRealm: |-
local:
allowsSignup: false
enableCaptcha: false
users:
- id: "${chart-admin-username}"
name: "Jenkins Admin"
password: "${chart-admin-password}"
authorizationStrategy: |-
loggedInUsersCanDoAnything:
allowAnonymousRead: false
```
With the configuration above there is only a single user.
This is fine for getting started quickly, but it needs to be adjusted for any serious environment.
So you should adjust this to suite your needs.
That could be using LDAP / OIDC / .. as authorization strategy and use globalMatrix as authorization strategy to configure more fine-grained permissions.
### Consider using a custom image
This chart allows the user to specify plugins which should be installed. However, for production use cases one should consider to build a custom Jenkins image which has all required plugins pre-installed.
This way you can be sure which plugins Jenkins is using when starting up and you avoid trouble in case of connectivity issues to the Jenkins update site.
The [docker repository](https://github.com/jenkinsci/docker) for the Jenkins image contains [documentation](https://github.com/jenkinsci/docker#preinstalling-plugins) how to do it.
Here is an example how that can be done:
```Dockerfile
FROM jenkins/jenkins:lts
RUN jenkins-plugin-cli --plugins kubernetes workflow-aggregator git configuration-as-code
```
NOTE: If you want a reproducible build then you should specify a non-floating tag for the image `jenkins/jenkins:2.249.3` and specify plugin versions.
Once you built the image and pushed it to your registry you can specify it in your values file like this:
```yaml
controller:
image: "registry/my-jenkins"
tag: "v1.2.3"
installPlugins: false
```
Notice: `installPlugins` is set to false to disable plugin download. In this case, the image `registry/my-jenkins:v1.2.3` must have the plugins specified as default value for [the `controller.installPlugins` directive](https://github.com/jenkinsci/helm-charts/blob/main/charts/jenkins/VALUES_SUMMARY.md#jenkins-plugins) to ensure that the configuration side-car system works as expected.
In case you are using a private registry you can use 'imagePullSecretName' to specify the name of the secret to use when pulling the image:
```yaml
controller:
image: "registry/my-jenkins"
tag: "v1.2.3"
imagePullSecretName: registry-secret
installPlugins: false
```
### External URL Configuration
If you are using the ingress definitions provided by this chart via the `controller.ingress` block the configured hostname will be the ingress hostname starting with `https://` or `http://` depending on the `tls` configuration.
The Protocol can be overwritten by specifying `controller.jenkinsUrlProtocol`.
If you are not using the provided ingress you can specify `controller.jenkinsUrl` to change the URL definition.
### Configuration as Code
Jenkins Configuration as Code (JCasC) is now a standard component in the Jenkins project.
To allow JCasC's configuration from the helm values, the plugin [`configuration-as-code`](https://plugins.jenkins.io/configuration-as-code/) must be installed in the Jenkins Controller's Docker image (which is the case by default as specified by the [default value of the directive `controller.installPlugins`](https://github.com/jenkinsci/helm-charts/blob/main/charts/jenkins/VALUES_SUMMARY.md#jenkins-plugins)).
JCasc configuration is passed through Helm values under the key `controller.JCasC`.
The section ["Jenkins Configuration as Code (JCasC)" of the page "VALUES_SUMMARY.md"](https://github.com/jenkinsci/helm-charts/blob/main/charts/jenkins/VALUES_SUMMARY.md#jenkins-configuration-as-code-jcasc) lists all the possible directives.
In particular, you may specify custom JCasC scripts by adding sub-key under the `controller.JCasC.configScripts` for each configuration area where each corresponds to a plugin or section of the UI.
The sub-keys (prior to `|` character) are only labels used to give the section a meaningful name.
The only restriction is they must conform to RFC 1123 definition of a DNS label, so they may only contain lowercase letters, numbers, and hyphens.
Each key will become the name of a configuration yaml file on the controller in `/var/jenkins_home/casc_configs` (by default) and will be processed by the Configuration as Code Plugin during Jenkins startup.
The lines after each `|` become the content of the configuration yaml file.
The first line after this is a JCasC root element, e.g. jenkins, credentials, etc.
Best reference is the Documentation link here: `https://<jenkins_url>/configuration-as-code`.
The example below sets custom systemMessage:
```yaml
controller:
JCasC:
configScripts:
welcome-message: |
jenkins:
systemMessage: Welcome to our CI\CD server.
```
More complex example that creates ldap settings:
```yaml
controller:
JCasC:
configScripts:
ldap-settings: |
jenkins:
securityRealm:
ldap:
configurations:
- server: ldap.acme.com
rootDN: dc=acme,dc=uk
managerPasswordSecret: ${LDAP_PASSWORD}
groupMembershipStrategy:
fromUserRecord:
attributeName: "memberOf"
```
Keep in mind that default configuration file already contains some values that you won't be able to override under configScripts section.
For example, you can not configure Jenkins URL and System Admin email address like this because of conflicting configuration error.
Incorrect:
```yaml
controller:
JCasC:
configScripts:
jenkins-url: |
unclassified:
location:
url: https://example.com/jenkins
adminAddress: example@mail.com
```
Correct:
```yaml
controller:
jenkinsUrl: https://example.com/jenkins
jenkinsAdminEmail: example@mail.com
```
Further JCasC examples can be found [here](https://github.com/jenkinsci/configuration-as-code-plugin/tree/master/demos).
#### Breaking out large Config as Code scripts
Jenkins Config as Code scripts can become quite large, and maintaining all of your scripts within one yaml file can be difficult. The Config as Code plugin itself suggests updating the `CASC_JENKINS_CONFIG` environment variable to be a comma separated list of paths for the plugin to traverse, picking up the yaml files as needed.
However, under the Jenkins helm chart, this `CASC_JENKINS_CONFIG` value is maintained through the templates. A better solution is to split your `controller.JCasC.configScripts` into separate values files, and provide each file during the helm install.
For example, you can have a values file (e.g values_main.yaml) that defines the values described in the `VALUES_SUMMARY.md` for your Jenkins configuration:
```yaml
jenkins:
controller:
jenkinsUrlProtocol: https
installPlugins: false
...
```
In a second file (e.g values_jenkins_casc.yaml), you can define a section of your config scripts:
```yaml
jenkins:
controller:
JCasC:
configScripts:
jenkinsCasc: |
jenkins:
disableRememberMe: false
mode: NORMAL
...
```
And keep extending your config scripts by creating more files (so not all config scripts are located in one yaml file for better maintenance):
values_jenkins_unclassified.yaml
```yaml
jenkins:
controller:
JCasC:
configScripts:
unclassifiedCasc: |
unclassified:
...
```
When installing, you provide all relevant yaml files (e.g `helm install -f values_main.yaml -f values_jenkins_casc.yaml -f values_jenkins_unclassified.yaml ...`). Instead of updating the `CASC_JENKINS_CONFIG` environment variable to include multiple paths, multiple CasC yaml files will be created in the same path `var/jenkins_home/casc_configs`.
#### Config as Code With or Without Auto-Reload
Config as Code changes (to `controller.JCasC.configScripts`) can either force a new pod to be created and only be applied at next startup, or can be auto-reloaded on-the-fly.
If you set `controller.sidecars.configAutoReload.enabled` to `true`, a second, auxiliary container will be installed into the Jenkins controller pod, known as a "sidecar".
This watches for changes to configScripts, copies the content onto the Jenkins file-system and issues a POST to `http://<jenkins_url>/reload-configuration-as-code` with a pre-shared key.
You can monitor this sidecar's logs using command `kubectl logs <controller_pod> -c config-reload -f`.
If you want to enable auto-reload then you also need to configure rbac as the container which triggers the reload needs to watch the config maps:
```yaml
controller:
sidecars:
configAutoReload:
enabled: true
rbac:
create: true
```
### Allow Limited HTML Markup in User-Submitted Text
Some third-party systems (e.g. GitHub) use HTML-formatted data in their payload sent to a Jenkins webhook (e.g. URL of a pull-request being built).
To display such data as processed HTML instead of raw text set `controller.enableRawHtmlMarkupFormatter` to true.
This option requires installation of the [OWASP Markup Formatter Plugin (antisamy-markup-formatter)](https://plugins.jenkins.io/antisamy-markup-formatter/).
This plugin is **not** installed by default but may be added to `controller.additionalPlugins`.
### Change max connections to Kubernetes API
When using agents with containers other than JNLP, The kubernetes plugin will communicate with those containers using the Kubernetes API. this changes the maximum concurrent connections
```yaml
agent:
maxRequestsPerHostStr: "32"
```
This will change the configuration of the kubernetes "cloud" (as called by jenkins) that is created automatically as part of this helm chart.
### Change container cleanup timeout API
For tasks that use very large images, this timeout can be increased to avoid early termination of the task while the Kubernetes pod is still deploying.
```yaml
agent:
retentionTimeout: "32"
```
This will change the configuration of the kubernetes "cloud" (as called by jenkins) that is created automatically as part of this helm chart.
### Change seconds to wait for pod to be running
This will change how long Jenkins will wait (seconds) for pod to be in running state.
```yaml
agent:
waitForPodSec: "32"
```
This will change the configuration of the kubernetes "cloud" (as called by jenkins) that is created automatically as part of this helm chart.
### Mounting Volumes into Agent Pods
Your Jenkins Agents will run as pods, and it's possible to inject volumes where needed:
```yaml
agent:
volumes:
- type: Secret
secretName: jenkins-mysecrets
mountPath: /var/run/secrets/jenkins-mysecrets
```
The supported volume types are: `ConfigMap`, `EmptyDir`, `HostPath`, `Nfs`, `PVC`, `Secret`.
Each type supports a different set of configurable attributes, defined by [the corresponding Java class](https://github.com/jenkinsci/kubernetes-plugin/tree/master/src/main/java/org/csanchez/jenkins/plugins/kubernetes/volumes).
### NetworkPolicy
To make use of the NetworkPolicy resources created by default, install [a networking plugin that implements the Kubernetes NetworkPolicy spec](https://kubernetes.io/docs/tasks/administer-cluster/declare-network-policy#before-you-begin).
[Install](#install-chart) helm chart with network policy enabled by setting `networkPolicy.enabled` to `true`.
You can use `controller.networkPolicy.internalAgents` and `controller.networkPolicy.externalAgents` stanzas for fine-grained controls over where internal/external agents can connect from.
Internal ones are allowed based on pod labels and (optionally) namespaces, and external ones are allowed based on IP ranges.
### Script approval list
`controller.scriptApproval` allows to pass function signatures that will be allowed in pipelines.
Example:
```yaml
controller:
scriptApproval:
- "method java.util.Base64$Decoder decode java.lang.String"
- "new java.lang.String byte[]"
- "staticMethod java.util.Base64 getDecoder"
```
### Custom Labels
`controller.serviceLabels` can be used to add custom labels in `jenkins-controller-svc.yaml`.
For example:
```yaml
ServiceLabels:
expose: true
```
### Persistence
The Jenkins image stores persistence under `/var/jenkins_home` path of the container.
A dynamically managed Persistent Volume Claim is used to keep the data across deployments, by default.
This is known to work in GCE, AWS, and minikube. Alternatively, a previously configured Persistent Volume Claim can be used.
It is possible to mount several volumes using `persistence.volumes` and `persistence.mounts` parameters.
See additional `persistence` values using [configuration commands](#configuration).
#### Existing PersistentVolumeClaim
1. Create the PersistentVolume
2. Create the PersistentVolumeClaim
3. [Install](#install-chart) the chart, setting `persistence.existingClaim` to `PVC_NAME`
#### Long Volume Attach/Mount Times
Certain volume type and filesystem format combinations may experience long
attach/mount times, [10 or more minutes][K8S_VOLUME_TIMEOUT], when using
`fsGroup`. This issue may result in the following entries in the pod's event
history:
```console
Warning FailedMount 38m kubelet, aks-default-41587790-2 Unable to attach or mount volumes: unmounted volumes=[jenkins-home], unattached volumes=[plugins plugin-dir jenkins-token-rmq2g sc-config-volume tmp jenkins-home jenkins-config secrets-dir]: timed out waiting for the condition
```
In these cases, experiment with replacing `fsGroup` with
`supplementalGroups` in the pod's `securityContext`. This can be achieved by
setting the `controller.podSecurityContextOverride` Helm chart value to
something like:
```yaml
controller:
podSecurityContextOverride:
runAsNonRoot: true
runAsUser: 1000
supplementalGroups: [1000]
```
This issue has been reported on [azureDisk with ext4][K8S_VOLUME_TIMEOUT] and
on [Alibaba cloud][K8S_VOLUME_TIMEOUT_ALIBABA].
[K8S_VOLUME_TIMEOUT]: https://github.com/kubernetes/kubernetes/issues/67014
[K8S_VOLUME_TIMEOUT_ALIBABA]: https://github.com/kubernetes/kubernetes/issues/67014#issuecomment-698770511
#### Storage Class
It is possible to define which storage class to use, by setting `persistence.storageClass` to `[customStorageClass]`.
If set to a dash (`-`), dynamic provisioning is disabled.
If the storage class is set to null or left undefined (`""`), the default provisioner is used (gp2 on AWS, standard on GKE, AWS & OpenStack).
### Additional Secrets
Additional secrets and Additional Existing Secrets,
can be mounted into the Jenkins controller through the chart or created using `controller.additionalSecrets` or `controller.additionalExistingSecrets`.
A common use case might be identity provider credentials if using an external LDAP or OIDC-based identity provider.
The secret may then be referenced in JCasC configuration (see [JCasC configuration](#configuration-as-code)).
`values.yaml` controller section, referencing mounted secrets:
```yaml
controller:
# the 'name' and 'keyName' are concatenated with a '-' in between, so for example:
# an existing secret "secret-credentials" and a key inside it named "github-password" should be used in Jcasc as ${secret-credentials-github-password}
# 'name' and 'keyName' must be lowercase RFC 1123 label must consist of lower case alphanumeric characters or '-',
# and must start and end with an alphanumeric character (e.g. 'my-name', or '123-abc')
# existingSecret existing secret "secret-credentials" and a key inside it named "github-username" should be used in Jcasc as ${github-username}
# When using existingSecret no need to specify the keyName under additionalExistingSecrets.
existingSecret: secret-credentials
additionalExistingSecrets:
- name: secret-credentials
keyName: github-username
- name: secret-credentials
keyName: github-password
- name: secret-credentials
keyName: token
additionalSecrets:
- name: client_id
value: abc123
- name: client_secret
value: xyz999
JCasC:
securityRealm: |
oic:
clientId: ${client_id}
clientSecret: ${client_secret}
...
configScripts:
jenkins-casc-configs: |
credentials:
system:
domainCredentials:
- credentials:
- string:
description: "github access token"
id: "github_app_token"
scope: GLOBAL
secret: ${secret-credentials-token}
- usernamePassword:
description: "github access username password"
id: "github_username_pass"
password: ${secret-credentials-github-password}
scope: GLOBAL
username: ${secret-credentials-github-username}
```
For more information, see [JCasC documentation](https://github.com/jenkinsci/configuration-as-code-plugin/blob/master/docs/features/secrets.adoc#kubernetes-secrets).
### Secret Claims from HashiCorp Vault
It's possible for this chart to generate `SecretClaim` resources in order to automatically create and maintain Kubernetes `Secrets` from HashiCorp [Vault](https://www.vaultproject.io/) via [`kube-vault-controller`](https://github.com/roboll/kube-vault-controller)
These `Secrets` can then be referenced in the same manner as Additional Secrets above.
This can be achieved by defining required Secret Claims within `controller.secretClaims`, as follows:
```yaml
controller:
secretClaims:
- name: jenkins-secret
path: secret/path
- name: jenkins-short-ttl
path: secret/short-ttl-path
renew: 60
```
### RBAC
RBAC is enabled by default. If you want to disable it you will need to set `rbac.create` to `false`.
### Adding Custom Pod Templates
It is possible to add custom pod templates for the default configured kubernetes cloud.
Add a key under `agent.podTemplates` for each pod template. Each key (prior to `|` character) is just a label, and can be any value.
Keys are only used to give the pod template a meaningful name. The only restriction is they may only contain RFC 1123 \ DNS label characters: lowercase letters, numbers, and hyphens. Each pod template can contain multiple containers.
There's no need to add the _jnlp_ container since the kubernetes plugin will automatically inject it into the pod.
For this pod templates configuration to be loaded the following values must be set:
```yaml
controller.JCasC.defaultConfig: true
```
The example below creates a python pod template in the kubernetes cloud:
```yaml
agent:
podTemplates:
python: |
- name: python
label: jenkins-python
serviceAccount: jenkins
containers:
- name: python
image: python:3
command: "/bin/sh -c"
args: "cat"
ttyEnabled: true
privileged: true
resourceRequestCpu: "400m"
resourceRequestMemory: "512Mi"
resourceLimitCpu: "1"
resourceLimitMemory: "1024Mi"
```
Best reference is `https://<jenkins_url>/configuration-as-code/reference#Cloud-kubernetes`.
### Adding Pod Templates Using additionalAgents
`additionalAgents` may be used to configure additional kubernetes pod templates.
Each additional agent corresponds to `agent` in terms of the configurable values and inherits all values from `agent` so you only need to specify values which differ.
For example:
```yaml
agent:
podName: default
customJenkinsLabels: default
# set resources for additional agents to inherit
resources:
limits:
cpu: "1"
memory: "2048Mi"
additionalAgents:
maven:
podName: maven
customJenkinsLabels: maven
# An example of overriding the jnlp container
# sideContainerName: jnlp
image: jenkins/jnlp-agent-maven
tag: latest
python:
podName: python
customJenkinsLabels: python
sideContainerName: python
image: python
tag: "3"
command: "/bin/sh -c"
args: "cat"
TTYEnabled: true
```
### Ingress Configuration
This chart provides ingress resources configurable via the `controller.ingress` block.
The simplest configuration looks like the following:
```yaml
controller:
ingress:
enabled: true
paths: []
apiVersion: "extensions/v1beta1"
hostName: jenkins.example.com
```
This snippet configures an ingress rule for exposing jenkins at `jenkins.example.com`
You can define labels and annotations via `controller.ingress.labels` and `controller.ingress.annotations` respectively.
Additionally, you can configure the ingress tls via `controller.ingress.tls`.
By default, this ingress rule exposes all paths.
If needed this can be overwritten by specifying the wanted paths in `controller.ingress.paths`
If you want to configure a secondary ingress e.g. you don't want the jenkins instance exposed but still want to receive webhooks you can configure `controller.secondaryingress`.
The secondaryingress doesn't expose anything by default and has to be configured via `controller.secondaryingress.paths`:
```yaml
controller:
ingress:
enabled: true
apiVersion: "extensions/v1beta1"
hostName: "jenkins.internal.example.com"
annotations:
kubernetes.io/ingress.class: "internal"
secondaryingress:
enabled: true
apiVersion: "extensions/v1beta1"
hostName: "jenkins-scm.example.com"
annotations:
kubernetes.io/ingress.class: "public"
paths:
- /github-webhook
```
## Prometheus Metrics
If you want to expose Prometheus metrics you need to install the [Jenkins Prometheus Metrics Plugin](https://github.com/jenkinsci/prometheus-plugin).
It will expose an endpoint (default `/prometheus`) with metrics where a Prometheus Server can scrape.
If you have implemented [Prometheus Operator](https://github.com/prometheus-operator/prometheus-operator), you can set `controller.prometheus.enabled` to `true` to configure a `ServiceMonitor` and `PrometheusRule`.
If you want to further adjust alerting rules you can do so by configuring `controller.prometheus.alertingrules`
If you have implemented Prometheus without using the operator, you can leave `controller.prometheus.enabled` set to `false`.
### Running Behind a Forward Proxy
The controller pod uses an Init Container to install plugins etc. If you are behind a corporate proxy it may be useful to set `controller.initContainerEnv` to add environment variables such as `http_proxy`, so that these can be downloaded.
Additionally, you may want to add env vars for the init container, the Jenkins container, and the JVM (`controller.javaOpts`):
```yaml
controller:
initContainerEnv:
- name: http_proxy
value: "http://192.168.64.1:3128"
- name: https_proxy
value: "http://192.168.64.1:3128"
- name: no_proxy
value: ""
- name: JAVA_OPTS
value: "-Dhttps.proxyHost=proxy_host_name_without_protocol -Dhttps.proxyPort=3128"
containerEnv:
- name: http_proxy
value: "http://192.168.64.1:3128"
- name: https_proxy
value: "http://192.168.64.1:3128"
javaOpts: >-
-Dhttp.proxyHost=192.168.64.1
-Dhttp.proxyPort=3128
-Dhttps.proxyHost=192.168.64.1
-Dhttps.proxyPort=3128
```
### HTTPS Keystore Configuration
[This configuration](https://wiki.jenkins.io/pages/viewpage.action?pageId=135468777) enables jenkins to use keystore in order to serve HTTPS.
Here is the [value file section](https://wiki.jenkins.io/pages/viewpage.action?pageId=135468777#RunningJenkinswithnativeSSL/HTTPS-ConfigureJenkinstouseHTTPSandtheJKSkeystore) related to keystore configuration.
Keystore itself should be placed in front of `jenkinsKeyStoreBase64Encoded` key and in base64 encoded format. To achieve that after having `keystore.jks` file simply do this: `cat keystore.jks | base64` and paste the output in front of `jenkinsKeyStoreBase64Encoded`.
After enabling `httpsKeyStore.enable` make sure that `httpPort` and `targetPort` are not the same, as `targetPort` will serve HTTPS.
Do not set `controller.httpsKeyStore.httpPort` to `-1` because it will cause readiness and liveliness prob to fail.
If you already have a kubernetes secret that has keystore and its password you can specify its' name in front of `jenkinsHttpsJksSecretName`, You need to remember that your secret should have proper data key names `jenkins-jks-file` (or override the key name using `jenkinsHttpsJksSecretKey`)
and `https-jks-password` (or override the key name using `jenkinsHttpsJksPasswordSecretKey`; additionally you can make it get the password from a different secret using `jenkinsHttpsJksPasswordSecretName`). Example:
```yaml
controller:
httpsKeyStore:
enable: true
jenkinsHttpsJksSecretName: ''
httpPort: 8081
path: "/var/jenkins_keystore"
fileName: "keystore.jks"
password: "changeit"
jenkinsKeyStoreBase64Encoded: ''
```
### AWS Security Group Policies
To create SecurityGroupPolicies set `awsSecurityGroupPolicies.enabled` to true and add your policies. Each policy requires a `name`, array of `securityGroupIds` and a `podSelector`. Example:
```yaml
awsSecurityGroupPolicies:
enabled: true
policies:
- name: "jenkins-controller"
securityGroupIds:
- sg-123456789
podSelector:
matchExpressions:
- key: app.kubernetes.io/component
operator: In
values:
- jenkins-controller
```
### Agent Direct Connection
Set `directConnection` to `true` to allow agents to connect directly to a given TCP port without having to negotiate a HTTP(S) connection. This can allow you to have agent connections without an external HTTP(S) port. Example:
```yaml
agent:
jenkinsTunnel: "jenkinsci-agent:50000"
directConnection: true
```
## Migration Guide
### From stable repository
Upgrade an existing release from `stable/jenkins` to `jenkins/jenkins` seamlessly by ensuring you have the latest [repository info](#get-repository-info) and running the [upgrade commands](#upgrade-chart) specifying the `jenkins/jenkins` chart.
### Major Version Upgrades
Chart release versions follow [SemVer](../../CONTRIBUTING.md#versioning), where a MAJOR version change (example `1.0.0` -> `2.0.0`) indicates an incompatible breaking change needing manual actions.
See [UPGRADING.md](./UPGRADING.md) for a list of breaking changes

View File

@ -0,0 +1,148 @@
# Upgrade Notes
## To 5.0.0
- `controller.image`, `controller.tag`, and `controller.tagLabel` have been removed. If you want to overwrite the image you now need to configure any or all of:
- `controller.image.registry`
- `controller.image.repository`
- `controller.image.tag`
- `controller.image.tagLabel`
- `controller.imagePullPolicy` has been removed. If you want to overwrite the pull policy you now need to configure `controller.image.pullPolicy`.
- `controller.sidecars.configAutoReload.image` has been removed. If you want to overwrite the configAutoReload image you now need to configure any or all of:
- `controller.sidecars.configAutoReload.image.registry`
- `controller.sidecars.configAutoReload.image.repository`
- `controller.sidecars.configAutoReload.image.tag`
- `controller.sidecars.other` has been renamed to `controller.sidecars.additionalSidecarContainers`.
- `agent.image` and `agent.tag` have been removed. If you want to overwrite the agent image you now need to configure any or all of:
- `agent.image.repository`
- `agent.image.tag`
- The registry can still be overwritten by `agent.jnlpregistry`
- `agent.additionalContainers[*].image` has been renamed to `agent.additionalContainers[*].image.repository`
- `agent.additionalContainers[*].tag` has been renamed to `agent.additionalContainers[*].image.tag`
- `additionalAgents.*.image` has been renamed to `additionalAgents.*.image.repository`
- `additionalAgents.*.tag` has been renamed to `additionalAgents.*.image.tag`
- `additionalClouds.*.additionalAgents.*.image` has been renamed to `additionalClouds.*.additionalAgents.*.image.repository`
- `additionalClouds.*.additionalAgents.*.tag` has been renamed to `additionalClouds.*.additionalAgents.*.image.tag`
- `helmtest.bats.image` has been split up to:
- `helmtest.bats.image.registry`
- `helmtest.bats.image.repository`
- `helmtest.bats.image.tag`
- `controller.adminUsername` and `controller.adminPassword` have been renamed to `controller.admin.username` and `controller.admin.password` respectively
- `controller.adminSecret` has been renamed to `controller.admin.createSecret`
- `backup.*` was unmaintained and has thus been removed. See the following page for alternatives: [Kubernetes Backup and Migrations](https://nubenetes.com/kubernetes-backup-migrations/).
## To 4.0.0
Removes automatic `remotingSecurity` setting when using a container tag older than `2.326` (introduced in [`3.11.7`](./CHANGELOG.md#3117)). If you're using a version older than `2.326`, you should explicitly set `.controller.legacyRemotingSecurityEnabled` to `true`.
## To 3.0.0
* Check `securityRealm` and `authorizationStrategy` and adjust it.
Otherwise, your configured users and permissions will be overridden.
* You need to use helm version 3 as the `Chart.yaml` uses `apiVersion: v2`.
* All XML configuration options have been removed.
In case those are still in use you need to migrate to configuration as code.
Upgrade guide to 2.0.0 contains pointers how to do that.
* Jenkins is now using a `StatefulSet` instead of a `Deployment`
* terminology has been adjusted that's also reflected in values.yaml
The following values from `values.yaml` have been renamed:
* `master` => `controller`
* `master.useSecurity` => `controller.adminSecret`
* `master.slaveListenerPort` => `controller.agentListenerPort`
* `master.slaveHostPort` => `controller.agentListenerHostPort`
* `master.slaveKubernetesNamespace` => `agent.namespace`
* `master.slaveDefaultsProviderTemplate` => `agent.defaultsProviderTemplate`
* `master.slaveJenkinsUrl` => `agent.jenkinsUrl`
* `master.slaveJenkinsTunnel` => `agent.jenkinsTunnel`
* `master.slaveConnectTimeout` => `agent.kubernetesConnectTimeout`
* `master.slaveReadTimeout` => `agent.kubernetesReadTimeout`
* `master.slaveListenerServiceAnnotations` => `controller.agentListenerServiceAnnotations`
* `master.slaveListenerServiceType` => `controller.agentListenerServiceType`
* `master.slaveListenerLoadBalancerIP` => `controller.agentListenerLoadBalancerIP`
* `agent.slaveConnectTimeout` => `agent.connectTimeout`
* Removed values:
* `master.imageTag`: use `controller.image` and `controller.tag` instead
* `slave.imageTag`: use `agent.image` and `agent.tag` instead
## To 2.0.0
Configuration as Code is now default + container does not run as root anymore.
### Configuration as Code new default
Configuration is done via [Jenkins Configuration as Code Plugin](https://github.com/jenkinsci/configuration-as-code-plugin) by default.
That means that changes in values which result in a configuration change are always applied.
In contrast, the XML configuration was only applied during the first start and never altered.
:exclamation::exclamation::exclamation:
Attention:
This also means if you manually altered configuration then this will most likely be reset to what was configured by default.
It also applies to `securityRealm` and `authorizationStrategy` as they are also configured using configuration as code.
:exclamation::exclamation::exclamation:
### Image does not run as root anymore
It's not recommended to run containers in Kubernetes as `root`.
❗Attention: If you had not configured a different user before then you need to ensure that your image supports the user and group ID configured and also manually change permissions of all files so that Jenkins is still able to use them.
### Summary of updated values
As version 2.0.0 only updates default values and nothing else it's still possible to migrate to this version and opt out of some or all new defaults.
All you have to do is ensure the old values are set in your installation.
Here we show which values have changed and the previous default values:
```yaml
controller:
runAsUser: 1000 # was unset before
fsGroup: 1000 # was unset before
JCasC:
enabled: true # was false
defaultConfig: true # was false
sidecars:
configAutoReload:
enabled: true # was false
```
### Migration steps
Migration instructions heavily depend on your current setup.
So think of the list below more as a general guideline of what should be done.
- Ensure that the Jenkins image you are using contains a user with ID 1000 and a group with the same ID.
That's the case for `jenkins/jenkins:lts` image, which the chart uses by default
- Make a backup of your existing installation especially the persistent volume
- Ensure that you have the configuration as code plugin installed
- Export your current settings via the plugin:
`Manage Jenkins` -> `Configuration as Code` -> `Download Configuration`
- prepare your values file for the update e.g. add additional configuration as code setting that you need.
The export taken from above might be a good starting point for this.
In addition, the [demos](https://github.com/jenkinsci/configuration-as-code-plugin/tree/master/demos) from the plugin itself are quite useful.
- Test drive those setting on a separate installation
- Put Jenkins to Quiet Down mode so that it does not accept new jobs
`<JENKINS_URL>/quietDown`
- Change permissions of all files and folders to the new user and group ID:
```console
kubectl exec -it <jenkins_pod> -c jenkins /bin/bash
chown -R 1000:1000 /var/jenkins_home
```
- Update Jenkins
## To 1.0.0
Breaking changes:
- Values have been renamed to follow [helm recommended naming conventions](https://helm.sh/docs/chart_best_practices/#naming-conventions) so that all variables start with a lowercase letter and words are separated with camelcase
- All resources are now using [helm recommended standard labels](https://helm.sh/docs/chart_best_practices/#standard-labels)
As a result of the label changes also the selectors of the deployment have been updated.
Those are immutable so trying an updated will cause an error like:
```console
Error: Deployment.apps "jenkins" is invalid: spec.selector: Invalid value: v1.LabelSelector{MatchLabels:map[string]string{"app.kubernetes.io/component":"jenkins-controller", "app.kubernetes.io/instance":"jenkins"}, MatchExpressions:[]v1.LabelSelectorRequirement(nil)}: field is immutable
```
In order to upgrade, [uninstall](./README.md#uninstall-chart) the Jenkins Deployment before upgrading:

View File

@ -0,0 +1,311 @@
# Jenkins
## Configuration
The following tables list the configurable parameters of the Jenkins chart and their default values.
## Values
| Key | Type | Description | Default |
|:----|:-----|:---------|:------------|
| [additionalAgents](./values.yaml#L1169) | object | Configure additional | `{}` |
| [additionalClouds](./values.yaml#L1194) | object | | `{}` |
| [agent.TTYEnabled](./values.yaml#L1087) | bool | Allocate pseudo tty to the side container | `false` |
| [agent.additionalContainers](./values.yaml#L1122) | list | Add additional containers to the agents | `[]` |
| [agent.alwaysPullImage](./values.yaml#L980) | bool | Always pull agent container image before build | `false` |
| [agent.annotations](./values.yaml#L1118) | object | Annotations to apply to the pod | `{}` |
| [agent.args](./values.yaml#L1081) | string | Arguments passed to command to execute | `"${computer.jnlpmac} ${computer.name}"` |
| [agent.command](./values.yaml#L1079) | string | Command to execute when side container starts | `nil` |
| [agent.componentName](./values.yaml#L948) | string | | `"jenkins-agent"` |
| [agent.connectTimeout](./values.yaml#L1116) | int | Timeout in seconds for an agent to be online | `100` |
| [agent.containerCap](./values.yaml#L1089) | int | Max number of agents to launch | `10` |
| [agent.customJenkinsLabels](./values.yaml#L945) | list | Append Jenkins labels to the agent | `[]` |
| [agent.defaultsProviderTemplate](./values.yaml#L907) | string | The name of the pod template to use for providing default values | `""` |
| [agent.directConnection](./values.yaml#L951) | bool | | `false` |
| [agent.disableDefaultAgent](./values.yaml#L1140) | bool | Disable the default Jenkins Agent configuration | `false` |
| [agent.enabled](./values.yaml#L905) | bool | Enable Kubernetes plugin jnlp-agent podTemplate | `true` |
| [agent.envVars](./values.yaml#L1062) | list | Environment variables for the agent Pod | `[]` |
| [agent.hostNetworking](./values.yaml#L959) | bool | Enables the agent to use the host network | `false` |
| [agent.idleMinutes](./values.yaml#L1094) | int | Allows the Pod to remain active for reuse until the configured number of minutes has passed since the last step was executed on it | `0` |
| [agent.image.repository](./values.yaml#L938) | string | Repository to pull the agent jnlp image from | `"jenkins/inbound-agent"` |
| [agent.image.tag](./values.yaml#L940) | string | Tag of the image to pull | `"3256.v88a_f6e922152-1"` |
| [agent.imagePullSecretName](./values.yaml#L947) | string | Name of the secret to be used to pull the image | `nil` |
| [agent.inheritYamlMergeStrategy](./values.yaml#L1114) | bool | Controls whether the defined yaml merge strategy will be inherited if another defined pod template is configured to inherit from the current one | `false` |
| [agent.jenkinsTunnel](./values.yaml#L915) | string | Overrides the Kubernetes Jenkins tunnel | `nil` |
| [agent.jenkinsUrl](./values.yaml#L911) | string | Overrides the Kubernetes Jenkins URL | `nil` |
| [agent.jnlpregistry](./values.yaml#L935) | string | Custom registry used to pull the agent jnlp image from | `nil` |
| [agent.kubernetesConnectTimeout](./values.yaml#L921) | int | The connection timeout in seconds for connections to Kubernetes API. The minimum value is 5 | `5` |
| [agent.kubernetesReadTimeout](./values.yaml#L923) | int | The read timeout in seconds for connections to Kubernetes API. The minimum value is 15 | `15` |
| [agent.livenessProbe](./values.yaml#L970) | object | | `{}` |
| [agent.maxRequestsPerHostStr](./values.yaml#L925) | string | The maximum concurrent connections to Kubernetes API | `"32"` |
| [agent.namespace](./values.yaml#L931) | string | Namespace in which the Kubernetes agents should be launched | `nil` |
| [agent.nodeSelector](./values.yaml#L1073) | object | Node labels for pod assignment | `{}` |
| [agent.nodeUsageMode](./values.yaml#L943) | string | | `"NORMAL"` |
| [agent.podLabels](./values.yaml#L933) | object | Custom Pod labels (an object with `label-key: label-value` pairs) | `{}` |
| [agent.podName](./values.yaml#L1091) | string | Agent Pod base name | `"default"` |
| [agent.podRetention](./values.yaml#L989) | string | | `"Never"` |
| [agent.podTemplates](./values.yaml#L1150) | object | Configures extra pod templates for the default kubernetes cloud | `{}` |
| [agent.privileged](./values.yaml#L953) | bool | Agent privileged container | `false` |
| [agent.resources](./values.yaml#L961) | object | Resources allocation (Requests and Limits) | `{"limits":{"cpu":"512m","memory":"512Mi"},"requests":{"cpu":"512m","memory":"512Mi"}}` |
| [agent.restrictedPssSecurityContext](./values.yaml#L986) | bool | Set a restricted securityContext on jnlp containers | `false` |
| [agent.retentionTimeout](./values.yaml#L927) | int | Time in minutes after which the Kubernetes cloud plugin will clean up an idle worker that has not already terminated | `5` |
| [agent.runAsGroup](./values.yaml#L957) | string | Configure container group | `nil` |
| [agent.runAsUser](./values.yaml#L955) | string | Configure container user | `nil` |
| [agent.secretEnvVars](./values.yaml#L1066) | list | Mount a secret as environment variable | `[]` |
| [agent.showRawYaml](./values.yaml#L993) | bool | | `true` |
| [agent.sideContainerName](./values.yaml#L1083) | string | Side container name | `"jnlp"` |
| [agent.skipTlsVerify](./values.yaml#L917) | bool | Disables the verification of the controller certificate on remote connection. This flag correspond to the "Disable https certificate check" flag in kubernetes plugin UI | `false` |
| [agent.usageRestricted](./values.yaml#L919) | bool | Enable the possibility to restrict the usage of this agent to specific folder. This flag correspond to the "Restrict pipeline support to authorized folders" flag in kubernetes plugin UI | `false` |
| [agent.volumes](./values.yaml#L1000) | list | Additional volumes | `[]` |
| [agent.waitForPodSec](./values.yaml#L929) | int | Seconds to wait for pod to be running | `600` |
| [agent.websocket](./values.yaml#L950) | bool | Enables agent communication via websockets | `false` |
| [agent.workingDir](./values.yaml#L942) | string | Configure working directory for default agent | `"/home/jenkins/agent"` |
| [agent.workspaceVolume](./values.yaml#L1035) | object | Workspace volume (defaults to EmptyDir) | `{}` |
| [agent.yamlMergeStrategy](./values.yaml#L1112) | string | Defines how the raw yaml field gets merged with yaml definitions from inherited pod templates. Possible values: "merge" or "override" | `"override"` |
| [agent.yamlTemplate](./values.yaml#L1101) | string | The raw yaml of a Pod API Object to merge into the agent spec | `""` |
| [awsSecurityGroupPolicies.enabled](./values.yaml#L1320) | bool | | `false` |
| [awsSecurityGroupPolicies.policies[0].name](./values.yaml#L1322) | string | | `""` |
| [awsSecurityGroupPolicies.policies[0].podSelector](./values.yaml#L1324) | object | | `{}` |
| [awsSecurityGroupPolicies.policies[0].securityGroupIds](./values.yaml#L1323) | list | | `[]` |
| [checkDeprecation](./values.yaml#L1317) | bool | Checks if any deprecated values are used | `true` |
| [clusterZone](./values.yaml#L21) | string | Override the cluster name for FQDN resolving | `"cluster.local"` |
| [controller.JCasC.authorizationStrategy](./values.yaml#L533) | string | Jenkins Config as Code Authorization Strategy-section | `"loggedInUsersCanDoAnything:\n allowAnonymousRead: false"` |
| [controller.JCasC.configMapAnnotations](./values.yaml#L538) | object | Annotations for the JCasC ConfigMap | `{}` |
| [controller.JCasC.configScripts](./values.yaml#L507) | object | List of Jenkins Config as Code scripts | `{}` |
| [controller.JCasC.configUrls](./values.yaml#L504) | list | Remote URLs for configuration files. | `[]` |
| [controller.JCasC.defaultConfig](./values.yaml#L498) | bool | Enables default Jenkins configuration via configuration as code plugin | `true` |
| [controller.JCasC.overwriteConfiguration](./values.yaml#L502) | bool | Whether Jenkins Config as Code should overwrite any existing configuration | `false` |
| [controller.JCasC.security](./values.yaml#L514) | object | Jenkins Config as Code security-section | `{"apiToken":{"creationOfLegacyTokenEnabled":false,"tokenGenerationOnCreationEnabled":false,"usageStatisticsEnabled":true}}` |
| [controller.JCasC.securityRealm](./values.yaml#L522) | string | Jenkins Config as Code Security Realm-section | `"local:\n allowsSignup: false\n enableCaptcha: false\n users:\n - id: \"${chart-admin-username}\"\n name: \"Jenkins Admin\"\n password: \"${chart-admin-password}\""` |
| [controller.additionalExistingSecrets](./values.yaml#L459) | list | List of additional existing secrets to mount | `[]` |
| [controller.additionalPlugins](./values.yaml#L409) | list | List of plugins to install in addition to those listed in controller.installPlugins | `[]` |
| [controller.additionalSecrets](./values.yaml#L468) | list | List of additional secrets to create and mount | `[]` |
| [controller.admin.createSecret](./values.yaml#L91) | bool | Create secret for admin user | `true` |
| [controller.admin.existingSecret](./values.yaml#L94) | string | The name of an existing secret containing the admin credentials | `""` |
| [controller.admin.password](./values.yaml#L81) | string | Admin password created as a secret if `controller.admin.createSecret` is true | `<random password>` |
| [controller.admin.passwordKey](./values.yaml#L86) | string | The key in the existing admin secret containing the password | `"jenkins-admin-password"` |
| [controller.admin.userKey](./values.yaml#L84) | string | The key in the existing admin secret containing the username | `"jenkins-admin-user"` |
| [controller.admin.username](./values.yaml#L78) | string | Admin username created as a secret if `controller.admin.createSecret` is true | `"admin"` |
| [controller.affinity](./values.yaml#L660) | object | Affinity settings | `{}` |
| [controller.agentListenerEnabled](./values.yaml#L318) | bool | Create Agent listener service | `true` |
| [controller.agentListenerExternalTrafficPolicy](./values.yaml#L328) | string | Traffic Policy of for the agentListener service | `nil` |
| [controller.agentListenerHostPort](./values.yaml#L322) | string | Host port to listen for agents | `nil` |
| [controller.agentListenerLoadBalancerIP](./values.yaml#L358) | string | Static IP for the agentListener LoadBalancer | `nil` |
| [controller.agentListenerLoadBalancerSourceRanges](./values.yaml#L330) | list | Allowed inbound IP for the agentListener service | `["0.0.0.0/0"]` |
| [controller.agentListenerNodePort](./values.yaml#L324) | string | Node port to listen for agents | `nil` |
| [controller.agentListenerPort](./values.yaml#L320) | int | Listening port for agents | `50000` |
| [controller.agentListenerServiceAnnotations](./values.yaml#L353) | object | Annotations for the agentListener service | `{}` |
| [controller.agentListenerServiceType](./values.yaml#L350) | string | Defines how to expose the agentListener service | `"ClusterIP"` |
| [controller.backendconfig.annotations](./values.yaml#L763) | object | backendconfig annotations | `{}` |
| [controller.backendconfig.apiVersion](./values.yaml#L757) | string | backendconfig API version | `"extensions/v1beta1"` |
| [controller.backendconfig.enabled](./values.yaml#L755) | bool | Enables backendconfig | `false` |
| [controller.backendconfig.labels](./values.yaml#L761) | object | backendconfig labels | `{}` |
| [controller.backendconfig.name](./values.yaml#L759) | string | backendconfig name | `nil` |
| [controller.backendconfig.spec](./values.yaml#L765) | object | backendconfig spec | `{}` |
| [controller.cloudName](./values.yaml#L487) | string | Name of default cloud configuration. | `"kubernetes"` |
| [controller.clusterIp](./values.yaml#L217) | string | k8s service clusterIP. Only used if serviceType is ClusterIP | `nil` |
| [controller.componentName](./values.yaml#L34) | string | Used for label app.kubernetes.io/component | `"jenkins-controller"` |
| [controller.containerEnv](./values.yaml#L150) | list | Environment variables for Jenkins Container | `[]` |
| [controller.containerEnvFrom](./values.yaml#L147) | list | Environment variable sources for Jenkins Container | `[]` |
| [controller.containerSecurityContext](./values.yaml#L205) | object | Allow controlling the securityContext for the jenkins container | `{"allowPrivilegeEscalation":false,"readOnlyRootFilesystem":true,"runAsGroup":1000,"runAsUser":1000}` |
| [controller.csrf.defaultCrumbIssuer.enabled](./values.yaml#L339) | bool | Enable the default CSRF Crumb issuer | `true` |
| [controller.csrf.defaultCrumbIssuer.proxyCompatability](./values.yaml#L341) | bool | Enable proxy compatibility | `true` |
| [controller.customInitContainers](./values.yaml#L541) | list | Custom init-container specification in raw-yaml format | `[]` |
| [controller.customJenkinsLabels](./values.yaml#L68) | list | Append Jenkins labels to the controller | `[]` |
| [controller.disableRememberMe](./values.yaml#L59) | bool | Disable use of remember me | `false` |
| [controller.disabledAgentProtocols](./values.yaml#L333) | list | Disabled agent protocols | `["JNLP-connect","JNLP2-connect"]` |
| [controller.enableRawHtmlMarkupFormatter](./values.yaml#L429) | bool | Enable HTML parsing using OWASP Markup Formatter Plugin (antisamy-markup-formatter) | `false` |
| [controller.executorMode](./values.yaml#L65) | string | Sets the executor mode of the Jenkins node. Possible values are "NORMAL" or "EXCLUSIVE" | `"NORMAL"` |
| [controller.existingSecret](./values.yaml#L456) | string | | `nil` |
| [controller.extraPorts](./values.yaml#L388) | list | Optionally configure other ports to expose in the controller container | `[]` |
| [controller.fsGroup](./values.yaml#L186) | int | Deprecated in favor of `controller.podSecurityContextOverride`. uid that will be used for persistent volume. | `1000` |
| [controller.googlePodMonitor.enabled](./values.yaml#L826) | bool | | `false` |
| [controller.googlePodMonitor.scrapeEndpoint](./values.yaml#L831) | string | | `"/prometheus"` |
| [controller.googlePodMonitor.scrapeInterval](./values.yaml#L829) | string | | `"60s"` |
| [controller.healthProbes](./values.yaml#L248) | bool | Enable Kubernetes Probes configuration configured in `controller.probes` | `true` |
| [controller.hostAliases](./values.yaml#L779) | list | Allows for adding entries to Pod /etc/hosts | `[]` |
| [controller.hostNetworking](./values.yaml#L70) | bool | | `false` |
| [controller.httpsKeyStore.disableSecretMount](./values.yaml#L847) | bool | | `false` |
| [controller.httpsKeyStore.enable](./values.yaml#L838) | bool | Enables HTTPS keystore on jenkins controller | `false` |
| [controller.httpsKeyStore.fileName](./values.yaml#L855) | string | Jenkins keystore filename which will appear under controller.httpsKeyStore.path | `"keystore.jks"` |
| [controller.httpsKeyStore.httpPort](./values.yaml#L851) | int | HTTP Port that Jenkins should listen to along with HTTPS, it also serves as the liveness and readiness probes port. | `8081` |
| [controller.httpsKeyStore.jenkinsHttpsJksPasswordSecretKey](./values.yaml#L846) | string | Name of the key in the secret that contains the JKS password | `"https-jks-password"` |
| [controller.httpsKeyStore.jenkinsHttpsJksPasswordSecretName](./values.yaml#L844) | string | Name of the secret that contains the JKS password, if it is not in the same secret as the JKS file | `""` |
| [controller.httpsKeyStore.jenkinsHttpsJksSecretKey](./values.yaml#L842) | string | Name of the key in the secret that already has ssl keystore | `"jenkins-jks-file"` |
| [controller.httpsKeyStore.jenkinsHttpsJksSecretName](./values.yaml#L840) | string | Name of the secret that already has ssl keystore | `""` |
| [controller.httpsKeyStore.jenkinsKeyStoreBase64Encoded](./values.yaml#L860) | string | Base64 encoded Keystore content. Keystore must be converted to base64 then being pasted here | `nil` |
| [controller.httpsKeyStore.password](./values.yaml#L857) | string | Jenkins keystore password | `"password"` |
| [controller.httpsKeyStore.path](./values.yaml#L853) | string | Path of HTTPS keystore file | `"/var/jenkins_keystore"` |
| [controller.image.pullPolicy](./values.yaml#L47) | string | Controller image pull policy | `"Always"` |
| [controller.image.registry](./values.yaml#L37) | string | Controller image registry | `"docker.io"` |
| [controller.image.repository](./values.yaml#L39) | string | Controller image repository | `"jenkins/jenkins"` |
| [controller.image.tag](./values.yaml#L42) | string | Controller image tag override; i.e., tag: "2.440.1-jdk17" | `nil` |
| [controller.image.tagLabel](./values.yaml#L45) | string | Controller image tag label | `"jdk17"` |
| [controller.imagePullSecretName](./values.yaml#L49) | string | Controller image pull secret | `nil` |
| [controller.ingress.annotations](./values.yaml#L702) | object | Ingress annotations | `{}` |
| [controller.ingress.apiVersion](./values.yaml#L698) | string | Ingress API version | `"extensions/v1beta1"` |
| [controller.ingress.enabled](./values.yaml#L681) | bool | Enables ingress | `false` |
| [controller.ingress.hostName](./values.yaml#L715) | string | Ingress hostname | `nil` |
| [controller.ingress.labels](./values.yaml#L700) | object | Ingress labels | `{}` |
| [controller.ingress.path](./values.yaml#L711) | string | Ingress path | `nil` |
| [controller.ingress.paths](./values.yaml#L685) | list | Override for the default Ingress paths | `[]` |
| [controller.ingress.resourceRootUrl](./values.yaml#L717) | string | Hostname to serve assets from | `nil` |
| [controller.ingress.tls](./values.yaml#L719) | list | Ingress TLS configuration | `[]` |
| [controller.initConfigMap](./values.yaml#L446) | string | Name of the existing ConfigMap that contains init scripts | `nil` |
| [controller.initContainerEnv](./values.yaml#L141) | list | Environment variables for Init Container | `[]` |
| [controller.initContainerEnvFrom](./values.yaml#L137) | list | Environment variable sources for Init Container | `[]` |
| [controller.initContainerResources](./values.yaml#L128) | object | Resources allocation (Requests and Limits) for Init Container | `{}` |
| [controller.initScripts](./values.yaml#L442) | object | Map of groovy init scripts to be executed during Jenkins controller start | `{}` |
| [controller.initializeOnce](./values.yaml#L414) | bool | Initialize only on first installation. Ensures plugins do not get updated inadvertently. Requires `persistence.enabled` to be set to `true` | `false` |
| [controller.installLatestPlugins](./values.yaml#L403) | bool | Download the minimum required version or latest version of all dependencies | `true` |
| [controller.installLatestSpecifiedPlugins](./values.yaml#L406) | bool | Set to true to download the latest version of any plugin that is requested to have the latest version | `false` |
| [controller.installPlugins](./values.yaml#L395) | list | List of Jenkins plugins to install. If you don't want to install plugins, set it to `false` | `["kubernetes:4253.v7700d91739e5","workflow-aggregator:600.vb_57cdd26fdd7","git:5.2.2","configuration-as-code:1836.vccda_4a_122a_a_e"]` |
| [controller.javaOpts](./values.yaml#L156) | string | Append to `JAVA_OPTS` env var | `nil` |
| [controller.jenkinsAdminEmail](./values.yaml#L96) | string | Email address for the administrator of the Jenkins instance | `nil` |
| [controller.jenkinsHome](./values.yaml#L101) | string | Custom Jenkins home path | `"/var/jenkins_home"` |
| [controller.jenkinsOpts](./values.yaml#L158) | string | Append to `JENKINS_OPTS` env var | `nil` |
| [controller.jenkinsRef](./values.yaml#L106) | string | Custom Jenkins reference path | `"/usr/share/jenkins/ref"` |
| [controller.jenkinsUriPrefix](./values.yaml#L173) | string | Root URI Jenkins will be served on | `nil` |
| [controller.jenkinsUrl](./values.yaml#L168) | string | Set Jenkins URL if you are not using the ingress definitions provided by the chart | `nil` |
| [controller.jenkinsUrlProtocol](./values.yaml#L165) | string | Set protocol for Jenkins URL; `https` if `controller.ingress.tls`, `http` otherwise | `nil` |
| [controller.jenkinsWar](./values.yaml#L109) | string | | `"/usr/share/jenkins/jenkins.war"` |
| [controller.jmxPort](./values.yaml#L385) | string | Open a port, for JMX stats | `nil` |
| [controller.legacyRemotingSecurityEnabled](./values.yaml#L361) | bool | Whether legacy remoting security should be enabled | `false` |
| [controller.lifecycle](./values.yaml#L51) | object | Lifecycle specification for controller-container | `{}` |
| [controller.loadBalancerIP](./values.yaml#L376) | string | Optionally assign a known public LB IP | `nil` |
| [controller.loadBalancerSourceRanges](./values.yaml#L372) | list | Allowed inbound IP addresses | `["0.0.0.0/0"]` |
| [controller.markupFormatter](./values.yaml#L433) | string | Yaml of the markup formatter to use | `"plainText"` |
| [controller.nodePort](./values.yaml#L223) | string | k8s node port. Only used if serviceType is NodePort | `nil` |
| [controller.nodeSelector](./values.yaml#L647) | object | Node labels for pod assignment | `{}` |
| [controller.numExecutors](./values.yaml#L62) | int | Set Number of executors | `0` |
| [controller.overwritePlugins](./values.yaml#L418) | bool | Overwrite installed plugins on start | `false` |
| [controller.overwritePluginsFromImage](./values.yaml#L422) | bool | Overwrite plugins that are already installed in the controller image | `true` |
| [controller.podAnnotations](./values.yaml#L668) | object | Annotations for controller pod | `{}` |
| [controller.podDisruptionBudget.annotations](./values.yaml#L312) | object | | `{}` |
| [controller.podDisruptionBudget.apiVersion](./values.yaml#L310) | string | Policy API version | `"policy/v1beta1"` |
| [controller.podDisruptionBudget.enabled](./values.yaml#L305) | bool | Enable Kubernetes Pod Disruption Budget configuration | `false` |
| [controller.podDisruptionBudget.labels](./values.yaml#L313) | object | | `{}` |
| [controller.podDisruptionBudget.maxUnavailable](./values.yaml#L315) | string | Number of pods that can be unavailable. Either an absolute number or a percentage | `"0"` |
| [controller.podLabels](./values.yaml#L241) | object | Custom Pod labels (an object with `label-key: label-value` pairs) | `{}` |
| [controller.podSecurityContextOverride](./values.yaml#L202) | string | Completely overwrites the contents of the pod security context, ignoring the values provided for `runAsUser`, `fsGroup`, and `securityContextCapabilities` | `nil` |
| [controller.priorityClassName](./values.yaml#L665) | string | The name of a `priorityClass` to apply to the controller pod | `nil` |
| [controller.probes.livenessProbe.failureThreshold](./values.yaml#L266) | int | Set the failure threshold for the liveness probe | `5` |
| [controller.probes.livenessProbe.httpGet.path](./values.yaml#L269) | string | Set the Pod's HTTP path for the liveness probe | `"{{ default \"\" .Values.controller.jenkinsUriPrefix }}/login"` |
| [controller.probes.livenessProbe.httpGet.port](./values.yaml#L271) | string | Set the Pod's HTTP port to use for the liveness probe | `"http"` |
| [controller.probes.livenessProbe.initialDelaySeconds](./values.yaml#L280) | string | Set the initial delay for the liveness probe in seconds | `nil` |
| [controller.probes.livenessProbe.periodSeconds](./values.yaml#L273) | int | Set the time interval between two liveness probes executions in seconds | `10` |
| [controller.probes.livenessProbe.timeoutSeconds](./values.yaml#L275) | int | Set the timeout for the liveness probe in seconds | `5` |
| [controller.probes.readinessProbe.failureThreshold](./values.yaml#L284) | int | Set the failure threshold for the readiness probe | `3` |
| [controller.probes.readinessProbe.httpGet.path](./values.yaml#L287) | string | Set the Pod's HTTP path for the liveness probe | `"{{ default \"\" .Values.controller.jenkinsUriPrefix }}/login"` |
| [controller.probes.readinessProbe.httpGet.port](./values.yaml#L289) | string | Set the Pod's HTTP port to use for the readiness probe | `"http"` |
| [controller.probes.readinessProbe.initialDelaySeconds](./values.yaml#L298) | string | Set the initial delay for the readiness probe in seconds | `nil` |
| [controller.probes.readinessProbe.periodSeconds](./values.yaml#L291) | int | Set the time interval between two readiness probes executions in seconds | `10` |
| [controller.probes.readinessProbe.timeoutSeconds](./values.yaml#L293) | int | Set the timeout for the readiness probe in seconds | `5` |
| [controller.probes.startupProbe.failureThreshold](./values.yaml#L253) | int | Set the failure threshold for the startup probe | `12` |
| [controller.probes.startupProbe.httpGet.path](./values.yaml#L256) | string | Set the Pod's HTTP path for the startup probe | `"{{ default \"\" .Values.controller.jenkinsUriPrefix }}/login"` |
| [controller.probes.startupProbe.httpGet.port](./values.yaml#L258) | string | Set the Pod's HTTP port to use for the startup probe | `"http"` |
| [controller.probes.startupProbe.periodSeconds](./values.yaml#L260) | int | Set the time interval between two startup probes executions in seconds | `10` |
| [controller.probes.startupProbe.timeoutSeconds](./values.yaml#L262) | int | Set the timeout for the startup probe in seconds | `5` |
| [controller.projectNamingStrategy](./values.yaml#L425) | string | | `"standard"` |
| [controller.prometheus.alertingRulesAdditionalLabels](./values.yaml#L812) | object | Additional labels to add to the PrometheusRule object | `{}` |
| [controller.prometheus.alertingrules](./values.yaml#L810) | list | Array of prometheus alerting rules | `[]` |
| [controller.prometheus.enabled](./values.yaml#L795) | bool | Enables prometheus service monitor | `false` |
| [controller.prometheus.metricRelabelings](./values.yaml#L822) | list | | `[]` |
| [controller.prometheus.prometheusRuleNamespace](./values.yaml#L814) | string | Set a custom namespace where to deploy PrometheusRule resource | `""` |
| [controller.prometheus.relabelings](./values.yaml#L820) | list | | `[]` |
| [controller.prometheus.scrapeEndpoint](./values.yaml#L805) | string | The endpoint prometheus should get metrics from | `"/prometheus"` |
| [controller.prometheus.scrapeInterval](./values.yaml#L801) | string | How often prometheus should scrape metrics | `"60s"` |
| [controller.prometheus.serviceMonitorAdditionalLabels](./values.yaml#L797) | object | Additional labels to add to the service monitor object | `{}` |
| [controller.prometheus.serviceMonitorNamespace](./values.yaml#L799) | string | Set a custom namespace where to deploy ServiceMonitor resource | `nil` |
| [controller.resources](./values.yaml#L115) | object | Resource allocation (Requests and Limits) | `{"limits":{"cpu":"2000m","memory":"4096Mi"},"requests":{"cpu":"50m","memory":"256Mi"}}` |
| [controller.route.annotations](./values.yaml#L774) | object | Route annotations | `{}` |
| [controller.route.enabled](./values.yaml#L770) | bool | Enables openshift route | `false` |
| [controller.route.labels](./values.yaml#L772) | object | Route labels | `{}` |
| [controller.route.path](./values.yaml#L776) | string | Route path | `nil` |
| [controller.runAsUser](./values.yaml#L183) | int | Deprecated in favor of `controller.podSecurityContextOverride`. uid that jenkins runs with. | `1000` |
| [controller.schedulerName](./values.yaml#L643) | string | Name of the Kubernetes scheduler to use | `""` |
| [controller.scriptApproval](./values.yaml#L437) | list | List of groovy functions to approve | `[]` |
| [controller.secondaryingress.annotations](./values.yaml#L737) | object | | `{}` |
| [controller.secondaryingress.apiVersion](./values.yaml#L735) | string | | `"extensions/v1beta1"` |
| [controller.secondaryingress.enabled](./values.yaml#L729) | bool | | `false` |
| [controller.secondaryingress.hostName](./values.yaml#L744) | string | | `nil` |
| [controller.secondaryingress.labels](./values.yaml#L736) | object | | `{}` |
| [controller.secondaryingress.paths](./values.yaml#L732) | list | | `[]` |
| [controller.secondaryingress.tls](./values.yaml#L745) | string | | `nil` |
| [controller.secretClaims](./values.yaml#L480) | list | List of `SecretClaim` resources to create | `[]` |
| [controller.securityContextCapabilities](./values.yaml#L192) | object | | `{}` |
| [controller.serviceAnnotations](./values.yaml#L230) | object | Jenkins controller service annotations | `{}` |
| [controller.serviceExternalTrafficPolicy](./values.yaml#L227) | string | | `nil` |
| [controller.serviceLabels](./values.yaml#L236) | object | Labels for the Jenkins controller-service | `{}` |
| [controller.servicePort](./values.yaml#L219) | int | k8s service port | `8080` |
| [controller.serviceType](./values.yaml#L214) | string | k8s service type | `"ClusterIP"` |
| [controller.shareProcessNamespace](./values.yaml#L124) | bool | | `false` |
| [controller.sidecars.additionalSidecarContainers](./values.yaml#L625) | list | Configures additional sidecar container(s) for the Jenkins controller | `[]` |
| [controller.sidecars.configAutoReload.additionalVolumeMounts](./values.yaml#L571) | list | Enables additional volume mounts for the config auto-reload container | `[]` |
| [controller.sidecars.configAutoReload.containerSecurityContext](./values.yaml#L620) | object | Enable container security context | `{"allowPrivilegeEscalation":false,"readOnlyRootFilesystem":true}` |
| [controller.sidecars.configAutoReload.enabled](./values.yaml#L554) | bool | Enables Jenkins Config as Code auto-reload | `true` |
| [controller.sidecars.configAutoReload.env](./values.yaml#L602) | object | Environment variables for the Jenkins Config as Code auto-reload container | `{}` |
| [controller.sidecars.configAutoReload.envFrom](./values.yaml#L600) | list | Environment variable sources for the Jenkins Config as Code auto-reload container | `[]` |
| [controller.sidecars.configAutoReload.folder](./values.yaml#L613) | string | | `"/var/jenkins_home/casc_configs"` |
| [controller.sidecars.configAutoReload.image.registry](./values.yaml#L557) | string | Registry for the image that triggers the reload | `"docker.io"` |
| [controller.sidecars.configAutoReload.image.repository](./values.yaml#L559) | string | Repository of the image that triggers the reload | `"kiwigrid/k8s-sidecar"` |
| [controller.sidecars.configAutoReload.image.tag](./values.yaml#L561) | string | Tag for the image that triggers the reload | `"1.27.5"` |
| [controller.sidecars.configAutoReload.imagePullPolicy](./values.yaml#L562) | string | | `"IfNotPresent"` |
| [controller.sidecars.configAutoReload.logging](./values.yaml#L577) | object | Config auto-reload logging settings | `{"configuration":{"backupCount":3,"formatter":"JSON","logLevel":"INFO","logToConsole":true,"logToFile":false,"maxBytes":1024,"override":false}}` |
| [controller.sidecars.configAutoReload.logging.configuration.override](./values.yaml#L581) | bool | Enables custom log config utilizing using the settings below. | `false` |
| [controller.sidecars.configAutoReload.reqRetryConnect](./values.yaml#L595) | int | How many connection-related errors to retry on | `10` |
| [controller.sidecars.configAutoReload.resources](./values.yaml#L563) | object | | `{}` |
| [controller.sidecars.configAutoReload.scheme](./values.yaml#L590) | string | The scheme to use when connecting to the Jenkins configuration as code endpoint | `"http"` |
| [controller.sidecars.configAutoReload.skipTlsVerify](./values.yaml#L592) | bool | Skip TLS verification when connecting to the Jenkins configuration as code endpoint | `false` |
| [controller.sidecars.configAutoReload.sleepTime](./values.yaml#L597) | string | How many seconds to wait before updating config-maps/secrets (sets METHOD=SLEEP on the sidecar) | `nil` |
| [controller.sidecars.configAutoReload.sshTcpPort](./values.yaml#L611) | int | | `1044` |
| [controller.statefulSetAnnotations](./values.yaml#L670) | object | Annotations for controller StatefulSet | `{}` |
| [controller.statefulSetLabels](./values.yaml#L232) | object | Jenkins controller custom labels for the StatefulSet | `{}` |
| [controller.targetPort](./values.yaml#L221) | int | k8s target port | `8080` |
| [controller.terminationGracePeriodSeconds](./values.yaml#L653) | string | Set TerminationGracePeriodSeconds | `nil` |
| [controller.terminationMessagePath](./values.yaml#L655) | string | Set the termination message path | `nil` |
| [controller.terminationMessagePolicy](./values.yaml#L657) | string | Set the termination message policy | `nil` |
| [controller.testEnabled](./values.yaml#L834) | bool | Can be used to disable rendering controller test resources when using helm template | `true` |
| [controller.tolerations](./values.yaml#L651) | list | Toleration labels for pod assignment | `[]` |
| [controller.topologySpreadConstraints](./values.yaml#L677) | object | Topology spread constraints | `{}` |
| [controller.updateStrategy](./values.yaml#L674) | object | Update strategy for StatefulSet | `{}` |
| [controller.usePodSecurityContext](./values.yaml#L176) | bool | Enable pod security context (must be `true` if podSecurityContextOverride, runAsUser or fsGroup are set) | `true` |
| [credentialsId](./values.yaml#L27) | string | The Jenkins credentials to access the Kubernetes API server. For the default cluster it is not needed. | `nil` |
| [fullnameOverride](./values.yaml#L13) | string | Override the full resource names | `jenkins-(release-name)` or `jenkins` if the release-name is `jenkins` |
| [helmtest.bats.image.registry](./values.yaml#L1333) | string | Registry of the image used to test the framework | `"docker.io"` |
| [helmtest.bats.image.repository](./values.yaml#L1335) | string | Repository of the image used to test the framework | `"bats/bats"` |
| [helmtest.bats.image.tag](./values.yaml#L1337) | string | Tag of the image to test the framework | `"1.11.0"` |
| [kubernetesURL](./values.yaml#L24) | string | The URL of the Kubernetes API server | `"https://kubernetes.default"` |
| [nameOverride](./values.yaml#L10) | string | Override the resource name prefix | `Chart.Name` |
| [namespaceOverride](./values.yaml#L16) | string | Override the deployment namespace | `Release.Namespace` |
| [networkPolicy.apiVersion](./values.yaml#L1263) | string | NetworkPolicy ApiVersion | `"networking.k8s.io/v1"` |
| [networkPolicy.enabled](./values.yaml#L1258) | bool | Enable the creation of NetworkPolicy resources | `false` |
| [networkPolicy.externalAgents.except](./values.yaml#L1277) | list | A list of IP sub-ranges to be excluded from the allowlisted IP range | `[]` |
| [networkPolicy.externalAgents.ipCIDR](./values.yaml#L1275) | string | The IP range from which external agents are allowed to connect to controller, i.e., 172.17.0.0/16 | `nil` |
| [networkPolicy.internalAgents.allowed](./values.yaml#L1267) | bool | Allow internal agents (from the same cluster) to connect to controller. Agent pods will be filtered based on PodLabels | `true` |
| [networkPolicy.internalAgents.namespaceLabels](./values.yaml#L1271) | object | A map of labels (keys/values) that agents namespaces must have to be able to connect to controller | `{}` |
| [networkPolicy.internalAgents.podLabels](./values.yaml#L1269) | object | A map of labels (keys/values) that agent pods must have to be able to connect to controller | `{}` |
| [persistence.accessMode](./values.yaml#L1233) | string | The PVC access mode | `"ReadWriteOnce"` |
| [persistence.annotations](./values.yaml#L1229) | object | Annotations for the PVC | `{}` |
| [persistence.dataSource](./values.yaml#L1239) | object | Existing data source to clone PVC from | `{}` |
| [persistence.enabled](./values.yaml#L1213) | bool | Enable the use of a Jenkins PVC | `true` |
| [persistence.existingClaim](./values.yaml#L1219) | string | Provide the name of a PVC | `nil` |
| [persistence.labels](./values.yaml#L1231) | object | Labels for the PVC | `{}` |
| [persistence.mounts](./values.yaml#L1251) | list | Additional mounts | `[]` |
| [persistence.size](./values.yaml#L1235) | string | The size of the PVC | `"8Gi"` |
| [persistence.storageClass](./values.yaml#L1227) | string | Storage class for the PVC | `nil` |
| [persistence.subPath](./values.yaml#L1244) | string | SubPath for jenkins-home mount | `nil` |
| [persistence.volumes](./values.yaml#L1246) | list | Additional volumes | `[]` |
| [rbac.create](./values.yaml#L1283) | bool | Whether RBAC resources are created | `true` |
| [rbac.readSecrets](./values.yaml#L1285) | bool | Whether the Jenkins service account should be able to read Kubernetes secrets | `false` |
| [renderHelmLabels](./values.yaml#L30) | bool | Enables rendering of the helm.sh/chart label to the annotations | `true` |
| [serviceAccount.annotations](./values.yaml#L1295) | object | Configures annotations for the ServiceAccount | `{}` |
| [serviceAccount.create](./values.yaml#L1289) | bool | Configures if a ServiceAccount with this name should be created | `true` |
| [serviceAccount.extraLabels](./values.yaml#L1297) | object | Configures extra labels for the ServiceAccount | `{}` |
| [serviceAccount.imagePullSecretName](./values.yaml#L1299) | string | Controller ServiceAccount image pull secret | `nil` |
| [serviceAccount.name](./values.yaml#L1293) | string | | `nil` |
| [serviceAccountAgent.annotations](./values.yaml#L1310) | object | Configures annotations for the agent ServiceAccount | `{}` |
| [serviceAccountAgent.create](./values.yaml#L1304) | bool | Configures if an agent ServiceAccount should be created | `false` |
| [serviceAccountAgent.extraLabels](./values.yaml#L1312) | object | Configures extra labels for the agent ServiceAccount | `{}` |
| [serviceAccountAgent.imagePullSecretName](./values.yaml#L1314) | string | Agent ServiceAccount image pull secret | `nil` |
| [serviceAccountAgent.name](./values.yaml#L1308) | string | The name of the agent ServiceAccount to be used by access-controlled resources | `nil` |

View File

@ -0,0 +1,28 @@
# Jenkins
## Configuration
The following tables list the configurable parameters of the Jenkins chart and their default values.
{{- define "chart.valueDefaultColumnRender" -}}
{{- $defaultValue := (trimAll "`" (default .Default .AutoDefault) | replace "\n" "") -}}
`{{- $defaultValue | replace "\n" "" -}}`
{{- end -}}
{{- define "chart.typeColumnRender" -}}
{{- .Type -}}
{{- end -}}
{{- define "chart.valueDescription" -}}
{{- default .Description .AutoDescription }}
{{- end -}}
{{- define "chart.valuesTable" -}}
| Key | Type | Description | Default |
|:----|:-----|:---------|:------------|
{{- range .Values }}
| [{{ .Key }}](./values.yaml#L{{ .LineNumber }}) | {{ template "chart.typeColumnRender" . }} | {{ template "chart.valueDescription" . }} | {{ template "chart.valueDefaultColumnRender" . }} |
{{- end }}
{{- end }}
{{ template "chart.valuesSection" . }}

View File

@ -0,0 +1,68 @@
{{- $prefix := .Values.controller.jenkinsUriPrefix | default "" -}}
{{- $url := "" -}}
1. Get your '{{ .Values.controller.admin.username }}' user password by running:
kubectl exec --namespace {{ template "jenkins.namespace" . }} -it svc/{{ template "jenkins.fullname" . }} -c jenkins -- /bin/cat /run/secrets/additional/chart-admin-password && echo
{{- if .Values.controller.ingress.hostName -}}
{{- if .Values.controller.ingress.tls -}}
{{- $url = print "https://" .Values.controller.ingress.hostName $prefix -}}
{{- else -}}
{{- $url = print "http://" .Values.controller.ingress.hostName $prefix -}}
{{- end }}
2. Visit {{ $url }}
{{- else }}
2. Get the Jenkins URL to visit by running these commands in the same shell:
{{- if contains "NodePort" .Values.controller.serviceType }}
export NODE_PORT=$(kubectl get --namespace {{ template "jenkins.namespace" . }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "jenkins.fullname" . }})
export NODE_IP=$(kubectl get nodes --namespace {{ template "jenkins.namespace" . }} -o jsonpath="{.items[0].status.addresses[0].address}")
{{- if .Values.controller.httpsKeyStore.enable -}}
{{- $url = print "https://$NODE_IP:$NODE_PORT" $prefix -}}
{{- else -}}
{{- $url = print "http://$NODE_IP:$NODE_PORT" $prefix -}}
{{- end }}
echo {{ $url }}
{{- else if contains "LoadBalancer" .Values.controller.serviceType }}
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
You can watch the status of by running 'kubectl get svc --namespace {{ template "jenkins.namespace" . }} -w {{ template "jenkins.fullname" . }}'
export SERVICE_IP=$(kubectl get svc --namespace {{ template "jenkins.namespace" . }} {{ template "jenkins.fullname" . }} --template "{{ "{{ range (index .status.loadBalancer.ingress 0) }}{{ . }}{{ end }}" }}")
{{- if .Values.controller.httpsKeyStore.enable -}}
{{- $url = print "https://$SERVICE_IP:" .Values.controller.servicePort $prefix -}}
{{- else -}}
{{- $url = print "http://$SERVICE_IP:" .Values.controller.servicePort $prefix -}}
{{- end }}
echo {{ $url }}
{{- else if contains "ClusterIP" .Values.controller.serviceType -}}
{{- if .Values.controller.httpsKeyStore.enable -}}
{{- $url = print "https://127.0.0.1:" .Values.controller.servicePort $prefix -}}
{{- else -}}
{{- $url = print "http://127.0.0.1:" .Values.controller.servicePort $prefix -}}
{{- end }}
echo {{ $url }}
kubectl --namespace {{ template "jenkins.namespace" . }} port-forward svc/{{template "jenkins.fullname" . }} {{ .Values.controller.servicePort }}:{{ .Values.controller.servicePort }}
{{- end }}
{{- end }}
3. Login with the password from step 1 and the username: {{ .Values.controller.admin.username }}
4. Configure security realm and authorization strategy
5. Use Jenkins Configuration as Code by specifying configScripts in your values.yaml file, see documentation: {{ $url }}/configuration-as-code and examples: https://github.com/jenkinsci/configuration-as-code-plugin/tree/master/demos
For more information on running Jenkins on Kubernetes, visit:
https://cloud.google.com/solutions/jenkins-on-container-engine
For more information about Jenkins Configuration as Code, visit:
https://jenkins.io/projects/jcasc/
{{ if and (eq .Values.controller.image.repository "jenkins/jenkins") (eq .Values.controller.image.registry "docker.io") }}
NOTE: Consider using a custom image with pre-installed plugins
{{- else if .Values.controller.installPlugins }}
NOTE: Consider disabling `installPlugins` if your image already contains plugins.
{{- end }}
{{- if .Values.persistence.enabled }}
{{- else }}
#################################################################################
###### WARNING: Persistence is disabled!!! You will lose your data when #####
###### the Jenkins pod is terminated. #####
#################################################################################
{{- end }}

View File

@ -0,0 +1,673 @@
{{/* vim: set filetype=mustache: */}}
{{/*
Expand the name of the chart.
*/}}
{{- define "jenkins.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{/*
Expand the label of the chart.
*/}}
{{- define "jenkins.label" -}}
{{- printf "%s-%s" (include "jenkins.name" .) .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{/*
Allow the release namespace to be overridden for multi-namespace deployments in combined charts.
*/}}
{{- define "jenkins.namespace" -}}
{{- if .Values.namespaceOverride -}}
{{- .Values.namespaceOverride -}}
{{- else -}}
{{- .Release.Namespace -}}
{{- end -}}
{{- end -}}
{{- define "jenkins.agent.namespace" -}}
{{- if .Values.agent.namespace -}}
{{- tpl .Values.agent.namespace . -}}
{{- else -}}
{{- if .Values.namespaceOverride -}}
{{- .Values.namespaceOverride -}}
{{- else -}}
{{- .Release.Namespace -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "jenkins.fullname" -}}
{{- if .Values.fullnameOverride -}}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- $name := default .Chart.Name .Values.nameOverride -}}
{{- if contains $name .Release.Name -}}
{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{/*
Returns the admin password
https://github.com/helm/charts/issues/5167#issuecomment-619137759
*/}}
{{- define "jenkins.password" -}}
{{- if .Values.controller.admin.password -}}
{{- .Values.controller.admin.password | b64enc | quote }}
{{- else -}}
{{- $secret := (lookup "v1" "Secret" .Release.Namespace (include "jenkins.fullname" .)).data -}}
{{- if $secret -}}
{{/*
Reusing current password since secret exists
*/}}
{{- index $secret ( .Values.controller.admin.passwordKey | default "jenkins-admin-password" ) -}}
{{- else -}}
{{/*
Generate new password
*/}}
{{- randAlphaNum 22 | b64enc | quote }}
{{- end -}}
{{- end -}}
{{- end -}}
{{/*
Returns the Jenkins URL
*/}}
{{- define "jenkins.url" -}}
{{- if .Values.controller.jenkinsUrl }}
{{- .Values.controller.jenkinsUrl }}
{{- else }}
{{- if .Values.controller.ingress.hostName }}
{{- if .Values.controller.ingress.tls }}
{{- default "https" .Values.controller.jenkinsUrlProtocol }}://{{ tpl .Values.controller.ingress.hostName $ }}{{ default "" .Values.controller.jenkinsUriPrefix }}
{{- else }}
{{- default "http" .Values.controller.jenkinsUrlProtocol }}://{{ tpl .Values.controller.ingress.hostName $ }}{{ default "" .Values.controller.jenkinsUriPrefix }}
{{- end }}
{{- else }}
{{- default "http" .Values.controller.jenkinsUrlProtocol }}://{{ template "jenkins.fullname" . }}:{{.Values.controller.servicePort}}{{ default "" .Values.controller.jenkinsUriPrefix }}
{{- end}}
{{- end}}
{{- end -}}
{{/*
Returns configuration as code default config
*/}}
{{- define "jenkins.casc.defaults" -}}
jenkins:
{{- $configScripts := toYaml .Values.controller.JCasC.configScripts }}
{{- if and (.Values.controller.JCasC.authorizationStrategy) (not (contains "authorizationStrategy:" $configScripts)) }}
authorizationStrategy:
{{- tpl .Values.controller.JCasC.authorizationStrategy . | nindent 4 }}
{{- end }}
{{- if and (.Values.controller.JCasC.securityRealm) (not (contains "securityRealm:" $configScripts)) }}
securityRealm:
{{- tpl .Values.controller.JCasC.securityRealm . | nindent 4 }}
{{- end }}
disableRememberMe: {{ .Values.controller.disableRememberMe }}
{{- if .Values.controller.legacyRemotingSecurityEnabled }}
remotingSecurity:
enabled: true
{{- end }}
mode: {{ .Values.controller.executorMode }}
numExecutors: {{ .Values.controller.numExecutors }}
{{- if not (kindIs "invalid" .Values.controller.customJenkinsLabels) }}
labelString: "{{ join " " .Values.controller.customJenkinsLabels }}"
{{- end }}
{{- if .Values.controller.projectNamingStrategy }}
{{- if kindIs "string" .Values.controller.projectNamingStrategy }}
projectNamingStrategy: "{{ .Values.controller.projectNamingStrategy }}"
{{- else }}
projectNamingStrategy:
{{- toYaml .Values.controller.projectNamingStrategy | nindent 4 }}
{{- end }}
{{- end }}
markupFormatter:
{{- if .Values.controller.enableRawHtmlMarkupFormatter }}
rawHtml:
disableSyntaxHighlighting: true
{{- else }}
{{- toYaml .Values.controller.markupFormatter | nindent 4 }}
{{- end }}
clouds:
- kubernetes:
containerCapStr: "{{ .Values.agent.containerCap }}"
{{- if .Values.agent.jnlpregistry }}
jnlpregistry: "{{ .Values.agent.jnlpregistry }}"
{{- end }}
defaultsProviderTemplate: "{{ .Values.agent.defaultsProviderTemplate }}"
connectTimeout: "{{ .Values.agent.kubernetesConnectTimeout }}"
readTimeout: "{{ .Values.agent.kubernetesReadTimeout }}"
{{- if .Values.agent.directConnection }}
directConnection: true
{{- else }}
{{- if .Values.agent.jenkinsUrl }}
jenkinsUrl: "{{ tpl .Values.agent.jenkinsUrl . }}"
{{- else }}
jenkinsUrl: "http://{{ template "jenkins.fullname" . }}.{{ template "jenkins.namespace" . }}.svc.{{.Values.clusterZone}}:{{.Values.controller.servicePort}}{{ default "" .Values.controller.jenkinsUriPrefix }}"
{{- end }}
{{- if not .Values.agent.websocket }}
{{- if .Values.agent.jenkinsTunnel }}
jenkinsTunnel: "{{ tpl .Values.agent.jenkinsTunnel . }}"
{{- else }}
jenkinsTunnel: "{{ template "jenkins.fullname" . }}-agent.{{ template "jenkins.namespace" . }}.svc.{{.Values.clusterZone}}:{{ .Values.controller.agentListenerPort }}"
{{- end }}
{{- else }}
webSocket: true
{{- end }}
{{- end }}
skipTlsVerify: {{ .Values.agent.skipTlsVerify | default false}}
usageRestricted: {{ .Values.agent.usageRestricted | default false}}
maxRequestsPerHostStr: {{ .Values.agent.maxRequestsPerHostStr | quote }}
retentionTimeout: {{ .Values.agent.retentionTimeout | quote }}
waitForPodSec: {{ .Values.agent.waitForPodSec | quote }}
name: "{{ .Values.controller.cloudName }}"
namespace: "{{ template "jenkins.agent.namespace" . }}"
restrictedPssSecurityContext: {{ .Values.agent.restrictedPssSecurityContext }}
serverUrl: "{{ .Values.kubernetesURL }}"
credentialsId: "{{ .Values.credentialsId }}"
{{- if .Values.agent.enabled }}
podLabels:
- key: "jenkins/{{ .Release.Name }}-{{ .Values.agent.componentName }}"
value: "true"
{{- range $key, $val := .Values.agent.podLabels }}
- key: {{ $key | quote }}
value: {{ $val | quote }}
{{- end }}
templates:
{{- if not .Values.agent.disableDefaultAgent }}
{{- include "jenkins.casc.podTemplate" . | nindent 8 }}
{{- end }}
{{- if .Values.additionalAgents }}
{{- /* save .Values.agent */}}
{{- $agent := .Values.agent }}
{{- range $name, $additionalAgent := .Values.additionalAgents }}
{{- $additionalContainersEmpty := and (hasKey $additionalAgent "additionalContainers") (empty $additionalAgent.additionalContainers) }}
{{- /* merge original .Values.agent into additional agent to ensure it at least has the default values */}}
{{- $additionalAgent := merge $additionalAgent $agent }}
{{- /* clear list of additional containers in case it is configured empty for this agent (merge might have overwritten that) */}}
{{- if $additionalContainersEmpty }}
{{- $_ := set $additionalAgent "additionalContainers" list }}
{{- end }}
{{- /* set .Values.agent to $additionalAgent */}}
{{- $_ := set $.Values "agent" $additionalAgent }}
{{- include "jenkins.casc.podTemplate" $ | nindent 8 }}
{{- end }}
{{- /* restore .Values.agent */}}
{{- $_ := set .Values "agent" $agent }}
{{- end }}
{{- if .Values.agent.podTemplates }}
{{- range $key, $val := .Values.agent.podTemplates }}
{{- tpl $val $ | nindent 8 }}
{{- end }}
{{- end }}
{{- end }}
{{- if .Values.additionalClouds }}
{{- /* save root */}}
{{- $oldRoot := deepCopy $ }}
{{- range $name, $additionalCloud := .Values.additionalClouds }}
{{- $newRoot := deepCopy $ }}
{{- /* clear additionalAgents from the copy if override set to `true` */}}
{{- if .additionalAgentsOverride }}
{{- $_ := set $newRoot.Values "additionalAgents" list}}
{{- end}}
{{- $newValues := merge $additionalCloud $newRoot.Values }}
{{- $_ := set $newRoot "Values" $newValues }}
{{- /* clear additionalClouds from the copy */}}
{{- $_ := set $newRoot.Values "additionalClouds" list }}
{{- with $newRoot}}
- kubernetes:
containerCapStr: "{{ .Values.agent.containerCap }}"
{{- if .Values.agent.jnlpregistry }}
jnlpregistry: "{{ .Values.agent.jnlpregistry }}"
{{- end }}
defaultsProviderTemplate: "{{ .Values.agent.defaultsProviderTemplate }}"
connectTimeout: "{{ .Values.agent.kubernetesConnectTimeout }}"
readTimeout: "{{ .Values.agent.kubernetesReadTimeout }}"
{{- if .Values.agent.directConnection }}
directConnection: true
{{- else }}
{{- if .Values.agent.jenkinsUrl }}
jenkinsUrl: "{{ tpl .Values.agent.jenkinsUrl . }}"
{{- else }}
jenkinsUrl: "http://{{ template "jenkins.fullname" . }}.{{ template "jenkins.namespace" . }}.svc.{{.Values.clusterZone}}:{{.Values.controller.servicePort}}{{ default "" .Values.controller.jenkinsUriPrefix }}"
{{- end }}
{{- if not .Values.agent.websocket }}
{{- if .Values.agent.jenkinsTunnel }}
jenkinsTunnel: "{{ tpl .Values.agent.jenkinsTunnel . }}"
{{- else }}
jenkinsTunnel: "{{ template "jenkins.fullname" . }}-agent.{{ template "jenkins.namespace" . }}.svc.{{.Values.clusterZone}}:{{ .Values.controller.agentListenerPort }}"
{{- end }}
{{- else }}
webSocket: true
{{- end }}
{{- end }}
skipTlsVerify: {{ .Values.agent.skipTlsVerify | default false}}
usageRestricted: {{ .Values.agent.usageRestricted | default false}}
maxRequestsPerHostStr: {{ .Values.agent.maxRequestsPerHostStr | quote }}
retentionTimeout: {{ .Values.agent.retentionTimeout | quote }}
waitForPodSec: {{ .Values.agent.waitForPodSec | quote }}
name: {{ $name | quote }}
namespace: "{{ template "jenkins.agent.namespace" . }}"
restrictedPssSecurityContext: {{ .Values.agent.restrictedPssSecurityContext }}
serverUrl: "{{ .Values.kubernetesURL }}"
credentialsId: "{{ .Values.credentialsId }}"
{{- if .Values.agent.enabled }}
podLabels:
- key: "jenkins/{{ .Release.Name }}-{{ .Values.agent.componentName }}"
value: "true"
{{- range $key, $val := .Values.agent.podLabels }}
- key: {{ $key | quote }}
value: {{ $val | quote }}
{{- end }}
templates:
{{- if not .Values.agent.disableDefaultAgent }}
{{- include "jenkins.casc.podTemplate" . | nindent 8 }}
{{- end }}
{{- if .Values.additionalAgents }}
{{- /* save .Values.agent */}}
{{- $agent := .Values.agent }}
{{- range $name, $additionalAgent := .Values.additionalAgents }}
{{- $additionalContainersEmpty := and (hasKey $additionalAgent "additionalContainers") (empty $additionalAgent.additionalContainers) }}
{{- /* merge original .Values.agent into additional agent to ensure it at least has the default values */}}
{{- $additionalAgent := merge $additionalAgent $agent }}
{{- /* clear list of additional containers in case it is configured empty for this agent (merge might have overwritten that) */}}
{{- if $additionalContainersEmpty }}
{{- $_ := set $additionalAgent "additionalContainers" list }}
{{- end }}
{{- /* set .Values.agent to $additionalAgent */}}
{{- $_ := set $.Values "agent" $additionalAgent }}
{{- include "jenkins.casc.podTemplate" $ | nindent 8 }}
{{- end }}
{{- /* restore .Values.agent */}}
{{- $_ := set .Values "agent" $agent }}
{{- end }}
{{- with .Values.agent.podTemplates }}
{{- range $key, $val := . }}
{{- tpl $val $ | nindent 8 }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
{{- /* restore root */}}
{{- $_ := set $ "Values" $oldRoot.Values }}
{{- end }}
{{- if .Values.controller.csrf.defaultCrumbIssuer.enabled }}
crumbIssuer:
standard:
excludeClientIPFromCrumb: {{ if .Values.controller.csrf.defaultCrumbIssuer.proxyCompatability }}true{{ else }}false{{- end }}
{{- end }}
{{- include "jenkins.casc.security" . }}
{{- with .Values.controller.scriptApproval }}
scriptApproval:
approvedSignatures:
{{- range $key, $val := . }}
- "{{ $val }}"
{{- end }}
{{- end }}
unclassified:
location:
{{- with .Values.controller.jenkinsAdminEmail }}
adminAddress: {{ . }}
{{- end }}
url: {{ template "jenkins.url" . }}
{{- end -}}
{{/*
Returns a name template to be used for jcasc configmaps, using
suffix passed in at call as index 0
*/}}
{{- define "jenkins.casc.configName" -}}
{{- $name := index . 0 -}}
{{- $root := index . 1 -}}
"{{- include "jenkins.fullname" $root -}}-jenkins-{{ $name }}"
{{- end -}}
{{/*
Returns kubernetes pod template configuration as code
*/}}
{{- define "jenkins.casc.podTemplate" -}}
- name: "{{ .Values.agent.podName }}"
namespace: "{{ template "jenkins.agent.namespace" . }}"
{{- if .Values.agent.annotations }}
annotations:
{{- range $key, $value := .Values.agent.annotations }}
- key: {{ $key }}
value: {{ $value | quote }}
{{- end }}
{{- end }}
id: {{ sha256sum (toYaml .Values.agent) }}
containers:
- name: "{{ .Values.agent.sideContainerName }}"
alwaysPullImage: {{ .Values.agent.alwaysPullImage }}
args: "{{ .Values.agent.args | replace "$" "^$" }}"
{{- with .Values.agent.command }}
command: {{ . }}
{{- end }}
envVars:
- envVar:
{{- if .Values.agent.directConnection }}
key: "JENKINS_DIRECT_CONNECTION"
{{- if .Values.agent.jenkinsTunnel }}
value: "{{ tpl .Values.agent.jenkinsTunnel . }}"
{{- else }}
value: "{{ template "jenkins.fullname" . }}-agent.{{ template "jenkins.namespace" . }}.svc.{{.Values.clusterZone}}:{{ .Values.controller.agentListenerPort }}"
{{- end }}
{{- else }}
key: "JENKINS_URL"
{{- if .Values.agent.jenkinsUrl }}
value: {{ tpl .Values.agent.jenkinsUrl . }}
{{- else }}
value: "http://{{ template "jenkins.fullname" . }}.{{ template "jenkins.namespace" . }}.svc.{{.Values.clusterZone}}:{{.Values.controller.servicePort}}{{ default "/" .Values.controller.jenkinsUriPrefix }}"
{{- end }}
{{- end }}
image: "{{ .Values.agent.image.repository }}:{{ .Values.agent.image.tag }}"
{{- if .Values.agent.livenessProbe }}
livenessProbe:
execArgs: {{.Values.agent.livenessProbe.execArgs | quote}}
failureThreshold: {{.Values.agent.livenessProbe.failureThreshold}}
initialDelaySeconds: {{.Values.agent.livenessProbe.initialDelaySeconds}}
periodSeconds: {{.Values.agent.livenessProbe.periodSeconds}}
successThreshold: {{.Values.agent.livenessProbe.successThreshold}}
timeoutSeconds: {{.Values.agent.livenessProbe.timeoutSeconds}}
{{- end }}
privileged: "{{- if .Values.agent.privileged }}true{{- else }}false{{- end }}"
resourceLimitCpu: {{.Values.agent.resources.limits.cpu}}
resourceLimitMemory: {{.Values.agent.resources.limits.memory}}
{{- with .Values.agent.resources.limits.ephemeralStorage }}
resourceLimitEphemeralStorage: {{.}}
{{- end }}
resourceRequestCpu: {{.Values.agent.resources.requests.cpu}}
resourceRequestMemory: {{.Values.agent.resources.requests.memory}}
{{- with .Values.agent.resources.requests.ephemeralStorage }}
resourceRequestEphemeralStorage: {{.}}
{{- end }}
{{- with .Values.agent.runAsUser }}
runAsUser: {{ . }}
{{- end }}
{{- with .Values.agent.runAsGroup }}
runAsGroup: {{ . }}
{{- end }}
ttyEnabled: {{ .Values.agent.TTYEnabled }}
workingDir: {{ .Values.agent.workingDir }}
{{- range $additionalContainers := .Values.agent.additionalContainers }}
- name: "{{ $additionalContainers.sideContainerName }}"
alwaysPullImage: {{ $additionalContainers.alwaysPullImage | default $.Values.agent.alwaysPullImage }}
args: "{{ $additionalContainers.args | replace "$" "^$" }}"
{{- with $additionalContainers.command }}
command: {{ . }}
{{- end }}
envVars:
- envVar:
key: "JENKINS_URL"
{{- if $additionalContainers.jenkinsUrl }}
value: {{ tpl ($additionalContainers.jenkinsUrl) . }}
{{- else }}
value: "http://{{ template "jenkins.fullname" $ }}.{{ template "jenkins.namespace" $ }}.svc.{{ $.Values.clusterZone }}:{{ $.Values.controller.servicePort }}{{ default "/" $.Values.controller.jenkinsUriPrefix }}"
{{- end }}
image: "{{ $additionalContainers.image.repository }}:{{ $additionalContainers.image.tag }}"
{{- if $additionalContainers.livenessProbe }}
livenessProbe:
execArgs: {{$additionalContainers.livenessProbe.execArgs | quote}}
failureThreshold: {{$additionalContainers.livenessProbe.failureThreshold}}
initialDelaySeconds: {{$additionalContainers.livenessProbe.initialDelaySeconds}}
periodSeconds: {{$additionalContainers.livenessProbe.periodSeconds}}
successThreshold: {{$additionalContainers.livenessProbe.successThreshold}}
timeoutSeconds: {{$additionalContainers.livenessProbe.timeoutSeconds}}
{{- end }}
privileged: "{{- if $additionalContainers.privileged }}true{{- else }}false{{- end }}"
resourceLimitCpu: {{ if $additionalContainers.resources }}{{ $additionalContainers.resources.limits.cpu }}{{ else }}{{ $.Values.agent.resources.limits.cpu }}{{ end }}
resourceLimitMemory: {{ if $additionalContainers.resources }}{{ $additionalContainers.resources.limits.memory }}{{ else }}{{ $.Values.agent.resources.limits.memory }}{{ end }}
resourceRequestCpu: {{ if $additionalContainers.resources }}{{ $additionalContainers.resources.requests.cpu }}{{ else }}{{ $.Values.agent.resources.requests.cpu }}{{ end }}
resourceRequestMemory: {{ if $additionalContainers.resources }}{{ $additionalContainers.resources.requests.memory }}{{ else }}{{ $.Values.agent.resources.requests.memory }}{{ end }}
{{- if or $additionalContainers.runAsUser $.Values.agent.runAsUser }}
runAsUser: {{ $additionalContainers.runAsUser | default $.Values.agent.runAsUser }}
{{- end }}
{{- if or $additionalContainers.runAsGroup $.Values.agent.runAsGroup }}
runAsGroup: {{ $additionalContainers.runAsGroup | default $.Values.agent.runAsGroup }}
{{- end }}
ttyEnabled: {{ $additionalContainers.TTYEnabled | default $.Values.agent.TTYEnabled }}
workingDir: {{ $additionalContainers.workingDir | default $.Values.agent.workingDir }}
{{- end }}
{{- if or .Values.agent.envVars .Values.agent.secretEnvVars }}
envVars:
{{- range $index, $var := .Values.agent.envVars }}
- envVar:
key: {{ $var.name }}
value: {{ tpl $var.value $ }}
{{- end }}
{{- range $index, $var := .Values.agent.secretEnvVars }}
- secretEnvVar:
key: {{ $var.key }}
secretName: {{ $var.secretName }}
secretKey: {{ $var.secretKey }}
optional: {{ $var.optional | default false }}
{{- end }}
{{- end }}
idleMinutes: {{ .Values.agent.idleMinutes }}
instanceCap: 2147483647
{{- if .Values.agent.hostNetworking }}
hostNetwork: {{ .Values.agent.hostNetworking }}
{{- end }}
{{- if .Values.agent.imagePullSecretName }}
imagePullSecrets:
- name: {{ .Values.agent.imagePullSecretName }}
{{- end }}
label: "{{ .Release.Name }}-{{ .Values.agent.componentName }} {{ .Values.agent.customJenkinsLabels | join " " }}"
{{- if .Values.agent.nodeSelector }}
nodeSelector:
{{- $local := dict "first" true }}
{{- range $key, $value := .Values.agent.nodeSelector }}
{{- if $local.first }} {{ else }},{{ end }}
{{- $key }}={{ tpl $value $ }}
{{- $_ := set $local "first" false }}
{{- end }}
{{- end }}
nodeUsageMode: {{ quote .Values.agent.nodeUsageMode }}
podRetention: {{ .Values.agent.podRetention }}
showRawYaml: {{ .Values.agent.showRawYaml }}
serviceAccount: "{{ include "jenkins.serviceAccountAgentName" . }}"
slaveConnectTimeoutStr: "{{ .Values.agent.connectTimeout }}"
{{- if .Values.agent.volumes }}
volumes:
{{- range $index, $volume := .Values.agent.volumes }}
-{{- if (eq $volume.type "ConfigMap") }} configMapVolume:
{{- else if (eq $volume.type "EmptyDir") }} emptyDirVolume:
{{- else if (eq $volume.type "EphemeralVolume") }} genericEphemeralVolume:
{{- else if (eq $volume.type "HostPath") }} hostPathVolume:
{{- else if (eq $volume.type "Nfs") }} nfsVolume:
{{- else if (eq $volume.type "PVC") }} persistentVolumeClaim:
{{- else if (eq $volume.type "Secret") }} secretVolume:
{{- else }} {{ $volume.type }}:
{{- end }}
{{- range $key, $value := $volume }}
{{- if not (eq $key "type") }}
{{ $key }}: {{ if kindIs "string" $value }}{{ tpl $value $ | quote }}{{ else }}{{ $value }}{{ end }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
{{- if .Values.agent.workspaceVolume }}
workspaceVolume:
{{- if (eq .Values.agent.workspaceVolume.type "DynamicPVC") }}
dynamicPVC:
{{- else if (eq .Values.agent.workspaceVolume.type "EmptyDir") }}
emptyDirWorkspaceVolume:
{{- else if (eq .Values.agent.workspaceVolume.type "EphemeralVolume") }}
genericEphemeralVolume:
{{- else if (eq .Values.agent.workspaceVolume.type "HostPath") }}
hostPathWorkspaceVolume:
{{- else if (eq .Values.agent.workspaceVolume.type "Nfs") }}
nfsWorkspaceVolume:
{{- else if (eq .Values.agent.workspaceVolume.type "PVC") }}
persistentVolumeClaimWorkspaceVolume:
{{- else }}
{{ .Values.agent.workspaceVolume.type }}:
{{- end }}
{{- range $key, $value := .Values.agent.workspaceVolume }}
{{- if not (eq $key "type") }}
{{ $key }}: {{ if kindIs "string" $value }}{{ tpl $value $ | quote }}{{ else }}{{ $value }}{{ end }}
{{- end }}
{{- end }}
{{- end }}
{{- if .Values.agent.yamlTemplate }}
yaml: |-
{{- tpl (trim .Values.agent.yamlTemplate) . | nindent 4 }}
{{- end }}
yamlMergeStrategy: {{ .Values.agent.yamlMergeStrategy }}
inheritYamlMergeStrategy: {{ .Values.agent.inheritYamlMergeStrategy }}
{{- end -}}
{{- define "jenkins.kubernetes-version" -}}
{{- if .Values.controller.installPlugins -}}
{{- range .Values.controller.installPlugins -}}
{{- if hasPrefix "kubernetes:" . }}
{{- $split := splitList ":" . }}
{{- printf "%s" (index $split 1 ) -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- define "jenkins.casc.security" }}
security:
{{- with .Values.controller.JCasC }}
{{- if .security }}
{{- .security | toYaml | nindent 2 }}
{{- end }}
{{- end }}
{{- end -}}
{{/*
Create the name of the service account to use
*/}}
{{- define "jenkins.serviceAccountName" -}}
{{- if .Values.serviceAccount.create -}}
{{ default (include "jenkins.fullname" .) .Values.serviceAccount.name }}
{{- else -}}
{{ default "default" .Values.serviceAccount.name }}
{{- end -}}
{{- end -}}
{{/*
Create the name of the service account for Jenkins agents to use
*/}}
{{- define "jenkins.serviceAccountAgentName" -}}
{{- if .Values.serviceAccountAgent.create -}}
{{ default (printf "%s-%s" (include "jenkins.fullname" .) "agent") .Values.serviceAccountAgent.name }}
{{- else -}}
{{ default "default" .Values.serviceAccountAgent.name }}
{{- end -}}
{{- end -}}
{{/*
Create a full tag name for controller image
*/}}
{{- define "controller.image.tag" -}}
{{- if .Values.controller.image.tagLabel -}}
{{- default (printf "%s-%s" .Chart.AppVersion .Values.controller.image.tagLabel) .Values.controller.image.tag -}}
{{- else -}}
{{- default .Chart.AppVersion .Values.controller.image.tag -}}
{{- end -}}
{{- end -}}
{{/*
Create the HTTP port for interacting with the controller
*/}}
{{- define "controller.httpPort" -}}
{{- if .Values.controller.httpsKeyStore.enable -}}
{{- .Values.controller.httpsKeyStore.httpPort -}}
{{- else -}}
{{- .Values.controller.targetPort -}}
{{- end -}}
{{- end -}}
{{- define "jenkins.configReloadContainer" -}}
{{- $root := index . 0 -}}
{{- $containerName := index . 1 -}}
{{- $containerType := index . 2 -}}
- name: {{ $containerName }}
image: "{{ $root.Values.controller.sidecars.configAutoReload.image.registry }}/{{ $root.Values.controller.sidecars.configAutoReload.image.repository }}:{{ $root.Values.controller.sidecars.configAutoReload.image.tag }}"
imagePullPolicy: {{ $root.Values.controller.sidecars.configAutoReload.imagePullPolicy }}
{{- if $root.Values.controller.sidecars.configAutoReload.containerSecurityContext }}
securityContext: {{- toYaml $root.Values.controller.sidecars.configAutoReload.containerSecurityContext | nindent 4 }}
{{- end }}
{{- if $root.Values.controller.sidecars.configAutoReload.envFrom }}
envFrom:
{{ (tpl (toYaml $root.Values.controller.sidecars.configAutoReload.envFrom) $root) | indent 4 }}
{{- end }}
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: LABEL
value: "{{ template "jenkins.fullname" $root }}-jenkins-config"
- name: FOLDER
value: "{{ $root.Values.controller.sidecars.configAutoReload.folder }}"
- name: NAMESPACE
value: '{{ $root.Values.controller.sidecars.configAutoReload.searchNamespace | default (include "jenkins.namespace" $root) }}'
{{- if eq $containerType "init" }}
- name: METHOD
value: "LIST"
{{- else if $root.Values.controller.sidecars.configAutoReload.sleepTime }}
- name: METHOD
value: "SLEEP"
- name: SLEEP_TIME
value: "{{ $root.Values.controller.sidecars.configAutoReload.sleepTime }}"
{{- end }}
{{- if eq $containerType "sidecar" }}
- name: REQ_URL
value: "{{- default "http" $root.Values.controller.sidecars.configAutoReload.scheme }}://localhost:{{- include "controller.httpPort" $root -}}{{- $root.Values.controller.jenkinsUriPrefix -}}/reload-configuration-as-code/?casc-reload-token=$(POD_NAME)"
- name: REQ_METHOD
value: "POST"
- name: REQ_RETRY_CONNECT
value: "{{ $root.Values.controller.sidecars.configAutoReload.reqRetryConnect }}"
{{- if $root.Values.controller.sidecars.configAutoReload.skipTlsVerify }}
- name: REQ_SKIP_TLS_VERIFY
value: "true"
{{- end }}
{{- end }}
{{- if $root.Values.controller.sidecars.configAutoReload.env }}
{{- range $envVarItem := $root.Values.controller.sidecars.configAutoReload.env -}}
{{- if or (ne $containerType "init") (ne .name "METHOD") }}
{{- (tpl (toYaml (list $envVarItem)) $root) | nindent 4 }}
{{- end -}}
{{- end -}}
{{- end }}
{{- if $root.Values.controller.sidecars.configAutoReload.logging.configuration.override }}
- name: LOG_CONFIG
value: "{{ $root.Values.controller.jenkinsHome }}/auto-reload/auto-reload-config.yaml"
{{- end }}
resources:
{{ toYaml $root.Values.controller.sidecars.configAutoReload.resources | indent 4 }}
volumeMounts:
- name: sc-config-volume
mountPath: {{ $root.Values.controller.sidecars.configAutoReload.folder | quote }}
- name: jenkins-home
mountPath: {{ $root.Values.controller.jenkinsHome }}
{{- if $root.Values.persistence.subPath }}
subPath: {{ $root.Values.persistence.subPath }}
{{- end }}
{{- if $root.Values.controller.sidecars.configAutoReload.logging.configuration.override }}
- name: auto-reload-config
mountPath: {{ $root.Values.controller.jenkinsHome }}/auto-reload
- name: auto-reload-config-logs
mountPath: {{ $root.Values.controller.jenkinsHome }}/auto-reload-logs
{{- end }}
{{- if $root.Values.controller.sidecars.configAutoReload.additionalVolumeMounts }}
{{ (tpl (toYaml $root.Values.controller.sidecars.configAutoReload.additionalVolumeMounts) $root) | indent 4 }}
{{- end }}
{{- end -}}

View File

@ -0,0 +1,60 @@
{{- if .Values.controller.sidecars.configAutoReload.logging.configuration.override }}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ template "jenkins.fullname" . }}-auto-reload-config
namespace: {{ template "jenkins.namespace" . }}
labels:
"app.kubernetes.io/name": {{ template "jenkins.name" . }}
{{- if .Values.renderHelmLabels }}
"helm.sh/chart": "{{ .Chart.Name }}-{{ .Chart.Version }}"
{{- end }}
"app.kubernetes.io/managed-by": "{{ $.Release.Service }}"
"app.kubernetes.io/instance": "{{ $.Release.Name }}"
"app.kubernetes.io/component": "{{ $.Values.controller.componentName }}"
data:
auto-reload-config.yaml: |-
version: 1
disable_existing_loggers: false
root:
level: {{ .Values.controller.sidecars.configAutoReload.logging.configuration.logLevel }}
handlers:
{{- if .Values.controller.sidecars.configAutoReload.logging.configuration.logToConsole}}
- console
{{- end }}
{{- if .Values.controller.sidecars.configAutoReload.logging.configuration.logToFile }}
- file
{{- end }}
handlers:
{{- if .Values.controller.sidecars.configAutoReload.logging.configuration.logToConsole}}
console:
class: logging.StreamHandler
level: {{ .Values.controller.sidecars.configAutoReload.logging.configuration.logLevel }}
formatter: {{ .Values.controller.sidecars.configAutoReload.logging.configuration.formatter }}
{{- end }}
{{- if .Values.controller.sidecars.configAutoReload.logging.configuration.logToFile }}
file:
class : logging.handlers.RotatingFileHandler
formatter: {{ .Values.controller.sidecars.configAutoReload.logging.configuration.formatter }}
filename: {{ .Values.controller.jenkinsHome }}/auto-reload-logs/file.log
maxBytes: {{ .Values.controller.sidecars.configAutoReload.logging.configuration.maxBytes }}
backupCount: {{ .Values.controller.sidecars.configAutoReload.logging.configuration.backupCount }}
{{- end }}
formatters:
JSON:
"()": logger.JsonFormatter
format: "%(levelname)s %(message)s"
rename_fields:
message: msg
levelname: level
LOGFMT:
"()": logger.LogfmtFormatter
keys:
- time
- level
- msg
mapping:
time: asctime
level: levelname
msg: message
{{- end }}

View File

@ -0,0 +1,18 @@
{{- if .Values.controller.initScripts -}}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ template "jenkins.fullname" . }}-init-scripts
namespace: {{ template "jenkins.namespace" . }}
labels:
"app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
"app.kubernetes.io/managed-by": "{{ .Release.Service }}"
"app.kubernetes.io/instance": "{{ .Release.Name }}"
"app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
data:
{{- range $key, $val := .Values.controller.initScripts }}
init{{ $key }}.groovy: |-
{{ tpl $val $ | indent 4 }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,92 @@
{{- $jenkinsHome := .Values.controller.jenkinsHome -}}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ template "jenkins.fullname" . }}
namespace: {{ template "jenkins.namespace" . }}
labels:
"app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
"app.kubernetes.io/managed-by": "{{ .Release.Service }}"
"app.kubernetes.io/instance": "{{ .Release.Name }}"
"app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
data:
apply_config.sh: |-
set -e
{{- if .Values.controller.initializeOnce }}
if [ -f {{ .Values.controller.jenkinsHome }}/initialization-completed ]; then
echo "controller was previously initialized, refusing to re-initialize"
exit 0
fi
{{- end }}
echo "disable Setup Wizard"
# Prevent Setup Wizard when JCasC is enabled
echo $JENKINS_VERSION > {{ .Values.controller.jenkinsHome }}/jenkins.install.UpgradeWizard.state
echo $JENKINS_VERSION > {{ .Values.controller.jenkinsHome }}/jenkins.install.InstallUtil.lastExecVersion
{{- if .Values.controller.overwritePlugins }}
echo "remove all plugins from shared volume"
# remove all plugins from shared volume
rm -rf {{ .Values.controller.jenkinsHome }}/plugins/*
{{- end }}
{{- if .Values.controller.JCasC.overwriteConfiguration }}
echo "deleting all XML config files"
rm -f {{ .Values.controller.jenkinsHome }}/config.xml
rm -f {{ .Values.controller.jenkinsHome }}/*plugins*.xml
find {{ .Values.controller.jenkinsHome }} -maxdepth 1 -type f -iname '*configuration*.xml' -exec rm -f {} \;
{{- end }}
{{- if .Values.controller.installPlugins }}
echo "download plugins"
# Install missing plugins
cp /var/jenkins_config/plugins.txt {{ .Values.controller.jenkinsHome }};
rm -rf {{ .Values.controller.jenkinsRef }}/plugins/*.lock
version () { echo "$@" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }'; }
if [ -f "{{ .Values.controller.jenkinsWar }}" ] && [ -n "$(command -v jenkins-plugin-cli)" 2>/dev/null ] && [ $(version $(jenkins-plugin-cli --version)) -ge $(version "2.1.1") ]; then
jenkins-plugin-cli --verbose --war "{{ .Values.controller.jenkinsWar }}" --plugin-file "{{ .Values.controller.jenkinsHome }}/plugins.txt" --latest {{ .Values.controller.installLatestPlugins }}{{- if .Values.controller.installLatestSpecifiedPlugins }} --latest-specified{{- end }};
else
/usr/local/bin/install-plugins.sh `echo $(cat {{ .Values.controller.jenkinsHome }}/plugins.txt)`;
fi
echo "copy plugins to shared volume"
# Copy plugins to shared volume
yes n | cp -i {{ .Values.controller.jenkinsRef }}/plugins/* /var/jenkins_plugins/;
{{- end }}
{{- if not .Values.controller.sidecars.configAutoReload.enabled }}
echo "copy configuration as code files"
mkdir -p {{ .Values.controller.jenkinsHome }}/casc_configs;
rm -rf {{ .Values.controller.jenkinsHome }}/casc_configs/*
{{- if or .Values.controller.JCasC.defaultConfig .Values.controller.JCasC.configScripts }}
cp -v /var/jenkins_config/*.yaml {{ .Values.controller.jenkinsHome }}/casc_configs
{{- end }}
{{- end }}
echo "finished initialization"
{{- if .Values.controller.initializeOnce }}
touch {{ .Values.controller.jenkinsHome }}/initialization-completed
{{- end }}
{{- if not .Values.controller.sidecars.configAutoReload.enabled }}
# Only add config to this script if we aren't auto-reloading otherwise the pod will restart upon each config change:
{{- if .Values.controller.JCasC.defaultConfig }}
jcasc-default-config.yaml: |-
{{- include "jenkins.casc.defaults" . |nindent 4}}
{{- end }}
{{- range $key, $val := .Values.controller.JCasC.configScripts }}
{{ $key }}.yaml: |-
{{ tpl $val $| indent 4 }}
{{- end }}
{{- end }}
plugins.txt: |-
{{- if .Values.controller.installPlugins }}
{{- range $installPlugin := .Values.controller.installPlugins }}
{{- $installPlugin | nindent 4 }}
{{- end }}
{{- range $addlPlugin := .Values.controller.additionalPlugins }}
{{- /* duplicate plugin check */}}
{{- range $installPlugin := $.Values.controller.installPlugins }}
{{- if eq (splitList ":" $addlPlugin | first) (splitList ":" $installPlugin | first) }}
{{- $message := print "[PLUGIN CONFLICT] controller.additionalPlugins contains '" $addlPlugin "'" }}
{{- $message := print $message " but controller.installPlugins already contains '" $installPlugin "'." }}
{{- $message := print $message " Override controller.installPlugins to use '" $addlPlugin "' plugin." }}
{{- fail $message }}
{{- end }}
{{- end }}
{{- $addlPlugin | nindent 4 }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,151 @@
{{- if .Values.checkDeprecation }}
{{- if .Values.master }}
{{ fail "`master` does no longer exist. It has been renamed to `controller`" }}
{{- end }}
{{- if .Values.controller.imageTag }}
{{ fail "`controller.imageTag` does no longer exist. Please use `controller.image.tag` instead" }}
{{- end }}
{{- if .Values.controller.slaveListenerPort }}
{{ fail "`controller.slaveListenerPort` does no longer exist. It has been renamed to `controller.agentListenerPort`" }}
{{- end }}
{{- if .Values.controller.slaveHostPort }}
{{ fail "`controller.slaveHostPort` does no longer exist. It has been renamed to `controller.agentListenerHostPort`" }}
{{- end }}
{{- if .Values.controller.slaveKubernetesNamespace }}
{{ fail "`controller.slaveKubernetesNamespace` does no longer exist. It has been renamed to `agent.namespace`" }}
{{- end }}
{{- if .Values.controller.slaveDefaultsProviderTemplate }}
{{ fail "`controller.slaveDefaultsProviderTemplate` does no longer exist. It has been renamed to `agent.defaultsProviderTemplate`" }}
{{- end }}
{{- if .Values.controller.useSecurity }}
{{ fail "`controller.useSecurity` does no longer exist. It has been renamed to `controller.adminSecret`" }}
{{- end }}
{{- if .Values.controller.slaveJenkinsUrl }}
{{ fail "`controller.slaveJenkinsUrl` does no longer exist. It has been renamed to `agent.jenkinsUrl`" }}
{{- end }}
{{- if .Values.controller.slaveJenkinsTunnel }}
{{ fail "`controller.slaveJenkinsTunnel` does no longer exist. It has been renamed to `agent.jenkinsTunnel`" }}
{{- end }}
{{- if .Values.controller.slaveConnectTimeout }}
{{ fail "`controller.slaveConnectTimeout` does no longer exist. It has been renamed to `agent.kubernetesConnectTimeout`" }}
{{- end }}
{{- if .Values.controller.slaveReadTimeout }}
{{ fail "`controller.slaveReadTimeout` does no longer exist. It has been renamed to `agent.kubernetesReadTimeout`" }}
{{- end }}
{{- if .Values.controller.slaveListenerServiceType }}
{{ fail "`controller.slaveListenerServiceType` does no longer exist. It has been renamed to `controller.agentListenerServiceType`" }}
{{- end }}
{{- if .Values.controller.slaveListenerLoadBalancerIP }}
{{ fail "`controller.slaveListenerLoadBalancerIP` does no longer exist. It has been renamed to `controller.agentListenerLoadBalancerIP`" }}
{{- end }}
{{- if .Values.controller.slaveListenerServiceAnnotations }}
{{ fail "`controller.slaveListenerServiceAnnotations` does no longer exist. It has been renamed to `controller.agentListenerServiceAnnotations`" }}
{{- end }}
{{- if .Values.agent.slaveConnectTimeout }}
{{ fail "`agent.slaveConnectTimeout` does no longer exist. It has been renamed to `agent.connectTimeout`" }}
{{- end }}
{{- if .Values.NetworkPolicy }}
{{- if .Values.NetworkPolicy.Enabled }}
{{ fail "`NetworkPolicy.Enabled` does no longer exist. It has been renamed to `networkPolicy.enabled`" }}
{{- end }}
{{- if .Values.NetworkPolicy.ApiVersion }}
{{ fail "`NetworkPolicy.ApiVersion` does no longer exist. It has been renamed to `networkPolicy.apiVersion`" }}
{{- end }}
{{ fail "NetworkPolicy.* values have been renamed, please check the documentation" }}
{{- end }}
{{- if .Values.rbac.install }}
{{ fail "`rbac.install` does no longer exist. It has been renamed to `rbac.create` and is enabled by default!" }}
{{- end }}
{{- if .Values.rbac.serviceAccountName }}
{{ fail "`rbac.serviceAccountName` does no longer exist. It has been renamed to `serviceAccount.name`" }}
{{- end }}
{{- if .Values.rbac.serviceAccountAnnotations }}
{{ fail "`rbac.serviceAccountAnnotations` does no longer exist. It has been renamed to `serviceAccount.annotations`" }}
{{- end }}
{{- if .Values.rbac.roleRef }}
{{ fail "`rbac.roleRef` does no longer exist. RBAC roles are now generated, please check the documentation" }}
{{- end }}
{{- if .Values.rbac.roleKind }}
{{ fail "`rbac.roleKind` does no longer exist. RBAC roles are now generated, please check the documentation" }}
{{- end }}
{{- if .Values.rbac.roleBindingKind }}
{{ fail "`rbac.roleBindingKind` does no longer exist. RBAC roles are now generated, please check the documentation" }}
{{- end }}
{{- if .Values.controller.JCasC.pluginVersion }}
{{ fail "controller.JCasC.pluginVersion has been deprecated, please use controller.installPlugins instead" }}
{{- end }}
{{- if .Values.controller.deploymentLabels }}
{{ fail "`controller.deploymentLabels` does no longer exist. It has been renamed to `controller.statefulSetLabels`" }}
{{- end }}
{{- if .Values.controller.deploymentAnnotations }}
{{ fail "`controller.deploymentAnnotations` does no longer exist. It has been renamed to `controller.statefulSetAnnotations`" }}
{{- end }}
{{- if .Values.controller.rollingUpdate }}
{{ fail "`controller.rollingUpdate` does no longer exist. It is no longer relevant, since a StatefulSet is used for the Jenkins controller" }}
{{- end }}
{{- if .Values.controller.tag }}
{{ fail "`controller.tag` no longer exists. It has been renamed to `controller.image.tag'" }}
{{- end }}
{{- if .Values.controller.tagLabel }}
{{ fail "`controller.tagLabel` no longer exists. It has been renamed to `controller.image.tagLabel`" }}
{{- end }}
{{- if .Values.controller.adminSecret }}
{{ fail "`controller.adminSecret` no longer exists. It has been renamed to `controller.admin.createSecret`" }}
{{- end }}
{{- if .Values.controller.adminUser }}
{{ fail "`controller.adminUser` no longer exists. It has been renamed to `controller.admin.username`" }}
{{- end }}
{{- if .Values.controller.adminPassword }}
{{ fail "`controller.adminPassword` no longer exists. It has been renamed to `controller.admin.password`" }}
{{- end }}
{{- if .Values.controller.sidecars.other }}
{{ fail "`controller.sidecars.other` no longer exists. It has been renamed to `controller.sidecars.additionalSidecarContainers`" }}
{{- end }}
{{- if .Values.agent.tag }}
{{ fail "`controller.agent.tag` no longer exists. It has been renamed to `controller.agent.image.tag`" }}
{{- end }}
{{- if .Values.backup }}
{{ fail "`controller.backup` no longer exists." }}
{{- end }}
{{- if .Values.helmtest.bats.tag }}
{{ fail "`helmtest.bats.tag` no longer exists. It has been renamed to `helmtest.bats.image.tag`" }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,41 @@
{{- if not (contains "jenkins-home" (quote .Values.persistence.volumes)) }}
{{- if and .Values.persistence.enabled (not .Values.persistence.existingClaim) -}}
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
{{- if .Values.persistence.annotations }}
annotations:
{{ toYaml .Values.persistence.annotations | indent 4 }}
{{- end }}
name: {{ template "jenkins.fullname" . }}
namespace: {{ template "jenkins.namespace" . }}
labels:
"app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
{{- if .Values.renderHelmLabels }}
"helm.sh/chart": "{{ template "jenkins.label" .}}"
{{- end }}
"app.kubernetes.io/managed-by": "{{ .Release.Service }}"
"app.kubernetes.io/instance": "{{ .Release.Name }}"
"app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
{{- if .Values.persistence.labels }}
{{ toYaml .Values.persistence.labels | indent 4 }}
{{- end }}
spec:
{{- if .Values.persistence.dataSource }}
dataSource:
{{ toYaml .Values.persistence.dataSource | indent 4 }}
{{- end }}
accessModes:
- {{ .Values.persistence.accessMode | quote }}
resources:
requests:
storage: {{ .Values.persistence.size | quote }}
{{- if .Values.persistence.storageClass }}
{{- if (eq "-" .Values.persistence.storageClass) }}
storageClassName: ""
{{- else }}
storageClassName: "{{ .Values.persistence.storageClass }}"
{{- end }}
{{- end }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,53 @@
{{- $root := . }}
{{- if .Values.controller.sidecars.configAutoReload.enabled }}
{{- range $key, $val := .Values.controller.JCasC.configScripts }}
{{- if $val }}
---
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ template "jenkins.casc.configName" (list (printf "config-%s" $key) $ )}}
namespace: {{ template "jenkins.namespace" $root }}
labels:
"app.kubernetes.io/name": {{ template "jenkins.name" $root}}
{{- if $root.Values.renderHelmLabels }}
"helm.sh/chart": "{{ $root.Chart.Name }}-{{ $root.Chart.Version }}"
{{- end }}
"app.kubernetes.io/managed-by": "{{ $.Release.Service }}"
"app.kubernetes.io/instance": "{{ $.Release.Name }}"
"app.kubernetes.io/component": "{{ $.Values.controller.componentName }}"
{{ template "jenkins.fullname" $root }}-jenkins-config: "true"
{{- if $root.Values.controller.JCasC.configMapAnnotations }}
annotations:
{{ toYaml $root.Values.controller.JCasC.configMapAnnotations | indent 4 }}
{{- end }}
data:
{{ $key }}.yaml: |-
{{ tpl $val $| indent 4 }}
{{- end }}
{{- end }}
{{- if .Values.controller.JCasC.defaultConfig }}
---
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ template "jenkins.casc.configName" (list "jcasc-config" $ )}}
namespace: {{ template "jenkins.namespace" $root }}
labels:
"app.kubernetes.io/name": {{ template "jenkins.name" $root}}
{{- if .Values.renderHelmLabels }}
"helm.sh/chart": "{{ $root.Chart.Name }}-{{ $root.Chart.Version }}"
{{- end }}
"app.kubernetes.io/managed-by": "{{ $.Release.Service }}"
"app.kubernetes.io/instance": "{{ $.Release.Name }}"
"app.kubernetes.io/component": "{{ $.Values.controller.componentName }}"
{{ template "jenkins.fullname" $root }}-jenkins-config: "true"
{{- if $root.Values.controller.JCasC.configMapAnnotations }}
annotations:
{{ toYaml $root.Values.controller.JCasC.configMapAnnotations | indent 4 }}
{{- end }}
data:
jcasc-default-config.yaml: |-
{{- include "jenkins.casc.defaults" . | nindent 4 }}
{{- end}}
{{- end }}

View File

@ -0,0 +1,43 @@
{{- if .Values.controller.agentListenerEnabled }}
apiVersion: v1
kind: Service
metadata:
name: {{ template "jenkins.fullname" . }}-agent
namespace: {{ template "jenkins.namespace" . }}
labels:
"app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
{{- if .Values.renderHelmLabels }}
"helm.sh/chart": "{{ template "jenkins.label" .}}"
{{- end }}
"app.kubernetes.io/managed-by": "{{ .Release.Service }}"
"app.kubernetes.io/instance": "{{ .Release.Name }}"
"app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
{{- if .Values.controller.agentListenerServiceAnnotations }}
annotations:
{{- toYaml .Values.controller.agentListenerServiceAnnotations | nindent 4 }}
{{- end }}
spec:
{{- if .Values.controller.agentListenerExternalTrafficPolicy }}
externalTrafficPolicy: {{.Values.controller.agentListenerExternalTrafficPolicy}}
{{- end }}
ports:
- port: {{ .Values.controller.agentListenerPort }}
targetPort: {{ .Values.controller.agentListenerPort }}
{{- if (and (eq .Values.controller.agentListenerServiceType "NodePort") (not (empty .Values.controller.agentListenerNodePort))) }}
nodePort: {{ .Values.controller.agentListenerNodePort }}
{{- end }}
name: agent-listener
selector:
"app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
"app.kubernetes.io/instance": "{{ .Release.Name }}"
type: {{ .Values.controller.agentListenerServiceType }}
{{if eq .Values.controller.agentListenerServiceType "LoadBalancer"}}
{{- if .Values.controller.agentListenerLoadBalancerSourceRanges }}
loadBalancerSourceRanges:
{{ toYaml .Values.controller.agentListenerLoadBalancerSourceRanges | indent 4 }}
{{- end }}
{{- end }}
{{- if and (eq .Values.controller.agentListenerServiceType "LoadBalancer") (.Values.controller.agentListenerLoadBalancerIP) }}
loadBalancerIP: {{ .Values.controller.agentListenerLoadBalancerIP }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,16 @@
{{- if .Values.awsSecurityGroupPolicies.enabled -}}
{{- range .Values.awsSecurityGroupPolicies.policies -}}
apiVersion: vpcresources.k8s.aws/v1beta1
kind: SecurityGroupPolicy
metadata:
name: {{ .name }}
namespace: {{ template "jenkins.namespace" $ }}
spec:
podSelector:
{{- toYaml .podSelector | nindent 6}}
securityGroups:
groupIds:
{{- toYaml .securityGroupIds | nindent 6}}
---
{{- end -}}
{{- end -}}

View File

@ -0,0 +1,26 @@
{{- if and .Values.controller.prometheus.enabled .Values.controller.prometheus.alertingrules }}
---
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: {{ template "jenkins.fullname" . }}
{{- if .Values.controller.prometheus.prometheusRuleNamespace }}
namespace: {{ .Values.controller.prometheus.prometheusRuleNamespace }}
{{- else }}
namespace: {{ template "jenkins.namespace" . }}
{{- end }}
labels:
"app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
{{- if .Values.renderHelmLabels }}
"helm.sh/chart": "{{ template "jenkins.label" .}}"
{{- end }}
"app.kubernetes.io/managed-by": "{{ .Release.Service }}"
"app.kubernetes.io/instance": "{{ .Release.Name }}"
"app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
{{- range $key, $val := .Values.controller.prometheus.alertingRulesAdditionalLabels }}
{{ $key }}: {{ $val | quote }}
{{- end}}
spec:
groups:
{{ toYaml .Values.controller.prometheus.alertingrules | indent 2 }}
{{- end }}

View File

@ -0,0 +1,24 @@
{{- if .Values.controller.backendconfig.enabled }}
apiVersion: {{ .Values.controller.backendconfig.apiVersion }}
kind: BackendConfig
metadata:
name: {{ .Values.controller.backendconfig.name }}
namespace: {{ template "jenkins.namespace" . }}
labels:
"app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
{{- if .Values.renderHelmLabels }}
"helm.sh/chart": "{{ template "jenkins.label" .}}"
{{- end }}
"app.kubernetes.io/managed-by": "{{ .Release.Service }}"
"app.kubernetes.io/instance": "{{ .Release.Name }}"
"app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
{{- if .Values.controller.backendconfig.labels }}
{{ toYaml .Values.controller.backendconfig.labels | indent 4 }}
{{- end }}
{{- if .Values.controller.backendconfig.annotations }}
annotations:
{{ toYaml .Values.controller.backendconfig.annotations | indent 4 }}
{{- end }}
spec:
{{ toYaml .Values.controller.backendconfig.spec | indent 2 }}
{{- end }}

View File

@ -0,0 +1,77 @@
{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}
{{- if .Values.controller.ingress.enabled }}
{{- if semverCompare ">=1.19-0" $kubeTargetVersion -}}
apiVersion: networking.k8s.io/v1
{{- else if semverCompare ">=1.14-0" $kubeTargetVersion -}}
apiVersion: networking.k8s.io/v1beta1
{{- else -}}
apiVersion: {{ .Values.controller.ingress.apiVersion }}
{{- end }}
kind: Ingress
metadata:
namespace: {{ template "jenkins.namespace" . }}
labels:
"app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
{{- if .Values.renderHelmLabels }}
"helm.sh/chart": "{{ template "jenkins.label" .}}"
{{- end }}
"app.kubernetes.io/managed-by": "{{ .Release.Service }}"
"app.kubernetes.io/instance": "{{ .Release.Name }}"
"app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
{{- if .Values.controller.ingress.labels }}
{{ toYaml .Values.controller.ingress.labels | indent 4 }}
{{- end }}
{{- if .Values.controller.ingress.annotations }}
annotations:
{{ toYaml .Values.controller.ingress.annotations | indent 4 }}
{{- end }}
name: {{ template "jenkins.fullname" . }}
spec:
{{- if .Values.controller.ingress.ingressClassName }}
ingressClassName: {{ .Values.controller.ingress.ingressClassName | quote }}
{{- end }}
rules:
- http:
paths:
{{- if empty (.Values.controller.ingress.paths) }}
- backend:
{{- if semverCompare ">=1.19-0" $kubeTargetVersion }}
service:
name: {{ template "jenkins.fullname" . }}
port:
number: {{ .Values.controller.servicePort }}
pathType: ImplementationSpecific
{{- else }}
serviceName: {{ template "jenkins.fullname" . }}
servicePort: {{ .Values.controller.servicePort }}
{{- end }}
{{- if .Values.controller.ingress.path }}
path: {{ .Values.controller.ingress.path }}
{{- end -}}
{{- else }}
{{ tpl (toYaml .Values.controller.ingress.paths | indent 6) . }}
{{- end -}}
{{- if .Values.controller.ingress.hostName }}
host: {{ tpl .Values.controller.ingress.hostName . | quote }}
{{- end }}
{{- if .Values.controller.ingress.resourceRootUrl }}
- http:
paths:
- backend:
{{- if semverCompare ">=1.19-0" $kubeTargetVersion }}
service:
name: {{ template "jenkins.fullname" . }}
port:
number: {{ .Values.controller.servicePort }}
pathType: ImplementationSpecific
{{- else }}
serviceName: {{ template "jenkins.fullname" . }}
servicePort: {{ .Values.controller.servicePort }}
{{- end }}
host: {{ tpl .Values.controller.ingress.resourceRootUrl . | quote }}
{{- end }}
{{- if .Values.controller.ingress.tls }}
tls:
{{ tpl (toYaml .Values.controller.ingress.tls ) . | indent 4 }}
{{- end -}}
{{- end }}

View File

@ -0,0 +1,76 @@
{{- if .Values.networkPolicy.enabled }}
kind: NetworkPolicy
apiVersion: {{ .Values.networkPolicy.apiVersion }}
metadata:
name: "{{ .Release.Name }}-{{ .Values.controller.componentName }}"
namespace: {{ template "jenkins.namespace" . }}
labels:
"app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
{{- if .Values.renderHelmLabels }}
"helm.sh/chart": "{{ template "jenkins.label" .}}"
{{- end }}
"app.kubernetes.io/managed-by": "{{ .Release.Service }}"
"app.kubernetes.io/instance": "{{ .Release.Name }}"
"app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
spec:
podSelector:
matchLabels:
"app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
"app.kubernetes.io/instance": "{{ .Release.Name }}"
ingress:
# Allow web access to the UI
- ports:
- port: {{ .Values.controller.targetPort }}
{{- if .Values.controller.agentListenerEnabled }}
# Allow inbound connections from agents
- from:
{{- if .Values.networkPolicy.internalAgents.allowed }}
- podSelector:
matchLabels:
"jenkins/{{ .Release.Name }}-{{ .Values.agent.componentName }}": "true"
{{- range $k,$v:= .Values.networkPolicy.internalAgents.podLabels }}
{{ $k }}: {{ $v }}
{{- end }}
{{- if .Values.networkPolicy.internalAgents.namespaceLabels }}
namespaceSelector:
matchLabels:
{{- range $k,$v:= .Values.networkPolicy.internalAgents.namespaceLabels }}
{{ $k }}: {{ $v }}
{{- end }}
{{- end }}
{{- end }}
{{- if or .Values.networkPolicy.externalAgents.ipCIDR .Values.networkPolicy.externalAgents.except }}
- ipBlock:
cidr: {{ required "ipCIDR is required if you wish to allow external agents to connect to Jenkins Controller." .Values.networkPolicy.externalAgents.ipCIDR }}
{{- if .Values.networkPolicy.externalAgents.except }}
except:
{{- range .Values.networkPolicy.externalAgents.except }}
- {{ . }}
{{- end }}
{{- end }}
{{- end }}
ports:
- port: {{ .Values.controller.agentListenerPort }}
{{- end }}
{{- if .Values.agent.enabled }}
---
kind: NetworkPolicy
apiVersion: {{ .Values.networkPolicy.apiVersion }}
metadata:
name: "{{ .Release.Name }}-{{ .Values.agent.componentName }}"
namespace: {{ template "jenkins.namespace" . }}
labels:
"app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
{{- if .Values.renderHelmLabels }}
"helm.sh/chart": "{{ template "jenkins.label" .}}"
{{- end }}
"app.kubernetes.io/managed-by": "{{ .Release.Service }}"
"app.kubernetes.io/instance": "{{ .Release.Name }}"
"app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
spec:
podSelector:
matchLabels:
# DefaultDeny
"jenkins/{{ .Release.Name }}-{{ .Values.agent.componentName }}": "true"
{{- end }}
{{- end }}

View File

@ -0,0 +1,34 @@
{{- if .Values.controller.podDisruptionBudget.enabled }}
{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}
{{- if semverCompare ">=1.21-0" $kubeTargetVersion -}}
apiVersion: policy/v1
{{- else if semverCompare ">=1.5-0" $kubeTargetVersion -}}
apiVersion: policy/v1beta1
{{- else -}}
apiVersion: {{ .Values.controller.podDisruptionBudget.apiVersion }}
{{- end }}
kind: PodDisruptionBudget
metadata:
name: {{ template "jenkins.fullname" . }}-pdb
namespace: {{ template "jenkins.namespace" . }}
labels:
"app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
{{- if .Values.renderHelmLabels }}
"helm.sh/chart": "{{ template "jenkins.label" .}}"
{{- end }}
"app.kubernetes.io/managed-by": "{{ .Release.Service }}"
"app.kubernetes.io/instance": "{{ .Release.Name }}"
"app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
{{- if .Values.controller.podDisruptionBudget.labels -}}
{{ toYaml .Values.controller.podDisruptionBudget.labels | nindent 4 }}
{{- end }}
{{- if .Values.controller.podDisruptionBudget.annotations }}
annotations: {{ toYaml .Values.controller.podDisruptionBudget.annotations | nindent 4 }}
{{- end }}
spec:
maxUnavailable: {{ .Values.controller.podDisruptionBudget.maxUnavailable }}
selector:
matchLabels:
"app.kubernetes.io/instance": "{{ .Release.Name }}"
"app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
{{- end }}

View File

@ -0,0 +1,30 @@
{{- if .Values.controller.googlePodMonitor.enabled }}
apiVersion: monitoring.googleapis.com/v1
kind: PodMonitoring
metadata:
name: {{ template "jenkins.fullname" . }}
{{- if .Values.controller.googlePodMonitor.serviceMonitorNamespace }}
namespace: {{ .Values.controller.googlePodMonitor.serviceMonitorNamespace }}
{{- else }}
namespace: {{ template "jenkins.namespace" . }}
{{- end }}
labels:
"app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
{{- if .Values.renderHelmLabels }}
"helm.sh/chart": "{{ template "jenkins.label" .}}"
{{- end }}
"app.kubernetes.io/managed-by": "{{ .Release.Service }}"
"app.kubernetes.io/instance": "{{ .Release.Name }}"
"app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
spec:
endpoints:
- interval: {{ .Values.controller.googlePodMonitor.scrapeInterval }}
port: http
path: {{ .Values.controller.jenkinsUriPrefix }}{{ .Values.controller.googlePodMonitor.scrapeEndpoint }}
selector:
matchLabels:
"app.kubernetes.io/instance": "{{ .Release.Name }}"
"app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
{{- end }}

View File

@ -0,0 +1,34 @@
{{- if .Values.controller.route.enabled }}
apiVersion: route.openshift.io/v1
kind: Route
metadata:
namespace: {{ template "jenkins.namespace" . }}
labels:
app: {{ template "jenkins.fullname" . }}
{{- if .Values.renderHelmLabels }}
"helm.sh/chart": "{{ template "jenkins.label" .}}"
{{- end }}
release: "{{ .Release.Name }}"
heritage: "{{ .Release.Service }}"
component: "{{ .Release.Name }}-{{ .Values.controller.componentName }}"
{{- if .Values.controller.route.labels }}
{{ toYaml .Values.controller.route.labels | indent 4 }}
{{- end }}
{{- if .Values.controller.route.annotations }}
annotations:
{{ toYaml .Values.controller.route.annotations | indent 4 }}
{{- end }}
name: {{ template "jenkins.fullname" . }}
spec:
host: {{ .Values.controller.route.path }}
port:
targetPort: http
tls:
insecureEdgeTerminationPolicy: Redirect
termination: edge
to:
kind: Service
name: {{ template "jenkins.fullname" . }}
weight: 100
wildcardPolicy: None
{{- end }}

View File

@ -0,0 +1,56 @@
{{- if .Values.controller.secondaryingress.enabled }}
{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}
{{- $serviceName := include "jenkins.fullname" . -}}
{{- $servicePort := .Values.controller.servicePort -}}
{{- if semverCompare ">=1.19-0" $kubeTargetVersion -}}
apiVersion: networking.k8s.io/v1
{{- else if semverCompare ">=1.14-0" $kubeTargetVersion -}}
apiVersion: networking.k8s.io/v1beta1
{{- else -}}
apiVersion: {{ .Values.controller.secondaryingress.apiVersion }}
{{- end }}
kind: Ingress
metadata:
namespace: {{ template "jenkins.namespace" . }}
labels:
"app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
{{- if .Values.renderHelmLabels }}
"helm.sh/chart": "{{ template "jenkins.label" .}}"
{{- end }}
"app.kubernetes.io/managed-by": "{{ .Release.Service }}"
"app.kubernetes.io/instance": "{{ .Release.Name }}"
"app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
{{- if .Values.controller.secondaryingress.labels -}}
{{ toYaml .Values.controller.secondaryingress.labels | nindent 4 }}
{{- end }}
{{- if .Values.controller.secondaryingress.annotations }}
annotations: {{ toYaml .Values.controller.secondaryingress.annotations | nindent 4 }}
{{- end }}
name: {{ template "jenkins.fullname" . }}-secondary
spec:
{{- if .Values.controller.secondaryingress.ingressClassName }}
ingressClassName: {{ .Values.controller.secondaryingress.ingressClassName | quote }}
{{- end }}
rules:
- host: {{ .Values.controller.secondaryingress.hostName }}
http:
paths:
{{- range .Values.controller.secondaryingress.paths }}
- path: {{ . | quote }}
backend:
{{ if semverCompare ">=1.19-0" $kubeTargetVersion }}
service:
name: {{ $serviceName }}
port:
number: {{ $servicePort }}
pathType: ImplementationSpecific
{{ else }}
serviceName: {{ $serviceName }}
servicePort: {{ $servicePort }}
{{ end }}
{{- end}}
{{- if .Values.controller.secondaryingress.tls }}
tls:
{{ toYaml .Values.controller.secondaryingress.tls | indent 4 }}
{{- end -}}
{{- end }}

View File

@ -0,0 +1,45 @@
{{- if and .Values.controller.prometheus.enabled }}
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: {{ template "jenkins.fullname" . }}
{{- if .Values.controller.prometheus.serviceMonitorNamespace }}
namespace: {{ .Values.controller.prometheus.serviceMonitorNamespace }}
{{- else }}
namespace: {{ template "jenkins.namespace" . }}
{{- end }}
labels:
"app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
{{- if .Values.renderHelmLabels }}
"helm.sh/chart": "{{ template "jenkins.label" .}}"
{{- end }}
"app.kubernetes.io/managed-by": "{{ .Release.Service }}"
"app.kubernetes.io/instance": "{{ .Release.Name }}"
"app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
{{- range $key, $val := .Values.controller.prometheus.serviceMonitorAdditionalLabels }}
{{ $key }}: {{ $val | quote }}
{{- end}}
spec:
endpoints:
- interval: {{ .Values.controller.prometheus.scrapeInterval }}
port: http
path: {{ .Values.controller.jenkinsUriPrefix }}{{ .Values.controller.prometheus.scrapeEndpoint }}
{{- with .Values.controller.prometheus.relabelings }}
relabelings:
{{- toYaml . | nindent 6 }}
{{- end }}
{{- with .Values.controller.prometheus.metricRelabelings }}
metricRelabelings:
{{- toYaml . | nindent 6 }}
{{- end }}
jobLabel: {{ template "jenkins.fullname" . }}
namespaceSelector:
matchNames:
- "{{ template "jenkins.namespace" $ }}"
selector:
matchLabels:
"app.kubernetes.io/instance": "{{ .Release.Name }}"
"app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
{{- end }}

View File

@ -0,0 +1,424 @@
{{- if .Capabilities.APIVersions.Has "apps/v1" }}
apiVersion: apps/v1
{{- else }}
apiVersion: apps/v1beta1
{{- end }}
kind: StatefulSet
metadata:
name: {{ template "jenkins.fullname" . }}
namespace: {{ template "jenkins.namespace" . }}
labels:
"app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
{{- if .Values.renderHelmLabels }}
"helm.sh/chart": "{{ template "jenkins.label" .}}"
{{- end }}
"app.kubernetes.io/managed-by": "{{ .Release.Service }}"
"app.kubernetes.io/instance": "{{ .Release.Name }}"
"app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
{{- range $key, $val := .Values.controller.statefulSetLabels }}
{{ $key }}: {{ $val | quote }}
{{- end}}
{{- if .Values.controller.statefulSetAnnotations }}
annotations:
{{ toYaml .Values.controller.statefulSetAnnotations | indent 4 }}
{{- end }}
spec:
serviceName: {{ template "jenkins.fullname" . }}
replicas: 1
selector:
matchLabels:
"app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
"app.kubernetes.io/instance": "{{ .Release.Name }}"
{{- if .Values.controller.updateStrategy }}
updateStrategy:
{{ toYaml .Values.controller.updateStrategy | indent 4 }}
{{- end }}
template:
metadata:
labels:
"app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
"app.kubernetes.io/managed-by": "{{ .Release.Service }}"
"app.kubernetes.io/instance": "{{ .Release.Name }}"
"app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
{{- range $key, $val := .Values.controller.podLabels }}
{{ $key }}: {{ $val | quote }}
{{- end}}
annotations:
checksum/config: {{ include (print $.Template.BasePath "/config.yaml") . | sha256sum }}
{{- if .Values.controller.initScripts }}
checksum/config-init-scripts: {{ include (print $.Template.BasePath "/config-init-scripts.yaml") . | sha256sum }}
{{- end }}
{{- if .Values.controller.podAnnotations }}
{{ tpl (toYaml .Values.controller.podAnnotations | indent 8) . }}
{{- end }}
spec:
{{- if .Values.controller.schedulerName }}
schedulerName: {{ .Values.controller.schedulerName }}
{{- end }}
{{- if .Values.controller.nodeSelector }}
nodeSelector:
{{ toYaml .Values.controller.nodeSelector | indent 8 }}
{{- end }}
{{- if .Values.controller.tolerations }}
tolerations:
{{ toYaml .Values.controller.tolerations | indent 8 }}
{{- end }}
{{- if .Values.controller.affinity }}
affinity:
{{ toYaml .Values.controller.affinity | indent 8 }}
{{- end }}
{{- if .Values.controller.topologySpreadConstraints }}
topologySpreadConstraints:
{{ toYaml .Values.controller.topologySpreadConstraints | indent 8 }}
{{- end }}
{{- if quote .Values.controller.terminationGracePeriodSeconds }}
terminationGracePeriodSeconds: {{ .Values.controller.terminationGracePeriodSeconds }}
{{- end }}
{{- if .Values.controller.priorityClassName }}
priorityClassName: {{ .Values.controller.priorityClassName }}
{{- end }}
{{- if .Values.controller.shareProcessNamespace }}
shareProcessNamespace: true
{{- end }}
{{- if .Values.controller.usePodSecurityContext }}
securityContext:
{{- if kindIs "map" .Values.controller.podSecurityContextOverride }}
{{- tpl (toYaml .Values.controller.podSecurityContextOverride | nindent 8) . -}}
{{- else }}
{{/* The rest of this section should be replaced with the contents of this comment one the runAsUser, fsGroup, and securityContextCapabilities Helm chart values have been removed:
runAsUser: 1000
fsGroup: 1000
runAsNonRoot: true
*/}}
runAsUser: {{ default 0 .Values.controller.runAsUser }}
{{- if and (.Values.controller.runAsUser) (.Values.controller.fsGroup) }}
{{- if not (eq (int .Values.controller.runAsUser) 0) }}
fsGroup: {{ .Values.controller.fsGroup }}
runAsNonRoot: true
{{- end }}
{{- if .Values.controller.securityContextCapabilities }}
capabilities:
{{- toYaml .Values.controller.securityContextCapabilities | nindent 10 }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
serviceAccountName: "{{ template "jenkins.serviceAccountName" . }}"
{{- if .Values.controller.hostNetworking }}
hostNetwork: true
dnsPolicy: ClusterFirstWithHostNet
{{- end }}
{{- if .Values.controller.hostAliases }}
hostAliases:
{{- toYaml .Values.controller.hostAliases | nindent 8 }}
{{- end }}
initContainers:
{{- if .Values.controller.customInitContainers }}
{{ tpl (toYaml .Values.controller.customInitContainers) . | indent 8 }}
{{- end }}
{{- if .Values.controller.sidecars.configAutoReload.enabled }}
{{- include "jenkins.configReloadContainer" (list $ "config-reload-init" "init") | nindent 8 }}
{{- end}}
- name: "init"
image: "{{ .Values.controller.image.registry }}/{{ .Values.controller.image.repository }}:{{- include "controller.image.tag" . -}}"
imagePullPolicy: "{{ .Values.controller.image.pullPolicy }}"
{{- if .Values.controller.containerSecurityContext }}
securityContext: {{- toYaml .Values.controller.containerSecurityContext | nindent 12 }}
{{- end }}
command: [ "sh", "/var/jenkins_config/apply_config.sh" ]
{{- if .Values.controller.initContainerEnvFrom }}
envFrom:
{{ (tpl (toYaml .Values.controller.initContainerEnvFrom) .) | indent 12 }}
{{- end }}
{{- if .Values.controller.initContainerEnv }}
env:
{{ (tpl (toYaml .Values.controller.initContainerEnv) .) | indent 12 }}
{{- end }}
resources:
{{- if .Values.controller.initContainerResources }}
{{ toYaml .Values.controller.initContainerResources | indent 12 }}
{{- else }}
{{ toYaml .Values.controller.resources | indent 12 }}
{{- end }}
volumeMounts:
{{- if .Values.persistence.mounts }}
{{ toYaml .Values.persistence.mounts | indent 12 }}
{{- end }}
- mountPath: {{ .Values.controller.jenkinsHome }}
name: jenkins-home
{{- if .Values.persistence.subPath }}
subPath: {{ .Values.persistence.subPath }}
{{- end }}
- mountPath: /var/jenkins_config
name: jenkins-config
{{- if .Values.controller.installPlugins }}
{{- if .Values.controller.overwritePluginsFromImage }}
- mountPath: {{ .Values.controller.jenkinsRef }}/plugins
name: plugins
{{- end }}
- mountPath: /var/jenkins_plugins
name: plugin-dir
- mountPath: /tmp
name: tmp-volume
{{- end }}
{{- if or .Values.controller.initScripts .Values.controller.initConfigMap }}
- mountPath: {{ .Values.controller.jenkinsHome }}/init.groovy.d
name: init-scripts
{{- end }}
{{- if and .Values.controller.httpsKeyStore.enable (not .Values.controller.httpsKeyStore.disableSecretMount) }}
{{- $httpsJKSDirPath := printf "%s" .Values.controller.httpsKeyStore.path }}
- mountPath: {{ $httpsJKSDirPath }}
name: jenkins-https-keystore
{{- end }}
containers:
- name: jenkins
image: "{{ .Values.controller.image.registry }}/{{ .Values.controller.image.repository }}:{{- include "controller.image.tag" . -}}"
imagePullPolicy: "{{ .Values.controller.image.pullPolicy }}"
{{- if .Values.controller.containerSecurityContext }}
securityContext: {{- toYaml .Values.controller.containerSecurityContext | nindent 12 }}
{{- end }}
{{- if .Values.controller.overrideArgs }}
args: [
{{- range $overrideArg := .Values.controller.overrideArgs }}
"{{- tpl $overrideArg $ }}",
{{- end }}
]
{{- else if .Values.controller.httpsKeyStore.enable }}
{{- $httpsJKSFilePath := printf "%s/%s" .Values.controller.httpsKeyStore.path .Values.controller.httpsKeyStore.fileName }}
args: [ "--httpPort={{.Values.controller.httpsKeyStore.httpPort}}", "--httpsPort={{.Values.controller.targetPort}}", '--httpsKeyStore={{ $httpsJKSFilePath }}', "--httpsKeyStorePassword=$(JENKINS_HTTPS_KEYSTORE_PASSWORD)" ]
{{- else }}
args: [ "--httpPort={{.Values.controller.targetPort}}"]
{{- end }}
{{- if .Values.controller.lifecycle }}
lifecycle:
{{ toYaml .Values.controller.lifecycle | indent 12 }}
{{- end }}
{{- if .Values.controller.terminationMessagePath }}
terminationMessagePath: {{ .Values.controller.terminationMessagePath }}
{{- end }}
{{- if .Values.controller.terminationMessagePolicy }}
terminationMessagePolicy: {{ .Values.controller.terminationMessagePolicy }}
{{- end }}
{{- if .Values.controller.containerEnvFrom }}
envFrom:
{{ (tpl ( toYaml .Values.controller.containerEnvFrom) .) | indent 12 }}
{{- end }}
env:
{{- if .Values.controller.containerEnv }}
{{ (tpl ( toYaml .Values.controller.containerEnv) .) | indent 12 }}
{{- end }}
{{- if or .Values.controller.additionalSecrets .Values.controller.existingSecret .Values.controller.additionalExistingSecrets .Values.controller.admin.createSecret }}
- name: SECRETS
value: /run/secrets/additional
{{- end }}
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: JAVA_OPTS
value: >-
{{ if .Values.controller.sidecars.configAutoReload.enabled }} -Dcasc.reload.token=$(POD_NAME) {{ end }}{{ default "" .Values.controller.javaOpts }}
- name: JENKINS_OPTS
value: >-
{{ if .Values.controller.jenkinsUriPrefix }}--prefix={{ .Values.controller.jenkinsUriPrefix }} {{ end }} --webroot=/var/jenkins_cache/war {{ default "" .Values.controller.jenkinsOpts}}
- name: JENKINS_SLAVE_AGENT_PORT
value: "{{ .Values.controller.agentListenerPort }}"
{{- if .Values.controller.httpsKeyStore.enable }}
- name: JENKINS_HTTPS_KEYSTORE_PASSWORD
{{- if not .Values.controller.httpsKeyStore.disableSecretMount }}
valueFrom:
secretKeyRef:
name: {{ if .Values.controller.httpsKeyStore.jenkinsHttpsJksPasswordSecretName }} {{ .Values.controller.httpsKeyStore.jenkinsHttpsJksPasswordSecretName }} {{ else if .Values.controller.httpsKeyStore.jenkinsHttpsJksSecretName }} {{ .Values.controller.httpsKeyStore.jenkinsHttpsJksSecretName }} {{ else }} {{ template "jenkins.fullname" . }}-https-jks {{ end }}
key: "{{ .Values.controller.httpsKeyStore.jenkinsHttpsJksPasswordSecretKey }}"
{{- else }}
value: {{ .Values.controller.httpsKeyStore.password }}
{{- end }}
{{- end }}
- name: CASC_JENKINS_CONFIG
value: {{ .Values.controller.sidecars.configAutoReload.folder | default (printf "%s/casc_configs" (.Values.controller.jenkinsRef)) }}{{- if .Values.controller.JCasC.configUrls }},{{ join "," .Values.controller.JCasC.configUrls }}{{- end }}
ports:
{{- if .Values.controller.httpsKeyStore.enable }}
- containerPort: {{.Values.controller.httpsKeyStore.httpPort}}
{{- else }}
- containerPort: {{.Values.controller.targetPort}}
{{- end }}
name: http
- containerPort: {{ .Values.controller.agentListenerPort }}
name: agent-listener
{{- if .Values.controller.agentListenerHostPort }}
hostPort: {{ .Values.controller.agentListenerHostPort }}
{{- end }}
{{- if .Values.controller.jmxPort }}
- containerPort: {{ .Values.controller.jmxPort }}
name: jmx
{{- end }}
{{- range $index, $port := .Values.controller.extraPorts }}
- containerPort: {{ $port.port }}
name: {{ $port.name }}
{{- end }}
{{- if and .Values.controller.healthProbes .Values.controller.probes}}
{{- if semverCompare ">=1.16-0" .Capabilities.KubeVersion.GitVersion }}
startupProbe:
{{ tpl (toYaml .Values.controller.probes.startupProbe | indent 12) .}}
{{- end }}
livenessProbe:
{{ tpl (toYaml .Values.controller.probes.livenessProbe | indent 12) .}}
readinessProbe:
{{ tpl (toYaml .Values.controller.probes.readinessProbe | indent 12) .}}
{{- end }}
resources:
{{ toYaml .Values.controller.resources | indent 12 }}
volumeMounts:
{{- if .Values.persistence.mounts }}
{{ toYaml .Values.persistence.mounts | indent 12 }}
{{- end }}
{{- if and .Values.controller.httpsKeyStore.enable (not .Values.controller.httpsKeyStore.disableSecretMount) }}
{{- $httpsJKSDirPath := printf "%s" .Values.controller.httpsKeyStore.path }}
- mountPath: {{ $httpsJKSDirPath }}
name: jenkins-https-keystore
{{- end }}
- mountPath: {{ .Values.controller.jenkinsHome }}
name: jenkins-home
readOnly: false
{{- if .Values.persistence.subPath }}
subPath: {{ .Values.persistence.subPath }}
{{- end }}
- mountPath: /var/jenkins_config
name: jenkins-config
readOnly: true
{{- if .Values.controller.installPlugins }}
- mountPath: {{ .Values.controller.jenkinsRef }}/plugins/
name: plugin-dir
readOnly: false
{{- end }}
{{- if or .Values.controller.initScripts .Values.controller.initConfigMap }}
- mountPath: {{ .Values.controller.jenkinsHome }}/init.groovy.d
name: init-scripts
{{- end }}
{{- if .Values.controller.sidecars.configAutoReload.enabled }}
- name: sc-config-volume
mountPath: {{ .Values.controller.sidecars.configAutoReload.folder | default (printf "%s/casc_configs" (.Values.controller.jenkinsRef)) }}
{{- end }}
{{- if or .Values.controller.additionalSecrets .Values.controller.existingSecret .Values.controller.additionalExistingSecrets .Values.controller.admin.createSecret }}
- name: jenkins-secrets
mountPath: /run/secrets/additional
readOnly: true
{{- end }}
- name: jenkins-cache
mountPath: /var/jenkins_cache
- mountPath: /tmp
name: tmp-volume
{{- if .Values.controller.sidecars.configAutoReload.enabled }}
{{- include "jenkins.configReloadContainer" (list $ "config-reload" "sidecar") | nindent 8 }}
{{- end}}
{{- if .Values.controller.sidecars.additionalSidecarContainers}}
{{ tpl (toYaml .Values.controller.sidecars.additionalSidecarContainers | indent 8) .}}
{{- end }}
volumes:
{{- if .Values.persistence.volumes }}
{{ tpl (toYaml .Values.persistence.volumes | indent 6) . }}
{{- end }}
{{- if .Values.controller.sidecars.configAutoReload.logging.configuration.override }}
- name: auto-reload-config
configMap:
name: {{ template "jenkins.fullname" . }}-auto-reload-config
- name: auto-reload-config-logs
emptyDir: {}
{{- end }}
{{- if .Values.controller.installPlugins }}
{{- if .Values.controller.overwritePluginsFromImage }}
- name: plugins
emptyDir: {}
{{- end }}
{{- end }}
{{- if and .Values.controller.initScripts .Values.controller.initConfigMap }}
- name: init-scripts
projected:
sources:
- configMap:
name: {{ template "jenkins.fullname" . }}-init-scripts
- configMap:
name: {{ .Values.controller.initConfigMap }}
{{- else if .Values.controller.initConfigMap }}
- name: init-scripts
configMap:
name: {{ .Values.controller.initConfigMap }}
{{- else if .Values.controller.initScripts }}
- name: init-scripts
configMap:
name: {{ template "jenkins.fullname" . }}-init-scripts
{{- end }}
- name: jenkins-config
configMap:
name: {{ template "jenkins.fullname" . }}
{{- if .Values.controller.installPlugins }}
- name: plugin-dir
emptyDir: {}
{{- end }}
{{- if or .Values.controller.additionalSecrets .Values.controller.existingSecret .Values.controller.additionalExistingSecrets .Values.controller.admin.createSecret }}
- name: jenkins-secrets
projected:
sources:
{{- if .Values.controller.additionalSecrets }}
- secret:
name: {{ template "jenkins.fullname" . }}-additional-secrets
{{- end }}
{{- if .Values.controller.additionalExistingSecrets }}
{{- range $key, $value := .Values.controller.additionalExistingSecrets }}
- secret:
name: {{ tpl $value.name $ }}
items:
- key: {{ tpl $value.keyName $ }}
path: {{ tpl $value.name $ }}-{{ tpl $value.keyName $ }}
{{- end }}
{{- end }}
{{- if .Values.controller.admin.createSecret }}
- secret:
name: {{ .Values.controller.admin.existingSecret | default (include "jenkins.fullname" .) }}
items:
- key: {{ .Values.controller.admin.userKey | default "jenkins-admin-user" }}
path: chart-admin-username
- key: {{ .Values.controller.admin.passwordKey | default "jenkins-admin-password" }}
path: chart-admin-password
{{- end }}
{{- if .Values.controller.existingSecret }}
- secret:
name: {{ .Values.controller.existingSecret }}
{{- end }}
{{- end }}
- name: jenkins-cache
emptyDir: {}
{{- if not (contains "jenkins-home" (quote .Values.persistence.volumes)) }}
- name: jenkins-home
{{- if .Values.persistence.enabled }}
persistentVolumeClaim:
claimName: {{ .Values.persistence.existingClaim | default (include "jenkins.fullname" .) }}
{{- else }}
emptyDir: {}
{{- end -}}
{{- end }}
- name: sc-config-volume
emptyDir: {}
- name: tmp-volume
emptyDir: {}
{{- if and .Values.controller.httpsKeyStore.enable (not .Values.controller.httpsKeyStore.disableSecretMount) }}
- name: jenkins-https-keystore
secret:
secretName: {{ if .Values.controller.httpsKeyStore.jenkinsHttpsJksSecretName }} {{ .Values.controller.httpsKeyStore.jenkinsHttpsJksSecretName }} {{ else }} {{ template "jenkins.fullname" . }}-https-jks {{ end }}
items:
- key: {{ .Values.controller.httpsKeyStore.jenkinsHttpsJksSecretKey }}
path: {{ .Values.controller.httpsKeyStore.fileName }}
{{- end }}
{{- if .Values.controller.imagePullSecretName }}
imagePullSecrets:
- name: {{ .Values.controller.imagePullSecretName }}
{{- end -}}

View File

@ -0,0 +1,56 @@
apiVersion: v1
kind: Service
metadata:
name: {{template "jenkins.fullname" . }}
namespace: {{ template "jenkins.namespace" . }}
labels:
"app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
{{- if .Values.renderHelmLabels }}
"helm.sh/chart": "{{ template "jenkins.label" .}}"
{{- end }}
"app.kubernetes.io/managed-by": "{{ .Release.Service }}"
"app.kubernetes.io/instance": "{{ .Release.Name }}"
"app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
{{- if .Values.controller.serviceLabels }}
{{ toYaml .Values.controller.serviceLabels | indent 4 }}
{{- end }}
{{- if .Values.controller.serviceAnnotations }}
annotations:
{{ toYaml .Values.controller.serviceAnnotations | indent 4 }}
{{- end }}
spec:
{{- if .Values.controller.serviceExternalTrafficPolicy }}
externalTrafficPolicy: {{.Values.controller.serviceExternalTrafficPolicy}}
{{- end }}
{{- if (and (eq .Values.controller.serviceType "ClusterIP") (not (empty .Values.controller.clusterIP))) }}
clusterIP: {{.Values.controller.clusterIP}}
{{- end }}
ports:
- port: {{.Values.controller.servicePort}}
name: http
targetPort: {{ .Values.controller.targetPort }}
{{- if (and (eq .Values.controller.serviceType "NodePort") (not (empty .Values.controller.nodePort))) }}
nodePort: {{.Values.controller.nodePort}}
{{- end }}
{{- range $index, $port := .Values.controller.extraPorts }}
- port: {{ $port.port }}
name: {{ $port.name }}
{{- if $port.targetPort }}
targetPort: {{ $port.targetPort }}
{{- else }}
targetPort: {{ $port.port }}
{{- end -}}
{{- end }}
selector:
"app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
"app.kubernetes.io/instance": "{{ .Release.Name }}"
type: {{.Values.controller.serviceType}}
{{if eq .Values.controller.serviceType "LoadBalancer"}}
{{- if .Values.controller.loadBalancerSourceRanges }}
loadBalancerSourceRanges:
{{ toYaml .Values.controller.loadBalancerSourceRanges | indent 4 }}
{{- end }}
{{if .Values.controller.loadBalancerIP}}
loadBalancerIP: {{.Values.controller.loadBalancerIP}}
{{end}}
{{end}}

View File

@ -0,0 +1,149 @@
{{ if .Values.rbac.create }}
{{- $serviceName := include "jenkins.fullname" . -}}
# This role is used to allow Jenkins scheduling of agents via Kubernetes plugin.
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: {{ $serviceName }}-schedule-agents
namespace: {{ template "jenkins.agent.namespace" . }}
labels:
"app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
{{- if .Values.renderHelmLabels }}
"helm.sh/chart": "{{ template "jenkins.label" .}}"
{{- end }}
"app.kubernetes.io/managed-by": "{{ .Release.Service }}"
"app.kubernetes.io/instance": "{{ .Release.Name }}"
"app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
rules:
- apiGroups: [""]
resources: ["pods", "pods/exec", "pods/log", "persistentvolumeclaims", "events"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["pods", "pods/exec", "persistentvolumeclaims"]
verbs: ["create", "delete", "deletecollection", "patch", "update"]
---
# We bind the role to the Jenkins service account. The role binding is created in the namespace
# where the agents are supposed to run.
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: {{ $serviceName }}-schedule-agents
namespace: {{ template "jenkins.agent.namespace" . }}
labels:
"app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
{{- if .Values.renderHelmLabels }}
"helm.sh/chart": "{{ template "jenkins.label" .}}"
{{- end }}
"app.kubernetes.io/managed-by": "{{ .Release.Service }}"
"app.kubernetes.io/instance": "{{ .Release.Name }}"
"app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: {{ $serviceName }}-schedule-agents
subjects:
- kind: ServiceAccount
name: {{ template "jenkins.serviceAccountName" .}}
namespace: {{ template "jenkins.namespace" . }}
---
{{- if .Values.rbac.readSecrets }}
# This is needed if you want to use https://jenkinsci.github.io/kubernetes-credentials-provider-plugin/
# as it needs permissions to get/watch/list Secrets
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: {{ template "jenkins.fullname" . }}-read-secrets
namespace: {{ template "jenkins.namespace" . }}
labels:
"app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
{{- if .Values.renderHelmLabels }}
"helm.sh/chart": "{{ template "jenkins.label" .}}"
{{- end }}
"app.kubernetes.io/managed-by": "{{ .Release.Service }}"
"app.kubernetes.io/instance": "{{ .Release.Name }}"
"app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "watch", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: {{ $serviceName }}-read-secrets
namespace: {{ template "jenkins.namespace" . }}
labels:
"app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
{{- if .Values.renderHelmLabels }}
"helm.sh/chart": "{{ template "jenkins.label" .}}"
{{- end }}
"app.kubernetes.io/managed-by": "{{ .Release.Service }}"
"app.kubernetes.io/instance": "{{ .Release.Name }}"
"app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: {{ template "jenkins.fullname" . }}-read-secrets
subjects:
- kind: ServiceAccount
name: {{ template "jenkins.serviceAccountName" . }}
namespace: {{ template "jenkins.namespace" . }}
---
{{- end}}
{{- if .Values.controller.sidecars.configAutoReload.enabled }}
# The sidecar container which is responsible for reloading configuration changes
# needs permissions to watch ConfigMaps
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: {{ template "jenkins.fullname" . }}-casc-reload
namespace: {{ template "jenkins.namespace" . }}
labels:
"app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
{{- if .Values.renderHelmLabels }}
"helm.sh/chart": "{{ template "jenkins.label" .}}"
{{- end }}
"app.kubernetes.io/managed-by": "{{ .Release.Service }}"
"app.kubernetes.io/instance": "{{ .Release.Name }}"
"app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
rules:
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["get", "watch", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: {{ $serviceName }}-watch-configmaps
namespace: {{ template "jenkins.namespace" . }}
labels:
"app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
{{- if .Values.renderHelmLabels }}
"helm.sh/chart": "{{ template "jenkins.label" .}}"
{{- end }}
"app.kubernetes.io/managed-by": "{{ .Release.Service }}"
"app.kubernetes.io/instance": "{{ .Release.Name }}"
"app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: {{ template "jenkins.fullname" . }}-casc-reload
subjects:
- kind: ServiceAccount
name: {{ template "jenkins.serviceAccountName" . }}
namespace: {{ template "jenkins.namespace" . }}
{{- end}}
{{ end }}

View File

@ -0,0 +1,21 @@
{{- if .Values.controller.additionalSecrets -}}
---
apiVersion: v1
kind: Secret
metadata:
name: {{ template "jenkins.fullname" . }}-additional-secrets
namespace: {{ template "jenkins.namespace" . }}
labels:
"app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
{{- if .Values.renderHelmLabels }}
"helm.sh/chart": "{{ template "jenkins.label" .}}"
{{- end }}
"app.kubernetes.io/managed-by": "{{ .Release.Service }}"
"app.kubernetes.io/instance": "{{ .Release.Name }}"
"app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
type: Opaque
data:
{{- range .Values.controller.additionalSecrets }}
{{ .name }}: {{ .value | b64enc }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,29 @@
{{- if .Values.controller.secretClaims -}}
{{- $r := .Release -}}
{{- $v := .Values -}}
{{- $chart := printf "%s-%s" .Chart.Name .Chart.Version -}}
{{- $namespace := include "jenkins.namespace" . -}}
{{- $serviceName := include "jenkins.fullname" . -}}
{{ range .Values.controller.secretClaims }}
---
kind: SecretClaim
apiVersion: vaultproject.io/v1
metadata:
name: {{ $serviceName }}-{{ .name | default .path | lower }}
namespace: {{ $namespace }}
labels:
"app.kubernetes.io/name": '{{ $serviceName }}'
{{- if $v.renderHelmLabels }}
"helm.sh/chart": "{{ $chart }}"
{{- end }}
"app.kubernetes.io/managed-by": "{{ $r.Service }}"
"app.kubernetes.io/instance": "{{ $r.Name }}"
"app.kubernetes.io/component": "{{ $v.controller.componentName }}"
spec:
type: {{ .type | default "Opaque" }}
path: {{ .path }}
{{- if .renew }}
renew: {{ .renew }}
{{- end }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,20 @@
{{- if and .Values.controller.httpsKeyStore.enable ( not .Values.controller.httpsKeyStore.jenkinsHttpsJksSecretName ) (not .Values.controller.httpsKeyStore.disableSecretMount) -}}
apiVersion: v1
kind: Secret
metadata:
name: {{ template "jenkins.fullname" . }}-https-jks
namespace: {{ template "jenkins.namespace" . }}
labels:
"app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
{{- if .Values.renderHelmLabels }}
"helm.sh/chart": "{{ template "jenkins.label" .}}"
{{- end }}
"app.kubernetes.io/managed-by": "{{ .Release.Service }}"
"app.kubernetes.io/instance": "{{ .Release.Name }}"
"app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
type: Opaque
data:
jenkins-jks-file: |
{{ .Values.controller.httpsKeyStore.jenkinsKeyStoreBase64Encoded | indent 4 }}
https-jks-password: {{ .Values.controller.httpsKeyStore.password | b64enc }}
{{- end }}

View File

@ -0,0 +1,20 @@
{{- if and (not .Values.controller.admin.existingSecret) (.Values.controller.admin.createSecret) -}}
apiVersion: v1
kind: Secret
metadata:
name: {{ template "jenkins.fullname" . }}
namespace: {{ template "jenkins.namespace" . }}
labels:
"app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
{{- if .Values.renderHelmLabels }}
"helm.sh/chart": "{{ template "jenkins.label" .}}"
{{- end }}
"app.kubernetes.io/managed-by": "{{ .Release.Service }}"
"app.kubernetes.io/instance": "{{ .Release.Name }}"
"app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
type: Opaque
data:
jenkins-admin-password: {{ template "jenkins.password" . }}
jenkins-admin-user: {{ .Values.controller.admin.username | b64enc | quote }}
{{- end }}

View File

@ -0,0 +1,26 @@
{{ if .Values.serviceAccountAgent.create }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ include "jenkins.serviceAccountAgentName" . }}
namespace: {{ template "jenkins.agent.namespace" . }}
{{- if .Values.serviceAccountAgent.annotations }}
annotations:
{{ tpl (toYaml .Values.serviceAccountAgent.annotations) . | indent 4 }}
{{- end }}
labels:
"app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
{{- if .Values.renderHelmLabels }}
"helm.sh/chart": "{{ template "jenkins.label" .}}"
{{- end }}
"app.kubernetes.io/managed-by": "{{ .Release.Service }}"
"app.kubernetes.io/instance": "{{ .Release.Name }}"
"app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
{{- if .Values.serviceAccountAgent.extraLabels }}
{{ tpl (toYaml .Values.serviceAccountAgent.extraLabels) . | indent 4 }}
{{- end }}
{{- if .Values.serviceAccountAgent.imagePullSecretName }}
imagePullSecrets:
- name: {{ .Values.serviceAccountAgent.imagePullSecretName }}
{{- end -}}
{{ end }}

View File

@ -0,0 +1,26 @@
{{ if .Values.serviceAccount.create }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ include "jenkins.serviceAccountName" . }}
namespace: {{ template "jenkins.namespace" . }}
{{- if .Values.serviceAccount.annotations }}
annotations:
{{ tpl (toYaml .Values.serviceAccount.annotations) . | indent 4 }}
{{- end }}
labels:
"app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
{{- if .Values.renderHelmLabels }}
"helm.sh/chart": "{{ template "jenkins.label" .}}"
{{- end }}
"app.kubernetes.io/managed-by": "{{ .Release.Service }}"
"app.kubernetes.io/instance": "{{ .Release.Name }}"
"app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
{{- if .Values.serviceAccount.extraLabels }}
{{ tpl (toYaml .Values.serviceAccount.extraLabels) . | indent 4 }}
{{- end }}
{{- if .Values.serviceAccount.imagePullSecretName }}
imagePullSecrets:
- name: {{ .Values.serviceAccount.imagePullSecretName }}
{{- end -}}
{{ end }}

View File

@ -0,0 +1,49 @@
{{- if .Values.controller.testEnabled }}
apiVersion: v1
kind: Pod
metadata:
name: "{{ .Release.Name }}-ui-test-{{ randAlphaNum 5 | lower }}"
namespace: {{ template "jenkins.namespace" . }}
annotations:
"helm.sh/hook": test-success
spec:
{{- if .Values.controller.nodeSelector }}
nodeSelector:
{{ toYaml .Values.controller.nodeSelector | indent 4 }}
{{- end }}
{{- if .Values.controller.tolerations }}
tolerations:
{{ toYaml .Values.controller.tolerations | indent 4 }}
{{- end }}
initContainers:
- name: "test-framework"
image: "{{ .Values.helmtest.bats.image.registry }}/{{ .Values.helmtest.bats.image.repository }}:{{ .Values.helmtest.bats.image.tag }}"
command:
- "bash"
- "-c"
args:
- |
# copy bats to tools dir
set -ex
cp -R /opt/bats /tools/bats/
volumeMounts:
- mountPath: /tools
name: tools
containers:
- name: {{ .Release.Name }}-ui-test
image: "{{ .Values.controller.image.registry }}/{{ .Values.controller.image.repository }}:{{- include "controller.image.tag" . -}}"
command: ["/tools/bats/bin/bats", "-t", "/tests/run.sh"]
volumeMounts:
- mountPath: /tests
name: tests
readOnly: true
- mountPath: /tools
name: tools
volumes:
- name: tests
configMap:
name: {{ template "jenkins.fullname" . }}-tests
- name: tools
emptyDir: {}
restartPolicy: Never
{{- end }}

View File

@ -0,0 +1,14 @@
{{- if .Values.controller.testEnabled }}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ template "jenkins.fullname" . }}-tests
namespace: {{ template "jenkins.namespace" . }}
annotations:
"helm.sh/hook": test
data:
run.sh: |-
@test "Testing Jenkins UI is accessible" {
curl --retry 48 --retry-delay 10 {{ template "jenkins.fullname" . }}:{{ .Values.controller.servicePort }}{{ default "" .Values.controller.jenkinsUriPrefix }}/login
}
{{- end }}

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,6 @@ annotations:
url: https://www.kubecost.com
catalog.cattle.io/certified: partner
catalog.cattle.io/display-name: Kubecost
catalog.cattle.io/featured: "1"
catalog.cattle.io/release-name: cost-analyzer
apiVersion: v2
appVersion: 2.3.3

View File

@ -0,0 +1,14 @@
annotations:
artifacthub.io/links: |
- name: Homepage
url: https://www.kubecost.com
catalog.cattle.io/certified: partner
catalog.cattle.io/display-name: Kubecost
catalog.cattle.io/featured: "1"
catalog.cattle.io/release-name: cost-analyzer
apiVersion: v2
appVersion: 2.3.4
description: Kubecost Helm chart - monitor your cloud costs!
icon: file://assets/icons/cost-analyzer.png
name: cost-analyzer
version: 2.3.4

View File

@ -0,0 +1,116 @@
# Kubecost Helm chart
This is the official Helm chart for [Kubecost](https://www.kubecost.com/), an enterprise-grade application to monitor and manage Kubernetes spend. Please see the [website](https://www.kubecost.com/) for more details on what Kubecost can do for you and the official documentation [here](https://docs.kubecost.com/), or contact [team@kubecost.com](mailto:team@kubecost.com) for assistance.
To install via Helm, run the following command.
```sh
helm upgrade --install kubecost -n kubecost --create-namespace \
--repo https://kubecost.github.io/cost-analyzer/ cost-analyzer \
--set kubecostToken="aGVsbUBrdWJlY29zdC5jb20=xm343yadf98"
```
Alternatively, add the Helm repository first and scan for updates.
```sh
helm repo add kubecost https://kubecost.github.io/cost-analyzer/
helm repo update
```
Next, install the chart.
```sh
helm install kubecost kubecost/cost-analyzer -n kubecost --create-namespace \
--set kubecostToken="aGVsbUBrdWJlY29zdC5jb20=xm343yadf98"
```
While Helm is the [recommended install path](http://kubecost.com/install) for Kubecost especially in production, Kubecost can alternatively be deployed with a single-file manifest using the following command. Keep in mind when choosing this method, Kubecost will be installed from a development branch and may include unreleased changes.
```sh
kubectl apply -f https://raw.githubusercontent.com/kubecost/cost-analyzer-helm-chart/develop/kubecost.yaml
```
The following table lists commonly used configuration parameters for the Kubecost Helm chart and their default values. Please see the [values file](values.yaml) for the complete set of definable values.
| Parameter | Description | Default |
|------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------|
| `global.prometheus.enabled` | If false, use an existing Prometheus install. [More info](http://docs.kubecost.com/custom-prom). | `true` |
| `prometheus.server.persistentVolume.enabled` | If true, Prometheus server will create a Persistent Volume Claim. | `true` |
| `prometheus.server.persistentVolume.size` | Prometheus server data Persistent Volume size. Default set to retain ~6000 samples per second for 15 days. | `32Gi` |
| `prometheus.server.retention` | Determines when to remove old data. | `15d` |
| `prometheus.server.resources` | Prometheus server resource requests and limits. | `{}` |
| `prometheus.nodeExporter.resources` | Node exporter resource requests and limits. | `{}` |
| `prometheus.nodeExporter.enabled` `prometheus.serviceAccounts.nodeExporter.create` | If false, do not crate NodeExporter daemonset. | `true` |
| `prometheus.alertmanager.persistentVolume.enabled` | If true, Alertmanager will create a Persistent Volume Claim. | `true` |
| `prometheus.pushgateway.persistentVolume.enabled` | If true, Prometheus Pushgateway will create a Persistent Volume Claim. | `true` |
| `persistentVolume.enabled` | If true, Kubecost will create a Persistent Volume Claim for product config data. | `true` |
| `persistentVolume.size` | Define PVC size for cost-analyzer | `32.0Gi` |
| `persistentVolume.dbSize` | Define PVC size for cost-analyzer's flat file database | `32.0Gi` |
| `ingress.enabled` | If true, Ingress will be created | `false` |
| `ingress.annotations` | Ingress annotations | `{}` |
| `ingress.className` | Ingress class name | `{}` |
| `ingress.paths` | Ingress paths | `["/"]` |
| `ingress.hosts` | Ingress hostnames | `[cost-analyzer.local]` |
| `ingress.tls` | Ingress TLS configuration (YAML) | `[]` |
| `networkPolicy.enabled` | If true, create a NetworkPolicy to deny egress | `false` |
| `networkPolicy.costAnalyzer.enabled` | If true, create a newtork policy for cost-analzyer | `false` |
| `networkPolicy.costAnalyzer.annotations` | Annotations to be added to the network policy | `{}` |
| `networkPolicy.costAnalyzer.additionalLabels` | Additional labels to be added to the network policy | `{}` |
| `networkPolicy.costAnalyzer.ingressRules` | A list of network policy ingress rules | `null` |
| `networkPolicy.costAnalyzer.egressRules` | A list of network policy egress rules | `null` |
| `networkCosts.enabled` | If true, collect network allocation metrics [More info](http://docs.kubecost.com/network-allocation) | `false` |
| `networkCosts.podMonitor.enabled` | If true, a [PodMonitor](https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#podmonitor) for the network-cost daemonset is created | `false` |
| `serviceMonitor.enabled` | Set this to `true` to create ServiceMonitor for Prometheus operator | `false` |
| `serviceMonitor.additionalLabels` | Additional labels that can be used so ServiceMonitor will be discovered by Prometheus | `{}` |
| `serviceMonitor.relabelings` | Sets Prometheus metric_relabel_configs on the scrape job | `[]` |
| `serviceMonitor.metricRelabelings` | Sets Prometheus relabel_configs on the scrape job | `[]` |
| `prometheusRule.enabled` | Set this to `true` to create PrometheusRule for Prometheus operator | `false` |
| `prometheusRule.additionalLabels` | Additional labels that can be used so PrometheusRule will be discovered by Prometheus | `{}` |
| `grafana.resources` | Grafana resource requests and limits. | `{}` |
| `grafana.serviceAccount.create` | If true, create a Service Account for Grafana. | `true` |
| `grafana.serviceAccount.name` | Grafana Service Account name. | `{}` |
| `grafana.sidecar.datasources.defaultDatasourceEnabled` | Set this to `false` to disable creation of Prometheus datasource in Grafana | `true` |
| `serviceAccount.create` | Set this to `false` if you want to create the service account `kubecost-cost-analyzer` on your own | `true` |
| `tolerations` | node taints to tolerate | `[]` |
| `affinity` | pod affinity | `{}` |
| `kubecostProductConfigs.productKey.mountPath` | Use instead of `kubecostProductConfigs.productKey.secretname` to declare the path at which the product key file is mounted (eg. by a secrets provisioner) | `N/A` |
| `kubecostFrontend.api.fqdn` | Customize the upstream api FQDN | `computed in terms of the service name and namespace` |
| `kubecostFrontend.model.fqdn` | Customize the upstream model FQDN | `computed in terms of the service name and namespace` |
| `clusterController.fqdn` | Customize the upstream cluster controller FQDN | `computed in terms of the service name and namespace` |
| `global.grafana.fqdn` | Customize the upstream grafana FQDN | `computed in terms of the release name and namespace` |
## Adjusting Log Output
The log output can be customized during deployment by using the `LOG_LEVEL` and/or `LOG_FORMAT` environment variables.
### Adjusting Log Level
Adjusting the log level increases or decreases the level of verbosity written to the logs. To set the log level to `trace`, the following flag can be added to the `helm` command.
```sh
--set 'kubecostModel.extraEnv[0].name=LOG_LEVEL,kubecostModel.extraEnv[0].value=trace'
```
### Adjusting Log Format
Adjusting the log format changes the format in which the logs are output making it easier for log aggregators to parse and display logged messages. The `LOG_FORMAT` environment variable accepts the values `JSON`, for a structured output, and `pretty` for a nice, human-readable output.
| Value | Output |
|--------|----------------------------------------------------------------------------------------------------------------------------|
| `JSON` | `{"level":"info","time":"2006-01-02T15:04:05.999999999Z07:00","message":"Starting cost-model (git commit \"1.91.0-rc.0\")"}` |
| `pretty` | `2006-01-02T15:04:05.999999999Z07:00 INF Starting cost-model (git commit "1.91.0-rc.0")` |
## Testing
To perform local testing do next:
- install locally [kind](https://github.com/kubernetes-sigs/kind) according to documentation.
- install locally [ct](https://github.com/helm/chart-testing) according to documentation.
- create local cluster using `kind` \
use image version from https://github.com/kubernetes-sigs/kind/releases e.g. `kindest/node:v1.25.11@sha256:227fa11ce74ea76a0474eeefb84cb75d8dad1b08638371ecf0e86259b35be0c8`
```shell
kind create cluster --image kindest/node:v1.25.11@sha256:227fa11ce74ea76a0474eeefb84cb75d8dad1b08638371ecf0e86259b35be0c8
```
- perform ct execution
```shell
ct install --chart-dirs="." --charts="."
```

View File

@ -0,0 +1,25 @@
# Kubecost
[Kubecost](https://kubecost.com/) is an open-source Kubernetes cost monitoring solution.
Kubecost gives teams visibility into current and historical Kubernetes spend and resource allocation. These models provide cost transparency in Kubernetes environments that support multiple applications, teams, departments, etc.
To see more on the functionality of the full Kubecost product, please visit the [features page](https://kubecost.com/#features) on our website.
Here is a summary of features enabled by this cost model:
- Real-time cost allocation by Kubernetes service, deployment, namespace, label, statefulset, daemonset, pod, and container
- Dynamic asset pricing enabled by integrations with AWS, Azure, and GCP billing APIs
- Supports on-prem k8s clusters with custom pricing sheets
- Allocation for in-cluster resources like CPU, GPU, memory, and persistent volumes.
- Allocation for AWS & GCP out-of-cluster resources like RDS instances and S3 buckets with key (optional)
- Easily export pricing data to Prometheus with /metrics endpoint ([learn more](https://github.com/kubecost/cost-model/blob/develop/PROMETHEUS.md))
- Free and open source distribution (Apache2 license)
## Requirements
- Kubernetes 1.8+
- kube-state-metrics
- Grafana
- Prometheus
- Node Exporter

View File

@ -0,0 +1,17 @@
kubecostAggregator:
enabled: true
cloudCost:
enabled: true
aggregatorDbStorage:
storageRequest: 10Gi
kubecostModel:
federatedStorageConfigSecret: federated-store
kubecostProductConfigs:
cloudIntegrationSecret: cloud-integration
clusterName: CLUSTER_NAME
prometheus:
server:
global:
external_labels:
# cluster_id should be unique for all clusters and the same value as .kubecostProductConfigs.clusterName
cluster_id: CLUSTER_NAME

View File

@ -0,0 +1,35 @@
kubecostProductConfigs:
clusterName: CLUSTER_NAME
# cloudIntegrationSecret: cloud-integration
federatedETL:
useExistingS3Config: false
federatedCluster: true
kubecostModel:
containerStatsEnabled: true
federatedStorageConfigSecret: federated-store
serviceAccount: # this example uses AWS IRSA, which creates a service account with rights to the s3 bucket. If using keys+secrets in the federated-store, set create: true
create: true
global:
prometheus:
enabled: true
# fqdn: http://prometheus-operated.monitoring:9090
grafana: # prometheus metrics will be local cluster only, disable grafana to save resources
enabled: false
proxy: false
prometheus:
nodeExporter:
enabled: false
server:
global:
external_labels:
# cluster_id should be unique for all clusters and the same value as .kubecostProductConfigs.clusterName
cluster_id: CLUSTER_NAME
networkCosts:
# optional, see: https://docs.kubecost.com/install-and-configure/advanced-configuration/network-costs-configuration
enabled: true
config:
services:
# set the appropriate cloud provider to true
amazon-web-services: true
# google-cloud-services: true
# azure-cloud-services: true

View File

@ -0,0 +1,46 @@
### This test is to verify that Kubecost aggregator is deployed as a StatefulSet,
### cluster controller is installed, and the various Prometheus components are installed.
global:
podAnnotations:
kubecost.io/test1: value1
kubecost.io/test2: value2
additionalLabels:
kubecosttest1: value1
kubecosttest2: value2
prometheus:
enabled: true
# fqdn: http://prometheus-operated.monitoring:9090
grafana: # prometheus metrics will be local cluster only, disable grafana to save resources
enabled: false
proxy: false
kubecostProductConfigs:
clusterName: CLUSTER_NAME
kubecostAggregator:
deployMethod: statefulset
kubecostModel:
federatedStorageConfigSecret: federated-store
clusterController:
enabled: true
actionConfigs:
clusterTurndown:
- name: my-schedule2
start: "2034-02-09T00:00:00Z"
end: "2034-02-09T01:00:00Z"
repeat: none
prometheus:
nodeExporter:
enabled: true
alertmanager:
enabled: true
configmapReload:
prometheus:
enabled: true
pushgateway:
enabled: true
server:
statefulSet:
enabled: true
global:
external_labels:
# cluster_id should be unique for all clusters and the same value as .kubecostProductConfigs.clusterName
cluster_id: CLUSTER_NAME

View File

@ -0,0 +1,78 @@
# TurndownSchedule Custom Resource Definition for persistence
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: turndownschedules.kubecost.com
spec:
group: kubecost.com
names:
kind: TurndownSchedule
singular: turndownschedule
plural: turndownschedules
shortNames:
- td
- tds
scope: Cluster
versions:
- name: v1alpha1
served: true
storage: true
subresources:
status: {}
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
start:
type: string
format: date-time
end:
type: string
format: date-time
repeat:
type: string
enum: [none, daily, weekly]
status:
type: object
properties:
state:
type: string
lastUpdated:
format: date-time
type: string
current:
type: string
scaleDownId:
type: string
nextScaleDownTime:
format: date-time
type: string
scaleDownMetadata:
additionalProperties:
type: string
type: object
scaleUpID:
type: string
nextScaleUpTime:
format: date-time
type: string
scaleUpMetadata:
additionalProperties:
type: string
type: object
additionalPrinterColumns:
- name: State
type: string
description: The state of the turndownschedule
jsonPath: .status.state
- name: Next Turndown
type: string
description: The next turndown date-time
jsonPath: .status.nextScaleDownTime
- name: Next Turn Up
type: string
description: The next turn up date-time
jsonPath: .status.nextScaleUpTime

View File

@ -0,0 +1,7 @@
EndTimestamp,InstanceID,Region,AssetClass,InstanceIDField,InstanceType,MarketPriceHourly,Version
2028-01-06 23:34:45 UTC,,us-east-2,node,metadata.name,g4dn.xlarge,5.55,
2028-01-06 23:34:45 UTC,,,node,metadata.name,R730-type1,1.35,
2028-01-06 23:34:45 UTC,,,pv,metadata.name,standard,0.44,
2028-01-06 23:34:45 UTC,a100,,gpu,gpu.nvidia.com/class,,0.75,
2028-01-06 23:34:45 UTC,RTX3090,,gpu,nvidia.com/gpu_type,,0.65,
2028-01-06 23:34:45 UTC,i-01045ab6d13179700,,,spec.providerID,,1.2,
1 EndTimestamp InstanceID Region AssetClass InstanceIDField InstanceType MarketPriceHourly Version
2 2028-01-06 23:34:45 UTC us-east-2 node metadata.name g4dn.xlarge 5.55
3 2028-01-06 23:34:45 UTC node metadata.name R730-type1 1.35
4 2028-01-06 23:34:45 UTC pv metadata.name standard 0.44
5 2028-01-06 23:34:45 UTC a100 gpu gpu.nvidia.com/class 0.75
6 2028-01-06 23:34:45 UTC RTX3090 gpu nvidia.com/gpu_type 0.65
7 2028-01-06 23:34:45 UTC i-01045ab6d13179700 spec.providerID 1.2

View File

@ -0,0 +1,45 @@
# Kubecost Grafana Dashboards
## Overview
Kubecost, by default, is bundled with a Grafana instance that already contains the dashboards in this folder.
The dashboards in this repo are imported into Kubecost, unless disabled with
The same dashboards have template versions in [grafana-templates/](grafana-templates/) for those wanting to load the dashboards into an existing Grafana instance.
## Caveats
The primary purpose of the dashboards provided is to allow visibility into the metrics used by Kubecost to create the cost-model.
The networkCosts-metrics dashboard requires the optional networkCosts daemonset to be [enabled](https://docs.kubecost.com/install-and-configure/advanced-configuration/network-costs-configuration).
## Metrics Required
`kubecost-container-stats` metrics:
```
container_cpu_usage_seconds_total
kube_pod_container_resource_requests
container_memory_working_set_bytes
container_cpu_cfs_throttled_periods_total
container_cpu_cfs_periods_total
```
`network-transfer-data` metrics:
```
kubecost_pod_network_ingress_bytes_total
kubecost_pod_network_egress_bytes_total
```
`disk-usage` metrics:
```
container_fs_limit_bytes
container_fs_usage_bytes
```
## Additional Information
Kubecost Grafana [Configuration Guide](https://docs.kubecost.com/install-and-configure/advanced-configuration/custom-grafana)

View File

@ -0,0 +1,549 @@
{
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": {
"type": "datasource",
"uid": "grafana"
},
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"target": {
"limit": 100,
"matchAny": false,
"tags": [],
"type": "dashboard"
},
"type": "dashboard"
}
]
},
"editable": true,
"fiscalYearStartMonth": 0,
"graphTooltip": 0,
"id": 16,
"links": [],
"liveNow": false,
"panels": [
{
"datasource": {
"type": "prometheus",
"uid": "PBFA97CFB590B2093"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 10,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "never",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "decbytes"
},
"overrides": []
},
"gridPos": {
"h": 9,
"w": 12,
"x": 0,
"y": 0
},
"id": 2,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "multi",
"sort": "none"
}
},
"pluginVersion": "9.0.2",
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "PBFA97CFB590B2093"
},
"editorMode": "code",
"expr": "sum(container_fs_limit_bytes{instance=~'$disk', device!=\"tmpfs\", id=\"/\", cluster_id=~'$cluster'}) by (cluster_id, instance)",
"format": "time_series",
"interval": "",
"intervalFactor": 1,
"legendFormat": "{{cluster_id}}/{{instance}}",
"range": true,
"refId": "A"
}
],
"title": "Disk Size",
"type": "timeseries"
},
{
"datasource": {
"type": "prometheus",
"uid": "PBFA97CFB590B2093"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 10,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "never",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"decimals": 1,
"mappings": [],
"min": 0,
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "percentunit"
},
"overrides": []
},
"gridPos": {
"h": 9,
"w": 12,
"x": 12,
"y": 0
},
"id": 4,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "multi",
"sort": "none"
}
},
"pluginVersion": "9.0.2",
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "PBFA97CFB590B2093"
},
"editorMode": "code",
"expr": "sum(container_fs_usage_bytes{instance=~'$disk',id=\"/\", cluster_id=~'$cluster'}) by (cluster_id, instance) / sum(container_fs_limit_bytes{instance=~'$disk',device!=\"tmpfs\", id=\"/\", cluster_id=~'$cluster'}) by (cluster_id,instance)",
"format": "time_series",
"interval": "",
"intervalFactor": 1,
"legendFormat": "{{cluster_id}}-{{instance}}",
"range": true,
"refId": "A"
}
],
"title": "Disk Utilization",
"type": "timeseries"
},
{
"datasource": {
"type": "prometheus",
"uid": "PBFA97CFB590B2093"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 10,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "never",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"decimals": 1,
"mappings": [],
"min": 0,
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "percentunit"
},
"overrides": []
},
"gridPos": {
"h": 9,
"w": 12,
"x": 0,
"y": 9
},
"id": 5,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "multi",
"sort": "none"
}
},
"pluginVersion": "9.0.2",
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "PBFA97CFB590B2093"
},
"editorMode": "code",
"expr": "1 - sum(container_fs_inodes_free{instance=~'$disk',id=\"/\", cluster_id=~'$cluster'}) by (cluster_id, instance) / sum(container_fs_inodes_total{instance=~'$disk',id=\"/\", cluster_id=~'$cluster'}) by (cluster_id, instance)",
"format": "time_series",
"intervalFactor": 1,
"legendFormat": "{{cluster_id}}/{{instance}}",
"range": true,
"refId": "A"
}
],
"title": "iNode Utilization",
"type": "timeseries"
},
{
"datasource": {
"type": "prometheus",
"uid": "PBFA97CFB590B2093"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 10,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "never",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "decbytes"
},
"overrides": []
},
"gridPos": {
"h": 9,
"w": 12,
"x": 12,
"y": 9
},
"id": 3,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "multi",
"sort": "none"
}
},
"pluginVersion": "9.0.2",
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "PBFA97CFB590B2093"
},
"editorMode": "code",
"expr": "sum(container_fs_usage_bytes{instance=~'$disk',id=\"/\", cluster_id=~'$cluster'}) by (cluster_id, instance)",
"format": "time_series",
"interval": "",
"intervalFactor": 1,
"legendFormat": "{{cluster_id}}/{{instance}}",
"range": true,
"refId": "A"
}
],
"title": "Disk Usage",
"type": "timeseries"
}
],
"schemaVersion": 39,
"tags": [
"kubecost",
"cost",
"utilization",
"metrics"
],
"templating": {
"list": [
{
"current": {
"selected": false,
"text": "Prometheus",
"value": "PBFA97CFB590B2093"
},
"hide": 0,
"includeAll": false,
"multi": false,
"name": "datasource",
"options": [],
"query": "prometheus",
"queryValue": "",
"refresh": 1,
"regex": "",
"skipUrlSync": false,
"type": "datasource"
},
{
"current": {
"selected": true,
"text": "All",
"value": "$__all"
},
"datasource": {
"type": "prometheus",
"uid": "PBFA97CFB590B2093"
},
"definition": "label_values(cluster_id)",
"hide": 0,
"includeAll": true,
"multi": false,
"name": "cluster",
"options": [],
"query": {
"query": "label_values(cluster_id)",
"refId": "StandardVariableQuery"
},
"refresh": 2,
"regex": "",
"skipUrlSync": false,
"sort": 5,
"type": "query"
},
{
"current": {
"selected": true,
"text": "ip-192-168-147-146.us-east-2.compute.internal",
"value": "ip-192-168-147-146.us-east-2.compute.internal"
},
"datasource": {
"type": "prometheus",
"uid": "PBFA97CFB590B2093"
},
"definition": "label_values(container_fs_limit_bytes{cluster_id=~\"$cluster\"}, instance)",
"hide": 0,
"includeAll": true,
"multi": false,
"name": "disk",
"options": [],
"query": {
"query": "label_values(container_fs_limit_bytes{cluster_id=~\"$cluster\"}, instance)",
"refId": "StandardVariableQuery"
},
"refresh": 2,
"regex": "",
"skipUrlSync": false,
"sort": 5,
"tagValuesQuery": "",
"tagsQuery": "",
"type": "query",
"useTags": false
}
]
},
"time": {
"from": "now-7d",
"to": "now"
},
"timepicker": {
"refresh_intervals": [
"5s",
"10s",
"30s",
"1m",
"5m",
"15m",
"30m",
"1h",
"2h",
"1d"
],
"time_options": [
"5m",
"15m",
"1h",
"6h",
"12h",
"24h",
"2d",
"7d",
"30d"
]
},
"timezone": "",
"title": "Attached disk metrics",
"uid": "nBH7qBgMk",
"version": 7,
"weekStart": ""
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,668 @@
{
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": {
"type": "grafana",
"uid": "-- Grafana --"
},
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"type": "dashboard"
}
]
},
"editable": true,
"fiscalYearStartMonth": 0,
"graphTooltip": 0,
"links": [],
"liveNow": false,
"panels": [
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "bytes"
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 0,
"y": 0
},
"id": 7,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"editorMode": "code",
"expr": "sum(rate(container_fs_writes_bytes_total{pod=~\".+-aggregator-0\",namespace=~\"$namespace\"}[2m])) by (namespace)",
"instant": false,
"legendFormat": "__auto",
"range": true,
"refId": "A"
}
],
"title": "Storage Write",
"type": "timeseries"
},
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "bytes"
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 12,
"y": 0
},
"id": 6,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"editorMode": "code",
"expr": "sum(rate(container_fs_reads_bytes_total{pod=~\".+-aggregator-0\",namespace=~\"$namespace\"}[2m])) by (namespace)",
"instant": false,
"legendFormat": "__auto",
"range": true,
"refId": "A"
}
],
"title": "Storage Read",
"type": "timeseries"
},
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"decimals": 0,
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "bytes"
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 0,
"y": 8
},
"id": 4,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"editorMode": "code",
"expr": "sum(container_memory_working_set_bytes{container=\"aggregator\",pod!=\"\",namespace=~\"$namespace\"} ) by (namespace)",
"instant": false,
"legendFormat": "__auto",
"range": true,
"refId": "A"
}
],
"title": "Memory Usage",
"type": "timeseries"
},
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 12,
"y": 8
},
"id": 5,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"editorMode": "code",
"expr": "sum(rate(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate\r\n{container=\"aggregator\",pod!=\"\",namespace=~\"$namespace\"}[2m])) by (namespace)",
"instant": false,
"legendFormat": "__auto",
"range": true,
"refId": "A"
}
],
"title": "CPU Usage",
"type": "timeseries"
},
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "bytes"
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 0,
"y": 16
},
"id": 2,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"editorMode": "code",
"expr": "sum(kubelet_volume_stats_available_bytes{persistentvolumeclaim=~\"aggregator.+\",namespace=~\"$namespace\"}) by (namespace)",
"hide": false,
"instant": false,
"legendFormat": "__auto",
"range": true,
"refId": "C"
}
],
"title": "Storage Available",
"type": "timeseries"
},
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "bytes"
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 12,
"y": 16
},
"id": 3,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"editorMode": "code",
"expr": "sum(rate(container_network_receive_bytes_total{pod=~\".+aggregator-0\",namespace=~\"$namespace\"}[2m])) by (namespace)",
"instant": false,
"legendFormat": "__auto",
"range": true,
"refId": "A"
}
],
"title": "Network Receive Bytes",
"type": "timeseries"
}
],
"refresh": "30s",
"schemaVersion": 39,
"tags": [
"utilization",
"metrics",
"kubecost"
],
"templating": {
"list": [
{
"current": {
"selected": true,
"text": "Prometheus",
"value": "prometheus"
},
"hide": 0,
"includeAll": false,
"multi": false,
"name": "datasource",
"options": [],
"query": "prometheus",
"queryValue": "",
"refresh": 1,
"regex": "",
"skipUrlSync": false,
"type": "datasource"
},
{
"current": {
"selected": false,
"text": "All",
"value": "$__all"
},
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"definition": "label_values(container_memory_working_set_bytes{container=\"aggregator\"},namespace)",
"hide": 0,
"includeAll": true,
"multi": false,
"name": "namespace",
"options": [],
"query": {
"qryType": 1,
"query": "label_values(container_memory_working_set_bytes{container=\"aggregator\"},namespace)",
"refId": "PrometheusVariableQueryEditor-VariableQuery"
},
"refresh": 1,
"regex": "",
"skipUrlSync": false,
"sort": 5,
"type": "query"
}
]
},
"time": {
"from": "now-1d",
"to": "now"
},
"timepicker": {},
"timezone": "",
"title": "Kubecost Aggregator Metrics",
"uid": "kubecost_aggregator_metrics",
"version": 1,
"weekStart": ""
}

View File

@ -0,0 +1,787 @@
{
"__inputs": [
{
"name": "DS_THANOS",
"label": "Thanos",
"description": "",
"type": "datasource",
"pluginId": "prometheus",
"pluginName": "Prometheus"
}
],
"__elements": {},
"__requires": [
{
"type": "grafana",
"id": "grafana",
"name": "Grafana",
"version": "10.3.1"
},
{
"type": "datasource",
"id": "prometheus",
"name": "Prometheus",
"version": "1.0.0"
},
{
"type": "panel",
"id": "timeseries",
"name": "Time series",
"version": ""
}
],
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": {
"type": "datasource",
"uid": "grafana"
},
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"target": {
"limit": 100,
"matchAny": false,
"tags": [],
"type": "dashboard"
},
"type": "dashboard"
}
]
},
"description": "",
"editable": true,
"fiscalYearStartMonth": 0,
"gnetId": 9063,
"graphTooltip": 0,
"id": null,
"links": [],
"liveNow": false,
"panels": [
{
"datasource": {
"type": "prometheus",
"uid": "${DS_THANOS}"
},
"description": "Maximum CPU Core Usage vs avg Requested",
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 2,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": 3600000,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"min": 0,
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "none",
"unitScale": true
},
"overrides": []
},
"gridPos": {
"h": 7,
"w": 12,
"x": 0,
"y": 0
},
"id": 94,
"links": [],
"options": {
"legend": {
"calcs": [
"max"
],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "multi",
"sort": "desc"
}
},
"pluginVersion": "9.4.7",
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "${DS_THANOS}"
},
"editorMode": "code",
"expr": "max(irate(container_cpu_usage_seconds_total\r\n {cluster_id=\"$cluster\",namespace=~\"$namespace\",pod=~\"$pod\", container=~\"$container\", container!=\"POD\",container!=\"\"}\r\n [$__rate_interval])) \r\n by (cluster_id, namespace, pod, container)",
"format": "time_series",
"hide": false,
"instant": false,
"interval": "",
"intervalFactor": 1,
"legendFormat": "{{cluster_id}} {{namespace}}/{{pod}}/{{container}} (usage max)",
"metric": "container_cpu",
"refId": "A",
"step": 10
},
{
"datasource": {
"type": "prometheus",
"uid": "${DS_THANOS}"
},
"editorMode": "code",
"exemplar": true,
"expr": "avg(kube_pod_container_resource_requests\r\n {cluster_id=\"$cluster\",resource=\"cpu\",unit=\"core\",namespace=~\"$namespace\",pod=~\"$pod\",container=~\"$container\",container!=\"POD\"}\r\n ) \r\nby (cluster_id,namespace,pod,container)",
"legendFormat": "{{cluster_id}} {{namespace}}/{{pod}}/{{container}} (requested)",
"range": true,
"refId": "B"
}
],
"timeFrom": "",
"title": "CPU Core Usage vs Requested",
"type": "timeseries"
},
{
"datasource": {
"type": "prometheus",
"uid": "${DS_THANOS}"
},
"description": "Max memory used vs avg requested",
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 2,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": 3600000,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"min": 0,
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "bytes",
"unitScale": true
},
"overrides": []
},
"gridPos": {
"h": 7,
"w": 12,
"x": 12,
"y": 0
},
"id": 96,
"links": [],
"options": {
"legend": {
"calcs": [
"max"
],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "multi",
"sort": "asc"
}
},
"pluginVersion": "9.4.7",
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "${DS_THANOS}"
},
"editorMode": "code",
"expr": "max(max_over_time(container_memory_working_set_bytes\r\n {namespace=~\"$namespace\",pod=~\"$pod\",cluster_id=\"$cluster\",container=~\"$container\",container!=\"POD\",container!=\"\"}\r\n [$__rate_interval])) \r\nby (cluster_id,namespace,pod,container)",
"format": "time_series",
"hide": false,
"instant": false,
"interval": "",
"intervalFactor": 1,
"legendFormat": "{{cluster_id}} {{namespace}}/{{pod}}/{{container}} (usage max)",
"metric": "container_cpu",
"refId": "MEMORY_USAGE",
"step": 10
},
{
"datasource": {
"type": "prometheus",
"uid": "${DS_THANOS}"
},
"editorMode": "code",
"expr": "avg(kube_pod_container_resource_requests\n {resource=\"memory\",unit=\"byte\",cluster_id=\"$cluster\",namespace=~\"$namespace\",pod=~\"$pod\", container=~\"$container\",container!=\"POD\"}\n )\nby (cluster_id,namespace,pod,container)",
"format": "time_series",
"hide": false,
"instant": false,
"intervalFactor": 1,
"legendFormat": "{{cluster_id}} {{namespace}}/{{pod}}/{{container}} (requested)",
"refId": "MEMORY_REQUESTED"
}
],
"timeFrom": "",
"title": "Memory Usage vs Requested",
"type": "timeseries"
},
{
"datasource": {
"type": "prometheus",
"uid": "${DS_THANOS}"
},
"description": "Network traffic by pod",
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 10,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 2,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": 3600000,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "Bps",
"unitScale": true
},
"overrides": []
},
"gridPos": {
"h": 7,
"w": 12,
"x": 0,
"y": 7
},
"id": 95,
"links": [],
"options": {
"legend": {
"calcs": [
"mean"
],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "multi",
"sort": "desc"
}
},
"pluginVersion": "9.4.7",
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "${DS_THANOS}"
},
"editorMode": "code",
"expr": "sum(irate(container_network_receive_bytes_total\n {cluster_id=~\"$cluster\",namespace=~\"$namespace\",pod=~\"$pod\"}\n [$__rate_interval])) \nby (cluster_id, namespace, pod)",
"format": "time_series",
"hide": false,
"instant": false,
"interval": "",
"intervalFactor": 1,
"legendFormat": "{{cluster_id}} {{namespace}}/{{pod}}<- in",
"metric": "container_cpu",
"refId": "A",
"step": 10
},
{
"datasource": {
"type": "prometheus",
"uid": "${DS_THANOS}"
},
"editorMode": "code",
"expr": "- sum(irate(container_network_transmit_bytes_total\n {cluster_id=\"$cluster\",namespace=~\"$namespace\",pod=~\"$pod\"}\n [$__rate_interval])) \nby (cluster_id, namespace, pod)",
"format": "time_series",
"hide": false,
"instant": false,
"interval": "",
"intervalFactor": 1,
"legendFormat": "{{cluster_id}} {{namespace}}/{{pod}}-> out",
"refId": "B"
}
],
"timeFrom": "",
"title": "Network IO",
"type": "timeseries"
},
{
"datasource": {
"type": "prometheus",
"uid": "${DS_THANOS}"
},
"description": "Disk read writes",
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 10,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 2,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": 3600000,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "Bps",
"unitScale": true
},
"overrides": []
},
"gridPos": {
"h": 7,
"w": 12,
"x": 12,
"y": 7
},
"id": 97,
"links": [],
"options": {
"legend": {
"calcs": [
"mean"
],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "multi",
"sort": "desc"
}
},
"pluginVersion": "9.4.7",
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "${DS_THANOS}"
},
"editorMode": "code",
"expr": "sum(irate(container_fs_writes_bytes_total\r\n {cluster_id=\"$cluster\",namespace=~\"$namespace\",container!=\"POD\",pod!=\"\",pod=~\"$pod\",container=~\"$container\"}\r\n [$__rate_interval])) \r\nby (cluster_id,namespace,pod,container)",
"format": "time_series",
"hide": false,
"instant": false,
"interval": "",
"intervalFactor": 1,
"legendFormat": "{{cluster_id}} {{pod}}/{{container}}<- write",
"metric": "container_cpu",
"refId": "A",
"step": 10
},
{
"datasource": {
"type": "prometheus",
"uid": "${DS_THANOS}"
},
"editorMode": "code",
"expr": "- sum(irate(container_fs_reads_bytes_total\r\n {cluster_id=\"$cluster\",namespace=~\"$namespace\",container!=\"POD\",pod!=\"\",pod=~\"$pod\",container=~\"$container\"}\r\n [$__rate_interval])) \r\nby (cluster_id,namespace,pod,container)",
"format": "time_series",
"hide": false,
"instant": false,
"interval": "",
"intervalFactor": 1,
"legendFormat": "{{cluster_id}} {{pod}}/{{container}}-> read",
"refId": "B"
}
],
"timeFrom": "",
"title": "Disk IO",
"type": "timeseries"
},
{
"datasource": {
"type": "prometheus",
"uid": "${DS_THANOS}"
},
"description": "This graph shows the % of periods where a pod is being throttled. Values range from 0-100",
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 2,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": 1800000,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"min": 0,
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "percent",
"unitScale": true
},
"overrides": []
},
"gridPos": {
"h": 7,
"w": 12,
"x": 0,
"y": 14
},
"id": 99,
"links": [],
"options": {
"legend": {
"calcs": [
"mean"
],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "multi",
"sort": "desc"
}
},
"pluginVersion": "9.4.7",
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "${DS_THANOS}"
},
"editorMode": "code",
"expr": "100\n * sum by(cluster_id, namespace, pod, container) (increase(container_cpu_cfs_throttled_periods_total{container!=\"\",cluster_id=\"$cluster\", namespace=~\"$namespace\", pod=~\"$pod\", container=~\"$container\", container!=\"POD\"}[$__rate_interval]))\n / sum by(cluster_id,namespace,pod,container) (increase(container_cpu_cfs_periods_total{container!=\"\",cluster_id=\"$cluster\",namespace=~\"$namespace\",pod=~\"$pod\",container=~\"$container\",container!=\"POD\"}[$__rate_interval]))",
"format": "time_series",
"instant": false,
"interval": "",
"intervalFactor": 1,
"legendFormat": "",
"refId": "B"
}
],
"timeFrom": "",
"title": "CPU throttle percent",
"type": "timeseries"
}
],
"refresh": "",
"revision": 1,
"schemaVersion": 39,
"tags": [
"utilization",
"metrics",
"kubecost"
],
"templating": {
"list": [
{
"current": {},
"definition": "label_values(cluster_id)",
"hide": 0,
"includeAll": false,
"multi": false,
"name": "cluster",
"options": [],
"query": {
"query": "label_values(cluster_id)",
"refId": "StandardVariableQuery"
},
"refresh": 2,
"regex": "",
"skipUrlSync": false,
"sort": 5,
"type": "query"
},
{
"current": {},
"definition": "label_values(kube_namespace_labels{cluster_id=\"$cluster\"}, namespace) ",
"hide": 0,
"includeAll": true,
"label": "",
"multi": false,
"name": "namespace",
"options": [],
"query": {
"query": "label_values(kube_namespace_labels{cluster_id=\"$cluster\"}, namespace) ",
"refId": "StandardVariableQuery"
},
"refresh": 2,
"regex": "",
"skipUrlSync": false,
"sort": 5,
"tagValuesQuery": "",
"tagsQuery": "",
"type": "query",
"useTags": false
},
{
"current": {},
"definition": "label_values(kube_pod_labels{cluster_id=\"$cluster\",namespace=~\"$namespace\"}, pod) ",
"hide": 0,
"includeAll": true,
"label": "pod",
"multi": false,
"name": "pod",
"options": [],
"query": {
"query": "label_values(kube_pod_labels{cluster_id=\"$cluster\",namespace=~\"$namespace\"}, pod) ",
"refId": "StandardVariableQuery"
},
"refresh": 2,
"regex": "",
"skipUrlSync": false,
"sort": 1,
"tagValuesQuery": "",
"tagsQuery": "",
"type": "query",
"useTags": false
},
{
"current": {},
"definition": "label_values(container_memory_working_set_bytes{cluster_id=\"$cluster\",namespace=~\"$namespace\",pod=~\"$pod\", container!=\"POD\"}, container) ",
"hide": 0,
"includeAll": true,
"multi": false,
"name": "container",
"options": [],
"query": {
"query": "label_values(container_memory_working_set_bytes{cluster_id=\"$cluster\",namespace=~\"$namespace\",pod=~\"$pod\", container!=\"POD\"}, container) ",
"refId": "StandardVariableQuery"
},
"refresh": 2,
"regex": "",
"skipUrlSync": false,
"sort": 5,
"type": "query"
}
]
},
"time": {
"from": "now-2d",
"to": "now"
},
"timepicker": {
"hidden": false,
"refresh_intervals": [
"10s",
"30s",
"1m",
"5m",
"15m",
"30m",
"1h",
"2h",
"1d"
],
"time_options": [
"5m",
"15m",
"1h",
"6h",
"12h",
"24h",
"2d",
"7d",
"30d"
]
},
"timezone": "browser",
"title": "Pod utilization metrics (multi-cluster)",
"uid": "at-cost-analysis-pod2",
"version": 1,
"weekStart": ""
}

View File

@ -0,0 +1,571 @@
{
"__inputs": [
{
"name": "DS_PROMETHEUS",
"label": "Prometheus",
"description": "",
"type": "datasource",
"pluginId": "prometheus",
"pluginName": "Prometheus"
}
],
"__elements": {},
"__requires": [
{
"type": "grafana",
"id": "grafana",
"name": "Grafana",
"version": "10.4.2"
},
{
"type": "datasource",
"id": "prometheus",
"name": "Prometheus",
"version": "1.0.0"
},
{
"type": "panel",
"id": "timeseries",
"name": "Time series",
"version": ""
}
],
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": {
"type": "datasource",
"uid": "grafana"
},
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"target": {
"limit": 100,
"matchAny": false,
"tags": [],
"type": "dashboard"
},
"type": "dashboard"
}
]
},
"editable": true,
"fiscalYearStartMonth": 0,
"graphTooltip": 0,
"id": null,
"links": [],
"liveNow": false,
"panels": [
{
"datasource": {
"type": "prometheus",
"uid": "${DS_PROMETHEUS}"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 10,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "never",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "decbytes"
},
"overrides": []
},
"gridPos": {
"h": 9,
"w": 12,
"x": 0,
"y": 0
},
"id": 2,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "multi",
"sort": "none"
}
},
"pluginVersion": "9.0.2",
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "${DS_PROMETHEUS}"
},
"editorMode": "code",
"expr": "sum(container_fs_limit_bytes{instance=~'$disk', device!=\"tmpfs\", id=\"/\", cluster_id=~'$cluster'}) by (cluster_id, instance)",
"format": "time_series",
"interval": "",
"intervalFactor": 1,
"legendFormat": "{{cluster_id}}/{{instance}}",
"range": true,
"refId": "A"
}
],
"title": "Disk Size",
"type": "timeseries"
},
{
"datasource": {
"type": "prometheus",
"uid": "${DS_PROMETHEUS}"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 10,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "never",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"decimals": 1,
"mappings": [],
"min": 0,
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "percentunit"
},
"overrides": []
},
"gridPos": {
"h": 9,
"w": 12,
"x": 12,
"y": 0
},
"id": 4,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "multi",
"sort": "none"
}
},
"pluginVersion": "9.0.2",
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "${DS_PROMETHEUS}"
},
"editorMode": "code",
"expr": "sum(container_fs_usage_bytes{instance=~'$disk',id=\"/\", cluster_id=~'$cluster'}) by (cluster_id, instance) / sum(container_fs_limit_bytes{instance=~'$disk',device!=\"tmpfs\", id=\"/\", cluster_id=~'$cluster'}) by (cluster_id,instance)",
"format": "time_series",
"interval": "",
"intervalFactor": 1,
"legendFormat": "{{cluster_id}}-{{instance}}",
"range": true,
"refId": "A"
}
],
"title": "Disk Utilization",
"type": "timeseries"
},
{
"datasource": {
"type": "prometheus",
"uid": "${DS_PROMETHEUS}"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 10,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "never",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"decimals": 1,
"mappings": [],
"min": 0,
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "percentunit"
},
"overrides": []
},
"gridPos": {
"h": 9,
"w": 12,
"x": 0,
"y": 9
},
"id": 5,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "multi",
"sort": "none"
}
},
"pluginVersion": "9.0.2",
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "${DS_PROMETHEUS}"
},
"editorMode": "code",
"expr": "1 - sum(container_fs_inodes_free{instance=~'$disk',id=\"/\", cluster_id=~'$cluster'}) by (cluster_id, instance) / sum(container_fs_inodes_total{instance=~'$disk',id=\"/\", cluster_id=~'$cluster'}) by (cluster_id, instance)",
"format": "time_series",
"intervalFactor": 1,
"legendFormat": "{{cluster_id}}/{{instance}}",
"range": true,
"refId": "A"
}
],
"title": "iNode Utilization",
"type": "timeseries"
},
{
"datasource": {
"type": "prometheus",
"uid": "${DS_PROMETHEUS}"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 10,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "never",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "decbytes"
},
"overrides": []
},
"gridPos": {
"h": 9,
"w": 12,
"x": 12,
"y": 9
},
"id": 3,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "multi",
"sort": "none"
}
},
"pluginVersion": "9.0.2",
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "${DS_PROMETHEUS}"
},
"editorMode": "code",
"expr": "sum(container_fs_usage_bytes{instance=~'$disk',id=\"/\", cluster_id=~'$cluster'}) by (cluster_id, instance)",
"format": "time_series",
"interval": "",
"intervalFactor": 1,
"legendFormat": "{{cluster_id}}/{{instance}}",
"range": true,
"refId": "A"
}
],
"title": "Disk Usage",
"type": "timeseries"
}
],
"schemaVersion": 39,
"tags": [
"kubecost",
"utilization",
"metrics"
],
"templating": {
"list": [
{
"current": {
"selected": false,
"text": "Prometheus",
"value": "Prometheus"
},
"hide": 0,
"includeAll": false,
"multi": false,
"name": "datasource",
"options": [],
"query": "prometheus",
"queryValue": "",
"refresh": 1,
"regex": "",
"skipUrlSync": false,
"type": "datasource"
},
{
"current": {},
"datasource": {
"type": "prometheus",
"uid": "${DS_PROMETHEUS}"
},
"definition": "label_values(cluster_id)",
"hide": 0,
"includeAll": true,
"multi": false,
"name": "cluster",
"options": [],
"query": {
"query": "label_values(cluster_id)",
"refId": "StandardVariableQuery"
},
"refresh": 2,
"regex": "",
"skipUrlSync": false,
"sort": 5,
"type": "query"
},
{
"current": {},
"datasource": {
"type": "prometheus",
"uid": "${DS_PROMETHEUS}"
},
"definition": "label_values(container_fs_limit_bytes{cluster_id=~\"$cluster\"}, instance)",
"hide": 0,
"includeAll": true,
"multi": false,
"name": "disk",
"options": [],
"query": {
"query": "label_values(container_fs_limit_bytes{cluster_id=~\"$cluster\"}, instance)",
"refId": "StandardVariableQuery"
},
"refresh": 2,
"regex": "",
"skipUrlSync": false,
"sort": 5,
"tagValuesQuery": "",
"tagsQuery": "",
"type": "query",
"useTags": false
}
]
},
"time": {
"from": "now-7d",
"to": "now"
},
"timepicker": {
"refresh_intervals": [
"5s",
"10s",
"30s",
"1m",
"5m",
"15m",
"30m",
"1h",
"2h",
"1d"
],
"time_options": [
"5m",
"15m",
"1h",
"6h",
"12h",
"24h",
"2d",
"7d",
"30d"
]
},
"timezone": "",
"title": "Attached disk metrics (multi-cluster)",
"uid": "nBH7qBgMk",
"version": 2,
"weekStart": ""
}

View File

@ -0,0 +1,685 @@
{
"__inputs": [
{
"name": "DS_PROMETHEUS",
"label": "Prometheus",
"description": "",
"type": "datasource",
"pluginId": "prometheus",
"pluginName": "Prometheus"
}
],
"__elements": {},
"__requires": [
{
"type": "grafana",
"id": "grafana",
"name": "Grafana",
"version": "10.4.2"
},
{
"type": "datasource",
"id": "prometheus",
"name": "Prometheus",
"version": "1.0.0"
},
{
"type": "panel",
"id": "timeseries",
"name": "Time series",
"version": ""
}
],
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": {
"type": "grafana",
"uid": "-- Grafana --"
},
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"target": {
"limit": 100,
"matchAny": false,
"tags": [],
"type": "dashboard"
},
"type": "dashboard"
}
]
},
"description": "https://docs.kubecost.com/install-and-configure/advanced-configuration/network-costs-configuration",
"editable": true,
"fiscalYearStartMonth": 0,
"graphTooltip": 0,
"id": null,
"links": [],
"liveNow": false,
"panels": [
{
"collapsed": false,
"gridPos": {
"h": 1,
"w": 24,
"x": 0,
"y": 0
},
"id": 12,
"panels": [],
"title": "Network Data Transfers (negative is egress data)",
"type": "row"
},
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "bars",
"fillOpacity": 100,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "bytes"
},
"overrides": []
},
"gridPos": {
"h": 14,
"w": 11,
"x": 0,
"y": 1
},
"id": 10,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"editorMode": "code",
"expr": "sum(increase(kubecost_pod_network_ingress_bytes_total\n {namespace=~\"$namespace\", cluster_id=~\"$cluster\", pod_name=~\"$pod_name\", service=~\"$service\"}\n [1h]\n ))\nby($aggregation) ",
"interval": "1h",
"legendFormat": "__auto",
"range": true,
"refId": "A"
},
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"editorMode": "code",
"expr": "-sum(increase(kubecost_pod_network_egress_bytes_total\n {namespace=~\"$namespace\", cluster_id=~\"$cluster\", pod_name=~\"$pod_name\", service=~\"$service\"}\n [1h]\n ))\nby($aggregation) ",
"hide": false,
"interval": "1h",
"legendFormat": "__auto",
"range": true,
"refId": "B"
}
],
"title": "All Data",
"type": "timeseries"
},
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "bars",
"fillOpacity": 100,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "bytes"
},
"overrides": []
},
"gridPos": {
"h": 14,
"w": 13,
"x": 11,
"y": 1
},
"id": 2,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"editorMode": "code",
"expr": "sum(increase(kubecost_pod_network_ingress_bytes_total\n {internet=\"true\", namespace=~\"$namespace\", cluster_id=~\"$cluster\", pod_name=~\"$pod_name\", service=~\"$service\"}\n [1h]\n))\nby($aggregation) ",
"hide": false,
"interval": "1h",
"legendFormat": "__auto",
"range": true,
"refId": "A"
},
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"editorMode": "code",
"expr": "- sum(increase(kubecost_pod_network_egress_bytes_total\n {internet=\"true\", namespace=~\"$namespace\", cluster_id=~\"$cluster\", pod_name=~\"$pod_name\", service=~\"$service\"}\n [1h]))\nby($aggregation) ",
"hide": false,
"interval": "1h",
"legendFormat": "__auto",
"range": true,
"refId": "B"
}
],
"title": "Internet Data",
"type": "timeseries"
},
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"description": "Cross region and cross zone subnets must be defined via the configMap. \nSee: \n<https://docs.kubecost.com/install-and-configure/advanced-configuration/network-costs-configuration#overriding-traffic-classifications>",
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "bars",
"fillOpacity": 100,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"decimals": 2,
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "bytes"
},
"overrides": []
},
"gridPos": {
"h": 14,
"w": 11,
"x": 0,
"y": 15
},
"id": 9,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"editorMode": "code",
"expr": "sum(increase(kubecost_pod_network_ingress_bytes_total\n {internet=\"false\",namespace=~\"$namespace\",cluster_id=~\"$cluster\",pod_name=~\"$pod_name\", sameRegion=\"false\",sameZone=\"false\", service=~\"$service\"}\n [1h]))\nby($aggregation)",
"interval": "1h",
"legendFormat": "__auto",
"range": true,
"refId": "A"
},
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"editorMode": "code",
"expr": "- sum(increase(kubecost_pod_network_egress_bytes_total\n {internet=\"false\", namespace=~\"$namespace\",cluster_id=~\"$cluster\",pod_name=~\"$pod_name\",sameRegion=\"false\", sameZone=\"false\", service=~\"$service\"}\n [1h]))\nby($aggregation) ",
"hide": false,
"interval": "1h",
"legendFormat": "__auto",
"range": true,
"refId": "B"
}
],
"title": "Cross Region Data",
"type": "timeseries"
},
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"description": "Cross region and cross zone subnets must be defined via the configMap. \nSee: \n<https://docs.kubecost.com/install-and-configure/advanced-configuration/network-costs-configuration#overriding-traffic-classifications>",
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "bars",
"fillOpacity": 100,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"decimals": 2,
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "bytes"
},
"overrides": []
},
"gridPos": {
"h": 14,
"w": 13,
"x": 11,
"y": 15
},
"id": 8,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"editorMode": "code",
"expr": "sum(increase(kubecost_pod_network_ingress_bytes_total\n {internet=\"false\", namespace=~\"$namespace\", cluster_id=~\"$cluster\", pod_name=~\"$pod_name\", sameRegion=\"true\", sameZone=\"false\", service=~\"$service\"}\n [1h]))\nby($aggregation)",
"interval": "1h",
"legendFormat": "__auto",
"range": true,
"refId": "A"
},
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"editorMode": "code",
"expr": "- sum(increase(kubecost_pod_network_egress_bytes_total\n {internet=\"false\", namespace=~\"$namespace\", cluster_id=~\"$cluster\", pod_name=~\"$pod_name\", sameRegion=\"true\", sameZone=\"false\", service=~\"$service\"}\n [1h]))\nby($aggregation)",
"hide": false,
"interval": "1h",
"legendFormat": "__auto",
"range": true,
"refId": "B"
}
],
"title": "Cross Zone Data",
"type": "timeseries"
}
],
"refresh": "",
"revision": 1,
"schemaVersion": 39,
"tags": [
"kubecost"
],
"templating": {
"list": [
{
"current": {},
"hide": 0,
"includeAll": false,
"multi": false,
"name": "datasource",
"options": [],
"query": "prometheus",
"queryValue": "",
"refresh": 1,
"regex": "",
"skipUrlSync": false,
"type": "datasource"
},
{
"current": {
"selected": false,
"text": "namespace",
"value": "namespace"
},
"hide": 0,
"includeAll": false,
"multi": false,
"name": "aggregation",
"options": [
{
"selected": false,
"text": "cluster_id",
"value": "cluster_id"
},
{
"selected": true,
"text": "namespace",
"value": "namespace"
},
{
"selected": false,
"text": "pod_name",
"value": "pod_name"
}
],
"query": "cluster_id, namespace, pod_name",
"queryValue": "",
"skipUrlSync": false,
"type": "custom"
},
{
"current": {},
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"definition": "label_values(cluster_id)",
"hide": 0,
"includeAll": true,
"multi": false,
"name": "cluster",
"options": [],
"query": {
"query": "label_values(cluster_id)",
"refId": "StandardVariableQuery"
},
"refresh": 1,
"regex": "",
"skipUrlSync": false,
"sort": 5,
"type": "query"
},
{
"current": {
"selected": true,
"text": "kubecost",
"value": "kubecost"
},
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"definition": "label_values(kube_namespace_labels{cluster_id=~\"$cluster\"}, namespace) ",
"hide": 0,
"includeAll": true,
"multi": false,
"name": "namespace",
"options": [],
"query": {
"query": "label_values(kube_namespace_labels{cluster_id=~\"$cluster\"}, namespace) ",
"refId": "StandardVariableQuery"
},
"refresh": 2,
"regex": "",
"skipUrlSync": false,
"sort": 5,
"type": "query"
},
{
"current": {},
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"definition": "label_values(kubecost_pod_network_egress_bytes_total{cluster_id=~\"$cluster\", namespace=~\"$namespace\"},pod_name)",
"hide": 0,
"includeAll": true,
"multi": false,
"name": "pod_name",
"options": [],
"query": {
"qryType": 1,
"query": "label_values(kubecost_pod_network_egress_bytes_total{cluster_id=~\"$cluster\", namespace=~\"$namespace\"},pod_name)",
"refId": "PrometheusVariableQueryEditor-VariableQuery"
},
"refresh": 2,
"regex": "",
"skipUrlSync": false,
"sort": 5,
"type": "query"
},
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"filters": [],
"hide": 0,
"name": "filter",
"skipUrlSync": false,
"type": "adhoc"
},
{
"current": {},
"definition": "label_values(kubecost_pod_network_egress_bytes_total{namespace=~\"$namespace\"},service)",
"hide": 0,
"includeAll": true,
"multi": false,
"name": "service",
"options": [],
"query": {
"qryType": 1,
"query": "label_values(kubecost_pod_network_egress_bytes_total{namespace=~\"$namespace\"},service)",
"refId": "PrometheusVariableQueryEditor-VariableQuery"
},
"refresh": 1,
"regex": "",
"skipUrlSync": false,
"sort": 5,
"type": "query"
}
]
},
"time": {
"from": "now-7d",
"to": "now"
},
"timepicker": {},
"timezone": "",
"title": "Kubecost Network Costs Metrics",
"uid": "kubecost-networkCosts-metrics",
"version": 8,
"weekStart": ""
}

View File

@ -0,0 +1,408 @@
{
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": {
"type": "grafana",
"uid": "-- Grafana --"
},
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"target": {
"limit": 100,
"matchAny": false,
"tags": [],
"type": "dashboard"
},
"type": "dashboard"
}
]
},
"editable": true,
"fiscalYearStartMonth": 0,
"graphTooltip": 0,
"id": 29,
"links": [],
"liveNow": false,
"panels": [
{
"collapsed": false,
"gridPos": {
"h": 1,
"w": 24,
"x": 0,
"y": 0
},
"id": 2,
"panels": [],
"title": "Requests - Usage (negative values are unused reservations)",
"type": "row"
},
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": 3600000,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "bytes"
},
"overrides": []
},
"gridPos": {
"h": 16,
"w": 24,
"x": 0,
"y": 1
},
"id": 4,
"options": {
"legend": {
"calcs": [
"lastNotNull"
],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"editorMode": "code",
"expr": "sum by ($aggregation) (\n (sum by (cluster_id,namespace,pod,container) (container_memory_usage_bytes{cluster_id=~\"$cluster\",namespace=~\"$namespace\",container=~\"$container\",container!=\"POD\",container!=\"\"}))\n -(sum by (cluster_id,namespace,pod,container) (kube_pod_container_resource_requests{resource=\"memory\",unit=\"byte\",cluster_id=~\"$cluster\",namespace=~\"$namespace\",container=~\"$container\",container!=\"POD\",container!=\"\"}))\n)",
"legendFormat": "__auto",
"range": true,
"refId": "A"
},
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"editorMode": "code",
"expr": "sum by ($aggregation) (\n -(sum by (cluster_id,namespace,pod,container) (kube_pod_container_resource_requests{resource=\"memory\",unit=\"byte\",cluster_id=~\"$cluster\",namespace=~\"$namespace\",container=~\"$container\",container!=\"POD\",container!=\"\"}))\n)",
"hide": true,
"legendFormat": "{{$aggregation}} Request",
"range": true,
"refId": "B"
}
],
"title": "Memory Request-Usage",
"type": "timeseries"
},
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": 3600000,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "none"
},
"overrides": []
},
"gridPos": {
"h": 14,
"w": 24,
"x": 0,
"y": 17
},
"id": 6,
"options": {
"legend": {
"calcs": [
"lastNotNull"
],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"editorMode": "code",
"expr": "sum by ($aggregation)(\n (sum by (cluster_id,namespace,pod,container) (rate(container_cpu_usage_seconds_total{cluster_id=~\"$cluster\", namespace=~\"$namespace\", container=~\"$container\", container!=\"POD\",container!=\"\"}[1h])))\n - \n (sum by (cluster_id,namespace,pod,container) (kube_pod_container_resource_requests{resource=\"cpu\",cluster_id=~\"$cluster\", namespace=~\"$namespace\", container=~\"$container\", container!=\"POD\",container!=\"\"}))\n)\n \n",
"legendFormat": "__auto",
"range": true,
"refId": "A"
},
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"editorMode": "code",
"expr": "-sum by ($aggregation)(\n (sum by (cluster_id,namespace,pod,container) (kube_pod_container_resource_requests{resource=\"cpu\",cluster_id=~\"$cluster\", namespace=~\"$namespace\", container=~\"$container\", container!=\"POD\",container!=\"\"}))\n)",
"hide": true,
"legendFormat": "{{$aggregation}} Request",
"range": true,
"refId": "B"
}
],
"title": "CPU Request-Usage",
"type": "timeseries"
}
],
"schemaVersion": 37,
"style": "dark",
"tags": [
"utilization",
"metrics",
"kubecost"
],
"templating": {
"list": [
{
"current": {
"selected": false,
"text": "default",
"value": "default"
},
"hide": 0,
"includeAll": false,
"multi": false,
"name": "datasource",
"options": [],
"query": "prometheus",
"queryValue": "",
"refresh": 1,
"regex": "",
"skipUrlSync": false,
"type": "datasource"
},
{
"current": {
"selected": true,
"text": "namespace",
"value": "namespace"
},
"hide": 0,
"includeAll": false,
"multi": false,
"name": "aggregation",
"options": [
{
"selected": false,
"text": "cluster_id",
"value": "cluster_id"
},
{
"selected": true,
"text": "namespace",
"value": "namespace"
},
{
"selected": false,
"text": "container",
"value": "container"
}
],
"query": "cluster_id,namespace,container",
"queryValue": "",
"skipUrlSync": false,
"type": "custom"
},
{
"current": {
"selected": true,
"text": "All",
"value": "$__all"
},
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"definition": "label_values(kube_namespace_labels, cluster_id)",
"hide": 0,
"includeAll": true,
"multi": false,
"name": "cluster",
"options": [],
"query": {
"query": "label_values(kube_namespace_labels, cluster_id)",
"refId": "StandardVariableQuery"
},
"refresh": 2,
"regex": "",
"skipUrlSync": false,
"sort": 5,
"type": "query"
},
{
"current": {
"selected": true,
"text": "kubecost",
"value": "kubecost"
},
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"definition": "label_values(kube_namespace_labels{cluster_id=~\"$cluster\"}, namespace) ",
"hide": 0,
"includeAll": true,
"multi": false,
"name": "namespace",
"options": [],
"query": {
"query": "label_values(kube_namespace_labels{cluster_id=~\"$cluster\"}, namespace) ",
"refId": "StandardVariableQuery"
},
"refresh": 2,
"regex": "",
"skipUrlSync": false,
"sort": 5,
"type": "query"
},
{
"current": {
"selected": false,
"text": "All",
"value": "$__all"
},
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"definition": "label_values(container_memory_working_set_bytes{cluster_id=~\"$cluster\",namespace=~\"$namespace\", container!=\"POD\"}, container) ",
"hide": 0,
"includeAll": true,
"multi": false,
"name": "container",
"options": [],
"query": {
"query": "label_values(container_memory_working_set_bytes{cluster_id=~\"$cluster\",namespace=~\"$namespace\", container!=\"POD\"}, container) ",
"refId": "StandardVariableQuery"
},
"refresh": 2,
"regex": "",
"skipUrlSync": false,
"sort": 5,
"type": "query"
}
]
},
"time": {
"from": "now-6h",
"to": "now"
},
"timepicker": {},
"timezone": "",
"title": "Kubernetes Resource Efficiency",
"uid": "kubernetes-resource-efficiency",
"version": 1,
"weekStart": ""
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,408 @@
{
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": {
"type": "grafana",
"uid": "-- Grafana --"
},
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"type": "dashboard"
}
]
},
"description": "Most used metrics when troubleshooting applications",
"editable": true,
"fiscalYearStartMonth": 0,
"graphTooltip": 0,
"id": 14,
"links": [],
"liveNow": false,
"panels": [
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "bars",
"fillOpacity": 80,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "binBps"
},
"overrides": []
},
"gridPos": {
"h": 10,
"w": 24,
"x": 0,
"y": 0
},
"id": 11,
"options": {
"legend": {
"calcs": [],
"displayMode": "table",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"disableTextWrap": false,
"editorMode": "code",
"expr": "sum(\n rate(kubecost_pod_network_ingress_bytes_total\n {namespace=~\"$namespace\", pod_name=~\"$pod\",service!=\"\",service=~\"$service\"}\n [1h]\n )\n) \nby (namespace,service) ",
"fullMetaSearch": false,
"includeNullMetadata": true,
"instant": false,
"interval": "1h",
"legendFormat": "{{namespace}}/{{service}}",
"range": true,
"refId": "A",
"useBackend": false
},
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"disableTextWrap": false,
"editorMode": "code",
"expr": "- sum(\n rate(kubecost_pod_network_egress_bytes_total\n {namespace=~\"$namespace\", pod_name=~\"$pod\",service!=\"\",service=~\"$service\"}\n [1h]\n )\n) \nby(namespace, service) ",
"fullMetaSearch": false,
"hide": false,
"includeNullMetadata": true,
"instant": false,
"interval": "1h",
"legendFormat": "{{namespace}}/{{service}}",
"range": true,
"refId": "B",
"useBackend": false
}
],
"title": "Kubecost Network Cloud Service by Namespace (egress is negative)",
"type": "timeseries"
},
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "bars",
"fillOpacity": 80,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "binBps"
},
"overrides": []
},
"gridPos": {
"h": 14,
"w": 24,
"x": 0,
"y": 10
},
"id": 10,
"options": {
"legend": {
"calcs": [],
"displayMode": "table",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"disableTextWrap": false,
"editorMode": "code",
"expr": "sum(topk(5,\n rate(kubecost_pod_network_ingress_bytes_total\n {namespace=~\"$namespace\", pod_name=~\"$pod\",service!=\"\",service=~\"$service\"}\n [1h]\n )\n) )\nby(namespace, pod_name,service) ",
"fullMetaSearch": false,
"includeNullMetadata": true,
"instant": false,
"interval": "1h",
"legendFormat": "{{namespace}}/{{pod_name}}/{{service}}",
"range": true,
"refId": "A",
"useBackend": false
},
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"disableTextWrap": false,
"editorMode": "code",
"expr": "- sum(topk(5,\n rate(kubecost_pod_network_egress_bytes_total\n {namespace=~\"$namespace\", pod_name=~\"$pod\",service!=\"\",service=~\"$service\"}\n [1h]\n )\n) )\nby(namespace, pod_name,service) ",
"fullMetaSearch": false,
"hide": false,
"includeNullMetadata": true,
"instant": false,
"interval": "1h",
"legendFormat": "{{namespace}}/{{pod_name}}/{{service}}",
"range": true,
"refId": "B",
"useBackend": false
}
],
"title": "Kubecost Network Cloud Service by Pod (egress is negative)",
"type": "timeseries"
}
],
"refresh": "5s",
"schemaVersion": 39,
"tags": [
"utilization",
"metrics",
"kubecost"
],
"templating": {
"list": [
{
"current": {
"selected": false,
"text": "Prometheus",
"value": "PBFA97CFB590B2093"
},
"hide": 0,
"includeAll": false,
"multi": false,
"name": "datasource",
"options": [],
"query": "prometheus",
"queryValue": "",
"refresh": 1,
"regex": "",
"skipUrlSync": false,
"type": "datasource"
},
{
"current": {
"selected": false,
"text": "All",
"value": "$__all"
},
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"definition": "label_values(kube_namespace_labels,namespace)",
"hide": 0,
"includeAll": true,
"multi": false,
"name": "namespace",
"options": [],
"query": {
"qryType": 1,
"query": "label_values(kube_namespace_labels,namespace)",
"refId": "PrometheusVariableQueryEditor-VariableQuery"
},
"refresh": 1,
"regex": "",
"skipUrlSync": false,
"sort": 5,
"type": "query"
},
{
"current": {
"selected": false,
"text": "All",
"value": "$__all"
},
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"definition": "label_values(kube_pod_owner{namespace=~\"$namespace\"},pod)",
"hide": 0,
"includeAll": true,
"multi": false,
"name": "pod",
"options": [],
"query": {
"qryType": 1,
"query": "label_values(kube_pod_owner{namespace=~\"$namespace\"},pod)",
"refId": "PrometheusVariableQueryEditor-VariableQuery"
},
"refresh": 1,
"regex": "",
"skipUrlSync": false,
"sort": 5,
"type": "query"
},
{
"current": {
"selected": false,
"text": "All",
"value": "$__all"
},
"datasource": {
"type": "prometheus",
"uid": "PBFA97CFB590B2093"
},
"definition": "label_values(kube_pod_container_status_running{namespace=\"$namespace\"},container)",
"hide": 0,
"includeAll": true,
"multi": false,
"name": "container",
"options": [],
"query": {
"qryType": 1,
"query": "label_values(kube_pod_container_status_running{namespace=\"$namespace\"},container)",
"refId": "PrometheusVariableQueryEditor-VariableQuery"
},
"refresh": 1,
"regex": "",
"skipUrlSync": false,
"sort": 5,
"type": "query"
},
{
"current": {
"selected": true,
"text": "All",
"value": "$__all"
},
"definition": "label_values(kubecost_pod_network_egress_bytes_total{namespace=~\"$namespace\"},service)",
"hide": 0,
"includeAll": true,
"multi": false,
"name": "service",
"options": [],
"query": {
"qryType": 1,
"query": "label_values(kubecost_pod_network_egress_bytes_total{namespace=~\"$namespace\"},service)",
"refId": "PrometheusVariableQueryEditor-VariableQuery"
},
"refresh": 1,
"regex": "",
"skipUrlSync": false,
"sort": 5,
"type": "query"
}
]
},
"time": {
"from": "now-2d",
"to": "now"
},
"timepicker": {},
"timezone": "",
"title": "Kubecost Network Cloud Service Metrics",
"uid": "kubecost-network-cloud-services",
"version": 1,
"weekStart": ""
}

View File

@ -0,0 +1,672 @@
{
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": {
"type": "grafana",
"uid": "-- Grafana --"
},
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"target": {
"limit": 100,
"matchAny": false,
"tags": [],
"type": "dashboard"
},
"type": "dashboard"
}
]
},
"description": "https://docs.kubecost.com/install-and-configure/advanced-configuration/network-costs-configuration",
"editable": true,
"fiscalYearStartMonth": 0,
"graphTooltip": 0,
"id": 2,
"links": [],
"liveNow": false,
"panels": [
{
"collapsed": false,
"gridPos": {
"h": 1,
"w": 24,
"x": 0,
"y": 0
},
"id": 12,
"panels": [],
"title": "Network Data Transfers (negative is egress data)",
"type": "row"
},
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "bars",
"fillOpacity": 100,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "bytes"
},
"overrides": []
},
"gridPos": {
"h": 14,
"w": 11,
"x": 0,
"y": 1
},
"id": 10,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"editorMode": "code",
"expr": "sum(increase(kubecost_pod_network_ingress_bytes_total\n {namespace=~\"$namespace\", cluster_id=~\"$cluster\", pod_name=~\"$pod_name\", service=~\"$service\"}\n [1h]\n ))\nby($aggregation) ",
"interval": "1h",
"legendFormat": "__auto",
"range": true,
"refId": "A"
},
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"editorMode": "code",
"expr": "-sum(increase(kubecost_pod_network_egress_bytes_total\n {namespace=~\"$namespace\", cluster_id=~\"$cluster\", pod_name=~\"$pod_name\", service=~\"$service\"}\n [1h]\n ))\nby($aggregation) ",
"hide": false,
"interval": "1h",
"legendFormat": "__auto",
"range": true,
"refId": "B"
}
],
"title": "All Data",
"type": "timeseries"
},
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "bars",
"fillOpacity": 100,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "bytes"
},
"overrides": []
},
"gridPos": {
"h": 14,
"w": 13,
"x": 11,
"y": 1
},
"id": 2,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"editorMode": "code",
"expr": "sum(increase(kubecost_pod_network_ingress_bytes_total\n {internet=\"true\", namespace=~\"$namespace\", cluster_id=~\"$cluster\", pod_name=~\"$pod_name\", service=~\"$service\"}\n [1h]\n))\nby($aggregation) ",
"hide": false,
"interval": "1h",
"legendFormat": "__auto",
"range": true,
"refId": "A"
},
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"editorMode": "code",
"expr": "- sum(increase(kubecost_pod_network_egress_bytes_total\n {internet=\"true\", namespace=~\"$namespace\", cluster_id=~\"$cluster\", pod_name=~\"$pod_name\", service=~\"$service\"}\n [1h]))\nby($aggregation) ",
"hide": false,
"interval": "1h",
"legendFormat": "__auto",
"range": true,
"refId": "B"
}
],
"title": "Internet Data",
"type": "timeseries"
},
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"description": "Cross region and cross zone subnets must be defined via the configMap. \nSee: \n<https://docs.kubecost.com/install-and-configure/advanced-configuration/network-costs-configuration#overriding-traffic-classifications>",
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "bars",
"fillOpacity": 100,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"decimals": 2,
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "bytes"
},
"overrides": []
},
"gridPos": {
"h": 14,
"w": 11,
"x": 0,
"y": 15
},
"id": 9,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"editorMode": "code",
"expr": "sum(increase(kubecost_pod_network_ingress_bytes_total\n {internet=\"false\",namespace=~\"$namespace\",cluster_id=~\"$cluster\",pod_name=~\"$pod_name\", sameRegion=\"false\",sameZone=\"false\", service=~\"$service\"}\n [1h]))\nby($aggregation)",
"interval": "1h",
"legendFormat": "__auto",
"range": true,
"refId": "A"
},
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"editorMode": "code",
"expr": "- sum(increase(kubecost_pod_network_egress_bytes_total\n {internet=\"false\", namespace=~\"$namespace\",cluster_id=~\"$cluster\",pod_name=~\"$pod_name\",sameRegion=\"false\", sameZone=\"false\", service=~\"$service\"}\n [1h]))\nby($aggregation) ",
"hide": false,
"interval": "1h",
"legendFormat": "__auto",
"range": true,
"refId": "B"
}
],
"title": "Cross Region Data",
"type": "timeseries"
},
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"description": "Cross region and cross zone subnets must be defined via the configMap. \nSee: \n<https://docs.kubecost.com/install-and-configure/advanced-configuration/network-costs-configuration#overriding-traffic-classifications>",
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "bars",
"fillOpacity": 100,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"decimals": 2,
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "bytes"
},
"overrides": []
},
"gridPos": {
"h": 14,
"w": 13,
"x": 11,
"y": 15
},
"id": 8,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"editorMode": "code",
"expr": "sum(increase(kubecost_pod_network_ingress_bytes_total\n {internet=\"false\", namespace=~\"$namespace\", cluster_id=~\"$cluster\", pod_name=~\"$pod_name\", sameRegion=\"true\", sameZone=\"false\", service=~\"$service\"}\n [1h]))\nby($aggregation)",
"interval": "1h",
"legendFormat": "__auto",
"range": true,
"refId": "A"
},
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"editorMode": "code",
"expr": "- sum(increase(kubecost_pod_network_egress_bytes_total\n {internet=\"false\", namespace=~\"$namespace\", cluster_id=~\"$cluster\", pod_name=~\"$pod_name\", sameRegion=\"true\", sameZone=\"false\", service=~\"$service\"}\n [1h]))\nby($aggregation)",
"hide": false,
"interval": "1h",
"legendFormat": "__auto",
"range": true,
"refId": "B"
}
],
"title": "Cross Zone Data",
"type": "timeseries"
}
],
"refresh": "",
"revision": 1,
"schemaVersion": 39,
"tags": [
"utilization",
"metrics",
"kubecost"
],
"templating": {
"list": [
{
"current": {
"selected": false,
"text": "Prometheus",
"value": "PBFA97CFB590B2093"
},
"hide": 0,
"includeAll": false,
"multi": false,
"name": "datasource",
"options": [],
"query": "prometheus",
"queryValue": "",
"refresh": 1,
"regex": "",
"skipUrlSync": false,
"type": "datasource"
},
{
"current": {
"selected": false,
"text": "namespace",
"value": "namespace"
},
"hide": 0,
"includeAll": false,
"multi": false,
"name": "aggregation",
"options": [
{
"selected": false,
"text": "cluster_id",
"value": "cluster_id"
},
{
"selected": true,
"text": "namespace",
"value": "namespace"
},
{
"selected": false,
"text": "pod_name",
"value": "pod_name"
}
],
"query": "cluster_id, namespace, pod_name",
"queryValue": "",
"skipUrlSync": false,
"type": "custom"
},
{
"current": {
"selected": false,
"text": "All",
"value": "$__all"
},
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"definition": "label_values(cluster_id)",
"hide": 0,
"includeAll": true,
"multi": false,
"name": "cluster",
"options": [],
"query": {
"query": "label_values(cluster_id)",
"refId": "StandardVariableQuery"
},
"refresh": 1,
"regex": "",
"skipUrlSync": false,
"sort": 5,
"type": "query"
},
{
"current": {
"selected": true,
"text": "kubecost",
"value": "kubecost"
},
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"definition": "label_values(kube_namespace_labels{cluster_id=~\"$cluster\"}, namespace) ",
"hide": 0,
"includeAll": true,
"multi": false,
"name": "namespace",
"options": [],
"query": {
"query": "label_values(kube_namespace_labels{cluster_id=~\"$cluster\"}, namespace) ",
"refId": "StandardVariableQuery"
},
"refresh": 2,
"regex": "",
"skipUrlSync": false,
"sort": 5,
"type": "query"
},
{
"current": {
"selected": false,
"text": "All",
"value": "$__all"
},
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"definition": "label_values(kubecost_pod_network_egress_bytes_total{cluster_id=~\"$cluster\", namespace=~\"$namespace\"},pod_name)",
"hide": 0,
"includeAll": true,
"multi": false,
"name": "pod_name",
"options": [],
"query": {
"qryType": 1,
"query": "label_values(kubecost_pod_network_egress_bytes_total{cluster_id=~\"$cluster\", namespace=~\"$namespace\"},pod_name)",
"refId": "PrometheusVariableQueryEditor-VariableQuery"
},
"refresh": 2,
"regex": "",
"skipUrlSync": false,
"sort": 5,
"type": "query"
},
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"filters": [],
"hide": 0,
"name": "filter",
"skipUrlSync": false,
"type": "adhoc"
},
{
"current": {
"selected": false,
"text": "All",
"value": "$__all"
},
"definition": "label_values(kubecost_pod_network_egress_bytes_total{namespace=~\"$namespace\"},service)",
"hide": 0,
"includeAll": true,
"multi": false,
"name": "service",
"options": [],
"query": {
"qryType": 1,
"query": "label_values(kubecost_pod_network_egress_bytes_total{namespace=~\"$namespace\"},service)",
"refId": "PrometheusVariableQueryEditor-VariableQuery"
},
"refresh": 1,
"regex": "",
"skipUrlSync": false,
"sort": 5,
"type": "query"
}
]
},
"time": {
"from": "now-7d",
"to": "now"
},
"timepicker": {},
"timezone": "",
"title": "Kubecost Network Costs Metrics",
"uid": "kubecost-networkCosts-metrics",
"version": 2,
"weekStart": ""
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,788 @@
{
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": {
"type": "datasource",
"uid": "grafana"
},
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"target": {
"limit": 100,
"matchAny": false,
"tags": [],
"type": "dashboard"
},
"type": "dashboard"
}
]
},
"description": "",
"editable": true,
"fiscalYearStartMonth": 0,
"gnetId": 9063,
"graphTooltip": 0,
"id": 4,
"links": [],
"liveNow": false,
"panels": [
{
"datasource": {
"type": "prometheus",
"uid": "Thanos"
},
"description": "Maximum CPU Core Usage vs avg Requested",
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 2,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": 3600000,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"min": 0,
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "none",
"unitScale": true
},
"overrides": []
},
"gridPos": {
"h": 7,
"w": 12,
"x": 0,
"y": 0
},
"id": 94,
"links": [],
"options": {
"legend": {
"calcs": [
"max"
],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "multi",
"sort": "desc"
}
},
"pluginVersion": "9.4.7",
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "Thanos"
},
"editorMode": "code",
"expr": "max(irate(container_cpu_usage_seconds_total\r\n {cluster_id=\"$cluster\",namespace=~\"$namespace\",pod=~\"$pod\", container=~\"$container\", container!=\"POD\",container!=\"\"}\r\n [$__rate_interval])) \r\n by (cluster_id, namespace, pod, container)",
"format": "time_series",
"hide": false,
"instant": false,
"interval": "",
"intervalFactor": 1,
"legendFormat": "{{cluster_id}} {{namespace}}/{{pod}}/{{container}} (usage max)",
"metric": "container_cpu",
"refId": "A",
"step": 10
},
{
"datasource": {
"type": "prometheus",
"uid": "Thanos"
},
"editorMode": "code",
"exemplar": true,
"expr": "avg(kube_pod_container_resource_requests\r\n {cluster_id=\"$cluster\",resource=\"cpu\",unit=\"core\",namespace=~\"$namespace\",pod=~\"$pod\",container=~\"$container\",container!=\"POD\"}\r\n ) \r\nby (cluster_id,namespace,pod,container)",
"legendFormat": "{{cluster_id}} {{namespace}}/{{pod}}/{{container}} (requested)",
"range": true,
"refId": "B"
}
],
"timeFrom": "",
"title": "CPU Core Usage vs Requested",
"type": "timeseries"
},
{
"datasource": {
"type": "prometheus",
"uid": "Thanos"
},
"description": "Max memory used vs avg requested",
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 2,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": 3600000,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"min": 0,
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "bytes",
"unitScale": true
},
"overrides": []
},
"gridPos": {
"h": 7,
"w": 12,
"x": 12,
"y": 0
},
"id": 96,
"links": [],
"options": {
"legend": {
"calcs": [
"max"
],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "multi",
"sort": "asc"
}
},
"pluginVersion": "9.4.7",
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "Thanos"
},
"editorMode": "code",
"expr": "max(max_over_time(container_memory_working_set_bytes\r\n {namespace=~\"$namespace\",pod=~\"$pod\",cluster_id=\"$cluster\",container=~\"$container\",container!=\"POD\",container!=\"\"}\r\n [$__rate_interval])) \r\nby (cluster_id,namespace,pod,container)",
"format": "time_series",
"hide": false,
"instant": false,
"interval": "",
"intervalFactor": 1,
"legendFormat": "{{cluster_id}} {{namespace}}/{{pod}}/{{container}} (usage max)",
"metric": "container_cpu",
"refId": "MEMORY_USAGE",
"step": 10
},
{
"datasource": {
"type": "prometheus",
"uid": "Thanos"
},
"editorMode": "code",
"expr": "avg(kube_pod_container_resource_requests\n {resource=\"memory\",unit=\"byte\",cluster_id=\"$cluster\",namespace=~\"$namespace\",pod=~\"$pod\", container=~\"$container\",container!=\"POD\"}\n )\nby (cluster_id,namespace,pod,container)",
"format": "time_series",
"hide": false,
"instant": false,
"intervalFactor": 1,
"legendFormat": "{{cluster_id}} {{namespace}}/{{pod}}/{{container}} (requested)",
"refId": "MEMORY_REQUESTED"
}
],
"timeFrom": "",
"title": "Memory Usage vs Requested",
"type": "timeseries"
},
{
"datasource": {
"type": "prometheus",
"uid": "Thanos"
},
"description": "Network traffic by pod",
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 10,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 2,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": 3600000,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "Bps",
"unitScale": true
},
"overrides": []
},
"gridPos": {
"h": 7,
"w": 12,
"x": 0,
"y": 7
},
"id": 95,
"links": [],
"options": {
"legend": {
"calcs": [
"mean"
],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "multi",
"sort": "desc"
}
},
"pluginVersion": "9.4.7",
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "Thanos"
},
"editorMode": "code",
"expr": "sum(irate(container_network_receive_bytes_total\n {cluster_id=~\"$cluster\",namespace=~\"$namespace\",pod=~\"$pod\"}\n [$__rate_interval])) \nby (cluster_id, namespace, pod)",
"format": "time_series",
"hide": false,
"instant": false,
"interval": "",
"intervalFactor": 1,
"legendFormat": "{{cluster_id}} {{namespace}}/{{pod}}<- in",
"metric": "container_cpu",
"refId": "A",
"step": 10
},
{
"datasource": {
"type": "prometheus",
"uid": "Thanos"
},
"editorMode": "code",
"expr": "- sum(irate(container_network_transmit_bytes_total\n {cluster_id=\"$cluster\",namespace=~\"$namespace\",pod=~\"$pod\"}\n [$__rate_interval])) \nby (cluster_id, namespace, pod)",
"format": "time_series",
"hide": false,
"instant": false,
"interval": "",
"intervalFactor": 1,
"legendFormat": "{{cluster_id}} {{namespace}}/{{pod}}-> out",
"refId": "B"
}
],
"timeFrom": "",
"title": "Network IO",
"type": "timeseries"
},
{
"datasource": {
"type": "prometheus",
"uid": "Thanos"
},
"description": "Disk read writes",
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 10,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 2,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": 3600000,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "Bps",
"unitScale": true
},
"overrides": []
},
"gridPos": {
"h": 7,
"w": 12,
"x": 12,
"y": 7
},
"id": 97,
"links": [],
"options": {
"legend": {
"calcs": [
"mean"
],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "multi",
"sort": "desc"
}
},
"pluginVersion": "9.4.7",
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "Thanos"
},
"editorMode": "code",
"expr": "sum(irate(container_fs_writes_bytes_total\r\n {cluster_id=\"$cluster\",namespace=~\"$namespace\",container!=\"POD\",pod!=\"\",pod=~\"$pod\",container=~\"$container\"}\r\n [$__rate_interval])) \r\nby (cluster_id,namespace,pod,container)",
"format": "time_series",
"hide": false,
"instant": false,
"interval": "",
"intervalFactor": 1,
"legendFormat": "{{cluster_id}} {{pod}}/{{container}}<- write",
"metric": "container_cpu",
"refId": "A",
"step": 10
},
{
"datasource": {
"type": "prometheus",
"uid": "Thanos"
},
"editorMode": "code",
"expr": "- sum(irate(container_fs_reads_bytes_total\r\n {cluster_id=\"$cluster\",namespace=~\"$namespace\",container!=\"POD\",pod!=\"\",pod=~\"$pod\",container=~\"$container\"}\r\n [$__rate_interval])) \r\nby (cluster_id,namespace,pod,container)",
"format": "time_series",
"hide": false,
"instant": false,
"interval": "",
"intervalFactor": 1,
"legendFormat": "{{cluster_id}} {{pod}}/{{container}}-> read",
"refId": "B"
}
],
"timeFrom": "",
"title": "Disk IO",
"type": "timeseries"
},
{
"datasource": {
"type": "prometheus",
"uid": "Thanos"
},
"description": "This graph shows the % of periods where a pod is being throttled. Values range from 0-100",
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 2,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": 1800000,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"min": 0,
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "percent",
"unitScale": true
},
"overrides": []
},
"gridPos": {
"h": 7,
"w": 12,
"x": 0,
"y": 14
},
"id": 99,
"links": [],
"options": {
"legend": {
"calcs": [
"mean"
],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "multi",
"sort": "desc"
}
},
"pluginVersion": "9.4.7",
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "Thanos"
},
"editorMode": "code",
"expr": "100\n * sum by(cluster_id, namespace, pod, container) (increase(container_cpu_cfs_throttled_periods_total{container!=\"\",cluster_id=\"$cluster\", namespace=~\"$namespace\", pod=~\"$pod\", container=~\"$container\", container!=\"POD\"}[$__rate_interval]))\n / sum by(cluster_id,namespace,pod,container) (increase(container_cpu_cfs_periods_total{container!=\"\",cluster_id=\"$cluster\",namespace=~\"$namespace\",pod=~\"$pod\",container=~\"$container\",container!=\"POD\"}[$__rate_interval]))",
"format": "time_series",
"instant": false,
"interval": "",
"intervalFactor": 1,
"legendFormat": "",
"refId": "B"
}
],
"timeFrom": "",
"title": "CPU throttle percent",
"type": "timeseries"
}
],
"refresh": "",
"revision": 1,
"schemaVersion": 39,
"tags": [
"utilization",
"metrics",
"kubecost"
],
"templating": {
"list": [
{
"current": {
"selected": false,
"text": "CostManagement",
"value": "CostManagement"
},
"datasource": {
"type": "prometheus",
"uid": "Thanos"
},
"definition": "label_values(cluster_id)",
"hide": 0,
"includeAll": false,
"multi": false,
"name": "cluster",
"options": [],
"query": {
"query": "label_values(cluster_id)",
"refId": "StandardVariableQuery"
},
"refresh": 2,
"regex": "",
"skipUrlSync": false,
"sort": 5,
"type": "query"
},
{
"current": {
"selected": false,
"text": "kubecost",
"value": "kubecost"
},
"datasource": {
"type": "prometheus",
"uid": "Thanos"
},
"definition": "label_values(kube_namespace_labels{cluster_id=\"$cluster\"}, namespace) ",
"hide": 0,
"includeAll": true,
"label": "",
"multi": false,
"name": "namespace",
"options": [],
"query": {
"query": "label_values(kube_namespace_labels{cluster_id=\"$cluster\"}, namespace) ",
"refId": "StandardVariableQuery"
},
"refresh": 2,
"regex": "",
"skipUrlSync": false,
"sort": 5,
"tagValuesQuery": "",
"tagsQuery": "",
"type": "query",
"useTags": false
},
{
"current": {
"selected": false,
"text": "All",
"value": "$__all"
},
"datasource": {
"type": "prometheus",
"uid": "Thanos"
},
"definition": "label_values(kube_pod_labels{cluster_id=\"$cluster\",namespace=~\"$namespace\"}, pod) ",
"hide": 0,
"includeAll": true,
"label": "pod",
"multi": false,
"name": "pod",
"options": [],
"query": {
"query": "label_values(kube_pod_labels{cluster_id=\"$cluster\",namespace=~\"$namespace\"}, pod) ",
"refId": "StandardVariableQuery"
},
"refresh": 2,
"regex": "",
"skipUrlSync": false,
"sort": 1,
"tagValuesQuery": "",
"tagsQuery": "",
"type": "query",
"useTags": false
},
{
"current": {
"selected": false,
"text": "All",
"value": "$__all"
},
"datasource": {
"type": "prometheus",
"uid": "Thanos"
},
"definition": "label_values(container_memory_working_set_bytes{cluster_id=\"$cluster\",namespace=~\"$namespace\",pod=~\"$pod\", container!=\"POD\"}, container) ",
"hide": 0,
"includeAll": true,
"multi": false,
"name": "container",
"options": [],
"query": {
"query": "label_values(container_memory_working_set_bytes{cluster_id=\"$cluster\",namespace=~\"$namespace\",pod=~\"$pod\", container!=\"POD\"}, container) ",
"refId": "StandardVariableQuery"
},
"refresh": 2,
"regex": "",
"skipUrlSync": false,
"sort": 5,
"type": "query"
}
]
},
"time": {
"from": "now-2d",
"to": "now"
},
"timepicker": {
"hidden": false,
"refresh_intervals": [
"10s",
"30s",
"1m",
"5m",
"15m",
"30m",
"1h",
"2h",
"1d"
],
"time_options": [
"5m",
"15m",
"1h",
"6h",
"12h",
"24h",
"2d",
"7d",
"30d"
]
},
"timezone": "browser",
"title": "Pod utilization metrics (multi-cluster)",
"uid": "at-cost-analysis-pod-multicluster",
"version": 2,
"weekStart": ""
}

View File

@ -0,0 +1,757 @@
{
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": {
"type": "datasource",
"uid": "grafana"
},
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"target": {
"limit": 100,
"matchAny": false,
"tags": [],
"type": "dashboard"
},
"type": "dashboard"
}
]
},
"description": "",
"editable": true,
"fiscalYearStartMonth": 0,
"gnetId": 9063,
"graphTooltip": 0,
"id": 11,
"links": [],
"liveNow": false,
"panels": [
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"description": "Maximum CPU Core Usage vs Requested",
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"lineInterpolation": "linear",
"lineWidth": 2,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": 3600000,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"min": 0,
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "none"
},
"overrides": []
},
"gridPos": {
"h": 7,
"w": 12,
"x": 0,
"y": 0
},
"id": 94,
"links": [],
"options": {
"legend": {
"calcs": [
"max"
],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "multi",
"sort": "desc"
}
},
"pluginVersion": "9.4.7",
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"editorMode": "code",
"expr": "max(irate(\r\n container_cpu_usage_seconds_total\r\n {namespace=~\"$namespace\",pod=~\"$pod\",container=~\"$container\",container!=\"POD\",container!=\"\"}\r\n [$__rate_interval])) \r\n by (cluster_id, namespace, pod, container)",
"format": "time_series",
"hide": false,
"instant": false,
"interval": "",
"intervalFactor": 1,
"legendFormat": "{{cluster_id}} {{pod}}/{{container}} (usage max)",
"metric": "container_cpu",
"refId": "A",
"step": 10
},
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"editorMode": "code",
"exemplar": true,
"expr": "avg(kube_pod_container_resource_requests\r\n {resource=\"cpu\",unit=\"core\",namespace=~\"$namespace\",pod=~\"$pod\",container=~\"$container\",container!=\"POD\"}\r\n ) \r\nby (cluster_id, namespace, pod, container)",
"legendFormat": "{{cluster_id}} {{pod}}/{{container}} (avg requested)",
"range": true,
"refId": "B"
}
],
"timeFrom": "",
"title": "CPU Core Usage vs Requested",
"type": "timeseries"
},
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"description": "Max Memory usage vs avg requested",
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"lineInterpolation": "linear",
"lineWidth": 2,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": 3600000,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"min": 0,
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "bytes"
},
"overrides": []
},
"gridPos": {
"h": 7,
"w": 12,
"x": 12,
"y": 0
},
"id": 96,
"links": [],
"options": {
"legend": {
"calcs": [
"max"
],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "multi",
"sort": "asc"
}
},
"pluginVersion": "9.4.7",
"targets": [
{
"datasource": {
"uid": "${datasource}"
},
"editorMode": "code",
"expr": "max(max_over_time(\r\n container_memory_working_set_bytes\r\n {namespace=~\"$namespace\",pod=~\"$pod\",container=~\"$container\",container!=\"POD\",container!=\"\"}\r\n [$__rate_interval])) \r\nby (cluster_id,namespace,pod,container)",
"format": "time_series",
"hide": false,
"instant": false,
"interval": "",
"intervalFactor": 1,
"legendFormat": "{{cluster_id}} {{pod}}/{{container}} (usage max)",
"metric": "container_cpu",
"refId": "A",
"step": 10
},
{
"datasource": {
"uid": "${datasource}"
},
"editorMode": "code",
"expr": "avg(\n kube_pod_container_resource_requests\n {resource=\"memory\",unit=\"byte\",namespace=~\"$namespace\",pod=~\"$pod\",container=~\"$container\", container!=\"POD\"}\n )\nby (cluster_id,namespace,pod,container)",
"format": "time_series",
"hide": false,
"instant": false,
"intervalFactor": 1,
"legendFormat": "{{cluster_id}} {{pod}}/{{container}} (avg requested)",
"refId": "B"
}
],
"timeFrom": "",
"title": "Memory Usage vs Requested",
"type": "timeseries"
},
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"description": "Network traffic by pod",
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 10,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"lineInterpolation": "linear",
"lineWidth": 2,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": 3600000,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "Bps"
},
"overrides": []
},
"gridPos": {
"h": 7,
"w": 12,
"x": 0,
"y": 7
},
"id": 95,
"links": [],
"options": {
"legend": {
"calcs": [
"mean"
],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "multi",
"sort": "desc"
}
},
"pluginVersion": "9.4.7",
"targets": [
{
"datasource": {
"uid": "${datasource}"
},
"editorMode": "code",
"expr": "sum(irate(container_network_receive_bytes_total\n {namespace=~\"$namespace\",pod=~\"$pod\"}\n [$__rate_interval])) \nby (cluster_id, namespace, pod)",
"format": "time_series",
"hide": false,
"instant": false,
"interval": "",
"intervalFactor": 1,
"legendFormat": "{{cluster_id}} {{namespace}}/{{pod}}<- in",
"metric": "container_cpu",
"refId": "A",
"step": 10
},
{
"datasource": {
"uid": "${datasource}"
},
"editorMode": "code",
"expr": "- sum(irate(container_network_transmit_bytes_total\n {namespace=~\"$namespace\",pod=~\"$pod\"}\n [$__rate_interval])) \nby (cluster_id, namespace, pod)",
"format": "time_series",
"hide": false,
"instant": false,
"interval": "",
"intervalFactor": 1,
"legendFormat": "{{cluster_id}} {{namespace}}/{{pod}}-> out",
"refId": "B"
}
],
"timeFrom": "",
"title": "Network IO",
"type": "timeseries"
},
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"description": "Disk read writes",
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 10,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"lineInterpolation": "linear",
"lineWidth": 2,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": 3600000,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "Bps"
},
"overrides": []
},
"gridPos": {
"h": 7,
"w": 12,
"x": 12,
"y": 7
},
"id": 97,
"links": [],
"options": {
"legend": {
"calcs": [
"mean"
],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "multi",
"sort": "desc"
}
},
"pluginVersion": "9.4.7",
"targets": [
{
"datasource": {
"uid": "${datasource}"
},
"editorMode": "code",
"expr": "sum(irate(container_fs_writes_bytes_total\r\n {container!=\"POD\",pod!=\"\",pod=~\"$pod\",container=~\"$container\"}\r\n [$__rate_interval])) \r\nby (cluster_id,namespace,pod,container)",
"format": "time_series",
"hide": false,
"instant": false,
"interval": "",
"intervalFactor": 1,
"legendFormat": "{{cluster_id}} {{pod}}/{{container}}<- write",
"metric": "container_cpu",
"refId": "A",
"step": 10
},
{
"datasource": {
"uid": "${datasource}"
},
"editorMode": "code",
"expr": "- sum(irate(container_fs_reads_bytes_total\r\n {container!=\"POD\",pod!=\"\",pod=~\"$pod\",container=~\"$container\"}\r\n [$__rate_interval])) \r\nby (cluster_id,namespace,pod,container)",
"format": "time_series",
"hide": false,
"instant": false,
"interval": "",
"intervalFactor": 1,
"legendFormat": "{{cluster_id}} {{pod}}/{{container}}-> read",
"refId": "B"
}
],
"timeFrom": "",
"title": "Disk IO",
"type": "timeseries"
},
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"description": "This graph shows the % of periods where a pod is being throttled. Values range from 0-100",
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"lineInterpolation": "linear",
"lineWidth": 2,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": 1800000,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"min": 0,
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "percent"
},
"overrides": []
},
"gridPos": {
"h": 7,
"w": 12,
"x": 0,
"y": 14
},
"id": 99,
"links": [],
"options": {
"legend": {
"calcs": [
"mean"
],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "multi",
"sort": "desc"
}
},
"pluginVersion": "9.4.7",
"targets": [
{
"datasource": {
"uid": "${datasource}"
},
"editorMode": "code",
"expr": "100\n * sum by(cluster_id, namespace, pod, container) (increase(container_cpu_cfs_throttled_periods_total{container!=\"\", namespace=~\"$namespace\", pod=~\"$pod\", container=~\"$container\", container!=\"POD\"}[$__rate_interval]))\n / sum by(cluster_id, namespace, pod, container) (increase(container_cpu_cfs_periods_total{container!=\"\", namespace=~\"$namespace\", pod=~\"$pod\", container=~\"$container\", container!=\"POD\"}[$__rate_interval]))",
"format": "time_series",
"instant": false,
"interval": "",
"intervalFactor": 1,
"legendFormat": "__auto",
"refId": "B"
}
],
"timeFrom": "",
"title": "CPU throttle percent",
"type": "timeseries"
}
],
"refresh": "",
"revision": 1,
"schemaVersion": 38,
"style": "dark",
"tags": [
"kubecost",
"utilization",
"metrics"
],
"templating": {
"list": [
{
"current": {
"selected": false,
"text": "Prometheus",
"value": "Prometheus"
},
"hide": 0,
"includeAll": false,
"multi": false,
"name": "datasource",
"options": [],
"query": "prometheus",
"queryValue": "",
"refresh": 1,
"regex": "",
"skipUrlSync": false,
"type": "datasource"
},
{
"current": {
"selected": false,
"text": "All",
"value": "$__all"
},
"datasource": {
"uid": "${datasource}"
},
"definition": "label_values(kube_namespace_labels, namespace) ",
"hide": 0,
"includeAll": true,
"label": "",
"multi": false,
"name": "namespace",
"options": [],
"query": {
"query": "label_values(kube_namespace_labels, namespace) ",
"refId": "StandardVariableQuery"
},
"refresh": 2,
"regex": "",
"skipUrlSync": false,
"sort": 5,
"tagValuesQuery": "",
"tagsQuery": "",
"type": "query",
"useTags": false
},
{
"current": {
"selected": false,
"text": "All",
"value": "$__all"
},
"datasource": {
"uid": "${datasource}"
},
"definition": "label_values(kube_pod_labels{namespace=~\"$namespace\"}, pod) ",
"hide": 0,
"includeAll": true,
"label": "pod",
"multi": false,
"name": "pod",
"options": [],
"query": {
"query": "label_values(kube_pod_labels{namespace=~\"$namespace\"}, pod) ",
"refId": "StandardVariableQuery"
},
"refresh": 2,
"regex": "",
"skipUrlSync": false,
"sort": 1,
"tagValuesQuery": "",
"tagsQuery": "",
"type": "query",
"useTags": false
},
{
"current": {
"selected": false,
"text": "All",
"value": "$__all"
},
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"definition": "label_values(container_memory_working_set_bytes{namespace=~\"$namespace\",pod=~\"$pod\", container!=\"POD\"}, container) ",
"hide": 0,
"includeAll": true,
"multi": false,
"name": "container",
"options": [],
"query": {
"query": "label_values(container_memory_working_set_bytes{namespace=~\"$namespace\",pod=~\"$pod\", container!=\"POD\"}, container) ",
"refId": "StandardVariableQuery"
},
"refresh": 2,
"regex": "",
"skipUrlSync": false,
"sort": 5,
"type": "query"
}
]
},
"time": {
"from": "now-2d",
"to": "now"
},
"timepicker": {
"hidden": false,
"refresh_intervals": [
"10s",
"30s",
"1m",
"5m",
"15m",
"30m",
"1h",
"2h",
"1d"
],
"time_options": [
"5m",
"15m",
"1h",
"6h",
"12h",
"24h",
"2d",
"7d",
"30d"
]
},
"timezone": "browser",
"title": "Pod utilization metrics",
"uid": "at-cost-analysis-pod",
"version": 2,
"weekStart": ""
}

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More