Skip to content

Commit

Permalink
Merge branch 'master' into dependabot/pip/docker/postgres-kanister-to…
Browse files Browse the repository at this point in the history
…ols/common-pip-c7a91ce0bf
  • Loading branch information
mergify[bot] authored Feb 4, 2025
2 parents e66f6e6 + c4534cd commit 5ed2678
Show file tree
Hide file tree
Showing 12 changed files with 437 additions and 179 deletions.
67 changes: 56 additions & 11 deletions docs/functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -938,6 +938,15 @@ Arguments:
| ---------- | :------: | ------ | ----------- |
| instanceID | Yes | string | ID of RDS instance you want to create snapshot of |
| dbEngine | No | string | Required in case of RDS Aurora instance. Supported DB Engines: `aurora` `aurora-mysql` and `aurora-postgresql` |
| credentialsSource | No | string | Source for aws credentials. Supported sources: `profile`, `secret`, `serviceaccount`. Default value is `profile` |
| credentialsSecret | No | string | Secret to get credentials from. Only used with `credentialsSource: secret`. Secret with this name should be referenced in the Actionset |
| region | No | string | AWS region to use. Derived from profile or serviceaccount if not set |

::: tip NOTE

`credentialsSource: serviceaccount` uses kanister operator service account. IAM role for service
account should be set up to access the RDS database.
:::

Outputs:

