Skip to content

Commit

Permalink
minio storage: support dry run and container spec overrides
Browse files Browse the repository at this point in the history
  • Loading branch information
OriHoch committed Apr 22, 2019
1 parent f97c97e commit ae59dc6
Show file tree
Hide file tree
Showing 5 changed files with 198 additions and 22 deletions.
6 changes: 4 additions & 2 deletions ckan_cloud_operator/providers/storage/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@ def storage():
@click.option('--provider-id')
@click.option('--storage-suffix')
@click.option('--disk-name')
def initialize(interactive, provider_id, storage_suffix, disk_name):
@click.option('--dry-run', is_flag=True)
def initialize(interactive, provider_id, storage_suffix, disk_name, dry_run):
manager.initialize(interactive=interactive,
provider_id=provider_id,
storage_suffix=storage_suffix,
use_existing_disk_name=disk_name)
use_existing_disk_name=disk_name,
dry_run=dry_run)
logs.exit_great_success()

@storage.command()
Expand Down
5 changes: 3 additions & 2 deletions ckan_cloud_operator/providers/storage/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@
from .constants import PROVIDER_SUBMODULE


def initialize(interactive=False, provider_id=None, storage_suffix=None, use_existing_disk_name=None):
def initialize(interactive=False, provider_id=None, storage_suffix=None, use_existing_disk_name=None, dry_run=False):
get_provider(
default=minio_provider_id,
provider_id=provider_id
).initialize(
interactive=interactive,
storage_suffix=storage_suffix,
use_existing_disk_name=use_existing_disk_name
use_existing_disk_name=use_existing_disk_name,
dry_run=dry_run
)


Expand Down
43 changes: 25 additions & 18 deletions ckan_cloud_operator/providers/storage/minio/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,14 @@ def _config_interactive_set(default_values, namespace=None, is_secret=False, suf
import os
import binascii
import yaml
import json

from ckan_cloud_operator import kubectl
from ckan_cloud_operator import logs
from ckan_cloud_operator.routers import manager as routers_manager


def initialize(interactive=False, storage_suffix=None, use_existing_disk_name=None):
def initialize(interactive=False, storage_suffix=None, use_existing_disk_name=None, dry_run=False):
_config_interactive_set({
'disk-size-gb': None,
**({} if storage_suffix else {'router-name': routers_manager.get_default_infra_router_name()})
Expand All @@ -37,11 +39,12 @@ def initialize(interactive=False, storage_suffix=None, use_existing_disk_name=No
storage_suffix=storage_suffix,
use_existing_disk_name=use_existing_disk_name
),
storage_suffix=storage_suffix
storage_suffix=storage_suffix,
dry_run=dry_run
)
_apply_service(storage_suffix=storage_suffix)
_apply_service(storage_suffix=storage_suffix, dry_run=dry_run)
if not storage_suffix:
_update_route(storage_suffix=storage_suffix)
_update_route(storage_suffix=storage_suffix, dry_run=dry_run)
_set_provider()


Expand Down Expand Up @@ -76,12 +79,13 @@ def _apply_secret(storage_suffix=None):
_config_set(values={'MINIO_ACCESS_KEY': access_key, 'MINIO_SECRET_KEY': secret_key}, is_secret=True, suffix=storage_suffix)


def _apply_deployment(volume_spec, storage_suffix=None):
def _apply_deployment(volume_spec, storage_suffix=None, dry_run=False):
node_selector = volume_spec.pop('nodeSelector', None)
if node_selector:
pod_scheduling = {'nodeSelector': node_selector}
else:
pod_scheduling = {}
container_spec_overrides = _config_get('container-spec-overrides', required=False, default=None, suffix=storage_suffix)
kubectl.apply(kubectl.get_deployment(
_get_resource_name(suffix=storage_suffix),
_get_resource_labels(for_deployment=True, suffix=storage_suffix),
Expand Down Expand Up @@ -109,6 +113,7 @@ def _apply_deployment(volume_spec, storage_suffix=None):
'mountPath': '/export',
}
],
**(json.loads(container_spec_overrides) if container_spec_overrides else {})
}
],
'volumes': [
Expand All @@ -117,10 +122,10 @@ def _apply_deployment(volume_spec, storage_suffix=None):
}
}
}
))
), dry_run=dry_run)


def _apply_service(storage_suffix=None):
def _apply_service(storage_suffix=None, dry_run=False):
kubectl.apply(kubectl.get_resource(
'v1', 'Service',
_get_resource_name(suffix=storage_suffix),
Expand All @@ -133,7 +138,7 @@ def _apply_service(storage_suffix=None):
'app': _get_resource_labels(for_deployment=True, suffix=storage_suffix)['app']
}
}
))
), dry_run=dry_run)


