diff --git a/Makefile b/Makefile index d6b5422c8b..cdb74f546d 100644 --- a/Makefile +++ b/Makefile @@ -152,9 +152,13 @@ shellcheck: install-crds: generate-crds kubectl apply -f $(ALL_CRDS) +# Install roles that operator expects to be present by default. +install-roles: + kubectl apply -f ./config/operator/all-in-one/beat-roles.yaml + # Run locally against the configured Kubernetes cluster, with port-forwarding enabled so that # the operator can reach services running in the cluster through k8s port-forward feature -run: install-crds go-run +run: install-crds install-roles go-run go-run: # Run the operator locally with debug logs and operator image set to latest diff --git a/cmd/manager/main.go b/cmd/manager/main.go index 6886035c99..06df2f17b4 100644 --- a/cmd/manager/main.go +++ b/cmd/manager/main.go @@ -24,6 +24,8 @@ import ( "github.com/elastic/cloud-on-k8s/pkg/controller/apmserver" "github.com/elastic/cloud-on-k8s/pkg/controller/association" associationctl "github.com/elastic/cloud-on-k8s/pkg/controller/association/controller" + "github.com/elastic/cloud-on-k8s/pkg/controller/beat" + beatcommon "github.com/elastic/cloud-on-k8s/pkg/controller/beat/common" "github.com/elastic/cloud-on-k8s/pkg/controller/common/certificates" "github.com/elastic/cloud-on-k8s/pkg/controller/common/container" "github.com/elastic/cloud-on-k8s/pkg/controller/common/operator" @@ -166,6 +168,11 @@ func init() { "", fmt.Sprintf("K8s secret mounted into the path designated by %s to be used for webhook certificates", operator.WebhookCertDirFlag), ) + Cmd.Flags().Bool( + operator.ManageBeatAutodiscoverRBACFlag, + true, + "Determines whether the operator should set up bindings and service accounts for the Beats autodiscover feature", + ) // enable using dashed notation in flags and underscores in env viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_")) @@ -250,6 +257,8 @@ func execute() { CertDir: viper.GetString(operator.WebhookCertDirFlag), } + manageBeatAutodiscoverRBAC := viper.GetBool(operator.ManageBeatAutodiscoverRBACFlag) + // configure the manager cache based on the number of managed namespaces managedNamespaces := viper.GetStringSlice(operator.NamespacesFlag) switch { @@ -260,8 +269,15 @@ func execute() { opts.Namespace = managedNamespaces[0] default: log.Info("Operator configured to manage multiple namespaces", "namespaces", managedNamespaces, "operator_namespace", operatorNamespace) - // always include the operator namespace into the manager cache so that we can work with operator-internal resources in there - opts.NewCache = cache.MultiNamespacedCacheBuilder(append(managedNamespaces, operatorNamespace)) + // the manager cache should always include the operator namespace so that we can work with operator-internal resources + cachedNamespaces := append(managedNamespaces, operatorNamespace) + + // include empty namespace so that we can work with cluster-wide (non-namespaced) resources needed with autodiscover + if manageBeatAutodiscoverRBAC { + cachedNamespaces = append(cachedNamespaces, "") + } + + opts.NewCache = cache.MultiNamespacedCacheBuilder(cachedNamespaces) } // only expose prometheus metrics if provided a non-zero port @@ -330,6 +346,10 @@ func execute() { accessReviewer = rbac.NewPermissiveAccessReviewer() } + if manageBeatAutodiscoverRBAC { + beatcommon.EnableAutodiscoverRBACManagement() + } + if err = apmserver.Add(mgr, params); err != nil { log.Error(err, "unable to create controller", "controller", "ApmServer") os.Exit(1) @@ -346,6 +366,10 @@ func execute() { log.Error(err, "unable to create controller", "controller", "EnterpriseSearch") os.Exit(1) } + if err = beat.Add(mgr, params); err != nil { + log.Error(err, "unable to create controller", "controller", "Beat") + os.Exit(1) + } if err = associationctl.AddApmES(mgr, accessReviewer, params); err != nil { log.Error(err, "unable to create controller", "controller", "apm-es-association") os.Exit(1) @@ -362,6 +386,11 @@ func execute() { log.Error(err, "unable to create controller", "controller", "ent-es-association") os.Exit(1) } + if err = associationctl.AddBeatES(mgr, accessReviewer, params); err != nil { + log.Error(err, "unable to create controller", "controller", "beat-es-association") + os.Exit(1) + } + if err = remoteca.Add(mgr, accessReviewer, params); err != nil { log.Error(err, "unable to create controller", "controller", "RemoteClusterCertificateAuthorites") os.Exit(1) diff --git a/config/crds/all-crds.yaml b/config/crds/all-crds.yaml index 0885a3fff6..7da53c175f 100644 --- a/config/crds/all-crds.yaml +++ b/config/crds/all-crds.yaml @@ -457,6 +457,151 @@ status: --- apiVersion: apiextensions.k8s.io/v1beta1 kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.2.5 + creationTimestamp: null + name: beats.beat.k8s.elastic.co +spec: + additionalPrinterColumns: + - JSONPath: .status.health + name: health + type: string + - JSONPath: .status.availableNodes + description: Available nodes + name: available + type: integer + - JSONPath: .status.expectedNodes + description: Expected nodes + name: expected + type: integer + - JSONPath: .spec.type + description: Beat type + name: type + type: string + - JSONPath: .spec.version + description: Beat version + name: version + type: string + - JSONPath: .metadata.creationTimestamp + name: age + type: date + group: beat.k8s.elastic.co + names: + categories: + - elastic + kind: Beat + listKind: BeatList + plural: beats + shortNames: + - beat + singular: beat + scope: Namespaced + subresources: + status: {} + validation: + openAPIV3Schema: + description: Beat is the Schema for the Beats 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: BeatSpec defines the desired state of a Beat. + properties: + config: + description: Config holds the Beat configuration. If provided, it will + override the default configuration. + type: object + daemonSet: + description: DaemonSet specifies the Beat should be deployed as a DaemonSet, + and allows providing its spec. Cannot be used along with `deployment`. + If both are absent a default for the Type is used. + properties: {} + type: object + deployment: + description: Deployment specifies the Beat should be deployed as a Deployment, + and allows providing its spec. Cannot be used along with `daemonSet`. + If both are absent a default for the Type is used. + properties: + replicas: + format: int32 + type: integer + type: object + elasticsearchRef: + description: ElasticsearchRef is a reference to an Elasticsearch cluster + running in the same Kubernetes cluster. + properties: + name: + description: Name of the Kubernetes object. + type: string + namespace: + description: Namespace of the Kubernetes object. If empty, defaults + to the current namespace. + type: string + required: + - name + type: object + image: + description: Image is the Beat Docker image to deploy. Version and Type + have to match the Beat in the image. + type: string + serviceAccountName: + description: ServiceAccountName is used to check access from the current + resource to Elasticsearch resource in a different namespace. Can only + be used if ECK is enforcing RBAC on references. + type: string + type: + description: Type is the type of the Beat to deploy (filebeat, metricbeat, + etc.). Any string can be used, but well-known types will be recognized + and will allow to provide sane default configurations. + maxLength: 20 + type: string + version: + description: Version of the Beat. + type: string + required: + - type + - version + type: object + status: + description: BeatStatus defines the observed state of a Beat. + properties: + associationStatus: + description: AssociationStatus is the status of an association resource. + type: string + availableNodes: + format: int32 + type: integer + expectedNodes: + format: int32 + type: integer + health: + type: string + type: object + version: v1beta1 + versions: + - name: v1beta1 + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.2.5 diff --git a/config/crds/bases/beat.k8s.elastic.co_beats.yaml b/config/crds/bases/beat.k8s.elastic.co_beats.yaml new file mode 100644 index 0000000000..7d3c513864 --- /dev/null +++ b/config/crds/bases/beat.k8s.elastic.co_beats.yaml @@ -0,0 +1,12207 @@ + +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.2.5 + creationTimestamp: null + name: beats.beat.k8s.elastic.co +spec: + additionalPrinterColumns: + - JSONPath: .status.health + name: health + type: string + - JSONPath: .status.availableNodes + description: Available nodes + name: available + type: integer + - JSONPath: .status.expectedNodes + description: Expected nodes + name: expected + type: integer + - JSONPath: .spec.type + description: Beat type + name: type + type: string + - JSONPath: .spec.version + description: Beat version + name: version + type: string + - JSONPath: .metadata.creationTimestamp + name: age + type: date + group: beat.k8s.elastic.co + names: + categories: + - elastic + kind: Beat + listKind: BeatList + plural: beats + shortNames: + - beat + singular: beat + scope: Namespaced + subresources: + status: {} + validation: + openAPIV3Schema: + description: Beat is the Schema for the Beats 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: BeatSpec defines the desired state of a Beat. + properties: + config: + description: Config holds the Beat configuration. If provided, it will + override the default configuration. + type: object + daemonSet: + description: DaemonSet specifies the Beat should be deployed as a DaemonSet, + and allows providing its spec. Cannot be used along with `deployment`. + If both are absent a default for the Type is used. + properties: + podTemplate: + description: PodTemplateSpec describes the data a pod should have + when created from a template + properties: + metadata: + description: 'Standard object''s metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata' + type: object + spec: + description: 'Specification of the desired behavior of the pod. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status' + properties: + activeDeadlineSeconds: + description: Optional duration in seconds the pod may be + active on the node relative to StartTime before the system + will actively try to mark it failed and kill associated + containers. Value must be a positive integer. + format: int64 + type: integer + affinity: + description: If specified, the pod's scheduling constraints + properties: + nodeAffinity: + description: Describes node affinity scheduling rules + for the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule + pods to nodes that satisfy the affinity expressions + specified by this field, but it may choose a node + that violates one or more of the expressions. + The node that is most preferred is the one with + the greatest sum of weights, i.e. for each node + that meets all of the scheduling requirements + (resource request, requiredDuringScheduling affinity + expressions, etc.), compute a sum by iterating + through the elements of this field and adding + "weight" to the sum if the node matches the corresponding + matchExpressions; the node(s) with the highest + sum are the most preferred. + items: + description: An empty preferred scheduling term + matches all objects with implicit weight 0 (i.e. + it's a no-op). A null preferred scheduling term + matches no objects (i.e. is also a no-op). + properties: + preference: + description: A node selector term, associated + with the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that + the selector applies to. + type: string + operator: + description: Represents a key's + relationship to a set of values. + Valid operators are In, NotIn, + Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: 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. If + the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that + the selector applies to. + type: string + operator: + description: Represents a key's + relationship to a set of values. + Valid operators are In, NotIn, + Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: 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. If + the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + description: Weight associated with matching + the corresponding nodeSelectorTerm, in the + range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified + by this field are not met at scheduling time, + the pod will not be scheduled onto the node. If + the affinity requirements specified by this field + cease to be met at some point during pod execution + (e.g. due to an update), the system may or may + not try to eventually evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector + terms. The terms are ORed. + items: + description: A null or empty node selector + term matches no objects. The requirements + of them are ANDed. The TopologySelectorTerm + type implements a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that + the selector applies to. + type: string + operator: + description: Represents a key's + relationship to a set of values. + Valid operators are In, NotIn, + Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: 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. If + the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that + the selector applies to. + type: string + operator: + description: Represents a key's + relationship to a set of values. + Valid operators are In, NotIn, + Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: 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. If + the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object + type: object + podAffinity: + description: Describes pod affinity scheduling rules + (e.g. co-locate this pod in the same node, zone, etc. + as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule + pods to nodes that satisfy the affinity expressions + specified by this field, but it may choose a node + that violates one or more of the expressions. + The node that is most preferred is the one with + the greatest sum of weights, i.e. for each node + that meets all of the scheduling requirements + (resource request, requiredDuringScheduling affinity + expressions, etc.), compute a sum by iterating + through the elements of this field and adding + "weight" to the sum if the node has pods which + matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched + WeightedPodAffinityTerm fields are added per-node + to find the most preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, + associated with the corresponding weight. + properties: + labelSelector: + description: A label query over a set + of resources, in this case pods. + 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 + namespaces: + description: namespaces specifies which + namespaces the labelSelector applies + to (matches against); null or empty + list means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector + in the specified namespaces, where co-located + is defined as running on a node whose + value of the label with key topologyKey + matches that of any node on which any + of the selected pods is running. Empty + topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching + the corresponding podAffinityTerm, in the + range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified + by this field are not met at scheduling time, + the pod will not be scheduled onto the node. If + the affinity requirements specified by this field + cease to be met at some point during pod execution + (e.g. due to a pod label update), the system may + or may not try to eventually evict the pod from + its node. When there are multiple elements, the + lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those + matching the labelSelector relative to the given + namespace(s)) that this pod should be co-located + (affinity) or not co-located (anti-affinity) + with, where co-located is defined as running + on a node whose value of the label with key + matches that of any node on which + a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + namespaces: + description: namespaces specifies which namespaces + the labelSelector applies to (matches against); + null or empty list means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector + in the specified namespaces, where co-located + is defined as running on a node whose value + of the label with key topologyKey matches + that of any node on which any of the selected + pods is running. Empty topologyKey is not + allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling + rules (e.g. avoid putting this pod in the same node, + zone, etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule + pods to nodes that satisfy the anti-affinity expressions + specified by this field, but it may choose a node + that violates one or more of the expressions. + The node that is most preferred is the one with + the greatest sum of weights, i.e. for each node + that meets all of the scheduling requirements + (resource request, requiredDuringScheduling anti-affinity + expressions, etc.), compute a sum by iterating + through the elements of this field and adding + "weight" to the sum if the node has pods which + matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched + WeightedPodAffinityTerm fields are added per-node + to find the most preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, + associated with the corresponding weight. + properties: + labelSelector: + description: A label query over a set + of resources, in this case pods. + 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 + namespaces: + description: namespaces specifies which + namespaces the labelSelector applies + to (matches against); null or empty + list means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector + in the specified namespaces, where co-located + is defined as running on a node whose + value of the label with key topologyKey + matches that of any node on which any + of the selected pods is running. Empty + topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching + the corresponding podAffinityTerm, in the + range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified + by this field are not met at scheduling time, + the pod will not be scheduled onto the node. If + the anti-affinity requirements specified by this + field cease to be met at some point during pod + execution (e.g. due to a pod label update), the + system may or may not try to eventually evict + the pod from its node. When there are multiple + elements, the lists of nodes corresponding to + each podAffinityTerm are intersected, i.e. all + terms must be satisfied. + items: + description: Defines a set of pods (namely those + matching the labelSelector relative to the given + namespace(s)) that this pod should be co-located + (affinity) or not co-located (anti-affinity) + with, where co-located is defined as running + on a node whose value of the label with key + matches that of any node on which + a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + namespaces: + description: namespaces specifies which namespaces + the labelSelector applies to (matches against); + null or empty list means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector + in the specified namespaces, where co-located + is defined as running on a node whose value + of the label with key topologyKey matches + that of any node on which any of the selected + pods is running. Empty topologyKey is not + allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + automountServiceAccountToken: + description: AutomountServiceAccountToken indicates whether + a service account token should be automatically mounted. + type: boolean + containers: + description: List of containers belonging to the pod. Containers + cannot currently be added or removed. There must be at + least one container in a Pod. Cannot be updated. + items: + description: A single application container that you want + to run within a pod. + properties: + args: + description: 'Arguments to the entrypoint. The docker + image''s CMD is used if this is not provided. Variable + references $(VAR_NAME) are expanded using the container''s + environment. If a variable cannot be resolved, the + reference in the input string will be unchanged. + The $(VAR_NAME) syntax can be escaped with a double + $$, ie: $$(VAR_NAME). Escaped references will never + be expanded, regardless of whether the variable + exists or not. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell' + items: + type: string + type: array + command: + description: 'Entrypoint array. Not executed within + a shell. The docker image''s ENTRYPOINT is used + if this is not provided. Variable references $(VAR_NAME) + are expanded using the container''s environment. + If a variable cannot be resolved, the reference + in the input string will be unchanged. The $(VAR_NAME) + syntax can be escaped with a double $$, ie: $$(VAR_NAME). + Escaped references will never be expanded, regardless + of whether the variable exists or not. Cannot be + updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell' + items: + type: string + type: array + env: + description: List of environment variables to set + in the container. Cannot be updated. + 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 previous 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. The $(VAR_NAME) syntax + can be escaped with a double $$, ie: $$(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 + envFrom: + description: List of sources to populate environment + variables in the container. The keys defined within + a source must be a C_IDENTIFIER. All invalid keys + will be reported as an event when the container + is starting. When a key exists in multiple sources, + the value associated with the last source will take + precedence. Values defined by an Env with a duplicate + key will take precedence. Cannot be updated. + items: + description: EnvFromSource represents the source + of a set of ConfigMaps + properties: + configMapRef: + description: The ConfigMap to select from + 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 + optional: + description: Specify whether the ConfigMap + must be defined + type: boolean + type: object + prefix: + description: An optional identifier to prepend + to each key in the ConfigMap. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + 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 + optional: + description: Specify whether the Secret + must be defined + type: boolean + type: object + type: object + type: array + image: + description: 'Docker image name. More info: https://kubernetes.io/docs/concepts/containers/images + This field is optional to allow higher level config + management to default or override container images + in workload controllers like Deployments and StatefulSets.' + type: string + imagePullPolicy: + description: 'Image pull policy. One of Always, Never, + IfNotPresent. Defaults to Always if :latest tag + is specified, or IfNotPresent otherwise. Cannot + be updated. More info: https://kubernetes.io/docs/concepts/containers/images#updating-images' + type: string + lifecycle: + description: Actions that the management system should + take in response to container lifecycle events. + Cannot be updated. + properties: + postStart: + description: 'PostStart is called immediately + after a container is created. If the handler + fails, the container is terminated and restarted + according to its restart policy. Other management + of the container blocks until the hook completes. + More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks' + properties: + exec: + description: One and only one of the following + should be specified. Exec specifies the + action to take. + properties: + command: + description: Command is the command line + to execute inside the container, the + working directory for the command is + root ('/') in the container's filesystem. + The command is simply exec'd, it is + not run inside a shell, so traditional + shell instructions ('|', etc) won't + work. To use a shell, you need to explicitly + call out to that shell. Exit status + of 0 is treated as live/healthy and + non-zero is unhealthy. + items: + type: string + type: array + type: object + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, + defaults to the pod IP. You probably + want to set "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in + the request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a + custom header to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port + to access on the container. Number must + be in the range 1 to 65535. Name must + be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting + to the host. Defaults to HTTP. + type: string + required: + - port + type: object + tcpSocket: + description: 'TCPSocket specifies an action + involving a TCP port. TCP hooks not yet + supported TODO: implement a realistic TCP + lifecycle hook' + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port + to access on the container. Number must + be in the range 1 to 65535. Name must + be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + description: 'PreStop is called immediately before + a container is terminated due to an API request + or management event such as liveness/startup + probe failure, preemption, resource contention, + etc. The handler is not called if the container + crashes or exits. The reason for termination + is passed to the handler. The Pod''s termination + grace period countdown begins before the PreStop + hooked is executed. Regardless of the outcome + of the handler, the container will eventually + terminate within the Pod''s termination grace + period. Other management of the container blocks + until the hook completes or until the termination + grace period is reached. More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks' + properties: + exec: + description: One and only one of the following + should be specified. Exec specifies the + action to take. + properties: + command: + description: Command is the command line + to execute inside the container, the + working directory for the command is + root ('/') in the container's filesystem. + The command is simply exec'd, it is + not run inside a shell, so traditional + shell instructions ('|', etc) won't + work. To use a shell, you need to explicitly + call out to that shell. Exit status + of 0 is treated as live/healthy and + non-zero is unhealthy. + items: + type: string + type: array + type: object + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, + defaults to the pod IP. You probably + want to set "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in + the request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a + custom header to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port + to access on the container. Number must + be in the range 1 to 65535. Name must + be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting + to the host. Defaults to HTTP. + type: string + required: + - port + type: object + tcpSocket: + description: 'TCPSocket specifies an action + involving a TCP port. TCP hooks not yet + supported TODO: implement a realistic TCP + lifecycle hook' + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port + to access on the container. Number must + be in the range 1 to 65535. Name must + be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + type: object + livenessProbe: + description: 'Periodic probe of container liveness. + Container will be restarted if the probe fails. + Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + properties: + exec: + description: One and only one of the following + should be specified. Exec specifies the action + to take. + properties: + command: + description: Command is the command line to + execute inside the container, the working + directory for the command is root ('/') + in the container's filesystem. The command + is simply exec'd, it is not run inside a + shell, so traditional shell instructions + ('|', etc) won't work. To use a shell, you + need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy + and non-zero is unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for + the probe to be considered failed after having + succeeded. Defaults to 3. Minimum value is 1. + format: int32 + type: integer + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, defaults + to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to + access on the container. Number must be + in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting + to the host. Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container + has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform + the probe. Default to 10 seconds. Minimum value + is 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for + the probe to be considered successful after + having failed. Defaults to 1. Must be 1 for + liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: 'TCPSocket specifies an action involving + a TCP port. TCP hooks not yet supported TODO: + implement a realistic TCP lifecycle hook' + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to + access on the container. Number must be + in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + timeoutSeconds: + description: 'Number of seconds after which the + probe times out. Defaults to 1 second. Minimum + value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + name: + description: Name of the container specified as a + DNS_LABEL. Each container in a pod must have a unique + name (DNS_LABEL). Cannot be updated. + type: string + ports: + description: List of ports to expose from the container. + Exposing a port here gives the system additional + information about the network connections a container + uses, but is primarily informational. Not specifying + a port here DOES NOT prevent that port from being + exposed. Any port which is listening on the default + "0.0.0.0" address inside a container will be accessible + from the network. Cannot be updated. + items: + description: ContainerPort represents a network + port in a single container. + properties: + containerPort: + description: Number of port to expose on the + pod's IP address. This must be a valid port + number, 0 < x < 65536. + format: int32 + type: integer + hostIP: + description: What host IP to bind the external + port to. + type: string + hostPort: + description: Number of port to expose on the + host. If specified, this must be a valid port + number, 0 < x < 65536. If HostNetwork is specified, + this must match ContainerPort. Most containers + do not need this. + format: int32 + type: integer + name: + description: If specified, this must be an IANA_SVC_NAME + and unique within the pod. Each named port + in a pod must have a unique name. Name for + the port that can be referred to by services. + type: string + protocol: + description: Protocol for port. Must be UDP, + TCP, or SCTP. Defaults to "TCP". + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + description: 'Periodic probe of container service + readiness. Container will be removed from service + endpoints if the probe fails. Cannot be updated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + properties: + exec: + description: One and only one of the following + should be specified. Exec specifies the action + to take. + properties: + command: + description: Command is the command line to + execute inside the container, the working + directory for the command is root ('/') + in the container's filesystem. The command + is simply exec'd, it is not run inside a + shell, so traditional shell instructions + ('|', etc) won't work. To use a shell, you + need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy + and non-zero is unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for + the probe to be considered failed after having + succeeded. Defaults to 3. Minimum value is 1. + format: int32 + type: integer + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, defaults + to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to + access on the container. Number must be + in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting + to the host. Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container + has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform + the probe. Default to 10 seconds. Minimum value + is 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for + the probe to be considered successful after + having failed. Defaults to 1. Must be 1 for + liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: 'TCPSocket specifies an action involving + a TCP port. TCP hooks not yet supported TODO: + implement a realistic TCP lifecycle hook' + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to + access on the container. Number must be + in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + timeoutSeconds: + description: 'Number of seconds after which the + probe times out. Defaults to 1 second. Minimum + value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + resources: + description: 'Compute Resources required by this container. + Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + properties: + 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-compute-resources-container/' + 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-compute-resources-container/' + type: object + type: object + securityContext: + description: 'Security options the pod should run + with. More info: https://kubernetes.io/docs/concepts/policy/security-context/ + More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/' + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls + whether a process can gain more privileges than + its parent process. This bool directly controls + if the no_new_privs flag will be set on the + container process. AllowPrivilegeEscalation + is true always when the container is: 1) run + as Privileged 2) has CAP_SYS_ADMIN' + type: boolean + capabilities: + description: The capabilities to add/drop when + running containers. Defaults to the default + set of capabilities granted by the container + runtime. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX + capabilities type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX + capabilities type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. + Processes in privileged containers are essentially + equivalent to root on the host. Defaults to + false. + type: boolean + procMount: + description: procMount denotes the type of proc + mount to use for the containers. The default + is DefaultProcMount which uses the container + runtime defaults for readonly paths and masked + paths. This requires the ProcMountType feature + flag to be enabled. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only + root filesystem. Default is false. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of + the container process. Uses runtime default + if unset. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes + precedence. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must + run as a non-root user. If true, the Kubelet + will validate the image at runtime to ensure + that it does not run as UID 0 (root) and fail + to start the container if it does. If unset + or false, no such validation will be performed. + May also be set in PodSecurityContext. If set + in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes + precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of + the container process. Defaults to user specified + in image metadata if unspecified. May also be + set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified + in SecurityContext takes precedence. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied + to the container. If unspecified, the container + runtime will allocate a random SELinux context + for each container. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes + precedence. + properties: + level: + description: Level is SELinux level label + that applies to the container. + type: string + role: + description: Role is a SELinux role label + that applies to the container. + type: string + type: + description: Type is a SELinux type label + that applies to the container. + type: string + user: + description: User is a SELinux user label + that applies to the container. + type: string + type: object + windowsOptions: + description: The Windows specific settings applied + to all containers. If unspecified, the options + from the PodSecurityContext will be used. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes + precedence. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the + GMSA admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential + spec named by the GMSACredentialSpecName + field. This field is alpha-level and is + only honored by servers that enable the + WindowsGMSA feature flag. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the + name of the GMSA credential spec to use. + This field is alpha-level and is only honored + by servers that enable the WindowsGMSA feature + flag. + type: string + runAsUserName: + description: The UserName in Windows to run + the entrypoint of the container process. + Defaults to the user specified in image + metadata if unspecified. May also be set + in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified + in SecurityContext takes precedence. This + field is beta-level and may be disabled + with the WindowsRunAsUserName feature flag. + type: string + type: object + type: object + startupProbe: + description: 'StartupProbe indicates that the Pod + has successfully initialized. If specified, no other + probes are executed until this completes successfully. + If this probe fails, the Pod will be restarted, + just as if the livenessProbe failed. This can be + used to provide different probe parameters at the + beginning of a Pod''s lifecycle, when it might take + a long time to load data or warm a cache, than during + steady-state operation. This cannot be updated. + This is an alpha feature enabled by the StartupProbe + feature flag. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + properties: + exec: + description: One and only one of the following + should be specified. Exec specifies the action + to take. + properties: + command: + description: Command is the command line to + execute inside the container, the working + directory for the command is root ('/') + in the container's filesystem. The command + is simply exec'd, it is not run inside a + shell, so traditional shell instructions + ('|', etc) won't work. To use a shell, you + need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy + and non-zero is unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for + the probe to be considered failed after having + succeeded. Defaults to 3. Minimum value is 1. + format: int32 + type: integer + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, defaults + to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to + access on the container. Number must be + in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting + to the host. Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container + has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform + the probe. Default to 10 seconds. Minimum value + is 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for + the probe to be considered successful after + having failed. Defaults to 1. Must be 1 for + liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: 'TCPSocket specifies an action involving + a TCP port. TCP hooks not yet supported TODO: + implement a realistic TCP lifecycle hook' + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to + access on the container. Number must be + in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + timeoutSeconds: + description: 'Number of seconds after which the + probe times out. Defaults to 1 second. Minimum + value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + stdin: + description: Whether this container should allocate + a buffer for stdin in the container runtime. If + this is not set, reads from stdin in the container + will always result in EOF. Default is false. + type: boolean + stdinOnce: + description: Whether the container runtime should + close the stdin channel after it has been opened + by a single attach. When stdin is true the stdin + stream will remain open across multiple attach sessions. + If stdinOnce is set to true, stdin is opened on + container start, is empty until the first client + attaches to stdin, and then remains open and accepts + data until the client disconnects, at which time + stdin is closed and remains closed until the container + is restarted. If this flag is false, a container + processes that reads from stdin will never receive + an EOF. Default is false + type: boolean + terminationMessagePath: + description: 'Optional: Path at which the file to + which the container''s termination message will + be written is mounted into the container''s filesystem. + Message written is intended to be brief final status, + such as an assertion failure message. Will be truncated + by the node if greater than 4096 bytes. The total + message length across all containers will be limited + to 12kb. Defaults to /dev/termination-log. Cannot + be updated.' + type: string + terminationMessagePolicy: + description: Indicate how the termination message + should be populated. File will use the contents + of terminationMessagePath to populate the container + status message on both success and failure. FallbackToLogsOnError + will use the last chunk of container log output + if the termination message file is empty and the + container exited with an error. The log output is + limited to 2048 bytes or 80 lines, whichever is + smaller. Defaults to File. Cannot be updated. + type: string + tty: + description: Whether this container should allocate + a TTY for itself, also requires 'stdin' to be true. + Default is false. + type: boolean + volumeDevices: + description: volumeDevices is the list of block devices + to be used by the container. This is a beta feature. + items: + description: volumeDevice describes a mapping of + a raw block device within a container. + properties: + devicePath: + description: devicePath is the path inside of + the container that the device will be mapped + to. + type: string + name: + description: name must match the name of a persistentVolumeClaim + in the pod + type: string + required: + - devicePath + - name + type: object + type: array + volumeMounts: + description: Pod volumes to mount into the container's + filesystem. Cannot be updated. + 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 + workingDir: + description: Container's working directory. If not + specified, the container runtime's default will + be used, which might be configured in the container + image. Cannot be updated. + type: string + required: + - name + type: object + type: array + dnsConfig: + description: Specifies the DNS parameters of a pod. Parameters + specified here will be merged to the generated DNS configuration + based on DNSPolicy. + properties: + nameservers: + description: A list of DNS name server IP addresses. + This will be appended to the base nameservers generated + from DNSPolicy. Duplicated nameservers will be removed. + items: + type: string + type: array + options: + description: A list of DNS resolver options. This will + be merged with the base options generated from DNSPolicy. + Duplicated entries will be removed. Resolution options + given in Options will override those that appear in + the base DNSPolicy. + items: + description: PodDNSConfigOption defines DNS resolver + options of a pod. + properties: + name: + description: Required. + type: string + value: + type: string + type: object + type: array + searches: + description: A list of DNS search domains for host-name + lookup. This will be appended to the base search paths + generated from DNSPolicy. Duplicated search paths + will be removed. + items: + type: string + type: array + type: object + dnsPolicy: + description: Set DNS policy for the pod. Defaults to "ClusterFirst". + Valid values are 'ClusterFirstWithHostNet', 'ClusterFirst', + 'Default' or 'None'. DNS parameters given in DNSConfig + will be merged with the policy selected with DNSPolicy. + To have DNS options set along with hostNetwork, you have + to specify DNS policy explicitly to 'ClusterFirstWithHostNet'. + type: string + enableServiceLinks: + description: 'EnableServiceLinks indicates whether information + about services should be injected into pod''s environment + variables, matching the syntax of Docker links. Optional: + Defaults to true.' + type: boolean + ephemeralContainers: + description: List of ephemeral containers run in this pod. + Ephemeral containers may be run in an existing pod to + perform user-initiated actions such as debugging. This + list cannot be specified when creating a pod, and it cannot + be modified by updating the pod spec. In order to add + an ephemeral container to an existing pod, use the pod's + ephemeralcontainers subresource. This field is alpha-level + and is only honored by servers that enable the EphemeralContainers + feature. + items: + description: An EphemeralContainer is a container that + may be added temporarily to an existing pod for user-initiated + activities such as debugging. Ephemeral containers have + no resource or scheduling guarantees, and they will + not be restarted when they exit or when a pod is removed + or restarted. If an ephemeral container causes a pod + to exceed its resource allocation, the pod may be evicted. + Ephemeral containers may not be added by directly updating + the pod spec. They must be added via the pod's ephemeralcontainers + subresource, and they will appear in the pod spec once + added. This is an alpha feature enabled by the EphemeralContainers + feature flag. + properties: + args: + description: 'Arguments to the entrypoint. The docker + image''s CMD is used if this is not provided. Variable + references $(VAR_NAME) are expanded using the container''s + environment. If a variable cannot be resolved, the + reference in the input string will be unchanged. + The $(VAR_NAME) syntax can be escaped with a double + $$, ie: $$(VAR_NAME). Escaped references will never + be expanded, regardless of whether the variable + exists or not. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell' + items: + type: string + type: array + command: + description: 'Entrypoint array. Not executed within + a shell. The docker image''s ENTRYPOINT is used + if this is not provided. Variable references $(VAR_NAME) + are expanded using the container''s environment. + If a variable cannot be resolved, the reference + in the input string will be unchanged. The $(VAR_NAME) + syntax can be escaped with a double $$, ie: $$(VAR_NAME). + Escaped references will never be expanded, regardless + of whether the variable exists or not. Cannot be + updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell' + items: + type: string + type: array + env: + description: List of environment variables to set + in the container. Cannot be updated. + 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 previous 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. The $(VAR_NAME) syntax + can be escaped with a double $$, ie: $$(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 + envFrom: + description: List of sources to populate environment + variables in the container. The keys defined within + a source must be a C_IDENTIFIER. All invalid keys + will be reported as an event when the container + is starting. When a key exists in multiple sources, + the value associated with the last source will take + precedence. Values defined by an Env with a duplicate + key will take precedence. Cannot be updated. + items: + description: EnvFromSource represents the source + of a set of ConfigMaps + properties: + configMapRef: + description: The ConfigMap to select from + 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 + optional: + description: Specify whether the ConfigMap + must be defined + type: boolean + type: object + prefix: + description: An optional identifier to prepend + to each key in the ConfigMap. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + 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 + optional: + description: Specify whether the Secret + must be defined + type: boolean + type: object + type: object + type: array + image: + description: 'Docker image name. More info: https://kubernetes.io/docs/concepts/containers/images' + type: string + imagePullPolicy: + description: 'Image pull policy. One of Always, Never, + IfNotPresent. Defaults to Always if :latest tag + is specified, or IfNotPresent otherwise. Cannot + be updated. More info: https://kubernetes.io/docs/concepts/containers/images#updating-images' + type: string + lifecycle: + description: Lifecycle is not allowed for ephemeral + containers. + properties: + postStart: + description: 'PostStart is called immediately + after a container is created. If the handler + fails, the container is terminated and restarted + according to its restart policy. Other management + of the container blocks until the hook completes. + More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks' + properties: + exec: + description: One and only one of the following + should be specified. Exec specifies the + action to take. + properties: + command: + description: Command is the command line + to execute inside the container, the + working directory for the command is + root ('/') in the container's filesystem. + The command is simply exec'd, it is + not run inside a shell, so traditional + shell instructions ('|', etc) won't + work. To use a shell, you need to explicitly + call out to that shell. Exit status + of 0 is treated as live/healthy and + non-zero is unhealthy. + items: + type: string + type: array + type: object + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, + defaults to the pod IP. You probably + want to set "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in + the request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a + custom header to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port + to access on the container. Number must + be in the range 1 to 65535. Name must + be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting + to the host. Defaults to HTTP. + type: string + required: + - port + type: object + tcpSocket: + description: 'TCPSocket specifies an action + involving a TCP port. TCP hooks not yet + supported TODO: implement a realistic TCP + lifecycle hook' + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port + to access on the container. Number must + be in the range 1 to 65535. Name must + be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + description: 'PreStop is called immediately before + a container is terminated due to an API request + or management event such as liveness/startup + probe failure, preemption, resource contention, + etc. The handler is not called if the container + crashes or exits. The reason for termination + is passed to the handler. The Pod''s termination + grace period countdown begins before the PreStop + hooked is executed. Regardless of the outcome + of the handler, the container will eventually + terminate within the Pod''s termination grace + period. Other management of the container blocks + until the hook completes or until the termination + grace period is reached. More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks' + properties: + exec: + description: One and only one of the following + should be specified. Exec specifies the + action to take. + properties: + command: + description: Command is the command line + to execute inside the container, the + working directory for the command is + root ('/') in the container's filesystem. + The command is simply exec'd, it is + not run inside a shell, so traditional + shell instructions ('|', etc) won't + work. To use a shell, you need to explicitly + call out to that shell. Exit status + of 0 is treated as live/healthy and + non-zero is unhealthy. + items: + type: string + type: array + type: object + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, + defaults to the pod IP. You probably + want to set "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in + the request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a + custom header to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port + to access on the container. Number must + be in the range 1 to 65535. Name must + be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting + to the host. Defaults to HTTP. + type: string + required: + - port + type: object + tcpSocket: + description: 'TCPSocket specifies an action + involving a TCP port. TCP hooks not yet + supported TODO: implement a realistic TCP + lifecycle hook' + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port + to access on the container. Number must + be in the range 1 to 65535. Name must + be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + type: object + livenessProbe: + description: Probes are not allowed for ephemeral + containers. + properties: + exec: + description: One and only one of the following + should be specified. Exec specifies the action + to take. + properties: + command: + description: Command is the command line to + execute inside the container, the working + directory for the command is root ('/') + in the container's filesystem. The command + is simply exec'd, it is not run inside a + shell, so traditional shell instructions + ('|', etc) won't work. To use a shell, you + need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy + and non-zero is unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for + the probe to be considered failed after having + succeeded. Defaults to 3. Minimum value is 1. + format: int32 + type: integer + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, defaults + to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to + access on the container. Number must be + in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting + to the host. Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container + has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform + the probe. Default to 10 seconds. Minimum value + is 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for + the probe to be considered successful after + having failed. Defaults to 1. Must be 1 for + liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: 'TCPSocket specifies an action involving + a TCP port. TCP hooks not yet supported TODO: + implement a realistic TCP lifecycle hook' + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to + access on the container. Number must be + in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + timeoutSeconds: + description: 'Number of seconds after which the + probe times out. Defaults to 1 second. Minimum + value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + name: + description: Name of the ephemeral container specified + as a DNS_LABEL. This name must be unique among all + containers, init containers and ephemeral containers. + type: string + ports: + description: Ports are not allowed for ephemeral containers. + items: + description: ContainerPort represents a network + port in a single container. + properties: + containerPort: + description: Number of port to expose on the + pod's IP address. This must be a valid port + number, 0 < x < 65536. + format: int32 + type: integer + hostIP: + description: What host IP to bind the external + port to. + type: string + hostPort: + description: Number of port to expose on the + host. If specified, this must be a valid port + number, 0 < x < 65536. If HostNetwork is specified, + this must match ContainerPort. Most containers + do not need this. + format: int32 + type: integer + name: + description: If specified, this must be an IANA_SVC_NAME + and unique within the pod. Each named port + in a pod must have a unique name. Name for + the port that can be referred to by services. + type: string + protocol: + description: Protocol for port. Must be UDP, + TCP, or SCTP. Defaults to "TCP". + type: string + required: + - containerPort + type: object + type: array + readinessProbe: + description: Probes are not allowed for ephemeral + containers. + properties: + exec: + description: One and only one of the following + should be specified. Exec specifies the action + to take. + properties: + command: + description: Command is the command line to + execute inside the container, the working + directory for the command is root ('/') + in the container's filesystem. The command + is simply exec'd, it is not run inside a + shell, so traditional shell instructions + ('|', etc) won't work. To use a shell, you + need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy + and non-zero is unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for + the probe to be considered failed after having + succeeded. Defaults to 3. Minimum value is 1. + format: int32 + type: integer + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, defaults + to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to + access on the container. Number must be + in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting + to the host. Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container + has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform + the probe. Default to 10 seconds. Minimum value + is 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for + the probe to be considered successful after + having failed. Defaults to 1. Must be 1 for + liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: 'TCPSocket specifies an action involving + a TCP port. TCP hooks not yet supported TODO: + implement a realistic TCP lifecycle hook' + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to + access on the container. Number must be + in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + timeoutSeconds: + description: 'Number of seconds after which the + probe times out. Defaults to 1 second. Minimum + value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + resources: + description: Resources are not allowed for ephemeral + containers. Ephemeral containers use spare resources + already allocated to the pod. + properties: + 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-compute-resources-container/' + 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-compute-resources-container/' + type: object + type: object + securityContext: + description: SecurityContext is not allowed for ephemeral + containers. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls + whether a process can gain more privileges than + its parent process. This bool directly controls + if the no_new_privs flag will be set on the + container process. AllowPrivilegeEscalation + is true always when the container is: 1) run + as Privileged 2) has CAP_SYS_ADMIN' + type: boolean + capabilities: + description: The capabilities to add/drop when + running containers. Defaults to the default + set of capabilities granted by the container + runtime. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX + capabilities type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX + capabilities type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. + Processes in privileged containers are essentially + equivalent to root on the host. Defaults to + false. + type: boolean + procMount: + description: procMount denotes the type of proc + mount to use for the containers. The default + is DefaultProcMount which uses the container + runtime defaults for readonly paths and masked + paths. This requires the ProcMountType feature + flag to be enabled. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only + root filesystem. Default is false. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of + the container process. Uses runtime default + if unset. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes + precedence. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must + run as a non-root user. If true, the Kubelet + will validate the image at runtime to ensure + that it does not run as UID 0 (root) and fail + to start the container if it does. If unset + or false, no such validation will be performed. + May also be set in PodSecurityContext. If set + in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes + precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of + the container process. Defaults to user specified + in image metadata if unspecified. May also be + set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified + in SecurityContext takes precedence. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied + to the container. If unspecified, the container + runtime will allocate a random SELinux context + for each container. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes + precedence. + properties: + level: + description: Level is SELinux level label + that applies to the container. + type: string + role: + description: Role is a SELinux role label + that applies to the container. + type: string + type: + description: Type is a SELinux type label + that applies to the container. + type: string + user: + description: User is a SELinux user label + that applies to the container. + type: string + type: object + windowsOptions: + description: The Windows specific settings applied + to all containers. If unspecified, the options + from the PodSecurityContext will be used. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes + precedence. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the + GMSA admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential + spec named by the GMSACredentialSpecName + field. This field is alpha-level and is + only honored by servers that enable the + WindowsGMSA feature flag. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the + name of the GMSA credential spec to use. + This field is alpha-level and is only honored + by servers that enable the WindowsGMSA feature + flag. + type: string + runAsUserName: + description: The UserName in Windows to run + the entrypoint of the container process. + Defaults to the user specified in image + metadata if unspecified. May also be set + in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified + in SecurityContext takes precedence. This + field is beta-level and may be disabled + with the WindowsRunAsUserName feature flag. + type: string + type: object + type: object + startupProbe: + description: Probes are not allowed for ephemeral + containers. + properties: + exec: + description: One and only one of the following + should be specified. Exec specifies the action + to take. + properties: + command: + description: Command is the command line to + execute inside the container, the working + directory for the command is root ('/') + in the container's filesystem. The command + is simply exec'd, it is not run inside a + shell, so traditional shell instructions + ('|', etc) won't work. To use a shell, you + need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy + and non-zero is unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for + the probe to be considered failed after having + succeeded. Defaults to 3. Minimum value is 1. + format: int32 + type: integer + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, defaults + to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to + access on the container. Number must be + in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting + to the host. Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container + has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform + the probe. Default to 10 seconds. Minimum value + is 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for + the probe to be considered successful after + having failed. Defaults to 1. Must be 1 for + liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: 'TCPSocket specifies an action involving + a TCP port. TCP hooks not yet supported TODO: + implement a realistic TCP lifecycle hook' + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to + access on the container. Number must be + in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + timeoutSeconds: + description: 'Number of seconds after which the + probe times out. Defaults to 1 second. Minimum + value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + stdin: + description: Whether this container should allocate + a buffer for stdin in the container runtime. If + this is not set, reads from stdin in the container + will always result in EOF. Default is false. + type: boolean + stdinOnce: + description: Whether the container runtime should + close the stdin channel after it has been opened + by a single attach. When stdin is true the stdin + stream will remain open across multiple attach sessions. + If stdinOnce is set to true, stdin is opened on + container start, is empty until the first client + attaches to stdin, and then remains open and accepts + data until the client disconnects, at which time + stdin is closed and remains closed until the container + is restarted. If this flag is false, a container + processes that reads from stdin will never receive + an EOF. Default is false + type: boolean + targetContainerName: + description: If set, the name of the container from + PodSpec that this ephemeral container targets. The + ephemeral container will be run in the namespaces + (IPC, PID, etc) of this container. If not set then + the ephemeral container is run in whatever namespaces + are shared for the pod. Note that the container + runtime must support this feature. + type: string + terminationMessagePath: + description: 'Optional: Path at which the file to + which the container''s termination message will + be written is mounted into the container''s filesystem. + Message written is intended to be brief final status, + such as an assertion failure message. Will be truncated + by the node if greater than 4096 bytes. The total + message length across all containers will be limited + to 12kb. Defaults to /dev/termination-log. Cannot + be updated.' + type: string + terminationMessagePolicy: + description: Indicate how the termination message + should be populated. File will use the contents + of terminationMessagePath to populate the container + status message on both success and failure. FallbackToLogsOnError + will use the last chunk of container log output + if the termination message file is empty and the + container exited with an error. The log output is + limited to 2048 bytes or 80 lines, whichever is + smaller. Defaults to File. Cannot be updated. + type: string + tty: + description: Whether this container should allocate + a TTY for itself, also requires 'stdin' to be true. + Default is false. + type: boolean + volumeDevices: + description: volumeDevices is the list of block devices + to be used by the container. This is a beta feature. + items: + description: volumeDevice describes a mapping of + a raw block device within a container. + properties: + devicePath: + description: devicePath is the path inside of + the container that the device will be mapped + to. + type: string + name: + description: name must match the name of a persistentVolumeClaim + in the pod + type: string + required: + - devicePath + - name + type: object + type: array + volumeMounts: + description: Pod volumes to mount into the container's + filesystem. Cannot be updated. + 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 + workingDir: + description: Container's working directory. If not + specified, the container runtime's default will + be used, which might be configured in the container + image. Cannot be updated. + type: string + required: + - name + type: object + type: array + hostAliases: + description: HostAliases is an optional list of hosts and + IPs that will be injected into the pod's hosts file if + specified. This is only valid for non-hostNetwork pods. + items: + description: HostAlias holds the mapping between IP and + hostnames that will be injected as an entry in the pod's + hosts file. + properties: + hostnames: + description: Hostnames for the above IP address. + items: + type: string + type: array + ip: + description: IP address of the host file entry. + type: string + type: object + type: array + hostIPC: + description: 'Use the host''s ipc namespace. Optional: Default + to false.' + type: boolean + hostNetwork: + description: Host networking requested for this pod. Use + the host's network namespace. If this option is set, the + ports that will be used must be specified. Default to + false. + type: boolean + hostPID: + description: 'Use the host''s pid namespace. Optional: Default + to false.' + type: boolean + hostname: + description: Specifies the hostname of the Pod If not specified, + the pod's hostname will be set to a system-defined value. + type: string + imagePullSecrets: + description: 'ImagePullSecrets is an optional list of references + to secrets in the same namespace to use for pulling any + of the images used by this PodSpec. If specified, these + secrets will be passed to individual puller implementations + for them to use. For example, in the case of docker, only + DockerConfig type secrets are honored. More info: https://kubernetes.io/docs/concepts/containers/images#specifying-imagepullsecrets-on-a-pod' + items: + description: LocalObjectReference contains enough information + to let you locate the referenced object inside the same + namespace. + 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 + type: array + initContainers: + description: 'List of initialization containers belonging + to the pod. Init containers are executed in order prior + to containers being started. If any init container fails, + the pod is considered to have failed and is handled according + to its restartPolicy. The name for an init container or + normal container must be unique among all containers. + Init containers may not have Lifecycle actions, Readiness + probes, Liveness probes, or Startup probes. The resourceRequirements + of an init container are taken into account during scheduling + by finding the highest request/limit for each resource + type, and then using the max of of that value or the sum + of the normal containers. Limits are applied to init containers + in a similar fashion. Init containers cannot currently + be added or removed. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/' + items: + description: A single application container that you want + to run within a pod. + properties: + args: + description: 'Arguments to the entrypoint. The docker + image''s CMD is used if this is not provided. Variable + references $(VAR_NAME) are expanded using the container''s + environment. If a variable cannot be resolved, the + reference in the input string will be unchanged. + The $(VAR_NAME) syntax can be escaped with a double + $$, ie: $$(VAR_NAME). Escaped references will never + be expanded, regardless of whether the variable + exists or not. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell' + items: + type: string + type: array + command: + description: 'Entrypoint array. Not executed within + a shell. The docker image''s ENTRYPOINT is used + if this is not provided. Variable references $(VAR_NAME) + are expanded using the container''s environment. + If a variable cannot be resolved, the reference + in the input string will be unchanged. The $(VAR_NAME) + syntax can be escaped with a double $$, ie: $$(VAR_NAME). + Escaped references will never be expanded, regardless + of whether the variable exists or not. Cannot be + updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell' + items: + type: string + type: array + env: + description: List of environment variables to set + in the container. Cannot be updated. + 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 previous 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. The $(VAR_NAME) syntax + can be escaped with a double $$, ie: $$(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 + envFrom: + description: List of sources to populate environment + variables in the container. The keys defined within + a source must be a C_IDENTIFIER. All invalid keys + will be reported as an event when the container + is starting. When a key exists in multiple sources, + the value associated with the last source will take + precedence. Values defined by an Env with a duplicate + key will take precedence. Cannot be updated. + items: + description: EnvFromSource represents the source + of a set of ConfigMaps + properties: + configMapRef: + description: The ConfigMap to select from + 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 + optional: + description: Specify whether the ConfigMap + must be defined + type: boolean + type: object + prefix: + description: An optional identifier to prepend + to each key in the ConfigMap. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + 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 + optional: + description: Specify whether the Secret + must be defined + type: boolean + type: object + type: object + type: array + image: + description: 'Docker image name. More info: https://kubernetes.io/docs/concepts/containers/images + This field is optional to allow higher level config + management to default or override container images + in workload controllers like Deployments and StatefulSets.' + type: string + imagePullPolicy: + description: 'Image pull policy. One of Always, Never, + IfNotPresent. Defaults to Always if :latest tag + is specified, or IfNotPresent otherwise. Cannot + be updated. More info: https://kubernetes.io/docs/concepts/containers/images#updating-images' + type: string + lifecycle: + description: Actions that the management system should + take in response to container lifecycle events. + Cannot be updated. + properties: + postStart: + description: 'PostStart is called immediately + after a container is created. If the handler + fails, the container is terminated and restarted + according to its restart policy. Other management + of the container blocks until the hook completes. + More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks' + properties: + exec: + description: One and only one of the following + should be specified. Exec specifies the + action to take. + properties: + command: + description: Command is the command line + to execute inside the container, the + working directory for the command is + root ('/') in the container's filesystem. + The command is simply exec'd, it is + not run inside a shell, so traditional + shell instructions ('|', etc) won't + work. To use a shell, you need to explicitly + call out to that shell. Exit status + of 0 is treated as live/healthy and + non-zero is unhealthy. + items: + type: string + type: array + type: object + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, + defaults to the pod IP. You probably + want to set "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in + the request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a + custom header to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port + to access on the container. Number must + be in the range 1 to 65535. Name must + be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting + to the host. Defaults to HTTP. + type: string + required: + - port + type: object + tcpSocket: + description: 'TCPSocket specifies an action + involving a TCP port. TCP hooks not yet + supported TODO: implement a realistic TCP + lifecycle hook' + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port + to access on the container. Number must + be in the range 1 to 65535. Name must + be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + description: 'PreStop is called immediately before + a container is terminated due to an API request + or management event such as liveness/startup + probe failure, preemption, resource contention, + etc. The handler is not called if the container + crashes or exits. The reason for termination + is passed to the handler. The Pod''s termination + grace period countdown begins before the PreStop + hooked is executed. Regardless of the outcome + of the handler, the container will eventually + terminate within the Pod''s termination grace + period. Other management of the container blocks + until the hook completes or until the termination + grace period is reached. More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks' + properties: + exec: + description: One and only one of the following + should be specified. Exec specifies the + action to take. + properties: + command: + description: Command is the command line + to execute inside the container, the + working directory for the command is + root ('/') in the container's filesystem. + The command is simply exec'd, it is + not run inside a shell, so traditional + shell instructions ('|', etc) won't + work. To use a shell, you need to explicitly + call out to that shell. Exit status + of 0 is treated as live/healthy and + non-zero is unhealthy. + items: + type: string + type: array + type: object + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, + defaults to the pod IP. You probably + want to set "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in + the request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a + custom header to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port + to access on the container. Number must + be in the range 1 to 65535. Name must + be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting + to the host. Defaults to HTTP. + type: string + required: + - port + type: object + tcpSocket: + description: 'TCPSocket specifies an action + involving a TCP port. TCP hooks not yet + supported TODO: implement a realistic TCP + lifecycle hook' + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port + to access on the container. Number must + be in the range 1 to 65535. Name must + be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + type: object + livenessProbe: + description: 'Periodic probe of container liveness. + Container will be restarted if the probe fails. + Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + properties: + exec: + description: One and only one of the following + should be specified. Exec specifies the action + to take. + properties: + command: + description: Command is the command line to + execute inside the container, the working + directory for the command is root ('/') + in the container's filesystem. The command + is simply exec'd, it is not run inside a + shell, so traditional shell instructions + ('|', etc) won't work. To use a shell, you + need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy + and non-zero is unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for + the probe to be considered failed after having + succeeded. Defaults to 3. Minimum value is 1. + format: int32 + type: integer + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, defaults + to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to + access on the container. Number must be + in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting + to the host. Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container + has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform + the probe. Default to 10 seconds. Minimum value + is 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for + the probe to be considered successful after + having failed. Defaults to 1. Must be 1 for + liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: 'TCPSocket specifies an action involving + a TCP port. TCP hooks not yet supported TODO: + implement a realistic TCP lifecycle hook' + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to + access on the container. Number must be + in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + timeoutSeconds: + description: 'Number of seconds after which the + probe times out. Defaults to 1 second. Minimum + value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + name: + description: Name of the container specified as a + DNS_LABEL. Each container in a pod must have a unique + name (DNS_LABEL). Cannot be updated. + type: string + ports: + description: List of ports to expose from the container. + Exposing a port here gives the system additional + information about the network connections a container + uses, but is primarily informational. Not specifying + a port here DOES NOT prevent that port from being + exposed. Any port which is listening on the default + "0.0.0.0" address inside a container will be accessible + from the network. Cannot be updated. + items: + description: ContainerPort represents a network + port in a single container. + properties: + containerPort: + description: Number of port to expose on the + pod's IP address. This must be a valid port + number, 0 < x < 65536. + format: int32 + type: integer + hostIP: + description: What host IP to bind the external + port to. + type: string + hostPort: + description: Number of port to expose on the + host. If specified, this must be a valid port + number, 0 < x < 65536. If HostNetwork is specified, + this must match ContainerPort. Most containers + do not need this. + format: int32 + type: integer + name: + description: If specified, this must be an IANA_SVC_NAME + and unique within the pod. Each named port + in a pod must have a unique name. Name for + the port that can be referred to by services. + type: string + protocol: + description: Protocol for port. Must be UDP, + TCP, or SCTP. Defaults to "TCP". + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + description: 'Periodic probe of container service + readiness. Container will be removed from service + endpoints if the probe fails. Cannot be updated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + properties: + exec: + description: One and only one of the following + should be specified. Exec specifies the action + to take. + properties: + command: + description: Command is the command line to + execute inside the container, the working + directory for the command is root ('/') + in the container's filesystem. The command + is simply exec'd, it is not run inside a + shell, so traditional shell instructions + ('|', etc) won't work. To use a shell, you + need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy + and non-zero is unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for + the probe to be considered failed after having + succeeded. Defaults to 3. Minimum value is 1. + format: int32 + type: integer + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, defaults + to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to + access on the container. Number must be + in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting + to the host. Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container + has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform + the probe. Default to 10 seconds. Minimum value + is 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for + the probe to be considered successful after + having failed. Defaults to 1. Must be 1 for + liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: 'TCPSocket specifies an action involving + a TCP port. TCP hooks not yet supported TODO: + implement a realistic TCP lifecycle hook' + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to + access on the container. Number must be + in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + timeoutSeconds: + description: 'Number of seconds after which the + probe times out. Defaults to 1 second. Minimum + value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + resources: + description: 'Compute Resources required by this container. + Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + properties: + 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-compute-resources-container/' + 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-compute-resources-container/' + type: object + type: object + securityContext: + description: 'Security options the pod should run + with. More info: https://kubernetes.io/docs/concepts/policy/security-context/ + More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/' + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls + whether a process can gain more privileges than + its parent process. This bool directly controls + if the no_new_privs flag will be set on the + container process. AllowPrivilegeEscalation + is true always when the container is: 1) run + as Privileged 2) has CAP_SYS_ADMIN' + type: boolean + capabilities: + description: The capabilities to add/drop when + running containers. Defaults to the default + set of capabilities granted by the container + runtime. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX + capabilities type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX + capabilities type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. + Processes in privileged containers are essentially + equivalent to root on the host. Defaults to + false. + type: boolean + procMount: + description: procMount denotes the type of proc + mount to use for the containers. The default + is DefaultProcMount which uses the container + runtime defaults for readonly paths and masked + paths. This requires the ProcMountType feature + flag to be enabled. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only + root filesystem. Default is false. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of + the container process. Uses runtime default + if unset. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes + precedence. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must + run as a non-root user. If true, the Kubelet + will validate the image at runtime to ensure + that it does not run as UID 0 (root) and fail + to start the container if it does. If unset + or false, no such validation will be performed. + May also be set in PodSecurityContext. If set + in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes + precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of + the container process. Defaults to user specified + in image metadata if unspecified. May also be + set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified + in SecurityContext takes precedence. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied + to the container. If unspecified, the container + runtime will allocate a random SELinux context + for each container. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes + precedence. + properties: + level: + description: Level is SELinux level label + that applies to the container. + type: string + role: + description: Role is a SELinux role label + that applies to the container. + type: string + type: + description: Type is a SELinux type label + that applies to the container. + type: string + user: + description: User is a SELinux user label + that applies to the container. + type: string + type: object + windowsOptions: + description: The Windows specific settings applied + to all containers. If unspecified, the options + from the PodSecurityContext will be used. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes + precedence. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the + GMSA admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential + spec named by the GMSACredentialSpecName + field. This field is alpha-level and is + only honored by servers that enable the + WindowsGMSA feature flag. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the + name of the GMSA credential spec to use. + This field is alpha-level and is only honored + by servers that enable the WindowsGMSA feature + flag. + type: string + runAsUserName: + description: The UserName in Windows to run + the entrypoint of the container process. + Defaults to the user specified in image + metadata if unspecified. May also be set + in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified + in SecurityContext takes precedence. This + field is beta-level and may be disabled + with the WindowsRunAsUserName feature flag. + type: string + type: object + type: object + startupProbe: + description: 'StartupProbe indicates that the Pod + has successfully initialized. If specified, no other + probes are executed until this completes successfully. + If this probe fails, the Pod will be restarted, + just as if the livenessProbe failed. This can be + used to provide different probe parameters at the + beginning of a Pod''s lifecycle, when it might take + a long time to load data or warm a cache, than during + steady-state operation. This cannot be updated. + This is an alpha feature enabled by the StartupProbe + feature flag. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + properties: + exec: + description: One and only one of the following + should be specified. Exec specifies the action + to take. + properties: + command: + description: Command is the command line to + execute inside the container, the working + directory for the command is root ('/') + in the container's filesystem. The command + is simply exec'd, it is not run inside a + shell, so traditional shell instructions + ('|', etc) won't work. To use a shell, you + need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy + and non-zero is unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for + the probe to be considered failed after having + succeeded. Defaults to 3. Minimum value is 1. + format: int32 + type: integer + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, defaults + to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to + access on the container. Number must be + in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting + to the host. Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container + has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform + the probe. Default to 10 seconds. Minimum value + is 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for + the probe to be considered successful after + having failed. Defaults to 1. Must be 1 for + liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: 'TCPSocket specifies an action involving + a TCP port. TCP hooks not yet supported TODO: + implement a realistic TCP lifecycle hook' + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to + access on the container. Number must be + in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + timeoutSeconds: + description: 'Number of seconds after which the + probe times out. Defaults to 1 second. Minimum + value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + stdin: + description: Whether this container should allocate + a buffer for stdin in the container runtime. If + this is not set, reads from stdin in the container + will always result in EOF. Default is false. + type: boolean + stdinOnce: + description: Whether the container runtime should + close the stdin channel after it has been opened + by a single attach. When stdin is true the stdin + stream will remain open across multiple attach sessions. + If stdinOnce is set to true, stdin is opened on + container start, is empty until the first client + attaches to stdin, and then remains open and accepts + data until the client disconnects, at which time + stdin is closed and remains closed until the container + is restarted. If this flag is false, a container + processes that reads from stdin will never receive + an EOF. Default is false + type: boolean + terminationMessagePath: + description: 'Optional: Path at which the file to + which the container''s termination message will + be written is mounted into the container''s filesystem. + Message written is intended to be brief final status, + such as an assertion failure message. Will be truncated + by the node if greater than 4096 bytes. The total + message length across all containers will be limited + to 12kb. Defaults to /dev/termination-log. Cannot + be updated.' + type: string + terminationMessagePolicy: + description: Indicate how the termination message + should be populated. File will use the contents + of terminationMessagePath to populate the container + status message on both success and failure. FallbackToLogsOnError + will use the last chunk of container log output + if the termination message file is empty and the + container exited with an error. The log output is + limited to 2048 bytes or 80 lines, whichever is + smaller. Defaults to File. Cannot be updated. + type: string + tty: + description: Whether this container should allocate + a TTY for itself, also requires 'stdin' to be true. + Default is false. + type: boolean + volumeDevices: + description: volumeDevices is the list of block devices + to be used by the container. This is a beta feature. + items: + description: volumeDevice describes a mapping of + a raw block device within a container. + properties: + devicePath: + description: devicePath is the path inside of + the container that the device will be mapped + to. + type: string + name: + description: name must match the name of a persistentVolumeClaim + in the pod + type: string + required: + - devicePath + - name + type: object + type: array + volumeMounts: + description: Pod volumes to mount into the container's + filesystem. Cannot be updated. + 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 + workingDir: + description: Container's working directory. If not + specified, the container runtime's default will + be used, which might be configured in the container + image. Cannot be updated. + type: string + required: + - name + type: object + type: array + nodeName: + description: NodeName is a request to schedule this pod + onto a specific node. If it is non-empty, the scheduler + simply schedules this pod onto that node, assuming that + it fits resource requirements. + type: string + nodeSelector: + additionalProperties: + type: string + description: 'NodeSelector is a selector which must be true + for the pod to fit on a node. Selector which must match + a node''s labels for the pod to be scheduled on that node. + More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/' + type: object + overhead: + 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: 'Overhead represents the resource overhead + associated with running a pod for a given RuntimeClass. + This field will be autopopulated at admission time by + the RuntimeClass admission controller. If the RuntimeClass + admission controller is enabled, overhead must not be + set in Pod create requests. The RuntimeClass admission + controller will reject Pod create requests which have + the overhead already set. If RuntimeClass is configured + and selected in the PodSpec, Overhead will be set to the + value defined in the corresponding RuntimeClass, otherwise + it will remain unset and treated as zero. More info: https://git.k8s.io/enhancements/keps/sig-node/20190226-pod-overhead.md + This field is alpha-level as of Kubernetes v1.16, and + is only honored by servers that enable the PodOverhead + feature.' + type: object + preemptionPolicy: + description: PreemptionPolicy is the Policy for preempting + pods with lower priority. One of Never, PreemptLowerPriority. + Defaults to PreemptLowerPriority if unset. This field + is alpha-level and is only honored by servers that enable + the NonPreemptingPriority feature. + type: string + priority: + description: The priority value. Various system components + use this field to find the priority of the pod. When Priority + Admission Controller is enabled, it prevents users from + setting this field. The admission controller populates + this field from PriorityClassName. The higher the value, + the higher the priority. + format: int32 + type: integer + priorityClassName: + description: If specified, indicates the pod's priority. + "system-node-critical" and "system-cluster-critical" are + two special keywords which indicate the highest priorities + with the former being the highest priority. Any other + name must be defined by creating a PriorityClass object + with that name. If not specified, the pod priority will + be default or zero if there is no default. + type: string + readinessGates: + description: 'If specified, all readiness gates will be + evaluated for pod readiness. A pod is ready when all its + containers are ready AND all conditions specified in the + readiness gates have status equal to "True" More info: + https://git.k8s.io/enhancements/keps/sig-network/0007-pod-ready%2B%2B.md' + items: + description: PodReadinessGate contains the reference to + a pod condition + properties: + conditionType: + description: ConditionType refers to a condition in + the pod's condition list with matching type. + type: string + required: + - conditionType + type: object + type: array + restartPolicy: + description: 'Restart policy for all containers within the + pod. One of Always, OnFailure, Never. Default to Always. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#restart-policy' + type: string + runtimeClassName: + description: 'RuntimeClassName refers to a RuntimeClass + object in the node.k8s.io group, which should be used + to run this pod. If no RuntimeClass resource matches + the named class, the pod will not be run. If unset or + empty, the "legacy" RuntimeClass will be used, which is + an implicit class with an empty definition that uses the + default runtime handler. More info: https://git.k8s.io/enhancements/keps/sig-node/runtime-class.md + This is a beta feature as of Kubernetes v1.14.' + type: string + schedulerName: + description: If specified, the pod will be dispatched by + specified scheduler. If not specified, the pod will be + dispatched by default scheduler. + type: string + securityContext: + description: 'SecurityContext holds pod-level security attributes + and common container settings. Optional: Defaults to empty. See + type description for default values of each field.' + properties: + fsGroup: + description: "A special supplemental group that applies + to all containers in a pod. Some volume types allow + the Kubelet to change the ownership of that volume + to be owned by the pod: \n 1. The owning GID will + be the FSGroup 2. The setgid bit is set (new files + created in the volume will be owned by FSGroup) 3. + The permission bits are OR'd with rw-rw---- \n If + unset, the Kubelet will not modify the ownership and + permissions of any volume." + format: int64 + type: integer + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be + set in SecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as + a non-root user. If true, the Kubelet will validate + the image at runtime to ensure that it does not run + as UID 0 (root) and fail to start the container if + it does. If unset or false, no such validation will + be performed. May also be set in SecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata + if unspecified. May also be set in SecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence + for that container. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to all + containers. If unspecified, the container runtime + will allocate a random SELinux context for each container. May + also be set in SecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + supplementalGroups: + description: A list of groups applied to the first process + run in each container, in addition to the container's + primary GID. If unspecified, no groups will be added + to any container. + items: + format: int64 + type: integer + type: array + sysctls: + description: Sysctls hold a list of namespaced sysctls + used for the pod. Pods with unsupported sysctls (by + the container runtime) might fail to launch. + items: + description: Sysctl defines a kernel parameter to + be set + properties: + name: + description: Name of a property to set + type: string + value: + description: Value of a property to set + type: string + required: + - name + - value + type: object + type: array + windowsOptions: + description: The Windows specific settings applied to + all containers. If unspecified, the options within + a container's SecurityContext will be used. If set + in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA + admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec + named by the GMSACredentialSpecName field. This + field is alpha-level and is only honored by servers + that enable the WindowsGMSA feature flag. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name + of the GMSA credential spec to use. This field + is alpha-level and is only honored by servers + that enable the WindowsGMSA feature flag. + type: string + runAsUserName: + description: The UserName in Windows to run the + entrypoint of the container process. Defaults + to the user specified in image metadata if unspecified. + May also be set in PodSecurityContext. If set + in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + This field is beta-level and may be disabled with + the WindowsRunAsUserName feature flag. + type: string + type: object + type: object + serviceAccount: + description: 'DeprecatedServiceAccount is a depreciated + alias for ServiceAccountName. Deprecated: Use serviceAccountName + instead.' + type: string + serviceAccountName: + description: 'ServiceAccountName is the name of the ServiceAccount + to use to run this pod. More info: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/' + type: string + shareProcessNamespace: + description: 'Share a single process namespace between all + of the containers in a pod. When this is set containers + will be able to view and signal processes from other containers + in the same pod, and the first process in each container + will not be assigned PID 1. HostPID and ShareProcessNamespace + cannot both be set. Optional: Default to false.' + type: boolean + subdomain: + description: If specified, the fully qualified Pod hostname + will be "...svc.". If not specified, the pod will not have a domainname + at all. + type: string + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs + to terminate gracefully. May be decreased in delete request. + Value must be non-negative integer. The value zero indicates + delete immediately. If this value is nil, the default + grace period will be used instead. The grace period is + the duration in seconds after the processes running in + the pod are sent a termination signal and the time when + the processes are forcibly halted with a kill signal. + Set this value longer than the expected cleanup time for + your process. Defaults to 30 seconds. + format: int64 + type: integer + tolerations: + description: If specified, the pod's tolerations. + items: + description: The pod this Toleration is attached to tolerates + any taint that matches the triple + using the matching operator . + properties: + effect: + description: Effect indicates the taint effect to + match. Empty means match all taint effects. When + specified, allowed values are NoSchedule, PreferNoSchedule + and NoExecute. + type: string + key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. If + the key is empty, operator must be Exists; this + combination means to match all values and all keys. + type: string + operator: + description: Operator represents a key's relationship + to the value. Valid operators are Exists and Equal. + Defaults to Equal. Exists is equivalent to wildcard + for value, so that a pod can tolerate all taints + of a particular category. + type: string + tolerationSeconds: + description: TolerationSeconds represents the period + of time the toleration (which must be of effect + NoExecute, otherwise this field is ignored) tolerates + the taint. By default, it is not set, which means + tolerate the taint forever (do not evict). Zero + and negative values will be treated as 0 (evict + immediately) by the system. + format: int64 + type: integer + value: + description: Value is the taint value the toleration + matches to. If the operator is Exists, the value + should be empty, otherwise just a regular string. + type: string + type: object + type: array + topologySpreadConstraints: + description: TopologySpreadConstraints describes how a group + of pods ought to spread across topology domains. Scheduler + will schedule pods in a way which abides by the constraints. + This field is alpha-level and is only honored by clusters + that enables the EvenPodsSpread feature. All topologySpreadConstraints + are ANDed. + items: + description: TopologySpreadConstraint specifies how to + spread matching pods among the given topology. + properties: + labelSelector: + description: LabelSelector is used to find matching + pods. Pods that match this label selector are counted + to determine the number of pods in their corresponding + topology domain. + 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 + maxSkew: + description: 'MaxSkew describes the degree to which + pods may be unevenly distributed. It''s the maximum + permitted difference between the number of matching + pods in any two topology domains of a given topology + type. For example, in a 3-zone cluster, MaxSkew + is set to 1, and pods with the same labelSelector + spread as 1/1/0: | zone1 | zone2 | zone3 | | P | P | | + - if MaxSkew is 1, incoming pod can only be scheduled + to zone3 to become 1/1/1; scheduling it onto zone1(zone2) + would make the ActualSkew(2-0) on zone1(zone2) violate + MaxSkew(1). - if MaxSkew is 2, incoming pod can + be scheduled onto any zone. It''s a required field. + Default value is 1 and 0 is not allowed.' + format: int32 + type: integer + topologyKey: + description: TopologyKey is the key of node labels. + Nodes that have a label with this key and identical + values are considered to be in the same topology. + We consider each as a "bucket", and + try to put balanced number of pods into each bucket. + It's a required field. + type: string + whenUnsatisfiable: + description: 'WhenUnsatisfiable indicates how to deal + with a pod if it doesn''t satisfy the spread constraint. + - DoNotSchedule (default) tells the scheduler not + to schedule it - ScheduleAnyway tells the scheduler + to still schedule it It''s considered as "Unsatisfiable" + if and only if placing incoming pod on any topology + violates "MaxSkew". For example, in a 3-zone cluster, + MaxSkew is set to 1, and pods with the same labelSelector + spread as 3/1/1: | zone1 | zone2 | zone3 | | P P + P | P | P | If WhenUnsatisfiable is set + to DoNotSchedule, incoming pod can only be scheduled + to zone2(zone3) to become 3/2/1(3/1/2) as ActualSkew(2-1) + on zone2(zone3) satisfies MaxSkew(1). In other words, + the cluster can still be imbalanced, but scheduler + won''t make it *more* imbalanced. It''s a required + field.' + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array + x-kubernetes-list-map-keys: + - topologyKey + - whenUnsatisfiable + x-kubernetes-list-type: map + volumes: + description: 'List of volumes that can be mounted by containers + belonging to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes' + 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: '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: '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: 'Specify "true" to force and set + the ReadOnly property in VolumeMounts to "true". + If omitted, the default is "false". More info: + https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + type: boolean + volumeID: + description: '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: 'Host Caching mode: None, Read Only, + Read Write.' + type: string + diskName: + description: The Name of the data disk in the + blob storage + type: string + diskURI: + description: The URI the data disk in the blob + storage + type: string + fsType: + description: 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: 'Expected values 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: 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: Defaults to false (read/write). ReadOnly + here will force the ReadOnly setting in VolumeMounts. + type: boolean + secretName: + description: the name of secret that contains + Azure Storage Account Name and Key + type: string + shareName: + description: 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: '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: 'Optional: Used as the mounted root, + rather than the full Ceph tree, default is /' + type: string + readOnly: + description: '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: '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: '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: '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: '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: 'Optional: 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: '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: 'volume id 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: 'Optional: mode bits to use on created + files by default. Must be a value between 0 + and 0777. 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: 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: The key to project. + type: string + mode: + description: 'Optional: mode bits to use + on this file, must be a value between + 0 and 0777. 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: 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: Specify whether the ConfigMap or + its keys must be defined + type: boolean + type: object + csi: + description: CSI (Container Storage Interface) represents + storage that is handled by an external CSI driver + (Alpha 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: Filesystem type 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: 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 value between 0 + and 0777. 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 to use + on this file, must be a value between + 0 and 0777. 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: '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: '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 + 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: '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: 'Optional: FC target lun number' + format: int32 + type: integer + readOnly: + description: 'Optional: Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts.' + type: boolean + targetWWNs: + description: 'Optional: FC target worldwide names + (WWNs)' + items: + type: string + type: array + wwids: + description: '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: 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: 'Optional: Extra command options + if any.' + type: object + readOnly: + description: 'Optional: Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts.' + type: boolean + secretRef: + description: '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: Name of the dataset stored as metadata + -> name on the dataset for Flocker should be + considered as deprecated + type: string + datasetUUID: + description: 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: '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: '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: '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: 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 URL + type: string + revision: + description: 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: 'EndpointsName 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: whether support iSCSI Discovery CHAP + authentication + type: boolean + chapAuthSession: + description: whether support iSCSI Session CHAP + authentication + type: boolean + fsType: + description: '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: Custom iSCSI Initiator Name. If initiatorName + is specified with iscsiInterface simultaneously, + new iSCSI interface : will be created for the connection. + type: string + iqn: + description: Target iSCSI Qualified Name. + type: string + iscsiInterface: + description: iSCSI Interface Name that uses an + iSCSI transport. Defaults to 'default' (tcp). + type: string + lun: + description: iSCSI Target Lun number. + format: int32 + type: integer + portals: + description: 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: 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: 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: 'Volume''s name. 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: 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: 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: 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: 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: Items for all in one resources secrets, + configmaps, and downward API + properties: + defaultMode: + description: Mode bits to use on created files + by default. Must be a value between 0 and 0777. + 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: list of volume projections + items: + description: Projection that may be projected + along with other supported volume types + properties: + configMap: + description: information about the configMap + data to project + properties: + items: + description: 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: The key to project. + type: string + mode: + description: 'Optional: mode bits + to use on this file, must be + a value between 0 and 0777. + 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: 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: Specify whether the ConfigMap + or its keys must be defined + type: boolean + type: object + downwardAPI: + description: 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 + to use on this file, must be + a value between 0 and 0777. + 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: information about the secret + data to project + properties: + items: + description: 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: The key to project. + type: string + mode: + description: 'Optional: mode bits + to use on this file, must be + a value between 0 and 0777. + 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: 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: Specify whether the Secret + or its key must be defined + type: boolean + type: object + serviceAccountToken: + description: 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 + required: + - sources + 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: '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: '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: '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: '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: '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: 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: The host address of the ScaleIO API + Gateway. + type: string + protectionDomain: + description: The name of the ScaleIO Protection + Domain for the configured storage. + type: string + readOnly: + description: 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: Flag to enable/disable SSL communication + with Gateway, default false + type: boolean + storageMode: + description: Indicates whether the storage for + a volume should be ThickProvisioned or ThinProvisioned. + Default is ThinProvisioned. + type: string + storagePool: + description: The ScaleIO Storage Pool associated + with the protection domain. + type: string + system: + description: The name of the storage system as + configured in ScaleIO. + type: string + volumeName: + description: 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: 'Optional: mode bits to use on created + files by default. Must be a value between 0 + and 0777. 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: 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: The key to project. + type: string + mode: + description: 'Optional: mode bits to use + on this file, must be a value between + 0 and 0777. 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: 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: Specify whether the Secret or its + keys must be defined + type: boolean + secretName: + description: '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: 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: 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: 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: Storage Policy Based Management (SPBM) + profile ID associated with the StoragePolicyName. + type: string + storagePolicyName: + description: Storage Policy Based Management (SPBM) + profile name. + type: string + volumePath: + description: Path that identifies vSphere volume + vmdk + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + required: + - containers + type: object + type: object + type: object + deployment: + description: Deployment specifies the Beat should be deployed as a Deployment, + and allows providing its spec. Cannot be used along with `daemonSet`. + If both are absent a default for the Type is used. + properties: + podTemplate: + description: PodTemplateSpec describes the data a pod should have + when created from a template + properties: + metadata: + description: 'Standard object''s metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata' + type: object + spec: + description: 'Specification of the desired behavior of the pod. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status' + properties: + activeDeadlineSeconds: + description: Optional duration in seconds the pod may be + active on the node relative to StartTime before the system + will actively try to mark it failed and kill associated + containers. Value must be a positive integer. + format: int64 + type: integer + affinity: + description: If specified, the pod's scheduling constraints + properties: + nodeAffinity: + description: Describes node affinity scheduling rules + for the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule + pods to nodes that satisfy the affinity expressions + specified by this field, but it may choose a node + that violates one or more of the expressions. + The node that is most preferred is the one with + the greatest sum of weights, i.e. for each node + that meets all of the scheduling requirements + (resource request, requiredDuringScheduling affinity + expressions, etc.), compute a sum by iterating + through the elements of this field and adding + "weight" to the sum if the node matches the corresponding + matchExpressions; the node(s) with the highest + sum are the most preferred. + items: + description: An empty preferred scheduling term + matches all objects with implicit weight 0 (i.e. + it's a no-op). A null preferred scheduling term + matches no objects (i.e. is also a no-op). + properties: + preference: + description: A node selector term, associated + with the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that + the selector applies to. + type: string + operator: + description: Represents a key's + relationship to a set of values. + Valid operators are In, NotIn, + Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: 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. If + the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that + the selector applies to. + type: string + operator: + description: Represents a key's + relationship to a set of values. + Valid operators are In, NotIn, + Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: 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. If + the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + description: Weight associated with matching + the corresponding nodeSelectorTerm, in the + range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified + by this field are not met at scheduling time, + the pod will not be scheduled onto the node. If + the affinity requirements specified by this field + cease to be met at some point during pod execution + (e.g. due to an update), the system may or may + not try to eventually evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector + terms. The terms are ORed. + items: + description: A null or empty node selector + term matches no objects. The requirements + of them are ANDed. The TopologySelectorTerm + type implements a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that + the selector applies to. + type: string + operator: + description: Represents a key's + relationship to a set of values. + Valid operators are In, NotIn, + Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: 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. If + the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that + the selector applies to. + type: string + operator: + description: Represents a key's + relationship to a set of values. + Valid operators are In, NotIn, + Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: 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. If + the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object + type: object + podAffinity: + description: Describes pod affinity scheduling rules + (e.g. co-locate this pod in the same node, zone, etc. + as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule + pods to nodes that satisfy the affinity expressions + specified by this field, but it may choose a node + that violates one or more of the expressions. + The node that is most preferred is the one with + the greatest sum of weights, i.e. for each node + that meets all of the scheduling requirements + (resource request, requiredDuringScheduling affinity + expressions, etc.), compute a sum by iterating + through the elements of this field and adding + "weight" to the sum if the node has pods which + matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched + WeightedPodAffinityTerm fields are added per-node + to find the most preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, + associated with the corresponding weight. + properties: + labelSelector: + description: A label query over a set + of resources, in this case pods. + 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 + namespaces: + description: namespaces specifies which + namespaces the labelSelector applies + to (matches against); null or empty + list means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector + in the specified namespaces, where co-located + is defined as running on a node whose + value of the label with key topologyKey + matches that of any node on which any + of the selected pods is running. Empty + topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching + the corresponding podAffinityTerm, in the + range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified + by this field are not met at scheduling time, + the pod will not be scheduled onto the node. If + the affinity requirements specified by this field + cease to be met at some point during pod execution + (e.g. due to a pod label update), the system may + or may not try to eventually evict the pod from + its node. When there are multiple elements, the + lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those + matching the labelSelector relative to the given + namespace(s)) that this pod should be co-located + (affinity) or not co-located (anti-affinity) + with, where co-located is defined as running + on a node whose value of the label with key + matches that of any node on which + a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + namespaces: + description: namespaces specifies which namespaces + the labelSelector applies to (matches against); + null or empty list means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector + in the specified namespaces, where co-located + is defined as running on a node whose value + of the label with key topologyKey matches + that of any node on which any of the selected + pods is running. Empty topologyKey is not + allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling + rules (e.g. avoid putting this pod in the same node, + zone, etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule + pods to nodes that satisfy the anti-affinity expressions + specified by this field, but it may choose a node + that violates one or more of the expressions. + The node that is most preferred is the one with + the greatest sum of weights, i.e. for each node + that meets all of the scheduling requirements + (resource request, requiredDuringScheduling anti-affinity + expressions, etc.), compute a sum by iterating + through the elements of this field and adding + "weight" to the sum if the node has pods which + matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched + WeightedPodAffinityTerm fields are added per-node + to find the most preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, + associated with the corresponding weight. + properties: + labelSelector: + description: A label query over a set + of resources, in this case pods. + 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 + namespaces: + description: namespaces specifies which + namespaces the labelSelector applies + to (matches against); null or empty + list means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector + in the specified namespaces, where co-located + is defined as running on a node whose + value of the label with key topologyKey + matches that of any node on which any + of the selected pods is running. Empty + topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching + the corresponding podAffinityTerm, in the + range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified + by this field are not met at scheduling time, + the pod will not be scheduled onto the node. If + the anti-affinity requirements specified by this + field cease to be met at some point during pod + execution (e.g. due to a pod label update), the + system may or may not try to eventually evict + the pod from its node. When there are multiple + elements, the lists of nodes corresponding to + each podAffinityTerm are intersected, i.e. all + terms must be satisfied. + items: + description: Defines a set of pods (namely those + matching the labelSelector relative to the given + namespace(s)) that this pod should be co-located + (affinity) or not co-located (anti-affinity) + with, where co-located is defined as running + on a node whose value of the label with key + matches that of any node on which + a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + namespaces: + description: namespaces specifies which namespaces + the labelSelector applies to (matches against); + null or empty list means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector + in the specified namespaces, where co-located + is defined as running on a node whose value + of the label with key topologyKey matches + that of any node on which any of the selected + pods is running. Empty topologyKey is not + allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + automountServiceAccountToken: + description: AutomountServiceAccountToken indicates whether + a service account token should be automatically mounted. + type: boolean + containers: + description: List of containers belonging to the pod. Containers + cannot currently be added or removed. There must be at + least one container in a Pod. Cannot be updated. + items: + description: A single application container that you want + to run within a pod. + properties: + args: + description: 'Arguments to the entrypoint. The docker + image''s CMD is used if this is not provided. Variable + references $(VAR_NAME) are expanded using the container''s + environment. If a variable cannot be resolved, the + reference in the input string will be unchanged. + The $(VAR_NAME) syntax can be escaped with a double + $$, ie: $$(VAR_NAME). Escaped references will never + be expanded, regardless of whether the variable + exists or not. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell' + items: + type: string + type: array + command: + description: 'Entrypoint array. Not executed within + a shell. The docker image''s ENTRYPOINT is used + if this is not provided. Variable references $(VAR_NAME) + are expanded using the container''s environment. + If a variable cannot be resolved, the reference + in the input string will be unchanged. The $(VAR_NAME) + syntax can be escaped with a double $$, ie: $$(VAR_NAME). + Escaped references will never be expanded, regardless + of whether the variable exists or not. Cannot be + updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell' + items: + type: string + type: array + env: + description: List of environment variables to set + in the container. Cannot be updated. + 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 previous 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. The $(VAR_NAME) syntax + can be escaped with a double $$, ie: $$(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 + envFrom: + description: List of sources to populate environment + variables in the container. The keys defined within + a source must be a C_IDENTIFIER. All invalid keys + will be reported as an event when the container + is starting. When a key exists in multiple sources, + the value associated with the last source will take + precedence. Values defined by an Env with a duplicate + key will take precedence. Cannot be updated. + items: + description: EnvFromSource represents the source + of a set of ConfigMaps + properties: + configMapRef: + description: The ConfigMap to select from + 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 + optional: + description: Specify whether the ConfigMap + must be defined + type: boolean + type: object + prefix: + description: An optional identifier to prepend + to each key in the ConfigMap. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + 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 + optional: + description: Specify whether the Secret + must be defined + type: boolean + type: object + type: object + type: array + image: + description: 'Docker image name. More info: https://kubernetes.io/docs/concepts/containers/images + This field is optional to allow higher level config + management to default or override container images + in workload controllers like Deployments and StatefulSets.' + type: string + imagePullPolicy: + description: 'Image pull policy. One of Always, Never, + IfNotPresent. Defaults to Always if :latest tag + is specified, or IfNotPresent otherwise. Cannot + be updated. More info: https://kubernetes.io/docs/concepts/containers/images#updating-images' + type: string + lifecycle: + description: Actions that the management system should + take in response to container lifecycle events. + Cannot be updated. + properties: + postStart: + description: 'PostStart is called immediately + after a container is created. If the handler + fails, the container is terminated and restarted + according to its restart policy. Other management + of the container blocks until the hook completes. + More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks' + properties: + exec: + description: One and only one of the following + should be specified. Exec specifies the + action to take. + properties: + command: + description: Command is the command line + to execute inside the container, the + working directory for the command is + root ('/') in the container's filesystem. + The command is simply exec'd, it is + not run inside a shell, so traditional + shell instructions ('|', etc) won't + work. To use a shell, you need to explicitly + call out to that shell. Exit status + of 0 is treated as live/healthy and + non-zero is unhealthy. + items: + type: string + type: array + type: object + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, + defaults to the pod IP. You probably + want to set "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in + the request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a + custom header to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port + to access on the container. Number must + be in the range 1 to 65535. Name must + be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting + to the host. Defaults to HTTP. + type: string + required: + - port + type: object + tcpSocket: + description: 'TCPSocket specifies an action + involving a TCP port. TCP hooks not yet + supported TODO: implement a realistic TCP + lifecycle hook' + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port + to access on the container. Number must + be in the range 1 to 65535. Name must + be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + description: 'PreStop is called immediately before + a container is terminated due to an API request + or management event such as liveness/startup + probe failure, preemption, resource contention, + etc. The handler is not called if the container + crashes or exits. The reason for termination + is passed to the handler. The Pod''s termination + grace period countdown begins before the PreStop + hooked is executed. Regardless of the outcome + of the handler, the container will eventually + terminate within the Pod''s termination grace + period. Other management of the container blocks + until the hook completes or until the termination + grace period is reached. More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks' + properties: + exec: + description: One and only one of the following + should be specified. Exec specifies the + action to take. + properties: + command: + description: Command is the command line + to execute inside the container, the + working directory for the command is + root ('/') in the container's filesystem. + The command is simply exec'd, it is + not run inside a shell, so traditional + shell instructions ('|', etc) won't + work. To use a shell, you need to explicitly + call out to that shell. Exit status + of 0 is treated as live/healthy and + non-zero is unhealthy. + items: + type: string + type: array + type: object + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, + defaults to the pod IP. You probably + want to set "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in + the request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a + custom header to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port + to access on the container. Number must + be in the range 1 to 65535. Name must + be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting + to the host. Defaults to HTTP. + type: string + required: + - port + type: object + tcpSocket: + description: 'TCPSocket specifies an action + involving a TCP port. TCP hooks not yet + supported TODO: implement a realistic TCP + lifecycle hook' + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port + to access on the container. Number must + be in the range 1 to 65535. Name must + be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + type: object + livenessProbe: + description: 'Periodic probe of container liveness. + Container will be restarted if the probe fails. + Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + properties: + exec: + description: One and only one of the following + should be specified. Exec specifies the action + to take. + properties: + command: + description: Command is the command line to + execute inside the container, the working + directory for the command is root ('/') + in the container's filesystem. The command + is simply exec'd, it is not run inside a + shell, so traditional shell instructions + ('|', etc) won't work. To use a shell, you + need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy + and non-zero is unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for + the probe to be considered failed after having + succeeded. Defaults to 3. Minimum value is 1. + format: int32 + type: integer + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, defaults + to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to + access on the container. Number must be + in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting + to the host. Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container + has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform + the probe. Default to 10 seconds. Minimum value + is 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for + the probe to be considered successful after + having failed. Defaults to 1. Must be 1 for + liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: 'TCPSocket specifies an action involving + a TCP port. TCP hooks not yet supported TODO: + implement a realistic TCP lifecycle hook' + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to + access on the container. Number must be + in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + timeoutSeconds: + description: 'Number of seconds after which the + probe times out. Defaults to 1 second. Minimum + value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + name: + description: Name of the container specified as a + DNS_LABEL. Each container in a pod must have a unique + name (DNS_LABEL). Cannot be updated. + type: string + ports: + description: List of ports to expose from the container. + Exposing a port here gives the system additional + information about the network connections a container + uses, but is primarily informational. Not specifying + a port here DOES NOT prevent that port from being + exposed. Any port which is listening on the default + "0.0.0.0" address inside a container will be accessible + from the network. Cannot be updated. + items: + description: ContainerPort represents a network + port in a single container. + properties: + containerPort: + description: Number of port to expose on the + pod's IP address. This must be a valid port + number, 0 < x < 65536. + format: int32 + type: integer + hostIP: + description: What host IP to bind the external + port to. + type: string + hostPort: + description: Number of port to expose on the + host. If specified, this must be a valid port + number, 0 < x < 65536. If HostNetwork is specified, + this must match ContainerPort. Most containers + do not need this. + format: int32 + type: integer + name: + description: If specified, this must be an IANA_SVC_NAME + and unique within the pod. Each named port + in a pod must have a unique name. Name for + the port that can be referred to by services. + type: string + protocol: + description: Protocol for port. Must be UDP, + TCP, or SCTP. Defaults to "TCP". + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + description: 'Periodic probe of container service + readiness. Container will be removed from service + endpoints if the probe fails. Cannot be updated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + properties: + exec: + description: One and only one of the following + should be specified. Exec specifies the action + to take. + properties: + command: + description: Command is the command line to + execute inside the container, the working + directory for the command is root ('/') + in the container's filesystem. The command + is simply exec'd, it is not run inside a + shell, so traditional shell instructions + ('|', etc) won't work. To use a shell, you + need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy + and non-zero is unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for + the probe to be considered failed after having + succeeded. Defaults to 3. Minimum value is 1. + format: int32 + type: integer + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, defaults + to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to + access on the container. Number must be + in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting + to the host. Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container + has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform + the probe. Default to 10 seconds. Minimum value + is 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for + the probe to be considered successful after + having failed. Defaults to 1. Must be 1 for + liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: 'TCPSocket specifies an action involving + a TCP port. TCP hooks not yet supported TODO: + implement a realistic TCP lifecycle hook' + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to + access on the container. Number must be + in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + timeoutSeconds: + description: 'Number of seconds after which the + probe times out. Defaults to 1 second. Minimum + value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + resources: + description: 'Compute Resources required by this container. + Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + properties: + 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-compute-resources-container/' + 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-compute-resources-container/' + type: object + type: object + securityContext: + description: 'Security options the pod should run + with. More info: https://kubernetes.io/docs/concepts/policy/security-context/ + More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/' + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls + whether a process can gain more privileges than + its parent process. This bool directly controls + if the no_new_privs flag will be set on the + container process. AllowPrivilegeEscalation + is true always when the container is: 1) run + as Privileged 2) has CAP_SYS_ADMIN' + type: boolean + capabilities: + description: The capabilities to add/drop when + running containers. Defaults to the default + set of capabilities granted by the container + runtime. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX + capabilities type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX + capabilities type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. + Processes in privileged containers are essentially + equivalent to root on the host. Defaults to + false. + type: boolean + procMount: + description: procMount denotes the type of proc + mount to use for the containers. The default + is DefaultProcMount which uses the container + runtime defaults for readonly paths and masked + paths. This requires the ProcMountType feature + flag to be enabled. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only + root filesystem. Default is false. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of + the container process. Uses runtime default + if unset. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes + precedence. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must + run as a non-root user. If true, the Kubelet + will validate the image at runtime to ensure + that it does not run as UID 0 (root) and fail + to start the container if it does. If unset + or false, no such validation will be performed. + May also be set in PodSecurityContext. If set + in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes + precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of + the container process. Defaults to user specified + in image metadata if unspecified. May also be + set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified + in SecurityContext takes precedence. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied + to the container. If unspecified, the container + runtime will allocate a random SELinux context + for each container. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes + precedence. + properties: + level: + description: Level is SELinux level label + that applies to the container. + type: string + role: + description: Role is a SELinux role label + that applies to the container. + type: string + type: + description: Type is a SELinux type label + that applies to the container. + type: string + user: + description: User is a SELinux user label + that applies to the container. + type: string + type: object + windowsOptions: + description: The Windows specific settings applied + to all containers. If unspecified, the options + from the PodSecurityContext will be used. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes + precedence. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the + GMSA admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential + spec named by the GMSACredentialSpecName + field. This field is alpha-level and is + only honored by servers that enable the + WindowsGMSA feature flag. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the + name of the GMSA credential spec to use. + This field is alpha-level and is only honored + by servers that enable the WindowsGMSA feature + flag. + type: string + runAsUserName: + description: The UserName in Windows to run + the entrypoint of the container process. + Defaults to the user specified in image + metadata if unspecified. May also be set + in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified + in SecurityContext takes precedence. This + field is beta-level and may be disabled + with the WindowsRunAsUserName feature flag. + type: string + type: object + type: object + startupProbe: + description: 'StartupProbe indicates that the Pod + has successfully initialized. If specified, no other + probes are executed until this completes successfully. + If this probe fails, the Pod will be restarted, + just as if the livenessProbe failed. This can be + used to provide different probe parameters at the + beginning of a Pod''s lifecycle, when it might take + a long time to load data or warm a cache, than during + steady-state operation. This cannot be updated. + This is an alpha feature enabled by the StartupProbe + feature flag. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + properties: + exec: + description: One and only one of the following + should be specified. Exec specifies the action + to take. + properties: + command: + description: Command is the command line to + execute inside the container, the working + directory for the command is root ('/') + in the container's filesystem. The command + is simply exec'd, it is not run inside a + shell, so traditional shell instructions + ('|', etc) won't work. To use a shell, you + need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy + and non-zero is unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for + the probe to be considered failed after having + succeeded. Defaults to 3. Minimum value is 1. + format: int32 + type: integer + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, defaults + to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to + access on the container. Number must be + in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting + to the host. Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container + has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform + the probe. Default to 10 seconds. Minimum value + is 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for + the probe to be considered successful after + having failed. Defaults to 1. Must be 1 for + liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: 'TCPSocket specifies an action involving + a TCP port. TCP hooks not yet supported TODO: + implement a realistic TCP lifecycle hook' + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to + access on the container. Number must be + in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + timeoutSeconds: + description: 'Number of seconds after which the + probe times out. Defaults to 1 second. Minimum + value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + stdin: + description: Whether this container should allocate + a buffer for stdin in the container runtime. If + this is not set, reads from stdin in the container + will always result in EOF. Default is false. + type: boolean + stdinOnce: + description: Whether the container runtime should + close the stdin channel after it has been opened + by a single attach. When stdin is true the stdin + stream will remain open across multiple attach sessions. + If stdinOnce is set to true, stdin is opened on + container start, is empty until the first client + attaches to stdin, and then remains open and accepts + data until the client disconnects, at which time + stdin is closed and remains closed until the container + is restarted. If this flag is false, a container + processes that reads from stdin will never receive + an EOF. Default is false + type: boolean + terminationMessagePath: + description: 'Optional: Path at which the file to + which the container''s termination message will + be written is mounted into the container''s filesystem. + Message written is intended to be brief final status, + such as an assertion failure message. Will be truncated + by the node if greater than 4096 bytes. The total + message length across all containers will be limited + to 12kb. Defaults to /dev/termination-log. Cannot + be updated.' + type: string + terminationMessagePolicy: + description: Indicate how the termination message + should be populated. File will use the contents + of terminationMessagePath to populate the container + status message on both success and failure. FallbackToLogsOnError + will use the last chunk of container log output + if the termination message file is empty and the + container exited with an error. The log output is + limited to 2048 bytes or 80 lines, whichever is + smaller. Defaults to File. Cannot be updated. + type: string + tty: + description: Whether this container should allocate + a TTY for itself, also requires 'stdin' to be true. + Default is false. + type: boolean + volumeDevices: + description: volumeDevices is the list of block devices + to be used by the container. This is a beta feature. + items: + description: volumeDevice describes a mapping of + a raw block device within a container. + properties: + devicePath: + description: devicePath is the path inside of + the container that the device will be mapped + to. + type: string + name: + description: name must match the name of a persistentVolumeClaim + in the pod + type: string + required: + - devicePath + - name + type: object + type: array + volumeMounts: + description: Pod volumes to mount into the container's + filesystem. Cannot be updated. + 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 + workingDir: + description: Container's working directory. If not + specified, the container runtime's default will + be used, which might be configured in the container + image. Cannot be updated. + type: string + required: + - name + type: object + type: array + dnsConfig: + description: Specifies the DNS parameters of a pod. Parameters + specified here will be merged to the generated DNS configuration + based on DNSPolicy. + properties: + nameservers: + description: A list of DNS name server IP addresses. + This will be appended to the base nameservers generated + from DNSPolicy. Duplicated nameservers will be removed. + items: + type: string + type: array + options: + description: A list of DNS resolver options. This will + be merged with the base options generated from DNSPolicy. + Duplicated entries will be removed. Resolution options + given in Options will override those that appear in + the base DNSPolicy. + items: + description: PodDNSConfigOption defines DNS resolver + options of a pod. + properties: + name: + description: Required. + type: string + value: + type: string + type: object + type: array + searches: + description: A list of DNS search domains for host-name + lookup. This will be appended to the base search paths + generated from DNSPolicy. Duplicated search paths + will be removed. + items: + type: string + type: array + type: object + dnsPolicy: + description: Set DNS policy for the pod. Defaults to "ClusterFirst". + Valid values are 'ClusterFirstWithHostNet', 'ClusterFirst', + 'Default' or 'None'. DNS parameters given in DNSConfig + will be merged with the policy selected with DNSPolicy. + To have DNS options set along with hostNetwork, you have + to specify DNS policy explicitly to 'ClusterFirstWithHostNet'. + type: string + enableServiceLinks: + description: 'EnableServiceLinks indicates whether information + about services should be injected into pod''s environment + variables, matching the syntax of Docker links. Optional: + Defaults to true.' + type: boolean + ephemeralContainers: + description: List of ephemeral containers run in this pod. + Ephemeral containers may be run in an existing pod to + perform user-initiated actions such as debugging. This + list cannot be specified when creating a pod, and it cannot + be modified by updating the pod spec. In order to add + an ephemeral container to an existing pod, use the pod's + ephemeralcontainers subresource. This field is alpha-level + and is only honored by servers that enable the EphemeralContainers + feature. + items: + description: An EphemeralContainer is a container that + may be added temporarily to an existing pod for user-initiated + activities such as debugging. Ephemeral containers have + no resource or scheduling guarantees, and they will + not be restarted when they exit or when a pod is removed + or restarted. If an ephemeral container causes a pod + to exceed its resource allocation, the pod may be evicted. + Ephemeral containers may not be added by directly updating + the pod spec. They must be added via the pod's ephemeralcontainers + subresource, and they will appear in the pod spec once + added. This is an alpha feature enabled by the EphemeralContainers + feature flag. + properties: + args: + description: 'Arguments to the entrypoint. The docker + image''s CMD is used if this is not provided. Variable + references $(VAR_NAME) are expanded using the container''s + environment. If a variable cannot be resolved, the + reference in the input string will be unchanged. + The $(VAR_NAME) syntax can be escaped with a double + $$, ie: $$(VAR_NAME). Escaped references will never + be expanded, regardless of whether the variable + exists or not. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell' + items: + type: string + type: array + command: + description: 'Entrypoint array. Not executed within + a shell. The docker image''s ENTRYPOINT is used + if this is not provided. Variable references $(VAR_NAME) + are expanded using the container''s environment. + If a variable cannot be resolved, the reference + in the input string will be unchanged. The $(VAR_NAME) + syntax can be escaped with a double $$, ie: $$(VAR_NAME). + Escaped references will never be expanded, regardless + of whether the variable exists or not. Cannot be + updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell' + items: + type: string + type: array + env: + description: List of environment variables to set + in the container. Cannot be updated. + 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 previous 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. The $(VAR_NAME) syntax + can be escaped with a double $$, ie: $$(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 + envFrom: + description: List of sources to populate environment + variables in the container. The keys defined within + a source must be a C_IDENTIFIER. All invalid keys + will be reported as an event when the container + is starting. When a key exists in multiple sources, + the value associated with the last source will take + precedence. Values defined by an Env with a duplicate + key will take precedence. Cannot be updated. + items: + description: EnvFromSource represents the source + of a set of ConfigMaps + properties: + configMapRef: + description: The ConfigMap to select from + 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 + optional: + description: Specify whether the ConfigMap + must be defined + type: boolean + type: object + prefix: + description: An optional identifier to prepend + to each key in the ConfigMap. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + 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 + optional: + description: Specify whether the Secret + must be defined + type: boolean + type: object + type: object + type: array + image: + description: 'Docker image name. More info: https://kubernetes.io/docs/concepts/containers/images' + type: string + imagePullPolicy: + description: 'Image pull policy. One of Always, Never, + IfNotPresent. Defaults to Always if :latest tag + is specified, or IfNotPresent otherwise. Cannot + be updated. More info: https://kubernetes.io/docs/concepts/containers/images#updating-images' + type: string + lifecycle: + description: Lifecycle is not allowed for ephemeral + containers. + properties: + postStart: + description: 'PostStart is called immediately + after a container is created. If the handler + fails, the container is terminated and restarted + according to its restart policy. Other management + of the container blocks until the hook completes. + More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks' + properties: + exec: + description: One and only one of the following + should be specified. Exec specifies the + action to take. + properties: + command: + description: Command is the command line + to execute inside the container, the + working directory for the command is + root ('/') in the container's filesystem. + The command is simply exec'd, it is + not run inside a shell, so traditional + shell instructions ('|', etc) won't + work. To use a shell, you need to explicitly + call out to that shell. Exit status + of 0 is treated as live/healthy and + non-zero is unhealthy. + items: + type: string + type: array + type: object + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, + defaults to the pod IP. You probably + want to set "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in + the request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a + custom header to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port + to access on the container. Number must + be in the range 1 to 65535. Name must + be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting + to the host. Defaults to HTTP. + type: string + required: + - port + type: object + tcpSocket: + description: 'TCPSocket specifies an action + involving a TCP port. TCP hooks not yet + supported TODO: implement a realistic TCP + lifecycle hook' + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port + to access on the container. Number must + be in the range 1 to 65535. Name must + be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + description: 'PreStop is called immediately before + a container is terminated due to an API request + or management event such as liveness/startup + probe failure, preemption, resource contention, + etc. The handler is not called if the container + crashes or exits. The reason for termination + is passed to the handler. The Pod''s termination + grace period countdown begins before the PreStop + hooked is executed. Regardless of the outcome + of the handler, the container will eventually + terminate within the Pod''s termination grace + period. Other management of the container blocks + until the hook completes or until the termination + grace period is reached. More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks' + properties: + exec: + description: One and only one of the following + should be specified. Exec specifies the + action to take. + properties: + command: + description: Command is the command line + to execute inside the container, the + working directory for the command is + root ('/') in the container's filesystem. + The command is simply exec'd, it is + not run inside a shell, so traditional + shell instructions ('|', etc) won't + work. To use a shell, you need to explicitly + call out to that shell. Exit status + of 0 is treated as live/healthy and + non-zero is unhealthy. + items: + type: string + type: array + type: object + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, + defaults to the pod IP. You probably + want to set "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in + the request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a + custom header to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port + to access on the container. Number must + be in the range 1 to 65535. Name must + be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting + to the host. Defaults to HTTP. + type: string + required: + - port + type: object + tcpSocket: + description: 'TCPSocket specifies an action + involving a TCP port. TCP hooks not yet + supported TODO: implement a realistic TCP + lifecycle hook' + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port + to access on the container. Number must + be in the range 1 to 65535. Name must + be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + type: object + livenessProbe: + description: Probes are not allowed for ephemeral + containers. + properties: + exec: + description: One and only one of the following + should be specified. Exec specifies the action + to take. + properties: + command: + description: Command is the command line to + execute inside the container, the working + directory for the command is root ('/') + in the container's filesystem. The command + is simply exec'd, it is not run inside a + shell, so traditional shell instructions + ('|', etc) won't work. To use a shell, you + need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy + and non-zero is unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for + the probe to be considered failed after having + succeeded. Defaults to 3. Minimum value is 1. + format: int32 + type: integer + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, defaults + to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to + access on the container. Number must be + in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting + to the host. Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container + has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform + the probe. Default to 10 seconds. Minimum value + is 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for + the probe to be considered successful after + having failed. Defaults to 1. Must be 1 for + liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: 'TCPSocket specifies an action involving + a TCP port. TCP hooks not yet supported TODO: + implement a realistic TCP lifecycle hook' + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to + access on the container. Number must be + in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + timeoutSeconds: + description: 'Number of seconds after which the + probe times out. Defaults to 1 second. Minimum + value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + name: + description: Name of the ephemeral container specified + as a DNS_LABEL. This name must be unique among all + containers, init containers and ephemeral containers. + type: string + ports: + description: Ports are not allowed for ephemeral containers. + items: + description: ContainerPort represents a network + port in a single container. + properties: + containerPort: + description: Number of port to expose on the + pod's IP address. This must be a valid port + number, 0 < x < 65536. + format: int32 + type: integer + hostIP: + description: What host IP to bind the external + port to. + type: string + hostPort: + description: Number of port to expose on the + host. If specified, this must be a valid port + number, 0 < x < 65536. If HostNetwork is specified, + this must match ContainerPort. Most containers + do not need this. + format: int32 + type: integer + name: + description: If specified, this must be an IANA_SVC_NAME + and unique within the pod. Each named port + in a pod must have a unique name. Name for + the port that can be referred to by services. + type: string + protocol: + description: Protocol for port. Must be UDP, + TCP, or SCTP. Defaults to "TCP". + type: string + required: + - containerPort + type: object + type: array + readinessProbe: + description: Probes are not allowed for ephemeral + containers. + properties: + exec: + description: One and only one of the following + should be specified. Exec specifies the action + to take. + properties: + command: + description: Command is the command line to + execute inside the container, the working + directory for the command is root ('/') + in the container's filesystem. The command + is simply exec'd, it is not run inside a + shell, so traditional shell instructions + ('|', etc) won't work. To use a shell, you + need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy + and non-zero is unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for + the probe to be considered failed after having + succeeded. Defaults to 3. Minimum value is 1. + format: int32 + type: integer + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, defaults + to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to + access on the container. Number must be + in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting + to the host. Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container + has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform + the probe. Default to 10 seconds. Minimum value + is 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for + the probe to be considered successful after + having failed. Defaults to 1. Must be 1 for + liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: 'TCPSocket specifies an action involving + a TCP port. TCP hooks not yet supported TODO: + implement a realistic TCP lifecycle hook' + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to + access on the container. Number must be + in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + timeoutSeconds: + description: 'Number of seconds after which the + probe times out. Defaults to 1 second. Minimum + value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + resources: + description: Resources are not allowed for ephemeral + containers. Ephemeral containers use spare resources + already allocated to the pod. + properties: + 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-compute-resources-container/' + 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-compute-resources-container/' + type: object + type: object + securityContext: + description: SecurityContext is not allowed for ephemeral + containers. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls + whether a process can gain more privileges than + its parent process. This bool directly controls + if the no_new_privs flag will be set on the + container process. AllowPrivilegeEscalation + is true always when the container is: 1) run + as Privileged 2) has CAP_SYS_ADMIN' + type: boolean + capabilities: + description: The capabilities to add/drop when + running containers. Defaults to the default + set of capabilities granted by the container + runtime. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX + capabilities type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX + capabilities type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. + Processes in privileged containers are essentially + equivalent to root on the host. Defaults to + false. + type: boolean + procMount: + description: procMount denotes the type of proc + mount to use for the containers. The default + is DefaultProcMount which uses the container + runtime defaults for readonly paths and masked + paths. This requires the ProcMountType feature + flag to be enabled. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only + root filesystem. Default is false. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of + the container process. Uses runtime default + if unset. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes + precedence. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must + run as a non-root user. If true, the Kubelet + will validate the image at runtime to ensure + that it does not run as UID 0 (root) and fail + to start the container if it does. If unset + or false, no such validation will be performed. + May also be set in PodSecurityContext. If set + in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes + precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of + the container process. Defaults to user specified + in image metadata if unspecified. May also be + set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified + in SecurityContext takes precedence. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied + to the container. If unspecified, the container + runtime will allocate a random SELinux context + for each container. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes + precedence. + properties: + level: + description: Level is SELinux level label + that applies to the container. + type: string + role: + description: Role is a SELinux role label + that applies to the container. + type: string + type: + description: Type is a SELinux type label + that applies to the container. + type: string + user: + description: User is a SELinux user label + that applies to the container. + type: string + type: object + windowsOptions: + description: The Windows specific settings applied + to all containers. If unspecified, the options + from the PodSecurityContext will be used. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes + precedence. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the + GMSA admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential + spec named by the GMSACredentialSpecName + field. This field is alpha-level and is + only honored by servers that enable the + WindowsGMSA feature flag. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the + name of the GMSA credential spec to use. + This field is alpha-level and is only honored + by servers that enable the WindowsGMSA feature + flag. + type: string + runAsUserName: + description: The UserName in Windows to run + the entrypoint of the container process. + Defaults to the user specified in image + metadata if unspecified. May also be set + in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified + in SecurityContext takes precedence. This + field is beta-level and may be disabled + with the WindowsRunAsUserName feature flag. + type: string + type: object + type: object + startupProbe: + description: Probes are not allowed for ephemeral + containers. + properties: + exec: + description: One and only one of the following + should be specified. Exec specifies the action + to take. + properties: + command: + description: Command is the command line to + execute inside the container, the working + directory for the command is root ('/') + in the container's filesystem. The command + is simply exec'd, it is not run inside a + shell, so traditional shell instructions + ('|', etc) won't work. To use a shell, you + need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy + and non-zero is unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for + the probe to be considered failed after having + succeeded. Defaults to 3. Minimum value is 1. + format: int32 + type: integer + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, defaults + to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to + access on the container. Number must be + in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting + to the host. Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container + has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform + the probe. Default to 10 seconds. Minimum value + is 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for + the probe to be considered successful after + having failed. Defaults to 1. Must be 1 for + liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: 'TCPSocket specifies an action involving + a TCP port. TCP hooks not yet supported TODO: + implement a realistic TCP lifecycle hook' + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to + access on the container. Number must be + in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + timeoutSeconds: + description: 'Number of seconds after which the + probe times out. Defaults to 1 second. Minimum + value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + stdin: + description: Whether this container should allocate + a buffer for stdin in the container runtime. If + this is not set, reads from stdin in the container + will always result in EOF. Default is false. + type: boolean + stdinOnce: + description: Whether the container runtime should + close the stdin channel after it has been opened + by a single attach. When stdin is true the stdin + stream will remain open across multiple attach sessions. + If stdinOnce is set to true, stdin is opened on + container start, is empty until the first client + attaches to stdin, and then remains open and accepts + data until the client disconnects, at which time + stdin is closed and remains closed until the container + is restarted. If this flag is false, a container + processes that reads from stdin will never receive + an EOF. Default is false + type: boolean + targetContainerName: + description: If set, the name of the container from + PodSpec that this ephemeral container targets. The + ephemeral container will be run in the namespaces + (IPC, PID, etc) of this container. If not set then + the ephemeral container is run in whatever namespaces + are shared for the pod. Note that the container + runtime must support this feature. + type: string + terminationMessagePath: + description: 'Optional: Path at which the file to + which the container''s termination message will + be written is mounted into the container''s filesystem. + Message written is intended to be brief final status, + such as an assertion failure message. Will be truncated + by the node if greater than 4096 bytes. The total + message length across all containers will be limited + to 12kb. Defaults to /dev/termination-log. Cannot + be updated.' + type: string + terminationMessagePolicy: + description: Indicate how the termination message + should be populated. File will use the contents + of terminationMessagePath to populate the container + status message on both success and failure. FallbackToLogsOnError + will use the last chunk of container log output + if the termination message file is empty and the + container exited with an error. The log output is + limited to 2048 bytes or 80 lines, whichever is + smaller. Defaults to File. Cannot be updated. + type: string + tty: + description: Whether this container should allocate + a TTY for itself, also requires 'stdin' to be true. + Default is false. + type: boolean + volumeDevices: + description: volumeDevices is the list of block devices + to be used by the container. This is a beta feature. + items: + description: volumeDevice describes a mapping of + a raw block device within a container. + properties: + devicePath: + description: devicePath is the path inside of + the container that the device will be mapped + to. + type: string + name: + description: name must match the name of a persistentVolumeClaim + in the pod + type: string + required: + - devicePath + - name + type: object + type: array + volumeMounts: + description: Pod volumes to mount into the container's + filesystem. Cannot be updated. + 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 + workingDir: + description: Container's working directory. If not + specified, the container runtime's default will + be used, which might be configured in the container + image. Cannot be updated. + type: string + required: + - name + type: object + type: array + hostAliases: + description: HostAliases is an optional list of hosts and + IPs that will be injected into the pod's hosts file if + specified. This is only valid for non-hostNetwork pods. + items: + description: HostAlias holds the mapping between IP and + hostnames that will be injected as an entry in the pod's + hosts file. + properties: + hostnames: + description: Hostnames for the above IP address. + items: + type: string + type: array + ip: + description: IP address of the host file entry. + type: string + type: object + type: array + hostIPC: + description: 'Use the host''s ipc namespace. Optional: Default + to false.' + type: boolean + hostNetwork: + description: Host networking requested for this pod. Use + the host's network namespace. If this option is set, the + ports that will be used must be specified. Default to + false. + type: boolean + hostPID: + description: 'Use the host''s pid namespace. Optional: Default + to false.' + type: boolean + hostname: + description: Specifies the hostname of the Pod If not specified, + the pod's hostname will be set to a system-defined value. + type: string + imagePullSecrets: + description: 'ImagePullSecrets is an optional list of references + to secrets in the same namespace to use for pulling any + of the images used by this PodSpec. If specified, these + secrets will be passed to individual puller implementations + for them to use. For example, in the case of docker, only + DockerConfig type secrets are honored. More info: https://kubernetes.io/docs/concepts/containers/images#specifying-imagepullsecrets-on-a-pod' + items: + description: LocalObjectReference contains enough information + to let you locate the referenced object inside the same + namespace. + 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 + type: array + initContainers: + description: 'List of initialization containers belonging + to the pod. Init containers are executed in order prior + to containers being started. If any init container fails, + the pod is considered to have failed and is handled according + to its restartPolicy. The name for an init container or + normal container must be unique among all containers. + Init containers may not have Lifecycle actions, Readiness + probes, Liveness probes, or Startup probes. The resourceRequirements + of an init container are taken into account during scheduling + by finding the highest request/limit for each resource + type, and then using the max of of that value or the sum + of the normal containers. Limits are applied to init containers + in a similar fashion. Init containers cannot currently + be added or removed. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/' + items: + description: A single application container that you want + to run within a pod. + properties: + args: + description: 'Arguments to the entrypoint. The docker + image''s CMD is used if this is not provided. Variable + references $(VAR_NAME) are expanded using the container''s + environment. If a variable cannot be resolved, the + reference in the input string will be unchanged. + The $(VAR_NAME) syntax can be escaped with a double + $$, ie: $$(VAR_NAME). Escaped references will never + be expanded, regardless of whether the variable + exists or not. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell' + items: + type: string + type: array + command: + description: 'Entrypoint array. Not executed within + a shell. The docker image''s ENTRYPOINT is used + if this is not provided. Variable references $(VAR_NAME) + are expanded using the container''s environment. + If a variable cannot be resolved, the reference + in the input string will be unchanged. The $(VAR_NAME) + syntax can be escaped with a double $$, ie: $$(VAR_NAME). + Escaped references will never be expanded, regardless + of whether the variable exists or not. Cannot be + updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell' + items: + type: string + type: array + env: + description: List of environment variables to set + in the container. Cannot be updated. + 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 previous 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. The $(VAR_NAME) syntax + can be escaped with a double $$, ie: $$(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 + envFrom: + description: List of sources to populate environment + variables in the container. The keys defined within + a source must be a C_IDENTIFIER. All invalid keys + will be reported as an event when the container + is starting. When a key exists in multiple sources, + the value associated with the last source will take + precedence. Values defined by an Env with a duplicate + key will take precedence. Cannot be updated. + items: + description: EnvFromSource represents the source + of a set of ConfigMaps + properties: + configMapRef: + description: The ConfigMap to select from + 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 + optional: + description: Specify whether the ConfigMap + must be defined + type: boolean + type: object + prefix: + description: An optional identifier to prepend + to each key in the ConfigMap. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + 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 + optional: + description: Specify whether the Secret + must be defined + type: boolean + type: object + type: object + type: array + image: + description: 'Docker image name. More info: https://kubernetes.io/docs/concepts/containers/images + This field is optional to allow higher level config + management to default or override container images + in workload controllers like Deployments and StatefulSets.' + type: string + imagePullPolicy: + description: 'Image pull policy. One of Always, Never, + IfNotPresent. Defaults to Always if :latest tag + is specified, or IfNotPresent otherwise. Cannot + be updated. More info: https://kubernetes.io/docs/concepts/containers/images#updating-images' + type: string + lifecycle: + description: Actions that the management system should + take in response to container lifecycle events. + Cannot be updated. + properties: + postStart: + description: 'PostStart is called immediately + after a container is created. If the handler + fails, the container is terminated and restarted + according to its restart policy. Other management + of the container blocks until the hook completes. + More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks' + properties: + exec: + description: One and only one of the following + should be specified. Exec specifies the + action to take. + properties: + command: + description: Command is the command line + to execute inside the container, the + working directory for the command is + root ('/') in the container's filesystem. + The command is simply exec'd, it is + not run inside a shell, so traditional + shell instructions ('|', etc) won't + work. To use a shell, you need to explicitly + call out to that shell. Exit status + of 0 is treated as live/healthy and + non-zero is unhealthy. + items: + type: string + type: array + type: object + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, + defaults to the pod IP. You probably + want to set "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in + the request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a + custom header to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port + to access on the container. Number must + be in the range 1 to 65535. Name must + be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting + to the host. Defaults to HTTP. + type: string + required: + - port + type: object + tcpSocket: + description: 'TCPSocket specifies an action + involving a TCP port. TCP hooks not yet + supported TODO: implement a realistic TCP + lifecycle hook' + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port + to access on the container. Number must + be in the range 1 to 65535. Name must + be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + description: 'PreStop is called immediately before + a container is terminated due to an API request + or management event such as liveness/startup + probe failure, preemption, resource contention, + etc. The handler is not called if the container + crashes or exits. The reason for termination + is passed to the handler. The Pod''s termination + grace period countdown begins before the PreStop + hooked is executed. Regardless of the outcome + of the handler, the container will eventually + terminate within the Pod''s termination grace + period. Other management of the container blocks + until the hook completes or until the termination + grace period is reached. More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks' + properties: + exec: + description: One and only one of the following + should be specified. Exec specifies the + action to take. + properties: + command: + description: Command is the command line + to execute inside the container, the + working directory for the command is + root ('/') in the container's filesystem. + The command is simply exec'd, it is + not run inside a shell, so traditional + shell instructions ('|', etc) won't + work. To use a shell, you need to explicitly + call out to that shell. Exit status + of 0 is treated as live/healthy and + non-zero is unhealthy. + items: + type: string + type: array + type: object + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, + defaults to the pod IP. You probably + want to set "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in + the request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a + custom header to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port + to access on the container. Number must + be in the range 1 to 65535. Name must + be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting + to the host. Defaults to HTTP. + type: string + required: + - port + type: object + tcpSocket: + description: 'TCPSocket specifies an action + involving a TCP port. TCP hooks not yet + supported TODO: implement a realistic TCP + lifecycle hook' + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port + to access on the container. Number must + be in the range 1 to 65535. Name must + be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + type: object + livenessProbe: + description: 'Periodic probe of container liveness. + Container will be restarted if the probe fails. + Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + properties: + exec: + description: One and only one of the following + should be specified. Exec specifies the action + to take. + properties: + command: + description: Command is the command line to + execute inside the container, the working + directory for the command is root ('/') + in the container's filesystem. The command + is simply exec'd, it is not run inside a + shell, so traditional shell instructions + ('|', etc) won't work. To use a shell, you + need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy + and non-zero is unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for + the probe to be considered failed after having + succeeded. Defaults to 3. Minimum value is 1. + format: int32 + type: integer + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, defaults + to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to + access on the container. Number must be + in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting + to the host. Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container + has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform + the probe. Default to 10 seconds. Minimum value + is 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for + the probe to be considered successful after + having failed. Defaults to 1. Must be 1 for + liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: 'TCPSocket specifies an action involving + a TCP port. TCP hooks not yet supported TODO: + implement a realistic TCP lifecycle hook' + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to + access on the container. Number must be + in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + timeoutSeconds: + description: 'Number of seconds after which the + probe times out. Defaults to 1 second. Minimum + value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + name: + description: Name of the container specified as a + DNS_LABEL. Each container in a pod must have a unique + name (DNS_LABEL). Cannot be updated. + type: string + ports: + description: List of ports to expose from the container. + Exposing a port here gives the system additional + information about the network connections a container + uses, but is primarily informational. Not specifying + a port here DOES NOT prevent that port from being + exposed. Any port which is listening on the default + "0.0.0.0" address inside a container will be accessible + from the network. Cannot be updated. + items: + description: ContainerPort represents a network + port in a single container. + properties: + containerPort: + description: Number of port to expose on the + pod's IP address. This must be a valid port + number, 0 < x < 65536. + format: int32 + type: integer + hostIP: + description: What host IP to bind the external + port to. + type: string + hostPort: + description: Number of port to expose on the + host. If specified, this must be a valid port + number, 0 < x < 65536. If HostNetwork is specified, + this must match ContainerPort. Most containers + do not need this. + format: int32 + type: integer + name: + description: If specified, this must be an IANA_SVC_NAME + and unique within the pod. Each named port + in a pod must have a unique name. Name for + the port that can be referred to by services. + type: string + protocol: + description: Protocol for port. Must be UDP, + TCP, or SCTP. Defaults to "TCP". + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + description: 'Periodic probe of container service + readiness. Container will be removed from service + endpoints if the probe fails. Cannot be updated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + properties: + exec: + description: One and only one of the following + should be specified. Exec specifies the action + to take. + properties: + command: + description: Command is the command line to + execute inside the container, the working + directory for the command is root ('/') + in the container's filesystem. The command + is simply exec'd, it is not run inside a + shell, so traditional shell instructions + ('|', etc) won't work. To use a shell, you + need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy + and non-zero is unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for + the probe to be considered failed after having + succeeded. Defaults to 3. Minimum value is 1. + format: int32 + type: integer + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, defaults + to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to + access on the container. Number must be + in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting + to the host. Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container + has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform + the probe. Default to 10 seconds. Minimum value + is 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for + the probe to be considered successful after + having failed. Defaults to 1. Must be 1 for + liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: 'TCPSocket specifies an action involving + a TCP port. TCP hooks not yet supported TODO: + implement a realistic TCP lifecycle hook' + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to + access on the container. Number must be + in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + timeoutSeconds: + description: 'Number of seconds after which the + probe times out. Defaults to 1 second. Minimum + value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + resources: + description: 'Compute Resources required by this container. + Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + properties: + 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-compute-resources-container/' + 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-compute-resources-container/' + type: object + type: object + securityContext: + description: 'Security options the pod should run + with. More info: https://kubernetes.io/docs/concepts/policy/security-context/ + More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/' + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls + whether a process can gain more privileges than + its parent process. This bool directly controls + if the no_new_privs flag will be set on the + container process. AllowPrivilegeEscalation + is true always when the container is: 1) run + as Privileged 2) has CAP_SYS_ADMIN' + type: boolean + capabilities: + description: The capabilities to add/drop when + running containers. Defaults to the default + set of capabilities granted by the container + runtime. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX + capabilities type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX + capabilities type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. + Processes in privileged containers are essentially + equivalent to root on the host. Defaults to + false. + type: boolean + procMount: + description: procMount denotes the type of proc + mount to use for the containers. The default + is DefaultProcMount which uses the container + runtime defaults for readonly paths and masked + paths. This requires the ProcMountType feature + flag to be enabled. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only + root filesystem. Default is false. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of + the container process. Uses runtime default + if unset. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes + precedence. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must + run as a non-root user. If true, the Kubelet + will validate the image at runtime to ensure + that it does not run as UID 0 (root) and fail + to start the container if it does. If unset + or false, no such validation will be performed. + May also be set in PodSecurityContext. If set + in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes + precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of + the container process. Defaults to user specified + in image metadata if unspecified. May also be + set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified + in SecurityContext takes precedence. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied + to the container. If unspecified, the container + runtime will allocate a random SELinux context + for each container. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes + precedence. + properties: + level: + description: Level is SELinux level label + that applies to the container. + type: string + role: + description: Role is a SELinux role label + that applies to the container. + type: string + type: + description: Type is a SELinux type label + that applies to the container. + type: string + user: + description: User is a SELinux user label + that applies to the container. + type: string + type: object + windowsOptions: + description: The Windows specific settings applied + to all containers. If unspecified, the options + from the PodSecurityContext will be used. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes + precedence. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the + GMSA admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential + spec named by the GMSACredentialSpecName + field. This field is alpha-level and is + only honored by servers that enable the + WindowsGMSA feature flag. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the + name of the GMSA credential spec to use. + This field is alpha-level and is only honored + by servers that enable the WindowsGMSA feature + flag. + type: string + runAsUserName: + description: The UserName in Windows to run + the entrypoint of the container process. + Defaults to the user specified in image + metadata if unspecified. May also be set + in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified + in SecurityContext takes precedence. This + field is beta-level and may be disabled + with the WindowsRunAsUserName feature flag. + type: string + type: object + type: object + startupProbe: + description: 'StartupProbe indicates that the Pod + has successfully initialized. If specified, no other + probes are executed until this completes successfully. + If this probe fails, the Pod will be restarted, + just as if the livenessProbe failed. This can be + used to provide different probe parameters at the + beginning of a Pod''s lifecycle, when it might take + a long time to load data or warm a cache, than during + steady-state operation. This cannot be updated. + This is an alpha feature enabled by the StartupProbe + feature flag. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + properties: + exec: + description: One and only one of the following + should be specified. Exec specifies the action + to take. + properties: + command: + description: Command is the command line to + execute inside the container, the working + directory for the command is root ('/') + in the container's filesystem. The command + is simply exec'd, it is not run inside a + shell, so traditional shell instructions + ('|', etc) won't work. To use a shell, you + need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy + and non-zero is unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for + the probe to be considered failed after having + succeeded. Defaults to 3. Minimum value is 1. + format: int32 + type: integer + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, defaults + to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to + access on the container. Number must be + in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting + to the host. Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container + has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform + the probe. Default to 10 seconds. Minimum value + is 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for + the probe to be considered successful after + having failed. Defaults to 1. Must be 1 for + liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: 'TCPSocket specifies an action involving + a TCP port. TCP hooks not yet supported TODO: + implement a realistic TCP lifecycle hook' + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to + access on the container. Number must be + in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + timeoutSeconds: + description: 'Number of seconds after which the + probe times out. Defaults to 1 second. Minimum + value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + stdin: + description: Whether this container should allocate + a buffer for stdin in the container runtime. If + this is not set, reads from stdin in the container + will always result in EOF. Default is false. + type: boolean + stdinOnce: + description: Whether the container runtime should + close the stdin channel after it has been opened + by a single attach. When stdin is true the stdin + stream will remain open across multiple attach sessions. + If stdinOnce is set to true, stdin is opened on + container start, is empty until the first client + attaches to stdin, and then remains open and accepts + data until the client disconnects, at which time + stdin is closed and remains closed until the container + is restarted. If this flag is false, a container + processes that reads from stdin will never receive + an EOF. Default is false + type: boolean + terminationMessagePath: + description: 'Optional: Path at which the file to + which the container''s termination message will + be written is mounted into the container''s filesystem. + Message written is intended to be brief final status, + such as an assertion failure message. Will be truncated + by the node if greater than 4096 bytes. The total + message length across all containers will be limited + to 12kb. Defaults to /dev/termination-log. Cannot + be updated.' + type: string + terminationMessagePolicy: + description: Indicate how the termination message + should be populated. File will use the contents + of terminationMessagePath to populate the container + status message on both success and failure. FallbackToLogsOnError + will use the last chunk of container log output + if the termination message file is empty and the + container exited with an error. The log output is + limited to 2048 bytes or 80 lines, whichever is + smaller. Defaults to File. Cannot be updated. + type: string + tty: + description: Whether this container should allocate + a TTY for itself, also requires 'stdin' to be true. + Default is false. + type: boolean + volumeDevices: + description: volumeDevices is the list of block devices + to be used by the container. This is a beta feature. + items: + description: volumeDevice describes a mapping of + a raw block device within a container. + properties: + devicePath: + description: devicePath is the path inside of + the container that the device will be mapped + to. + type: string + name: + description: name must match the name of a persistentVolumeClaim + in the pod + type: string + required: + - devicePath + - name + type: object + type: array + volumeMounts: + description: Pod volumes to mount into the container's + filesystem. Cannot be updated. + 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 + workingDir: + description: Container's working directory. If not + specified, the container runtime's default will + be used, which might be configured in the container + image. Cannot be updated. + type: string + required: + - name + type: object + type: array + nodeName: + description: NodeName is a request to schedule this pod + onto a specific node. If it is non-empty, the scheduler + simply schedules this pod onto that node, assuming that + it fits resource requirements. + type: string + nodeSelector: + additionalProperties: + type: string + description: 'NodeSelector is a selector which must be true + for the pod to fit on a node. Selector which must match + a node''s labels for the pod to be scheduled on that node. + More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/' + type: object + overhead: + 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: 'Overhead represents the resource overhead + associated with running a pod for a given RuntimeClass. + This field will be autopopulated at admission time by + the RuntimeClass admission controller. If the RuntimeClass + admission controller is enabled, overhead must not be + set in Pod create requests. The RuntimeClass admission + controller will reject Pod create requests which have + the overhead already set. If RuntimeClass is configured + and selected in the PodSpec, Overhead will be set to the + value defined in the corresponding RuntimeClass, otherwise + it will remain unset and treated as zero. More info: https://git.k8s.io/enhancements/keps/sig-node/20190226-pod-overhead.md + This field is alpha-level as of Kubernetes v1.16, and + is only honored by servers that enable the PodOverhead + feature.' + type: object + preemptionPolicy: + description: PreemptionPolicy is the Policy for preempting + pods with lower priority. One of Never, PreemptLowerPriority. + Defaults to PreemptLowerPriority if unset. This field + is alpha-level and is only honored by servers that enable + the NonPreemptingPriority feature. + type: string + priority: + description: The priority value. Various system components + use this field to find the priority of the pod. When Priority + Admission Controller is enabled, it prevents users from + setting this field. The admission controller populates + this field from PriorityClassName. The higher the value, + the higher the priority. + format: int32 + type: integer + priorityClassName: + description: If specified, indicates the pod's priority. + "system-node-critical" and "system-cluster-critical" are + two special keywords which indicate the highest priorities + with the former being the highest priority. Any other + name must be defined by creating a PriorityClass object + with that name. If not specified, the pod priority will + be default or zero if there is no default. + type: string + readinessGates: + description: 'If specified, all readiness gates will be + evaluated for pod readiness. A pod is ready when all its + containers are ready AND all conditions specified in the + readiness gates have status equal to "True" More info: + https://git.k8s.io/enhancements/keps/sig-network/0007-pod-ready%2B%2B.md' + items: + description: PodReadinessGate contains the reference to + a pod condition + properties: + conditionType: + description: ConditionType refers to a condition in + the pod's condition list with matching type. + type: string + required: + - conditionType + type: object + type: array + restartPolicy: + description: 'Restart policy for all containers within the + pod. One of Always, OnFailure, Never. Default to Always. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#restart-policy' + type: string + runtimeClassName: + description: 'RuntimeClassName refers to a RuntimeClass + object in the node.k8s.io group, which should be used + to run this pod. If no RuntimeClass resource matches + the named class, the pod will not be run. If unset or + empty, the "legacy" RuntimeClass will be used, which is + an implicit class with an empty definition that uses the + default runtime handler. More info: https://git.k8s.io/enhancements/keps/sig-node/runtime-class.md + This is a beta feature as of Kubernetes v1.14.' + type: string + schedulerName: + description: If specified, the pod will be dispatched by + specified scheduler. If not specified, the pod will be + dispatched by default scheduler. + type: string + securityContext: + description: 'SecurityContext holds pod-level security attributes + and common container settings. Optional: Defaults to empty. See + type description for default values of each field.' + properties: + fsGroup: + description: "A special supplemental group that applies + to all containers in a pod. Some volume types allow + the Kubelet to change the ownership of that volume + to be owned by the pod: \n 1. The owning GID will + be the FSGroup 2. The setgid bit is set (new files + created in the volume will be owned by FSGroup) 3. + The permission bits are OR'd with rw-rw---- \n If + unset, the Kubelet will not modify the ownership and + permissions of any volume." + format: int64 + type: integer + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be + set in SecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as + a non-root user. If true, the Kubelet will validate + the image at runtime to ensure that it does not run + as UID 0 (root) and fail to start the container if + it does. If unset or false, no such validation will + be performed. May also be set in SecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata + if unspecified. May also be set in SecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence + for that container. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to all + containers. If unspecified, the container runtime + will allocate a random SELinux context for each container. May + also be set in SecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + supplementalGroups: + description: A list of groups applied to the first process + run in each container, in addition to the container's + primary GID. If unspecified, no groups will be added + to any container. + items: + format: int64 + type: integer + type: array + sysctls: + description: Sysctls hold a list of namespaced sysctls + used for the pod. Pods with unsupported sysctls (by + the container runtime) might fail to launch. + items: + description: Sysctl defines a kernel parameter to + be set + properties: + name: + description: Name of a property to set + type: string + value: + description: Value of a property to set + type: string + required: + - name + - value + type: object + type: array + windowsOptions: + description: The Windows specific settings applied to + all containers. If unspecified, the options within + a container's SecurityContext will be used. If set + in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA + admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec + named by the GMSACredentialSpecName field. This + field is alpha-level and is only honored by servers + that enable the WindowsGMSA feature flag. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name + of the GMSA credential spec to use. This field + is alpha-level and is only honored by servers + that enable the WindowsGMSA feature flag. + type: string + runAsUserName: + description: The UserName in Windows to run the + entrypoint of the container process. Defaults + to the user specified in image metadata if unspecified. + May also be set in PodSecurityContext. If set + in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + This field is beta-level and may be disabled with + the WindowsRunAsUserName feature flag. + type: string + type: object + type: object + serviceAccount: + description: 'DeprecatedServiceAccount is a depreciated + alias for ServiceAccountName. Deprecated: Use serviceAccountName + instead.' + type: string + serviceAccountName: + description: 'ServiceAccountName is the name of the ServiceAccount + to use to run this pod. More info: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/' + type: string + shareProcessNamespace: + description: 'Share a single process namespace between all + of the containers in a pod. When this is set containers + will be able to view and signal processes from other containers + in the same pod, and the first process in each container + will not be assigned PID 1. HostPID and ShareProcessNamespace + cannot both be set. Optional: Default to false.' + type: boolean + subdomain: + description: If specified, the fully qualified Pod hostname + will be "...svc.". If not specified, the pod will not have a domainname + at all. + type: string + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs + to terminate gracefully. May be decreased in delete request. + Value must be non-negative integer. The value zero indicates + delete immediately. If this value is nil, the default + grace period will be used instead. The grace period is + the duration in seconds after the processes running in + the pod are sent a termination signal and the time when + the processes are forcibly halted with a kill signal. + Set this value longer than the expected cleanup time for + your process. Defaults to 30 seconds. + format: int64 + type: integer + tolerations: + description: If specified, the pod's tolerations. + items: + description: The pod this Toleration is attached to tolerates + any taint that matches the triple + using the matching operator . + properties: + effect: + description: Effect indicates the taint effect to + match. Empty means match all taint effects. When + specified, allowed values are NoSchedule, PreferNoSchedule + and NoExecute. + type: string + key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. If + the key is empty, operator must be Exists; this + combination means to match all values and all keys. + type: string + operator: + description: Operator represents a key's relationship + to the value. Valid operators are Exists and Equal. + Defaults to Equal. Exists is equivalent to wildcard + for value, so that a pod can tolerate all taints + of a particular category. + type: string + tolerationSeconds: + description: TolerationSeconds represents the period + of time the toleration (which must be of effect + NoExecute, otherwise this field is ignored) tolerates + the taint. By default, it is not set, which means + tolerate the taint forever (do not evict). Zero + and negative values will be treated as 0 (evict + immediately) by the system. + format: int64 + type: integer + value: + description: Value is the taint value the toleration + matches to. If the operator is Exists, the value + should be empty, otherwise just a regular string. + type: string + type: object + type: array + topologySpreadConstraints: + description: TopologySpreadConstraints describes how a group + of pods ought to spread across topology domains. Scheduler + will schedule pods in a way which abides by the constraints. + This field is alpha-level and is only honored by clusters + that enables the EvenPodsSpread feature. All topologySpreadConstraints + are ANDed. + items: + description: TopologySpreadConstraint specifies how to + spread matching pods among the given topology. + properties: + labelSelector: + description: LabelSelector is used to find matching + pods. Pods that match this label selector are counted + to determine the number of pods in their corresponding + topology domain. + 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 + maxSkew: + description: 'MaxSkew describes the degree to which + pods may be unevenly distributed. It''s the maximum + permitted difference between the number of matching + pods in any two topology domains of a given topology + type. For example, in a 3-zone cluster, MaxSkew + is set to 1, and pods with the same labelSelector + spread as 1/1/0: | zone1 | zone2 | zone3 | | P | P | | + - if MaxSkew is 1, incoming pod can only be scheduled + to zone3 to become 1/1/1; scheduling it onto zone1(zone2) + would make the ActualSkew(2-0) on zone1(zone2) violate + MaxSkew(1). - if MaxSkew is 2, incoming pod can + be scheduled onto any zone. It''s a required field. + Default value is 1 and 0 is not allowed.' + format: int32 + type: integer + topologyKey: + description: TopologyKey is the key of node labels. + Nodes that have a label with this key and identical + values are considered to be in the same topology. + We consider each as a "bucket", and + try to put balanced number of pods into each bucket. + It's a required field. + type: string + whenUnsatisfiable: + description: 'WhenUnsatisfiable indicates how to deal + with a pod if it doesn''t satisfy the spread constraint. + - DoNotSchedule (default) tells the scheduler not + to schedule it - ScheduleAnyway tells the scheduler + to still schedule it It''s considered as "Unsatisfiable" + if and only if placing incoming pod on any topology + violates "MaxSkew". For example, in a 3-zone cluster, + MaxSkew is set to 1, and pods with the same labelSelector + spread as 3/1/1: | zone1 | zone2 | zone3 | | P P + P | P | P | If WhenUnsatisfiable is set + to DoNotSchedule, incoming pod can only be scheduled + to zone2(zone3) to become 3/2/1(3/1/2) as ActualSkew(2-1) + on zone2(zone3) satisfies MaxSkew(1). In other words, + the cluster can still be imbalanced, but scheduler + won''t make it *more* imbalanced. It''s a required + field.' + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array + x-kubernetes-list-map-keys: + - topologyKey + - whenUnsatisfiable + x-kubernetes-list-type: map + volumes: + description: 'List of volumes that can be mounted by containers + belonging to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes' + 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: '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: '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: 'Specify "true" to force and set + the ReadOnly property in VolumeMounts to "true". + If omitted, the default is "false". More info: + https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + type: boolean + volumeID: + description: '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: 'Host Caching mode: None, Read Only, + Read Write.' + type: string + diskName: + description: The Name of the data disk in the + blob storage + type: string + diskURI: + description: The URI the data disk in the blob + storage + type: string + fsType: + description: 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: 'Expected values 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: 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: Defaults to false (read/write). ReadOnly + here will force the ReadOnly setting in VolumeMounts. + type: boolean + secretName: + description: the name of secret that contains + Azure Storage Account Name and Key + type: string + shareName: + description: 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: '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: 'Optional: Used as the mounted root, + rather than the full Ceph tree, default is /' + type: string + readOnly: + description: '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: '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: '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: '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: '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: 'Optional: 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: '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: 'volume id 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: 'Optional: mode bits to use on created + files by default. Must be a value between 0 + and 0777. 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: 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: The key to project. + type: string + mode: + description: 'Optional: mode bits to use + on this file, must be a value between + 0 and 0777. 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: 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: Specify whether the ConfigMap or + its keys must be defined + type: boolean + type: object + csi: + description: CSI (Container Storage Interface) represents + storage that is handled by an external CSI driver + (Alpha 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: Filesystem type 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: 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 value between 0 + and 0777. 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 to use + on this file, must be a value between + 0 and 0777. 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: '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: '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 + 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: '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: 'Optional: FC target lun number' + format: int32 + type: integer + readOnly: + description: 'Optional: Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts.' + type: boolean + targetWWNs: + description: 'Optional: FC target worldwide names + (WWNs)' + items: + type: string + type: array + wwids: + description: '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: 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: 'Optional: Extra command options + if any.' + type: object + readOnly: + description: 'Optional: Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts.' + type: boolean + secretRef: + description: '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: Name of the dataset stored as metadata + -> name on the dataset for Flocker should be + considered as deprecated + type: string + datasetUUID: + description: 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: '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: '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: '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: 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 URL + type: string + revision: + description: 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: 'EndpointsName 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: whether support iSCSI Discovery CHAP + authentication + type: boolean + chapAuthSession: + description: whether support iSCSI Session CHAP + authentication + type: boolean + fsType: + description: '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: Custom iSCSI Initiator Name. If initiatorName + is specified with iscsiInterface simultaneously, + new iSCSI interface : will be created for the connection. + type: string + iqn: + description: Target iSCSI Qualified Name. + type: string + iscsiInterface: + description: iSCSI Interface Name that uses an + iSCSI transport. Defaults to 'default' (tcp). + type: string + lun: + description: iSCSI Target Lun number. + format: int32 + type: integer + portals: + description: 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: 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: 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: 'Volume''s name. 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: 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: 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: 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: 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: Items for all in one resources secrets, + configmaps, and downward API + properties: + defaultMode: + description: Mode bits to use on created files + by default. Must be a value between 0 and 0777. + 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: list of volume projections + items: + description: Projection that may be projected + along with other supported volume types + properties: + configMap: + description: information about the configMap + data to project + properties: + items: + description: 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: The key to project. + type: string + mode: + description: 'Optional: mode bits + to use on this file, must be + a value between 0 and 0777. + 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: 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: Specify whether the ConfigMap + or its keys must be defined + type: boolean + type: object + downwardAPI: + description: 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 + to use on this file, must be + a value between 0 and 0777. + 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: information about the secret + data to project + properties: + items: + description: 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: The key to project. + type: string + mode: + description: 'Optional: mode bits + to use on this file, must be + a value between 0 and 0777. + 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: 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: Specify whether the Secret + or its key must be defined + type: boolean + type: object + serviceAccountToken: + description: 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 + required: + - sources + 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: '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: '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: '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: '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: '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: 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: The host address of the ScaleIO API + Gateway. + type: string + protectionDomain: + description: The name of the ScaleIO Protection + Domain for the configured storage. + type: string + readOnly: + description: 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: Flag to enable/disable SSL communication + with Gateway, default false + type: boolean + storageMode: + description: Indicates whether the storage for + a volume should be ThickProvisioned or ThinProvisioned. + Default is ThinProvisioned. + type: string + storagePool: + description: The ScaleIO Storage Pool associated + with the protection domain. + type: string + system: + description: The name of the storage system as + configured in ScaleIO. + type: string + volumeName: + description: 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: 'Optional: mode bits to use on created + files by default. Must be a value between 0 + and 0777. 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: 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: The key to project. + type: string + mode: + description: 'Optional: mode bits to use + on this file, must be a value between + 0 and 0777. 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: 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: Specify whether the Secret or its + keys must be defined + type: boolean + secretName: + description: '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: 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: 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: 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: Storage Policy Based Management (SPBM) + profile ID associated with the StoragePolicyName. + type: string + storagePolicyName: + description: Storage Policy Based Management (SPBM) + profile name. + type: string + volumePath: + description: Path that identifies vSphere volume + vmdk + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + required: + - containers + type: object + type: object + replicas: + format: int32 + type: integer + type: object + elasticsearchRef: + description: ElasticsearchRef is a reference to an Elasticsearch cluster + running in the same Kubernetes cluster. + properties: + name: + description: Name of the Kubernetes object. + type: string + namespace: + description: Namespace of the Kubernetes object. If empty, defaults + to the current namespace. + type: string + required: + - name + type: object + image: + description: Image is the Beat Docker image to deploy. Version and Type + have to match the Beat in the image. + type: string + serviceAccountName: + description: ServiceAccountName is used to check access from the current + resource to Elasticsearch resource in a different namespace. Can only + be used if ECK is enforcing RBAC on references. + type: string + type: + description: Type is the type of the Beat to deploy (filebeat, metricbeat, + etc.). Any string can be used, but well-known types will be recognized + and will allow to provide sane default configurations. + maxLength: 20 + type: string + version: + description: Version of the Beat. + type: string + required: + - type + - version + type: object + status: + description: BeatStatus defines the observed state of a Beat. + properties: + associationStatus: + description: AssociationStatus is the status of an association resource. + type: string + availableNodes: + format: int32 + type: integer + expectedNodes: + format: int32 + type: integer + health: + type: string + type: object + type: object + version: v1beta1 + versions: + - name: v1beta1 + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/config/crds/bases/kustomization.yaml b/config/crds/bases/kustomization.yaml index 3c28d99936..770bd2e8ff 100644 --- a/config/crds/bases/kustomization.yaml +++ b/config/crds/bases/kustomization.yaml @@ -3,3 +3,4 @@ resources: - elasticsearch.k8s.elastic.co_elasticsearches.yaml - kibana.k8s.elastic.co_kibanas.yaml - enterprisesearch.k8s.elastic.co_enterprisesearches.yaml + - beat.k8s.elastic.co_beats.yaml diff --git a/config/crds/patches/beat-patches.yaml b/config/crds/patches/beat-patches.yaml new file mode 100644 index 0000000000..30fe46383c --- /dev/null +++ b/config/crds/patches/beat-patches.yaml @@ -0,0 +1,17 @@ +# Remove validation.openAPIV3Schema.type that causes failures on k8s 1.11. +# This should have been fixed with https://github.com/kubernetes-sigs/controller-tools/pull/72, but it looks like +# this commit has been lost in history. See https://github.com/kubernetes-sigs/controller-tools/issues/296. +# TODO: remove once fixed in controller-tools +- op: remove + path: /spec/validation/openAPIV3Schema/type + +# Using `kubectl apply` stores the complete CRD file as an annotation, +# which may be too big for the annotations size limit. +# One way to mitigate this problem is to remove the (huge) podTemplate properties from the CRD. +# It also avoids the problem of having any k8s-version specific field in the Pod schema, +# that would maybe not match the user's k8s version. +- op: remove + path: /spec/validation/openAPIV3Schema/properties/spec/properties/daemonSet/properties/podTemplate + +- op: remove + path: /spec/validation/openAPIV3Schema/properties/spec/properties/deployment/properties/podTemplate diff --git a/config/crds/patches/kustomization.yaml b/config/crds/patches/kustomization.yaml index 44f4b374f6..3514871bd0 100644 --- a/config/crds/patches/kustomization.yaml +++ b/config/crds/patches/kustomization.yaml @@ -49,3 +49,10 @@ patchesJson6902: kind: CustomResourceDefinition name: enterprisesearches.enterprisesearch.k8s.elastic.co path: ent-patches.yaml + # custom patches for Beat + - target: + group: apiextensions.k8s.io + version: v1beta1 + kind: CustomResourceDefinition + name: beats.beat.k8s.elastic.co + path: beat-patches.yaml diff --git a/config/dev/elastic-psp.yaml b/config/dev/elastic-psp.yaml index 1096a0c33a..2b11afd039 100644 --- a/config/dev/elastic-psp.yaml +++ b/config/dev/elastic-psp.yaml @@ -51,7 +51,7 @@ apiVersion: policy/v1beta1 kind: PodSecurityPolicy metadata: - name: elastic.filebeat.restricted + name: elastic.beat.restricted annotations: seccomp.security.alpha.kubernetes.io/allowedProfileNames: 'docker/default,runtime/default' apparmor.security.beta.kubernetes.io/allowedProfileNames: 'runtime/default' @@ -59,12 +59,7 @@ apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default' spec: privileged: false - # Required to prevent escalations to root. allowPrivilegeEscalation: false - # This is redundant with non-root + disallow privilege escalation, - # but we can provide it for defense in depth. - requiredDropCapabilities: - - ALL # Allow core volume types. volumes: - 'configMap' diff --git a/config/e2e/filebeat.yaml b/config/e2e/filebeat.yaml index 13e2016d60..61656b4fa8 100644 --- a/config/e2e/filebeat.yaml +++ b/config/e2e/filebeat.yaml @@ -214,7 +214,7 @@ rules: resources: - podsecuritypolicies resourceNames: - - elastic.filebeat.restricted + - elastic.beat.restricted verbs: - use --- @@ -237,7 +237,7 @@ subjects: apiVersion: security.openshift.io/v1 kind: SecurityContextConstraints metadata: - name: filebeat + name: beat allowHostDirVolumePlugin: true allowHostIPC: false allowHostNetwork: true @@ -262,6 +262,10 @@ supplementalGroups: type: RunAsAny users: - system:serviceaccount:{{ .E2ENamespace }}:filebeat +groups: +{{- range .Operator.ManagedNamespaces }} + - system:serviceaccounts:{{ . }} +{{- end }} volumes: - '*' {{end}} diff --git a/config/e2e/operator.yaml b/config/e2e/operator.yaml index 5d9357372f..6ec9ade4be 100644 --- a/config/e2e/operator.yaml +++ b/config/e2e/operator.yaml @@ -25,6 +25,7 @@ rules: - secrets - services - configmaps + - serviceaccounts verbs: - get - list @@ -38,6 +39,7 @@ rules: resources: - deployments - statefulsets + - daemonsets verbs: - get - list @@ -58,6 +60,28 @@ rules: - update - patch - delete +# required to allow the operator to bind service accounts it manages +# to role that holds permissions needed for Beat autodiscover feature +- apiGroups: + - rbac.authorization.k8s.io + resources: + - clusterroles + verbs: + - bind + resourceNames: + - elastic-beat-autodiscover +- apiGroups: + - rbac.authorization.k8s.io + resources: + - clusterrolebindings + verbs: + - get + - list + - watch + - create + - update + - patch + - delete - apiGroups: - elasticsearch.k8s.elastic.co resources: @@ -116,6 +140,20 @@ rules: - update - patch - delete +- apiGroups: + - beat.k8s.elastic.co + resources: + - beats + - beats/status + - beats/finalizers + verbs: + - get + - list + - watch + - create + - update + - patch + - delete - apiGroups: - admissionregistration.k8s.io resources: @@ -271,3 +309,18 @@ spec: name: https-webhook selector: control-plane: {{ .Operator.Name }} +--- +# permissions needed for Beat cluster-wide autodiscover feature +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: elastic-beat-autodiscover +rules: +- apiGroups: [""] # "" indicates the core API group + resources: + - namespaces + - pods + verbs: + - get + - watch + - list diff --git a/config/e2e/rbac.yaml b/config/e2e/rbac.yaml index 8fa78d7eb9..928b1cd38f 100644 --- a/config/e2e/rbac.yaml +++ b/config/e2e/rbac.yaml @@ -27,6 +27,7 @@ rules: - podsecuritypolicies resourceNames: - elastic.restricted + - elastic.beat.restricted verbs: - use - apiGroups: @@ -104,6 +105,7 @@ rules: resources: - deployments - statefulsets + - daemonsets verbs: - get - list @@ -161,6 +163,19 @@ rules: - update - patch - delete + - apiGroups: + - beat.k8s.elastic.co + resources: + - beats + - beats/status + verbs: + - get + - list + - watch + - create + - update + - patch + - delete - apiGroups: - storage.k8s.io resources: diff --git a/config/operator/Makefile b/config/operator/Makefile index 328b0d47b1..7c677eb453 100644 --- a/config/operator/Makefile +++ b/config/operator/Makefile @@ -23,7 +23,7 @@ generate-all-in-one: printf "\n---\n" && cat $$yaml ; \ done | \ sed \ - -e "/# /d" \ + -e "s|#.*||" \ -e "s||$$OPERATOR_IMAGE|g" \ -e "s||$$OPERATOR_NAME|g" \ -e "s||$$NAMESPACE|g" @@ -36,7 +36,7 @@ endif printf "\n---\n" && cat $$yaml ; \ done | \ sed \ - -e "/# /d" \ + -e "s|#.*||" \ -e "s||$$OPERATOR_IMAGE|g" \ -e "s||$$OPERATOR_NAME|g" \ -e "s||$$NAMESPACE|g" \ @@ -45,7 +45,7 @@ endif @ (MANAGED_NS_LIST=$${MANAGED_NAMESPACES//,/ }; \ for managed_ns in $$MANAGED_NS_LIST; do \ printf "\n---\n" && sed \ - -e "/# /d" \ + -e "s|#.*||" \ -e "s||$$NAMESPACE|g" \ -e "s||$$OPERATOR_NAME|g" \ -e "s||$$managed_ns|g" \ diff --git a/config/operator/all-in-one/beat-roles.yaml b/config/operator/all-in-one/beat-roles.yaml new file mode 100644 index 0000000000..bda2aa26ee --- /dev/null +++ b/config/operator/all-in-one/beat-roles.yaml @@ -0,0 +1,14 @@ +# permissions needed for Beat cluster-wide autodiscover feature +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: elastic-beat-autodiscover +rules: +- apiGroups: [""] + resources: + - namespaces + - pods + verbs: + - get + - watch + - list diff --git a/config/operator/all-in-one/cluster_role.template.yaml b/config/operator/all-in-one/cluster_role.template.yaml index dee4810c46..6fddbf8c6d 100644 --- a/config/operator/all-in-one/cluster_role.template.yaml +++ b/config/operator/all-in-one/cluster_role.template.yaml @@ -12,6 +12,28 @@ rules: - subjectaccessreviews verbs: - create +# required to allow the operator to bind service accounts it manages +# to role that holds permissions needed for Beat autodiscover feature +- apiGroups: + - "rbac.authorization.k8s.io" + resources: + - clusterrolebindings + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - rbac.authorization.k8s.io + resources: + - clusterroles + verbs: + - bind + resourceNames: + - elastic-beat-autodiscover - apiGroups: - "" resources: @@ -22,6 +44,7 @@ rules: - secrets - services - configmaps + - serviceaccounts verbs: - get - list @@ -35,6 +58,7 @@ rules: resources: - deployments - statefulsets + - daemonsets # used by Beats verbs: - get - list @@ -113,6 +137,20 @@ rules: - update - patch - delete +- apiGroups: + - beat.k8s.elastic.co + resources: + - beats + - beats/status + - beats/finalizers + verbs: + - get + - list + - watch + - create + - update + - patch + - delete - apiGroups: - admissionregistration.k8s.io resources: diff --git a/config/operator/all-in-one/rbac.yaml b/config/operator/all-in-one/rbac.yaml index 634f5cf760..6f741e23a2 100644 --- a/config/operator/all-in-one/rbac.yaml +++ b/config/operator/all-in-one/rbac.yaml @@ -19,6 +19,9 @@ rules: - apiGroups: ["enterprisesearch.k8s.elastic.co"] resources: ["enterprisesearches"] verbs: ["get", "list", "watch"] + - apiGroups: ["beat.k8s.elastic.co"] + resources: ["beats"] + verbs: ["get", "list", "watch"] --- @@ -42,3 +45,6 @@ rules: - apiGroups: ["enterprisesearch.k8s.elastic.co"] resources: ["enterprisesearches"] verbs: ["create", "delete", "deletecollection", "patch", "update"] + - apiGroups: ["beat.k8s.elastic.co"] + resources: ["beats"] + verbs: ["create", "delete", "deletecollection", "patch", "update"] diff --git a/config/operator/global/rbac.yaml b/config/operator/global/rbac.yaml index 634f5cf760..6f741e23a2 100644 --- a/config/operator/global/rbac.yaml +++ b/config/operator/global/rbac.yaml @@ -19,6 +19,9 @@ rules: - apiGroups: ["enterprisesearch.k8s.elastic.co"] resources: ["enterprisesearches"] verbs: ["get", "list", "watch"] + - apiGroups: ["beat.k8s.elastic.co"] + resources: ["beats"] + verbs: ["get", "list", "watch"] --- @@ -42,3 +45,6 @@ rules: - apiGroups: ["enterprisesearch.k8s.elastic.co"] resources: ["enterprisesearches"] verbs: ["create", "delete", "deletecollection", "patch", "update"] + - apiGroups: ["beat.k8s.elastic.co"] + resources: ["beats"] + verbs: ["create", "delete", "deletecollection", "patch", "update"] diff --git a/config/operator/namespace/beat-roles.yaml b/config/operator/namespace/beat-roles.yaml new file mode 100644 index 0000000000..bda2aa26ee --- /dev/null +++ b/config/operator/namespace/beat-roles.yaml @@ -0,0 +1,14 @@ +# permissions needed for Beat cluster-wide autodiscover feature +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: elastic-beat-autodiscover +rules: +- apiGroups: [""] + resources: + - namespaces + - pods + verbs: + - get + - watch + - list diff --git a/config/operator/namespace/cluster_role.template.yaml b/config/operator/namespace/cluster_role.template.yaml index a25373930b..32e1dcbca4 100644 --- a/config/operator/namespace/cluster_role.template.yaml +++ b/config/operator/namespace/cluster_role.template.yaml @@ -33,6 +33,7 @@ rules: - secrets - services - configmaps + - serviceaccounts verbs: - get - list @@ -41,11 +42,34 @@ rules: - update - patch - delete +# required to allow the operator to bind service accounts it manages +# to role that holds permissions needed for Beat autodiscover feature +- apiGroups: + - "rbac.authorization.k8s.io" + resources: + - clusterrolebindings + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - rbac.authorization.k8s.io + resources: + - clusterroles + verbs: + - bind + resourceNames: + - elastic-beat-autodiscover - apiGroups: - apps resources: - deployments - statefulsets + - daemonsets # used by Beats verbs: - get - list @@ -129,4 +153,17 @@ rules: - update - patch - delete - +- apiGroups: + - beat.k8s.elastic.co + resources: + - beats + - beats/status + - beats/finalizers + verbs: + - get + - list + - watch + - create + - update + - patch + - delete diff --git a/config/operator/namespace/rbac.yaml b/config/operator/namespace/rbac.yaml index 634f5cf760..6f741e23a2 100644 --- a/config/operator/namespace/rbac.yaml +++ b/config/operator/namespace/rbac.yaml @@ -19,6 +19,9 @@ rules: - apiGroups: ["enterprisesearch.k8s.elastic.co"] resources: ["enterprisesearches"] verbs: ["get", "list", "watch"] + - apiGroups: ["beat.k8s.elastic.co"] + resources: ["beats"] + verbs: ["get", "list", "watch"] --- @@ -42,3 +45,6 @@ rules: - apiGroups: ["enterprisesearch.k8s.elastic.co"] resources: ["enterprisesearches"] verbs: ["create", "delete", "deletecollection", "patch", "update"] + - apiGroups: ["beat.k8s.elastic.co"] + resources: ["beats"] + verbs: ["create", "delete", "deletecollection", "patch", "update"] diff --git a/config/samples/beat/filebeat_es_kibana_apm.yaml b/config/samples/beat/filebeat_es_kibana_apm.yaml new file mode 100644 index 0000000000..7e23876756 --- /dev/null +++ b/config/samples/beat/filebeat_es_kibana_apm.yaml @@ -0,0 +1,55 @@ +# This sample sets up an Elasticsearch cluster with Kibana instance, APM instance and Filebeat preconfigured for it. +apiVersion: elasticsearch.k8s.elastic.co/v1 +kind: Elasticsearch +metadata: + name: elasticsearch-sample +spec: + version: 7.7.0 + nodeSets: + - name: default + count: 3 + config: + # This setting could have performance implications for production clusters. + # See: https://www.elastic.co/guide/en/cloud-on-k8s/master/k8s-virtual-memory.html + node.store.allow_mmap: false +--- +apiVersion: kibana.k8s.elastic.co/v1 +kind: Kibana +metadata: + name: kibana-sample +spec: + version: 7.7.0 + count: 1 + elasticsearchRef: + name: elasticsearch-sample + podTemplate: + metadata: + labels: + foo: bar + spec: + containers: + - name: kibana + resources: + limits: + memory: 1Gi + cpu: 1 +--- +apiVersion: apm.k8s.elastic.co/v1 +kind: ApmServer +metadata: + name: apm-sample +spec: + version: 7.7.0 + count: 1 + elasticsearchRef: + name: elasticsearch-sample +--- +apiVersion: beat.k8s.elastic.co/v1beta1 +kind: Beat +metadata: + name: filebeat-sample +spec: + type: filebeat + version: 7.7.0 + elasticsearchRef: + name: elasticsearch-sample diff --git a/config/webhook/manifests.yaml b/config/webhook/manifests.yaml index 993a62e77b..fe32777f4d 100644 --- a/config/webhook/manifests.yaml +++ b/config/webhook/manifests.yaml @@ -42,6 +42,24 @@ webhooks: - UPDATE resources: - apmservers +- clientConfig: + caBundle: Cg== + service: + name: webhook-service + namespace: system + path: /validate-beat-k8s-elastic-co-v1beta1-beat + failurePolicy: Ignore + name: elastic-beat-validation-v1beta1.k8s.elastic.co + rules: + - apiGroups: + - beat.k8s.elastic.co + apiVersions: + - v1beta1 + operations: + - CREATE + - UPDATE + resources: + - beats - clientConfig: caBundle: Cg== service: diff --git a/docs/reference/api-docs.asciidoc b/docs/reference/api-docs.asciidoc index cddb77f92d..b7f1ad4b26 100644 --- a/docs/reference/api-docs.asciidoc +++ b/docs/reference/api-docs.asciidoc @@ -14,6 +14,7 @@ endif::[] .Packages - xref:{anchor_prefix}-apm-k8s-elastic-co-v1[$$apm.k8s.elastic.co/v1$$] - xref:{anchor_prefix}-apm-k8s-elastic-co-v1beta1[$$apm.k8s.elastic.co/v1beta1$$] +- xref:{anchor_prefix}-beat-k8s-elastic-co-v1beta1[$$beat.k8s.elastic.co/v1beta1$$] - xref:{anchor_prefix}-common-k8s-elastic-co-v1[$$common.k8s.elastic.co/v1$$] - xref:{anchor_prefix}-common-k8s-elastic-co-v1beta1[$$common.k8s.elastic.co/v1beta1$$] - xref:{anchor_prefix}-elasticsearch-k8s-elastic-co-v1[$$elasticsearch.k8s.elastic.co/v1$$] @@ -131,6 +132,94 @@ ApmServerSpec holds the specification of an APM Server. +[id="{anchor_prefix}-beat-k8s-elastic-co-v1beta1"] +== beat.k8s.elastic.co/v1beta1 + +Package v1beta1 contains API Schema definitions for the beat v1beta1 API group + +.Resource Types +- xref:{anchor_prefix}-github-com-elastic-cloud-on-k8s-pkg-apis-beat-v1beta1-beat[$$Beat$$] + + + +[id="{anchor_prefix}-github-com-elastic-cloud-on-k8s-pkg-apis-beat-v1beta1-beat"] +=== Beat + +Beat is the Schema for the Beats API. + + + +[cols="25a,75a", options="header"] +|=== +| Field | Description +| *`apiVersion`* __string__ | `beat.k8s.elastic.co/v1beta1` +| *`kind`* __string__ | `Beat` +| *`metadata`* __link:https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/#objectmeta-v1-meta[$$ObjectMeta$$]__ | Refer to Kubernetes API documentation for fields of `metadata`. + +| *`spec`* __xref:{anchor_prefix}-github-com-elastic-cloud-on-k8s-pkg-apis-beat-v1beta1-beatspec[$$BeatSpec$$]__ | +|=== + + +[id="{anchor_prefix}-github-com-elastic-cloud-on-k8s-pkg-apis-beat-v1beta1-beatspec"] +=== BeatSpec + +BeatSpec defines the desired state of a Beat. + +.Appears In: +**** +- xref:{anchor_prefix}-github-com-elastic-cloud-on-k8s-pkg-apis-beat-v1beta1-beat[$$Beat$$] +**** + +[cols="25a,75a", options="header"] +|=== +| Field | Description +| *`type`* __string__ | Type is the type of the Beat to deploy (filebeat, metricbeat, etc.). Any string can be used, but well-known types will be recognized and will allow to provide sane default configurations. +| *`version`* __string__ | Version of the Beat. +| *`elasticsearchRef`* __xref:{anchor_prefix}-github-com-elastic-cloud-on-k8s-pkg-apis-common-v1-objectselector[$$ObjectSelector$$]__ | ElasticsearchRef is a reference to an Elasticsearch cluster running in the same Kubernetes cluster. +| *`image`* __string__ | Image is the Beat Docker image to deploy. Version and Type have to match the Beat in the image. +| *`config`* __xref:{anchor_prefix}-github-com-elastic-cloud-on-k8s-pkg-apis-common-v1-config[$$Config$$]__ | Config holds the Beat configuration. If provided, it will override the default configuration. +| *`serviceAccountName`* __string__ | ServiceAccountName is used to check access from the current resource to Elasticsearch resource in a different namespace. Can only be used if ECK is enforcing RBAC on references. +| *`daemonSet`* __xref:{anchor_prefix}-github-com-elastic-cloud-on-k8s-pkg-apis-beat-v1beta1-daemonsetspec[$$DaemonSetSpec$$]__ | DaemonSet specifies the Beat should be deployed as a DaemonSet, and allows providing its spec. Cannot be used along with `deployment`. If both are absent a default for the Type is used. +| *`deployment`* __xref:{anchor_prefix}-github-com-elastic-cloud-on-k8s-pkg-apis-beat-v1beta1-deploymentspec[$$DeploymentSpec$$]__ | Deployment specifies the Beat should be deployed as a Deployment, and allows providing its spec. Cannot be used along with `daemonSet`. If both are absent a default for the Type is used. +|=== + + +[id="{anchor_prefix}-github-com-elastic-cloud-on-k8s-pkg-apis-beat-v1beta1-daemonsetspec"] +=== DaemonSetSpec + + + +.Appears In: +**** +- xref:{anchor_prefix}-github-com-elastic-cloud-on-k8s-pkg-apis-beat-v1beta1-beatspec[$$BeatSpec$$] +**** + +[cols="25a,75a", options="header"] +|=== +| Field | Description +| *`podTemplate`* __link:https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/#podtemplatespec-v1-core[$$PodTemplateSpec$$]__ | +|=== + + +[id="{anchor_prefix}-github-com-elastic-cloud-on-k8s-pkg-apis-beat-v1beta1-deploymentspec"] +=== DeploymentSpec + + + +.Appears In: +**** +- xref:{anchor_prefix}-github-com-elastic-cloud-on-k8s-pkg-apis-beat-v1beta1-beatspec[$$BeatSpec$$] +**** + +[cols="25a,75a", options="header"] +|=== +| Field | Description +| *`podTemplate`* __link:https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/#podtemplatespec-v1-core[$$PodTemplateSpec$$]__ | +| *`replicas`* __integer__ | +|=== + + + [id="{anchor_prefix}-common-k8s-elastic-co-v1"] == common.k8s.elastic.co/v1 @@ -146,6 +235,7 @@ Config represents untyped YAML configuration. .Appears In: **** - xref:{anchor_prefix}-github-com-elastic-cloud-on-k8s-pkg-apis-apm-v1-apmserverspec[$$ApmServerSpec$$] +- xref:{anchor_prefix}-github-com-elastic-cloud-on-k8s-pkg-apis-beat-v1beta1-beatspec[$$BeatSpec$$] - xref:{anchor_prefix}-github-com-elastic-cloud-on-k8s-pkg-apis-enterprisesearch-v1beta1-enterprisesearchspec[$$EnterpriseSearchSpec$$] - xref:{anchor_prefix}-github-com-elastic-cloud-on-k8s-pkg-apis-kibana-v1-kibanaspec[$$KibanaSpec$$] - xref:{anchor_prefix}-github-com-elastic-cloud-on-k8s-pkg-apis-elasticsearch-v1-nodeset[$$NodeSet$$] @@ -200,6 +290,7 @@ ObjectSelector defines a reference to a Kubernetes object. .Appears In: **** - xref:{anchor_prefix}-github-com-elastic-cloud-on-k8s-pkg-apis-apm-v1-apmserverspec[$$ApmServerSpec$$] +- xref:{anchor_prefix}-github-com-elastic-cloud-on-k8s-pkg-apis-beat-v1beta1-beatspec[$$BeatSpec$$] - xref:{anchor_prefix}-github-com-elastic-cloud-on-k8s-pkg-apis-enterprisesearch-v1beta1-enterprisesearchspec[$$EnterpriseSearchSpec$$] - xref:{anchor_prefix}-github-com-elastic-cloud-on-k8s-pkg-apis-kibana-v1-kibanaspec[$$KibanaSpec$$] - xref:{anchor_prefix}-github-com-elastic-cloud-on-k8s-pkg-apis-elasticsearch-v1-remotecluster[$$RemoteCluster$$] diff --git a/hack/api-docs/config.yaml b/hack/api-docs/config.yaml index 51f0311e25..cd4546191f 100644 --- a/hack/api-docs/config.yaml +++ b/hack/api-docs/config.yaml @@ -1,8 +1,8 @@ processor: ignoreTypes: - - "(Elasticsearch|Kibana|ApmServer|EnterpriseSearch)List$" - - "(Elasticsearch|Kibana|ApmServer|EnterpriseSearch)Health$" - - "(Elasticsearch|Kibana|ApmServer|Reconciler|EnterpriseSearch)Status$" + - "(Elasticsearch|Kibana|ApmServer|EnterpriseSearch|Beat)List$" + - "(Elasticsearch|Kibana|ApmServer|EnterpriseSearch|Beat)Health$" + - "(Elasticsearch|Kibana|ApmServer|Reconciler|EnterpriseSearch|Beat)Status$" - "ElasticsearchSettings$" - "Associa(ted|tion|tionStatus|tionConf)$" - "APM(Es|Kibana)Association" diff --git a/pkg/apis/beat/v1beta1/beat_types.go b/pkg/apis/beat/v1beta1/beat_types.go new file mode 100644 index 0000000000..3813299354 --- /dev/null +++ b/pkg/apis/beat/v1beta1/beat_types.go @@ -0,0 +1,180 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package v1beta1 + +import ( + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + commonv1 "github.com/elastic/cloud-on-k8s/pkg/apis/common/v1" +) + +// BeatSpec defines the desired state of a Beat. +type BeatSpec struct { + // Type is the type of the Beat to deploy (filebeat, metricbeat, etc.). Any string can be used, + // but well-known types will be recognized and will allow to provide sane default configurations. + // +kubebuilder:validation:MaxLength=20 + Type string `json:"type"` + + // Version of the Beat. + Version string `json:"version"` + + // ElasticsearchRef is a reference to an Elasticsearch cluster running in the same Kubernetes cluster. + // +kubebuilder:validation:Optional + ElasticsearchRef commonv1.ObjectSelector `json:"elasticsearchRef,omitempty"` + + // Image is the Beat Docker image to deploy. Version and Type have to match the Beat in the image. + // +kubebuilder:validation:Optional + Image string `json:"image,omitempty"` + + // Config holds the Beat configuration. If provided, it will override the default configuration. + // +kubebuilder:validation:Optional + Config *commonv1.Config `json:"config,omitempty"` + + // ServiceAccountName is used to check access from the current resource to Elasticsearch resource in a different namespace. + // Can only be used if ECK is enforcing RBAC on references. + // +kubebuilder:validation:Optional + ServiceAccountName string `json:"serviceAccountName,omitempty"` + + // DaemonSet specifies the Beat should be deployed as a DaemonSet, and allows providing its spec. + // Cannot be used along with `deployment`. If both are absent a default for the Type is used. + // +kubebuilder:validation:Optional + DaemonSet *DaemonSetSpec `json:"daemonSet,omitempty"` + + // Deployment specifies the Beat should be deployed as a Deployment, and allows providing its spec. + // Cannot be used along with `daemonSet`. If both are absent a default for the Type is used. + // +kubebuilder:validation:Optional + Deployment *DeploymentSpec `json:"deployment,omitempty"` +} + +type DaemonSetSpec struct { + PodTemplate corev1.PodTemplateSpec `json:"podTemplate,omitempty"` +} + +type DeploymentSpec struct { + PodTemplate corev1.PodTemplateSpec `json:"podTemplate,omitempty"` + Replicas *int32 `json:"replicas,omitempty"` +} + +// BeatStatus defines the observed state of a Beat. +type BeatStatus struct { + // +kubebuilder:validation:Optional + commonv1.ReconcilerStatus `json:",inline"` + + // +kubebuilder:validation:Optional + ExpectedNodes int32 `json:"expectedNodes,omitempty"` + + // +kubebuilder:validation:Optional + Health BeatHealth `json:"health,omitempty"` + + // +kubebuilder:validation:Optional + Association commonv1.AssociationStatus `json:"associationStatus,omitempty"` +} + +type BeatHealth string + +const ( + // BeatRedHealth means that the health is neither yellow nor green. + BeatRedHealth BeatHealth = "red" + + // BeatYellowHealth means that: + // 1) at least one Pod is Ready, and + // 2) association is not configured, or configured and established + BeatYellowHealth BeatHealth = "yellow" + + // BeatGreenHealth means that: + // 1) all Pods are Ready, and + // 2) association is not configured, or configured and established + BeatGreenHealth BeatHealth = "green" +) + +// +kubebuilder:object:root=true + +// Beat is the Schema for the Beats API. +// +kubebuilder:resource:categories=elastic,shortName=beat +// +kubebuilder:subresource:status +// +kubebuilder:printcolumn:name="health",type="string",JSONPath=".status.health" +// +kubebuilder:printcolumn:name="available",type="integer",JSONPath=".status.availableNodes",description="Available nodes" +// +kubebuilder:printcolumn:name="expected",type="integer",JSONPath=".status.expectedNodes",description="Expected nodes" +// +kubebuilder:printcolumn:name="type",type="string",JSONPath=".spec.type",description="Beat type" +// +kubebuilder:printcolumn:name="version",type="string",JSONPath=".spec.version",description="Beat version" +// +kubebuilder:printcolumn:name="age",type="date",JSONPath=".metadata.creationTimestamp" +// +kubebuilder:storageversion +type Beat struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec BeatSpec `json:"spec,omitempty"` + Status BeatStatus `json:"status,omitempty"` + assocConf *commonv1.AssociationConf `json:"-"` //nolint:govet +} + +func (b *Beat) Associated() commonv1.Associated { + if b != nil { + return b + } + return &Beat{} +} + +func (b *Beat) AssociatedType() string { + return commonv1.ElasticsearchAssociationType +} + +func (b *Beat) AssociationRef() commonv1.ObjectSelector { + return b.Spec.ElasticsearchRef.WithDefaultNamespace(b.Namespace) +} + +func (b *Beat) AssociationConfAnnotationName() string { + return commonv1.ElasticsearchConfigAnnotationName +} + +func (b *Beat) GetAssociations() []commonv1.Association { + return []commonv1.Association{b} +} + +// IsMarkedForDeletion returns true if the Beat is going to be deleted +func (b *Beat) IsMarkedForDeletion() bool { + return !b.DeletionTimestamp.IsZero() +} + +func (b *Beat) ServiceAccountName() string { + return b.Spec.ServiceAccountName +} + +func (b *Beat) ElasticsearchRef() commonv1.ObjectSelector { + return b.Spec.ElasticsearchRef +} + +func (b *Beat) AssociationConf() *commonv1.AssociationConf { + return b.assocConf +} + +func (b *Beat) SetAssociationConf(assocConf *commonv1.AssociationConf) { + b.assocConf = assocConf +} + +func (b *Beat) AssociationStatus() commonv1.AssociationStatus { + return b.Status.Association +} + +func (b *Beat) SetAssociationStatus(status commonv1.AssociationStatus) { + b.Status.Association = status +} + +var _ commonv1.Associated = &Beat{} +var _ commonv1.Association = &Beat{} + +// +kubebuilder:object:root=true + +// BeatList contains a list of Beats. +type BeatList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Beat `json:"items"` +} + +func init() { + SchemeBuilder.Register(&Beat{}, &BeatList{}) +} diff --git a/pkg/apis/beat/v1beta1/doc.go b/pkg/apis/beat/v1beta1/doc.go new file mode 100644 index 0000000000..3564a118b0 --- /dev/null +++ b/pkg/apis/beat/v1beta1/doc.go @@ -0,0 +1,11 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +// Package v1beta1 contains API Schema definitions for the beat v1beta1 API group +// +k8s:openapi-gen=true +// +k8s:deepcopy-gen=package,register +// +k8s:conversion-gen=github.com/elastic/cloud-on-k8s/pkg/apis/beat +// +k8s:defaulter-gen=TypeMeta +// +groupName=beat.k8s.elastic.co +package v1beta1 diff --git a/pkg/apis/beat/v1beta1/groupversion_info.go b/pkg/apis/beat/v1beta1/groupversion_info.go new file mode 100644 index 0000000000..7b3ada90d8 --- /dev/null +++ b/pkg/apis/beat/v1beta1/groupversion_info.go @@ -0,0 +1,21 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package v1beta1 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +var ( + // GroupVersion is group version used to register these objects + GroupVersion = schema.GroupVersion{Group: "beat.k8s.elastic.co", Version: "v1beta1"} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme + SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} + + // AddToScheme is required by pkg/client/... + AddToScheme = SchemeBuilder.AddToScheme +) diff --git a/pkg/apis/beat/v1beta1/webhook.go b/pkg/apis/beat/v1beta1/webhook.go new file mode 100644 index 0000000000..4663d7093d --- /dev/null +++ b/pkg/apis/beat/v1beta1/webhook.go @@ -0,0 +1,135 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package v1beta1 + +import ( + "errors" + + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/validation/field" + ctrl "sigs.k8s.io/controller-runtime" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/webhook" + + commonv1 "github.com/elastic/cloud-on-k8s/pkg/apis/common/v1" + "github.com/elastic/cloud-on-k8s/pkg/controller/common/version" + "github.com/elastic/cloud-on-k8s/pkg/utils/stringsutil" +) + +var ( + groupKind = schema.GroupKind{Group: GroupVersion.Group, Kind: "Beat"} + validationLog = logf.Log.WithName("beat-v1beta1-validation") + + defaultChecks = []func(*Beat) field.ErrorList{ + checkNoUnknownFields, + checkNameLength, + checkSupportedVersion, + checkAtMostOneDeploymentOption, + checkImageIfTypeUnknown, + } + + updateChecks = []func(old, curr *Beat) field.ErrorList{ + checkNoDowngrade, + } +) + +// +kubebuilder:webhook:path=/validate-beat-k8s-elastic-co-v1beta1-beat,mutating=false,failurePolicy=ignore,groups=beat.k8s.elastic.co,resources=beats,verbs=create;update,versions=v1beta1,name=elastic-beat-validation-v1beta1.k8s.elastic.co + +var _ webhook.Validator = &Beat{} + +func (b *Beat) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(b). + Complete() +} + +func (b *Beat) ValidateCreate() error { + validationLog.V(1).Info("Validate create", "name", b.Name) + return b.validate(nil) +} + +func (b *Beat) ValidateDelete() error { + validationLog.V(1).Info("Validate delete", "name", b.Name) + return nil +} + +func (b *Beat) ValidateUpdate(old runtime.Object) error { + validationLog.V(1).Info("Validate update", "name", b.Name) + oldObj, ok := old.(*Beat) + if !ok { + return errors.New("cannot cast old object to Beat type") + } + + return b.validate(oldObj) +} + +func (b *Beat) validate(old *Beat) error { + var errors field.ErrorList + if old != nil { + for _, uc := range updateChecks { + if err := uc(old, b); err != nil { + errors = append(errors, err...) + } + } + + if len(errors) > 0 { + return apierrors.NewInvalid(groupKind, b.Name, errors) + } + } + + for _, dc := range defaultChecks { + if err := dc(b); err != nil { + errors = append(errors, err...) + } + } + + if len(errors) > 0 { + return apierrors.NewInvalid(groupKind, b.Name, errors) + } + return nil +} + +func checkNoUnknownFields(b *Beat) field.ErrorList { + return commonv1.NoUnknownFields(b, b.ObjectMeta) +} + +func checkNameLength(ent *Beat) field.ErrorList { + return commonv1.CheckNameLength(ent) +} + +func checkSupportedVersion(b *Beat) field.ErrorList { + return commonv1.CheckSupportedStackVersion(b.Spec.Version, version.SupportedBeatVersions) +} + +func checkAtMostOneDeploymentOption(b *Beat) field.ErrorList { + if b.Spec.DaemonSet != nil && b.Spec.Deployment != nil { + msg := "Specify either daemonSet or deployment, not both" + return field.ErrorList{ + field.Forbidden(field.NewPath("spec").Child("daemonSet"), msg), + field.Forbidden(field.NewPath("spec").Child("deployment"), msg), + } + } + + return nil +} + +func checkImageIfTypeUnknown(b *Beat) field.ErrorList { + knownTypes := []string{"filebeat", "metricbeat"} + if !stringsutil.StringInSlice(b.Spec.Type, knownTypes) && + b.Spec.Image == "" { + return field.ErrorList{ + field.Required( + field.NewPath("spec").Child("image"), + "Image is required if Beat type is not one of [filebeat, metricbeat]"), + } + } + return nil +} + +func checkNoDowngrade(prev, curr *Beat) field.ErrorList { + return commonv1.CheckNoDowngrade(prev.Spec.Version, curr.Spec.Version) +} diff --git a/pkg/apis/beat/v1beta1/zz_generated.deepcopy.go b/pkg/apis/beat/v1beta1/zz_generated.deepcopy.go new file mode 100644 index 0000000000..93e1f0eab8 --- /dev/null +++ b/pkg/apis/beat/v1beta1/zz_generated.deepcopy.go @@ -0,0 +1,161 @@ +// +build !ignore_autogenerated + +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +// Code generated by controller-gen. DO NOT EDIT. + +package v1beta1 + +import ( + "github.com/elastic/cloud-on-k8s/pkg/apis/common/v1" + "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Beat) DeepCopyInto(out *Beat) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + out.Status = in.Status + if in.assocConf != nil { + in, out := &in.assocConf, &out.assocConf + *out = new(v1.AssociationConf) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Beat. +func (in *Beat) DeepCopy() *Beat { + if in == nil { + return nil + } + out := new(Beat) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Beat) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BeatList) DeepCopyInto(out *BeatList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Beat, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BeatList. +func (in *BeatList) DeepCopy() *BeatList { + if in == nil { + return nil + } + out := new(BeatList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *BeatList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BeatSpec) DeepCopyInto(out *BeatSpec) { + *out = *in + out.ElasticsearchRef = in.ElasticsearchRef + if in.Config != nil { + in, out := &in.Config, &out.Config + *out = (*in).DeepCopy() + } + if in.DaemonSet != nil { + in, out := &in.DaemonSet, &out.DaemonSet + *out = new(DaemonSetSpec) + (*in).DeepCopyInto(*out) + } + if in.Deployment != nil { + in, out := &in.Deployment, &out.Deployment + *out = new(DeploymentSpec) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BeatSpec. +func (in *BeatSpec) DeepCopy() *BeatSpec { + if in == nil { + return nil + } + out := new(BeatSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BeatStatus) DeepCopyInto(out *BeatStatus) { + *out = *in + out.ReconcilerStatus = in.ReconcilerStatus +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BeatStatus. +func (in *BeatStatus) DeepCopy() *BeatStatus { + if in == nil { + return nil + } + out := new(BeatStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DaemonSetSpec) DeepCopyInto(out *DaemonSetSpec) { + *out = *in + in.PodTemplate.DeepCopyInto(&out.PodTemplate) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DaemonSetSpec. +func (in *DaemonSetSpec) DeepCopy() *DaemonSetSpec { + if in == nil { + return nil + } + out := new(DaemonSetSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DeploymentSpec) DeepCopyInto(out *DeploymentSpec) { + *out = *in + in.PodTemplate.DeepCopyInto(&out.PodTemplate) + if in.Replicas != nil { + in, out := &in.Replicas, &out.Replicas + *out = new(int32) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DeploymentSpec. +func (in *DeploymentSpec) DeepCopy() *DeploymentSpec { + if in == nil { + return nil + } + out := new(DeploymentSpec) + in.DeepCopyInto(out) + return out +} diff --git a/pkg/controller/association/conf.go b/pkg/controller/association/conf.go index da4dfee088..4add8ac3bf 100644 --- a/pkg/controller/association/conf.go +++ b/pkg/controller/association/conf.go @@ -94,7 +94,13 @@ func ElasticsearchAuthSettings(c k8s.Client, association commonv1.Association) ( if err := c.Get(secretObjKey, &secret); err != nil { return "", "", err } - return assocConf.AuthSecretKey, string(secret.Data[assocConf.AuthSecretKey]), nil + + data, ok := secret.Data[assocConf.AuthSecretKey] + if !ok { + return "", "", errors.Errorf("auth secret key %s doesn't exist", assocConf.AuthSecretKey) + } + + return assocConf.AuthSecretKey, string(data), nil } // GetAssociationConf extracts the association configuration from the given object by reading the annotations. diff --git a/pkg/controller/association/conf_test.go b/pkg/controller/association/conf_test.go index c4be3f4f0b..94f230b170 100644 --- a/pkg/controller/association/conf_test.go +++ b/pkg/controller/association/conf_test.go @@ -298,6 +298,23 @@ func TestElasticsearchAuthSettings(t *testing.T) { }, wantErr: true, }, + { + name: "When the auth secret key does not exist", + client: k8s.WrappedFakeClient(&corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "apmelasticsearchassociation-sample-elastic-internal-apm", + Namespace: "default", + }, + Data: map[string][]byte{"elastic-internal-apm": []byte("a2s1Nmt0N3Nwdmg4cmpqdDlucWhsN3cy")}, + }), + assocConf: commonv1.AssociationConf{ + AuthSecretName: "apmelasticsearchassociation-sample-elastic-internal-apm", + AuthSecretKey: "bad-key", + CASecretName: "ca-secret", + URL: "https://elasticsearch-sample-es-http.default.svc:9200", + }, + wantErr: true, + }, } for _, tt := range tests { diff --git a/pkg/controller/association/controller/beat_es.go b/pkg/controller/association/controller/beat_es.go new file mode 100644 index 0000000000..97aea1451a --- /dev/null +++ b/pkg/controller/association/controller/beat_es.go @@ -0,0 +1,52 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package controller + +import ( + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/manager" + + beatv1beta1 "github.com/elastic/cloud-on-k8s/pkg/apis/beat/v1beta1" + commonv1 "github.com/elastic/cloud-on-k8s/pkg/apis/common/v1" + esv1 "github.com/elastic/cloud-on-k8s/pkg/apis/elasticsearch/v1" + "github.com/elastic/cloud-on-k8s/pkg/controller/association" + "github.com/elastic/cloud-on-k8s/pkg/controller/common/operator" + eslabel "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/label" + esuser "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/user" + "github.com/elastic/cloud-on-k8s/pkg/utils/k8s" + "github.com/elastic/cloud-on-k8s/pkg/utils/rbac" +) + +const ( + // BeatESAssociationLabelName marks resources created by this controller for easier retrieval. + BeatESAssociationLabelName = "beatassociation.k8s.elastic.co/name" + + // BeatESAssociationLabelNamespace marks resources created by this controller for easier retrieval. + BeatESAssociationLabelNamespace = "beatassociation.k8s.elastic.co/namespace" +) + +func AddBeatES(mgr manager.Manager, accessReviewer rbac.AccessReviewer, params operator.Parameters) error { + return association.AddAssociationController(mgr, accessReviewer, params, association.AssociationInfo{ + AssociationObjTemplate: func() commonv1.Association { return &beatv1beta1.Beat{} }, + ElasticsearchRef: func(c k8s.Client, association commonv1.Association) (bool, commonv1.ObjectSelector, error) { + return true, association.AssociationRef(), nil + }, + ExternalServiceURL: getElasticsearchExternalURL, + AssociatedNamer: esv1.ESNamer, + AssociationName: "beat-es", + AssociatedShortName: "beat", + AssociationLabels: func(associated types.NamespacedName) map[string]string { + return map[string]string{ + BeatESAssociationLabelName: associated.Name, + BeatESAssociationLabelNamespace: associated.Namespace, + } + }, + UserSecretSuffix: "beat-user", + CASecretLabelName: eslabel.ClusterNameLabelName, + ESUserRole: func(commonv1.Associated) (string, error) { + return esuser.SuperUserBuiltinRole, nil + }, + }) +} diff --git a/pkg/controller/beat/common/autodiscover.go b/pkg/controller/beat/common/autodiscover.go new file mode 100644 index 0000000000..6c6c6c13cc --- /dev/null +++ b/pkg/controller/beat/common/autodiscover.go @@ -0,0 +1,206 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package common + +import ( + "context" + "fmt" + + "github.com/go-logr/logr" + "go.elastic.co/apm" + corev1 "k8s.io/api/core/v1" + rbacv1 "k8s.io/api/rbac/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + + beatv1beta1 "github.com/elastic/cloud-on-k8s/pkg/apis/beat/v1beta1" + "github.com/elastic/cloud-on-k8s/pkg/controller/common/hash" + "github.com/elastic/cloud-on-k8s/pkg/controller/common/reconciler" + "github.com/elastic/cloud-on-k8s/pkg/controller/common/tracing" + "github.com/elastic/cloud-on-k8s/pkg/utils/k8s" + "github.com/elastic/cloud-on-k8s/pkg/utils/maps" +) + +const ( + // serviceAccountNameTemplate is the template to be used with Beat name to obtain the name of a ServiceAccount. + // Note that users might depend on it. + serviceAccountNameTemplate = "elastic-beat-%s" + + // clusterRoleBindingNameTemplate is the template to be used with Beat namespace and name to obtain the name of + // a ClusterRoleBinding. + clusterRoleBindingNameTemplate = "elastic-beat-autodiscover-%s-%s" + + // clusterRoleName is the name of the ClusterRole. If autodiscover RBAC management is enabled, operator assumes + // that this role already exists in the cluster. + clusterRoleName = "elastic-beat-autodiscover" + + // autodiscoverBeatNameLabelName is a label name that is applied to ClusterRoleBinding for autodiscover + // permissions. Label value is the name of the Beat resource that the binding is for. + autodiscoverBeatNameLabelName = "autodiscover.beat.k8s.elastic.co/name" + + // autodiscoverBeatNamespaceLabelName is a label name that is applied to ClusterRoleBinding for autodiscover + // permissions. Label value is the namespace of the Beat resource that the binding is for. + autodiscoverBeatNamespaceLabelName = "autodiscover.beat.k8s.elastic.co/namespace" +) + +var ( + shouldManageRBAC = false +) + +// EnableAutodiscoverRBACManagement enables setting up autodiscover RBAC. +func EnableAutodiscoverRBACManagement() { + shouldManageRBAC = true +} + +// ShouldManageAutodiscoverRBAC returns true if autodiscover RBAC is expected to be set up by the operator. +func ShouldManageAutodiscoverRBAC() bool { + return shouldManageRBAC +} + +// SetupAutodiscoveryRBAC reconciles all resources needed for the default RBAC setup. +func ReconcileAutodiscoverRBAC(ctx context.Context, log logr.Logger, client k8s.Client, beat beatv1beta1.Beat) error { + if !ShouldManageAutodiscoverRBAC() { + return nil + } + + err := reconcileAutodiscoverRBAC(ctx, client, beat) + if err != nil { + log.V(1).Info( + "autodiscover rbac setup failed", + "namespace", beat.Namespace, + "beat_name", beat.Name) + } + + return err +} + +func CleanUp(client k8s.Client, nsName types.NamespacedName) error { + if ShouldManageAutodiscoverRBAC() { + clusterRoleBinding := &rbacv1.ClusterRoleBinding{ + ObjectMeta: metav1.ObjectMeta{ + Name: ClusterRoleBindingName(nsName.Namespace, nsName.Name), + }, + } + + if err := client.Delete(clusterRoleBinding); err != nil { + if !apierrors.IsNotFound(err) { + return err + } + } + } + + return nil +} + +func IsAutodiscoverResource(meta metav1.Object) (bool, types.NamespacedName) { + labels := meta.GetLabels() + if labels == nil { + return false, types.NamespacedName{} + } + + name, okName := labels[autodiscoverBeatNameLabelName] + ns, okNs := labels[autodiscoverBeatNamespaceLabelName] + if okName && okNs { + return true, types.NamespacedName{ + Name: name, + Namespace: ns, + } + } + + return false, types.NamespacedName{} +} + +func reconcileAutodiscoverRBAC(ctx context.Context, client k8s.Client, beat beatv1beta1.Beat) error { + span, _ := apm.StartSpan(ctx, "reconcile_autodiscover_rbac", tracing.SpanTypeApp) + defer span.End() + + if err := reconcileServiceAccount(client, beat); err != nil { + return err + } + + if err := reconcileClusterRoleBinding(client, beat); err != nil { + return err + } + + return nil +} + +func reconcileServiceAccount(client k8s.Client, beat beatv1beta1.Beat) error { + expected := &corev1.ServiceAccount{ + ObjectMeta: metav1.ObjectMeta{ + Name: ServiceAccountName(beat.Name), + Namespace: beat.Namespace, + Labels: addLabels(NewLabels(beat), beat), + }, + } + expected.Labels = hash.SetTemplateHashLabel(nil, expected) + + reconciled := &corev1.ServiceAccount{} + return reconciler.ReconcileResource(reconciler.Params{ + Client: client, + Owner: &beat, + Expected: expected, + Reconciled: reconciled, + NeedsUpdate: func() bool { + // compare hash of the service account at the time it was built + return hash.GetTemplateHashLabel(expected.Labels) != hash.GetTemplateHashLabel(reconciled.Labels) + }, + UpdateReconciled: func() { + expected.DeepCopyInto(reconciled) + }, + }) +} + +func reconcileClusterRoleBinding(client k8s.Client, beat beatv1beta1.Beat) error { + expected := &rbacv1.ClusterRoleBinding{ + ObjectMeta: metav1.ObjectMeta{ + Name: ClusterRoleBindingName(beat.Namespace, beat.Name), + Labels: addLabels(nil, beat), + }, + Subjects: []rbacv1.Subject{ + { + Kind: "ServiceAccount", + Name: ServiceAccountName(beat.Name), + Namespace: beat.Namespace, + }, + }, + RoleRef: rbacv1.RoleRef{ + APIGroup: rbacv1.GroupName, + Kind: "ClusterRole", + Name: clusterRoleName, + }, + } + expected.Labels = hash.SetTemplateHashLabel(expected.Labels, expected) + + reconciled := &rbacv1.ClusterRoleBinding{} + return reconciler.ReconcileResource(reconciler.Params{ + Client: client, + Expected: expected, + Reconciled: reconciled, + NeedsUpdate: func() bool { + // compare hash of the cluster role binding at the time it was built + return hash.GetTemplateHashLabel(expected.Labels) != hash.GetTemplateHashLabel(reconciled.Labels) + }, + UpdateReconciled: func() { + expected.DeepCopyInto(reconciled) + }, + }) +} + +func addLabels(labels map[string]string, beat beatv1beta1.Beat) map[string]string { + return maps.Merge(labels, map[string]string{ + autodiscoverBeatNameLabelName: beat.Name, + autodiscoverBeatNamespaceLabelName: beat.Namespace, + }) +} + +func ClusterRoleBindingName(namespace, name string) string { + return fmt.Sprintf(clusterRoleBindingNameTemplate, namespace, name) +} + +func ServiceAccountName(name string) string { + return fmt.Sprintf(serviceAccountNameTemplate, name) +} diff --git a/pkg/controller/beat/common/config.go b/pkg/controller/beat/common/config.go new file mode 100644 index 0000000000..633dcc50e3 --- /dev/null +++ b/pkg/controller/beat/common/config.go @@ -0,0 +1,121 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package common + +import ( + "hash" + "path" + + "github.com/go-logr/logr" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + beatv1beta1 "github.com/elastic/cloud-on-k8s/pkg/apis/beat/v1beta1" + commonv1 "github.com/elastic/cloud-on-k8s/pkg/apis/common/v1" + "github.com/elastic/cloud-on-k8s/pkg/controller/association" + "github.com/elastic/cloud-on-k8s/pkg/controller/common" + "github.com/elastic/cloud-on-k8s/pkg/controller/common/reconciler" + "github.com/elastic/cloud-on-k8s/pkg/controller/common/settings" + "github.com/elastic/cloud-on-k8s/pkg/utils/k8s" +) + +// setOutput will set the output section in Beat config according to the association configuration. +func setOutput(cfg *settings.CanonicalConfig, client k8s.Client, associated commonv1.Association) error { + if !associated.AssociationConf().IsConfigured() { + return nil + } + + username, password, err := association.ElasticsearchAuthSettings(client, associated) + if err != nil { + return err + } + + esOutput := settings.MustCanonicalConfig( + map[string]interface{}{ + "output.elasticsearch": map[string]interface{}{ + "hosts": []string{associated.AssociationConf().GetURL()}, + "username": username, + "password": password, + }, + }) + + if err := cfg.MergeWith(esOutput); err != nil { + return err + } + + if associated.AssociationConf().GetCACertProvided() { + if err := cfg.MergeWith(settings.MustCanonicalConfig( + map[string]interface{}{ + "output.elasticsearch.ssl.certificate_authorities": path.Join(CAMountPath, CAFileName), + })); err != nil { + return err + } + } + + return nil +} + +func buildBeatConfig( + log logr.Logger, + client k8s.Client, + beat beatv1beta1.Beat, + defaultConfig *settings.CanonicalConfig, +) ([]byte, error) { + cfg := settings.NewCanonicalConfig() + + if err := setOutput(cfg, client, &beat); err != nil { + return nil, err + } + + // use only the default config or only the provided config - no overriding, no merging + userConfig := beat.Spec.Config + if userConfig == nil { + if err := cfg.MergeWith(defaultConfig); err != nil { + return nil, err + } + } else { + userCfg, err := settings.NewCanonicalConfigFrom(userConfig.Data) + if err != nil { + return nil, err + } + + if err = cfg.MergeWith(userCfg); err != nil { + return nil, err + } + log.V(1).Info("Replacing ECK-managed configuration by user-provided configuration") + } + + return cfg.Render() +} + +func reconcileConfig( + params DriverParams, + defaultConfig *settings.CanonicalConfig, + configHash hash.Hash, +) error { + cfgBytes, err := buildBeatConfig(params.Logger, params.Client, params.Beat, defaultConfig) + if err != nil { + return err + } + + expected := corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: params.Beat.Namespace, + Name: ConfigSecretName(params.Beat.Spec.Type, params.Beat.Name), + Labels: common.AddCredentialsLabel(NewLabels(params.Beat)), + }, + Data: map[string][]byte{ + ConfigFileName: cfgBytes, + }, + } + + if _, err = reconciler.ReconcileSecret(params.Client, expected, ¶ms.Beat); err != nil { + return err + } + + _, _ = configHash.Write(cfgBytes) + + return nil +} diff --git a/pkg/controller/beat/common/config_test.go b/pkg/controller/beat/common/config_test.go new file mode 100644 index 0000000000..36d1b740ac --- /dev/null +++ b/pkg/controller/beat/common/config_test.go @@ -0,0 +1,161 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package common + +import ( + "testing" + + logrtesting "github.com/go-logr/logr/testing" + "github.com/stretchr/testify/require" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + beatv1beta1 "github.com/elastic/cloud-on-k8s/pkg/apis/beat/v1beta1" + commonv1 "github.com/elastic/cloud-on-k8s/pkg/apis/common/v1" + "github.com/elastic/cloud-on-k8s/pkg/controller/common/settings" + "github.com/elastic/cloud-on-k8s/pkg/utils/k8s" +) + +func Test_buildBeatConfig(t *testing.T) { + clientWithSecret := k8s.WrappedFakeClient( + &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "secret", + Namespace: "ns", + }, + Data: map[string][]byte{"elastic": []byte("123")}, + }, + &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "secret2", + Namespace: "ns", + }, + Data: map[string][]byte{"elastic": []byte("123")}, + }, + ) + + defaultConfig := settings.MustParseConfig([]byte("default: true")) + userConfig := &commonv1.Config{Data: map[string]interface{}{"user": "true"}} + userCanonicalConfig := settings.MustCanonicalConfig(userConfig.Data) + outputCAYaml := settings.MustParseConfig([]byte("output.elasticsearch.ssl.certificate_authorities: /mnt/elastic-internal/es-certs/ca.crt")) + outputYaml := settings.MustParseConfig([]byte(`output: + elasticsearch: + hosts: + - url + password: "123" + username: elastic +`)) + + withAssociation := beatv1beta1.Beat{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "ns", + }, + } + withAssociation.SetAssociationConf(&commonv1.AssociationConf{ + AuthSecretName: "secret", + AuthSecretKey: "elastic", + CACertProvided: false, + CASecretName: "secret2", + URL: "url", + }) + withAssociationWithCA := *withAssociation.DeepCopy() + withAssociationWithCA.AssociationConf().CACertProvided = true + + withAssociationWithCAAndConfig := *withAssociationWithCA.DeepCopy() + withAssociationWithCAAndConfig.Spec.Config = userConfig + + withAssociationWithConfig := *withAssociation.DeepCopy() + withAssociationWithConfig.Spec.Config = userConfig + + merge := func(cs ...*settings.CanonicalConfig) *settings.CanonicalConfig { + result := settings.NewCanonicalConfig() + _ = result.MergeWith(cs...) + return result + } + + for _, tt := range []struct { + name string + client k8s.Client + beat beatv1beta1.Beat + defaultConfig *settings.CanonicalConfig + want *settings.CanonicalConfig + wantErr bool + }{ + { + name: "neither default nor user config", + beat: beatv1beta1.Beat{}, + }, + { + name: "no association, only default config", + beat: beatv1beta1.Beat{}, + defaultConfig: defaultConfig, + want: defaultConfig, + }, + { + name: "no association, only user config", + beat: beatv1beta1.Beat{Spec: beatv1beta1.BeatSpec{ + Config: userConfig, + }}, + want: userCanonicalConfig, + }, + { + name: "no association, default and user config", + beat: beatv1beta1.Beat{Spec: beatv1beta1.BeatSpec{ + Config: userConfig, + }}, + defaultConfig: defaultConfig, + want: userCanonicalConfig, + }, + { + name: "association without ca, only default config", + client: clientWithSecret, + beat: withAssociation, + defaultConfig: defaultConfig, + want: merge(defaultConfig, outputYaml), + }, + { + name: "association without ca, only user config", + client: clientWithSecret, + beat: withAssociationWithConfig, + want: merge(userCanonicalConfig, outputYaml), + }, + { + name: "association without ca, default and user config", + client: clientWithSecret, + beat: withAssociationWithConfig, + defaultConfig: defaultConfig, + want: merge(userCanonicalConfig, outputYaml), + }, + { + name: "association with ca, only default config", + client: clientWithSecret, + beat: withAssociationWithCA, + defaultConfig: defaultConfig, + want: merge(defaultConfig, outputYaml, outputCAYaml), + }, + { + name: "association with ca, only user config", + client: clientWithSecret, + beat: withAssociationWithCAAndConfig, + want: merge(userCanonicalConfig, outputYaml, outputCAYaml), + }, + { + name: "association with ca, default and user config", + client: clientWithSecret, + beat: withAssociationWithCAAndConfig, + defaultConfig: defaultConfig, + want: merge(userCanonicalConfig, outputYaml, outputCAYaml), + }, + } { + t.Run(tt.name, func(t *testing.T) { + gotYaml, gotErr := buildBeatConfig(logrtesting.NullLogger{}, tt.client, tt.beat, tt.defaultConfig) + + diff := tt.want.Diff(settings.MustParseConfig(gotYaml), nil) + + require.Empty(t, diff) + require.Equal(t, gotErr != nil, tt.wantErr) + }) + } +} diff --git a/pkg/controller/beat/common/driver.go b/pkg/controller/beat/common/driver.go new file mode 100644 index 0000000000..1257581e35 --- /dev/null +++ b/pkg/controller/beat/common/driver.go @@ -0,0 +1,86 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package common + +import ( + "context" + "crypto/sha256" + "fmt" + + "github.com/go-logr/logr" + corev1 "k8s.io/api/core/v1" + + beatv1beta1 "github.com/elastic/cloud-on-k8s/pkg/apis/beat/v1beta1" + commonassociation "github.com/elastic/cloud-on-k8s/pkg/controller/common/association" + "github.com/elastic/cloud-on-k8s/pkg/controller/common/container" + "github.com/elastic/cloud-on-k8s/pkg/controller/common/defaults" + "github.com/elastic/cloud-on-k8s/pkg/controller/common/reconciler" + "github.com/elastic/cloud-on-k8s/pkg/controller/common/settings" + "github.com/elastic/cloud-on-k8s/pkg/utils/k8s" +) + +type Type string + +type Driver interface { + Reconcile() *reconciler.Results +} + +type DriverParams struct { + Client k8s.Client + Context context.Context + Logger logr.Logger + + Beat beatv1beta1.Beat +} + +func (dp *DriverParams) GetPodTemplate() corev1.PodTemplateSpec { + spec := dp.Beat.Spec + switch { + case spec.DaemonSet != nil: + return spec.DaemonSet.PodTemplate + case spec.Deployment != nil: + return spec.Deployment.PodTemplate + } + + return corev1.PodTemplateSpec{} +} + +func ValidateBeatSpec(spec beatv1beta1.BeatSpec) error { + if (spec.DaemonSet == nil && spec.Deployment == nil) || (spec.DaemonSet != nil && spec.Deployment != nil) { + return fmt.Errorf("either daemonset or deployment has to be specified") + } + return nil +} + +func Reconcile( + params DriverParams, + defaultConfig *settings.CanonicalConfig, + defaultImage container.Image, + modifyPodFunc func(builder *defaults.PodTemplateBuilder), +) *reconciler.Results { + results := reconciler.NewResult(params.Context) + + if err := ValidateBeatSpec(params.Beat.Spec); err != nil { + return results.WithError(err) + } + + if err := ReconcileAutodiscoverRBAC(params.Context, params.Logger, params.Client, params.Beat); err != nil { + results.WithError(err) + } + + configHash := sha256.New224() + if err := reconcileConfig(params, defaultConfig, configHash); err != nil { + return results.WithError(err) + } + + // we need to deref the secret here (if any) to include it in the configHash otherwise Beat will not be rolled on content changes + if err := commonassociation.WriteAssocToConfigHash(params.Client, ¶ms.Beat, configHash); err != nil { + return results.WithError(err) + } + + podTemplate := buildPodTemplate(params, defaultImage, modifyPodFunc, configHash) + results.WithResults(reconcilePodVehicle(podTemplate, params)) + return results +} diff --git a/pkg/controller/beat/common/driver_test.go b/pkg/controller/beat/common/driver_test.go new file mode 100644 index 0000000000..fe8d424932 --- /dev/null +++ b/pkg/controller/beat/common/driver_test.go @@ -0,0 +1,53 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package common + +import ( + "testing" + + beatv1beta1 "github.com/elastic/cloud-on-k8s/pkg/apis/beat/v1beta1" + "github.com/stretchr/testify/require" +) + +func Test_DriverParamsValidate(t *testing.T) { + params := func(ds *beatv1beta1.DaemonSetSpec, d *beatv1beta1.DeploymentSpec) DriverParams { + return DriverParams{ + Beat: beatv1beta1.Beat{ + Spec: beatv1beta1.BeatSpec{ + DaemonSet: ds, + Deployment: d, + }, + }, + } + } + + for _, tt := range []struct { + name string + driverParams DriverParams + wantErr bool + }{ + { + driverParams: params(nil, nil), + wantErr: true, + }, + { + driverParams: params(&beatv1beta1.DaemonSetSpec{}, &beatv1beta1.DeploymentSpec{}), + wantErr: true, + }, + { + driverParams: params(&beatv1beta1.DaemonSetSpec{}, nil), + wantErr: false, + }, + { + driverParams: params(nil, &beatv1beta1.DeploymentSpec{}), + wantErr: false, + }, + } { + t.Run(tt.name, func(t *testing.T) { + gotErr := ValidateBeatSpec(tt.driverParams.Beat.Spec) != nil + require.True(t, tt.wantErr == gotErr) + }) + } +} diff --git a/pkg/controller/beat/common/health.go b/pkg/controller/beat/common/health.go new file mode 100644 index 0000000000..675d371e10 --- /dev/null +++ b/pkg/controller/beat/common/health.go @@ -0,0 +1,26 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package common + +import ( + beatv1beta1 "github.com/elastic/cloud-on-k8s/pkg/apis/beat/v1beta1" + v1 "github.com/elastic/cloud-on-k8s/pkg/apis/common/v1" +) + +// CalculateHealth returns health of the Beat based on association status, desired count and ready count. +func CalculateHealth(associated v1.Association, ready, desired int32) beatv1beta1.BeatHealth { + if associated.AssociationConf().IsConfigured() && associated.AssociationStatus() != v1.AssociationEstablished { + return beatv1beta1.BeatRedHealth + } + + switch { + case ready == desired: + return beatv1beta1.BeatGreenHealth + case ready > 0: + return beatv1beta1.BeatYellowHealth + default: + return beatv1beta1.BeatRedHealth + } +} diff --git a/pkg/controller/beat/common/health_test.go b/pkg/controller/beat/common/health_test.go new file mode 100644 index 0000000000..ea3907a61e --- /dev/null +++ b/pkg/controller/beat/common/health_test.go @@ -0,0 +1,109 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package common_test + +import ( + "testing" + + beatcommon "github.com/elastic/cloud-on-k8s/pkg/controller/beat/common" + "github.com/stretchr/testify/require" + + beatv1beta1 "github.com/elastic/cloud-on-k8s/pkg/apis/beat/v1beta1" + commonv1 "github.com/elastic/cloud-on-k8s/pkg/apis/common/v1" +) + +func Test_CalculateHealth(t *testing.T) { + noAssociation := &beatv1beta1.Beat{} + createAssociation := func(associationEstablished bool) commonv1.Association { + result := &beatv1beta1.Beat{} + result.SetAssociationConf(&commonv1.AssociationConf{ + AuthSecretName: "name", + AuthSecretKey: "key", + CACertProvided: true, + CASecretName: "name", + URL: "url", + }) + + if associationEstablished { + result.SetAssociationStatus(commonv1.AssociationEstablished) + } + + return result + } + + for _, tt := range []struct { + name string + association commonv1.Association + ready, desired int32 + want beatv1beta1.BeatHealth + }{ + { + name: "no association, 0 desired", + association: noAssociation, + ready: 0, + desired: 0, + want: beatv1beta1.BeatGreenHealth, + }, + { + name: "no association, all ready", + association: noAssociation, + ready: 3, + desired: 3, + want: beatv1beta1.BeatGreenHealth, + }, + { + name: "no association, some ready", + association: noAssociation, + ready: 1, + desired: 5, + want: beatv1beta1.BeatYellowHealth, + }, + { + name: "no association, none ready", + association: noAssociation, + ready: 0, + desired: 4, + want: beatv1beta1.BeatRedHealth, + }, + { + name: "association not established, all ready", + association: createAssociation(false), + ready: 2, + desired: 2, + want: beatv1beta1.BeatRedHealth, + }, + { + name: "association established, 0 desired", + association: createAssociation(true), + want: beatv1beta1.BeatGreenHealth, + }, + { + name: "association established, all ready", + association: createAssociation(true), + ready: 2, + desired: 2, + want: beatv1beta1.BeatGreenHealth, + }, + { + name: "association established, some ready", + association: createAssociation(true), + ready: 1, + desired: 5, + want: beatv1beta1.BeatYellowHealth, + }, + { + name: "association established, none ready", + association: createAssociation(true), + ready: 0, + desired: 4, + want: beatv1beta1.BeatRedHealth, + }, + } { + t.Run(tt.name, func(t *testing.T) { + got := beatcommon.CalculateHealth(tt.association, tt.ready, tt.desired) + require.Equal(t, tt.want, got) + }) + } +} diff --git a/pkg/controller/beat/common/labels.go b/pkg/controller/beat/common/labels.go new file mode 100644 index 0000000000..d2bb6c0032 --- /dev/null +++ b/pkg/controller/beat/common/labels.go @@ -0,0 +1,25 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package common + +import ( + beatv1beta1 "github.com/elastic/cloud-on-k8s/pkg/apis/beat/v1beta1" + "github.com/elastic/cloud-on-k8s/pkg/controller/common" +) + +const ( + // Type represents the Beat type. + TypeLabelValue = "beat" + + // NameLabelName is used to represent a Beat in k8s resources. + NameLabelName = "beat.k8s.elastic.co/name" +) + +func NewLabels(beat beatv1beta1.Beat) map[string]string { + return map[string]string{ + common.TypeLabelName: TypeLabelValue, + NameLabelName: Name(beat.Name, beat.Spec.Type), + } +} diff --git a/pkg/controller/beat/common/name.go b/pkg/controller/beat/common/name.go new file mode 100644 index 0000000000..efe53414e2 --- /dev/null +++ b/pkg/controller/beat/common/name.go @@ -0,0 +1,20 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package common + +import ( + common_name "github.com/elastic/cloud-on-k8s/pkg/controller/common/name" +) + +// namer is a Namer that is configured with the defaults for resources related to a Beat resource. +var namer = common_name.NewNamer("beat") + +func ConfigSecretName(typeName, name string) string { + return namer.Suffix(name, typeName, "config") +} + +func Name(name, typeName string) string { + return namer.Suffix(name, typeName) +} diff --git a/pkg/controller/beat/common/name_test.go b/pkg/controller/beat/common/name_test.go new file mode 100644 index 0000000000..748c130c60 --- /dev/null +++ b/pkg/controller/beat/common/name_test.go @@ -0,0 +1,77 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package common + +import "testing" + +func TestNamer_ConfigSecretName(t *testing.T) { + for _, tt := range []struct { + name string + resourceName string + typ string + want string + }{ + { + name: "filebeat type", + resourceName: "my", + typ: "filebeat", + want: "my-beat-filebeat-config", + }, + { + name: "metricbeat type", + resourceName: "sample-metricbeat", + typ: "metricbeat", + want: "sample-metricbeat-beat-metricbeat-config", + }, + { + name: "other type", + resourceName: "x", + typ: "mybeat", + want: "x-beat-mybeat-config", + }, + } { + t.Run(tt.name, func(t *testing.T) { + got := ConfigSecretName(tt.typ, tt.resourceName) + if got != tt.want { + t.Errorf("config secret name is %s while %s was expected", got, tt.want) + } + }) + } +} + +func TestNamer_Name(t *testing.T) { + for _, tt := range []struct { + name string + resourceName string + typ string + want string + }{ + { + name: "filebeat type", + resourceName: "my", + typ: "filebeat", + want: "my-beat-filebeat", + }, + { + name: "metricbeat type", + resourceName: "sample-metricbeat", + typ: "metricbeat", + want: "sample-metricbeat-beat-metricbeat", + }, + { + name: "other type", + resourceName: "x", + typ: "mybeat", + want: "x-beat-mybeat", + }, + } { + t.Run(tt.name, func(t *testing.T) { + got := Name(tt.resourceName, tt.typ) + if got != tt.want { + t.Errorf("config secret name is %s while %s was expected", got, tt.want) + } + }) + } +} diff --git a/pkg/controller/beat/common/pod.go b/pkg/controller/beat/common/pod.go new file mode 100644 index 0000000000..ced1e0a729 --- /dev/null +++ b/pkg/controller/beat/common/pod.go @@ -0,0 +1,141 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package common + +import ( + "fmt" + "hash" + + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" + + "github.com/elastic/cloud-on-k8s/pkg/controller/common/container" + "github.com/elastic/cloud-on-k8s/pkg/controller/common/defaults" + "github.com/elastic/cloud-on-k8s/pkg/controller/common/volume" + "github.com/elastic/cloud-on-k8s/pkg/utils/maps" + "github.com/elastic/cloud-on-k8s/pkg/utils/pointer" +) + +const ( + CAVolumeName = "es-certs" + CAMountPath = "/mnt/elastic-internal/es-certs/" + CAFileName = "ca.crt" + + ConfigVolumeName = "config" + ConfigMountPath = "/etc/beat.yml" + ConfigFileName = "beat.yml" + + DataVolumeName = "data" + DataMountPathTemplate = "/var/lib/%s/%s/%s-data" + DataPathTemplate = "/usr/share/%s/data" + + // ConfigChecksumLabel is a label used to store a Beat config checksum. + ConfigChecksumLabel = "beat.k8s.elastic.co/config-checksum" + + // VersionLabelName is a label used to track the version of a Beat Pod. + VersionLabelName = "beat.k8s.elastic.co/version" +) + +var ( + defaultResources = corev1.ResourceRequirements{ + Limits: map[corev1.ResourceName]resource.Quantity{ + corev1.ResourceMemory: resource.MustParse("200Mi"), + corev1.ResourceCPU: resource.MustParse("100m"), + }, + Requests: map[corev1.ResourceName]resource.Quantity{ + corev1.ResourceMemory: resource.MustParse("200Mi"), + corev1.ResourceCPU: resource.MustParse("100m"), + }, + } +) + +func buildPodTemplate( + params DriverParams, + defaultImage container.Image, + modifyPodFunc func(builder *defaults.PodTemplateBuilder), + configHash hash.Hash) corev1.PodTemplateSpec { + podTemplate := params.GetPodTemplate() + + // Token mounting gets defaulted to false, which prevents from detecting whether user had set it. + // Instead, checking that here, before the default is applied. + // This is required for autodiscover which is enabled by default. + if podTemplate.Spec.AutomountServiceAccountToken == nil { + t := true + podTemplate.Spec.AutomountServiceAccountToken = &t + } + + spec := ¶ms.Beat.Spec + builder := defaults.NewPodTemplateBuilder(podTemplate, spec.Type) + + // might be nil if caller wants to use the default builder without any modifications + if modifyPodFunc != nil { + modifyPodFunc(builder) + } + + builder = builder. + WithTerminationGracePeriod(30). + WithEnv(corev1.EnvVar{ + Name: "NODE_NAME", + ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{ + FieldPath: "spec.nodeName", + }, + }}). + WithResources(defaultResources). + WithHostNetwork(). + WithLabels(maps.Merge(NewLabels(params.Beat), map[string]string{ + ConfigChecksumLabel: fmt.Sprintf("%x", configHash.Sum(nil)), + VersionLabelName: spec.Version})). + WithDockerImage(spec.Image, container.ImageRepository(defaultImage, spec.Version)). + WithArgs("-e", "-c", ConfigMountPath). + WithDNSPolicy(corev1.DNSClusterFirstWithHostNet). + WithPodSecurityContext(corev1.PodSecurityContext{ + RunAsUser: pointer.Int64(0), + }) + + if ShouldManageAutodiscoverRBAC() { + autodiscoverServiceAccountName := ServiceAccountName(params.Beat.Name) + // If SA is already provided, the call will be no-op. This is fine as we then assume + // that for this resource (despite operator configuration) the user took the responsibility + // of configuring RBAC. + builder.WithServiceAccount(autodiscoverServiceAccountName) + } + + dataVolume := createDataVolume(params) + volumes := []volume.VolumeLike{ + volume.NewSecretVolume( + ConfigSecretName(spec.Type, params.Beat.Name), + ConfigVolumeName, + ConfigMountPath, + ConfigFileName, + 0600), + dataVolume, + } + + if params.Beat.AssociationConf().CAIsConfigured() { + volumes = append(volumes, volume.NewSecretVolumeWithMountPath( + params.Beat.AssociationConf().GetCASecretName(), + CAVolumeName, + CAMountPath)) + } + + for _, v := range volumes { + builder = builder.WithVolumes(v.Volume()).WithVolumeMounts(v.VolumeMount()) + } + + return builder.PodTemplate +} + +func createDataVolume(dp DriverParams) volume.VolumeLike { + dataMountPath := fmt.Sprintf(DataPathTemplate, dp.Beat.Spec.Type) + hostDataPath := fmt.Sprintf(DataMountPathTemplate, dp.Beat.Namespace, dp.Beat.Name, dp.Beat.Spec.Type) + + return volume.NewHostVolume( + DataVolumeName, + hostDataPath, + dataMountPath, + false, + corev1.HostPathDirectoryOrCreate) +} diff --git a/pkg/controller/beat/common/reconcile.go b/pkg/controller/beat/common/reconcile.go new file mode 100644 index 0000000000..e078d5aa51 --- /dev/null +++ b/pkg/controller/beat/common/reconcile.go @@ -0,0 +1,144 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package common + +import ( + v1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/kubernetes/scheme" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + "sigs.k8s.io/controller-runtime/pkg/reconcile" + + beatv1beta1 "github.com/elastic/cloud-on-k8s/pkg/apis/beat/v1beta1" + "github.com/elastic/cloud-on-k8s/pkg/controller/common/daemonset" + "github.com/elastic/cloud-on-k8s/pkg/controller/common/deployment" + "github.com/elastic/cloud-on-k8s/pkg/controller/common/reconciler" + "github.com/elastic/cloud-on-k8s/pkg/utils/k8s" + "github.com/elastic/cloud-on-k8s/pkg/utils/pointer" +) + +func reconcilePodVehicle(podTemplate corev1.PodTemplateSpec, params DriverParams) *reconciler.Results { + results := reconciler.NewResult(params.Context) + if err := ValidateBeatSpec(params.Beat.Spec); err != nil { + return results.WithError(err) + } + + spec := params.Beat.Spec + name := Name(params.Beat.Name, spec.Type) + + var toDelete runtime.Object + var reconciliationFunc func(params ReconciliationParams) (int32, int32, error) + switch { + case spec.DaemonSet != nil: + reconciliationFunc = reconcileDaemonSet + toDelete = &v1.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: params.Beat.Namespace, + }, + } + case spec.Deployment != nil: + reconciliationFunc = reconcileDeployment + toDelete = &v1.DaemonSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: params.Beat.Namespace, + }, + } + } + + ready, desired, err := reconciliationFunc(ReconciliationParams{ + client: params.Client, + beat: params.Beat, + podTemplate: podTemplate, + }) + if err != nil { + return results.WithError(err) + } + + // clean up the other one + if err := params.Client.Get(types.NamespacedName{ + Namespace: params.Beat.Namespace, + Name: name, + }, toDelete); err == nil { + results.WithError(params.Client.Delete(toDelete)) + } else if !apierrors.IsNotFound(err) { + results.WithError(err) + } + + err = updateStatus(params, ready, desired) + if err != nil && apierrors.IsConflict(err) { + params.Logger.V(1).Info( + "Conflict while updating status", + "namespace", params.Beat.Namespace, + "beat_name", params.Beat.Name) + return results.WithResult(reconcile.Result{Requeue: true}) + } + + return results.WithError(err) +} + +type ReconciliationParams struct { + client k8s.Client + beat beatv1beta1.Beat + podTemplate corev1.PodTemplateSpec +} + +func reconcileDeployment(rp ReconciliationParams) (int32, int32, error) { + d := deployment.New(deployment.Params{ + Name: Name(rp.beat.Name, rp.beat.Spec.Type), + Namespace: rp.beat.Namespace, + Selector: NewLabels(rp.beat), + Labels: NewLabels(rp.beat), + PodTemplateSpec: rp.podTemplate, + Replicas: pointer.Int32OrDefault(rp.beat.Spec.Deployment.Replicas, int32(1)), + }) + if err := controllerutil.SetControllerReference(&rp.beat, &d, scheme.Scheme); err != nil { + return 0, 0, err + } + + reconciled, err := deployment.Reconcile(rp.client, d, &rp.beat) + if err != nil { + return 0, 0, err + } + + return reconciled.Status.ReadyReplicas, reconciled.Status.Replicas, nil +} + +func reconcileDaemonSet(rp ReconciliationParams) (int32, int32, error) { + ds := daemonset.New(daemonset.Params{ + PodTemplate: rp.podTemplate, + Name: Name(rp.beat.Name, rp.beat.Spec.Type), + Owner: &rp.beat, + Labels: NewLabels(rp.beat), + Selectors: NewLabels(rp.beat), + }) + + if err := controllerutil.SetControllerReference(&rp.beat, &ds, scheme.Scheme); err != nil { + return 0, 0, err + } + + reconciled, err := daemonset.Reconcile(rp.client, ds, &rp.beat) + if err != nil { + return 0, 0, err + } + + return reconciled.Status.NumberReady, reconciled.Status.DesiredNumberScheduled, nil +} + +func updateStatus(params DriverParams, ready, desired int32) error { + beat := params.Beat + + beat.Status.AvailableNodes = ready + beat.Status.ExpectedNodes = desired + beat.Status.Health = CalculateHealth(&beat, ready, desired) + beat.Status.Association = beat.AssociationStatus() + + return params.Client.Status().Update(&beat) +} diff --git a/pkg/controller/beat/controller.go b/pkg/controller/beat/controller.go new file mode 100644 index 0000000000..61be0d1f31 --- /dev/null +++ b/pkg/controller/beat/controller.go @@ -0,0 +1,244 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package beat + +import ( + "context" + + beatcommon "github.com/elastic/cloud-on-k8s/pkg/controller/beat/common" + "github.com/elastic/cloud-on-k8s/pkg/controller/beat/filebeat" + "go.elastic.co/apm" + appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + rbacv1 "k8s.io/api/rbac/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/tools/record" + "sigs.k8s.io/controller-runtime/pkg/controller" + "sigs.k8s.io/controller-runtime/pkg/handler" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/manager" + "sigs.k8s.io/controller-runtime/pkg/reconcile" + "sigs.k8s.io/controller-runtime/pkg/source" + + beatv1beta1 "github.com/elastic/cloud-on-k8s/pkg/apis/beat/v1beta1" + "github.com/elastic/cloud-on-k8s/pkg/controller/association" + "github.com/elastic/cloud-on-k8s/pkg/controller/beat/metricbeat" + "github.com/elastic/cloud-on-k8s/pkg/controller/beat/otherbeat" + "github.com/elastic/cloud-on-k8s/pkg/controller/common" + "github.com/elastic/cloud-on-k8s/pkg/controller/common/annotation" + "github.com/elastic/cloud-on-k8s/pkg/controller/common/events" + "github.com/elastic/cloud-on-k8s/pkg/controller/common/operator" + "github.com/elastic/cloud-on-k8s/pkg/controller/common/reconciler" + "github.com/elastic/cloud-on-k8s/pkg/controller/common/tracing" + "github.com/elastic/cloud-on-k8s/pkg/controller/common/watches" + "github.com/elastic/cloud-on-k8s/pkg/utils/k8s" +) + +const ( + controllerName = "beat-controller" +) + +var log = logf.Log.WithName(controllerName) + +// Add creates a new Beat Controller and adds it to the Manager with default RBAC. The Manager will set fields on the Controller +// and Start it when the Manager is Started. +func Add(mgr manager.Manager, params operator.Parameters) error { + r := newReconciler(mgr, params) + c, err := common.NewController(mgr, controllerName, r, params) + if err != nil { + return err + } + return addWatches(c) +} + +// newReconciler returns a new reconcile.Reconciler. +func newReconciler(mgr manager.Manager, params operator.Parameters) *ReconcileBeat { + client := k8s.WrapClient(mgr.GetClient()) + return &ReconcileBeat{ + Client: client, + recorder: mgr.GetEventRecorderFor(controllerName), + dynamicWatches: watches.NewDynamicWatches(), + Parameters: params, + } +} + +// Watch DaemonSets and Deployments +func addWatches(c controller.Controller) error { + // Watch for changes to Beat + if err := c.Watch(&source.Kind{Type: &beatv1beta1.Beat{}}, &handler.EnqueueRequestForObject{}); err != nil { + return err + } + + // Watch DaemonSets + if err := c.Watch(&source.Kind{Type: &appsv1.DaemonSet{}}, &handler.EnqueueRequestForOwner{ + IsController: true, + OwnerType: &beatv1beta1.Beat{}, + }); err != nil { + return err + } + + // Watch Deployments + if err := c.Watch(&source.Kind{Type: &appsv1.Deployment{}}, &handler.EnqueueRequestForOwner{ + IsController: true, + OwnerType: &beatv1beta1.Beat{}, + }); err != nil { + return err + } + + // Watch Secrets + if err := c.Watch(&source.Kind{Type: &corev1.Secret{}}, &handler.EnqueueRequestForOwner{ + IsController: true, + OwnerType: &beatv1beta1.Beat{}, + }); err != nil { + return err + } + + if beatcommon.ShouldManageAutodiscoverRBAC() { + // Watch ServiceAccounts + if err := c.Watch(&source.Kind{Type: &corev1.ServiceAccount{}}, &handler.EnqueueRequestForOwner{ + IsController: true, + OwnerType: &beatv1beta1.Beat{}, + }); err != nil { + return err + } + + // Watch relevant ClusterRoleBindings + if err := c.Watch(&source.Kind{Type: &rbacv1.ClusterRoleBinding{}}, &handler.EnqueueRequestsFromMapFunc{ + ToRequests: handler.ToRequestsFunc(func(object handler.MapObject) []reconcile.Request { + requests := []reconcile.Request{} + if result, nsName := beatcommon.IsAutodiscoverResource(object.Meta); result { + requests = append(requests, reconcile.Request{NamespacedName: nsName}) + } + return requests + }), + }); err != nil { + return err + } + } + + return nil +} + +var _ reconcile.Reconciler = &ReconcileBeat{} + +// ReconcileBeat reconciles a Beat object. +type ReconcileBeat struct { + k8s.Client + recorder record.EventRecorder + dynamicWatches watches.DynamicWatches + operator.Parameters + // iteration is the number of times this controller has run its Reconcile method + iteration uint64 +} + +// Reconcile reads that state of the cluster for a Beat object and makes changes based on the state read +// and what is in the Beat.Spec. +func (r *ReconcileBeat) Reconcile(request reconcile.Request) (reconcile.Result, error) { + defer common.LogReconciliationRun(log, request, "beat_name", &r.iteration)() + tx, ctx := tracing.NewTransaction(r.Tracer, request.NamespacedName, "beat") + defer tracing.EndTransaction(tx) + + var beat beatv1beta1.Beat + if err := association.FetchWithAssociations(ctx, r.Client, request, &beat); err != nil { + if apierrors.IsNotFound(err) { + if err := r.onDelete(types.NamespacedName{ + Namespace: request.Namespace, + Name: request.Name, + }); err != nil { + return reconcile.Result{Requeue: true}, nil + } + return reconcile.Result{}, nil + } + return reconcile.Result{}, tracing.CaptureError(ctx, err) + } + + if common.IsUnmanaged(&beat) { + log.Info("Object is currently not managed by this controller. Skipping reconciliation", "namespace", beat.Namespace, "ent_name", beat.Name) + return reconcile.Result{}, nil + } + + if compatible, err := r.isCompatible(ctx, &beat); err != nil || !compatible { + return reconcile.Result{}, tracing.CaptureError(ctx, err) + } + + if beat.IsMarkedForDeletion() { + return reconcile.Result{}, nil + } + + if err := annotation.UpdateControllerVersion(ctx, r.Client, &beat, r.OperatorInfo.BuildInfo.Version); err != nil { + return reconcile.Result{}, tracing.CaptureError(ctx, err) + } + + res, err := r.doReconcile(ctx, beat).Aggregate() + k8s.EmitErrorEvent(r.recorder, err, &beat, events.EventReconciliationError, "Reconciliation error: %v", err) + + return res, err +} + +func (r *ReconcileBeat) doReconcile(ctx context.Context, beat beatv1beta1.Beat) *reconciler.Results { + results := reconciler.NewResult(ctx) + if !association.IsConfiguredIfSet(&beat, r.recorder) { + return results + } + + // Run validation in case the webhook is disabled + if err := r.validate(ctx, &beat); err != nil { + return results.WithError(err) + } + + driverResults := newDriver(ctx, r.Client, beat).Reconcile() + results.WithResults(driverResults) + + return results +} + +func (r *ReconcileBeat) validate(ctx context.Context, beat *beatv1beta1.Beat) error { + span, vctx := apm.StartSpan(ctx, "validate", tracing.SpanTypeApp) + defer span.End() + + if err := beat.ValidateCreate(); err != nil { + log.Error(err, "Validation failed") + k8s.EmitErrorEvent(r.recorder, err, beat, events.EventReasonValidation, err.Error()) + return tracing.CaptureError(vctx, err) + } + + return nil +} + +func (r *ReconcileBeat) isCompatible(ctx context.Context, beat *beatv1beta1.Beat) (bool, error) { + selector := map[string]string{beatcommon.NameLabelName: beat.Name} + compat, err := annotation.ReconcileCompatibility(ctx, r.Client, beat, selector, r.OperatorInfo.BuildInfo.Version) + if err != nil { + k8s.EmitErrorEvent(r.recorder, err, beat, events.EventCompatCheckError, "Error during compatibility check: %v", err) + } + return compat, err +} + +func (r *ReconcileBeat) onDelete(obj types.NamespacedName) error { + if beatcommon.ShouldManageAutodiscoverRBAC() { + return beatcommon.CleanUp(r.Client, obj) + } + + return nil +} + +func newDriver(ctx context.Context, client k8s.Client, beat beatv1beta1.Beat) beatcommon.Driver { + dp := beatcommon.DriverParams{ + Client: client, + Context: ctx, + Logger: log, + Beat: beat, + } + + switch beat.Spec.Type { + case string(filebeat.Type): + return filebeat.NewDriver(dp) + case string(metricbeat.Type): + return metricbeat.NewDriver(dp) + default: + return otherbeat.NewDriver(dp) + } +} diff --git a/pkg/controller/beat/filebeat/config.go b/pkg/controller/beat/filebeat/config.go new file mode 100644 index 0000000000..a62429032a --- /dev/null +++ b/pkg/controller/beat/filebeat/config.go @@ -0,0 +1,26 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package filebeat + +import "github.com/elastic/cloud-on-k8s/pkg/controller/common/settings" + +var ( + defaultConfig = settings.MustParseConfig([]byte( + `filebeat: + autodiscover: + providers: + - type: kubernetes + node: ${NODE_NAME} + hints: + enabled: true + default_config: + type: container + paths: + - /var/log/containers/*${data.kubernetes.container.id}.log +processors: +- add_cloud_metadata: {} +- add_host_metadata: {} +`)) +) diff --git a/pkg/controller/beat/filebeat/filebeat.go b/pkg/controller/beat/filebeat/filebeat.go new file mode 100644 index 0000000000..7f36d78241 --- /dev/null +++ b/pkg/controller/beat/filebeat/filebeat.go @@ -0,0 +1,67 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package filebeat + +import ( + beatv1beta1 "github.com/elastic/cloud-on-k8s/pkg/apis/beat/v1beta1" + beatcommon "github.com/elastic/cloud-on-k8s/pkg/controller/beat/common" + "github.com/elastic/cloud-on-k8s/pkg/controller/common/container" + "github.com/elastic/cloud-on-k8s/pkg/controller/common/defaults" + "github.com/elastic/cloud-on-k8s/pkg/controller/common/reconciler" + "github.com/elastic/cloud-on-k8s/pkg/controller/common/volume" +) + +const ( + Type beatcommon.Type = "filebeat" + + HostContainersVolumeName = "varlibdockercontainers" + HostContainersPath = "/var/lib/docker/containers" + HostContainersMountPath = "/var/lib/docker/containers" + + HostContainersLogsVolumeName = "varlogcontainers" + HostContainersLogsPath = "/var/log/containers" + HostContainersLogsMountPath = "/var/log/containers" + + HostPodsLogsVolumeName = "varlogpods" + HostPodsLogsPath = "/var/log/pods" + HostPodsLogsMountPath = "/var/log/pods" +) + +type Driver struct { + beatcommon.DriverParams + beatcommon.Driver +} + +func NewDriver(params beatcommon.DriverParams) beatcommon.Driver { + spec := ¶ms.Beat.Spec + // use the default for filebeat type if not provided + if spec.DaemonSet == nil && spec.Deployment == nil { + spec.DaemonSet = &beatv1beta1.DaemonSetSpec{} + } + + return &Driver{DriverParams: params} +} + +func (d *Driver) Reconcile() *reconciler.Results { + f := func(builder *defaults.PodTemplateBuilder) { + containersVolume := volume.NewReadOnlyHostVolume(HostContainersVolumeName, HostContainersPath, HostContainersMountPath) + containersLogsVolume := volume.NewReadOnlyHostVolume(HostContainersLogsVolumeName, HostContainersLogsPath, HostContainersLogsMountPath) + podsLogsVolume := volume.NewReadOnlyHostVolume(HostPodsLogsVolumeName, HostPodsLogsPath, HostPodsLogsMountPath) + + for _, volume := range []volume.VolumeLike{ + containersVolume, + containersLogsVolume, + podsLogsVolume, + } { + builder.WithVolumes(volume.Volume()).WithVolumeMounts(volume.VolumeMount()) + } + } + + return beatcommon.Reconcile( + d.DriverParams, + defaultConfig, + container.FilebeatImage, + f) +} diff --git a/pkg/controller/beat/metricbeat/config.go b/pkg/controller/beat/metricbeat/config.go new file mode 100644 index 0000000000..ec12450303 --- /dev/null +++ b/pkg/controller/beat/metricbeat/config.go @@ -0,0 +1,44 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package metricbeat + +import ( + "github.com/elastic/cloud-on-k8s/pkg/controller/common/settings" +) + +var ( + defaultConfig = settings.MustParseConfig([]byte( + `metricbeat: + autodiscover: + providers: + - hints: + default_config: {} + enabled: "true" + node: ${NODE_NAME} + type: kubernetes + modules: + - module: system + period: 10s + metricsets: + - cpu + - load + - memory + - network + - process + - process_summary + process: + include_top_n: + by_cpu: 5 + by_memory: 5 + processes: + - .* + - module: system + period: 1m + metricsets: + - fsstat +processors: +- add_cloud_metadata: {} +`)) +) diff --git a/pkg/controller/beat/metricbeat/metricbeat.go b/pkg/controller/beat/metricbeat/metricbeat.go new file mode 100644 index 0000000000..c98b65b91e --- /dev/null +++ b/pkg/controller/beat/metricbeat/metricbeat.go @@ -0,0 +1,70 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package metricbeat + +import ( + beatv1beta1 "github.com/elastic/cloud-on-k8s/pkg/apis/beat/v1beta1" + beatcommon "github.com/elastic/cloud-on-k8s/pkg/controller/beat/common" + "github.com/elastic/cloud-on-k8s/pkg/controller/common/container" + "github.com/elastic/cloud-on-k8s/pkg/controller/common/defaults" + "github.com/elastic/cloud-on-k8s/pkg/controller/common/reconciler" + "github.com/elastic/cloud-on-k8s/pkg/controller/common/volume" + corev1 "k8s.io/api/core/v1" +) + +const ( + Type beatcommon.Type = "metricbeat" + + DockerSockVolumeName = "dockersock" + DockerSockPath = "/var/run/docker.sock" + DockerSockMountPath = "/var/run/docker.sock" + + ProcVolumeName = "proc" + ProcPath = "/proc" + ProcMountPath = "/hostfs/proc" + + CGroupVolumeName = "cgroup" + CGroupPath = "/sys/fs/cgroup" + CGroupMountPath = "/hostfs/sys/fs/cgroup" +) + +type Driver struct { + beatcommon.DriverParams + beatcommon.Driver +} + +func NewDriver(params beatcommon.DriverParams) beatcommon.Driver { + spec := ¶ms.Beat.Spec + // use the default for metricbeat type if not provided + if spec.DaemonSet == nil && spec.Deployment == nil { + spec.DaemonSet = &beatv1beta1.DaemonSetSpec{} + } + + return &Driver{DriverParams: params} +} + +func (d *Driver) Reconcile() *reconciler.Results { + f := func(builder *defaults.PodTemplateBuilder) { + dockerSockVolume := volume.NewHostVolume(DockerSockVolumeName, DockerSockPath, DockerSockMountPath, false, corev1.HostPathUnset) + procVolume := volume.NewReadOnlyHostVolume(ProcVolumeName, ProcPath, ProcMountPath) + cgroupVolume := volume.NewReadOnlyHostVolume(CGroupVolumeName, CGroupPath, CGroupMountPath) + + for _, volume := range []volume.VolumeLike{ + dockerSockVolume, + procVolume, + cgroupVolume, + } { + builder.WithVolumes(volume.Volume()).WithVolumeMounts(volume.VolumeMount()) + } + + builder.WithArgs("-e", "-c", beatcommon.ConfigMountPath, "-system.hostfs=/hostfs") + } + + return beatcommon.Reconcile( + d.DriverParams, + defaultConfig, + container.MetricbeatImage, + f) +} diff --git a/pkg/controller/beat/otherbeat/otherbeat.go b/pkg/controller/beat/otherbeat/otherbeat.go new file mode 100644 index 0000000000..74a460d80e --- /dev/null +++ b/pkg/controller/beat/otherbeat/otherbeat.go @@ -0,0 +1,32 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package otherbeat + +import ( + beatv1beta1 "github.com/elastic/cloud-on-k8s/pkg/apis/beat/v1beta1" + beatcommon "github.com/elastic/cloud-on-k8s/pkg/controller/beat/common" + "github.com/elastic/cloud-on-k8s/pkg/controller/common/reconciler" + "github.com/elastic/cloud-on-k8s/pkg/utils/pointer" +) + +type Driver struct { + beatcommon.DriverParams + beatcommon.Driver +} + +func NewDriver(params beatcommon.DriverParams) beatcommon.Driver { + spec := ¶ms.Beat.Spec + // use the default for otherbeat type if not provided + if spec.DaemonSet == nil && spec.Deployment == nil { + spec.Deployment = &beatv1beta1.DeploymentSpec{ + Replicas: pointer.Int32(1), + } + } + return &Driver{DriverParams: params} +} + +func (d *Driver) Reconcile() *reconciler.Results { + return beatcommon.Reconcile(d.DriverParams, nil, "", nil) +} diff --git a/pkg/controller/common/association/association.go b/pkg/controller/common/association/association.go new file mode 100644 index 0000000000..0d9836b161 --- /dev/null +++ b/pkg/controller/common/association/association.go @@ -0,0 +1,72 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package association + +import ( + "hash" + + "github.com/pkg/errors" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/types" + + commonv1 "github.com/elastic/cloud-on-k8s/pkg/apis/common/v1" + "github.com/elastic/cloud-on-k8s/pkg/controller/common/certificates" + "github.com/elastic/cloud-on-k8s/pkg/utils/k8s" +) + +// WriteAssocToConfigHash dereferences auth secret (if any) to include it in the configHash. +func WriteAssocToConfigHash(client k8s.Client, assoc commonv1.Association, configHash hash.Hash) error { + if err := writeAuthSecretToConfigHash(client, assoc, configHash); err != nil { + return err + } + + return writeCASecretToConfigHash(client, assoc, configHash) +} + +func writeAuthSecretToConfigHash(client k8s.Client, assoc commonv1.Association, configHash hash.Hash) error { + assocConf := assoc.AssociationConf() + if !assocConf.AuthIsConfigured() { + return nil + } + + authSecretNsName := types.NamespacedName{ + Name: assocConf.GetAuthSecretName(), + Namespace: assoc.GetNamespace()} + var authSecret corev1.Secret + if err := client.Get(authSecretNsName, &authSecret); err != nil { + return err + } + authSecretData, ok := authSecret.Data[assocConf.GetAuthSecretKey()] + if !ok { + return errors.Errorf("auth secret key %s doesn't exist", assocConf.GetAuthSecretKey()) + } + + _, _ = configHash.Write(authSecretData) + + return nil +} + +func writeCASecretToConfigHash(client k8s.Client, assoc commonv1.Association, configHash hash.Hash) error { + assocConf := assoc.AssociationConf() + if !assocConf.CAIsConfigured() { + return nil + } + + publicCASecretNsName := types.NamespacedName{ + Namespace: assoc.GetNamespace(), + Name: assocConf.GetCASecretName()} + var publicCASecret corev1.Secret + if err := client.Get(publicCASecretNsName, &publicCASecret); err != nil { + return err + } + certPem, ok := publicCASecret.Data[certificates.CertFileName] + if !ok { + return errors.Errorf("public CA secret key %s doesn't exist", certificates.CertFileName) + } + + _, _ = configHash.Write(certPem) + + return nil +} diff --git a/pkg/controller/common/association/association_test.go b/pkg/controller/common/association/association_test.go new file mode 100644 index 0000000000..7a3b4c336a --- /dev/null +++ b/pkg/controller/common/association/association_test.go @@ -0,0 +1,174 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package association + +import ( + "crypto/sha256" + "testing" + + "github.com/elastic/cloud-on-k8s/pkg/controller/common/certificates" + "github.com/stretchr/testify/require" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + beatv1beta1 "github.com/elastic/cloud-on-k8s/pkg/apis/beat/v1beta1" + commonv1 "github.com/elastic/cloud-on-k8s/pkg/apis/common/v1" + "github.com/elastic/cloud-on-k8s/pkg/utils/k8s" +) + +func Test_writeAuthSecretToConfigHash(t *testing.T) { + for _, tt := range []struct { + name string + client k8s.Client + assoc func() commonv1.Association + wantHashed string + wantErr bool + }{ + { + name: "no association", + assoc: func() commonv1.Association { return &beatv1beta1.Beat{} }, + }, + { + name: "association secret missing", + client: k8s.WrappedFakeClient(), + assoc: func() commonv1.Association { + withAssoc := &beatv1beta1.Beat{ObjectMeta: metav1.ObjectMeta{Namespace: "test-ns"}} + withAssoc.SetAssociationConf(&commonv1.AssociationConf{ + AuthSecretName: "secret-name", + AuthSecretKey: "secret-key", + }) + return withAssoc + }, + wantHashed: "", + wantErr: true, + }, + { + name: "association secret data missing", + client: k8s.WrappedFakeClient(&corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "secret-name", + Namespace: "test-ns", + }, + }), + assoc: func() commonv1.Association { + withAssoc := &beatv1beta1.Beat{ObjectMeta: metav1.ObjectMeta{Namespace: "test-ns"}} + withAssoc.SetAssociationConf(&commonv1.AssociationConf{ + AuthSecretName: "secret-name", + AuthSecretKey: "non-existing-key", + }) + return withAssoc + }, + wantHashed: "", + wantErr: true, + }, + { + name: "association secret data present", + client: k8s.WrappedFakeClient(&corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "secret-name", + Namespace: "test-ns", + }, + Data: map[string][]byte{ + "secret-key": []byte("123"), + }, + }), + assoc: func() commonv1.Association { + withAssoc := &beatv1beta1.Beat{ObjectMeta: metav1.ObjectMeta{Namespace: "test-ns"}} + withAssoc.SetAssociationConf(&commonv1.AssociationConf{ + AuthSecretName: "secret-name", + AuthSecretKey: "secret-key", + }) + return withAssoc + }, + wantHashed: "123", + }, + } { + t.Run(tt.name, func(t *testing.T) { + configHashPassed := sha256.New224() + gotErr := writeAuthSecretToConfigHash(tt.client, tt.assoc(), configHashPassed) + require.Equal(t, tt.wantErr, gotErr != nil) + + configHash := sha256.New224() + _, _ = configHash.Write([]byte(tt.wantHashed)) + require.Equal(t, configHash.Sum(nil), configHashPassed.Sum(nil)) + }) + } +} + +func Test_writeCASecretToConfigHash(t *testing.T) { + for _, tt := range []struct { + name string + client k8s.Client + assoc func() commonv1.Association + wantHashed string + wantErr bool + }{ + { + name: "no association", + assoc: func() commonv1.Association { return &beatv1beta1.Beat{} }, + }, + { + name: "association ca secret missing", + client: k8s.WrappedFakeClient(), + assoc: func() commonv1.Association { + withAssoc := &beatv1beta1.Beat{ObjectMeta: metav1.ObjectMeta{Namespace: "test-ns"}} + withAssoc.SetAssociationConf(&commonv1.AssociationConf{ + CASecretName: "ca-secret-name", + }) + return withAssoc + }, + wantHashed: "", + wantErr: true, + }, + { + name: "association ca secret data missing", + client: k8s.WrappedFakeClient(&corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "secret-name", + Namespace: "test-ns", + }, + }), + assoc: func() commonv1.Association { + withAssoc := &beatv1beta1.Beat{ObjectMeta: metav1.ObjectMeta{Namespace: "test-ns"}} + withAssoc.SetAssociationConf(&commonv1.AssociationConf{ + CASecretName: "ca-secret-name", + }) + return withAssoc + }, + wantHashed: "", + wantErr: true, + }, + { + name: "association ca secret data present", + client: k8s.WrappedFakeClient(&corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "ca-secret-name", + Namespace: "test-ns", + }, + Data: map[string][]byte{ + certificates.CertFileName: []byte("456"), + }, + }), + assoc: func() commonv1.Association { + withAssoc := &beatv1beta1.Beat{ObjectMeta: metav1.ObjectMeta{Namespace: "test-ns"}} + withAssoc.SetAssociationConf(&commonv1.AssociationConf{ + CASecretName: "ca-secret-name", + }) + return withAssoc + }, + wantHashed: "456", + }, + } { + t.Run(tt.name, func(t *testing.T) { + configHashPassed := sha256.New224() + gotErr := writeCASecretToConfigHash(tt.client, tt.assoc(), configHashPassed) + require.Equal(t, tt.wantErr, gotErr != nil) + + configHash := sha256.New224() + _, _ = configHash.Write([]byte(tt.wantHashed)) + require.Equal(t, configHash.Sum(nil), configHashPassed.Sum(nil)) + }) + } +} diff --git a/pkg/controller/common/container/container.go b/pkg/controller/common/container/container.go index f97851e87a..2065e15a0c 100644 --- a/pkg/controller/common/container/container.go +++ b/pkg/controller/common/container/container.go @@ -24,6 +24,8 @@ const ( ElasticsearchImage Image = "elasticsearch/elasticsearch" KibanaImage Image = "kibana/kibana" EnterpriseSearchImage Image = "enterprise-search/enterprise-search" + FilebeatImage Image = "beats/filebeat" + MetricbeatImage Image = "beats/metricbeat" ) // ImageRepository returns the full container image name by concatenating the current container registry and the image path with the given version. diff --git a/pkg/controller/common/daemonset/reconcile.go b/pkg/controller/common/daemonset/reconcile.go new file mode 100644 index 0000000000..189fe5ab5a --- /dev/null +++ b/pkg/controller/common/daemonset/reconcile.go @@ -0,0 +1,72 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package daemonset + +import ( + appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/elastic/cloud-on-k8s/pkg/controller/common/hash" + "github.com/elastic/cloud-on-k8s/pkg/controller/common/reconciler" + "github.com/elastic/cloud-on-k8s/pkg/utils/k8s" +) + +type Params struct { + PodTemplate corev1.PodTemplateSpec + Name string + Owner metav1.Object + Labels map[string]string + Selectors map[string]string +} + +func New(params Params) appsv1.DaemonSet { + return appsv1.DaemonSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: params.Name, + Namespace: params.Owner.GetNamespace(), + Labels: params.Labels, + }, + Spec: appsv1.DaemonSetSpec{ + Selector: &metav1.LabelSelector{ + MatchLabels: params.Selectors, + }, + Template: params.PodTemplate, + }, + } +} + +// Reconcile creates or updates the given daemon set for the specified owner. +func Reconcile( + k8sClient k8s.Client, + expected appsv1.DaemonSet, + owner metav1.Object, +) (appsv1.DaemonSet, error) { + // label the daemon set with a hash of itself + expected = WithTemplateHash(expected) + + reconciled := &appsv1.DaemonSet{} + err := reconciler.ReconcileResource(reconciler.Params{ + Client: k8sClient, + Owner: owner, + Expected: &expected, + Reconciled: reconciled, + NeedsUpdate: func() bool { + // compare hash of the DaemonSet at the time it was built + return hash.GetTemplateHashLabel(reconciled.Labels) != hash.GetTemplateHashLabel(expected.Labels) + }, + UpdateReconciled: func() { + expected.DeepCopyInto(reconciled) + }, + }) + return *reconciled, err +} + +// WithTemplateHash returns a new DaemonSet with a hash of its template to ease comparisons. +func WithTemplateHash(d appsv1.DaemonSet) appsv1.DaemonSet { + dCopy := *d.DeepCopy() + dCopy.Labels = hash.SetTemplateHashLabel(dCopy.Labels, dCopy) + return dCopy +} diff --git a/pkg/controller/common/defaults/pod_template.go b/pkg/controller/common/defaults/pod_template.go index e1fb25c308..d5eca11693 100644 --- a/pkg/controller/common/defaults/pod_template.go +++ b/pkg/controller/common/defaults/pod_template.go @@ -337,3 +337,44 @@ func (b *PodTemplateBuilder) WithPreStopHook(handler corev1.Handler) *PodTemplat return b } + +func (b *PodTemplateBuilder) WithArgs(args ...string) *PodTemplateBuilder { + if b.Container.Args == nil { + b.Container.Args = args + } + return b +} + +func (b *PodTemplateBuilder) WithServiceAccount(serviceAccount string) *PodTemplateBuilder { + if b.PodTemplate.Spec.ServiceAccountName == "" { + b.PodTemplate.Spec.ServiceAccountName = serviceAccount + } + return b +} + +func (b *PodTemplateBuilder) WithHostNetwork() *PodTemplateBuilder { + b.PodTemplate.Spec.HostNetwork = true + return b +} + +func (b *PodTemplateBuilder) WithDNSPolicy(dnsPolicy corev1.DNSPolicy) *PodTemplateBuilder { + if b.PodTemplate.Spec.DNSPolicy == "" { + b.PodTemplate.Spec.DNSPolicy = dnsPolicy + } + return b +} + +func (b *PodTemplateBuilder) WithPodSecurityContext(securityContext corev1.PodSecurityContext) *PodTemplateBuilder { + if b.PodTemplate.Spec.SecurityContext == nil { + b.PodTemplate.Spec.SecurityContext = &securityContext + } + return b +} + +func (b *PodTemplateBuilder) WithAutomountServiceAccountToken() *PodTemplateBuilder { + if b.PodTemplate.Spec.AutomountServiceAccountToken == nil { + t := true + b.PodTemplate.Spec.AutomountServiceAccountToken = &t + } + return b +} diff --git a/pkg/controller/common/operator/flags.go b/pkg/controller/common/operator/flags.go index 6cb2358b66..dd0f9ecdbc 100644 --- a/pkg/controller/common/operator/flags.go +++ b/pkg/controller/common/operator/flags.go @@ -5,21 +5,22 @@ package operator const ( - AutoPortForwardFlag = "auto-port-forward" - CACertRotateBeforeFlag = "ca-cert-rotate-before" - CACertValidityFlag = "ca-cert-validity" - CertRotateBeforeFlag = "cert-rotate-before" - CertValidityFlag = "cert-validity" - ContainerRegistryFlag = "container-registry" - DebugHTTPListenFlag = "debug-http-listen" - EnableTracingFlag = "enable-tracing" - EnableWebhookFlag = "enable-webhook" - EnforceRBACOnRefsFlag = "enforce-rbac-on-refs" - ManageWebhookCertsFlag = "manage-webhook-certs" - MaxConcurrentReconcilesFlag = "max-concurrent-reconciles" - MetricsPortFlag = "metrics-port" - NamespacesFlag = "namespaces" - OperatorNamespaceFlag = "operator-namespace" - WebhookCertDirFlag = "webhook-cert-dir" - WebhookSecretFlag = "webhook-secret" + AutoPortForwardFlag = "auto-port-forward" + CACertRotateBeforeFlag = "ca-cert-rotate-before" + CACertValidityFlag = "ca-cert-validity" + CertRotateBeforeFlag = "cert-rotate-before" + CertValidityFlag = "cert-validity" + ContainerRegistryFlag = "container-registry" + DebugHTTPListenFlag = "debug-http-listen" + ManageBeatAutodiscoverRBACFlag = "manage-beat-autodiscover-rbac" + EnableTracingFlag = "enable-tracing" + EnableWebhookFlag = "enable-webhook" + EnforceRBACOnRefsFlag = "enforce-rbac-on-refs" + ManageWebhookCertsFlag = "manage-webhook-certs" + MaxConcurrentReconcilesFlag = "max-concurrent-reconciles" + MetricsPortFlag = "metrics-port" + NamespacesFlag = "namespaces" + OperatorNamespaceFlag = "operator-namespace" + WebhookCertDirFlag = "webhook-cert-dir" + WebhookSecretFlag = "webhook-secret" ) diff --git a/pkg/controller/common/scheme/scheme.go b/pkg/controller/common/scheme/scheme.go index cb19ec711a..b8f317bb2a 100644 --- a/pkg/controller/common/scheme/scheme.go +++ b/pkg/controller/common/scheme/scheme.go @@ -9,6 +9,7 @@ import ( apmv1 "github.com/elastic/cloud-on-k8s/pkg/apis/apm/v1" apmv1beta1 "github.com/elastic/cloud-on-k8s/pkg/apis/apm/v1beta1" + beatv1beta1 "github.com/elastic/cloud-on-k8s/pkg/apis/beat/v1beta1" commonv1 "github.com/elastic/cloud-on-k8s/pkg/apis/common/v1" commonv1beta1 "github.com/elastic/cloud-on-k8s/pkg/apis/common/v1beta1" esv1 "github.com/elastic/cloud-on-k8s/pkg/apis/elasticsearch/v1" @@ -52,6 +53,10 @@ func SetupScheme() { if err != nil { panic(err) } + err = beatv1beta1.AddToScheme(clientgoscheme.Scheme) + if err != nil { + panic(err) + } }) } @@ -85,5 +90,9 @@ func SetupV1beta1Scheme() { if err != nil { panic(err) } + err = beatv1beta1.AddToScheme(clientgoscheme.Scheme) + if err != nil { + panic(err) + } }) } diff --git a/pkg/controller/common/settings/canonical_config.go b/pkg/controller/common/settings/canonical_config.go index 390c8a4ffd..ba71519781 100644 --- a/pkg/controller/common/settings/canonical_config.go +++ b/pkg/controller/common/settings/canonical_config.go @@ -89,6 +89,16 @@ func ParseConfig(yml []byte) (*CanonicalConfig, error) { return fromConfig(config), nil } +// MustParseConfig parses the given configuration content into a CanonicalConfig. +// Expects content to be in YAML format. Panics on error. +func MustParseConfig(yml []byte) *CanonicalConfig { + config, err := uyaml.NewConfig(yml, Options...) + if err != nil { + panic(err) + } + return fromConfig(config) +} + // SetStrings sets key to string vals in c. An error is returned if key is invalid. func (c *CanonicalConfig) SetStrings(key string, vals ...string) error { if c == nil { diff --git a/pkg/controller/common/version/version.go b/pkg/controller/common/version/version.go index 688370dc94..7d2bf143f9 100644 --- a/pkg/controller/common/version/version.go +++ b/pkg/controller/common/version/version.go @@ -18,6 +18,7 @@ var ( SupportedAPMServerVersions = MinMaxVersion{Min: From(6, 2, 0), Max: From(8, 99, 99)} SupportedEnterpriseSearchVersions = MinMaxVersion{Min: From(7, 7, 0), Max: From(8, 99, 99)} SupportedKibanaVersions = MinMaxVersion{Min: From(6, 8, 0), Max: From(8, 99, 99)} + SupportedBeatVersions = MinMaxVersion{Min: From(7, 0, 0), Max: From(8, 99, 99)} ) // MinMaxVersion holds the minimum and maximum supported versions. diff --git a/pkg/controller/common/volume/host.go b/pkg/controller/common/volume/host.go new file mode 100644 index 0000000000..1e580248a6 --- /dev/null +++ b/pkg/controller/common/volume/host.go @@ -0,0 +1,63 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package volume + +import ( + corev1 "k8s.io/api/core/v1" +) + +// NewReadOnlyHostVolume creates a new HostVolume struct. +func NewReadOnlyHostVolume(name, hostPath, mountPath string) HostVolume { + return NewHostVolume(name, hostPath, mountPath, false, corev1.HostPathUnset) +} + +// NewHostVolume creates a new HostVolume struct with default mode +func NewHostVolume(name, hostPath, mountPath string, readOnly bool, hostPathType corev1.HostPathType) HostVolume { + return HostVolume{ + name: name, + hostPath: hostPath, + mountPath: mountPath, + readOnly: readOnly, + hostPathType: &hostPathType, + } +} + +// HostVolume defines a volume to expose a host path +type HostVolume struct { + name string + hostPath string + mountPath string + readOnly bool + hostPathType *corev1.HostPathType +} + +// VolumeMount returns the k8s volume mount. +func (hv HostVolume) VolumeMount() corev1.VolumeMount { + return corev1.VolumeMount{ + Name: hv.name, + MountPath: hv.mountPath, + ReadOnly: hv.readOnly, + } +} + +// Volume returns the k8s volume. +func (hv HostVolume) Volume() corev1.Volume { + return corev1.Volume{ + Name: hv.name, + VolumeSource: corev1.VolumeSource{ + HostPath: &corev1.HostPathVolumeSource{ + Path: hv.hostPath, + Type: hv.hostPathType, + }, + }, + } +} + +// Name returns the name of the volume +func (hv HostVolume) Name() string { + return hv.name +} + +var _ VolumeLike = HostVolume{} diff --git a/pkg/controller/common/volume/secret.go b/pkg/controller/common/volume/secret.go index 782354d1c3..14ab6dca9c 100644 --- a/pkg/controller/common/volume/secret.go +++ b/pkg/controller/common/volume/secret.go @@ -6,18 +6,22 @@ package volume import ( corev1 "k8s.io/api/core/v1" + + "github.com/elastic/cloud-on-k8s/pkg/utils/pointer" ) // SecretVolume captures a subset of data of the k8s secret volume/mount type. type SecretVolume struct { - name string - mountPath string - secretName string - items []corev1.KeyToPath + name string + mountPath string + secretName string + items []corev1.KeyToPath + subPath string + defaultMode *int32 } // NewSecretVolumeWithMountPath creates a new SecretVolume -func NewSecretVolumeWithMountPath(secretName string, name string, mountPath string) SecretVolume { +func NewSecretVolumeWithMountPath(secretName, name, mountPath string) SecretVolume { return SecretVolume{ name: name, mountPath: mountPath, @@ -25,8 +29,19 @@ func NewSecretVolumeWithMountPath(secretName string, name string, mountPath stri } } +// NewSecretVolume creates a new SecretVolume +func NewSecretVolume(secretName, name, mountPath, subPath string, defaultMode int32) SecretVolume { + return SecretVolume{ + name: name, + mountPath: mountPath, + secretName: secretName, + subPath: subPath, + defaultMode: pointer.Int32(defaultMode), + } +} + // NewSelectiveSecretVolumeWithMountPath creates a new SecretVolume that projects only the specified secrets into the file system. -func NewSelectiveSecretVolumeWithMountPath(secretName string, name string, mountPath string, projectedSecrets []string) SecretVolume { +func NewSelectiveSecretVolumeWithMountPath(secretName, name, mountPath string, projectedSecrets []string) SecretVolume { keyToPaths := make([]corev1.KeyToPath, len(projectedSecrets)) for i, s := range projectedSecrets { keyToPaths[i] = corev1.KeyToPath{ @@ -48,6 +63,7 @@ func (sv SecretVolume) VolumeMount() corev1.VolumeMount { Name: sv.name, MountPath: sv.mountPath, ReadOnly: true, + SubPath: sv.subPath, } } @@ -57,9 +73,10 @@ func (sv SecretVolume) Volume() corev1.Volume { Name: sv.name, VolumeSource: corev1.VolumeSource{ Secret: &corev1.SecretVolumeSource{ - SecretName: sv.secretName, - Items: sv.items, - Optional: &defaultOptional, + SecretName: sv.secretName, + Items: sv.items, + Optional: &defaultOptional, + DefaultMode: sv.defaultMode, }, }, } diff --git a/pkg/controller/kibana/driver.go b/pkg/controller/kibana/driver.go index df5b4a953b..6f3faae13f 100644 --- a/pkg/controller/kibana/driver.go +++ b/pkg/controller/kibana/driver.go @@ -21,6 +21,7 @@ import ( kbv1 "github.com/elastic/cloud-on-k8s/pkg/apis/kibana/v1" "github.com/elastic/cloud-on-k8s/pkg/controller/association" "github.com/elastic/cloud-on-k8s/pkg/controller/common" + commonassociation "github.com/elastic/cloud-on-k8s/pkg/controller/common/association" "github.com/elastic/cloud-on-k8s/pkg/controller/common/certificates" "github.com/elastic/cloud-on-k8s/pkg/controller/common/defaults" "github.com/elastic/cloud-on-k8s/pkg/controller/common/deployment" @@ -209,28 +210,15 @@ func (d *driver) deploymentParams(kb *kbv1.Kibana) (deployment.Params, error) { if keystoreResources != nil { _, _ = configChecksum.Write([]byte(keystoreResources.Version)) } - // we need to deref the secret here (if any) to include it in the checksum otherwise Kibana will not be rolled on contents changes - if kb.AssociationConf().AuthIsConfigured() { - esAuthKey := types.NamespacedName{Name: kb.AssociationConf().GetAuthSecretName(), Namespace: kb.Namespace} - esAuthSecret := corev1.Secret{} - if err := d.client.Get(esAuthKey, &esAuthSecret); err != nil { - return deployment.Params{}, err - } - _, _ = configChecksum.Write(esAuthSecret.Data[kb.AssociationConf().GetAuthSecretKey()]) + + // we need to deref the secret here to include it in the checksum otherwise Kibana will not be rolled on contents changes + if err := commonassociation.WriteAssocToConfigHash(d.client, kb, configChecksum); err != nil { + return deployment.Params{}, err } volumes := []commonvolume.SecretVolume{SecretVolume(*kb)} if kb.AssociationConf().CAIsConfigured() { - esPublicCAKey := types.NamespacedName{Namespace: kb.Namespace, Name: kb.AssociationConf().GetCASecretName()} - var esPublicCASecret corev1.Secret - if err := d.client.Get(esPublicCAKey, &esPublicCASecret); err != nil { - return deployment.Params{}, err - } - if certPem, ok := esPublicCASecret.Data[certificates.CertFileName]; ok { - _, _ = configChecksum.Write(certPem) - } - esCertsVolume := esCaCertSecretVolume(*kb) volumes = append(volumes, esCertsVolume) for i := range kibanaPodSpec.Spec.InitContainers { diff --git a/pkg/utils/pointer/numeric.go b/pkg/utils/pointer/numeric.go index 0e826db08b..f6558c0f37 100644 --- a/pkg/utils/pointer/numeric.go +++ b/pkg/utils/pointer/numeric.go @@ -6,3 +6,14 @@ package pointer // Int32 returns a pointer to an Int32 func Int32(v int32) *int32 { return &v } + +// Int32OrDefault returns value pointed to by v, or def if it's nil +func Int32OrDefault(v *int32, def int32) int32 { + if v == nil { + return def + } + return *v +} + +// Int64 returns a pointer to an Int64 +func Int64(v int64) *int64 { return &v } diff --git a/test/e2e/beat/config_test.go b/test/e2e/beat/config_test.go new file mode 100644 index 0000000000..c740bc4be2 --- /dev/null +++ b/test/e2e/beat/config_test.go @@ -0,0 +1,97 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package beat + +import ( + "fmt" + "testing" + + v1 "github.com/elastic/cloud-on-k8s/pkg/apis/elasticsearch/v1" + "github.com/stretchr/testify/require" + + commonv1 "github.com/elastic/cloud-on-k8s/pkg/apis/common/v1" + "github.com/elastic/cloud-on-k8s/pkg/controller/beat/filebeat" + "github.com/elastic/cloud-on-k8s/pkg/controller/beat/metricbeat" + "github.com/elastic/cloud-on-k8s/pkg/controller/common/settings" + "github.com/elastic/cloud-on-k8s/test/e2e/test" + "github.com/elastic/cloud-on-k8s/test/e2e/test/beat" + "github.com/elastic/cloud-on-k8s/test/e2e/test/elasticsearch" +) + +func TestFilebeatDefaultConfig(t *testing.T) { + name := "test-fb-default-cfg" + + esBuilder := elasticsearch.NewBuilder(name). + WithESMasterDataNodes(3, elasticsearch.DefaultResources) + + testPodBuilder := beat.NewPodBuilder(name) + + fbBuilder := beat.NewBuilder(name, filebeat.Type). + WithElasticsearchRef(esBuilder.Ref()). + WithESValidations( + beat.HasEventFromBeat(filebeat.Type), + beat.HasEventFromPod(testPodBuilder.Pod.Name), + beat.HasMessageContaining(testPodBuilder.Logged)) + + test.Sequence(nil, test.EmptySteps, esBuilder, fbBuilder, testPodBuilder).RunSequential(t) +} + +func TestMetricbeatDefaultConfig(t *testing.T) { + name := "test-mb-default-cfg" + + esBuilder := elasticsearch.NewBuilder(name). + WithESMasterDataNodes(3, elasticsearch.DefaultResources) + + testPodBuilder := beat.NewPodBuilder(name) + + mbBuilder := beat.NewBuilder(name, metricbeat.Type). + WithElasticsearchRef(esBuilder.Ref()). + WithESValidations( + beat.HasEventFromBeat(metricbeat.Type), + beat.HasEvent("event.dataset:system.cpu"), + beat.HasEvent("event.dataset:system.load"), + beat.HasEvent("event.dataset:system.memory"), + beat.HasEvent("event.dataset:system.network"), + beat.HasEvent("event.dataset:system.process"), + beat.HasEvent("event.dataset:system.process.summary"), + beat.HasEvent("event.dataset:system.fsstat"), + ) + + test.Sequence(nil, test.EmptySteps, esBuilder, mbBuilder, testPodBuilder).RunSequential(t) +} + +func TestHeartbeatConfig(t *testing.T) { + name := "test-hb-cfg" + + esBuilder := elasticsearch.NewBuilder(name). + WithESMasterDataNodes(3, elasticsearch.DefaultResources) + + hbBuilder := beat.NewBuilder(name, "heartbeat"). + WithElasticsearchRef(esBuilder.Ref()). + WithImage("docker.elastic.co/beats/heartbeat:7.7.0"). + WithESValidations( + beat.HasEventFromBeat("heartbeat"), + beat.HasEvent("monitor.status:up")) + + yaml := fmt.Sprintf(` +heartbeat.monitors: +- type: tcp + schedule: '@every 5s' + hosts: ["%s.%s.svc:9200"] +`, v1.HTTPService(esBuilder.Elasticsearch.Name), esBuilder.Elasticsearch.Namespace) + hbBuilder = applyConfigYaml(t, hbBuilder, yaml) + + test.Sequence(nil, test.EmptySteps, esBuilder, hbBuilder).RunSequential(t) +} + +// --- helpers + +func applyConfigYaml(t *testing.T, b beat.Builder, yaml string) beat.Builder { + config := &commonv1.Config{} + err := settings.MustParseConfig([]byte(yaml)).Unpack(&config.Data) + require.NoError(t, err) + + return b.WithConfig(config) +} diff --git a/test/e2e/run.sh b/test/e2e/run.sh index ea6c8768a6..c5f106e332 100755 --- a/test/e2e/run.sh +++ b/test/e2e/run.sh @@ -20,5 +20,5 @@ done # sleep 1s to allow filebeat to read all logs with 1s max_backoff # minimizes race condition in filebeat between reading log file and -# stopping reading due to pod termination autodiscovery event +# stopping reading due to pod termination autodiscover event sleep 1 diff --git a/test/e2e/samples_test.go b/test/e2e/samples_test.go index 3a9b5dcdc4..8fd500573a 100644 --- a/test/e2e/samples_test.go +++ b/test/e2e/samples_test.go @@ -12,9 +12,11 @@ import ( "testing" commonv1 "github.com/elastic/cloud-on-k8s/pkg/apis/common/v1" + beatcommon "github.com/elastic/cloud-on-k8s/pkg/controller/beat/common" "github.com/elastic/cloud-on-k8s/test/e2e/cmd/run" "github.com/elastic/cloud-on-k8s/test/e2e/test" "github.com/elastic/cloud-on-k8s/test/e2e/test/apmserver" + "github.com/elastic/cloud-on-k8s/test/e2e/test/beat" "github.com/elastic/cloud-on-k8s/test/e2e/test/elasticsearch" "github.com/elastic/cloud-on-k8s/test/e2e/test/helper" "github.com/elastic/cloud-on-k8s/test/e2e/test/kibana" @@ -82,6 +84,14 @@ func createBuilders(t *testing.T, decoder *helper.YAMLDecoder, sampleFile, testN WithRestrictedSecurityContext(). WithLabel(run.TestNameLabel, fullTestName). WithPodLabel(run.TestNameLabel, fullTestName) + case beat.Builder: + return b.WithNamespace(namespace). + WithSuffix(suffix). + WithElasticsearchRef(tweakServiceRef(b.Beat.Spec.ElasticsearchRef, suffix)). + WithRestrictedSecurityContext(). + WithLabel(run.TestNameLabel, testName). + WithPodLabel(run.TestNameLabel, testName). + WithESValidations(beat.HasEventFromBeat(beatcommon.Type(b.Beat.Spec.Type))) default: return b } diff --git a/test/e2e/smoke_test.go b/test/e2e/smoke_test.go index 7798a1d025..715256841c 100644 --- a/test/e2e/smoke_test.go +++ b/test/e2e/smoke_test.go @@ -9,31 +9,35 @@ import ( "os" "testing" + "github.com/elastic/cloud-on-k8s/pkg/controller/beat/filebeat" "github.com/elastic/cloud-on-k8s/test/e2e/cmd/run" "github.com/elastic/cloud-on-k8s/test/e2e/test" "github.com/elastic/cloud-on-k8s/test/e2e/test/apmserver" + "github.com/elastic/cloud-on-k8s/test/e2e/test/beat" "github.com/elastic/cloud-on-k8s/test/e2e/test/elasticsearch" "github.com/elastic/cloud-on-k8s/test/e2e/test/kibana" "k8s.io/apimachinery/pkg/util/rand" "k8s.io/apimachinery/pkg/util/yaml" ) -const sampleApmEsKibanaFile = "../../config/samples/apm/apm_es_kibana.yaml" +const sampleFile = "../../config/samples/beat/filebeat_es_kibana_apm.yaml" // TestSmoke runs a test suite using the ApmServer + Kibana + ES sample. func TestSmoke(t *testing.T) { var esBuilder elasticsearch.Builder var kbBuilder kibana.Builder var apmBuilder apmserver.Builder + var beatBuilder beat.Builder - yamlFile, err := os.Open(sampleApmEsKibanaFile) + yamlFile, err := os.Open(sampleFile) test.ExitOnErr(err) decoder := yaml.NewYAMLToJSONDecoder(bufio.NewReader(yamlFile)) // the decoding order depends on the yaml test.ExitOnErr(decoder.Decode(&esBuilder.Elasticsearch)) - test.ExitOnErr(decoder.Decode(&apmBuilder.ApmServer)) test.ExitOnErr(decoder.Decode(&kbBuilder.Kibana)) + test.ExitOnErr(decoder.Decode(&apmBuilder.ApmServer)) + test.ExitOnErr(decoder.Decode(&beatBuilder.Beat)) ns := test.Ctx().ManagedNamespace(0) randSuffix := rand.String(4) @@ -63,7 +67,15 @@ func TestSmoke(t *testing.T) { WithRestrictedSecurityContext(). WithLabel(run.TestNameLabel, testName). WithPodLabel(run.TestNameLabel, testName) + beatBuilder = beatBuilder. + WithSuffix(randSuffix). + WithNamespace(ns). + WithElasticsearchRef(esBuilder.Ref()). + WithRestrictedSecurityContext(). + WithLabel(run.TestNameLabel, testName). + WithPodLabel(run.TestNameLabel, testName). + WithESValidations(beat.HasEventFromBeat(filebeat.Type)) - test.Sequence(nil, test.EmptySteps, esBuilder, kbBuilder, apmBuilder). + test.Sequence(nil, test.EmptySteps, esBuilder, kbBuilder, apmBuilder, beatBuilder). RunSequential(t) } diff --git a/test/e2e/test/beat/builder.go b/test/e2e/test/beat/builder.go new file mode 100644 index 0000000000..38a8f53799 --- /dev/null +++ b/test/e2e/test/beat/builder.go @@ -0,0 +1,149 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package beat + +import ( + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/rand" + + beatv1beta1 "github.com/elastic/cloud-on-k8s/pkg/apis/beat/v1beta1" + commonv1 "github.com/elastic/cloud-on-k8s/pkg/apis/common/v1" + beatcommon "github.com/elastic/cloud-on-k8s/pkg/controller/beat/common" + "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/client" + "github.com/elastic/cloud-on-k8s/test/e2e/cmd/run" + "github.com/elastic/cloud-on-k8s/test/e2e/test" +) + +// Builder to create a Beat +type Builder struct { + Beat beatv1beta1.Beat + Validations []ValidationFunc +} + +func NewBuilderWithoutSuffix(name string, typ beatcommon.Type) Builder { + return newBuilder(name, typ, "") +} + +func NewBuilder(name string, typ beatcommon.Type) Builder { + return newBuilder(name, typ, rand.String(4)) +} + +func newBuilder(name string, typ beatcommon.Type, suffix string) Builder { + meta := metav1.ObjectMeta{ + Name: name, + Namespace: test.Ctx().ManagedNamespace(0), + Labels: map[string]string{run.TestNameLabel: name}, + } + + return Builder{ + Beat: beatv1beta1.Beat{ + ObjectMeta: meta, + Spec: beatv1beta1.BeatSpec{ + Type: string(typ), + Version: test.Ctx().ElasticStackVersion, + }, + }, + }. + WithSuffix(suffix). + WithLabel(run.TestNameLabel, name) +} + +type ValidationFunc func(client.Client) error + +func (b Builder) WithESValidations(validations ...ValidationFunc) Builder { + b.Validations = append(b.Validations, validations...) + + return b +} + +func (b Builder) WithElasticsearchRef(ref commonv1.ObjectSelector) Builder { + b.Beat.Spec.ElasticsearchRef = ref + return b +} + +func (b Builder) WithConfig(config *commonv1.Config) Builder { + b.Beat.Spec.Config = config + return b +} + +func (b Builder) WithImage(image string) Builder { + b.Beat.Spec.Image = image + return b +} + +func (b Builder) WithSuffix(suffix string) Builder { + if suffix != "" { + b.Beat.ObjectMeta.Name = b.Beat.ObjectMeta.Name + "-" + suffix + } + return b +} + +func (b Builder) WithNamespace(namespace string) Builder { + b.Beat.ObjectMeta.Namespace = namespace + return b +} + +func (b Builder) WithRestrictedSecurityContext() Builder { + if b.Beat.Spec.DaemonSet != nil { + b.Beat.Spec.DaemonSet.PodTemplate.Spec.SecurityContext = test.DefaultSecurityContext() + } + if b.Beat.Spec.Deployment != nil { + b.Beat.Spec.Deployment.PodTemplate.Spec.SecurityContext = test.DefaultSecurityContext() + } + + return b +} + +func (b Builder) WithContainerSecurityContext(securityContext corev1.SecurityContext) Builder { + if b.Beat.Spec.DaemonSet != nil { + for i := range b.Beat.Spec.DaemonSet.PodTemplate.Spec.Containers { + b.Beat.Spec.DaemonSet.PodTemplate.Spec.Containers[i].SecurityContext = &securityContext + } + } + if b.Beat.Spec.Deployment != nil { + for i := range b.Beat.Spec.Deployment.PodTemplate.Spec.Containers { + b.Beat.Spec.Deployment.PodTemplate.Spec.Containers[i].SecurityContext = &securityContext + } + } + + return b +} + +func (b Builder) WithLabel(key, value string) Builder { + if b.Beat.Labels == nil { + b.Beat.Labels = make(map[string]string) + } + b.Beat.Labels[key] = value + + return b +} + +func (b Builder) WithPodLabel(key, value string) Builder { + var podSpecs []corev1.PodTemplateSpec + + if b.Beat.Spec.DaemonSet != nil { + podSpecs = append(podSpecs, b.Beat.Spec.DaemonSet.PodTemplate) + } + if b.Beat.Spec.Deployment != nil { + podSpecs = append(podSpecs, b.Beat.Spec.Deployment.PodTemplate) + } + + for _, podSpec := range podSpecs { + if podSpec.Labels == nil { + podSpec.Labels = make(map[string]string) + } + podSpec.Labels[key] = value + } + + return b +} + +func (b Builder) RuntimeObjects() []runtime.Object { + return []runtime.Object{&b.Beat} +} + +var _ test.Builder = Builder{} diff --git a/test/e2e/test/beat/checks.go b/test/e2e/test/beat/checks.go new file mode 100644 index 0000000000..9ec1ed0623 --- /dev/null +++ b/test/e2e/test/beat/checks.go @@ -0,0 +1,61 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package beat + +import ( + "context" + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + + beatcommon "github.com/elastic/cloud-on-k8s/pkg/controller/beat/common" + "github.com/elastic/cloud-on-k8s/pkg/controller/elasticsearch/client" +) + +func HasEventFromBeat(name beatcommon.Type) ValidationFunc { + return HasEvent(fmt.Sprintf("agent.type:%s", name)) +} + +func HasEventFromPod(name string) ValidationFunc { + return HasEvent(fmt.Sprintf("kubernetes.pod.name:%s", name)) +} + +func HasMessageContaining(message string) ValidationFunc { + return HasEvent(fmt.Sprintf("message:%s", message)) +} + +func HasEvent(query string) ValidationFunc { + return hasEvent(fmt.Sprintf("/*beat*/_search?q=%s", query)) +} + +func hasEvent(url string) ValidationFunc { + return func(esClient client.Client) error { + req, err := http.NewRequest(http.MethodGet, url, nil) + if err != nil { + return err + } + + res, err := esClient.Request(context.Background(), req) + if err != nil { + return err + } + defer res.Body.Close() + resultBytes, err := ioutil.ReadAll(res.Body) + if err != nil { + return err + } + var results client.SearchResults + err = json.Unmarshal(resultBytes, &results) + if err != nil { + return err + } + if len(results.Hits.Hits) == 0 { + return fmt.Errorf("hit count should be more than 0 for %s", url) + } + + return nil + } +} diff --git a/test/e2e/test/beat/pod_builder.go b/test/e2e/test/beat/pod_builder.go new file mode 100644 index 0000000000..9b7bc4b15d --- /dev/null +++ b/test/e2e/test/beat/pod_builder.go @@ -0,0 +1,265 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package beat + +import ( + "fmt" + "testing" + + "github.com/pkg/errors" + "github.com/stretchr/testify/require" + corev1 "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/util/rand" + + "github.com/elastic/cloud-on-k8s/pkg/utils/k8s" + "github.com/elastic/cloud-on-k8s/test/e2e/cmd/run" + "github.com/elastic/cloud-on-k8s/test/e2e/test" +) + +// Builder to create a Pod. It can be used as a source of logging/metric data for Beat (deployed separately) to collect. +type PodBuilder struct { + Pod corev1.Pod + Logged string +} + +func NewPodBuilder(name string) PodBuilder { + return newPodBuilder(name, rand.String(4)) +} + +func newPodBuilder(name, suffix string) PodBuilder { + meta := metav1.ObjectMeta{ + Name: name, + Namespace: test.Ctx().ManagedNamespace(0), + Labels: map[string]string{run.TestNameLabel: name}, + } + + // inject random string into the logs to allow validating whether they end up in ES easily + loggedString := fmt.Sprintf("_%s_", rand.String(6)) + + return PodBuilder{ + Pod: corev1.Pod{ + ObjectMeta: meta, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "ubuntu", + Image: "busybox", + Command: []string{ + "sh", + "-c", + fmt.Sprintf("while [ true ]; do echo \"$(date) - %s\"; sleep 5; done", loggedString), + }, + }, + }, + SecurityContext: test.DefaultSecurityContext(), + }, + }, + Logged: loggedString, + }. + WithSuffix(suffix). + WithLabel(run.TestNameLabel, name) +} + +func (pb PodBuilder) WithSuffix(suffix string) PodBuilder { + if suffix != "" { + pb.Pod.ObjectMeta.Name = pb.Pod.ObjectMeta.Name + "-" + suffix + } + return pb +} + +func (pb PodBuilder) WithLabel(key, value string) PodBuilder { + if pb.Pod.Labels == nil { + pb.Pod.Labels = make(map[string]string) + } + pb.Pod.Labels[key] = value + + return pb +} + +func (pb PodBuilder) RuntimeObjects() []runtime.Object { + return []runtime.Object{&pb.Pod} +} + +func (pb PodBuilder) InitTestSteps(k *test.K8sClient) test.StepList { + return test.StepList{ + { + Name: "K8S should be accessible", + Test: test.Eventually(func() error { + pods := corev1.PodList{} + return k.Client.List(&pods) + }), + }, + { + Name: "Label test pods", + Test: test.Eventually(func() error { + return test.LabelTestPods( + k.Client, + test.Ctx(), + run.TestNameLabel, + pb.Pod.Labels[run.TestNameLabel]) + }), + Skip: func() bool { + return test.Ctx().Local + }, + }, + { + Name: "Remove pod if it already exists", + Test: test.Eventually(func() error { + for _, obj := range pb.RuntimeObjects() { + err := k.Client.Delete(obj) + if err != nil && !apierrors.IsNotFound(err) { + return err + } + } + // wait for pod to disappear + var pod corev1.Pod + err := k.Client.Get(types.NamespacedName{ + Namespace: pb.Pod.Namespace, + Name: pb.Pod.Name, + }, &pod) + if err != nil && !apierrors.IsNotFound(err) { + return err + } + if err == nil { + return fmt.Errorf("pod %s is still there", k8s.ExtractNamespacedName(&pb.Pod)) + } + return nil + }), + }, + } +} + +func (pb PodBuilder) CreationTestSteps(k *test.K8sClient) test.StepList { + return test.StepList{}. + WithSteps(test.StepList{ + test.Step{ + Name: "Creating a Pod should succeed", + Test: func(t *testing.T) { + for _, obj := range pb.RuntimeObjects() { + err := k.Client.Create(obj) + require.NoError(t, err) + } + }, + }, + test.Step{ + Name: "Pod should be created", + Test: func(t *testing.T) { + var createdPod corev1.Pod + err := k.Client.Get(k8s.ExtractNamespacedName(&pb.Pod), &createdPod) + require.NoError(t, err) + }, + }, + }) +} + +func (pb PodBuilder) CheckK8sTestSteps(k *test.K8sClient) test.StepList { + return test.StepList{ + test.Step{ + Name: "Pod should be ready and running", + Test: test.Eventually(func() error { + var pod corev1.Pod + if err := k.Client.Get(k8s.ExtractNamespacedName(&pb.Pod), &pod); err != nil { + return err + } + + // pod is running + if pod.Status.Phase != corev1.PodRunning { + return fmt.Errorf("pod not running yet") + } + + // pod is ready + if !k8s.IsPodReady(pod) { + return fmt.Errorf("pod not ready yet") + } + + return nil + }), + }, + } +} + +func (pb PodBuilder) CheckStackTestSteps(*test.K8sClient) test.StepList { + return test.StepList{} // nothing to do +} + +func (pb PodBuilder) UpgradeTestSteps(k *test.K8sClient) test.StepList { + return test.StepList{ + { + Name: "Applying pod mutation should succeed", + Test: func(t *testing.T) { + var pod corev1.Pod + require.NoError(t, k.Client.Get(k8s.ExtractNamespacedName(&pb.Pod), &pod)) + pod.Spec = pb.Pod.Spec + require.NoError(t, k.Client.Update(&pod)) + }, + }} +} + +func (pb PodBuilder) DeletionTestSteps(k *test.K8sClient) test.StepList { + return []test.Step{ + { + Name: "Deleting the resources should return no error", + Test: func(t *testing.T) { + for _, obj := range pb.RuntimeObjects() { + err := k.Client.Delete(obj) + require.NoError(t, err) + } + }, + }, + { + Name: "The resources should not be there anymore", + Test: test.Eventually(func() error { + for _, obj := range pb.RuntimeObjects() { + m, err := meta.Accessor(obj) + if err != nil { + return err + } + err = k.Client.Get(k8s.ExtractNamespacedName(m), obj.DeepCopyObject()) + if err != nil { + if apierrors.IsNotFound(err) { + continue + } + } + return errors.Wrap(err, "expected 404 not found API error here") + + } + return nil + }), + }, + { + Name: "Pod should be eventually be removed", + Test: test.Eventually(func() error { + // wait for pod to disappear + var pod corev1.Pod + err := k.Client.Get(types.NamespacedName{ + Namespace: pb.Pod.Namespace, + Name: pb.Pod.Name, + }, &pod) + if err != nil && !apierrors.IsNotFound(err) { + return err + } + if err == nil { + return fmt.Errorf("pod %s is still there", k8s.ExtractNamespacedName(&pb.Pod)) + } + return nil + }), + }, + } +} + +func (pb PodBuilder) MutationTestSteps(k *test.K8sClient) test.StepList { + panic("implement me") +} + +func (pb PodBuilder) MutationReversalTestContext() test.ReversalTestContext { + panic("implement me") +} + +var _ test.Builder = Builder{} diff --git a/test/e2e/test/beat/steps.go b/test/e2e/test/beat/steps.go new file mode 100644 index 0000000000..a3a2b2f7b0 --- /dev/null +++ b/test/e2e/test/beat/steps.go @@ -0,0 +1,222 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package beat + +import ( + "fmt" + "testing" + + "github.com/pkg/errors" + "github.com/stretchr/testify/require" + corev1 "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/apimachinery/pkg/runtime" + + beatv1beta1 "github.com/elastic/cloud-on-k8s/pkg/apis/beat/v1beta1" + esv1 "github.com/elastic/cloud-on-k8s/pkg/apis/elasticsearch/v1" + "github.com/elastic/cloud-on-k8s/pkg/utils/k8s" + "github.com/elastic/cloud-on-k8s/test/e2e/cmd/run" + "github.com/elastic/cloud-on-k8s/test/e2e/test" + "github.com/elastic/cloud-on-k8s/test/e2e/test/elasticsearch" +) + +func (b Builder) InitTestSteps(k *test.K8sClient) test.StepList { + return test.StepList{ + { + Name: "K8S should be accessible", + Test: test.Eventually(func() error { + pods := corev1.PodList{} + return k.Client.List(&pods) + }), + }, + { + Name: "Label test pods", + Test: test.Eventually(func() error { + return test.LabelTestPods( + k.Client, + test.Ctx(), + run.TestNameLabel, + b.Beat.Labels[run.TestNameLabel]) + }), + Skip: func() bool { + return test.Ctx().Local + }, + }, + { + Name: "Beat CRDs should exist", + Test: test.Eventually(func() error { + crds := []runtime.Object{ + &beatv1beta1.BeatList{}, + } + for _, crd := range crds { + if err := k.Client.List(crd); err != nil { + return err + } + } + return nil + }), + }, + { + Name: "Remove Beat if it already exists", + Test: test.Eventually(func() error { + for _, obj := range b.RuntimeObjects() { + err := k.Client.Delete(obj) + if err != nil && !apierrors.IsNotFound(err) { + return err + } + } + // wait for Beat pods to disappear + if err := k.CheckPodCount(0, test.BeatPodListOptions(b.Beat.Namespace, b.Beat.Name, b.Beat.Spec.Type)...); err != nil { + return err + } + + // it may take some extra time for Beat to be fully deleted + var beat beatv1beta1.Beat + err := k.Client.Get(k8s.ExtractNamespacedName(&b.Beat), &beat) + if err != nil && !apierrors.IsNotFound(err) { + return err + } + if err == nil { + return fmt.Errorf("beat %s is still there", k8s.ExtractNamespacedName(&b.Beat)) + } + return nil + }), + }, + } +} + +func (b Builder) CreationTestSteps(k *test.K8sClient) test.StepList { + return test.StepList{}. + WithSteps(test.StepList{ + test.Step{ + Name: "Creating a Beat should succeed", + Test: func(t *testing.T) { + for _, obj := range b.RuntimeObjects() { + err := k.Client.Create(obj) + require.NoError(t, err) + } + }, + }, + test.Step{ + Name: "Beat should be created", + Test: func(t *testing.T) { + var createdBeat beatv1beta1.Beat + err := k.Client.Get(k8s.ExtractNamespacedName(&b.Beat), &createdBeat) + require.NoError(t, err) + require.Equal(t, b.Beat.Spec.Version, createdBeat.Spec.Version) + }, + }, + }) +} + +func (b Builder) CheckK8sTestSteps(k *test.K8sClient) test.StepList { + return test.StepList{} +} + +func (b Builder) CheckStackTestSteps(k *test.K8sClient) test.StepList { + // health + return test.StepList{ + test.Step{ + Name: "Beat health should be green", + Test: test.Eventually(func() error { + var beat beatv1beta1.Beat + if err := k.Client.Get(k8s.ExtractNamespacedName(&b.Beat), &beat); err != nil { + return err + } + + if beat.Status.Health != beatv1beta1.BeatGreenHealth { + return fmt.Errorf("beat %s health is %s", beat.Name, beat.Status.Health) + } + + return nil + }), + }, + test.Step{ + Name: "ES data should pass validations", + Test: test.Eventually(func() error { + esNsName := b.Beat.ElasticsearchRef().WithDefaultNamespace(b.Beat.Namespace).NamespacedName() + var es esv1.Elasticsearch + if err := k.Client.Get(esNsName, &es); err != nil { + return err + } + + esClient, err := elasticsearch.NewElasticsearchClient(es, k) + if err != nil { + return err + } + + for _, validation := range b.Validations { + if err := validation(esClient); err != nil { + return err + } + } + + return nil + }), + }, + } +} + +func (b Builder) UpgradeTestSteps(k *test.K8sClient) test.StepList { + return test.StepList{ + { + Name: "Applying the Beat mutation should succeed", + Test: func(t *testing.T) { + var beat beatv1beta1.Beat + require.NoError(t, k.Client.Get(k8s.ExtractNamespacedName(&b.Beat), &beat)) + beat.Spec = b.Beat.Spec + require.NoError(t, k.Client.Update(&beat)) + }, + }} +} + +func (b Builder) DeletionTestSteps(k *test.K8sClient) test.StepList { + return []test.Step{ + { + Name: "Deleting the resources should return no error", + Test: func(t *testing.T) { + for _, obj := range b.RuntimeObjects() { + err := k.Client.Delete(obj) + require.NoError(t, err) + } + }, + }, + { + Name: "The resources should not be there anymore", + Test: test.Eventually(func() error { + for _, obj := range b.RuntimeObjects() { + m, err := meta.Accessor(obj) + if err != nil { + return err + } + err = k.Client.Get(k8s.ExtractNamespacedName(m), obj.DeepCopyObject()) + if err != nil { + if apierrors.IsNotFound(err) { + continue + } + } + return errors.Wrap(err, "expected 404 not found API error here") + + } + return nil + }), + }, + { + Name: "Beat pods should be eventually be removed", + Test: test.Eventually(func() error { + return k.CheckPodCount(0, test.BeatPodListOptions(b.Beat.Namespace, b.Beat.Name, b.Beat.Spec.Type)...) + }), + }, + } +} + +func (b Builder) MutationTestSteps(k *test.K8sClient) test.StepList { + panic("implement me") +} + +func (b Builder) MutationReversalTestContext() test.ReversalTestContext { + panic("implement me") +} diff --git a/test/e2e/test/helper/yaml.go b/test/e2e/test/helper/yaml.go index 7b73afa28d..9b16220839 100644 --- a/test/e2e/test/helper/yaml.go +++ b/test/e2e/test/helper/yaml.go @@ -10,10 +10,13 @@ import ( "io" apmv1 "github.com/elastic/cloud-on-k8s/pkg/apis/apm/v1" + beatv1beta1 "github.com/elastic/cloud-on-k8s/pkg/apis/beat/v1beta1" esv1 "github.com/elastic/cloud-on-k8s/pkg/apis/elasticsearch/v1" kbv1 "github.com/elastic/cloud-on-k8s/pkg/apis/kibana/v1" + beatcommon "github.com/elastic/cloud-on-k8s/pkg/controller/beat/common" "github.com/elastic/cloud-on-k8s/test/e2e/test" "github.com/elastic/cloud-on-k8s/test/e2e/test/apmserver" + "github.com/elastic/cloud-on-k8s/test/e2e/test/beat" "github.com/elastic/cloud-on-k8s/test/e2e/test/elasticsearch" "github.com/elastic/cloud-on-k8s/test/e2e/test/kibana" "k8s.io/apimachinery/pkg/runtime" @@ -33,6 +36,7 @@ func NewYAMLDecoder() *YAMLDecoder { scheme.AddKnownTypes(esv1.GroupVersion, &esv1.Elasticsearch{}, &esv1.ElasticsearchList{}) scheme.AddKnownTypes(kbv1.GroupVersion, &kbv1.Kibana{}, &kbv1.KibanaList{}) scheme.AddKnownTypes(apmv1.GroupVersion, &apmv1.ApmServer{}, &apmv1.ApmServerList{}) + scheme.AddKnownTypes(beatv1beta1.GroupVersion, &beatv1beta1.Beat{}, &beatv1beta1.BeatList{}) decoder := serializer.NewCodecFactory(scheme).UniversalDeserializer() return &YAMLDecoder{decoder: decoder} @@ -70,6 +74,10 @@ func (yd *YAMLDecoder) ToBuilders(reader *bufio.Reader, transform BuilderTransfo b := apmserver.NewBuilderWithoutSuffix(decodedObj.Name) b.ApmServer = *decodedObj builder = transform(b) + case *beatv1beta1.Beat: + b := beat.NewBuilderWithoutSuffix(decodedObj.Name, beatcommon.Type(decodedObj.Spec.Type)) + b.Beat = *decodedObj + builder = transform(b) default: return builders, fmt.Errorf("unexpected object type: %t", decodedObj) } diff --git a/test/e2e/test/k8s_client.go b/test/e2e/test/k8s_client.go index 579d9ba63e..5a2faafc1b 100644 --- a/test/e2e/test/k8s_client.go +++ b/test/e2e/test/k8s_client.go @@ -25,9 +25,11 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client/config" apmv1 "github.com/elastic/cloud-on-k8s/pkg/apis/apm/v1" + beatv1beta1 "github.com/elastic/cloud-on-k8s/pkg/apis/beat/v1beta1" esv1 "github.com/elastic/cloud-on-k8s/pkg/apis/elasticsearch/v1" kbv1 "github.com/elastic/cloud-on-k8s/pkg/apis/kibana/v1" "github.com/elastic/cloud-on-k8s/pkg/controller/apmserver" + beatcommon "github.com/elastic/cloud-on-k8s/pkg/controller/beat/common" "github.com/elastic/cloud-on-k8s/pkg/controller/common" "github.com/elastic/cloud-on-k8s/pkg/controller/common/certificates" "github.com/elastic/cloud-on-k8s/pkg/controller/common/name" @@ -73,6 +75,9 @@ func CreateClient() (k8s.Client, error) { if err := apmv1.AddToScheme(scheme.Scheme); err != nil { return nil, err } + if err := beatv1beta1.AddToScheme(scheme.Scheme); err != nil { + return nil, err + } client, err := k8sclient.New(cfg, k8sclient.Options{Scheme: scheme.Scheme}) if err != nil { return nil, err @@ -315,6 +320,15 @@ func ApmServerPodListOptions(apmNamespace, apmName string) []k8sclient.ListOptio } +func BeatPodListOptions(beatNamespace, beatName, beatType string) []k8sclient.ListOption { + ns := k8sclient.InNamespace(beatNamespace) + matchLabels := k8sclient.MatchingLabels(map[string]string{ + common.TypeLabelName: beatcommon.TypeLabelValue, + beatcommon.NameLabelName: beatcommon.Name(beatName, beatType), + }) + return []k8sclient.ListOption{ns, matchLabels} +} + func EventListOptions(namespace, name string) []k8sclient.ListOption { ns := k8sclient.InNamespace(namespace) matchFields := k8sclient.MatchingFields(map[string]string{