From c3166f09b83279201764f0111d20f4438648c89a Mon Sep 17 00:00:00 2001 From: constanca-m Date: Mon, 16 Jan 2023 15:50:35 +0100 Subject: [PATCH 01/15] Add support for 1.26 K8s version. Update kind version. --- .ci/Jenkinsfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.ci/Jenkinsfile b/.ci/Jenkinsfile index 278b4f8b76..b8d00bc136 100644 --- a/.ci/Jenkinsfile +++ b/.ci/Jenkinsfile @@ -15,8 +15,8 @@ pipeline { PIPELINE_LOG_LEVEL='INFO' AWS_ACCOUNT_SECRET = 'secret/observability-team/ci/elastic-observability-aws-account-auth' HOME = "${env.WORKSPACE}" - KIND_VERSION = 'v0.14.0' - K8S_VERSION = 'v1.25.0' + KIND_VERSION = 'v0.17.0' + K8S_VERSION = 'v1.26.0' JOB_GCS_BUCKET = 'fleet-ci-temp' JOB_GCS_BUCKET_INTERNAL = 'fleet-ci-temp-internal' JOB_GCS_CREDENTIALS = 'fleet-ci-gcs-plugin' From 999729976edf0c4a8f1c115d852a0033189b3bcc Mon Sep 17 00:00:00 2001 From: constanca-m Date: Tue, 31 Jan 2023 17:11:57 +0100 Subject: [PATCH 02/15] Add support for kustomize. --- docs/howto/system_testing.md | 8 ++--- internal/kubectl/kubectl.go | 8 ++--- internal/kubectl/kubectl_apply.go | 6 ++-- internal/kubectl/kubectl_delete.go | 4 +-- .../system/servicedeployer/kubernetes.go | 30 ++++++++++--------- 5 files changed, 26 insertions(+), 30 deletions(-) diff --git a/docs/howto/system_testing.md b/docs/howto/system_testing.md index c69caa40dd..e3d339f57a 100644 --- a/docs/howto/system_testing.md +++ b/docs/howto/system_testing.md @@ -302,11 +302,9 @@ There are some specific environment variables that should be leveraged to overco ### Kubernetes service deployer -The Kubernetes service deployer requires the `_dev/deploy/k8s` directory to be present. It can include additional `*.yaml` files to deploy -custom applications in the Kubernetes cluster (e.g. Nginx deployment). If no resource definitions (`*.yaml` files ) are needed, -the `_dev/deploy/k8s` directory must contain an `.empty` file (to preserve the `k8s` directory under version control). - -The Kubernetes service deployer needs [kind](https://kind.sigs.k8s.io/) to be installed and the cluster to be up and running: +The Kubernetes service deployer requires the `_dev/deploy/k8s` directory to be present. +It needs to include either a `kustomization.yaml` file or an `.empty` file. The first is needed to ensure the deployment of each resource. +In case there are no resources to deploy, then the `.empty` file should be present in `_dev/deploy/k8s` of the datastream directory. ```bash wget -qO- https://raw.githubusercontent.com/elastic/elastic-package/main/scripts/kind-config.yaml | kind create cluster --config - diff --git a/internal/kubectl/kubectl.go b/internal/kubectl/kubectl.go index ac40d07d78..9082e47fba 100644 --- a/internal/kubectl/kubectl.go +++ b/internal/kubectl/kubectl.go @@ -27,12 +27,8 @@ func CurrentContext() (string, error) { return string(bytes.TrimSpace(output)), nil } -func modifyKubernetesResources(action string, definitionPaths ...string) ([]byte, error) { - args := []string{action} - for _, definitionPath := range definitionPaths { - args = append(args, "-f") - args = append(args, definitionPath) - } +func modifyKubernetesResources(action string, definitionPath string) ([]byte, error) { + args := []string{action, "-k", definitionPath} if action != "delete" { // "delete" supports only '-o name' args = append(args, "-o", "yaml") diff --git a/internal/kubectl/kubectl_apply.go b/internal/kubectl/kubectl_apply.go index a89afbc3f4..33901a2d67 100644 --- a/internal/kubectl/kubectl_apply.go +++ b/internal/kubectl/kubectl_apply.go @@ -70,9 +70,9 @@ func (c condition) String() string { } // Apply function adds resources to the Kubernetes cluster based on provided definitions. -func Apply(definitionPaths ...string) error { - logger.Debugf("Apply Kubernetes definitions") - out, err := modifyKubernetesResources("apply", definitionPaths...) +func Apply(definitionPath string) error { + logger.Debugf("Apply Kubernetes custom definitions") + out, err := modifyKubernetesResources("apply", definitionPath) if err != nil { return errors.Wrap(err, "can't modify Kubernetes resources (apply)") } diff --git a/internal/kubectl/kubectl_delete.go b/internal/kubectl/kubectl_delete.go index 3057bdde0d..4fa25938cd 100644 --- a/internal/kubectl/kubectl_delete.go +++ b/internal/kubectl/kubectl_delete.go @@ -5,7 +5,7 @@ package kubectl // Delete function removes resources from the Kubernetes cluster based on provided definitions. -func Delete(definitionPaths ...string) error { - _, err := modifyKubernetesResources("delete", definitionPaths...) +func Delete(definitionPath string) error { + _, err := modifyKubernetesResources("delete", definitionPath) return err } diff --git a/internal/testrunner/runners/system/servicedeployer/kubernetes.go b/internal/testrunner/runners/system/servicedeployer/kubernetes.go index 4e67dc3093..d4596ac10b 100644 --- a/internal/testrunner/runners/system/servicedeployer/kubernetes.go +++ b/internal/testrunner/runners/system/servicedeployer/kubernetes.go @@ -37,17 +37,17 @@ type kubernetesDeployedService struct { func (s kubernetesDeployedService) TearDown() error { logger.Debugf("uninstall custom Kubernetes definitions (directory: %s)", s.definitionsDir) - definitionPaths, err := findKubernetesDefinitions(s.definitionsDir) + definitionPath, err := findKubernetesDefinitions(s.definitionsDir) if err != nil { return errors.Wrapf(err, "can't find Kubernetes definitions in given directory (path: %s)", s.definitionsDir) } - if len(definitionPaths) == 0 { + if len(definitionPath) == 0 { logger.Debugf("no custom definitions found (directory: %s). Nothing will be uninstalled.", s.definitionsDir) return nil } - err = kubectl.Delete(definitionPaths...) + err = kubectl.Delete(definitionPath) if err != nil { return errors.Wrapf(err, "can't uninstall Kubernetes resources (path: %s)", s.definitionsDir) } @@ -113,17 +113,17 @@ func (ksd KubernetesServiceDeployer) SetUp(ctxt ServiceContext) (DeployedService func (ksd KubernetesServiceDeployer) installCustomDefinitions() error { logger.Debugf("install custom Kubernetes definitions (directory: %s)", ksd.definitionsDir) - definitionPaths, err := findKubernetesDefinitions(ksd.definitionsDir) + definitionPath, err := findKubernetesDefinitions(ksd.definitionsDir) if err != nil { return errors.Wrapf(err, "can't find Kubernetes definitions in given directory (path: %s)", ksd.definitionsDir) } - if len(definitionPaths) == 0 { + if len(definitionPath) == 0 { logger.Debugf("no custom definitions found (directory: %s). Nothing else will be installed.", ksd.definitionsDir) return nil } - err = kubectl.Apply(definitionPaths...) + err = kubectl.Apply(definitionPath) if err != nil { return errors.Wrap(err, "can't install custom definitions") } @@ -132,15 +132,17 @@ func (ksd KubernetesServiceDeployer) installCustomDefinitions() error { var _ ServiceDeployer = new(KubernetesServiceDeployer) -func findKubernetesDefinitions(definitionsDir string) ([]string, error) { - files, err := filepath.Glob(filepath.Join(definitionsDir, "*.yaml")) - if err != nil { - return nil, errors.Wrapf(err, "can't read definitions directory (path: %s)", definitionsDir) +func findKubernetesDefinitions(definitionsDir string) (string, error) { + if _, err := os.Stat(definitionsDir); err != nil { + return "", errors.Wrapf(err, "can't read definitions directory (path: %s)", definitionsDir) } - - var definitionPaths []string - definitionPaths = append(definitionPaths, files...) - return definitionPaths, nil + if _, err := os.Stat(filepath.Join(definitionsDir, "kustomization.yaml")); err != nil { + if _, err := os.Stat(filepath.Join(definitionsDir, ".empty")); err != nil { + return "", errors.Errorf("kustomization.yaml file is missing (path: %s)", definitionsDir) + } + return "", nil + } + return definitionsDir, nil } func installElasticAgentInCluster() error { From 090b60631ab28da45ce63d25a2650d151f83eeac Mon Sep 17 00:00:00 2001 From: constanca-m Date: Tue, 31 Jan 2023 17:32:16 +0100 Subject: [PATCH 03/15] Fix doc. --- docs/howto/system_testing.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/howto/system_testing.md b/docs/howto/system_testing.md index e3d339f57a..998caf8769 100644 --- a/docs/howto/system_testing.md +++ b/docs/howto/system_testing.md @@ -306,6 +306,7 @@ The Kubernetes service deployer requires the `_dev/deploy/k8s` directory to be p It needs to include either a `kustomization.yaml` file or an `.empty` file. The first is needed to ensure the deployment of each resource. In case there are no resources to deploy, then the `.empty` file should be present in `_dev/deploy/k8s` of the datastream directory. +The Kubernetes service deployer needs [kind](https://kind.sigs.k8s.io/) to be installed and the cluster to be up and running: ```bash wget -qO- https://raw.githubusercontent.com/elastic/elastic-package/main/scripts/kind-config.yaml | kind create cluster --config - ``` From 9bcb14a0657953b937c2b457eb4b1cec4c9550c0 Mon Sep 17 00:00:00 2001 From: constanca-m Date: Mon, 6 Feb 2023 11:10:41 +0100 Subject: [PATCH 04/15] Fix function and variable names. --- internal/kubectl/kubectl.go | 4 +- internal/kubectl/kubectl_apply.go | 4 +- internal/kubectl/kubectl_delete.go | 4 +- .../system/servicedeployer/kubernetes.go | 55 ++++++++++--------- 4 files changed, 35 insertions(+), 32 deletions(-) diff --git a/internal/kubectl/kubectl.go b/internal/kubectl/kubectl.go index 9082e47fba..48402da5dd 100644 --- a/internal/kubectl/kubectl.go +++ b/internal/kubectl/kubectl.go @@ -27,8 +27,8 @@ func CurrentContext() (string, error) { return string(bytes.TrimSpace(output)), nil } -func modifyKubernetesResources(action string, definitionPath string) ([]byte, error) { - args := []string{action, "-k", definitionPath} +func modifyKubernetesResources(action string, definitionsPath string) ([]byte, error) { + args := []string{action, "-k", definitionsPath} if action != "delete" { // "delete" supports only '-o name' args = append(args, "-o", "yaml") diff --git a/internal/kubectl/kubectl_apply.go b/internal/kubectl/kubectl_apply.go index 33901a2d67..4214a2fabf 100644 --- a/internal/kubectl/kubectl_apply.go +++ b/internal/kubectl/kubectl_apply.go @@ -70,9 +70,9 @@ func (c condition) String() string { } // Apply function adds resources to the Kubernetes cluster based on provided definitions. -func Apply(definitionPath string) error { +func Apply(definitionsPath string) error { logger.Debugf("Apply Kubernetes custom definitions") - out, err := modifyKubernetesResources("apply", definitionPath) + out, err := modifyKubernetesResources("apply", definitionsPath) if err != nil { return errors.Wrap(err, "can't modify Kubernetes resources (apply)") } diff --git a/internal/kubectl/kubectl_delete.go b/internal/kubectl/kubectl_delete.go index 4fa25938cd..1fb57fa20f 100644 --- a/internal/kubectl/kubectl_delete.go +++ b/internal/kubectl/kubectl_delete.go @@ -5,7 +5,7 @@ package kubectl // Delete function removes resources from the Kubernetes cluster based on provided definitions. -func Delete(definitionPath string) error { - _, err := modifyKubernetesResources("delete", definitionPath) +func Delete(definitionsPath string) error { + _, err := modifyKubernetesResources("delete", definitionsPath) return err } diff --git a/internal/testrunner/runners/system/servicedeployer/kubernetes.go b/internal/testrunner/runners/system/servicedeployer/kubernetes.go index d4596ac10b..a26b1b3daa 100644 --- a/internal/testrunner/runners/system/servicedeployer/kubernetes.go +++ b/internal/testrunner/runners/system/servicedeployer/kubernetes.go @@ -25,31 +25,31 @@ import ( // KubernetesServiceDeployer is responsible for deploying resources in the Kubernetes cluster. type KubernetesServiceDeployer struct { - definitionsDir string + definitionsPath string } type kubernetesDeployedService struct { ctxt ServiceContext - definitionsDir string + definitionsPath string } func (s kubernetesDeployedService) TearDown() error { - logger.Debugf("uninstall custom Kubernetes definitions (directory: %s)", s.definitionsDir) + logger.Debugf("uninstall custom Kubernetes definitions (directory: %s)", s.definitionsPath) - definitionPath, err := findKubernetesDefinitions(s.definitionsDir) + definitionsPath, err := checkKubernetesDefinition(s.definitionsPath) if err != nil { - return errors.Wrapf(err, "can't find Kubernetes definitions in given directory (path: %s)", s.definitionsDir) + return errors.Wrapf(err, "can't find Kubernetes definitions in given directory (path: %s)", s.definitionsPath) } - if len(definitionPath) == 0 { - logger.Debugf("no custom definitions found (directory: %s). Nothing will be uninstalled.", s.definitionsDir) + if len(definitionsPath) == 0 { + logger.Debugf("no custom definitions found (directory: %s). Nothing will be uninstalled.", s.definitionsPath) return nil } - err = kubectl.Delete(definitionPath) + err = kubectl.Delete(definitionsPath) if err != nil { - return errors.Wrapf(err, "can't uninstall Kubernetes resources (path: %s)", s.definitionsDir) + return errors.Wrapf(err, "can't uninstall Kubernetes resources (path: %s)", s.definitionsPath) } return nil } @@ -70,9 +70,9 @@ func (s *kubernetesDeployedService) SetContext(sc ServiceContext) error { var _ DeployedService = new(kubernetesDeployedService) // NewKubernetesServiceDeployer function creates a new instance of KubernetesServiceDeployer. -func NewKubernetesServiceDeployer(definitionsDir string) (*KubernetesServiceDeployer, error) { +func NewKubernetesServiceDeployer(definitionsPath string) (*KubernetesServiceDeployer, error) { return &KubernetesServiceDeployer{ - definitionsDir: definitionsDir, + definitionsPath: definitionsPath, }, nil } @@ -105,25 +105,25 @@ func (ksd KubernetesServiceDeployer) SetUp(ctxt ServiceContext) (DeployedService // to deploy Agent Pod. Because of this, hostname inside pod will be equal to the name of the k8s host. ctxt.Agent.Host.NamePrefix = "kind-control-plane" return &kubernetesDeployedService{ - ctxt: ctxt, - definitionsDir: ksd.definitionsDir, + ctxt: ctxt, + definitionsPath: ksd.definitionsPath, }, nil } func (ksd KubernetesServiceDeployer) installCustomDefinitions() error { - logger.Debugf("install custom Kubernetes definitions (directory: %s)", ksd.definitionsDir) + logger.Debugf("install custom Kubernetes definitions (directory: %s)", ksd.definitionsPath) - definitionPath, err := findKubernetesDefinitions(ksd.definitionsDir) + definitionsPath, err := checkKubernetesDefinition(ksd.definitionsPath) if err != nil { - return errors.Wrapf(err, "can't find Kubernetes definitions in given directory (path: %s)", ksd.definitionsDir) + return errors.Wrapf(err, "can't find Kubernetes definitions in given path: %s", ksd.definitionsPath) } - if len(definitionPath) == 0 { - logger.Debugf("no custom definitions found (directory: %s). Nothing else will be installed.", ksd.definitionsDir) + if len(definitionsPath) == 0 { + logger.Debugf("no custom definitions found (path: %s). Nothing else will be installed.", ksd.definitionsPath) return nil } - err = kubectl.Apply(definitionPath) + err = kubectl.Apply(definitionsPath) if err != nil { return errors.Wrap(err, "can't install custom definitions") } @@ -132,17 +132,20 @@ func (ksd KubernetesServiceDeployer) installCustomDefinitions() error { var _ ServiceDeployer = new(KubernetesServiceDeployer) -func findKubernetesDefinitions(definitionsDir string) (string, error) { - if _, err := os.Stat(definitionsDir); err != nil { - return "", errors.Wrapf(err, "can't read definitions directory (path: %s)", definitionsDir) +func checkKubernetesDefinition(definitionsPath string) (string, error) { + if _, err := os.Stat(definitionsPath); err != nil { + return "", errors.Wrapf(err, "can't read definitions directory (path: %s)", definitionsPath) } - if _, err := os.Stat(filepath.Join(definitionsDir, "kustomization.yaml")); err != nil { - if _, err := os.Stat(filepath.Join(definitionsDir, ".empty")); err != nil { - return "", errors.Errorf("kustomization.yaml file is missing (path: %s)", definitionsDir) + // check if kustomization.yaml exists + if _, err := os.Stat(filepath.Join(definitionsPath, "kustomization.yaml")); err != nil { + // if it does not exist, then the .empty file needs to be present + if _, err := os.Stat(filepath.Join(definitionsPath, ".empty")); err != nil { + return "", errors.Errorf("kustomization.yaml file is missing (path: %s). Add one or create an .empty file"+ + " if no custom definitions are required.", definitionsPath) } return "", nil } - return definitionsDir, nil + return definitionsPath, nil } func installElasticAgentInCluster() error { From 15e5d6fa62a6c30c90fd18b09c1aa18e044daafb Mon Sep 17 00:00:00 2001 From: constanca-m Date: Mon, 6 Feb 2023 11:13:10 +0100 Subject: [PATCH 05/15] Fix how to. --- docs/howto/system_testing.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/howto/system_testing.md b/docs/howto/system_testing.md index 998caf8769..d2168b5385 100644 --- a/docs/howto/system_testing.md +++ b/docs/howto/system_testing.md @@ -303,8 +303,8 @@ There are some specific environment variables that should be leveraged to overco ### Kubernetes service deployer The Kubernetes service deployer requires the `_dev/deploy/k8s` directory to be present. -It needs to include either a `kustomization.yaml` file or an `.empty` file. The first is needed to ensure the deployment of each resource. -In case there are no resources to deploy, then the `.empty` file should be present in `_dev/deploy/k8s` of the datastream directory. +It needs to include either a `kustomization.yaml` file or an `.empty` file. The first is needed to ensure the deployment of each resource, +while the second is required if no custom resources are needed. The Kubernetes service deployer needs [kind](https://kind.sigs.k8s.io/) to be installed and the cluster to be up and running: ```bash From a8f0728130cef7edcc4c1fde0aeeb77611b95e61 Mon Sep 17 00:00:00 2001 From: constanca-m Date: Mon, 6 Feb 2023 15:28:18 +0100 Subject: [PATCH 06/15] Fix function name. --- .../testrunner/runners/system/servicedeployer/kubernetes.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/testrunner/runners/system/servicedeployer/kubernetes.go b/internal/testrunner/runners/system/servicedeployer/kubernetes.go index a26b1b3daa..191f178cf9 100644 --- a/internal/testrunner/runners/system/servicedeployer/kubernetes.go +++ b/internal/testrunner/runners/system/servicedeployer/kubernetes.go @@ -37,7 +37,7 @@ type kubernetesDeployedService struct { func (s kubernetesDeployedService) TearDown() error { logger.Debugf("uninstall custom Kubernetes definitions (directory: %s)", s.definitionsPath) - definitionsPath, err := checkKubernetesDefinition(s.definitionsPath) + definitionsPath, err := containsKustomization(s.definitionsPath) if err != nil { return errors.Wrapf(err, "can't find Kubernetes definitions in given directory (path: %s)", s.definitionsPath) } @@ -113,7 +113,7 @@ func (ksd KubernetesServiceDeployer) SetUp(ctxt ServiceContext) (DeployedService func (ksd KubernetesServiceDeployer) installCustomDefinitions() error { logger.Debugf("install custom Kubernetes definitions (directory: %s)", ksd.definitionsPath) - definitionsPath, err := checkKubernetesDefinition(ksd.definitionsPath) + definitionsPath, err := containsKustomization(ksd.definitionsPath) if err != nil { return errors.Wrapf(err, "can't find Kubernetes definitions in given path: %s", ksd.definitionsPath) } @@ -132,7 +132,7 @@ func (ksd KubernetesServiceDeployer) installCustomDefinitions() error { var _ ServiceDeployer = new(KubernetesServiceDeployer) -func checkKubernetesDefinition(definitionsPath string) (string, error) { +func containsKustomization(definitionsPath string) (string, error) { if _, err := os.Stat(definitionsPath); err != nil { return "", errors.Wrapf(err, "can't read definitions directory (path: %s)", definitionsPath) } From b335a8e79fa982fe2879c5794d4a103438ba1f3a Mon Sep 17 00:00:00 2001 From: constanca-m Date: Mon, 6 Feb 2023 15:48:25 +0100 Subject: [PATCH 07/15] Fix function readability. --- .../system/servicedeployer/kubernetes.go | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/internal/testrunner/runners/system/servicedeployer/kubernetes.go b/internal/testrunner/runners/system/servicedeployer/kubernetes.go index 191f178cf9..0eb9f86629 100644 --- a/internal/testrunner/runners/system/servicedeployer/kubernetes.go +++ b/internal/testrunner/runners/system/servicedeployer/kubernetes.go @@ -37,17 +37,17 @@ type kubernetesDeployedService struct { func (s kubernetesDeployedService) TearDown() error { logger.Debugf("uninstall custom Kubernetes definitions (directory: %s)", s.definitionsPath) - definitionsPath, err := containsKustomization(s.definitionsPath) + deleteResources, err := containsKustomization(s.definitionsPath) if err != nil { return errors.Wrapf(err, "can't find Kubernetes definitions in given directory (path: %s)", s.definitionsPath) } - if len(definitionsPath) == 0 { + if !deleteResources { logger.Debugf("no custom definitions found (directory: %s). Nothing will be uninstalled.", s.definitionsPath) return nil } - err = kubectl.Delete(definitionsPath) + err = kubectl.Delete(s.definitionsPath) if err != nil { return errors.Wrapf(err, "can't uninstall Kubernetes resources (path: %s)", s.definitionsPath) } @@ -113,17 +113,17 @@ func (ksd KubernetesServiceDeployer) SetUp(ctxt ServiceContext) (DeployedService func (ksd KubernetesServiceDeployer) installCustomDefinitions() error { logger.Debugf("install custom Kubernetes definitions (directory: %s)", ksd.definitionsPath) - definitionsPath, err := containsKustomization(ksd.definitionsPath) + installResources, err := containsKustomization(ksd.definitionsPath) if err != nil { return errors.Wrapf(err, "can't find Kubernetes definitions in given path: %s", ksd.definitionsPath) } - if len(definitionsPath) == 0 { + if !installResources { logger.Debugf("no custom definitions found (path: %s). Nothing else will be installed.", ksd.definitionsPath) return nil } - err = kubectl.Apply(definitionsPath) + err = kubectl.Apply(ksd.definitionsPath) if err != nil { return errors.Wrap(err, "can't install custom definitions") } @@ -132,20 +132,20 @@ func (ksd KubernetesServiceDeployer) installCustomDefinitions() error { var _ ServiceDeployer = new(KubernetesServiceDeployer) -func containsKustomization(definitionsPath string) (string, error) { +func containsKustomization(definitionsPath string) (bool, error) { if _, err := os.Stat(definitionsPath); err != nil { - return "", errors.Wrapf(err, "can't read definitions directory (path: %s)", definitionsPath) + return false, errors.Wrapf(err, "can't read definitions directory (path: %s)", definitionsPath) } // check if kustomization.yaml exists if _, err := os.Stat(filepath.Join(definitionsPath, "kustomization.yaml")); err != nil { // if it does not exist, then the .empty file needs to be present if _, err := os.Stat(filepath.Join(definitionsPath, ".empty")); err != nil { - return "", errors.Errorf("kustomization.yaml file is missing (path: %s). Add one or create an .empty file"+ + return false, errors.Errorf("kustomization.yaml file is missing (path: %s). Add one or create an .empty file"+ " if no custom definitions are required.", definitionsPath) } - return "", nil + return false, nil } - return definitionsPath, nil + return true, nil } func installElasticAgentInCluster() error { From 7139df0b43b46ba03e3b4a41de9d97a52c3fc5d2 Mon Sep 17 00:00:00 2001 From: constanca-m Date: Mon, 6 Feb 2023 17:44:58 +0100 Subject: [PATCH 08/15] Update README --- test/packages/with-kind/kubernetes/docs/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/packages/with-kind/kubernetes/docs/README.md b/test/packages/with-kind/kubernetes/docs/README.md index 8713649963..957e46f49d 100644 --- a/test/packages/with-kind/kubernetes/docs/README.md +++ b/test/packages/with-kind/kubernetes/docs/README.md @@ -82,7 +82,7 @@ This defaults to `/var/log/containers/*${kubernetes.container.id}.log`. ## Compatibility -The Kubernetes package is tested with Kubernetes 1.13.x, 1.14.x, 1.15.x, 1.16.x, 1.17.x, and 1.18.x +The Kubernetes package is tested with Kubernetes 1.23.x-1.26.x. ## Dashboard From e4d585334cfd1506ab5a5c0c254545d0ceffe4b6 Mon Sep 17 00:00:00 2001 From: constanca-m Date: Tue, 7 Feb 2023 10:26:27 +0100 Subject: [PATCH 09/15] Update testing with kind. --- .../_dev/deploy/k8s/cluster-role-binding.yaml | 15 -- .../_dev/deploy/k8s/cluster-role.yaml | 108 ---------- ...ample-redis-config.yaml => configmap.yaml} | 0 .../deploy/k8s/{conrjob.yaml => cronjob.yaml} | 4 +- .../kubernetes/_dev/deploy/k8s/daemonset.yaml | 48 +++++ .../_dev/deploy/k8s/deployment.yaml | 44 ---- .../_dev/deploy/k8s/kustomization.yaml | 10 + .../_dev/deploy/k8s/service-account.yaml | 8 - .../kubernetes/_dev/deploy/k8s/service.yaml | 19 -- .../pod/agent/stream/stream.yml.hbs | 14 ++ .../data_stream/pod/fields/base-fields.yml | 7 + .../kubernetes/data_stream/pod/fields/ecs.yml | 2 +- .../kubernetes/data_stream/pod/manifest.yml | 28 +++ .../data_stream/pod/sample_event.json | 183 ++++++++-------- .../_dev/test/system/test-default-config.yml | 6 + .../state_pod/agent/stream/stream.yml.hbs | 33 +++ .../data_stream/state_pod/fields/agent.yml | 198 ++++++++++++++++++ .../state_pod/fields/base-fields.yml | 146 +++++++++++++ .../data_stream/state_pod/fields/ecs.yml | 12 ++ .../data_stream/state_pod/fields/fields.yml | 26 +++ .../data_stream/state_pod/manifest.yml | 84 ++++++++ .../data_stream/state_pod/sample_event.json | 107 ++++++++++ 22 files changed, 824 insertions(+), 278 deletions(-) delete mode 100644 test/packages/with-kind/kubernetes/_dev/deploy/k8s/cluster-role-binding.yaml delete mode 100644 test/packages/with-kind/kubernetes/_dev/deploy/k8s/cluster-role.yaml rename test/packages/with-kind/kubernetes/_dev/deploy/k8s/{example-redis-config.yaml => configmap.yaml} (100%) rename test/packages/with-kind/kubernetes/_dev/deploy/k8s/{conrjob.yaml => cronjob.yaml} (89%) create mode 100644 test/packages/with-kind/kubernetes/_dev/deploy/k8s/daemonset.yaml delete mode 100644 test/packages/with-kind/kubernetes/_dev/deploy/k8s/deployment.yaml create mode 100644 test/packages/with-kind/kubernetes/_dev/deploy/k8s/kustomization.yaml delete mode 100644 test/packages/with-kind/kubernetes/_dev/deploy/k8s/service-account.yaml delete mode 100644 test/packages/with-kind/kubernetes/_dev/deploy/k8s/service.yaml create mode 100644 test/packages/with-kind/kubernetes/data_stream/state_pod/_dev/test/system/test-default-config.yml create mode 100644 test/packages/with-kind/kubernetes/data_stream/state_pod/agent/stream/stream.yml.hbs create mode 100644 test/packages/with-kind/kubernetes/data_stream/state_pod/fields/agent.yml create mode 100644 test/packages/with-kind/kubernetes/data_stream/state_pod/fields/base-fields.yml create mode 100644 test/packages/with-kind/kubernetes/data_stream/state_pod/fields/ecs.yml create mode 100644 test/packages/with-kind/kubernetes/data_stream/state_pod/fields/fields.yml create mode 100644 test/packages/with-kind/kubernetes/data_stream/state_pod/manifest.yml create mode 100644 test/packages/with-kind/kubernetes/data_stream/state_pod/sample_event.json diff --git a/test/packages/with-kind/kubernetes/_dev/deploy/k8s/cluster-role-binding.yaml b/test/packages/with-kind/kubernetes/_dev/deploy/k8s/cluster-role-binding.yaml deleted file mode 100644 index ff5c2be138..0000000000 --- a/test/packages/with-kind/kubernetes/_dev/deploy/k8s/cluster-role-binding.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - labels: - app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.0.0-rc.1 - name: kube-state-metrics -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: kube-state-metrics -subjects: - - kind: ServiceAccount - name: kube-state-metrics - namespace: kube-system diff --git a/test/packages/with-kind/kubernetes/_dev/deploy/k8s/cluster-role.yaml b/test/packages/with-kind/kubernetes/_dev/deploy/k8s/cluster-role.yaml deleted file mode 100644 index 1b567f9257..0000000000 --- a/test/packages/with-kind/kubernetes/_dev/deploy/k8s/cluster-role.yaml +++ /dev/null @@ -1,108 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - labels: - app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.0.0-rc.1 - name: kube-state-metrics -rules: - - apiGroups: - - "" - resources: - - configmaps - - secrets - - nodes - - pods - - services - - resourcequotas - - replicationcontrollers - - limitranges - - persistentvolumeclaims - - persistentvolumes - - namespaces - - endpoints - verbs: - - list - - watch - - apiGroups: - - apps - resources: - - statefulsets - - daemonsets - - deployments - - replicasets - verbs: - - list - - watch - - apiGroups: - - batch - resources: - - cronjobs - - jobs - verbs: - - list - - watch - - apiGroups: - - autoscaling - resources: - - horizontalpodautoscalers - verbs: - - list - - watch - - apiGroups: - - authentication.k8s.io - resources: - - tokenreviews - verbs: - - create - - apiGroups: - - authorization.k8s.io - resources: - - subjectaccessreviews - verbs: - - create - - apiGroups: - - policy - resources: - - poddisruptionbudgets - verbs: - - list - - watch - - apiGroups: - - certificates.k8s.io - resources: - - certificatesigningrequests - verbs: - - list - - watch - - apiGroups: - - storage.k8s.io - resources: - - storageclasses - - volumeattachments - verbs: - - list - - watch - - apiGroups: - - admissionregistration.k8s.io - resources: - - mutatingwebhookconfigurations - - validatingwebhookconfigurations - verbs: - - list - - watch - - apiGroups: - - networking.k8s.io - resources: - - networkpolicies - - ingresses - verbs: - - list - - watch - - apiGroups: - - coordination.k8s.io - resources: - - leases - verbs: - - list - - watch diff --git a/test/packages/with-kind/kubernetes/_dev/deploy/k8s/example-redis-config.yaml b/test/packages/with-kind/kubernetes/_dev/deploy/k8s/configmap.yaml similarity index 100% rename from test/packages/with-kind/kubernetes/_dev/deploy/k8s/example-redis-config.yaml rename to test/packages/with-kind/kubernetes/_dev/deploy/k8s/configmap.yaml diff --git a/test/packages/with-kind/kubernetes/_dev/deploy/k8s/conrjob.yaml b/test/packages/with-kind/kubernetes/_dev/deploy/k8s/cronjob.yaml similarity index 89% rename from test/packages/with-kind/kubernetes/_dev/deploy/k8s/conrjob.yaml rename to test/packages/with-kind/kubernetes/_dev/deploy/k8s/cronjob.yaml index 472da4598b..d9af61dc23 100644 --- a/test/packages/with-kind/kubernetes/_dev/deploy/k8s/conrjob.yaml +++ b/test/packages/with-kind/kubernetes/_dev/deploy/k8s/cronjob.yaml @@ -1,7 +1,9 @@ -apiVersion: batch/v1beta1 +apiVersion: batch/v1 kind: CronJob metadata: name: hello + labels: + k8s-app: myjob spec: schedule: "*/1 * * * *" jobTemplate: diff --git a/test/packages/with-kind/kubernetes/_dev/deploy/k8s/daemonset.yaml b/test/packages/with-kind/kubernetes/_dev/deploy/k8s/daemonset.yaml new file mode 100644 index 0000000000..ac269d4167 --- /dev/null +++ b/test/packages/with-kind/kubernetes/_dev/deploy/k8s/daemonset.yaml @@ -0,0 +1,48 @@ +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: fluentd-elasticsearch + namespace: kube-system + labels: + k8s-app: fluentd-logging +spec: + selector: + matchLabels: + name: fluentd-elasticsearch + template: + metadata: + labels: + name: fluentd-elasticsearch + spec: + tolerations: + # these tolerations are to have the daemonset runnable on control plane nodes + # remove them if your control plane nodes should not run pods + - key: node-role.kubernetes.io/control-plane + operator: Exists + effect: NoSchedule + - key: node-role.kubernetes.io/master + operator: Exists + effect: NoSchedule + containers: + - name: fluentd-elasticsearch + image: quay.io/fluentd_elasticsearch/fluentd:v2.5.2 + resources: + limits: + memory: 200Mi + requests: + cpu: 100m + memory: 200Mi + volumeMounts: + - name: varlog + mountPath: /var/log + - name: varlibdockercontainers + mountPath: /var/lib/docker/containers + readOnly: true + terminationGracePeriodSeconds: 30 + volumes: + - name: varlog + hostPath: + path: /var/log + - name: varlibdockercontainers + hostPath: + path: /var/lib/docker/containers diff --git a/test/packages/with-kind/kubernetes/_dev/deploy/k8s/deployment.yaml b/test/packages/with-kind/kubernetes/_dev/deploy/k8s/deployment.yaml deleted file mode 100644 index 420eece825..0000000000 --- a/test/packages/with-kind/kubernetes/_dev/deploy/k8s/deployment.yaml +++ /dev/null @@ -1,44 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.0.0-rc.1 - name: kube-state-metrics - namespace: kube-system -spec: - replicas: 1 - selector: - matchLabels: - app.kubernetes.io/name: kube-state-metrics - template: - metadata: - labels: - app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.0.0-rc.1 - spec: - containers: - - image: quay.io/coreos/kube-state-metrics:v1.9.0 - livenessProbe: - httpGet: - path: /healthz - port: 8080 - initialDelaySeconds: 5 - timeoutSeconds: 5 - name: kube-state-metrics - ports: - - containerPort: 8080 - name: http-metrics - - containerPort: 8081 - name: telemetry - readinessProbe: - httpGet: - path: / - port: 8081 - initialDelaySeconds: 5 - timeoutSeconds: 5 - securityContext: - runAsUser: 65534 - nodeSelector: - kubernetes.io/os: linux - serviceAccountName: kube-state-metrics diff --git a/test/packages/with-kind/kubernetes/_dev/deploy/k8s/kustomization.yaml b/test/packages/with-kind/kubernetes/_dev/deploy/k8s/kustomization.yaml new file mode 100644 index 0000000000..1117f584af --- /dev/null +++ b/test/packages/with-kind/kubernetes/_dev/deploy/k8s/kustomization.yaml @@ -0,0 +1,10 @@ +resources: + - pv.yaml + - pvc.yaml + - cronjob.yaml + - job.yaml + - daemonset.yaml + - configmap.yaml + - rq.yaml + - ss.yaml + - github.com/kubernetes/kube-state-metrics?ref=main diff --git a/test/packages/with-kind/kubernetes/_dev/deploy/k8s/service-account.yaml b/test/packages/with-kind/kubernetes/_dev/deploy/k8s/service-account.yaml deleted file mode 100644 index 1708b4beac..0000000000 --- a/test/packages/with-kind/kubernetes/_dev/deploy/k8s/service-account.yaml +++ /dev/null @@ -1,8 +0,0 @@ -apiVersion: v1 -kind: ServiceAccount -metadata: - labels: - app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.0.0-rc.1 - name: kube-state-metrics - namespace: kube-system diff --git a/test/packages/with-kind/kubernetes/_dev/deploy/k8s/service.yaml b/test/packages/with-kind/kubernetes/_dev/deploy/k8s/service.yaml deleted file mode 100644 index ef80dc44bc..0000000000 --- a/test/packages/with-kind/kubernetes/_dev/deploy/k8s/service.yaml +++ /dev/null @@ -1,19 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - labels: - app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.0.0-rc.1 - name: kube-state-metrics - namespace: kube-system -spec: - clusterIP: None - ports: - - name: http-metrics - port: 8080 - targetPort: http-metrics - - name: telemetry - port: 8081 - targetPort: telemetry - selector: - app.kubernetes.io/name: kube-state-metrics diff --git a/test/packages/with-kind/kubernetes/data_stream/pod/agent/stream/stream.yml.hbs b/test/packages/with-kind/kubernetes/data_stream/pod/agent/stream/stream.yml.hbs index 54fd7c22cc..4236eede2d 100644 --- a/test/packages/with-kind/kubernetes/data_stream/pod/agent/stream/stream.yml.hbs +++ b/test/packages/with-kind/kubernetes/data_stream/pod/agent/stream/stream.yml.hbs @@ -1,5 +1,8 @@ metricsets: ["pod"] add_metadata: {{add_metadata}} +{{#if add_resource_metadata_config}} +{{add_resource_metadata_config}} +{{/if}} hosts: {{#each hosts}} - {{this}} @@ -9,3 +12,14 @@ period: {{period}} bearer_token_file: {{bearer_token_file}} ssl.verification_mode: {{ssl.verification_mode}} {{/if}} +{{#if ssl.certificate_authorities}} +ssl.certificate_authorities: +{{#each ssl.certificate_authorities}} + - {{this}} +{{/each}} +{{/if}} + +{{#if processors}} +processors: +{{processors}} +{{/if}} \ No newline at end of file diff --git a/test/packages/with-kind/kubernetes/data_stream/pod/fields/base-fields.yml b/test/packages/with-kind/kubernetes/data_stream/pod/fields/base-fields.yml index 037e77a4e4..907af218e5 100644 --- a/test/packages/with-kind/kubernetes/data_stream/pod/fields/base-fields.yml +++ b/test/packages/with-kind/kubernetes/data_stream/pod/fields/base-fields.yml @@ -25,7 +25,13 @@ description: > Kubernetes pod UID + - name: pod.ip + type: ip + description: > + Kubernetes pod IP + - name: namespace + dimension: true type: keyword description: > Kubernetes namespace @@ -74,6 +80,7 @@ Kubernetes node UID - name: namespace_uid + dimension: true type: keyword description: > Kubernetes namespace UID diff --git a/test/packages/with-kind/kubernetes/data_stream/pod/fields/ecs.yml b/test/packages/with-kind/kubernetes/data_stream/pod/fields/ecs.yml index 1f83d6a406..e2c4743415 100644 --- a/test/packages/with-kind/kubernetes/data_stream/pod/fields/ecs.yml +++ b/test/packages/with-kind/kubernetes/data_stream/pod/fields/ecs.yml @@ -18,5 +18,5 @@ type: long format: bytes metric_type: counter - description: |- + description: | Total number of incoming bytes. diff --git a/test/packages/with-kind/kubernetes/data_stream/pod/manifest.yml b/test/packages/with-kind/kubernetes/data_stream/pod/manifest.yml index f9b3d340d8..b7944c3f1e 100644 --- a/test/packages/with-kind/kubernetes/data_stream/pod/manifest.yml +++ b/test/packages/with-kind/kubernetes/data_stream/pod/manifest.yml @@ -39,5 +39,33 @@ streams: required: true show_user: true default: none + - name: ssl.certificate_authorities + type: text + title: SSL Certificate Authorities + multi: true + required: false + show_user: false + - name: add_resource_metadata_config + type: yaml + title: Add node and namespace metadata + required: false + show_user: false + default: | + # add_resource_metadata: + # namespace: + # include_labels: ["namespacelabel1"] + # node: + # include_labels: ["nodelabel2"] + # include_annotations: ["nodeannotation1"] + # deployment: false + - name: processors + type: yaml + title: Processors + multi: false + required: false + show_user: false + description: > + Processors are used to reduce the number of fields in the exported event or to enhance the event with metadata. This executes in the agent before the events are shipped. See [Processors](https://www.elastic.co/guide/en/beats/filebeat/current/filtering-and-enhancing-data.html) for details. + title: Kubernetes Pod metrics description: Collect Kubernetes Pod metrics diff --git a/test/packages/with-kind/kubernetes/data_stream/pod/sample_event.json b/test/packages/with-kind/kubernetes/data_stream/pod/sample_event.json index 62e44029da..eba14a1827 100644 --- a/test/packages/with-kind/kubernetes/data_stream/pod/sample_event.json +++ b/test/packages/with-kind/kubernetes/data_stream/pod/sample_event.json @@ -1,125 +1,144 @@ { - "@timestamp": "2020-06-25T12:34:59.729Z", "kubernetes": { + "node": { + "uid": "57ccd748-c877-4be9-9b0e-568e9f205025", + "hostname": "kind-control-plane", + "name": "kind-control-plane", + "labels": { + "node_kubernetes_io/exclude-from-external-load-balancers": "", + "node-role_kubernetes_io/master": "", + "kubernetes_io/hostname": "kind-control-plane", + "node-role_kubernetes_io/control-plane": "", + "beta_kubernetes_io/os": "linux", + "kubernetes_io/arch": "amd64", + "kubernetes_io/os": "linux", + "beta_kubernetes_io/arch": "amd64" + } + }, "pod": { + "start_time": "2021-12-20T08:47:13Z", + "uid": "9a8de23e-5e64-462f-8576-f6591fb3f7b8", "memory": { "rss": { - "bytes": 7823360 + "bytes": 64204800 }, - "page_faults": 5742, - "major_page_faults": 0, + "major_page_faults": 792, "usage": { - "limit": { - "pct": 0.0008033509820466402 - }, - "bytes": 13508608, "node": { - "pct": 0.0008033509820466402 + "pct": 0.011827949440812145 + }, + "bytes": 117321728, + "limit": { + "pct": 0.011827949440812145 } }, "available": { "bytes": 0 }, + "page_faults": 27027, "working_set": { - "bytes": 8556544 - } - }, - "network": { - "rx": { - "bytes": 25671624, - "errors": 0 - }, - "tx": { - "errors": 0, - "bytes": 1092900259 + "bytes": 96862208, + "limit": { + "pct": 0.00976529512 + } } }, - "start_time": "2020-06-18T11:12:58Z", - "name": "kube-state-metrics-57cd6fdf9-hd959", - "uid": "a7c61334-dd52-4a12-bed5-4daee4c74139", + "ip": "172.20.0.2", + "name": "kube-controller-manager-kind-control-plane", "cpu": { "usage": { - "nanocores": 2811918, "node": { - "pct": 0.0007029795 + "pct": 0.001893070125 }, "limit": { - "pct": 0.0007029795 - } + "pct": 0.001893070125 + }, + "nanocores": 15144561 + } + }, + "network": { + "tx": { + "bytes": 0, + "errors": 0 + }, + "rx": { + "bytes": 0, + "errors": 0 } } }, "namespace": "kube-system", - "node": { - "name": "minikube" + "namespace_uid": "a4453575-518e-4a21-9909-34874f674177", + "namespace_labels": { + "kubernetes_io/metadata_name": "kube-system" + }, + "labels": { + "component": "kube-controller-manager", + "tier": "control-plane" } }, - "event": { - "duration": 20735189, - "dataset": "kubernetes.pod", - "module": "kubernetes" + "agent": { + "name": "kind-control-plane", + "id": "de42127b-4db8-4471-824e-a7b14f478663", + "ephemeral_id": "22ed892c-43bd-408a-9121-65e2f5b6a56e", + "type": "metricbeat", + "version": "8.1.0" }, - "ecs": { - "version": "1.5.0" + "elastic_agent": { + "id": "de42127b-4db8-4471-824e-a7b14f478663", + "version": "8.1.0", + "snapshot": true }, - "metricset": { - "period": 10000, - "name": "pod" + "orchestrator": { + "cluster": { + "name": "kind", + "url": "kind-control-plane:6443" + } + }, + "@timestamp": "2021-12-20T09:59:45.257Z", + "ecs": { + "version": "8.0.0" }, "service": { - "type": "kubernetes", - "address": "minikube:10250" + "address": "https://kind-control-plane:10250/stats/summary", + "type": "kubernetes" + }, + "data_stream": { + "namespace": "default", + "type": "metrics", + "dataset": "kubernetes.pod" }, "host": { - "name": "minikube", - "hostname": "minikube", - "architecture": "x86_64", + "hostname": "kind-control-plane", "os": { - "kernel": "4.19.81", + "kernel": "5.10.47-linuxkit", "codename": "Core", - "platform": "centos", - "version": "7 (Core)", + "name": "CentOS Linux", + "type": "linux", "family": "redhat", - "name": "CentOS Linux" + "version": "7 (Core)", + "platform": "centos" }, - "id": "b0e83d397c054b8a99a431072fe4617b", - "containerized": false, + "containerized": true, "ip": [ - "192.168.64.10", - "fe80::a883:2fff:fe7f:6b12", - "172.17.0.1", - "fe80::42:d4ff:fe8c:9493", - "fe80::2859:80ff:fe9e:fcd6", - "fe80::d83a:d9ff:fee9:7052", - "fe80::880a:b6ff:fe18:ba76", - "fe80::f447:faff:fe80:e88b", - "fe80::9cc3:ffff:fe95:e48e", - "fe80::6c1c:29ff:fe50:d40c", - "fe80::b4f3:11ff:fe60:14ed", - "fe80::20f2:2aff:fe96:1e7b", - "fe80::5434:baff:fede:5720", - "fe80::a878:91ff:fe29:81f7" + "10.244.0.1" ], + "name": "kind-control-plane", + "id": "85e35c2b5e1b39ba72393a6baf6ee7cd", "mac": [ - "aa:83:2f:7f:6b:12", - "02:42:d4:8c:94:93", - "2a:59:80:9e:fc:d6", - "da:3a:d9:e9:70:52", - "8a:0a:b6:18:ba:76", - "f6:47:fa:80:e8:8b", - "9e:c3:ff:95:e4:8e", - "6e:1c:29:50:d4:0c", - "b6:f3:11:60:14:ed", - "22:f2:2a:96:1e:7b", - "56:34:ba:de:57:20", - "aa:78:91:29:81:f7" - ] + "fe:ec:82:9f:29:19" + ], + "architecture": "x86_64" }, - "agent": { - "type": "metricbeat", - "version": "8.0.0", - "ephemeral_id": "b964a246-96c0-456a-a5c2-8c8b1040ecaf", - "id": "f7ec69f9-4997-4e76-b6c7-0c75206b727a", - "name": "minikube" + "metricset": { + "period": 10000, + "name": "pod" + }, + "event": { + "duration": 1041186, + "agent_id_status": "verified", + "ingested": "2021-12-20T09:59:45Z", + "module": "kubernetes", + "dataset": "kubernetes.pod" } } \ No newline at end of file diff --git a/test/packages/with-kind/kubernetes/data_stream/state_pod/_dev/test/system/test-default-config.yml b/test/packages/with-kind/kubernetes/data_stream/state_pod/_dev/test/system/test-default-config.yml new file mode 100644 index 0000000000..0f4bd620c0 --- /dev/null +++ b/test/packages/with-kind/kubernetes/data_stream/state_pod/_dev/test/system/test-default-config.yml @@ -0,0 +1,6 @@ +service: kubernetes +data_stream: + vars: + hosts: + # this is the DNS name of the k8s service for kube-state-metrics deployment + - http://kube-state-metrics:8080 diff --git a/test/packages/with-kind/kubernetes/data_stream/state_pod/agent/stream/stream.yml.hbs b/test/packages/with-kind/kubernetes/data_stream/state_pod/agent/stream/stream.yml.hbs new file mode 100644 index 0000000000..daa79726d9 --- /dev/null +++ b/test/packages/with-kind/kubernetes/data_stream/state_pod/agent/stream/stream.yml.hbs @@ -0,0 +1,33 @@ +metricsets: ["state_pod"] +add_metadata: {{add_metadata}} +{{#if add_resource_metadata_config}} +{{add_resource_metadata_config}} +{{/if}} +hosts: +{{#each hosts}} + - {{this}} +{{/each}} +period: {{period}} +{{#if leaderelection}} +condition: ${kubernetes_leaderelection.leader} == true +{{/if}} +{{#if node}} +node: {{node}} +{{/if}} +{{#if namespace}} +namespace: {{namespace}} +{{/if}} +{{#if bearer_token_file}} +bearer_token_file: {{bearer_token_file}} +{{/if}} +{{#if ssl.certificate_authorities}} +ssl.certificate_authorities: +{{#each ssl.certificate_authorities}} + - {{this}} +{{/each}} +{{/if}} + +{{#if processors}} +processors: +{{processors}} +{{/if}} \ No newline at end of file diff --git a/test/packages/with-kind/kubernetes/data_stream/state_pod/fields/agent.yml b/test/packages/with-kind/kubernetes/data_stream/state_pod/fields/agent.yml new file mode 100644 index 0000000000..da4e652c53 --- /dev/null +++ b/test/packages/with-kind/kubernetes/data_stream/state_pod/fields/agent.yml @@ -0,0 +1,198 @@ +- name: cloud + title: Cloud + group: 2 + description: Fields related to the cloud or infrastructure the events are coming from. + footnote: 'Examples: If Metricbeat is running on an EC2 host and fetches data from its host, the cloud info contains the data about this machine. If Metricbeat runs on a remote machine outside the cloud and fetches data from a service running in the cloud, the field contains cloud data from the machine the service is running on.' + type: group + fields: + - name: account.id + level: extended + type: keyword + ignore_above: 1024 + description: 'The cloud account or organization id used to identify different entities in a multi-tenant environment. + + Examples: AWS account id, Google Cloud ORG Id, or other unique identifier.' + example: 666777888999 + - name: availability_zone + level: extended + type: keyword + ignore_above: 1024 + description: Availability zone in which this host is running. + example: us-east-1c + - name: instance.id + level: extended + type: keyword + ignore_above: 1024 + description: Instance ID of the host machine. + example: i-1234567890abcdef0 + - name: instance.name + level: extended + type: keyword + ignore_above: 1024 + description: Instance name of the host machine. + - name: machine.type + level: extended + type: keyword + ignore_above: 1024 + description: Machine type of the host machine. + example: t2.medium + - name: provider + level: extended + type: keyword + ignore_above: 1024 + description: Name of the cloud provider. Example values are aws, azure, gcp, or digitalocean. + example: aws + - name: region + level: extended + type: keyword + ignore_above: 1024 + description: Region in which this host is running. + example: us-east-1 + - name: project.id + type: keyword + description: Name of the project in Google Cloud. + - name: image.id + type: keyword + description: Image ID for the cloud instance. +- name: container + title: Container + group: 2 + description: 'Container fields are used for meta information about the specific container that is the source of information. + + These fields help correlate data based containers from any runtime.' + type: group + fields: + - name: id + level: core + type: keyword + ignore_above: 1024 + description: Unique container id. + - name: image.name + level: extended + type: keyword + ignore_above: 1024 + description: Name of the image the container was built on. + - name: labels + level: extended + type: object + object_type: keyword + description: Image labels. + - name: name + level: extended + type: keyword + ignore_above: 1024 + description: Container name. +- name: host + title: Host + group: 2 + description: 'A host is defined as a general computing instance. + + ECS host.* fields should be populated with details about the host on which the event happened, or from which the measurement was taken. Host types include hardware, virtual machines, Docker containers, and Kubernetes nodes.' + type: group + fields: + - name: architecture + level: core + type: keyword + ignore_above: 1024 + description: Operating system architecture. + example: x86_64 + - name: domain + level: extended + type: keyword + ignore_above: 1024 + description: 'Name of the domain of which the host is a member. + + For example, on Windows this could be the host''s Active Directory domain or NetBIOS domain name. For Linux this could be the domain of the host''s LDAP provider.' + example: CONTOSO + default_field: false + - name: hostname + level: core + type: keyword + ignore_above: 1024 + description: 'Hostname of the host. + + It normally contains what the `hostname` command returns on the host machine.' + - name: id + level: core + type: keyword + ignore_above: 1024 + description: 'Unique host id. + + As hostname is not always unique, use values that are meaningful in your environment. + + Example: The current usage of `beat.name`.' + - name: ip + level: core + type: ip + description: Host ip addresses. + - name: mac + level: core + type: keyword + ignore_above: 1024 + description: Host mac addresses. + - name: name + level: core + type: keyword + ignore_above: 1024 + description: 'Name of the host. + + It can contain what `hostname` returns on Unix systems, the fully qualified domain name, or a name specified by the user. The sender decides which value to use.' + - name: os.family + level: extended + type: keyword + ignore_above: 1024 + description: OS family (such as redhat, debian, freebsd, windows). + example: debian + - name: os.kernel + level: extended + type: keyword + ignore_above: 1024 + description: Operating system kernel version as a raw string. + example: 4.4.0-112-generic + - name: os.name + level: extended + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + default_field: false + description: Operating system name, without the version. + example: Mac OS X + - name: os.platform + level: extended + type: keyword + ignore_above: 1024 + description: Operating system platform (such centos, ubuntu, windows). + example: darwin + - name: os.version + level: extended + type: keyword + ignore_above: 1024 + description: Operating system version as a raw string. + example: 10.14.1 + - name: type + level: core + type: keyword + ignore_above: 1024 + description: 'Type of host. + + For Cloud providers this can be the machine type like `t2.medium`. If vm, this could be the container, for example, or other information meaningful in your environment.' + - name: containerized + type: boolean + description: > + If the host is a container. + + - name: os.build + type: keyword + example: "18D109" + description: > + OS build information. + + - name: os.codename + type: keyword + example: "stretch" + description: > + OS codename, if any. + diff --git a/test/packages/with-kind/kubernetes/data_stream/state_pod/fields/base-fields.yml b/test/packages/with-kind/kubernetes/data_stream/state_pod/fields/base-fields.yml new file mode 100644 index 0000000000..2dd51e1638 --- /dev/null +++ b/test/packages/with-kind/kubernetes/data_stream/state_pod/fields/base-fields.yml @@ -0,0 +1,146 @@ +- name: data_stream.type + type: constant_keyword + description: Data stream type. +- name: data_stream.dataset + type: constant_keyword + description: Data stream dataset. +- name: data_stream.namespace + type: constant_keyword + description: Data stream namespace. +- name: '@timestamp' + type: date + description: Event timestamp. +- name: kubernetes + type: group + fields: + - name: pod.name + dimension: true + type: keyword + description: > + Kubernetes pod name + + - name: pod.uid + dimension: true + type: keyword + description: > + Kubernetes pod UID + + - name: pod.ip + type: ip + description: > + Kubernetes pod IP + + - name: namespace + dimension: true + type: keyword + description: > + Kubernetes namespace + + - name: node.name + type: keyword + description: > + Kubernetes node name + + - name: node.hostname + type: keyword + description: > + Kubernetes hostname as reported by the node’s kernel + + - name: labels.* + type: object + object_type: keyword + object_type_mapping_type: "*" + description: > + Kubernetes labels map + + - name: annotations.* + type: object + object_type: keyword + object_type_mapping_type: "*" + description: > + Kubernetes annotations map + + - name: node.labels.* + type: object + object_type: keyword + object_type_mapping_type: "*" + description: > + Kubernetes node labels map + + - name: node.annotations.* + type: object + object_type: keyword + object_type_mapping_type: "*" + description: > + Kubernetes node annotations map + + - name: node.uid + type: keyword + description: > + Kubernetes node UID + + - name: namespace_uid + type: keyword + description: > + Kubernetes namespace UID + + - name: namespace_labels.* + type: object + object_type: keyword + object_type_mapping_type: "*" + description: > + Kubernetes namespace labels map + + - name: namespace_annotations.* + type: object + object_type: keyword + object_type_mapping_type: "*" + description: > + Kubernetes namespace annotations map + + - name: selectors.* + type: object + object_type: keyword + object_type_mapping_type: "*" + description: > + Kubernetes Service selectors map + + - name: replicaset.name + type: keyword + description: > + Kubernetes replicaset name + + - name: deployment.name + type: keyword + description: > + Kubernetes deployment name + + - name: statefulset.name + type: keyword + description: > + Kubernetes statefulset name + + - name: daemonset.name + type: keyword + description: > + Kubernetes daemonset name + + - name: job.name + type: keyword + description: > + Name of the Job to which the Pod belongs + + - name: cronjob.name + type: keyword + description: > + Name of the CronJob to which the Pod belongs + + - name: container.name + type: keyword + description: > + Kubernetes container name + + - name: container.image + type: keyword + description: >- + Kubernetes container image diff --git a/test/packages/with-kind/kubernetes/data_stream/state_pod/fields/ecs.yml b/test/packages/with-kind/kubernetes/data_stream/state_pod/fields/ecs.yml new file mode 100644 index 0000000000..31cb2817b8 --- /dev/null +++ b/test/packages/with-kind/kubernetes/data_stream/state_pod/fields/ecs.yml @@ -0,0 +1,12 @@ +- external: ecs + name: ecs.version +- external: ecs + name: service.address +- external: ecs + name: service.type +- external: ecs + name: container.runtime +- external: ecs + name: orchestrator.cluster.name +- external: ecs + name: orchestrator.cluster.url diff --git a/test/packages/with-kind/kubernetes/data_stream/state_pod/fields/fields.yml b/test/packages/with-kind/kubernetes/data_stream/state_pod/fields/fields.yml new file mode 100644 index 0000000000..67d4cb4b22 --- /dev/null +++ b/test/packages/with-kind/kubernetes/data_stream/state_pod/fields/fields.yml @@ -0,0 +1,26 @@ +- name: kubernetes.pod + type: group + fields: + - name: ip + type: ip + description: | + Kubernetes pod IP + - name: host_ip + type: ip + description: | + Kubernetes pod host IP + - name: status + type: group + fields: + - name: phase + type: keyword + description: | + Kubernetes pod phase (Running, Pending...) + - name: ready + type: keyword + description: | + Kubernetes pod ready status (true, false or unknown) + - name: scheduled + type: keyword + description: | + Kubernetes pod scheduled status (true, false, unknown) diff --git a/test/packages/with-kind/kubernetes/data_stream/state_pod/manifest.yml b/test/packages/with-kind/kubernetes/data_stream/state_pod/manifest.yml new file mode 100644 index 0000000000..952ac9440e --- /dev/null +++ b/test/packages/with-kind/kubernetes/data_stream/state_pod/manifest.yml @@ -0,0 +1,84 @@ +title: Kubernetes Pod metrics +type: metrics +streams: + - input: kubernetes/metrics + enabled: true + vars: + - name: add_metadata + type: bool + title: Add Metadata + multi: false + required: true + show_user: true + default: true + - name: hosts + type: text + title: Hosts + multi: true + required: true + show_user: true + default: + - kube-state-metrics:8080 + - name: leaderelection + type: bool + title: Leader Election + multi: false + required: true + show_user: true + default: true + - name: period + type: text + title: Period + multi: false + required: true + show_user: true + default: 10s + - name: node + type: text + title: Node to watch resources from for metadata + multi: false + required: false + show_user: false + - name: namespace + type: text + title: Namespace to watch resources from for metadata + multi: false + required: false + show_user: false + - name: bearer_token_file + type: text + title: Bearer Token File + multi: false + required: false + show_user: false + default: /var/run/secrets/kubernetes.io/serviceaccount/token + - name: ssl.certificate_authorities + type: text + title: SSL Certificate Authorities + multi: true + required: false + show_user: false + - name: add_resource_metadata_config + type: yaml + title: Add node and namespace metadata + required: false + show_user: false + default: | + # add_resource_metadata: + # namespace: + # include_labels: ["namespacelabel1"] + # node: + # include_labels: ["nodelabel2"] + # include_annotations: ["nodeannotation1"] + # deployment: false + - name: processors + type: yaml + title: Processors + multi: false + required: false + show_user: false + description: > + Processors are used to reduce the number of fields in the exported event or to enhance the event with metadata. This executes in the agent before the events are shipped. See [Processors](https://www.elastic.co/guide/en/beats/filebeat/current/filtering-and-enhancing-data.html) for details. + + title: Kubernetes Pod metrics + description: Collect Kubernetes Pod metrics from kube_state_metrics diff --git a/test/packages/with-kind/kubernetes/data_stream/state_pod/sample_event.json b/test/packages/with-kind/kubernetes/data_stream/state_pod/sample_event.json new file mode 100644 index 0000000000..d01591af9d --- /dev/null +++ b/test/packages/with-kind/kubernetes/data_stream/state_pod/sample_event.json @@ -0,0 +1,107 @@ +{ + "kubernetes": { + "node": { + "uid": "57ccd748-c877-4be9-9b0e-568e9f205025", + "hostname": "kind-control-plane", + "name": "kind-control-plane", + "labels": { + "node_kubernetes_io/exclude-from-external-load-balancers": "", + "node-role_kubernetes_io/master": "", + "kubernetes_io/hostname": "kind-control-plane", + "node-role_kubernetes_io/control-plane": "", + "beta_kubernetes_io/os": "linux", + "kubernetes_io/arch": "amd64", + "kubernetes_io/os": "linux", + "beta_kubernetes_io/arch": "amd64" + } + }, + "pod": { + "uid": "d06d59c2-929f-4b13-bc7d-c2492200ce07", + "host_ip": "172.20.0.2", + "ip": "172.20.0.2", + "name": "elastic-agent-h2mgj", + "status": { + "phase": "running", + "ready": "true", + "scheduled": "true" + } + }, + "namespace": "kube-system", + "daemonset": { + "name": "elastic-agent" + }, + "namespace_uid": "a4453575-518e-4a21-9909-34874f674177", + "namespace_labels": { + "kubernetes_io/metadata_name": "kube-system" + }, + "labels": { + "app": "elastic-agent", + "controller-revision-hash": "57c5d7c56f", + "pod-template-generation": "3" + } + }, + "agent": { + "name": "kind-control-plane", + "id": "de42127b-4db8-4471-824e-a7b14f478663", + "type": "metricbeat", + "ephemeral_id": "22ed892c-43bd-408a-9121-65e2f5b6a56e", + "version": "8.1.0" + }, + "elastic_agent": { + "id": "de42127b-4db8-4471-824e-a7b14f478663", + "version": "8.1.0", + "snapshot": true + }, + "orchestrator": { + "cluster": { + "name": "kind", + "url": "kind-control-plane:6443" + } + }, + "@timestamp": "2021-12-20T10:03:24.643Z", + "ecs": { + "version": "8.0.0" + }, + "data_stream": { + "namespace": "default", + "type": "metrics", + "dataset": "kubernetes.state_pod" + }, + "service": { + "address": "http://kube-state-metrics:8080/metrics", + "type": "kubernetes" + }, + "host": { + "hostname": "kind-control-plane", + "os": { + "kernel": "5.10.47-linuxkit", + "codename": "Core", + "name": "CentOS Linux", + "family": "redhat", + "type": "linux", + "version": "7 (Core)", + "platform": "centos" + }, + "containerized": true, + "ip": [ + "10.244.0.1" + ], + "name": "kind-control-plane", + "id": "85e35c2b5e1b39ba72393a6baf6ee7cd", + "mac": [ + "fe:ec:82:9f:29:19" + ], + "architecture": "x86_64" + }, + "metricset": { + "period": 10000, + "name": "state_pod" + }, + "event": { + "duration": 736951, + "agent_id_status": "verified", + "ingested": "2021-12-20T10:03:25Z", + "module": "kubernetes", + "dataset": "kubernetes.state_pod" + } +} \ No newline at end of file From 69f1415f30248afd813ece6fb7ff79c9f95e43af Mon Sep 17 00:00:00 2001 From: constanca-m Date: Tue, 7 Feb 2023 10:59:51 +0100 Subject: [PATCH 10/15] Update manifest. --- .../with-kind/kubernetes/manifest.yml | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/test/packages/with-kind/kubernetes/manifest.yml b/test/packages/with-kind/kubernetes/manifest.yml index e72a1928b5..b73a8b7cfc 100644 --- a/test/packages/with-kind/kubernetes/manifest.yml +++ b/test/packages/with-kind/kubernetes/manifest.yml @@ -42,5 +42,25 @@ policy_templates: title: Metricbeat Kubernetes Overview size: 1896x961 type: image/png + - name: kube-state-metrics + title: Kube-state-metrics + description: Collect container metrics from Kubernetes Kube-state-metrics with Elastic Agent. + data_streams: + - state_pod + inputs: + - type: kubernetes/metrics + title: Collect Kubernetes metrics from kube-state-metrics + description: Collecting metrics from kube-state-metrics (container, cronjob, deployment, daemonset, node, persistentvolume, persistentvolumeclaim, pod, replicaset, resourcequota, service, statefulset, storageclass) + input_group: metrics + icons: + - src: /img/logo_kubernetes.svg + title: Logo Kubernetes + size: 32x32 + type: image/svg+xml + screenshots: + - src: /img/metricbeat_kubernetes_overview.png + title: Metricbeat Kubernetes Overview + size: 1896x961 + type: image/png owner: github: elastic/integrations From 092461980952f7aff354eab8f27772ee757dba57 Mon Sep 17 00:00:00 2001 From: constanca-m Date: Wed, 8 Feb 2023 09:12:56 +0100 Subject: [PATCH 11/15] Fix references. --- .../runners/system/servicedeployer/kubernetes.go | 13 +++++++++---- .../kubernetes/_dev/deploy/k8s/kustomization.yaml | 2 +- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/internal/testrunner/runners/system/servicedeployer/kubernetes.go b/internal/testrunner/runners/system/servicedeployer/kubernetes.go index 0eb9f86629..c792dd3187 100644 --- a/internal/testrunner/runners/system/servicedeployer/kubernetes.go +++ b/internal/testrunner/runners/system/servicedeployer/kubernetes.go @@ -23,6 +23,11 @@ import ( "github.com/elastic/elastic-package/internal/stack" ) +const ( + kustomizationFile = "kustomization.yaml" + emptyFile = ".empty" +) + // KubernetesServiceDeployer is responsible for deploying resources in the Kubernetes cluster. type KubernetesServiceDeployer struct { definitionsPath string @@ -137,11 +142,11 @@ func containsKustomization(definitionsPath string) (bool, error) { return false, errors.Wrapf(err, "can't read definitions directory (path: %s)", definitionsPath) } // check if kustomization.yaml exists - if _, err := os.Stat(filepath.Join(definitionsPath, "kustomization.yaml")); err != nil { + if _, err := os.Stat(filepath.Join(definitionsPath, kustomizationFile)); err != nil { // if it does not exist, then the .empty file needs to be present - if _, err := os.Stat(filepath.Join(definitionsPath, ".empty")); err != nil { - return false, errors.Errorf("kustomization.yaml file is missing (path: %s). Add one or create an .empty file"+ - " if no custom definitions are required.", definitionsPath) + if _, err := os.Stat(filepath.Join(definitionsPath, emptyFile)); err != nil { + return false, errors.Errorf("%s file is missing (path: %s). Add one or create an %s file"+ + " if no custom definitions are required.", kustomizationFile, definitionsPath, emptyFile) } return false, nil } diff --git a/test/packages/with-kind/kubernetes/_dev/deploy/k8s/kustomization.yaml b/test/packages/with-kind/kubernetes/_dev/deploy/k8s/kustomization.yaml index 1117f584af..ff8b061680 100644 --- a/test/packages/with-kind/kubernetes/_dev/deploy/k8s/kustomization.yaml +++ b/test/packages/with-kind/kubernetes/_dev/deploy/k8s/kustomization.yaml @@ -7,4 +7,4 @@ resources: - configmap.yaml - rq.yaml - ss.yaml - - github.com/kubernetes/kube-state-metrics?ref=main + - github.com/kubernetes/kube-state-metrics?ref=abe3fd3184e16893b5a47196f90a94ed13e1b04d From 1fc8992b266a5f26e8ee76dba0e1231952067b17 Mon Sep 17 00:00:00 2001 From: constanca-m Date: Wed, 8 Feb 2023 11:04:55 +0100 Subject: [PATCH 12/15] Make -f possible along with -k --- docs/howto/system_testing.md | 6 +- internal/kubectl/kubectl.go | 14 +- internal/kubectl/kubectl_apply.go | 2 +- internal/kubectl/kubectl_delete.go | 2 +- .../system/servicedeployer/kubernetes.go | 85 +++++--- .../_dev/deploy/k8s/cluster-role-binding.yaml | 16 ++ .../_dev/deploy/k8s/cluster-role.yaml | 121 +++++++++++ .../_dev/deploy/k8s/cronjob.yaml | 21 ++ .../_dev/deploy/k8s/deployment.yaml | 52 +++++ .../_dev/deploy/k8s/service-account.yaml | 10 + .../_dev/deploy/k8s/service.yaml | 20 ++ .../_dev/test/system/test-default-config.yml | 6 + .../state_cronjob/agent/stream/stream.yml.hbs | 30 +++ .../state_cronjob/fields/agent.yml | 198 ++++++++++++++++++ .../state_cronjob/fields/base-fields.yml | 106 ++++++++++ .../data_stream/state_cronjob/fields/ecs.yml | 10 + .../state_cronjob/fields/fields.yml | 42 ++++ .../data_stream/state_cronjob/manifest.yml | 71 +++++++ .../state_cronjob/sample_event.json | 126 +++++++++++ .../with-kind/kubernetes/manifest.yml | 1 + 20 files changed, 898 insertions(+), 41 deletions(-) create mode 100644 test/packages/with-kind/kubernetes/data_stream/state_cronjob/_dev/deploy/k8s/cluster-role-binding.yaml create mode 100644 test/packages/with-kind/kubernetes/data_stream/state_cronjob/_dev/deploy/k8s/cluster-role.yaml create mode 100644 test/packages/with-kind/kubernetes/data_stream/state_cronjob/_dev/deploy/k8s/cronjob.yaml create mode 100644 test/packages/with-kind/kubernetes/data_stream/state_cronjob/_dev/deploy/k8s/deployment.yaml create mode 100644 test/packages/with-kind/kubernetes/data_stream/state_cronjob/_dev/deploy/k8s/service-account.yaml create mode 100644 test/packages/with-kind/kubernetes/data_stream/state_cronjob/_dev/deploy/k8s/service.yaml create mode 100644 test/packages/with-kind/kubernetes/data_stream/state_cronjob/_dev/test/system/test-default-config.yml create mode 100644 test/packages/with-kind/kubernetes/data_stream/state_cronjob/agent/stream/stream.yml.hbs create mode 100644 test/packages/with-kind/kubernetes/data_stream/state_cronjob/fields/agent.yml create mode 100644 test/packages/with-kind/kubernetes/data_stream/state_cronjob/fields/base-fields.yml create mode 100644 test/packages/with-kind/kubernetes/data_stream/state_cronjob/fields/ecs.yml create mode 100644 test/packages/with-kind/kubernetes/data_stream/state_cronjob/fields/fields.yml create mode 100644 test/packages/with-kind/kubernetes/data_stream/state_cronjob/manifest.yml create mode 100644 test/packages/with-kind/kubernetes/data_stream/state_cronjob/sample_event.json diff --git a/docs/howto/system_testing.md b/docs/howto/system_testing.md index d2168b5385..f4d0bd38a8 100644 --- a/docs/howto/system_testing.md +++ b/docs/howto/system_testing.md @@ -302,9 +302,9 @@ There are some specific environment variables that should be leveraged to overco ### Kubernetes service deployer -The Kubernetes service deployer requires the `_dev/deploy/k8s` directory to be present. -It needs to include either a `kustomization.yaml` file or an `.empty` file. The first is needed to ensure the deployment of each resource, -while the second is required if no custom resources are needed. +The Kubernetes service deployer requires the `_dev/deploy/k8s` directory to be present. It can include additional `*.yaml` files to deploy +custom applications in the Kubernetes cluster (e.g. Nginx deployment). If no resource definitions (`*.yaml` files ) are needed, +the `_dev/deploy/k8s` directory must contain an `.empty` file (to preserve the `k8s` directory under version control). The Kubernetes service deployer needs [kind](https://kind.sigs.k8s.io/) to be installed and the cluster to be up and running: ```bash diff --git a/internal/kubectl/kubectl.go b/internal/kubectl/kubectl.go index 48402da5dd..2dd7b55f7e 100644 --- a/internal/kubectl/kubectl.go +++ b/internal/kubectl/kubectl.go @@ -6,7 +6,9 @@ package kubectl import ( "bytes" + "github.com/elastic/elastic-package/internal/testrunner/runners/system/servicedeployer" "os/exec" + "path/filepath" "github.com/pkg/errors" @@ -27,8 +29,16 @@ func CurrentContext() (string, error) { return string(bytes.TrimSpace(output)), nil } -func modifyKubernetesResources(action string, definitionsPath string) ([]byte, error) { - args := []string{action, "-k", definitionsPath} +func modifyKubernetesResources(action string, definitionPaths []string) ([]byte, error) { + args := []string{action} + for _, definitionPath := range definitionPaths { + if filepath.Base(definitionPath) == servicedeployer.KustomizationFile { + args = []string{action, "-k", definitionPath} + break + } + args = append(args, "-f") + args = append(args, definitionPath) + } if action != "delete" { // "delete" supports only '-o name' args = append(args, "-o", "yaml") diff --git a/internal/kubectl/kubectl_apply.go b/internal/kubectl/kubectl_apply.go index 4214a2fabf..a58c184907 100644 --- a/internal/kubectl/kubectl_apply.go +++ b/internal/kubectl/kubectl_apply.go @@ -70,7 +70,7 @@ func (c condition) String() string { } // Apply function adds resources to the Kubernetes cluster based on provided definitions. -func Apply(definitionsPath string) error { +func Apply(definitionsPath []string) error { logger.Debugf("Apply Kubernetes custom definitions") out, err := modifyKubernetesResources("apply", definitionsPath) if err != nil { diff --git a/internal/kubectl/kubectl_delete.go b/internal/kubectl/kubectl_delete.go index 1fb57fa20f..2116d78cb1 100644 --- a/internal/kubectl/kubectl_delete.go +++ b/internal/kubectl/kubectl_delete.go @@ -5,7 +5,7 @@ package kubectl // Delete function removes resources from the Kubernetes cluster based on provided definitions. -func Delete(definitionsPath string) error { +func Delete(definitionsPath []string) error { _, err := modifyKubernetesResources("delete", definitionsPath) return err } diff --git a/internal/testrunner/runners/system/servicedeployer/kubernetes.go b/internal/testrunner/runners/system/servicedeployer/kubernetes.go index c792dd3187..af4fadd6a6 100644 --- a/internal/testrunner/runners/system/servicedeployer/kubernetes.go +++ b/internal/testrunner/runners/system/servicedeployer/kubernetes.go @@ -23,38 +23,35 @@ import ( "github.com/elastic/elastic-package/internal/stack" ) -const ( - kustomizationFile = "kustomization.yaml" - emptyFile = ".empty" -) +const KustomizationFile = "kustomization.yaml" // KubernetesServiceDeployer is responsible for deploying resources in the Kubernetes cluster. type KubernetesServiceDeployer struct { - definitionsPath string + definitionsDir string } type kubernetesDeployedService struct { ctxt ServiceContext - definitionsPath string + definitionsDir string } func (s kubernetesDeployedService) TearDown() error { - logger.Debugf("uninstall custom Kubernetes definitions (directory: %s)", s.definitionsPath) + logger.Debugf("uninstall custom Kubernetes definitions (directory: %s)", s.definitionsDir) - deleteResources, err := containsKustomization(s.definitionsPath) + definitionPaths, err := findKubernetesDefinitions(s.definitionsDir) if err != nil { - return errors.Wrapf(err, "can't find Kubernetes definitions in given directory (path: %s)", s.definitionsPath) + return errors.Wrapf(err, "can't find Kubernetes definitions in given directory (path: %s)", s.definitionsDir) } - if !deleteResources { - logger.Debugf("no custom definitions found (directory: %s). Nothing will be uninstalled.", s.definitionsPath) + if len(definitionPaths) == 0 { + logger.Debugf("no custom definitions found (directory: %s). Nothing will be uninstalled.", s.definitionsDir) return nil } - err = kubectl.Delete(s.definitionsPath) + err = kubectl.Delete(definitionPaths) if err != nil { - return errors.Wrapf(err, "can't uninstall Kubernetes resources (path: %s)", s.definitionsPath) + return errors.Wrapf(err, "can't uninstall Kubernetes resources (path: %s)", s.definitionsDir) } return nil } @@ -77,7 +74,7 @@ var _ DeployedService = new(kubernetesDeployedService) // NewKubernetesServiceDeployer function creates a new instance of KubernetesServiceDeployer. func NewKubernetesServiceDeployer(definitionsPath string) (*KubernetesServiceDeployer, error) { return &KubernetesServiceDeployer{ - definitionsPath: definitionsPath, + definitionsDir: definitionsPath, }, nil } @@ -110,25 +107,25 @@ func (ksd KubernetesServiceDeployer) SetUp(ctxt ServiceContext) (DeployedService // to deploy Agent Pod. Because of this, hostname inside pod will be equal to the name of the k8s host. ctxt.Agent.Host.NamePrefix = "kind-control-plane" return &kubernetesDeployedService{ - ctxt: ctxt, - definitionsPath: ksd.definitionsPath, + ctxt: ctxt, + definitionsDir: ksd.definitionsDir, }, nil } func (ksd KubernetesServiceDeployer) installCustomDefinitions() error { - logger.Debugf("install custom Kubernetes definitions (directory: %s)", ksd.definitionsPath) + logger.Debugf("install custom Kubernetes definitions (directory: %s)", ksd.definitionsDir) - installResources, err := containsKustomization(ksd.definitionsPath) + definitionPaths, err := findKubernetesDefinitions(ksd.definitionsDir) if err != nil { - return errors.Wrapf(err, "can't find Kubernetes definitions in given path: %s", ksd.definitionsPath) + return errors.Wrapf(err, "can't find Kubernetes definitions in given path: %s", ksd.definitionsDir) } - if !installResources { - logger.Debugf("no custom definitions found (path: %s). Nothing else will be installed.", ksd.definitionsPath) + if len(definitionPaths) == 0 { + logger.Debugf("no custom definitions found (path: %s). Nothing else will be installed.", ksd.definitionsDir) return nil } - err = kubectl.Apply(ksd.definitionsPath) + err = kubectl.Apply(definitionPaths) if err != nil { return errors.Wrap(err, "can't install custom definitions") } @@ -137,20 +134,40 @@ func (ksd KubernetesServiceDeployer) installCustomDefinitions() error { var _ ServiceDeployer = new(KubernetesServiceDeployer) -func containsKustomization(definitionsPath string) (bool, error) { - if _, err := os.Stat(definitionsPath); err != nil { - return false, errors.Wrapf(err, "can't read definitions directory (path: %s)", definitionsPath) +func findKubernetesDefinitions(definitionsDir string) ([]string, error) { + /* + files, err := filepath.Glob(filepath.Join(definitionsDir, "*.yaml")) + if err != nil { + return nil, errors.Wrapf(err, "can't read definitions directory (path: %s)", definitionsDir) + var definitionPaths []string + definitionPaths = append(definitionPaths, files...) + return definitionPaths, nil + + */ + + files, err := filepath.Glob(filepath.Join(definitionsDir, "*.yaml")) + if err != nil { + return nil, errors.Wrapf(err, "can't read definitions directory (path: %s)", definitionsDir) } - // check if kustomization.yaml exists - if _, err := os.Stat(filepath.Join(definitionsPath, kustomizationFile)); err != nil { - // if it does not exist, then the .empty file needs to be present - if _, err := os.Stat(filepath.Join(definitionsPath, emptyFile)); err != nil { - return false, errors.Errorf("%s file is missing (path: %s). Add one or create an %s file"+ - " if no custom definitions are required.", kustomizationFile, definitionsPath, emptyFile) + + var definitionPaths []string + definitionPaths = append(definitionPaths, files...) + return definitionPaths, nil + + /* + if _, err := os.Stat(definitionsDir); err != nil { + return false, errors.Wrapf(err, "can't read definitions directory (path: %s)", definitionsDir) } - return false, nil - } - return true, nil + // check if kustomization.yaml exists + if _, err := os.Stat(filepath.Join(definitionsDir, kustomizationFile)); err != nil { + // if it does not exist, then the .empty file needs to be present + if _, err := os.Stat(filepath.Join(definitionsDir, emptyFile)); err != nil { + return false, errors.Errorf("%s file is missing (path: %s). Add one or create an %s file"+ + " if no custom definitions are required.", kustomizationFile, definitionsDir, emptyFile) + } + return false, nil + } + return true, nil*/ } func installElasticAgentInCluster() error { diff --git a/test/packages/with-kind/kubernetes/data_stream/state_cronjob/_dev/deploy/k8s/cluster-role-binding.yaml b/test/packages/with-kind/kubernetes/data_stream/state_cronjob/_dev/deploy/k8s/cluster-role-binding.yaml new file mode 100644 index 0000000000..7cf86ba834 --- /dev/null +++ b/test/packages/with-kind/kubernetes/data_stream/state_cronjob/_dev/deploy/k8s/cluster-role-binding.yaml @@ -0,0 +1,16 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + app.kubernetes.io/component: exporter + app.kubernetes.io/name: kube-state-metrics + app.kubernetes.io/version: 2.7.0 + name: kube-state-metrics +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: kube-state-metrics +subjects: + - kind: ServiceAccount + name: kube-state-metrics + namespace: kube-system diff --git a/test/packages/with-kind/kubernetes/data_stream/state_cronjob/_dev/deploy/k8s/cluster-role.yaml b/test/packages/with-kind/kubernetes/data_stream/state_cronjob/_dev/deploy/k8s/cluster-role.yaml new file mode 100644 index 0000000000..c03e78b4b5 --- /dev/null +++ b/test/packages/with-kind/kubernetes/data_stream/state_cronjob/_dev/deploy/k8s/cluster-role.yaml @@ -0,0 +1,121 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/component: exporter + app.kubernetes.io/name: kube-state-metrics + app.kubernetes.io/version: 2.7.0 + name: kube-state-metrics +rules: + - apiGroups: + - "" + resources: + - configmaps + - secrets + - nodes + - pods + - services + - serviceaccounts + - resourcequotas + - replicationcontrollers + - limitranges + - persistentvolumeclaims + - persistentvolumes + - namespaces + - endpoints + verbs: + - list + - watch + - apiGroups: + - apps + resources: + - statefulsets + - daemonsets + - deployments + - replicasets + verbs: + - list + - watch + - apiGroups: + - batch + resources: + - cronjobs + - jobs + verbs: + - list + - watch + - apiGroups: + - autoscaling + resources: + - horizontalpodautoscalers + verbs: + - list + - watch + - apiGroups: + - authentication.k8s.io + resources: + - tokenreviews + verbs: + - create + - apiGroups: + - authorization.k8s.io + resources: + - subjectaccessreviews + verbs: + - create + - apiGroups: + - policy + resources: + - poddisruptionbudgets + verbs: + - list + - watch + - apiGroups: + - certificates.k8s.io + resources: + - certificatesigningrequests + verbs: + - list + - watch + - apiGroups: + - storage.k8s.io + resources: + - storageclasses + - volumeattachments + verbs: + - list + - watch + - apiGroups: + - admissionregistration.k8s.io + resources: + - mutatingwebhookconfigurations + - validatingwebhookconfigurations + verbs: + - list + - watch + - apiGroups: + - networking.k8s.io + resources: + - networkpolicies + - ingressclasses + - ingresses + verbs: + - list + - watch + - apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - list + - watch + - apiGroups: + - rbac.authorization.k8s.io + resources: + - clusterrolebindings + - clusterroles + - rolebindings + - roles + verbs: + - list + - watch diff --git a/test/packages/with-kind/kubernetes/data_stream/state_cronjob/_dev/deploy/k8s/cronjob.yaml b/test/packages/with-kind/kubernetes/data_stream/state_cronjob/_dev/deploy/k8s/cronjob.yaml new file mode 100644 index 0000000000..d9af61dc23 --- /dev/null +++ b/test/packages/with-kind/kubernetes/data_stream/state_cronjob/_dev/deploy/k8s/cronjob.yaml @@ -0,0 +1,21 @@ +apiVersion: batch/v1 +kind: CronJob +metadata: + name: hello + labels: + k8s-app: myjob +spec: + schedule: "*/1 * * * *" + jobTemplate: + spec: + template: + spec: + containers: + - name: hello + image: busybox + imagePullPolicy: IfNotPresent + command: + - /bin/sh + - -c + - date; echo Hello from the Kubernetes cluster + restartPolicy: OnFailure diff --git a/test/packages/with-kind/kubernetes/data_stream/state_cronjob/_dev/deploy/k8s/deployment.yaml b/test/packages/with-kind/kubernetes/data_stream/state_cronjob/_dev/deploy/k8s/deployment.yaml new file mode 100644 index 0000000000..e28025a4f9 --- /dev/null +++ b/test/packages/with-kind/kubernetes/data_stream/state_cronjob/_dev/deploy/k8s/deployment.yaml @@ -0,0 +1,52 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app.kubernetes.io/component: exporter + app.kubernetes.io/name: kube-state-metrics + app.kubernetes.io/version: 2.7.0 + name: kube-state-metrics + namespace: kube-system +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: kube-state-metrics + template: + metadata: + labels: + app.kubernetes.io/component: exporter + app.kubernetes.io/name: kube-state-metrics + app.kubernetes.io/version: 2.7.0 + spec: + automountServiceAccountToken: true + containers: + - image: registry.k8s.io/kube-state-metrics/kube-state-metrics:v2.7.0 + livenessProbe: + httpGet: + path: /healthz + port: 8080 + initialDelaySeconds: 5 + timeoutSeconds: 5 + name: kube-state-metrics + ports: + - containerPort: 8080 + name: http-metrics + - containerPort: 8081 + name: telemetry + readinessProbe: + httpGet: + path: / + port: 8081 + initialDelaySeconds: 5 + timeoutSeconds: 5 + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + runAsUser: 65534 + nodeSelector: + kubernetes.io/os: linux + serviceAccountName: kube-state-metrics diff --git a/test/packages/with-kind/kubernetes/data_stream/state_cronjob/_dev/deploy/k8s/service-account.yaml b/test/packages/with-kind/kubernetes/data_stream/state_cronjob/_dev/deploy/k8s/service-account.yaml new file mode 100644 index 0000000000..8d6dc8e84d --- /dev/null +++ b/test/packages/with-kind/kubernetes/data_stream/state_cronjob/_dev/deploy/k8s/service-account.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +automountServiceAccountToken: false +kind: ServiceAccount +metadata: + labels: + app.kubernetes.io/component: exporter + app.kubernetes.io/name: kube-state-metrics + app.kubernetes.io/version: 2.7.0 + name: kube-state-metrics + namespace: kube-system diff --git a/test/packages/with-kind/kubernetes/data_stream/state_cronjob/_dev/deploy/k8s/service.yaml b/test/packages/with-kind/kubernetes/data_stream/state_cronjob/_dev/deploy/k8s/service.yaml new file mode 100644 index 0000000000..56cece9dfd --- /dev/null +++ b/test/packages/with-kind/kubernetes/data_stream/state_cronjob/_dev/deploy/k8s/service.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/component: exporter + app.kubernetes.io/name: kube-state-metrics + app.kubernetes.io/version: 2.7.0 + name: kube-state-metrics + namespace: kube-system +spec: + clusterIP: None + ports: + - name: http-metrics + port: 8080 + targetPort: http-metrics + - name: telemetry + port: 8081 + targetPort: telemetry + selector: + app.kubernetes.io/name: kube-state-metrics diff --git a/test/packages/with-kind/kubernetes/data_stream/state_cronjob/_dev/test/system/test-default-config.yml b/test/packages/with-kind/kubernetes/data_stream/state_cronjob/_dev/test/system/test-default-config.yml new file mode 100644 index 0000000000..0f4bd620c0 --- /dev/null +++ b/test/packages/with-kind/kubernetes/data_stream/state_cronjob/_dev/test/system/test-default-config.yml @@ -0,0 +1,6 @@ +service: kubernetes +data_stream: + vars: + hosts: + # this is the DNS name of the k8s service for kube-state-metrics deployment + - http://kube-state-metrics:8080 diff --git a/test/packages/with-kind/kubernetes/data_stream/state_cronjob/agent/stream/stream.yml.hbs b/test/packages/with-kind/kubernetes/data_stream/state_cronjob/agent/stream/stream.yml.hbs new file mode 100644 index 0000000000..2a409284cd --- /dev/null +++ b/test/packages/with-kind/kubernetes/data_stream/state_cronjob/agent/stream/stream.yml.hbs @@ -0,0 +1,30 @@ +metricsets: ["state_cronjob"] +add_metadata: {{add_metadata}} +hosts: +{{#each hosts}} + - {{this}} +{{/each}} +period: {{period}} +{{#if leaderelection}} +condition: ${kubernetes_leaderelection.leader} == true +{{/if}} +{{#if node}} +node: {{node}} +{{/if}} +{{#if namespace}} +namespace: {{namespace}} +{{/if}} +{{#if bearer_token_file}} +bearer_token_file: {{bearer_token_file}} +{{/if}} +{{#if ssl.certificate_authorities}} +ssl.certificate_authorities: +{{#each ssl.certificate_authorities}} + - {{this}} +{{/each}} +{{/if}} + +{{#if processors}} +processors: +{{processors}} +{{/if}} \ No newline at end of file diff --git a/test/packages/with-kind/kubernetes/data_stream/state_cronjob/fields/agent.yml b/test/packages/with-kind/kubernetes/data_stream/state_cronjob/fields/agent.yml new file mode 100644 index 0000000000..da4e652c53 --- /dev/null +++ b/test/packages/with-kind/kubernetes/data_stream/state_cronjob/fields/agent.yml @@ -0,0 +1,198 @@ +- name: cloud + title: Cloud + group: 2 + description: Fields related to the cloud or infrastructure the events are coming from. + footnote: 'Examples: If Metricbeat is running on an EC2 host and fetches data from its host, the cloud info contains the data about this machine. If Metricbeat runs on a remote machine outside the cloud and fetches data from a service running in the cloud, the field contains cloud data from the machine the service is running on.' + type: group + fields: + - name: account.id + level: extended + type: keyword + ignore_above: 1024 + description: 'The cloud account or organization id used to identify different entities in a multi-tenant environment. + + Examples: AWS account id, Google Cloud ORG Id, or other unique identifier.' + example: 666777888999 + - name: availability_zone + level: extended + type: keyword + ignore_above: 1024 + description: Availability zone in which this host is running. + example: us-east-1c + - name: instance.id + level: extended + type: keyword + ignore_above: 1024 + description: Instance ID of the host machine. + example: i-1234567890abcdef0 + - name: instance.name + level: extended + type: keyword + ignore_above: 1024 + description: Instance name of the host machine. + - name: machine.type + level: extended + type: keyword + ignore_above: 1024 + description: Machine type of the host machine. + example: t2.medium + - name: provider + level: extended + type: keyword + ignore_above: 1024 + description: Name of the cloud provider. Example values are aws, azure, gcp, or digitalocean. + example: aws + - name: region + level: extended + type: keyword + ignore_above: 1024 + description: Region in which this host is running. + example: us-east-1 + - name: project.id + type: keyword + description: Name of the project in Google Cloud. + - name: image.id + type: keyword + description: Image ID for the cloud instance. +- name: container + title: Container + group: 2 + description: 'Container fields are used for meta information about the specific container that is the source of information. + + These fields help correlate data based containers from any runtime.' + type: group + fields: + - name: id + level: core + type: keyword + ignore_above: 1024 + description: Unique container id. + - name: image.name + level: extended + type: keyword + ignore_above: 1024 + description: Name of the image the container was built on. + - name: labels + level: extended + type: object + object_type: keyword + description: Image labels. + - name: name + level: extended + type: keyword + ignore_above: 1024 + description: Container name. +- name: host + title: Host + group: 2 + description: 'A host is defined as a general computing instance. + + ECS host.* fields should be populated with details about the host on which the event happened, or from which the measurement was taken. Host types include hardware, virtual machines, Docker containers, and Kubernetes nodes.' + type: group + fields: + - name: architecture + level: core + type: keyword + ignore_above: 1024 + description: Operating system architecture. + example: x86_64 + - name: domain + level: extended + type: keyword + ignore_above: 1024 + description: 'Name of the domain of which the host is a member. + + For example, on Windows this could be the host''s Active Directory domain or NetBIOS domain name. For Linux this could be the domain of the host''s LDAP provider.' + example: CONTOSO + default_field: false + - name: hostname + level: core + type: keyword + ignore_above: 1024 + description: 'Hostname of the host. + + It normally contains what the `hostname` command returns on the host machine.' + - name: id + level: core + type: keyword + ignore_above: 1024 + description: 'Unique host id. + + As hostname is not always unique, use values that are meaningful in your environment. + + Example: The current usage of `beat.name`.' + - name: ip + level: core + type: ip + description: Host ip addresses. + - name: mac + level: core + type: keyword + ignore_above: 1024 + description: Host mac addresses. + - name: name + level: core + type: keyword + ignore_above: 1024 + description: 'Name of the host. + + It can contain what `hostname` returns on Unix systems, the fully qualified domain name, or a name specified by the user. The sender decides which value to use.' + - name: os.family + level: extended + type: keyword + ignore_above: 1024 + description: OS family (such as redhat, debian, freebsd, windows). + example: debian + - name: os.kernel + level: extended + type: keyword + ignore_above: 1024 + description: Operating system kernel version as a raw string. + example: 4.4.0-112-generic + - name: os.name + level: extended + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + default_field: false + description: Operating system name, without the version. + example: Mac OS X + - name: os.platform + level: extended + type: keyword + ignore_above: 1024 + description: Operating system platform (such centos, ubuntu, windows). + example: darwin + - name: os.version + level: extended + type: keyword + ignore_above: 1024 + description: Operating system version as a raw string. + example: 10.14.1 + - name: type + level: core + type: keyword + ignore_above: 1024 + description: 'Type of host. + + For Cloud providers this can be the machine type like `t2.medium`. If vm, this could be the container, for example, or other information meaningful in your environment.' + - name: containerized + type: boolean + description: > + If the host is a container. + + - name: os.build + type: keyword + example: "18D109" + description: > + OS build information. + + - name: os.codename + type: keyword + example: "stretch" + description: > + OS codename, if any. + diff --git a/test/packages/with-kind/kubernetes/data_stream/state_cronjob/fields/base-fields.yml b/test/packages/with-kind/kubernetes/data_stream/state_cronjob/fields/base-fields.yml new file mode 100644 index 0000000000..04fa3c6e64 --- /dev/null +++ b/test/packages/with-kind/kubernetes/data_stream/state_cronjob/fields/base-fields.yml @@ -0,0 +1,106 @@ +- name: data_stream.type + type: constant_keyword + description: Data stream type. +- name: data_stream.dataset + type: constant_keyword + description: Data stream dataset. +- name: data_stream.namespace + type: constant_keyword + description: Data stream namespace. +- name: '@timestamp' + type: date + description: Event timestamp. +- name: kubernetes + type: group + fields: + - name: pod.name + dimension: true + type: keyword + description: > + Kubernetes pod name + + - name: pod.uid + dimension: true + type: keyword + description: > + Kubernetes pod UID + + - name: pod.ip + type: ip + description: > + Kubernetes pod IP + + - name: namespace + dimension: true + type: keyword + description: > + Kubernetes namespace + + - name: namespace_uid + type: keyword + description: > + Kubernetes namespace UID + + - name: namespace_labels.* + type: object + object_type: keyword + object_type_mapping_type: "*" + description: > + Kubernetes namespace labels map + + - name: node.name + type: keyword + description: > + Kubernetes node name + + - name: node.hostname + type: keyword + description: > + Kubernetes hostname as reported by the node’s kernel + + - name: labels.* + type: object + object_type: keyword + object_type_mapping_type: "*" + description: > + Kubernetes labels map + + - name: annotations.* + type: object + object_type: keyword + object_type_mapping_type: "*" + description: > + Kubernetes annotations map + + - name: selectors.* + type: object + object_type: keyword + object_type_mapping_type: "*" + description: > + Kubernetes Service selectors map + + - name: replicaset.name + type: keyword + description: > + Kubernetes replicaset name + + - name: deployment.name + type: keyword + description: > + Kubernetes deployment name + + - name: statefulset.name + type: keyword + description: > + Kubernetes statefulset name + + - name: container.name + dimension: true + type: keyword + description: > + Kubernetes container name + + - name: container.image + type: keyword + description: >- + Kubernetes container image diff --git a/test/packages/with-kind/kubernetes/data_stream/state_cronjob/fields/ecs.yml b/test/packages/with-kind/kubernetes/data_stream/state_cronjob/fields/ecs.yml new file mode 100644 index 0000000000..cd4e3a89b1 --- /dev/null +++ b/test/packages/with-kind/kubernetes/data_stream/state_cronjob/fields/ecs.yml @@ -0,0 +1,10 @@ +- external: ecs + name: ecs.version +- external: ecs + name: service.address +- external: ecs + name: service.type +- external: ecs + name: orchestrator.cluster.name +- external: ecs + name: orchestrator.cluster.url diff --git a/test/packages/with-kind/kubernetes/data_stream/state_cronjob/fields/fields.yml b/test/packages/with-kind/kubernetes/data_stream/state_cronjob/fields/fields.yml new file mode 100644 index 0000000000..acf6803436 --- /dev/null +++ b/test/packages/with-kind/kubernetes/data_stream/state_cronjob/fields/fields.yml @@ -0,0 +1,42 @@ +- name: kubernetes.cronjob + type: group + fields: + - name: name + dimension: true + type: keyword + description: Cronjob name + - name: schedule + dimension: true + type: keyword + description: Cronjob schedule + - name: concurrency + dimension: true + type: keyword + description: Concurrency policy + - name: active.count + type: long + metric_type: gauge + description: Number of active pods for the cronjob + - name: is_suspended + type: boolean + description: Whether the cronjob is suspended + - name: created.sec + type: double + unit: s + metric_type: gauge + description: Epoch seconds since the cronjob was created + - name: last_schedule.sec + type: double + unit: s + metric_type: gauge + description: Epoch seconds for last cronjob run + - name: next_schedule.sec + type: double + unit: s + metric_type: gauge + description: Epoch seconds for next cronjob run + - name: deadline.sec + type: long + unit: s + metric_type: gauge + description: Deadline seconds after schedule for considering failed diff --git a/test/packages/with-kind/kubernetes/data_stream/state_cronjob/manifest.yml b/test/packages/with-kind/kubernetes/data_stream/state_cronjob/manifest.yml new file mode 100644 index 0000000000..d06cb5ada5 --- /dev/null +++ b/test/packages/with-kind/kubernetes/data_stream/state_cronjob/manifest.yml @@ -0,0 +1,71 @@ +title: Kubernetes Cronjob metrics +type: metrics +streams: + - input: kubernetes/metrics + enabled: true + vars: + - name: add_metadata + type: bool + title: Add Metadata + multi: false + required: true + show_user: true + default: true + - name: hosts + type: text + title: Hosts + multi: true + required: true + show_user: true + default: + - kube-state-metrics:8080 + - name: leaderelection + type: bool + title: Leader Election + multi: false + required: true + show_user: true + default: true + - name: period + type: text + title: Period + multi: false + required: true + show_user: true + default: 10s + - name: node + type: text + title: Node to watch resources from for metadata + multi: false + required: false + show_user: false + - name: namespace + type: text + title: Namespace to watch resources from for metadata + multi: false + required: false + show_user: false + - name: bearer_token_file + type: text + title: Bearer Token File + multi: false + required: false + show_user: false + default: /var/run/secrets/kubernetes.io/serviceaccount/token + - name: ssl.certificate_authorities + type: text + title: SSL Certificate Authorities + multi: true + required: false + show_user: false + - name: processors + type: yaml + title: Processors + multi: false + required: false + show_user: false + description: > + Processors are used to reduce the number of fields in the exported event or to enhance the event with metadata. This executes in the agent before the events are shipped. See [Processors](https://www.elastic.co/guide/en/beats/filebeat/current/filtering-and-enhancing-data.html) for details. + + title: Kubernetes Cronjob metrics + description: Collect Kubernetes Cronjob metrics from kube_state_metrics diff --git a/test/packages/with-kind/kubernetes/data_stream/state_cronjob/sample_event.json b/test/packages/with-kind/kubernetes/data_stream/state_cronjob/sample_event.json new file mode 100644 index 0000000000..ec050c2955 --- /dev/null +++ b/test/packages/with-kind/kubernetes/data_stream/state_cronjob/sample_event.json @@ -0,0 +1,126 @@ +{ + "kubernetes": { + "namespace": "default", + "namespace_uid": "5f4a8989-32b3-4fc9-ba5b-9dece58436b8", + "namespace_labels": { + "kubernetes_io/metadata_name": "default" + }, + "cronjob": { + "last_schedule": { + "sec": 1674053820 + }, + "created": { + "sec": 1674053817 + }, + "name": "hello", + "active": { + "count": 0 + }, + "is_suspended": false, + "next_schedule": { + "sec": 1674053880 + } + }, + "labels": { + "k8s-app": "myjob" + } + }, + "orchestrator": { + "cluster": { + "name": "kind", + "url": "kind-control-plane:6443" + } + }, + "agent": { + "name": "kind-control-plane", + "id": "c446ee97-62f8-47db-ac88-ada92aa550a0", + "type": "metricbeat", + "ephemeral_id": "b61db5f9-8e5a-4ec2-b73f-dd4ee1537110", + "version": "8.6.0" + }, + "@timestamp": "2023-01-18T14:57:16.597Z", + "ecs": { + "version": "8.0.0" + }, + "data_stream": { + "namespace": "default", + "type": "metrics", + "dataset": "kubernetes.state_cronjob" + }, + "service": { + "address": "http://kube-state-metrics:8080/metrics", + "type": "kubernetes" + }, + "host": { + "hostname": "kind-control-plane", + "os": { + "kernel": "5.10.104-linuxkit", + "codename": "focal", + "name": "Ubuntu", + "family": "debian", + "type": "linux", + "version": "20.04.5 LTS (Focal Fossa)", + "platform": "ubuntu" + }, + "containerized": false, + "ip": [ + "10.244.0.1", + "10.244.0.1", + "10.244.0.1", + "10.244.0.1", + "10.244.0.1", + "10.244.0.1", + "10.244.0.1", + "172.18.0.2", + "fc00:f853:ccd:e793::2", + "fe80::42:acff:fe12:2", + "10.244.0.1", + "172.21.0.2", + "10.244.0.1", + "10.244.0.1", + "10.244.0.1", + "10.244.0.1", + "10.244.0.1", + "10.244.0.1", + "10.244.0.1" + ], + "name": "kind-control-plane", + "id": "ee94d9f5b385448b805141d2b007ef9e", + "mac": [ + "02-42-AC-12-00-02", + "02-42-AC-15-00-02", + "26-44-88-00-0A-01", + "36-29-00-36-7F-53", + "52-A2-77-CF-D4-EC", + "62-BC-CF-94-14-6C", + "8E-B9-C8-09-2D-B8", + "92-BA-04-F3-2A-CC", + "A2-55-7D-53-57-91", + "A6-4F-D1-E2-1E-12", + "B6-ED-00-D6-1B-B8", + "BA-D7-49-95-5A-F5", + "CA-B9-E6-A7-52-0D", + "D6-F9-71-43-6C-24", + "DE-05-63-F9-0B-36", + "EE-C8-E8-11-00-F5", + "F6-52-0A-F0-63-83" + ], + "architecture": "x86_64" + }, + "elastic_agent": { + "id": "c446ee97-62f8-47db-ac88-ada92aa550a0", + "version": "8.6.0", + "snapshot": false + }, + "metricset": { + "period": 10000, + "name": "state_cronjob" + }, + "event": { + "duration": 11786458, + "agent_id_status": "verified", + "ingested": "2023-01-18T14:57:17Z", + "module": "kubernetes", + "dataset": "kubernetes.state_cronjob" + } +} \ No newline at end of file diff --git a/test/packages/with-kind/kubernetes/manifest.yml b/test/packages/with-kind/kubernetes/manifest.yml index b73a8b7cfc..9ec492b3ec 100644 --- a/test/packages/with-kind/kubernetes/manifest.yml +++ b/test/packages/with-kind/kubernetes/manifest.yml @@ -47,6 +47,7 @@ policy_templates: description: Collect container metrics from Kubernetes Kube-state-metrics with Elastic Agent. data_streams: - state_pod + - state_cronjob inputs: - type: kubernetes/metrics title: Collect Kubernetes metrics from kube-state-metrics From 86bcaf2efa97000999a34670cb762c4f4876c74d Mon Sep 17 00:00:00 2001 From: constanca-m Date: Wed, 8 Feb 2023 11:10:39 +0100 Subject: [PATCH 13/15] Fix import cycle. --- internal/kubectl/kubectl.go | 5 +++-- .../testrunner/runners/system/servicedeployer/kubernetes.go | 2 -- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/internal/kubectl/kubectl.go b/internal/kubectl/kubectl.go index 2dd7b55f7e..cab57d05eb 100644 --- a/internal/kubectl/kubectl.go +++ b/internal/kubectl/kubectl.go @@ -6,7 +6,6 @@ package kubectl import ( "bytes" - "github.com/elastic/elastic-package/internal/testrunner/runners/system/servicedeployer" "os/exec" "path/filepath" @@ -15,6 +14,8 @@ import ( "github.com/elastic/elastic-package/internal/logger" ) +const kustomizationFile = "kustomization.yaml" + // CurrentContext function returns the selected Kubernetes context. func CurrentContext() (string, error) { cmd := exec.Command("kubectl", "config", "current-context") @@ -32,7 +33,7 @@ func CurrentContext() (string, error) { func modifyKubernetesResources(action string, definitionPaths []string) ([]byte, error) { args := []string{action} for _, definitionPath := range definitionPaths { - if filepath.Base(definitionPath) == servicedeployer.KustomizationFile { + if filepath.Base(definitionPath) == kustomizationFile { args = []string{action, "-k", definitionPath} break } diff --git a/internal/testrunner/runners/system/servicedeployer/kubernetes.go b/internal/testrunner/runners/system/servicedeployer/kubernetes.go index af4fadd6a6..1248aade21 100644 --- a/internal/testrunner/runners/system/servicedeployer/kubernetes.go +++ b/internal/testrunner/runners/system/servicedeployer/kubernetes.go @@ -23,8 +23,6 @@ import ( "github.com/elastic/elastic-package/internal/stack" ) -const KustomizationFile = "kustomization.yaml" - // KubernetesServiceDeployer is responsible for deploying resources in the Kubernetes cluster. type KubernetesServiceDeployer struct { definitionsDir string From 2452a9ebe5c1daebdb133fad6527331d35130c1f Mon Sep 17 00:00:00 2001 From: constanca-m Date: Wed, 8 Feb 2023 11:29:14 +0100 Subject: [PATCH 14/15] Fix kustomization.yaml file path. --- internal/kubectl/kubectl.go | 2 +- .../system/servicedeployer/kubernetes.go | 25 ------------------- 2 files changed, 1 insertion(+), 26 deletions(-) diff --git a/internal/kubectl/kubectl.go b/internal/kubectl/kubectl.go index cab57d05eb..38a4367954 100644 --- a/internal/kubectl/kubectl.go +++ b/internal/kubectl/kubectl.go @@ -34,7 +34,7 @@ func modifyKubernetesResources(action string, definitionPaths []string) ([]byte, args := []string{action} for _, definitionPath := range definitionPaths { if filepath.Base(definitionPath) == kustomizationFile { - args = []string{action, "-k", definitionPath} + args = []string{action, "-k", filepath.Dir(definitionPath)} break } args = append(args, "-f") diff --git a/internal/testrunner/runners/system/servicedeployer/kubernetes.go b/internal/testrunner/runners/system/servicedeployer/kubernetes.go index 1248aade21..fcaf61e288 100644 --- a/internal/testrunner/runners/system/servicedeployer/kubernetes.go +++ b/internal/testrunner/runners/system/servicedeployer/kubernetes.go @@ -133,16 +133,6 @@ func (ksd KubernetesServiceDeployer) installCustomDefinitions() error { var _ ServiceDeployer = new(KubernetesServiceDeployer) func findKubernetesDefinitions(definitionsDir string) ([]string, error) { - /* - files, err := filepath.Glob(filepath.Join(definitionsDir, "*.yaml")) - if err != nil { - return nil, errors.Wrapf(err, "can't read definitions directory (path: %s)", definitionsDir) - var definitionPaths []string - definitionPaths = append(definitionPaths, files...) - return definitionPaths, nil - - */ - files, err := filepath.Glob(filepath.Join(definitionsDir, "*.yaml")) if err != nil { return nil, errors.Wrapf(err, "can't read definitions directory (path: %s)", definitionsDir) @@ -151,21 +141,6 @@ func findKubernetesDefinitions(definitionsDir string) ([]string, error) { var definitionPaths []string definitionPaths = append(definitionPaths, files...) return definitionPaths, nil - - /* - if _, err := os.Stat(definitionsDir); err != nil { - return false, errors.Wrapf(err, "can't read definitions directory (path: %s)", definitionsDir) - } - // check if kustomization.yaml exists - if _, err := os.Stat(filepath.Join(definitionsDir, kustomizationFile)); err != nil { - // if it does not exist, then the .empty file needs to be present - if _, err := os.Stat(filepath.Join(definitionsDir, emptyFile)); err != nil { - return false, errors.Errorf("%s file is missing (path: %s). Add one or create an %s file"+ - " if no custom definitions are required.", kustomizationFile, definitionsDir, emptyFile) - } - return false, nil - } - return true, nil*/ } func installElasticAgentInCluster() error { From a1512f6dac25e404ed7b14e4f80a2eb61dec2b0b Mon Sep 17 00:00:00 2001 From: constanca-m Date: Thu, 9 Feb 2023 10:57:46 +0100 Subject: [PATCH 15/15] Update system_testing.md --- docs/howto/system_testing.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/howto/system_testing.md b/docs/howto/system_testing.md index f4d0bd38a8..c549a5354f 100644 --- a/docs/howto/system_testing.md +++ b/docs/howto/system_testing.md @@ -303,7 +303,8 @@ There are some specific environment variables that should be leveraged to overco ### Kubernetes service deployer The Kubernetes service deployer requires the `_dev/deploy/k8s` directory to be present. It can include additional `*.yaml` files to deploy -custom applications in the Kubernetes cluster (e.g. Nginx deployment). If no resource definitions (`*.yaml` files ) are needed, +custom applications in the Kubernetes cluster (e.g. Nginx deployment). It is possible to use a `kustomization.yaml` file. +If no resource definitions (`*.yaml` files ) are needed, the `_dev/deploy/k8s` directory must contain an `.empty` file (to preserve the `k8s` directory under version control). The Kubernetes service deployer needs [kind](https://kind.sigs.k8s.io/) to be installed and the cluster to be up and running: