Skip to content

Ability to set pod environment variables on cluster resource #1794

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Apr 11, 2022

Conversation

dmvolod
Copy link
Contributor

@dmvolod dmvolod commented Feb 22, 2022

Fixes #1566
Closes #1209
Closes #1422
Closes #907
Closes #1807

Please pay attention, that this PR implementing an individual []EnvVar option to the cluster CR and has higher priority to the cluster pod_environment_secret and pod_environment_configmap options.

TODO (after approach approve)

  • Doc changes
  • Unit testing

@dmvolod
Copy link
Contributor Author

dmvolod commented Feb 28, 2022

@FxKu could you please to have a look at the fix approach. If it will be suitable, I will add docs and unit-test for it. Thanks in advance.

@cdmikechen
Copy link
Contributor

cdmikechen commented Mar 4, 2022

In CRD, Is there possible to add only some environment variables to pod? for example

spec:
  env:
    - name: ENV_1
      value: VALUE_1

@dmvolod
Copy link
Contributor Author

dmvolod commented Mar 4, 2022

In CRD, Is there possible to add only some environment variables to pod? for example

Not sure, that's good approach as will need to support both setup for predefined ConfigMap/Secret and current one. Common way much better and didn't overload CR if it's not needed

@dmvolod
Copy link
Contributor Author

dmvolod commented Mar 17, 2022

@FxKu could you please to find a time and have a look at the fix approach. If it will be suitable, I will add docs and unit-test for it. Thanks in advance.

@FxKu
Copy link
Member

FxKu commented Mar 21, 2022

Hey @dmvolod, while it looks elegant at first, I don't think it should be solved like this because only one way is possible - global config map or the need to add config maps for each cluster. The latter will be tedious if you need cluster-specific variables only for a handful of clusters while the rest of your fleet should be configured in the same way. Better have env variables from cluster-specific config maps / secrets to overwrite global ones - like we do it with other options, too. Probably, partly overwriting (in case of same env variables) will be most convenient.

@dmvolod
Copy link
Contributor Author

dmvolod commented Mar 21, 2022

Hey @dmvolod, while it looks elegant at first, I don't think it should be solved like this because only one way is possible - global config map or the need to add config maps for each cluster. The latter will be tedious if you need cluster-specific variables only for a handful of clusters while the rest of your fleet should be configured in the same way. Better have env variables from cluster-specific config maps / secrets to overwrite global ones - like we do it with other options, too. Probably, partly overwriting (in case of same env variables) will be most convenient.

Thanks for feedback, @FxKu . I'm also agree with approach to have a ConfigMap/Secret parameter for each cluster individually if needed and present. If you agree with this approach I will add these options to the CRD and implement logic to overwrite global parameters if CR parameters are present and find in the cluster ConfigMap/Secret.

@cdmikechen
Copy link
Contributor

I‘m looking forward to the progress of this PR.
I have similar needs at present. We need to deploy multiple Postgres to different namespaces and back up to different minio services.

@FxKu
Copy link
Member

FxKu commented Mar 23, 2022

@cdmikechen note that you can already run multiple operators next to each other configured differently. They could either watch only one namespace or you define a CONTROLLER_ID in deployment and manifests to specify ownership over clusters.

@cdmikechen
Copy link
Contributor

cdmikechen commented Mar 23, 2022

@cdmikechen note that you can already run multiple operators next to each other configured differently. They could either watch only one namespace or you define a CONTROLLER_ID in deployment and manifests to specify ownership over clusters.

@FxKu
Thanks~ It looks like a good solution for my needs. I used to deploy only one operator to manage all namespaces, which will really bring me some troubles.
I'll try it later and see if there will be any other problems.

@FxKu FxKu added this to the 1.9 milestone Mar 24, 2022
@dmvolod
Copy link
Contributor Author

dmvolod commented Mar 25, 2022

@FxKu please have a look at the new approach with individual []EnvVar option again and has a higher priority to the global cluster options. Thanks in advance.

@gc-jro
Copy link

gc-jro commented Mar 28, 2022

Hi @dmvolod, thanks for this PR.

Do you still plan to add the possibility to refer to a cluster specific secret for environment variables in the postgresql custom resource?

