diff --git a/cmd/oteld/manager/main.go b/cmd/oteld/manager/main.go index 4858ebe09994..bec05ffac653 100644 --- a/cmd/oteld/manager/main.go +++ b/cmd/oteld/manager/main.go @@ -56,7 +56,7 @@ func init() { viper.SetConfigName("config") viper.SetConfigType("yaml") - viper.SetDefault("OTELD_NAMESPACE", "default") + viper.SetDefault(constant.MonitorNamespaceEnvName, "default") viper.AddConfigPath(fmt.Sprintf("/etc/%s/", constant.OTeldAppName)) viper.AddConfigPath(fmt.Sprintf("$HOME/.%s", constant.OTeldAppName)) viper.AddConfigPath(".") diff --git a/config/crd/bases/monitor.kubeblocks.io_collectordatasources.yaml b/config/crd/bases/monitor.kubeblocks.io_collectordatasources.yaml index 21ef0693109b..266ff831ff87 100644 --- a/config/crd/bases/monitor.kubeblocks.io_collectordatasources.yaml +++ b/config/crd/bases/monitor.kubeblocks.io_collectordatasources.yaml @@ -1,10 +1,11 @@ ---- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.9.0 creationTimestamp: null + labels: + app.kubernetes.io/name: kubeblocks name: collectordatasources.monitor.kubeblocks.io spec: group: monitor.kubeblocks.io @@ -66,16 +67,12 @@ spec: - sidecar - statefulset type: string - name: - description: Name is the name of the data source - type: string type: description: Type is the type of the data source type: string required: - dataSourceList - exporterRef - - name - type type: object status: diff --git a/config/crd/bases/monitor.kubeblocks.io_logsexportersinks.yaml b/config/crd/bases/monitor.kubeblocks.io_logsexportersinks.yaml index a4fa1bb0a44d..3e0af2576ce4 100644 --- a/config/crd/bases/monitor.kubeblocks.io_logsexportersinks.yaml +++ b/config/crd/bases/monitor.kubeblocks.io_logsexportersinks.yaml @@ -1,10 +1,11 @@ ---- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.9.0 creationTimestamp: null + labels: + app.kubernetes.io/name: kubeblocks name: logsexportersinks.monitor.kubeblocks.io spec: group: monitor.kubeblocks.io diff --git a/config/crd/bases/monitor.kubeblocks.io_metricsexportersinks.yaml b/config/crd/bases/monitor.kubeblocks.io_metricsexportersinks.yaml index 73deb2b3d9e8..38d24321a88f 100644 --- a/config/crd/bases/monitor.kubeblocks.io_metricsexportersinks.yaml +++ b/config/crd/bases/monitor.kubeblocks.io_metricsexportersinks.yaml @@ -1,10 +1,11 @@ ---- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.9.0 creationTimestamp: null + labels: + app.kubernetes.io/name: kubeblocks name: metricsexportersinks.monitor.kubeblocks.io spec: group: monitor.kubeblocks.io diff --git a/config/crd/bases/monitor.kubeblocks.io_oteldcollectortemplates.yaml b/config/crd/bases/monitor.kubeblocks.io_oteldcollectortemplates.yaml new file mode 100644 index 000000000000..b488eda74c29 --- /dev/null +++ b/config/crd/bases/monitor.kubeblocks.io_oteldcollectortemplates.yaml @@ -0,0 +1,1903 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.9.0 + creationTimestamp: null + labels: + app.kubernetes.io/name: kubeblocks + name: oteldcollectortemplates.monitor.kubeblocks.io +spec: + group: monitor.kubeblocks.io + names: + kind: OTeldCollectorTemplate + listKind: OTeldCollectorTemplateList + plural: oteldcollectortemplates + singular: oteldcollectortemplate + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: CollectorDataSource is the Schema for the collectordatasources + 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: CollectorDataSourceSpec defines the desired state of CollectorDataSource + properties: + env: + description: ENV vars to set on the OpenTelemetry Collector's Pods. + These can then in certain cases be consumed in the config file for + the Collector. + items: + description: EnvVar represents an environment variable present in + a Container. + properties: + name: + description: Name of the environment variable. Must be a C_IDENTIFIER. + type: string + value: + description: 'Variable references $(VAR_NAME) are expanded using + the previously defined environment variables in the container + and any service environment variables. If a variable cannot + be resolved, the reference in the input string will be unchanged. + Double $$ are reduced to a single $, which allows for escaping + the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will produce the + string literal "$(VAR_NAME)". Escaped references will never + be expanded, regardless of whether the variable exists or + not. Defaults to "".' + type: string + valueFrom: + description: Source for the environment variable's value. Cannot + be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the ConfigMap or its key + must be defined + type: boolean + required: + - key + type: object + fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.labels['''']`, `metadata.annotations['''']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, + status.podIP, status.podIPs.' + properties: + apiVersion: + description: Version of the schema the FieldPath is + written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the specified + API version. + type: string + required: + - fieldPath + type: object + resourceFieldRef: + description: 'Selects a resource of the container: only + resources limits and requests (limits.cpu, limits.memory, + limits.ephemeral-storage, requests.cpu, requests.memory + and requests.ephemeral-storage) are currently supported.' + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the exposed + resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + secretKeyRef: + description: Selects a key of a secret in the pod's namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the Secret or its key must + be defined + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array + image: + description: Image is the image of the oteld + type: string + logLevel: + description: LogsLevel is the level of the oteld collector logs + type: string + metricsPort: + description: MetricsPort is the port of the oteld metrics + type: integer + mode: + description: Mode represents how the OTeld should be deployed (deployment, + daemonset, statefulset or sidecar) + enum: + - daemonset + - deployment + - sidecar + - statefulset + type: string + nodeSelector: + additionalProperties: + type: string + description: NodeSelector to schedule OpenTelemetry Collector pods. + This is only relevant to daemonset, statefulset, and deployment + mode + type: object + podAnnotations: + additionalProperties: + type: string + description: PodAnnotations is the set of annotations that will be + attached to Collector and Target Allocator pods. + type: object + ports: + description: Ports allows a set of ports to be exposed by the underlying + v1.Service. By default, the operator will attempt to infer the required + ports by parsing the .Spec.Config property but this property can + be used to open additional ports that can't be inferred by the operator, + like for custom receivers. + items: + description: ServicePort contains information on service's port. + properties: + appProtocol: + description: The application protocol for this port. This field + follows standard Kubernetes label syntax. Un-prefixed names + are reserved for IANA standard service names (as per RFC-6335 + and https://www.iana.org/assignments/service-names). Non-standard + protocols should use prefixed names such as mycompany.com/my-custom-protocol. + type: string + name: + description: The name of this port within the service. This + must be a DNS_LABEL. All ports within a ServiceSpec must have + unique names. When considering the endpoints for a Service, + this must match the 'name' field in the EndpointPort. Optional + if only one ServicePort is defined on this service. + type: string + nodePort: + description: 'The port on each node on which this service is + exposed when type is NodePort or LoadBalancer. Usually assigned + by the system. If a value is specified, in-range, and not + in use it will be used, otherwise the operation will fail. If + not specified, a port will be allocated if this Service requires + one. If this field is specified when creating a Service which + does not need it, creation will fail. This field will be wiped + when updating a Service to no longer need it (e.g. changing + type from NodePort to ClusterIP). More info: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport' + format: int32 + type: integer + port: + description: The port that will be exposed by this service. + format: int32 + type: integer + protocol: + default: TCP + description: The IP protocol for this port. Supports "TCP", + "UDP", and "SCTP". Default is TCP. + type: string + targetPort: + anyOf: + - type: integer + - type: string + description: 'Number or name of the port to access on the pods + targeted by the service. Number must be in the range 1 to + 65535. Name must be an IANA_SVC_NAME. If this is a string, + it will be looked up as a named port in the target Pod''s + container ports. If this is not specified, the value of the + ''port'' field is used (an identity map). This field is ignored + for services with clusterIP=None, and should be omitted or + set equal to the ''port'' field. More info: https://kubernetes.io/docs/concepts/services-networking/service/#defining-a-service' + x-kubernetes-int-or-string: true + required: + - port + type: object + type: array + x-kubernetes-list-type: atomic + resources: + description: Resources is the resource requirements for the oteld + properties: + claims: + description: "Claims lists the names of resources, defined in + spec.resourceClaims, that are used by this container. \n This + is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be set + for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in pod.spec.resourceClaims + of the Pod where this field is used. It makes that resource + available inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute resources + allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + useConfigMap: + description: UseConfigMap indicates whether to use configmap to store + oteld config + type: boolean + volumeMounts: + description: VolumeMounts represents the mount points to use in the + underlying collector deployment(s) + items: + description: VolumeMount describes a mounting of a Volume within + a container. + properties: + mountPath: + description: Path within the container at which the volume should + be mounted. Must not contain ':'. + type: string + mountPropagation: + description: mountPropagation determines how mounts are propagated + from the host to container and the other way around. When + not set, MountPropagationNone is used. This field is beta + in 1.10. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: Mounted read-only if true, read-write otherwise + (false or unspecified). Defaults to false. + type: boolean + subPath: + description: Path within the volume from which the container's + volume should be mounted. Defaults to "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume from which the + container's volume should be mounted. Behaves similarly to + SubPath but environment variable references $(VAR_NAME) are + expanded using the container's environment. Defaults to "" + (volume's root). SubPathExpr and SubPath are mutually exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-type: atomic + volumes: + description: Volumes represents which volumes to use in the underlying + collector deployment(s). + items: + description: Volume represents a named volume in a pod that may + be accessed by any container in the pod. + properties: + awsElasticBlockStore: + description: 'awsElasticBlockStore represents an AWS Disk resource + that is attached to a kubelet''s host machine and then exposed + to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + properties: + fsType: + description: 'fsType is the filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem + type is supported by the host operating system. Examples: + "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore + TODO: how do we prevent errors in the filesystem from + compromising the machine' + type: string + partition: + description: 'partition is the partition in the volume that + you want to mount. If omitted, the default is to mount + by volume name. Examples: For volume /dev/sda1, you specify + the partition as "1". Similarly, the volume partition + for /dev/sda is "0" (or you can leave the property empty).' + format: int32 + type: integer + readOnly: + description: 'readOnly value true will force the readOnly + setting in VolumeMounts. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + type: boolean + volumeID: + description: 'volumeID is unique ID of the persistent disk + resource in AWS (Amazon EBS volume). More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + type: string + required: + - volumeID + type: object + azureDisk: + description: azureDisk represents an Azure Data Disk mount on + the host and bind mount to the pod. + properties: + cachingMode: + description: 'cachingMode is the Host Caching mode: None, + Read Only, Read Write.' + type: string + diskName: + description: diskName is the Name of the data disk in the + blob storage + type: string + diskURI: + description: diskURI is the URI of data disk in the blob + storage + type: string + fsType: + description: fsType is Filesystem type to mount. Must be + a filesystem type supported by the host operating system. + Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. + type: string + kind: + description: 'kind expected values are Shared: multiple + blob disks per storage account Dedicated: single blob + disk per storage account Managed: azure managed data + disk (only in managed availability set). defaults to shared' + type: string + readOnly: + description: readOnly Defaults to false (read/write). ReadOnly + here will force the ReadOnly setting in VolumeMounts. + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + description: azureFile represents an Azure File Service mount + on the host and bind mount to the pod. + properties: + readOnly: + description: readOnly defaults to false (read/write). ReadOnly + here will force the ReadOnly setting in VolumeMounts. + type: boolean + secretName: + description: secretName is the name of secret that contains + Azure Storage Account Name and Key + type: string + shareName: + description: shareName is the azure share Name + type: string + required: + - secretName + - shareName + type: object + cephfs: + description: cephFS represents a Ceph FS mount on the host that + shares a pod's lifetime + properties: + monitors: + description: 'monitors is Required: Monitors is a collection + of Ceph monitors More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + items: + type: string + type: array + path: + description: 'path is Optional: Used as the mounted root, + rather than the full Ceph tree, default is /' + type: string + readOnly: + description: 'readOnly is Optional: Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts. + More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: boolean + secretFile: + description: 'secretFile is Optional: SecretFile is the + path to key ring for User, default is /etc/ceph/user.secret + More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: string + secretRef: + description: 'secretRef is Optional: SecretRef is reference + to the authentication secret for User, default is empty. + More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + user: + description: 'user is optional: User is the rados user name, + default is admin More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: string + required: + - monitors + type: object + cinder: + description: 'cinder represents a cinder volume attached and + mounted on kubelets host machine. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + properties: + fsType: + description: 'fsType is the filesystem type to mount. Must + be a filesystem type supported by the host operating system. + Examples: "ext4", "xfs", "ntfs". Implicitly inferred to + be "ext4" if unspecified. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: string + readOnly: + description: 'readOnly defaults to false (read/write). ReadOnly + here will force the ReadOnly setting in VolumeMounts. + More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: boolean + secretRef: + description: 'secretRef is optional: points to a secret + object containing parameters used to connect to OpenStack.' + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + volumeID: + description: 'volumeID used to identify the volume in cinder. + More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: string + required: + - volumeID + type: object + configMap: + description: configMap represents a configMap that should populate + this volume + properties: + defaultMode: + description: 'defaultMode is optional: mode bits used to + set permissions on created files by default. Must be an + octal value between 0000 and 0777 or a decimal value between + 0 and 511. YAML accepts both octal and decimal values, + JSON requires decimal values for mode bits. Defaults to + 0644. Directories within the path are not affected by + this setting. This might be in conflict with other options + that affect the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + items: + description: items if unspecified, each key-value pair in + the Data field of the referenced ConfigMap will be projected + into the volume as a file whose name is the key and content + is the value. If specified, the listed keys will be projected + into the specified paths, and unlisted keys will not be + present. If a key is specified which is not present in + the ConfigMap, the volume setup will error unless it is + marked optional. Paths must be relative and may not contain + the '..' path or start with '..'. + items: + description: Maps a string key to a path within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits used to + set permissions on this file. Must be an octal value + between 0000 and 0777 or a decimal value between + 0 and 511. YAML accepts both octal and decimal values, + JSON requires decimal values for mode bits. If not + specified, the volume defaultMode will be used. + This might be in conflict with other options that + affect the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + path: + description: path is the relative path of the file + to map the key to. May not be an absolute path. + May not contain the path element '..'. May not start + with the string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: optional specify whether the ConfigMap or its + keys must be defined + type: boolean + type: object + csi: + description: csi (Container Storage Interface) represents ephemeral + storage that is handled by certain external CSI drivers (Beta + feature). + properties: + driver: + description: driver is the name of the CSI driver that handles + this volume. Consult with your admin for the correct name + as registered in the cluster. + type: string + fsType: + description: fsType to mount. Ex. "ext4", "xfs", "ntfs". + If not provided, the empty value is passed to the associated + CSI driver which will determine the default filesystem + to apply. + type: string + nodePublishSecretRef: + description: nodePublishSecretRef is a reference to the + secret object containing sensitive information to pass + to the CSI driver to complete the CSI NodePublishVolume + and NodeUnpublishVolume calls. This field is optional, + and may be empty if no secret is required. If the secret + object contains more than one secret, all secret references + are passed. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + readOnly: + description: readOnly specifies a read-only configuration + for the volume. Defaults to false (read/write). + type: boolean + volumeAttributes: + additionalProperties: + type: string + description: volumeAttributes stores driver-specific properties + that are passed to the CSI driver. Consult your driver's + documentation for supported values. + type: object + required: + - driver + type: object + downwardAPI: + description: downwardAPI represents downward API about the pod + that should populate this volume + properties: + defaultMode: + description: 'Optional: mode bits to use on created files + by default. Must be a Optional: mode bits used to set + permissions on created files by default. Must be an octal + value between 0000 and 0777 or a decimal value between + 0 and 511. YAML accepts both octal and decimal values, + JSON requires decimal values for mode bits. Defaults to + 0644. Directories within the path are not affected by + this setting. This might be in conflict with other options + that affect the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + items: + description: Items is a list of downward API volume file + items: + description: DownwardAPIVolumeFile represents information + to create the file containing the pod field + properties: + fieldRef: + description: 'Required: Selects a field of the pod: + only annotations, labels, name and namespace are + supported.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + mode: + description: 'Optional: mode bits used to set permissions + on this file, must be an octal value between 0000 + and 0777 or a decimal value between 0 and 511. YAML + accepts both octal and decimal values, JSON requires + decimal values for mode bits. If not specified, + the volume defaultMode will be used. This might + be in conflict with other options that affect the + file mode, like fsGroup, and the result can be other + mode bits set.' + format: int32 + type: integer + path: + description: 'Required: Path is the relative path + name of the file to be created. Must not be absolute + or contain the ''..'' path. Must be utf-8 encoded. + The first item of the relative path must not start + with ''..''' + type: string + resourceFieldRef: + description: 'Selects a resource of the container: + only resources limits and requests (limits.cpu, + limits.memory, requests.cpu and requests.memory) + are currently supported.' + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + required: + - path + type: object + type: array + type: object + emptyDir: + description: 'emptyDir represents a temporary directory that + shares a pod''s lifetime. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + properties: + medium: + description: 'medium represents what type of storage medium + should back this directory. The default is "" which means + to use the node''s default medium. Must be an empty string + (default) or Memory. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + type: string + sizeLimit: + anyOf: + - type: integer + - type: string + description: 'sizeLimit is the total amount of local storage + required for this EmptyDir volume. The size limit is also + applicable for memory medium. The maximum usage on memory + medium EmptyDir would be the minimum value between the + SizeLimit specified here and the sum of memory limits + of all containers in a pod. The default is nil which means + that the limit is undefined. More info: http://kubernetes.io/docs/user-guide/volumes#emptydir' + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + ephemeral: + description: "ephemeral represents a volume that is handled + by a cluster storage driver. The volume's lifecycle is tied + to the pod that defines it - it will be created before the + pod starts, and deleted when the pod is removed. \n Use this + if: a) the volume is only needed while the pod runs, b) features + of normal volumes like restoring from snapshot or capacity + tracking are needed, c) the storage driver is specified through + a storage class, and d) the storage driver supports dynamic + volume provisioning through a PersistentVolumeClaim (see EphemeralVolumeSource + for more information on the connection between this volume + type and PersistentVolumeClaim). \n Use PersistentVolumeClaim + or one of the vendor-specific APIs for volumes that persist + for longer than the lifecycle of an individual pod. \n Use + CSI for light-weight local ephemeral volumes if the CSI driver + is meant to be used that way - see the documentation of the + driver for more information. \n A pod can use both types of + ephemeral volumes and persistent volumes at the same time." + properties: + volumeClaimTemplate: + description: "Will be used to create a stand-alone PVC to + provision the volume. The pod in which this EphemeralVolumeSource + is embedded will be the owner of the PVC, i.e. the PVC + will be deleted together with the pod. The name of the + PVC will be `-` where `` is the name from the `PodSpec.Volumes` array entry. + Pod validation will reject the pod if the concatenated + name is not valid for a PVC (for example, too long). \n + An existing PVC with that name that is not owned by the + pod will *not* be used for the pod to avoid using an unrelated + volume by mistake. Starting the pod is then blocked until + the unrelated PVC is removed. If such a pre-created PVC + is meant to be used by the pod, the PVC has to updated + with an owner reference to the pod once the pod exists. + Normally this should not be necessary, but it may be useful + when manually reconstructing a broken cluster. \n This + field is read-only and no changes will be made by Kubernetes + to the PVC after it has been created. \n Required, must + not be nil." + properties: + metadata: + description: May contain labels and annotations that + will be copied into the PVC when creating it. No other + fields are allowed and will be rejected during validation. + properties: + annotations: + additionalProperties: + type: string + type: object + finalizers: + items: + type: string + type: array + labels: + additionalProperties: + type: string + type: object + name: + type: string + namespace: + type: string + type: object + spec: + description: The specification for the PersistentVolumeClaim. + The entire content is copied unchanged into the PVC + that gets created from this template. The same fields + as in a PersistentVolumeClaim are also valid here. + properties: + accessModes: + description: 'accessModes contains the desired access + modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + dataSource: + description: 'dataSource field can be used to specify + either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) If the + provisioner or an external controller can support + the specified data source, it will create a new + volume based on the contents of the specified + data source. When the AnyVolumeDataSource feature + gate is enabled, dataSource contents will be copied + to dataSourceRef, and dataSourceRef contents will + be copied to dataSource when dataSourceRef.namespace + is not specified. If the namespace is specified, + then dataSourceRef will not be copied to dataSource.' + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API + group. For any other third-party types, APIGroup + is required. + type: string + kind: + description: Kind is the type of resource being + referenced + type: string + name: + description: Name is the name of resource being + referenced + type: string + required: + - kind + - name + type: object + dataSourceRef: + description: 'dataSourceRef specifies the object + from which to populate the volume with data, if + a non-empty volume is desired. This may be any + object from a non-empty API group (non core object) + or a PersistentVolumeClaim object. When this field + is specified, volume binding will only succeed + if the type of the specified object matches some + installed volume populator or dynamic provisioner. + This field will replace the functionality of the + dataSource field and as such if both fields are + non-empty, they must have the same value. For + backwards compatibility, when namespace isn''t + specified in dataSourceRef, both fields (dataSource + and dataSourceRef) will be set to the same value + automatically if one of them is empty and the + other is non-empty. When namespace is specified + in dataSourceRef, dataSource isn''t set to the + same value and must be empty. There are three + important differences between dataSource and dataSourceRef: + * While dataSource only allows two specific types + of objects, dataSourceRef allows any non-core + object, as well as PersistentVolumeClaim objects. + * While dataSource ignores disallowed values (dropping + them), dataSourceRef preserves all values, and + generates an error if a disallowed value is specified. + * While dataSource only allows local objects, + dataSourceRef allows objects in any namespaces. + (Beta) Using this field requires the AnyVolumeDataSource + feature gate to be enabled. (Alpha) Using the + namespace field of dataSourceRef requires the + CrossNamespaceVolumeDataSource feature gate to + be enabled.' + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API + group. For any other third-party types, APIGroup + is required. + type: string + kind: + description: Kind is the type of resource being + referenced + type: string + name: + description: Name is the name of resource being + referenced + type: string + namespace: + description: Namespace is the namespace of resource + being referenced Note that when a namespace + is specified, a gateway.networking.k8s.io/ReferenceGrant + object is required in the referent namespace + to allow that namespace's owner to accept + the reference. See the ReferenceGrant documentation + for details. (Alpha) This field requires the + CrossNamespaceVolumeDataSource feature gate + to be enabled. + type: string + required: + - kind + - name + type: object + resources: + description: 'resources represents the minimum resources + the volume should have. If RecoverVolumeExpansionFailure + feature is enabled users are allowed to specify + resource requirements that are lower than previous + value but must still be higher than capacity recorded + in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' + properties: + claims: + description: "Claims lists the names of resources, + defined in spec.resourceClaims, that are used + by this container. \n This is an alpha field + and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. + It can only be set for containers." + items: + description: ResourceClaim references one + entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name + of one entry in pod.spec.resourceClaims + of the Pod where this field is used. + It makes that resource available inside + a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount + of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum + amount of compute resources required. If Requests + is omitted for a container, it defaults to + Limits if that is explicitly specified, otherwise + to an implementation-defined value. More info: + https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + selector: + description: selector is a label query over volumes + to consider for binding. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + storageClassName: + description: 'storageClassName is the name of the + StorageClass required by the claim. More info: + https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + type: string + volumeMode: + description: volumeMode defines what type of volume + is required by the claim. Value of Filesystem + is implied when not included in claim spec. + type: string + volumeName: + description: volumeName is the binding reference + to the PersistentVolume backing this claim. + type: string + type: object + required: + - spec + type: object + type: object + fc: + description: fc represents a Fibre Channel resource that is + attached to a kubelet's host machine and then exposed to the + pod. + properties: + fsType: + description: 'fsType is the filesystem type to mount. Must + be a filesystem type supported by the host operating system. + Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. TODO: how do we prevent errors in the + filesystem from compromising the machine' + type: string + lun: + description: 'lun is Optional: FC target lun number' + format: int32 + type: integer + readOnly: + description: 'readOnly is Optional: Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts.' + type: boolean + targetWWNs: + description: 'targetWWNs is Optional: FC target worldwide + names (WWNs)' + items: + type: string + type: array + wwids: + description: 'wwids Optional: FC volume world wide identifiers + (wwids) Either wwids or combination of targetWWNs and + lun must be set, but not both simultaneously.' + items: + type: string + type: array + type: object + flexVolume: + description: flexVolume represents a generic volume resource + that is provisioned/attached using an exec based plugin. + properties: + driver: + description: driver is the name of the driver to use for + this volume. + type: string + fsType: + description: fsType is the filesystem type to mount. Must + be a filesystem type supported by the host operating system. + Ex. "ext4", "xfs", "ntfs". The default filesystem depends + on FlexVolume script. + type: string + options: + additionalProperties: + type: string + description: 'options is Optional: this field holds extra + command options if any.' + type: object + readOnly: + description: 'readOnly is Optional: defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts.' + type: boolean + secretRef: + description: 'secretRef is Optional: secretRef is reference + to the secret object containing sensitive information + to pass to the plugin scripts. This may be empty if no + secret object is specified. If the secret object contains + more than one secret, all secrets are passed to the plugin + scripts.' + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + required: + - driver + type: object + flocker: + description: flocker represents a Flocker volume attached to + a kubelet's host machine. This depends on the Flocker control + service being running + properties: + datasetName: + description: datasetName is Name of the dataset stored as + metadata -> name on the dataset for Flocker should be + considered as deprecated + type: string + datasetUUID: + description: datasetUUID is the UUID of the dataset. This + is unique identifier of a Flocker dataset + type: string + type: object + gcePersistentDisk: + description: 'gcePersistentDisk represents a GCE Disk resource + that is attached to a kubelet''s host machine and then exposed + to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + properties: + fsType: + description: 'fsType is filesystem type of the volume that + you want to mount. Tip: Ensure that the filesystem type + is supported by the host operating system. Examples: "ext4", + "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. + More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk + TODO: how do we prevent errors in the filesystem from + compromising the machine' + type: string + partition: + description: 'partition is the partition in the volume that + you want to mount. If omitted, the default is to mount + by volume name. Examples: For volume /dev/sda1, you specify + the partition as "1". Similarly, the volume partition + for /dev/sda is "0" (or you can leave the property empty). + More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + format: int32 + type: integer + pdName: + description: 'pdName is unique name of the PD resource in + GCE. Used to identify the disk in GCE. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + type: string + readOnly: + description: 'readOnly here will force the ReadOnly setting + in VolumeMounts. Defaults to false. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + type: boolean + required: + - pdName + type: object + gitRepo: + description: 'gitRepo represents a git repository at a particular + revision. DEPRECATED: GitRepo is deprecated. To provision + a container with a git repo, mount an EmptyDir into an InitContainer + that clones the repo using git, then mount the EmptyDir into + the Pod''s container.' + properties: + directory: + description: directory is the target directory name. Must + not contain or start with '..'. If '.' is supplied, the + volume directory will be the git repository. Otherwise, + if specified, the volume will contain the git repository + in the subdirectory with the given name. + type: string + repository: + description: repository is the URL + type: string + revision: + description: revision is the commit hash for the specified + revision. + type: string + required: + - repository + type: object + glusterfs: + description: 'glusterfs represents a Glusterfs mount on the + host that shares a pod''s lifetime. More info: https://examples.k8s.io/volumes/glusterfs/README.md' + properties: + endpoints: + description: 'endpoints is the endpoint name that details + Glusterfs topology. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: string + path: + description: 'path is the Glusterfs volume path. More info: + https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: string + readOnly: + description: 'readOnly here will force the Glusterfs volume + to be mounted with read-only permissions. Defaults to + false. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: boolean + required: + - endpoints + - path + type: object + hostPath: + description: 'hostPath represents a pre-existing file or directory + on the host machine that is directly exposed to the container. + This is generally used for system agents or other privileged + things that are allowed to see the host machine. Most containers + will NOT need this. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath + --- TODO(jonesdl) We need to restrict who can use host directory + mounts and who can/can not mount host directories as read/write.' + properties: + path: + description: 'path of the directory on the host. If the + path is a symlink, it will follow the link to the real + path. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' + type: string + type: + description: 'type for HostPath Volume Defaults to "" More + info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' + type: string + required: + - path + type: object + iscsi: + description: 'iscsi represents an ISCSI Disk resource that is + attached to a kubelet''s host machine and then exposed to + the pod. More info: https://examples.k8s.io/volumes/iscsi/README.md' + properties: + chapAuthDiscovery: + description: chapAuthDiscovery defines whether support iSCSI + Discovery CHAP authentication + type: boolean + chapAuthSession: + description: chapAuthSession defines whether support iSCSI + Session CHAP authentication + type: boolean + fsType: + description: 'fsType is the filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem + type is supported by the host operating system. Examples: + "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#iscsi + TODO: how do we prevent errors in the filesystem from + compromising the machine' + type: string + initiatorName: + description: initiatorName is the custom iSCSI Initiator + Name. If initiatorName is specified with iscsiInterface + simultaneously, new iSCSI interface : will be created for the connection. + type: string + iqn: + description: iqn is the target iSCSI Qualified Name. + type: string + iscsiInterface: + description: iscsiInterface is the interface Name that uses + an iSCSI transport. Defaults to 'default' (tcp). + type: string + lun: + description: lun represents iSCSI Target Lun number. + format: int32 + type: integer + portals: + description: portals is the iSCSI Target Portal List. The + portal is either an IP or ip_addr:port if the port is + other than default (typically TCP ports 860 and 3260). + items: + type: string + type: array + readOnly: + description: readOnly here will force the ReadOnly setting + in VolumeMounts. Defaults to false. + type: boolean + secretRef: + description: secretRef is the CHAP Secret for iSCSI target + and initiator authentication + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + targetPortal: + description: targetPortal is iSCSI Target Portal. The Portal + is either an IP or ip_addr:port if the port is other than + default (typically TCP ports 860 and 3260). + type: string + required: + - iqn + - lun + - targetPortal + type: object + name: + description: 'name of the volume. Must be a DNS_LABEL and unique + within the pod. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + nfs: + description: 'nfs represents an NFS mount on the host that shares + a pod''s lifetime More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + properties: + path: + description: 'path that is exported by the NFS server. More + info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: string + readOnly: + description: 'readOnly here will force the NFS export to + be mounted with read-only permissions. Defaults to false. + More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: boolean + server: + description: 'server is the hostname or IP address of the + NFS server. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: string + required: + - path + - server + type: object + persistentVolumeClaim: + description: 'persistentVolumeClaimVolumeSource represents a + reference to a PersistentVolumeClaim in the same namespace. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + properties: + claimName: + description: 'claimName is the name of a PersistentVolumeClaim + in the same namespace as the pod using this volume. More + info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + type: string + readOnly: + description: readOnly Will force the ReadOnly setting in + VolumeMounts. Default false. + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + description: photonPersistentDisk represents a PhotonController + persistent disk attached and mounted on kubelets host machine + properties: + fsType: + description: fsType is the filesystem type to mount. Must + be a filesystem type supported by the host operating system. + Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. + type: string + pdID: + description: pdID is the ID that identifies Photon Controller + persistent disk + type: string + required: + - pdID + type: object + portworxVolume: + description: portworxVolume represents a portworx volume attached + and mounted on kubelets host machine + properties: + fsType: + description: fSType represents the filesystem type to mount + Must be a filesystem type supported by the host operating + system. Ex. "ext4", "xfs". Implicitly inferred to be "ext4" + if unspecified. + type: string + readOnly: + description: readOnly defaults to false (read/write). ReadOnly + here will force the ReadOnly setting in VolumeMounts. + type: boolean + volumeID: + description: volumeID uniquely identifies a Portworx volume + type: string + required: + - volumeID + type: object + projected: + description: projected items for all in one resources secrets, + configmaps, and downward API + properties: + defaultMode: + description: defaultMode are the mode bits used to set permissions + on created files by default. Must be an octal value between + 0000 and 0777 or a decimal value between 0 and 511. YAML + accepts both octal and decimal values, JSON requires decimal + values for mode bits. Directories within the path are + not affected by this setting. This might be in conflict + with other options that affect the file mode, like fsGroup, + and the result can be other mode bits set. + format: int32 + type: integer + sources: + description: sources is the list of volume projections + items: + description: Projection that may be projected along with + other supported volume types + properties: + configMap: + description: configMap information about the configMap + data to project + properties: + items: + description: items if unspecified, each key-value + pair in the Data field of the referenced ConfigMap + will be projected into the volume as a file + whose name is the key and content is the value. + If specified, the listed keys will be projected + into the specified paths, and unlisted keys + will not be present. If a key is specified which + is not present in the ConfigMap, the volume + setup will error unless it is marked optional. + Paths must be relative and may not contain the + '..' path or start with '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits + used to set permissions on this file. + Must be an octal value between 0000 and + 0777 or a decimal value between 0 and + 511. YAML accepts both octal and decimal + values, JSON requires decimal values for + mode bits. If not specified, the volume + defaultMode will be used. This might be + in conflict with other options that affect + the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + path: + description: path is the relative path of + the file to map the key to. May not be + an absolute path. May not contain the + path element '..'. May not start with + the string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: optional specify whether the ConfigMap + or its keys must be defined + type: boolean + type: object + downwardAPI: + description: downwardAPI information about the downwardAPI + data to project + properties: + items: + description: Items is a list of DownwardAPIVolume + file + items: + description: DownwardAPIVolumeFile represents + information to create the file containing + the pod field + properties: + fieldRef: + description: 'Required: Selects a field + of the pod: only annotations, labels, + name and namespace are supported.' + properties: + apiVersion: + description: Version of the schema the + FieldPath is written in terms of, + defaults to "v1". + type: string + fieldPath: + description: Path of the field to select + in the specified API version. + type: string + required: + - fieldPath + type: object + mode: + description: 'Optional: mode bits used to + set permissions on this file, must be + an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML + accepts both octal and decimal values, + JSON requires decimal values for mode + bits. If not specified, the volume defaultMode + will be used. This might be in conflict + with other options that affect the file + mode, like fsGroup, and the result can + be other mode bits set.' + format: int32 + type: integer + path: + description: 'Required: Path is the relative + path name of the file to be created. Must + not be absolute or contain the ''..'' + path. Must be utf-8 encoded. The first + item of the relative path must not start + with ''..''' + type: string + resourceFieldRef: + description: 'Selects a resource of the + container: only resources limits and requests + (limits.cpu, limits.memory, requests.cpu + and requests.memory) are currently supported.' + properties: + containerName: + description: 'Container name: required + for volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format + of the exposed resources, defaults + to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to + select' + type: string + required: + - resource + type: object + required: + - path + type: object + type: array + type: object + secret: + description: secret information about the secret data + to project + properties: + items: + description: items if unspecified, each key-value + pair in the Data field of the referenced Secret + will be projected into the volume as a file + whose name is the key and content is the value. + If specified, the listed keys will be projected + into the specified paths, and unlisted keys + will not be present. If a key is specified which + is not present in the Secret, the volume setup + will error unless it is marked optional. Paths + must be relative and may not contain the '..' + path or start with '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits + used to set permissions on this file. + Must be an octal value between 0000 and + 0777 or a decimal value between 0 and + 511. YAML accepts both octal and decimal + values, JSON requires decimal values for + mode bits. If not specified, the volume + defaultMode will be used. This might be + in conflict with other options that affect + the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + path: + description: path is the relative path of + the file to map the key to. May not be + an absolute path. May not contain the + path element '..'. May not start with + the string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: optional field specify whether the + Secret or its key must be defined + type: boolean + type: object + serviceAccountToken: + description: serviceAccountToken is information about + the serviceAccountToken data to project + properties: + audience: + description: audience is the intended audience + of the token. A recipient of a token must identify + itself with an identifier specified in the audience + of the token, and otherwise should reject the + token. The audience defaults to the identifier + of the apiserver. + type: string + expirationSeconds: + description: expirationSeconds is the requested + duration of validity of the service account + token. As the token approaches expiration, the + kubelet volume plugin will proactively rotate + the service account token. The kubelet will + start trying to rotate the token if the token + is older than 80 percent of its time to live + or if the token is older than 24 hours.Defaults + to 1 hour and must be at least 10 minutes. + format: int64 + type: integer + path: + description: path is the path relative to the + mount point of the file to project the token + into. + type: string + required: + - path + type: object + type: object + type: array + type: object + quobyte: + description: quobyte represents a Quobyte mount on the host + that shares a pod's lifetime + properties: + group: + description: group to map volume access to Default is no + group + type: string + readOnly: + description: readOnly here will force the Quobyte volume + to be mounted with read-only permissions. Defaults to + false. + type: boolean + registry: + description: registry represents a single or multiple Quobyte + Registry services specified as a string as host:port pair + (multiple entries are separated with commas) which acts + as the central registry for volumes + type: string + tenant: + description: tenant owning the given Quobyte volume in the + Backend Used with dynamically provisioned Quobyte volumes, + value is set by the plugin + type: string + user: + description: user to map volume access to Defaults to serivceaccount + user + type: string + volume: + description: volume is a string that references an already + created Quobyte volume by name. + type: string + required: + - registry + - volume + type: object + rbd: + description: 'rbd represents a Rados Block Device mount on the + host that shares a pod''s lifetime. More info: https://examples.k8s.io/volumes/rbd/README.md' + properties: + fsType: + description: 'fsType is the filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem + type is supported by the host operating system. Examples: + "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#rbd + TODO: how do we prevent errors in the filesystem from + compromising the machine' + type: string + image: + description: 'image is the rados image name. More info: + https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + keyring: + description: 'keyring is the path to key ring for RBDUser. + Default is /etc/ceph/keyring. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + monitors: + description: 'monitors is a collection of Ceph monitors. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + items: + type: string + type: array + pool: + description: 'pool is the rados pool name. Default is rbd. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + readOnly: + description: 'readOnly here will force the ReadOnly setting + in VolumeMounts. Defaults to false. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: boolean + secretRef: + description: 'secretRef is name of the authentication secret + for RBDUser. If provided overrides keyring. Default is + nil. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + user: + description: 'user is the rados user name. Default is admin. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + required: + - image + - monitors + type: object + scaleIO: + description: scaleIO represents a ScaleIO persistent volume + attached and mounted on Kubernetes nodes. + properties: + fsType: + description: fsType is the filesystem type to mount. Must + be a filesystem type supported by the host operating system. + Ex. "ext4", "xfs", "ntfs". Default is "xfs". + type: string + gateway: + description: gateway is the host address of the ScaleIO + API Gateway. + type: string + protectionDomain: + description: protectionDomain is the name of the ScaleIO + Protection Domain for the configured storage. + type: string + readOnly: + description: readOnly Defaults to false (read/write). ReadOnly + here will force the ReadOnly setting in VolumeMounts. + type: boolean + secretRef: + description: secretRef references to the secret for ScaleIO + user and other sensitive information. If this is not provided, + Login operation will fail. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + sslEnabled: + description: sslEnabled Flag enable/disable SSL communication + with Gateway, default false + type: boolean + storageMode: + description: storageMode indicates whether the storage for + a volume should be ThickProvisioned or ThinProvisioned. + Default is ThinProvisioned. + type: string + storagePool: + description: storagePool is the ScaleIO Storage Pool associated + with the protection domain. + type: string + system: + description: system is the name of the storage system as + configured in ScaleIO. + type: string + volumeName: + description: volumeName is the name of a volume already + created in the ScaleIO system that is associated with + this volume source. + type: string + required: + - gateway + - secretRef + - system + type: object + secret: + description: 'secret represents a secret that should populate + this volume. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + properties: + defaultMode: + description: 'defaultMode is Optional: mode bits used to + set permissions on created files by default. Must be an + octal value between 0000 and 0777 or a decimal value between + 0 and 511. YAML accepts both octal and decimal values, + JSON requires decimal values for mode bits. Defaults to + 0644. Directories within the path are not affected by + this setting. This might be in conflict with other options + that affect the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + items: + description: items If unspecified, each key-value pair in + the Data field of the referenced Secret will be projected + into the volume as a file whose name is the key and content + is the value. If specified, the listed keys will be projected + into the specified paths, and unlisted keys will not be + present. If a key is specified which is not present in + the Secret, the volume setup will error unless it is marked + optional. Paths must be relative and may not contain the + '..' path or start with '..'. + items: + description: Maps a string key to a path within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits used to + set permissions on this file. Must be an octal value + between 0000 and 0777 or a decimal value between + 0 and 511. YAML accepts both octal and decimal values, + JSON requires decimal values for mode bits. If not + specified, the volume defaultMode will be used. + This might be in conflict with other options that + affect the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + path: + description: path is the relative path of the file + to map the key to. May not be an absolute path. + May not contain the path element '..'. May not start + with the string '..'. + type: string + required: + - key + - path + type: object + type: array + optional: + description: optional field specify whether the Secret or + its keys must be defined + type: boolean + secretName: + description: 'secretName is the name of the secret in the + pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + type: string + type: object + storageos: + description: storageOS represents a StorageOS volume attached + and mounted on Kubernetes nodes. + properties: + fsType: + description: fsType is the filesystem type to mount. Must + be a filesystem type supported by the host operating system. + Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. + type: string + readOnly: + description: readOnly defaults to false (read/write). ReadOnly + here will force the ReadOnly setting in VolumeMounts. + type: boolean + secretRef: + description: secretRef specifies the secret to use for obtaining + the StorageOS API credentials. If not specified, default + values will be attempted. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + volumeName: + description: volumeName is the human-readable name of the + StorageOS volume. Volume names are only unique within + a namespace. + type: string + volumeNamespace: + description: volumeNamespace specifies the scope of the + volume within StorageOS. If no namespace is specified + then the Pod's namespace will be used. This allows the + Kubernetes name scoping to be mirrored within StorageOS + for tighter integration. Set VolumeName to any name to + override the default behaviour. Set to "default" if you + are not using namespaces within StorageOS. Namespaces + that do not pre-exist within StorageOS will be created. + type: string + type: object + vsphereVolume: + description: vsphereVolume represents a vSphere volume attached + and mounted on kubelets host machine + properties: + fsType: + description: fsType is filesystem type to mount. Must be + a filesystem type supported by the host operating system. + Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. + type: string + storagePolicyID: + description: storagePolicyID is the storage Policy Based + Management (SPBM) profile ID associated with the StoragePolicyName. + type: string + storagePolicyName: + description: storagePolicyName is the storage Policy Based + Management (SPBM) profile name. + type: string + volumePath: + description: volumePath is the path that identifies vSphere + volume vmdk + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + x-kubernetes-list-type: atomic + required: + - useConfigMap + type: object + status: + description: CollectorDataSourceStatus defines the observed state of CollectorDataSource + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/controllers/monitor/builder/builder.go b/controllers/monitor/builder/builder.go index ae4f2abe5c47..5fc2f0b35de8 100644 --- a/controllers/monitor/builder/builder.go +++ b/controllers/monitor/builder/builder.go @@ -86,7 +86,10 @@ func MergeValMapFromYamlStr(defaultMap map[string]any, yamlStr string) { defaultMap = map[string]any{} } valMap := map[string]any{} - yaml.Unmarshal([]byte(yamlStr), &valMap) + err := yaml.Unmarshal([]byte(yamlStr), &valMap) + if err != nil { + return + } for k, v := range valMap { defaultMap[k] = v } diff --git a/controllers/monitor/oteld_controller.go b/controllers/monitor/oteld_controller.go index dd77912712a3..a51df12a1ec1 100644 --- a/controllers/monitor/oteld_controller.go +++ b/controllers/monitor/oteld_controller.go @@ -76,11 +76,13 @@ type OTeldReconciler struct { // - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.14.4/pkg/reconcile func (r *OTeldReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { reqCtx := monitortypes.ReconcileCtx{ - Ctx: ctx, - Req: req, - Log: log.FromContext(ctx).WithName("OTeldCollectorReconciler"), + Ctx: ctx, + Req: req, + Log: log.FromContext(ctx).WithName("OTeldCollectorReconciler"), + Namespace: viper.GetString(constant.MonitorNamespaceEnvName), - Config: r.Config, + Config: r.Config, + OteldCfgRef: &monitortypes.OteldCfgRef{}, } // TODO prepare required resources diff --git a/controllers/monitor/reconcile/configmap.go b/controllers/monitor/reconcile/configmap.go index 4ae7fbc11a41..ef09bf20bed9 100644 --- a/controllers/monitor/reconcile/configmap.go +++ b/controllers/monitor/reconcile/configmap.go @@ -32,15 +32,19 @@ import ( func ConfigMap(reqCtx types.ReconcileCtx, params types.OTeldParams) error { desired := []*corev1.ConfigMap{} + cg := reqCtx.GetConfigGenerator() + if cg == nil { + return fmt.Errorf("config generator is nil") + } if reqCtx.GetOteldInstance(monitorv1alpha1.ModeDaemonSet) != nil { - configmap, _ := buildConfigMapForOteld(reqCtx.Config, reqCtx.GetOteldInstance(monitorv1alpha1.ModeDaemonSet), reqCtx.Namespace, reqCtx.GetExporters(), params.ConfigGenerator) + configmap, _ := buildConfigMapForOteld(reqCtx.Config, reqCtx.GetOteldInstance(monitorv1alpha1.ModeDaemonSet), reqCtx.Namespace, reqCtx.GetExporters(), cg) if configmap != nil { desired = append(desired, configmap) } } if reqCtx.GetOteldInstance(monitorv1alpha1.ModeDeployment) != nil { - configmap, _ := buildConfigMapForOteld(reqCtx.Config, reqCtx.GetOteldInstance(monitorv1alpha1.ModeDeployment), reqCtx.Namespace, reqCtx.GetExporters(), nil) + configmap, _ := buildConfigMapForOteld(reqCtx.Config, reqCtx.GetOteldInstance(monitorv1alpha1.ModeDeployment), reqCtx.Namespace, reqCtx.GetExporters(), cg) if configmap != nil { desired = append(desired, configmap) } diff --git a/controllers/monitor/reconcile/deployment.go b/controllers/monitor/reconcile/deployment.go index c070843c3a1a..6fac639865cf 100644 --- a/controllers/monitor/reconcile/deployment.go +++ b/controllers/monitor/reconcile/deployment.go @@ -41,9 +41,9 @@ func Deployment(reqCtx monitortypes.ReconcileCtx, params monitortypes.OTeldParam namespace = viper.GetString(constant.MonitorNamespaceEnvName) ) - instance := reqCtx.GetOteldInstance(monitorv1alpha1.ModeDaemonSet) + instance := reqCtx.GetOteldInstance(monitorv1alpha1.ModeDeployment) - oteldDaemonset := buildDeploymentForOteld(reqCtx.Config, instance, namespace, OTeldName) + oteldDeployment := buildDeploymentForOteld(reqCtx.Config, instance, namespace, OTeldName) existingDeployment := &appsv1.Deployment{} err := k8sClient.Get(reqCtx.Ctx, client.ObjectKey{Name: OTeldName, Namespace: namespace}, existingDeployment) @@ -53,26 +53,26 @@ func Deployment(reqCtx monitortypes.ReconcileCtx, params monitortypes.OTeldParam params.Recorder.Eventf(existingDeployment, corev1.EventTypeWarning, "Failed to find secret", err.Error()) return err } - if existingDeployment == nil { + if oteldDeployment == nil { return nil } - return k8sClient.Create(reqCtx.Ctx, oteldDaemonset) + return k8sClient.Create(reqCtx.Ctx, oteldDeployment) } - if oteldDaemonset == nil { + if oteldDeployment == nil { return k8sClient.Delete(reqCtx.Ctx, existingDeployment) } - if reflect.DeepEqual(existingDeployment.Spec, oteldDaemonset.Spec) { + if reflect.DeepEqual(existingDeployment.Spec, oteldDeployment.Spec) { return nil } updatedDeployment := existingDeployment.DeepCopy() - updatedDeployment.Spec = oteldDaemonset.Spec - updatedDeployment.Labels = oteldDaemonset.Labels - updatedDeployment.Annotations = oteldDaemonset.Annotations + updatedDeployment.Spec = oteldDeployment.Spec + updatedDeployment.Labels = oteldDeployment.Labels + updatedDeployment.Annotations = oteldDeployment.Annotations reqCtx.Log.Info("updating existing daemonset", "daemonset", client.ObjectKeyFromObject(updatedDeployment)) - return k8sClient.Update(reqCtx.Ctx, oteldDaemonset) + return k8sClient.Update(reqCtx.Ctx, oteldDeployment) } func buildDeploymentForOteld(config *monitortypes.Config, instance *monitortypes.OteldInstance, namespace, name string) *appsv1.Deployment { diff --git a/controllers/monitor/reconcile/oteld.go b/controllers/monitor/reconcile/oteld.go index a872d89b2c41..c014936ed3c3 100644 --- a/controllers/monitor/reconcile/oteld.go +++ b/controllers/monitor/reconcile/oteld.go @@ -33,18 +33,18 @@ func OTeld(reqCtx monitortype.ReconcileCtx, params monitortype.OTeldParams) (err k8sClient = params.Client ) - params.ConfigGenerator = monitortype.NewConfigGenerator() + reqCtx.SetConfigGenerator(monitortype.NewConfigGenerator()) exporter := monitortype.Exporters{} metricsExporters := &v1alpha1.MetricsExporterSinkList{} if err = k8sClient.List(ctx, metricsExporters); err != nil { - return + return err } exporter.Metricsexporter = metricsExporters.Items logsExporters := &v1alpha1.LogsExporterSinkList{} if err = k8sClient.List(ctx, logsExporters); err != nil { - return + return err } exporter.Logsexporter = logsExporters.Items @@ -52,42 +52,40 @@ func OTeld(reqCtx monitortype.ReconcileCtx, params monitortype.OTeldParams) (err datasources := &v1alpha1.CollectorDataSourceList{} if err = k8sClient.List(ctx, datasources); err != nil { - return + return err } oteldTemplates := &v1alpha1.OTeldCollectorTemplateList{} if err = k8sClient.List(ctx, oteldTemplates); err != nil { - return - } - buildOteldInstance(reqCtx, metricsExporters, logsExporters, datasources, oteldTemplates) - return -} - -func buildOteldInstance( - reqCtx monitortype.ReconcileCtx, - metricsExporterList *v1alpha1.MetricsExporterSinkList, - logsExporterList *v1alpha1.LogsExporterSinkList, - datasources *v1alpha1.CollectorDataSourceList, - templates *v1alpha1.OTeldCollectorTemplateList, -) error { - instanceMap, err := BuildInstanceMapForPipline(datasources) - if err != nil { return err } + instanceMap, err := buildOteldInstance(datasources, oteldTemplates) reqCtx.SetOteldInstanceMap(instanceMap) - for _, template := range templates.Items { + for _, template := range oteldTemplates.Items { instance := reqCtx.GetOteldInstance(template.Spec.Mode) if instance == nil { continue } instance.OteldTemplate = &template } + if err != nil { + return err + } - if err := reqCtx.VerifyOteldInstance(metricsExporterList, logsExporterList); err != nil { + if err := reqCtx.VerifyOteldInstance(metricsExporters, logsExporters); err != nil { return err } - return nil + return +} + +func buildOteldInstance(datasources *v1alpha1.CollectorDataSourceList, templates *v1alpha1.OTeldCollectorTemplateList) (map[v1alpha1.Mode]*monitortype.OteldInstance, error) { + instanceMap, err := BuildInstanceMapForPipline(datasources) + if err != nil { + return nil, err + } + + return instanceMap, nil } func BuildInstanceMapForPipline(datasources *v1alpha1.CollectorDataSourceList) (map[v1alpha1.Mode]*monitortype.OteldInstance, error) { @@ -114,6 +112,10 @@ func BuildInstanceMapForPipline(datasources *v1alpha1.CollectorDataSourceList) ( CollectionInterval: dataSource.Spec.CollectionInterval, } } + + for _, exporter := range dataSource.Spec.ExporterNames { + pipline.ExporterMap[exporter] = true + } oteldInstance.MetricsPipline = append(oteldInstance.MetricsPipline, pipline) case v1alpha1.LogsDataSourceType: diff --git a/controllers/monitor/reconcile/secret.go b/controllers/monitor/reconcile/secret.go index 7cd213cb3ca6..73614206c522 100644 --- a/controllers/monitor/reconcile/secret.go +++ b/controllers/monitor/reconcile/secret.go @@ -36,15 +36,21 @@ const OteldSecretName = "oteld-secret" func Secret(reqCtx types.ReconcileCtx, params types.OTeldParams) error { desired := []*corev1.Secret{} - if reqCtx.GetOteldInstance(monitorv1alpha1.ModeDaemonSet) != nil { - secret, _ := buildSecretForOteld(reqCtx.Config, reqCtx.GetOteldInstance(monitorv1alpha1.ModeDaemonSet), reqCtx.Namespace, reqCtx.GetExporters(), params.ConfigGenerator) + cg := reqCtx.GetConfigGenerator() + if cg == nil { + return fmt.Errorf("config generator is nil") + } + daemonsetInstance := reqCtx.GetOteldInstance(monitorv1alpha1.ModeDaemonSet) + if daemonsetInstance != nil { + secret, _ := buildSecretForOteld(reqCtx.Config, daemonsetInstance, reqCtx.Namespace, reqCtx.GetExporters(), cg) if secret != nil { desired = append(desired, secret) } } - if reqCtx.GetOteldInstance(monitorv1alpha1.ModeDeployment) != nil { - secret, _ := buildSecretForOteld(reqCtx.Config, reqCtx.GetOteldInstance(monitorv1alpha1.ModeDeployment), reqCtx.Namespace, reqCtx.GetExporters(), params.ConfigGenerator) + deploymentInstance := reqCtx.GetOteldInstance(monitorv1alpha1.ModeDeployment) + if deploymentInstance != nil { + secret, _ := buildSecretForOteld(reqCtx.Config, deploymentInstance, reqCtx.Namespace, reqCtx.GetExporters(), cg) if secret != nil { desired = append(desired, secret) } diff --git a/controllers/monitor/reconcile/service.go b/controllers/monitor/reconcile/service.go index 3d92890b9210..8207f7bd232d 100644 --- a/controllers/monitor/reconcile/service.go +++ b/controllers/monitor/reconcile/service.go @@ -35,7 +35,10 @@ func Service(reqCtx types.ReconcileCtx, params types.OTeldParams) error { desired := []*corev1.Service{} if reqCtx.GetOteldInstance(monitorv1alpha1.ModeDaemonSet) != nil { - svc, _ := buildSvcForOtel(reqCtx.Config, reqCtx.GetOteldInstance(monitorv1alpha1.ModeDaemonSet), reqCtx.Namespace) + svc, err := buildSvcForOtel(reqCtx.Config, reqCtx.GetOteldInstance(monitorv1alpha1.ModeDaemonSet), reqCtx.Namespace) + if err != nil { + return err + } if svc != nil { desired = append(desired, svc) } diff --git a/controllers/monitor/reconcile/utils.go b/controllers/monitor/reconcile/utils.go index c3030dad0dbe..3c923cdefaf1 100644 --- a/controllers/monitor/reconcile/utils.go +++ b/controllers/monitor/reconcile/utils.go @@ -21,7 +21,6 @@ package reconcile import ( "fmt" - "gopkg.in/yaml.v2" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/util/intstr" @@ -40,86 +39,6 @@ const ( var ( defaultMetricsPort = 8888 - - env = []corev1.EnvVar{ - { - Name: "HOST_IP", - Value: "0.0.0.0", - }, - { - Name: "HOST_ROOT", - Value: "/host/root", - }, - { - Name: "POD_NAME", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "metadata.name", - }, - }, - }, - { - Name: "POD_NAMESPACE", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "metadata.namespace", - }, - }, - }, - { - Name: "NODE_NAME", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "spec.nodeName", - }, - }, - }, - } - - volumeMounts = []corev1.VolumeMount{ - { - Name: OTeldName, - MountPath: "/var/log/oteld", - }, - { - Name: "root", - MountPath: "/host/root", - ReadOnly: true, - }, - { - Name: "config-volume", - MountPath: "/etc/oteld/config", - }, - } - - hostPathType = corev1.HostPathDirectoryOrCreate - volumes = []corev1.Volume{ - { - Name: OTeldName, - VolumeSource: corev1.VolumeSource{ - HostPath: &corev1.HostPathVolumeSource{ - Path: "/etc/oteld", - Type: &hostPathType, - }, - }, - }, - { - Name: "root", - VolumeSource: corev1.VolumeSource{ - HostPath: &corev1.HostPathVolumeSource{ - Path: "/", - }, - }, - }, - { - Name: "config-volume", - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: OTeldName, - }, - }, - }, - } ) func buildPodSpecForOteld(config *types.Config, template *v1alpha1.OTeldCollectorTemplate) *corev1.PodSpec { @@ -156,7 +75,7 @@ func buildSvcForOtel(config *types.Config, instance *types.OteldInstance, namesp } name := fmt.Sprintf(OteldServiceNamePattern, instance.OteldTemplate.Spec.Mode) - port := defaultMetricsPort + port := instance.OteldTemplate.Spec.MetricsPort if instance != nil && instance.OteldTemplate != nil && instance.OteldTemplate.Spec.MetricsPort != 0 { port = instance.OteldTemplate.Spec.MetricsPort } @@ -222,18 +141,18 @@ func buildConfigMapForOteld(_ *types.Config, instance *types.OteldInstance, name } return builder.NewConfigMapBuilder(namespace, name). - SetBinaryData(map[string][]byte{"config.yaml": marshal}). + SetData(map[string]string{"config.yaml": string(marshal)}). AddLabelsInMap(commonLabels). SetOwnerReferences(instance.OteldTemplate.APIVersion, instance.OteldTemplate.Kind, instance.OteldTemplate). GetObject(), nil } func buildSecretForOteld(_ *types.Config, instance *types.OteldInstance, namespace string, exporters *types.Exporters, gc *types.OteldConfigGenerater) (*corev1.Secret, error) { - if instance == nil || instance.OteldTemplate == nil || !instance.OteldTemplate.Spec.UseConfigMap { + if instance == nil || instance.OteldTemplate == nil { return nil, nil } - name := fmt.Sprintf(OteldConfigMapNamePattern, instance.OteldTemplate.Spec.Mode) + name := fmt.Sprintf(OteldSecretNamePattern, instance.OteldTemplate.Spec.Mode) commonLabels := map[string]string{ constant.AppManagedByLabelKey: constant.AppName, diff --git a/controllers/monitor/types/otel_config.go b/controllers/monitor/types/otel_config.go index b2e6a125310e..9c565c0b7b14 100644 --- a/controllers/monitor/types/otel_config.go +++ b/controllers/monitor/types/otel_config.go @@ -49,7 +49,7 @@ func (cg *OteldConfigGenerater) GenerateOteldConfiguration(instance *OteldInstan if instance == nil || instance.OteldTemplate == nil { return nil, nil } - if cg.cache == nil && cg.cache[instance.OteldTemplate.Spec.Mode] != nil { + if cg.cache != nil && cg.cache[instance.OteldTemplate.Spec.Mode] != nil { return cg.cache[instance.OteldTemplate.Spec.Mode], nil } cfg := yaml.MapSlice{} @@ -110,7 +110,7 @@ func newReceiverCreator(name string, datasourceType v1alpha1.DataSourceType, rec for name, params := range receiverMap { tplName := fmt.Sprintf(CUEPathPattern, datasourceType, name) valueMap := map[string]any{} - if params.Parameter != "" { + if params.CollectionInterval != "" { valueMap["collection_interval"] = params.CollectionInterval } builder.MergeValMapFromYamlStr(valueMap, params.Parameter) diff --git a/controllers/monitor/types/otel_config_test.go b/controllers/monitor/types/otel_config_test.go index 3e52689fe0ec..d4eefac629bf 100644 --- a/controllers/monitor/types/otel_config_test.go +++ b/controllers/monitor/types/otel_config_test.go @@ -68,7 +68,7 @@ func fakeInstance() *OteldInstance { { Name: "metrics", ReceiverMap: map[string]Receiver{ - "apecloudmysql": {}, + "apecloudmysql": {Parameter: "endpoint: test5"}, "apecloudkubeletstats": {}, "apecloudnode": {}, }, diff --git a/controllers/monitor/types/pipline.go b/controllers/monitor/types/pipline.go index 8bf61989fe10..f0f6dda77080 100644 --- a/controllers/monitor/types/pipline.go +++ b/controllers/monitor/types/pipline.go @@ -54,7 +54,7 @@ func NewPipline() Pipline { func NewOteldInstance() *OteldInstance { return &OteldInstance{ - MetricsPipline: []Pipline{NewPipline()}, - LogsPipline: []Pipline{NewPipline()}, + MetricsPipline: []Pipline{}, + LogsPipline: []Pipline{}, } } diff --git a/controllers/monitor/types/types.go b/controllers/monitor/types/types.go index 53cfbc7f3e78..c770f50f8ff0 100644 --- a/controllers/monitor/types/types.go +++ b/controllers/monitor/types/types.go @@ -21,7 +21,6 @@ package types import ( "context" - "github.com/go-logr/logr" "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/tools/record" @@ -36,17 +35,17 @@ type OTeldParams struct { Client client.Client Scheme *runtime.Scheme Recorder record.EventRecorder +} - ConfigGenerator *OteldConfigGenerater +type OteldConfig struct { + OteldInstanceMap map[v1alpha1.Mode]*OteldInstance + Exporters *Exporters + ConfigGenerator *OteldConfigGenerater } -//type OteldConfig struct { -// AsMap yaml.MapSlice -//} -// -//type OteldCfgRef struct { -// Config *OteldConfig -//} +type OteldCfgRef struct { + Config *OteldConfig +} // ReconcileCtx wrapper for reconcile procedure context parameters type ReconcileCtx struct { @@ -56,47 +55,64 @@ type ReconcileCtx struct { Config *Config Namespace string - //OteldCfgRef *OteldCfgRef - OteldInstanceMap map[v1alpha1.Mode]*OteldInstance - Exporters *Exporters + OteldCfgRef *OteldCfgRef } -//func (c *ReconcileCtx) SetOteldConfig(configAsMap yaml.MapSlice) { -// if c.OteldCfgRef == nil { -// c.OteldCfgRef = &OteldCfgRef{} -// } -// c.OteldCfgRef.Config = &OteldConfig{AsMap: configAsMap} -//} -// -//func (c *ReconcileCtx) GetOteldConfigYaml() ([]byte, error) { -// if c.OteldCfgRef == nil || -// c.OteldCfgRef.Config == nil || -// c.OteldCfgRef.Config.AsMap == nil { -// return nil, cfgcore.MakeError("not found oteld config") -// } -// return yaml.Marshal(c.OteldCfgRef.Config.AsMap) -//} - -func (c *ReconcileCtx) SetOteldInstance(mode v1alpha1.Mode, instance *OteldInstance) { - if c.OteldInstanceMap == nil { - c.OteldInstanceMap = make(map[v1alpha1.Mode]*OteldInstance) +func (c *ReconcileCtx) SetConfigGenerator(cg *OteldConfigGenerater) { + if c.OteldCfgRef == nil { + c.OteldCfgRef = &OteldCfgRef{} + } + if c.OteldCfgRef.Config == nil { + c.OteldCfgRef.Config = &OteldConfig{} } - c.OteldInstanceMap[mode] = instance + c.OteldCfgRef.Config.ConfigGenerator = cg } -func (c *ReconcileCtx) GetOteldInstance(mode v1alpha1.Mode) *OteldInstance { - if c.OteldInstanceMap == nil { +func (c *ReconcileCtx) GetConfigGenerator() *OteldConfigGenerater { + if c.OteldCfgRef == nil || + c.OteldCfgRef.Config == nil || + c.OteldCfgRef.Config.OteldInstanceMap == nil { return nil } - return c.OteldInstanceMap[mode] + return c.OteldCfgRef.Config.ConfigGenerator +} + +func (c *ReconcileCtx) SetOteldInstanceMap(oteldInstanceMap map[v1alpha1.Mode]*OteldInstance) { + if c.OteldCfgRef == nil { + c.OteldCfgRef = &OteldCfgRef{} + } + if c.OteldCfgRef.Config == nil { + c.OteldCfgRef.Config = &OteldConfig{} + } + c.OteldCfgRef.Config.OteldInstanceMap = oteldInstanceMap +} + +func (c *ReconcileCtx) GetOteldConfig() (map[v1alpha1.Mode]*OteldInstance, error) { + if c.OteldCfgRef == nil || + c.OteldCfgRef.Config == nil || + c.OteldCfgRef.Config.OteldInstanceMap == nil { + return nil, cfgcore.MakeError("not found oteld config") + } + return c.OteldCfgRef.Config.OteldInstanceMap, nil } func (c *ReconcileCtx) SetExporters(exporters *Exporters) { - c.Exporters = exporters + if c.OteldCfgRef == nil { + c.OteldCfgRef = &OteldCfgRef{} + } + if c.OteldCfgRef.Config == nil { + c.OteldCfgRef.Config = &OteldConfig{} + } + c.OteldCfgRef.Config.Exporters = exporters } func (c *ReconcileCtx) GetExporters() *Exporters { - return c.Exporters + if c.OteldCfgRef == nil || + c.OteldCfgRef.Config == nil || + c.OteldCfgRef.Config.Exporters == nil { + return nil + } + return c.OteldCfgRef.Config.Exporters } func (c *ReconcileCtx) VerifyOteldInstance(metricsExporterList *v1alpha1.MetricsExporterSinkList, logsExporterList *v1alpha1.LogsExporterSinkList) error { @@ -109,11 +125,11 @@ func (c *ReconcileCtx) VerifyOteldInstance(metricsExporterList *v1alpha1.Metrics logMap[string(lExporter.Spec.Type)] = true } - for _, instance := range c.OteldInstanceMap { + for _, instance := range c.OteldCfgRef.Config.OteldInstanceMap { if instance.MetricsPipline != nil { for _, pipline := range instance.MetricsPipline { for key, _ := range pipline.ExporterMap { - if _, ok := logMap[key]; !ok { + if _, ok := metricsMap[key]; !ok { return cfgcore.MakeError("not found exporter %s", key) } } @@ -132,8 +148,11 @@ func (c *ReconcileCtx) VerifyOteldInstance(metricsExporterList *v1alpha1.Metrics return nil } -func (c *ReconcileCtx) SetOteldInstanceMap(instanceMap map[v1alpha1.Mode]*OteldInstance) { - c.OteldInstanceMap = instanceMap +func (c *ReconcileCtx) GetOteldInstance(mode v1alpha1.Mode) *OteldInstance { + if c.OteldCfgRef == nil || c.OteldCfgRef.Config == nil || c.OteldCfgRef.Config.OteldInstanceMap == nil { + return nil + } + return c.OteldCfgRef.Config.OteldInstanceMap[mode] } type ReconcileTask interface { @@ -159,10 +178,12 @@ func NewReconcileTask(name string, task ReconcileFunc) ReconcileTask { } newTask := func(reqCtx ReconcileCtx) error { reqCtx = ReconcileCtx{ - Ctx: reqCtx.Ctx, - Req: reqCtx.Req, - Log: reqCtx.Log.WithValues("subTask", name), - Config: reqCtx.Config, + Ctx: reqCtx.Ctx, + Req: reqCtx.Req, + Log: reqCtx.Log.WithValues("subTask", name), + Config: reqCtx.Config, + Namespace: reqCtx.Namespace, + OteldCfgRef: reqCtx.OteldCfgRef, } return task(reqCtx) } diff --git a/controllers/monitor/types/types_suite_test.go b/controllers/monitor/types/types_suite_test.go new file mode 100644 index 000000000000..3356638fa6ca --- /dev/null +++ b/controllers/monitor/types/types_suite_test.go @@ -0,0 +1,13 @@ +package types_test + +import ( + "testing" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +func TestTypes(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "Types Suite") +} diff --git a/deploy/helm/crds/monitor.kubeblocks.io_collectordatasources.yaml b/deploy/helm/crds/monitor.kubeblocks.io_collectordatasources.yaml index beaa0e4f271f..266ff831ff87 100644 --- a/deploy/helm/crds/monitor.kubeblocks.io_collectordatasources.yaml +++ b/deploy/helm/crds/monitor.kubeblocks.io_collectordatasources.yaml @@ -67,16 +67,12 @@ spec: - sidecar - statefulset type: string - name: - description: Name is the name of the data source - type: string type: description: Type is the type of the data source type: string required: - dataSourceList - exporterRef - - name - type type: object status: diff --git a/deploy/helm/crds/monitor.kubeblocks.io_metricsexportersinks.yaml b/deploy/helm/crds/monitor.kubeblocks.io_metricsexportersinks.yaml index 6bfd2f486e6f..38d24321a88f 100644 --- a/deploy/helm/crds/monitor.kubeblocks.io_metricsexportersinks.yaml +++ b/deploy/helm/crds/monitor.kubeblocks.io_metricsexportersinks.yaml @@ -37,14 +37,6 @@ spec: spec: description: MetricsExporterSinkSpec defines the desired state of MetricsExporterSink properties: - mode: - description: mode defines the mode of the exporterSink - enum: - - daemonset - - deployment - - sidecar - - statefulset - type: string prometheusConfig: description: lokiConfig defines the config of the loki properties: