mirror of
https://github.com/percona/percona-toolkit.git
synced 2025-09-11 21:51:21 +00:00
PT-2134 - support for PostgreSQL and MySQL operators (#567)
* PT-2134 - Support for PostgreSQL and PS MySQL operators For PS MySQL operator: added support of pt-mysql-summary For PostgreSQL operator: added support for pg_gather Options added: - kubeconfig - path to kubeconfig - forwardport - port to use when calling pt-*-summary tools ad pt_gather Options changed: - resource - now default value is (was pxc). New values added: psql - for PostgreSQL operator ps - for PS MySQL operator if default value () is used: only K8 information is collected Otherwise resource-specific summary is collected * PT-2134_support_for_PostgreSQL_and_MySQL_operators Fixed summary collection when connecting to PostgreSQL opertor and no resource specified * PT-2134 - support for PostgreSQL and MySQL operators Added test case for full supported set of values for option --resource, added --kubeconfig and --forwardport options for test cases, added support for environment variables KUBECONFIG_PXC, KUBECONFIG_PS, KUBECONFIG_PSMDB, KUBECONFIG_PSQL, FORWARDPORT for test cases * PT-2134 - support for PostgreSQL and MySQL operators updated docs/pt-k8s-debug-collector.rst, replaced README.md in src/go/pt-k8s-debug-collector wih symbolic link to docs/pt-k8s-debug-collector.rst to avoid having inconsistent documentation * PT-2134 - support for PostgreSQL and MySQL operators Removed curl STDERR from the command output * PT-2134 - support for PostgreSQL and MySQL operators typo in pt-k8s-debug-collector.rst * PT-2134 - support for PostgreSQL and MySQL operators Renamed --resource=psql to --resource=pg after review suggestion by Ege and collecting feedback from potential users Co-authored-by: EvgeniyPatlan <evgeniy.patlan@percona.com> Co-authored-by: Carlos Salguero <carlos.salguero@percona.com>
This commit is contained in:
@@ -46,6 +46,13 @@ Data, collected for PXC
|
||||
"perconaxtradbclusterrestores",
|
||||
"perconaxtradbclusters"
|
||||
|
||||
Summary, collected for PXC (available in file summary.txt)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
"pt-mysql-summary"
|
||||
|
||||
Individual files, collected for PXC
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@@ -60,6 +67,22 @@ Individual files, collected for PXC
|
||||
"var/lib/mysql/mysqld.post.processing.log",
|
||||
"var/lib/mysql/auto.cnf"
|
||||
|
||||
Data, collected for MySQL
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
"perconaservermysqlbackups",
|
||||
"perconaservermysqlrestores",
|
||||
"perconaservermysqls"
|
||||
|
||||
Summary, collected for MySQL (available in file summary.txt)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
"pt-mysql-summary"
|
||||
|
||||
Data, collected for MongoDB
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@@ -69,22 +92,90 @@ Data, collected for MongoDB
|
||||
"perconaservermongodbrestores",
|
||||
"perconaservermongodbs"
|
||||
|
||||
Summary, collected for MongoDB (available in file summary.txt)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
"pt-mongodb-summary"
|
||||
|
||||
Data, collected for PostgreSQL
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
"perconapgclusters",
|
||||
"pgclusters",
|
||||
"pgpolicies",
|
||||
"pgreplicas",
|
||||
"pgtasks"
|
||||
|
||||
Summary, collected for PostgreSQL (available in file summary.txt)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
"pg_gather"
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
``pt-k8s-debug-collector <flags>``
|
||||
|
||||
Flags:
|
||||
Supported Flags:
|
||||
================
|
||||
|
||||
``--resource` targeted custom resource name (default "pxc")``
|
||||
``--resource``
|
||||
|
||||
``--namespace` targeted namespace. By default data will be collected from all namespaces``
|
||||
Targeted custom resource name. Supported values:
|
||||
|
||||
``--cluster` targeted pxc/psmdb cluster. By default data from all available clusters to be collected``
|
||||
* ``pxc`` - PXC
|
||||
|
||||
* ``psmdb`` - MongoDB
|
||||
|
||||
* ``pg`` - PostgreSQL
|
||||
|
||||
* ``ps`` - MySQL
|
||||
|
||||
* ``none`` - Collect only general Kubernetes data, do not collect anything specific to the particular operator).
|
||||
|
||||
Default: ``none``
|
||||
|
||||
``--namespace``
|
||||
|
||||
Targeted namespace. By default data will be collected from all namespaces
|
||||
|
||||
``--cluster``
|
||||
|
||||
Targeted cluster. By default data from all available clusters to be collected
|
||||
|
||||
``--kubeconfig``
|
||||
|
||||
Path to kubeconfig. Default configuration be used if none specified
|
||||
|
||||
``--forwardport``
|
||||
|
||||
Port to use when collecting database-specific summaries. By default, 3306 will be used for PXC and MySQL, 27017 for MongoDB, and 5432 for PostgreSQL
|
||||
|
||||
Requirements
|
||||
============
|
||||
|
||||
- Installed and configured ``kubectl``
|
||||
- Installed and configured ``pt-mysql-summary``
|
||||
- Installed and configured ``pt-mongodb-summary``
|
||||
- Installed, configured, and available in PATH ``kubectl``
|
||||
- Installed, configured, and available in PATH ``pt-mysql-summary`` for PXC and MySQL
|
||||
- Installed, configured, and available in PATH ``pt-mongodb-summary`` for MongoDB
|
||||
|
||||
Known Issues
|
||||
============
|
||||
|
||||
On Kubernetes 1.21 - 1.24 warning is printed:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
2022/12/15 17:43:16 Error: get resource podsecuritypolicies in namespace default: error: <nil>, stderr: Warning: policy/v1beta1 PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+
|
||||
, stdout: apiVersion: v1
|
||||
items: []
|
||||
kind: List
|
||||
metadata:
|
||||
resourceVersion: ""
|
||||
|
||||
This warning is harmless and does not affect data collection. We will remove podsecuritypolicies once everyone upgrade to Kubernetes 1.25 or newer. Before that we advise to ignore this warning.
|
@@ -1,84 +0,0 @@
|
||||
# Debug collector tool
|
||||
|
||||
Collects debug data (logs, resource statuses etc.) from a k8s/OpenShift cluster. Data is packed into the `cluster-dump.tar.gz` archive in the current working directory.
|
||||
|
||||
## Data that will be collected
|
||||
|
||||
### Data, collected for all resources
|
||||
|
||||
```
|
||||
"pods",
|
||||
"replicasets",
|
||||
"deployments",
|
||||
"statefulsets",
|
||||
"replicationcontrollers",
|
||||
"events",
|
||||
"configmaps",
|
||||
"cronjobs",
|
||||
"jobs",
|
||||
"podsecuritypolicies",
|
||||
"poddisruptionbudgets",
|
||||
"perconaxtradbbackups",
|
||||
"perconaxtradbclusterbackups",
|
||||
"perconaxtradbclusterrestores",
|
||||
"perconaxtradbclusters",
|
||||
"clusterrolebindings",
|
||||
"clusterroles",
|
||||
"rolebindings",
|
||||
"roles",
|
||||
"storageclasses",
|
||||
"persistentvolumeclaims",
|
||||
"persistentvolumes",
|
||||
"modes",
|
||||
"your-custom-resource" (depends on 'resource' flag)
|
||||
|
||||
```
|
||||
|
||||
### Data, collected for PXC
|
||||
|
||||
```
|
||||
"perconaxtradbbackups",
|
||||
"perconaxtradbclusterbackups",
|
||||
"perconaxtradbclusterrestores",
|
||||
"perconaxtradbclusters"
|
||||
```
|
||||
|
||||
### Individual files, collected for PXC
|
||||
|
||||
```
|
||||
"var/lib/mysql/mysqld-error.log",
|
||||
"var/lib/mysql/innobackup.backup.log",
|
||||
"var/lib/mysql/innobackup.move.log",
|
||||
"var/lib/mysql/innobackup.prepare.log",
|
||||
"var/lib/mysql/grastate.dat",
|
||||
"var/lib/mysql/gvwstate.dat",
|
||||
"var/lib/mysql/mysqld.post.processing.log",
|
||||
"var/lib/mysql/auto.cnf"
|
||||
```
|
||||
|
||||
### Data, collected for MongoDB
|
||||
|
||||
```
|
||||
"perconaservermongodbbackups",
|
||||
"perconaservermongodbrestores",
|
||||
"perconaservermongodbs"
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
`pt-k8s-debug-collector <flags>`
|
||||
|
||||
Flags:
|
||||
|
||||
`--resource` targeted custom resource name (default "pxc")
|
||||
|
||||
`--namespace` targeted namespace. By default, data will be collected from all namespaces
|
||||
|
||||
`--cluster` targeted pxc/psmdb cluster. By default, data from all available clusters to be collected
|
||||
|
||||
## Requirements
|
||||
|
||||
- Installed and configured 'kubectl'
|
||||
- Installed and configured 'pt-mysql-summary'
|
||||
- Installed and configured 'pt-mongodb-summary'
|
||||
|
181
src/go/pt-k8s-debug-collector/README.rst
Normal file
181
src/go/pt-k8s-debug-collector/README.rst
Normal file
@@ -0,0 +1,181 @@
|
||||
.. _pt-k8s-debug-collector:
|
||||
|
||||
==================================
|
||||
:program:`pt-k8s-debug-collector`
|
||||
==================================
|
||||
|
||||
Collects debug data (logs, resource statuses etc.) from a k8s/OpenShift cluster. Data is packed into the ``cluster-dump.tar.gz`` archive in the current working directory.
|
||||
|
||||
Data that will be collected
|
||||
===========================
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
"pods",
|
||||
"replicasets",
|
||||
"deployments",
|
||||
"statefulsets",
|
||||
"replicationcontrollers",
|
||||
"events",
|
||||
"configmaps",
|
||||
"cronjobs",
|
||||
"jobs",
|
||||
"podsecuritypolicies",
|
||||
"poddisruptionbudgets",
|
||||
"perconaxtradbbackups",
|
||||
"perconaxtradbclusterbackups",
|
||||
"perconaxtradbclusterrestores",
|
||||
"perconaxtradbclusters",
|
||||
"clusterrolebindings",
|
||||
"clusterroles",
|
||||
"rolebindings",
|
||||
"roles",
|
||||
"storageclasses",
|
||||
"persistentvolumeclaims",
|
||||
"persistentvolumes",
|
||||
"modes",
|
||||
"your-custom-resource" (depends on 'resource' flag)
|
||||
|
||||
Data, collected for PXC
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
"perconaxtradbbackups",
|
||||
"perconaxtradbclusterbackups",
|
||||
"perconaxtradbclusterrestores",
|
||||
"perconaxtradbclusters"
|
||||
|
||||
Summary, collected for PXC (available in file summary.txt)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
"pt-mysql-summary"
|
||||
|
||||
Individual files, collected for PXC
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
"var/lib/mysql/mysqld-error.log",
|
||||
"var/lib/mysql/innobackup.backup.log",
|
||||
"var/lib/mysql/innobackup.move.log",
|
||||
"var/lib/mysql/innobackup.prepare.log",
|
||||
"var/lib/mysql/grastate.dat",
|
||||
"var/lib/mysql/gvwstate.dat",
|
||||
"var/lib/mysql/mysqld.post.processing.log",
|
||||
"var/lib/mysql/auto.cnf"
|
||||
|
||||
Data, collected for MySQL
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
"perconaservermysqlbackups",
|
||||
"perconaservermysqlrestores",
|
||||
"perconaservermysqls"
|
||||
|
||||
Summary, collected for MySQL (available in file summary.txt)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
"pt-mysql-summary"
|
||||
|
||||
Data, collected for MongoDB
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
"perconaservermongodbbackups",
|
||||
"perconaservermongodbrestores",
|
||||
"perconaservermongodbs"
|
||||
|
||||
Summary, collected for MongoDB (available in file summary.txt)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
"pt-mongodb-summary"
|
||||
|
||||
Data, collected for PostgreSQL
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
"perconapgclusters",
|
||||
"pgclusters",
|
||||
"pgpolicies",
|
||||
"pgreplicas",
|
||||
"pgtasks"
|
||||
|
||||
Summary, collected for PostgreSQL (available in file summary.txt)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
"pg_gather"
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
``pt-k8s-debug-collector <flags>``
|
||||
|
||||
Supported Flags:
|
||||
================
|
||||
|
||||
``--resource``
|
||||
|
||||
Targeted custom resource name. Supported values:
|
||||
|
||||
* ``pxc`` - PXC
|
||||
|
||||
* ``psmdb`` - MongoDB
|
||||
|
||||
* ``pg`` - PostgreSQL
|
||||
|
||||
* ``ps`` - MySQL
|
||||
|
||||
* ``none`` - Collect only general Kubernetes data, do not collect anything specific to the particular operator).
|
||||
|
||||
Default: ``none``
|
||||
|
||||
``--namespace``
|
||||
|
||||
Targeted namespace. By default data will be collected from all namespaces
|
||||
|
||||
``--cluster``
|
||||
|
||||
Targeted cluster. By default data from all available clusters to be collected
|
||||
|
||||
``--kubeconfig``
|
||||
|
||||
Path to kubeconfig. Default configuration be used if none specified
|
||||
|
||||
``--forwardport``
|
||||
|
||||
Port to use when collecting database-specific summaries. By default, 3306 will be used for PXC and MySQL, 27017 for MongoDB, and 5432 for PostgreSQL
|
||||
|
||||
Requirements
|
||||
============
|
||||
|
||||
- Installed, configured, and available in PATH ``kubectl``
|
||||
- Installed, configured, and available in PATH ``pt-mysql-summary`` for PXC and MySQL
|
||||
- Installed, configured, and available in PATH ``pt-mongodb-summary`` for MongoDB
|
||||
|
||||
Known Issues
|
||||
============
|
||||
|
||||
On Kubernetes 1.21 - 1.24 warning is printed:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
2022/12/15 17:43:16 Error: get resource podsecuritypolicies in namespace default: error: <nil>, stderr: Warning: policy/v1beta1 PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+
|
||||
, stdout: apiVersion: v1
|
||||
items: []
|
||||
kind: List
|
||||
metadata:
|
||||
resourceVersion: ""
|
||||
|
||||
This warning is harmless and does not affect data collection. We will remove podsecuritypolicies once everyone upgrade to Kubernetes 1.25 or newer. Before that we advise to ignore this warning.
|
@@ -21,6 +21,7 @@ import (
|
||||
// Dumper struct is for dumping cluster
|
||||
type Dumper struct {
|
||||
cmd string
|
||||
kubeconfig string
|
||||
resources []string
|
||||
filePaths []string
|
||||
namespace string
|
||||
@@ -28,10 +29,11 @@ type Dumper struct {
|
||||
errors string
|
||||
mode int64
|
||||
crType string
|
||||
forwardport string
|
||||
}
|
||||
|
||||
// New return new Dumper object
|
||||
func New(location, namespace, resource string) Dumper {
|
||||
func New(location, namespace, resource string, kubeconfig string, forwardport string) Dumper {
|
||||
resources := []string{
|
||||
"pods",
|
||||
"replicasets",
|
||||
@@ -54,11 +56,8 @@ func New(location, namespace, resource string) Dumper {
|
||||
}
|
||||
filePaths := make([]string, 0)
|
||||
if len(resource) > 0 {
|
||||
resources = append(resources, resource)
|
||||
|
||||
if resourceType(resource) == "pxc" {
|
||||
resources = append(resources,
|
||||
"perconaxtradbbackups",
|
||||
"perconaxtradbclusterbackups",
|
||||
"perconaxtradbclusterrestores",
|
||||
"perconaxtradbclusters")
|
||||
@@ -78,16 +77,32 @@ func New(location, namespace, resource string) Dumper {
|
||||
"perconaservermongodbrestores",
|
||||
"perconaservermongodbs",
|
||||
)
|
||||
} else if resourceType(resource) == "pg" {
|
||||
resources = append(resources,
|
||||
"perconapgclusters",
|
||||
"pgclusters",
|
||||
"pgpolicies",
|
||||
"pgreplicas",
|
||||
"pgtasks",
|
||||
)
|
||||
} else if resourceType(resource) == "ps" {
|
||||
resources = append(resources,
|
||||
"perconaservermysqlbackups",
|
||||
"perconaservermysqlrestores",
|
||||
"perconaservermysqls",
|
||||
)
|
||||
}
|
||||
}
|
||||
return Dumper{
|
||||
cmd: "kubectl",
|
||||
kubeconfig: kubeconfig,
|
||||
resources: resources,
|
||||
filePaths: filePaths,
|
||||
location: "cluster-dump",
|
||||
mode: int64(0o777),
|
||||
namespace: namespace,
|
||||
crType: resource,
|
||||
forwardport: forwardport,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,11 +202,14 @@ func (d *Dumper) DumpCluster() error {
|
||||
if len(pod.Labels) == 0 {
|
||||
continue
|
||||
}
|
||||
location = filepath.Join(d.location, ns.Name, pod.Name, "/pt-summary.txt")
|
||||
location = filepath.Join(d.location, ns.Name, pod.Name, "/summary.txt")
|
||||
component := resourceType(d.crType)
|
||||
if component == "psmdb" {
|
||||
component = "mongod"
|
||||
}
|
||||
if component == "ps" {
|
||||
component = "mysql"
|
||||
}
|
||||
if pod.Labels["app.kubernetes.io/instance"] != "" && pod.Labels["app.kubernetes.io/component"] != "" {
|
||||
resource := "secret/" + pod.Labels["app.kubernetes.io/instance"] + "-" + pod.Labels["app.kubernetes.io/component"]
|
||||
err = d.getResource(resource, ns.Name, true, tw)
|
||||
@@ -199,20 +217,27 @@ func (d *Dumper) DumpCluster() error {
|
||||
log.Printf("Error: get %s resource: %v", resource, err)
|
||||
}
|
||||
}
|
||||
if pod.Labels["app.kubernetes.io/component"] == component {
|
||||
if pod.Labels["app.kubernetes.io/component"] == component ||
|
||||
(component == "pg" && pod.Labels["pgo-pg-database"] == "true") {
|
||||
var crName string
|
||||
if component == "pg" {
|
||||
crName = pod.Labels["pg-cluster"]
|
||||
} else {
|
||||
crName = pod.Labels["app.kubernetes.io/instance"]
|
||||
}
|
||||
// Get summary
|
||||
output, err = d.getPodSummary(resourceType(d.crType), pod.Name, pod.Labels["app.kubernetes.io/instance"], tw)
|
||||
output, err = d.getPodSummary(resourceType(d.crType), pod.Name, crName, ns.Name, tw)
|
||||
if err != nil {
|
||||
d.logError(err.Error(), d.crType, pod.Name)
|
||||
err = addToArchive(location, d.mode, []byte(err.Error()), tw)
|
||||
if err != nil {
|
||||
log.Printf("Error: create pt-summary errors archive for pod %s in namespace %s: %v", pod.Name, ns.Name, err)
|
||||
log.Printf("Error: create summary errors archive for pod %s in namespace %s: %v", pod.Name, ns.Name, err)
|
||||
}
|
||||
} else {
|
||||
err = addToArchive(location, d.mode, output, tw)
|
||||
if err != nil {
|
||||
d.logError(err.Error(), "create pt-summary archive for pod "+pod.Name)
|
||||
log.Printf("Error: create pt-summary archive for pod %s: %v", pod.Name, err)
|
||||
d.logError(err.Error(), "create summary archive for pod "+pod.Name)
|
||||
log.Printf("Error: create summary archive for pod %s: %v", pod.Name, err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -247,6 +272,7 @@ func (d *Dumper) DumpCluster() error {
|
||||
// runCmd run command (Dumper.cmd) with given args, return it output
|
||||
func (d *Dumper) runCmd(args ...string) ([]byte, error) {
|
||||
var outb, errb bytes.Buffer
|
||||
args = append(args, "--kubeconfig", d.kubeconfig)
|
||||
cmd := exec.Command(d.cmd, args...)
|
||||
cmd.Stdout = &outb
|
||||
cmd.Stderr = &errb
|
||||
@@ -328,7 +354,7 @@ func (d *Dumper) getIndividualFiles(resource, namespace string, podName, path, l
|
||||
return addToArchive(location+"/"+path, d.mode, output, tw)
|
||||
}
|
||||
|
||||
func (d *Dumper) getPodSummary(resource, podName, crName string, tw *tar.Writer) ([]byte, error) {
|
||||
func (d *Dumper) getPodSummary(resource, podName, crName string, namespace string, tw *tar.Writer) ([]byte, error) {
|
||||
var (
|
||||
summCmdName string
|
||||
ports string
|
||||
@@ -336,33 +362,86 @@ func (d *Dumper) getPodSummary(resource, podName, crName string, tw *tar.Writer)
|
||||
)
|
||||
|
||||
switch resource {
|
||||
case "ps":
|
||||
fallthrough
|
||||
case "pxc":
|
||||
cr, err := d.getCR("pxc/" + crName)
|
||||
var pass, port string
|
||||
if d.forwardport != "" {
|
||||
port = d.forwardport
|
||||
} else {
|
||||
port = "3306"
|
||||
}
|
||||
cr, err := d.getCR(resource+"/"+crName, namespace)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "get cr")
|
||||
}
|
||||
pass, err := d.getDataFromSecret(cr.Spec.SecretName, "root")
|
||||
if cr.Spec.SecretName != "" {
|
||||
pass, err = d.getDataFromSecret(cr.Spec.SecretName, "root", namespace)
|
||||
} else {
|
||||
pass, err = d.getDataFromSecret(crName+"-secrets", "root", namespace)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "get password from pxc users secret")
|
||||
}
|
||||
ports = "3306:3306"
|
||||
ports = port + ":3306"
|
||||
summCmdName = "pt-mysql-summary"
|
||||
summCmdArgs = []string{"--host=127.0.0.1", "--port=3306", "--user=root", "--password=" + string(pass)}
|
||||
case "psmdb":
|
||||
cr, err := d.getCR("psmdb/" + crName)
|
||||
summCmdArgs = []string{"--host=127.0.0.1", "--port=" + port, "--user=root", "--password=" + string(pass)}
|
||||
case "pg":
|
||||
var user, pass, port string
|
||||
if d.forwardport != "" {
|
||||
port = d.forwardport
|
||||
} else {
|
||||
port = "5432"
|
||||
}
|
||||
cr, err := d.getCR("pgclusters", namespace)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "get cr")
|
||||
}
|
||||
pass, err := d.getDataFromSecret(cr.Spec.Secrets.Users, "MONGODB_CLUSTER_ADMIN_PASSWORD")
|
||||
if cr.Spec.SecretName != "" {
|
||||
user, err = d.getDataFromSecret(cr.Spec.SecretName, "username", namespace)
|
||||
} else {
|
||||
user, err = d.getDataFromSecret(crName+"-postgres-secret", "username", namespace)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "get user from PostgreSQL users secret")
|
||||
}
|
||||
if cr.Spec.SecretName != "" {
|
||||
pass, err = d.getDataFromSecret(cr.Spec.SecretName, "password", namespace)
|
||||
} else {
|
||||
pass, err = d.getDataFromSecret(crName+"-postgres-secret", "password", namespace)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "get password from PostgreSQL users secret")
|
||||
}
|
||||
ports = port + ":5432"
|
||||
summCmdName = "sh"
|
||||
summCmdArgs = []string{"-c", "curl https://raw.githubusercontent.com/percona/support-snippets/master/postgresql/pg_gather/gather.sql" +
|
||||
" 2>/dev/null | PGPASSWORD=" + string(pass) + " psql -X --host=127.0.0.1 --port=" + port + " --user=" + user}
|
||||
case "psmdb":
|
||||
var port string
|
||||
if d.forwardport != "" {
|
||||
port = d.forwardport
|
||||
} else {
|
||||
port = "27017"
|
||||
}
|
||||
cr, err := d.getCR("psmdb/"+crName, namespace)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "get cr")
|
||||
}
|
||||
user, err := d.getDataFromSecret(cr.Spec.Secrets.Users, "MONGODB_DATABASE_ADMIN_USER", namespace)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "get password from psmdb users secret")
|
||||
}
|
||||
ports = "27017:27017"
|
||||
pass, err := d.getDataFromSecret(cr.Spec.Secrets.Users, "MONGODB_DATABASE_ADMIN_PASSWORD", namespace)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "get password from psmdb users secret")
|
||||
}
|
||||
ports = port + ":27017"
|
||||
summCmdName = "pt-mongodb-summary"
|
||||
summCmdArgs = []string{"--username=clusterAdmin", "--password=" + pass, "--authenticationDatabase=admin", "127.0.0.1:27017"}
|
||||
summCmdArgs = []string{"--username=" + user, "--password=" + pass, "--authenticationDatabase=admin", "127.0.0.1:" + port}
|
||||
}
|
||||
|
||||
cmdPortFwd := exec.Command(d.cmd, "port-forward", "pod/"+podName, ports)
|
||||
cmdPortFwd := exec.Command(d.cmd, "port-forward", "pod/"+podName, ports, "-n", namespace, "--kubeconfig", d.kubeconfig)
|
||||
go func() {
|
||||
err := cmdPortFwd.Run()
|
||||
if err != nil {
|
||||
@@ -390,22 +469,22 @@ func (d *Dumper) getPodSummary(resource, podName, crName string, tw *tar.Writer)
|
||||
return []byte(fmt.Sprintf("stderr: %s, stdout: %s", errb.String(), outb.String())), nil
|
||||
}
|
||||
|
||||
func (d *Dumper) getCR(crName string) (crSecrets, error) {
|
||||
func (d *Dumper) getCR(crName string, namespace string) (crSecrets, error) {
|
||||
var cr crSecrets
|
||||
output, err := d.runCmd("get", crName, "-o", "json")
|
||||
output, err := d.runCmd("get", crName, "-o", "json", "-n", namespace)
|
||||
if err != nil {
|
||||
return cr, errors.Wrap(err, "get "+crName)
|
||||
}
|
||||
err = json.Unmarshal(output, &cr)
|
||||
if err != nil {
|
||||
return cr, errors.Wrap(err, "unmarshal psmdb cr")
|
||||
return cr, errors.Wrap(err, "unmarshal "+crName+" cr")
|
||||
}
|
||||
|
||||
return cr, nil
|
||||
}
|
||||
|
||||
func (d *Dumper) getDataFromSecret(secretName, dataName string) (string, error) {
|
||||
passEncoded, err := d.runCmd("get", "secrets/"+secretName, "--template={{.data."+dataName+"}}")
|
||||
func (d *Dumper) getDataFromSecret(secretName, dataName string, namespace string) (string, error) {
|
||||
passEncoded, err := d.runCmd("get", "secrets/"+secretName, "--template={{.data."+dataName+"}}", "-n", namespace)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "run get secret cmd")
|
||||
}
|
||||
@@ -422,6 +501,10 @@ func resourceType(s string) string {
|
||||
return "pxc"
|
||||
} else if s == "psmdb" || strings.HasPrefix(s, "psmdb/") {
|
||||
return "psmdb"
|
||||
} else if s == "pg" || strings.HasPrefix(s, "pg/") {
|
||||
return "pg"
|
||||
} else if s == "ps" || strings.HasPrefix(s, "ps/") {
|
||||
return "ps"
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
@@ -12,17 +12,21 @@ func main() {
|
||||
namespace := ""
|
||||
resource := ""
|
||||
clusterName := ""
|
||||
kubeconfig := ""
|
||||
forwardport := ""
|
||||
|
||||
flag.StringVar(&namespace, "namespace", "", "Namespace for collecting data. If empty data will be collected from all namespaces")
|
||||
flag.StringVar(&resource, "resource", "pxc", "Resource name. Default value - 'pxc'")
|
||||
flag.StringVar(&resource, "resource", "none", "Collect data, specific to the resource. Supported values: pxc, psmdb, pg, ps, none")
|
||||
flag.StringVar(&clusterName, "cluster", "", "Cluster name")
|
||||
flag.StringVar(&kubeconfig, "kubeconfig", "", "Path to kubeconfig")
|
||||
flag.StringVar(&forwardport, "forwardport", "", "Port to use for port forwarding")
|
||||
flag.Parse()
|
||||
|
||||
if len(clusterName) > 0 {
|
||||
resource += "/" + clusterName
|
||||
}
|
||||
|
||||
d := dumper.New("", namespace, resource)
|
||||
d := dumper.New("", namespace, resource, kubeconfig, forwardport)
|
||||
log.Println("Start collecting cluster data")
|
||||
|
||||
err := d.DumpCluster()
|
||||
|
@@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"strings"
|
||||
@@ -10,11 +11,33 @@ import (
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
/*
|
||||
This test requires:
|
||||
- Running K8 Operator installation
|
||||
- kubectl configuration files, one for each supported operator
|
||||
-- KUBECONFIG_PXC for K8SPXC
|
||||
-- KUBECONFIG_PS for K8SPS
|
||||
-- KUBECONFIG_PSMDB for K8SPSMDB
|
||||
-- KUBECONFIG_PG for K8SPG
|
||||
|
||||
You can additionally set option FORWARDPORT if you want to use custom port when testing summaries.
|
||||
|
||||
pt-mysql-summary and pt-mongodb-summary must be in the PATH.
|
||||
|
||||
Since running pt-k8s-debug-collector may take long time run go test with increase timeout:
|
||||
go test -timeout 6000s
|
||||
|
||||
We do not explicitly test --kubeconfig and --forwardport options, because they are used in other tests.
|
||||
*/
|
||||
|
||||
/*
|
||||
Tests collection of the individual files by pt-k8s-debug-collector.
|
||||
Requires running K8SPXC instance and kubectl, configured to access that instance by default.
|
||||
*/
|
||||
func TestIndividualFiles(t *testing.T) {
|
||||
if os.Getenv("KUBECONFIG_PXC") == "" {
|
||||
t.Skip("TestIndividualFiles requires K8SPXC")
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
cmd []string
|
||||
@@ -56,7 +79,7 @@ func TestIndividualFiles(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
cmd := exec.Command("../../../bin/pt-k8s-debug-collector")
|
||||
cmd := exec.Command("../../../bin/pt-k8s-debug-collector", "--kubeconfig", os.Getenv("KUBECONFIG_PXC"), "--forwardport", os.Getenv("FORWARDPORT"), "--resource", "pxc")
|
||||
if err := cmd.Run(); err != nil {
|
||||
t.Errorf("error executing pt-k8s-debug-collector: %s", err.Error())
|
||||
}
|
||||
@@ -77,3 +100,61 @@ func TestIndividualFiles(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Tests for supported values of the --resource option
|
||||
*/
|
||||
func TestResourceOption(t *testing.T) {
|
||||
testcmd := []string{"sh", "-c", "tar -tf cluster-dump.tar.gz --wildcards '*/summary.txt' 2>/dev/null | wc -l"}
|
||||
tests := []struct {
|
||||
name string
|
||||
want string
|
||||
kubeconfig string
|
||||
}{
|
||||
{
|
||||
name: "none",
|
||||
want: "0",
|
||||
kubeconfig: "",
|
||||
},
|
||||
{
|
||||
name: "pxc",
|
||||
want: "3",
|
||||
kubeconfig: os.Getenv("KUBECONFIG_PXC"),
|
||||
},
|
||||
{
|
||||
name: "ps",
|
||||
want: "3",
|
||||
kubeconfig: os.Getenv("KUBECONFIG_PS"),
|
||||
},
|
||||
{
|
||||
name: "psmdb",
|
||||
want: "3",
|
||||
kubeconfig: os.Getenv("KUBECONFIG_PSMDB"),
|
||||
},
|
||||
{
|
||||
name: "pg",
|
||||
want: "3",
|
||||
kubeconfig: os.Getenv("KUBECONFIG_PG"),
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
cmd := exec.Command("../../../bin/pt-k8s-debug-collector", "--kubeconfig", test.kubeconfig, "--forwardport", os.Getenv("FORWARDPORT"), "--resource", test.name)
|
||||
if err := cmd.Run(); err != nil {
|
||||
t.Errorf("error executing pt-k8s-debug-collector: %s", err.Error())
|
||||
}
|
||||
defer func() {
|
||||
cmd = exec.Command("rm", "-f", "cluster-dump.tar.gz")
|
||||
if err := cmd.Run(); err != nil {
|
||||
t.Errorf("error cleaning up test data: %s", err.Error())
|
||||
}
|
||||
}()
|
||||
out, err := exec.Command(testcmd[0], testcmd[1:]...).Output()
|
||||
if err != nil {
|
||||
t.Errorf("test %s, error running command %s:\n%s\n\nCommand output:\n%s", test.name, testcmd, err.Error(), out)
|
||||
}
|
||||
if strings.TrimRight(bytes.NewBuffer(out).String(), "\n") != test.want {
|
||||
t.Errorf("test %s, output is not as expected\nOutput: %s\nWanted: %s", test.name, out, test.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user