I’ve a slightly different set of requirements, where we maintain our cluster configuration in Git, but aren’t allowed to store confidential information (like wal-g backup settings) in plain text. To circumvent this, we use SealedSecrets [1] to store the settings encrypted in Git. In our k8s cluster the SealedSecrets get decrypted into normal secrets that can be used by the cluster. I’ve also the requirement that we’ve multiple postgresql clusters in the same namespace, and the need that they use different wal-g backup settings.

Therefore, it would be great if in addition to use individual []EnvVar settings in the postgresql CR, there would be an option to specify an individual secret in the postgresql CR that would be used for populating environment variables.
If you aren’t planning to add this option that’s totally fine, then I’ll ask my boss to get some time to patch the functionality in myself.

[1] https://github.com/bitnami-labs/sealed-secrets

@dmvolod
Copy link
Contributor Author

dmvolod commented Mar 29, 2022

Hi @gc-jro !

Yes, sure. Could you please to have a look at the EnvVar struct which is including EnvVarSource field and supports referencing to the Secret (SecretKeyRef).
https://github.com/kubernetes/api/blob/master/core/v1/types.go#L1977-L2015

What do you think about it?

@gc-jro
Copy link

gc-jro commented Mar 29, 2022

Ah I see. Thanks a lot for clearing that up for me. I really like it, it'll solve all my problems 😄

I'll just have to define something like

apiVersion: v1
kind: Secret
metadata:
  name: wal-g-envs
  namespace: yyy
data:
  BACKUP_NUM_TO_RETAIN: xxx
  ...
---
apiVersion: "acid.zalan.do/v1"
kind: postgresql
metadata:
  name: wal01-postgres-cluster
  namespace: yyy
spec:
  teamId: "wal01"
  volume:
    size: 20Gi
  env:
    - name: BACKUP_NUM_TO_RETAIN
      valueFrom:
        secretKeyRef:
          key: BACKUP_NUM_TO_RETAIN
          name: wal-g-envs
  ...

to forward the values from the secret to the database. Very neat.

Thank you very much. I can't wait to give it a spin once its merged into master.

@dmvolod dmvolod changed the title Ability to set pod_environment_secret and pod_environment_configmap on cluster resource Ability to set pod environment variables on cluster resource Mar 30, 2022
@FxKu
Copy link
Member

FxKu commented Mar 31, 2022

Thank @dmvolod ! Like the new approach much better. As you already pointed out, docs and unit test are the remaining bits to get this merged.

@FxKu FxKu removed this from the 1.9 milestone Apr 4, 2022
@FxKu
Copy link
Member

FxKu commented Apr 6, 2022

I got it working now. See my gist: https://gist.github.com/FxKu/0b4e0641f1c846a2a0edbc2c6ee6a0cc
Because I changed the expected list of []v1.EnvVar in TestPodEnvironmentConfigMapVariables the comparison with getPodEnvironmentConfigMapVariables result did not work anymore. But maybe it should be a test on its own together with fetching variables for the secrets and test clearly what overrides what (and also make it clearer in the docs, but I can help there).

@dmvolod
Copy link
Contributor Author

dmvolod commented Apr 6, 2022

I got it working now. See my gist: https://gist.github.com/FxKu/0b4e0641f1c846a2a0edbc2c6ee6a0cc
Because I changed the expected list of []v1.EnvVar in TestPodEnvironmentConfigMapVariables the comparison with getPodEnvironmentConfigMapVariables result did not work anymore. But maybe it should be a test on its own together with fetching variables for the secrets and test clearly what overrides what (and also make it clearer in the docs, but I can help there).

Thanks for test, @FxKu
Probably, we should move EnvVar logic to the generateSpiloPodEnvVars and utilize another tests for that. What do you think about it?

}
}
return false
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, it might be even better to do isEnvVarPresent in generateSpiloPodEnvVars, too, instead of appending duplicate variables and resolving it later with deduplicateEnvVars.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix logic, please review.

envVarConstant: "WAL_S3_BUCKET",
envVarValue: "custom-s3-bucket",
},
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

