-
Notifications
You must be signed in to change notification settings - Fork 559
Secret Manager improvements and Seldon Core secret passing #529
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
Secret Manager improvements and Seldon Core secret passing #529
Conversation
5152c0a to
137c644
Compare
81dc84b to
894fceb
Compare
safoinme
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!!
| from zenml.secret import register_secret_schema_class | ||
| from zenml.secret.base_secret import BaseSecretSchema | ||
|
|
||
| SELDON_S3_SECRET_SCHEMA_TYPE = "seldon_s3" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just question about names, shouldn't be Rclone instead of seldon RCLONE_S3_SECRET_SCHEMA_TYPE ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would like to keep rclone as an implementation detail and not expose ZenML users to it if possible. To be honest, I am not too happy with naming this seldon either, given that most of these schemas are very similar to other ways of configuring AWS/GCP/Azure credentials for other libraries and tools. ZenML should have a unified way of handling authentication for "the big 3". I'm hoping that's something we can look into later.
| from zenml.enums import SecretSchemaType | ||
| from zenml.secret import register_secret_schema_class | ||
| from zenml.secret.base_secret import BaseSecretSchema | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's not possible to use this schema unless AWS integration is installed (boto3). shouldn't schemas be something more general that isn't tied to this integration?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as my other answer: yes, it should be more general. ZenML should provide a unified authentication/credentials management API for the 3 hyperscalers at least (AWS, Google and Azure), and the integrations should implement adapters that convert from the ZenML API to their own specific methods of handling authentication. However, that will be a bigger effort not strictly required for what I'm solving with this PR. Here I'm fixing what I think was a minor design issue that we had: the core ZenML code (src/zenml/secret/secret_schema_class_registry.py in this case) must not depend on integration code (see the from zenml.integrations.aws.secret_schemas import AWSSecretSchema line I removed). It must always be the other way around.
If we really need the AWS schema to be part of the ZenML core, then we need to move it outside of the AWS integration space.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@stefannica I haven't finished my review on this yet (will continue right after I post this comment), however I thought I'd quickly ask for one clarification in the meantime: Spinning up the local k3d cluster and mounting the volume had to be done in two steps when we first implemented it:
- Mount the volume into the K3D cluster (inside
local_deployment_utils.create_k3d_cluster) - Mount the volume inside the kubeflow pod (which is what your PR handles)
The volume mounted to the K3D cluster right now is the entire global config directory (which I guess is where all the artifact store/metadata store/deployer/secret manager files are located?). As soon as someone creates a custom StackComponent it seems that they could point local_path to anything but it won't work.
Is this something to maybe point out in the local_path docstring (or even validate that it's inside the global config directory and raise an error otherwise?) or do you have any ideas/plans to support arbitrary directories?
|
|
||
| if isinstance(metadata_store, SQLiteMetadataStore): | ||
| for stack_comp in stack.components.values(): | ||
| local_path = stack_comp.local_path |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I saw this loop in at least two places, do you think it makes sense to sort of aggregate them in a
@property
def local_paths(self) -> Set[str]
or similar on the Stack?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looked like a good idea initially, but as I started to implement it I realized that I also need the components associated with the paths, for logging related tasks.
| push_docker_image, | ||
| ) | ||
|
|
||
| # if the orchestrator is not running in a local k3d cluster, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As the kubernetes context is completely arbitrary, it might be
- pointing to a local k3d cluster
- or even more likely: unspecified but still be pointing to a non-local cluster (even I sometimes run pipelines and just set the kubectl context right before)
I don't really have any better solution to differentiate between local/remote and I think the current implementation is fine, just wanted to mention it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As discussed offline, this is going to change in my next PR that implements a new convention for what constitutes "local" Kubeflow orchestrators.
schustmi
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome changes, can't wait to integrate that into the experiment tracking components!
We agreed to enforce the convention that local paths are always relative to the ZenML global configuration directory. This is documented as a docstring now in the |
Describe changes
This PR updates the Secret Manager implementation to make it more flexible:
As a result of unifying how the paths of local stack components are mounted inside local Kubeflow containers, the PR also updates the MLflow model deployer so that it can be used with a local Kubeflow orchestrator.
The final goal of this PR is to update the Seldon Core model deployer so that it configures Kubernetes secrets automatically from ZenML secrets. The model deployer component now accepts a new
--secretconfiguration attribute that points to a ZenML secret that contains credentials needed to access the AWS S3, GCS or Azure Blob storage artifact store. Three secret schemas are also included to help with that.Implementation Details
Formalizing stack components with locally persisted state
The base
StackComponentclass gets a new property that all stack components with local folders, like the default Artifact Store, the default Metadata Store and the local Secrets Manager need to implement to provide the path of the local folder where information is persisted:This property is then used in the Kubeflow orchestrator to determine which local folders need to be mounted in the Kubeflow pipeline containers when the local Kubeflow orchestrator is used. The end result is that the local Secrets Manager folder is now automatically mounted in Kubeflow and can be accessed from pipeline steps. This is important for pipeline steps like the Seldon Core model deployment step that must access a ZenML secret with credentials needed to authenticate the Seldon Core model servers to the Artifact Store.
Allowing registration of secret schemas from integrations
Following the same approach used for stack component classes, the
BaseSecretSchematype is now aClassVarattribute of type string:This allows secret schemas to be more easily registered from any part of the code, ZenML integration or otherwise:
Seldon Core authentication through ZenML secrets
The Seldon Core Model Deployer gets a new
secretconfiguration attribute that points to a ZenML secret. The Model Deployer then converts that ZenML secret into a Kubernetes secret. The Seldon Core integration also provides 3 different secret schemas for the 3 flavors of Artifact Store: AWS, GCP and Azure.Pre-requisites
Please ensure you have done the following:
Types of changes