Expand Down Expand Up @@ -994,6 +1003,10 @@ Arguments:
| image | No | string | kanister-tools image to be used for running export job |
| podAnnotations | No | map[string]string | custom annotations for the temporary pod that gets created |
| podLabels | No | map[string]string | custom labels for the temporary pod that gets created |
| credentialsSource | No | string | Source for aws credentials. Supported sources: `profile`, `secret`, `serviceaccount`. Default value is `profile` |
| credentialsSecret | No | string | Secret to get credentials from. Only used with `credentialsSource: secret`. Secret with this name should be [referenced in the Actionset](templates.html#secrets) |
| region | No | string | AWS region to use. Derived from profile or serviceaccount if not set |


::: tip NOTE

Expand All @@ -1006,6 +1019,19 @@ associated with instance with `instanceID` and will pass the same. - If
set, `default` DB Subnet group will be used.
:::

::: tip NOTE

If `credentialsSource` is configured to `profile` (default behaviour), the profile used has to be
an S3 profile configured with the same region as the database snapshot.
If it's required to export to another region, `credentialSource: secret` or `credentialSource: serviceaccount` can be used.
:::

::: tip NOTE

`credentialsSource: serviceaccount` uses kanister operator service account. IAM role for service
account should be set up to access the RDS database.
:::

Outputs:

| Output | Type | Description |
Expand Down Expand Up @@ -1069,13 +1095,13 @@ stored in an object storage.

::: tip NOTE

\- If [snapshotID] is set, the function will restore RDS
instance from the RDS snapshot. Otherwise *backupID* needs
to be set to restore the RDS instance from data dump. - While restoring
the data from RDS snapshot if RDS instance (where we have to restore the
data) doesn\'t exist, the RDS instance will be created. But if the data
- If `snapshotID` is set, the function will restore RDS
instance from the RDS snapshot. Otherwise `backupID` needs
to be set to restore the RDS instance from data dump.
- While restoring the data from RDS snapshot if RDS instance (where we have to restore the
data) doesn't exist, the RDS instance will be created. But if the data
is being restored from the Object Storage (data dump) and the RDS
instance doesn\'t exist new RDS instance will not be created and will
instance doesn't exist new RDS instance will not be created and will
result in an error.
:::

Expand All @@ -1096,15 +1122,25 @@ Arguments:
| image | No | string | kanister-tools image to be used for running restore, only relevant when restoring from data dump (if `snapshotID` is empty) |
| podAnnotations | No | map[string]string | custom annotations for the temporary pod that gets created |
| podLabels | No | map[string]string | custom labels for the temporary pod that gets created |
| credentialsSource | No | string | Source for aws credentials. Supported sources: `profile`, `secret`, `serviceaccount`. Default value is `profile` |
| credentialsSecret | No | string | Secret to get credentials from. Only used with `credentialsSource: secret`. Secret with this name should be referenced in the Actionset |
| region | No | string | AWS region to use. Derived from profile or serviceaccount if not set |


::: tip NOTE

\- If `snapshotID` is not set, restore will be done from data dump. In
that case `backupID` [arg] is required. - If
`securityGroupID` argument is not set, `RestoreRDSSnapshot` will find
- If `snapshotID` is not set, restore will be done from data dump. In
that case `backupID` arg is required.
- If `securityGroupID` argument is not set, `RestoreRDSSnapshot` will find
out Security Group IDs associated with instance with `instanceID` and
will pass the same. - If `dbSubnetGroup` argument is not set, `default`
DB Subnet group will be used.
will pass the same.
- If `dbSubnetGroup` argument is not set, `default` DB Subnet group will be used.
:::

::: tip NOTE

`credentialsSource: serviceaccount` uses kanister operator service account. IAM role for service
account should be set up to access the RDS database.
:::

Outputs:
Expand Down Expand Up @@ -1153,6 +1189,15 @@ Arguments:
| Argument | Required | Type | Description |
| ---------- | :------: | ------ | ----------- |
| snapshotID | No | string | ID of the RDS snapshot |
| credentialsSource | No | string | Source for aws credentials. Supported sources: `profile`, `secret`, `serviceaccount`. Default value is `profile` |
| credentialsSecret | No | string | Secret to get credentials from. Only used with `credentialsSource: secret`. Secret with this name should be referenced in the Actionset |
| region | No | string | AWS region to use. Derived from profile or serviceaccount if not set |

::: tip NOTE

`credentialsSource: serviceaccount` uses kanister operator service account. IAM role for service
account should be set up to access the RDS database.
:::

Example:

Expand Down
103 changes: 76 additions & 27 deletions examples/aws-rds/postgresql/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ aws rds wait db-instance-available --db-instance-identifier=test-postgresql-inst

Create a configmap which contains information to connect to the RDS DB instance

```
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
Expand Down Expand Up @@ -82,6 +82,32 @@ data operations such as backup should go. This is stored as a `profiles.cr.kanis
requires a Profile reference to complete the action. This CR (`profiles.cr.kanister.io`)
can be shared between Kanister-enabled application instances.

### Configure a secret to access RDS

By default the blueprints in this example are using credentials from the profile to access RDS
resources.

If you want to export your backups to a different region or a different object store (recommended),
you need to provide alternative credential configuration.

Here we use k8s secret with AWS credentials.
You need to make sure credentials provided in this secret can be used to access RDS operations.

```yaml
---
apiVersion: v1
kind: Secret
metadata:
name: rds-secret
namespace: pgtestrds
type: secrets.kanister.io/aws
data:
aws_access_key_id: "<your access key id>"
aws_secret_access_key: "<you secret>"
role: ""
```
This secret needs to be referenced in the acitonset.
### Create Blueprint
Expand All @@ -97,6 +123,12 @@ So as you can see we will have to create a blueprint depending on how are we goi

Use `rds-postgres-snap-blueprint.yaml` or `rds-postgres-blueprint.yaml` Blueprint if you want to take backup using RDS snapshots or you can use `rds-postgres-dump-blueprint.yaml` Blueprint if you want to extract postgres dump from snapshot and push to S3 storage

**NOTE:**
- The `rds-postgres-dump-blueprint.yaml` blueprint demonstrates how to use credentials from the secret.
- The `rds-postgres-snap-blueprint.yaml` blueprint demonstrates how to use credentials from the profile.

To change that you can modify the blueprints using those examples and documentation in https://docs.kanister.io/functions.html#createrdssnapshot


```bash
$ kubectl create -f <blueprint> -n kasten-io
Expand All @@ -106,40 +138,57 @@ $ kubectl create -f <blueprint> -n kasten-io

You can now take a snapshot of the PostgreSQL RDS instance data using an ActionSet defining backup for this application. Create an ActionSet in the same namespace as the controller.

> If you have deployed your application which uses RDS instance in namespace other than `pgtestrds`, you need to modify the commands used below to use the correct namespace
Get profile:

```bash
$ kubectl get profile -n pgtestrds
NAME AGE
s3-profile-sph7s 2h
```

Create actionset file:

> Use correct blueprint name (one of `rds-postgres-dump-bp` or `rds-postgres-snapshot-bp`) you have created earlier
> If you have deployed your application which uses RDS instance in namespace other than `pgtestrds`, you need to modify the commands used below to use the correct namespace
> Please make sure `region` option corresponds to the AWS region where your RDS is deployed.

```yaml
apiVersion: cr.kanister.io/v1alpha1
kind: ActionSet
metadata:
name: rds-backup
namespace: kasten-io
spec:
actions:
- name: backup
blueprint: <blueprint-name>
object:
apiVersion: v1
name: dbconfig
namespace: pgtestrds
resource: configmaps
profile:
name: <your profile>
namespace: pgtestrds
secrets:
aws:
name: rds-secret
namespace: pgtestrds
options:
region: <rds region>
```

Where:
- dbconfig is a configmap holding RDS infromation
Please see pgtest/deploy/config.yaml for configmap format
- rds-secret is an AWS secret with access to RDS resources

# Use correct blueprint name (one of `rds-postgres-dump-bp` or `rds-postgres-snapshot-bp`) you have created earlier

cat <<EOF | kubectl apply -f -
> apiVersion: cr.kanister.io/v1alpha1
> kind: ActionSet
> metadata:
> name: rds-backup
> namespace: kasten-io
> spec:
> actions:
> - name: backup
> blueprint: <blueprint-name>
> object:
> apiVersion: v1
> name: dbconfig
> namespace: pgtestrds
> resource: configmaps
> profile:
> name: s3-profile-sph7s
> namespace: pgtestrds
> EOF
actionset.cr.kanister.io/rds-backup created

# Where,
# dbconfig is a configmap holding RDS infromation
# Please see pgtest/deploy/config.yaml for configmap format
Apply actionset:

```bash
$ kubectl apply -f rds-backup-actionset.yaml
actionset.cr.kanister.io/rds-backup created
# View the status of the actionset
$ kubectl --namespace kasten-io describe actionset rds-backup
Expand Down
12 changes: 12 additions & 0 deletions examples/aws-rds/postgresql/rds-postgres-dump-blueprint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ actions:
name: createSnapshot
args:
instanceID: '{{ index .Object.data "postgres.instanceid" }}'
credentialsSource: secret
credentialsSecret: aws
region: '{{ .Options.region }}'
- func: ExportRDSSnapshotToLocation
name: exportSnapshot
objects:
Expand All @@ -35,10 +38,16 @@ actions:
snapshotID: "{{ .Phases.createSnapshot.Output.snapshotID }}"
backupArtifactPrefix: test-postgresql-instance/postgres
dbSubnetGroup: "{{ .Phases.createSnapshot.Output.dbSubnetGroup }}"
credentialsSource: secret
credentialsSecret: aws
region: '{{ .Options.region }}'
- func: DeleteRDSSnapshot
name: deleteSnapshot
args:
snapshotID: "{{ .Phases.createSnapshot.Output.snapshotID }}"
credentialsSource: secret
credentialsSecret: aws
region: '{{ .Options.region }}'
restore:
inputArtifactNames:
- backupInfo
Expand All @@ -60,6 +69,9 @@ actions:
password: '{{ index .Phases.restoreSnapshots.Secrets.dbsecret.Data "password" | toString }}'
dbEngine: "PostgreSQL"
dbSubnetGroup: "{{ .ArtifactsIn.backupInfo.KeyValue.dbSubnetGroup }}"
credentialsSource: secret
credentialsSecret: aws
region: '{{ .Options.region }}'
delete:
phases:
- func: KubeTask
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ require (
k8s.io/code-generator v0.31.5
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340
k8s.io/kubectl v0.31.5
sigs.k8s.io/controller-runtime v0.19.4
sigs.k8s.io/controller-runtime v0.19.5
sigs.k8s.io/structured-merge-diff/v4 v4.4.3
sigs.k8s.io/yaml v1.4.0
)
Expand Down Expand Up @@ -128,7 +128,7 @@ require (
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v4 v4.5.1 // indirect
github.com/golang-jwt/jwt/v5 v5.2.1 // indirect
github.com/golang/glog v1.2.2 // indirect
github.com/golang/glog v1.2.4 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/btree v1.0.1 // indirect
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -262,8 +262,8 @@ github.com/golang-jwt/jwt/v4 v4.5.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w
github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/glog v1.2.2 h1:1+mZ9upx1Dh6FmUTFR1naJ77miKiXgALjWOZ3NVFPmY=
github.com/golang/glog v1.2.2/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w=
github.com/golang/glog v1.2.4 h1:CNNw5U8lSiiBk7druxtSHHTsRWcxKoac6kZKm2peBBc=
github.com/golang/glog v1.2.4/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
Expand Down Expand Up @@ -867,8 +867,8 @@ k8s.io/utils v0.0.0-20200729134348-d5654de09c73/go.mod h1:jPW/WVKK9YHAvNhRxK0md/
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A=
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
sigs.k8s.io/controller-runtime v0.19.4 h1:SUmheabttt0nx8uJtoII4oIP27BVVvAKFvdvGFwV/Qo=
sigs.k8s.io/controller-runtime v0.19.4/go.mod h1:iRmWllt8IlaLjvTTDLhRBXIEtkCK6hwVBJJsYS9Ajf4=
sigs.k8s.io/controller-runtime v0.19.5 h1:rsE2cRYe0hK/rAAwiS1bwqgEcgCxTz9lavs3FMgLW0c=
sigs.k8s.io/controller-runtime v0.19.5/go.mod h1:iRmWllt8IlaLjvTTDLhRBXIEtkCK6hwVBJJsYS9Ajf4=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
sigs.k8s.io/kustomize/api v0.17.2 h1:E7/Fjk7V5fboiuijoZHgs4aHuexi5Y2loXlVOAVAG5g=
Expand Down
21 changes: 12 additions & 9 deletions pkg/function/create_rds_snapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,17 +74,12 @@ func (*createRDSSnapshotFunc) Name() string {
return CreateRDSSnapshotFuncName
}

func createRDSSnapshot(ctx context.Context, instanceID string, dbEngine RDSDBEngine, profile *param.Profile) (map[string]interface{}, error) {
func createRDSSnapshot(ctx context.Context, instanceID string, dbEngine RDSDBEngine, credentialsSource awsCredentialsSource, tp param.TemplateParams) (map[string]interface{}, error) {
var allocatedStorage int64
// Validate profile
if err := ValidateProfile(profile); err != nil {
return nil, errkit.Wrap(err, "Profile Validation failed")
}

// Get aws config from profile
awsConfig, region, err := getAWSConfigFromProfile(ctx, profile)
awsConfig, region, err := getAwsConfig(ctx, credentialsSource, tp)
if err != nil {
return nil, errkit.Wrap(err, "Failed to get AWS creds from profile")
return nil, errkit.Wrap(err, "Failed to get AWS creds")
}

// Create rds client
Expand Down Expand Up @@ -185,7 +180,12 @@ func (crs *createRDSSnapshotFunc) Exec(ctx context.Context, tp param.TemplatePar
return nil, err
}

return createRDSSnapshot(ctx, instanceID, dbEngine, tp.Profile)
credentialsSource, err := parseCredentialsSource(args)
if err != nil {
return nil, err
}

return createRDSSnapshot(ctx, instanceID, dbEngine, *credentialsSource, tp)
}

func (*createRDSSnapshotFunc) RequiredArgs() []string {
Expand All @@ -198,6 +198,9 @@ func (crs *createRDSSnapshotFunc) Arguments() []string {
return []string{
CreateRDSSnapshotInstanceIDArg,
CreateRDSSnapshotDBEngine,
CredentialsSourceArg,
CredentialsSecretArg,
RegionArg,
}
}

Expand Down
Loading

0 comments on commit 5ed2678

Please sign in to comment.