custom variables should not be pre-pended so this addition is also obsolete.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is approach from the following point

  • A custom variable called like a hard-coded variable that can be overridden (like WAL_S3_BUCKET)

},
},
},
},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test should incl. 3 kinds of variables - like in my gist.

  1. A custom variable called like a hard-coded variable that cannot be overridden (I uses KUBERNETES_SCOPE_LABEL)
  2. A custom variable called like a hard-coded variable that can be overridden (like WAL_S3_BUCKET)
  3. And a custom variable that's not in the list of hard-coded variables. And there we can test, if a variable from c.Spec.Env overwrites on from environment ConfigMap and/or Secret.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, thanks will implement this options.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implemented tests, please review.

@FxKu
Copy link
Member

FxKu commented Apr 7, 2022

Ok aside from missing unit tests there's one problem that has to be fixed. Right now we only append env vars and rely on deduplicateEnvVars to come up with the right set in the end. That is, it will take only the first mention of a variable into account except when the variable starts with WAL_ or LOG_. Then it will take the last mention.

This logic will not work anymore now that we have a third layer, the cluster-specific Env.

  1. It MUST NOT override our hard-coded set of variables from generateSpiloPodEnvVars up until this line. Only append after that.
  2. MUST override the PodEnvironmentConfigMap and/or Secret. So we append before that. But then WAL_ or LOG_ settings from PodEnvironmentConfigMap and/or Secret would override c.Spec.Env because of the logic in deduplicateEnvVars.

That's why I suggested that we should not simply append to the list of envVars but only do so if the key does not exists yet. So basically what you partly did with isEnvVarPresent. But instead of adding this check everywhere, we better write an append function for EnvVar lists that incl. this check. Finally, deduplicateEnvVars can be removed.

@dmvolod
Copy link
Contributor Author

dmvolod commented Apr 7, 2022

That's why I suggested that we should not simply append to the list of envVars but only do so if the key does not exists yet. So basically what you partly did with isEnvVarPresent. But instead of adding this check everywhere, we better write an append function for EnvVar lists that incl. this check. Finally, deduplicateEnvVars can be removed.

Does it means that we need to utilize new appendEnvVars function everywhere inside the generateSpiloPodEnvVars and related functions?

@FxKu
Copy link
Member

FxKu commented Apr 7, 2022

Yes, inside generateSpiloPodEnvVars. The flow should be:

  1. envVars := []v1.EnvVar{...}
  2. append spiloCompathWalPathList
  3. append c.Spec.Env
  4. fetch from getPodEnvironmentSecretVariables and append
  5. fetch from getPodEnvironmentConfigMapVariables and append
  6. fetch from generateCloneEnvironment and append
  7. fetch from generateStandbyEnvironment and append
  8. append WAL_ LOG_ AZURE_ etc. variables

I don't see why anything related to spilo env vars should happen outside of generateSpiloPodEnvVars. Noticed that deduplicateEnvVars is also used for sidecars. So maybe it can stay then.

@dmvolod
Copy link
Contributor Author

dmvolod commented Apr 7, 2022

Yes, inside generateSpiloPodEnvVars. The flow should be:

  1. envVars := []v1.EnvVar{...}
  2. append spiloCompathWalPathList
  3. append c.Spec.Env
  4. fetch from getPodEnvironmentSecretVariables and append
  5. fetch from getPodEnvironmentConfigMapVariables and append
  6. fetch from generateCloneEnvironment and append
  7. fetch from generateStandbyEnvironment and append
  8. append WAL_ LOG_ AZURE_ etc. variables

I don't see why anything related to spilo env vars should happen outside of generateSpiloPodEnvVars. Noticed that deduplicateEnvVars is also used for sidecars. So maybe it can stay then.

Thanks for idea, please have a look at the code. Added functions and changed from plain append to the new one.

@FxKu
Copy link
Member

FxKu commented Apr 11, 2022

👍

1 similar comment
@sdudoladov
Copy link
Member

👍

@sdudoladov sdudoladov merged commit 9bcb25a into zalando:master Apr 11, 2022
@FxKu
Copy link
Member

FxKu commented Apr 11, 2022

Thanks @dmvolod for your contribution. Good collaboration!

@dmvolod
Copy link
Contributor Author

dmvolod commented Apr 11, 2022

Thanks @FxKu and @sdudoladov for review and ideas.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
5 participants