def _get_or_create_volume(storage_suffix=None, use_existing_disk_name=None):
Expand All @@ -152,21 +157,23 @@ def _get_or_create_volume(storage_suffix=None, use_existing_disk_name=None):
return volume_spec


def _update_route(storage_suffix=None):
def _update_route(storage_suffix=None, dry_run=False):
backend_url_target_id = _get_backend_url_target_id(storage_suffix=storage_suffix)
router_name = _config_get('router-name', required=True, suffix=storage_suffix)
if not routers_manager.get_backend_url_routes(backend_url_target_id):
deployment_name = _get_resource_name(suffix=storage_suffix)
namespace = _get_namespace()
routers_manager.create_subdomain_route(
router_name,
{
'target-type': 'backend-url',
'target-resource-id': backend_url_target_id,
'backend-url': f'http://{deployment_name}.{namespace}:9000',
}
)
routers_manager.update(router_name, wait_ready=True)
subdomain_route = {
'target-type': 'backend-url',
'target-resource-id': backend_url_target_id,
'backend-url': f'http://{deployment_name}.{namespace}:9000',
}
if dry_run:
logs.info('create_subdomain_route', router_name, subdomain_route)
else:
routers_manager.create_subdomain_route(router_name, subdomain_route)
if not dry_run:
routers_manager.update(router_name, wait_ready=True)


def _get_namespace():
Expand Down
16 changes: 16 additions & 0 deletions docs/INFRA-MANAGEMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,3 +123,19 @@ Depending on instance, some paths can be set to public download:
```
mc policy download prod/ckan/instance/storage'*'
```

### Setting minio deployment container spec overrides

You can set overrides for the minio deployment container spec

For example, set resources:

```
ckan-cloud-operator config set --configmap-name ckan-cloud-provider-storage-minio container-spec-overrides '{"resources":{"requests":{"cpu": "1", memory": "1Gi"},"limits":{"memory":"2Gi"}}'
```

Initialize the storage provider to update the deployment, first with dry-run to validate:

```
ckan-cloud-operator storage initialize --dry-run
```
150 changes: 150 additions & 0 deletions notebooks/set minio deployment resources.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Set CPU/Memory resource requirements for Minio"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from ckan_cloud_operator import kubectl\n",
"\n",
"old_minio_pods = [pod for pod in kubectl.get('pod')['items'] if pod['metadata']['labels'].get('app') == 'provider-storage-minio']\n",
"assert len(old_minio_pods) == 1\n",
"old_minio_containers = old_minio_pods[0]['spec']['containers']\n",
"assert len(old_minio_containers) == 1"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import yaml\n",
"from IPython.core.display import HTML\n",
"\n",
"HTML('<h3>OLD RESOURECS</h3>\\n{}'.format(yaml.dump(old_minio_containers[0]['resources'], default_flow_style=False)))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Set new resources"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import json\n",
"from ckan_cloud_operator.config import manager as config_manager\n",
"\n",
"config_manager.set(\n",
" key='container-spec-overrides', \n",
" value=json.dumps({\n",
" \"resources\": {\n",
" \"requests\": {\n",
" \"cpu\": \"1\", \n",
" \"memory\": \"1Gi\"\n",
" },\n",
" \"limits\": {\n",
" \"memory\":\"2Gi\"\n",
" }\n",
" }\n",
" }),\n",
" configmap_name='ckan-cloud-provider-storage-minio'\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Apply deployment: Dry Run"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from ckan_cloud_operator.providers.storage.minio import manager as minio_manager\n",
"\n",
"minio_manager.initialize(dry_run=True)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Apply Deployment"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from ckan_cloud_operator.providers.storage.minio import manager as minio_manager\n",
"\n",
"minio_manager.initialize()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Check deployment progress"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import yaml\n",
"from ckan_cloud_operator import kubectl\n",
"\n",
"minio_pods = [pod for pod in kubectl.get('pod')['items'] if pod['metadata']['labels'].get('app') == 'provider-storage-minio']\n",
"pod_names = [pod['metadata']['name'] for pod in minio_pods]\n",
"print(yaml.dump(pod_names, default_flow_style=False))\n",
"\n",
"[print(kubectl.check_output(f'describe pod {pod_name}').decode()) for pod_name in pod_names]"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.3"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

0 comments on commit ae59dc6

Please sign in to comment.