[UI] support Postgres version and pod resource changes + adding IOPS and throughput config options (#1824)
This commit is contained in:
		
							parent
							
								
									654d22d04a
								
							
						
					
					
						commit
						d6641a9b0f
					
				|  | @ -126,6 +126,7 @@ edit | |||
|         if (i.metadata.selfLink) { delete i.metadata.selfLink } | ||||
|         if (i.metadata.uid) { delete i.metadata.uid } | ||||
|         if (i.metadata.resourceVersion) { delete i.metadata.resourceVersion } | ||||
|         if (i.metadata.managedFields) { delete i.metadata.managedFields } | ||||
| 
 | ||||
|         this.update() | ||||
|         this.refs.yamlNice.innerHTML = yamlParser.safeDump(i.postgresql, {sortKeys: true}) | ||||
|  | @ -138,7 +139,15 @@ edit | |||
|         o.spec.enableMasterLoadBalancer = i.spec.enableMasterLoadBalancer || false | ||||
|         o.spec.enableReplicaLoadBalancer = i.spec.enableReplicaLoadBalancer || false | ||||
|         o.spec.enableConnectionPooler = i.spec.enableConnectionPooler || false | ||||
|         o.spec.volume = { size: i.spec.volume.size } | ||||
| 
 | ||||
|         o.spec.volume = { | ||||
|           size: i.spec.volume.size, | ||||
|           throughput: i.spec.volume.throughput || 125, | ||||
|           iops: i.spec.volume.iops || 3000 | ||||
|         } | ||||
| 
 | ||||
|         o.spec.postgresql = {} | ||||
|         o.spec.postgresql.version = i.spec.postgresql.version | ||||
| 
 | ||||
|         if ('users' in i.spec && typeof i.spec.users === 'object') { | ||||
|           o.spec.users = Object.mapValues(i.spec.users, roleFlags => | ||||
|  | @ -166,7 +175,7 @@ edit | |||
|               ].forEach(resourceType => { | ||||
|                 if (resourceType in resources) { | ||||
|                   const resourceClaim = resources[resourceType] | ||||
|                   if (typeof resourceClaim === '') { | ||||
|                   if (typeof resourceClaim === 'string') { | ||||
|                     o.spec.resources[section][resourceType] = resources[resourceType] | ||||
|                   } | ||||
|                 } | ||||
|  |  | |||
|  | @ -13,6 +13,6 @@ help-general | |||
|     h3 Basics | ||||
| 
 | ||||
|     p. | ||||
|       The PostgreSQL operator will use your definition to create a new | ||||
|       The Postgres Operator will use your definition to create a new | ||||
|       PostgreSQL cluster for you. You can either copy the yaml definition | ||||
|       to the repositiory or you can just hit create cluster. | ||||
|       to a repositiory or hit create cluster (not available in prod). | ||||
|  |  | |||
|  | @ -266,6 +266,37 @@ new | |||
|                   ) | ||||
|                   .input-group-addon | ||||
|                     .input-units Gi | ||||
|             tr | ||||
|               td  | ||||
|               td Specify Iops and Throughput only if you need more than the default 3000 Iops and 125Mb/s EBS provides. | ||||
| 
 | ||||
|             tr | ||||
|               td Iops | ||||
|               td | ||||
|                 .input-group | ||||
|                   input.form-control( | ||||
|                     ref='iops' | ||||
|                     type='number' | ||||
|                     value='{ iops }' | ||||
|                     onchange='{ iopsChange }' | ||||
|                     onkeyup='{ iopsChange }' | ||||
|                   ) | ||||
|                   .input-group-addon | ||||
|                     .input-units | ||||
| 
 | ||||
|             tr | ||||
|               td Througput | ||||
|               td | ||||
|                 .input-group | ||||
|                   input.form-control( | ||||
|                     ref='throughput' | ||||
|                     type='number' | ||||
|                     value='{ throughput }' | ||||
|                     onchange='{ throughputChange }' | ||||
|                     onkeyup='{ throughputChange }' | ||||
|                   ) | ||||
|                   .input-group-addon | ||||
|                     .input-units MB/s | ||||
| 
 | ||||
|             tr(if='{ config.users_visible }') | ||||
|               td | ||||
|  | @ -509,7 +540,9 @@ new | |||
|         enableConnectionPooler: true | ||||
|         {{/if}} | ||||
|         volume: | ||||
|           size: "{{ volumeSize }}Gi" | ||||
|           size: "{{ volumeSize }}Gi"{{#if iops}} | ||||
|           iops: {{ iops }}{{/if}}{{#if throughput}} | ||||
|           throughput: {{ throughput }}{{/if}} | ||||
|         {{#if users}} | ||||
|         users:{{#each users}} | ||||
|           {{ state }}: []{{/each}}{{/if}} | ||||
|  | @ -560,6 +593,8 @@ new | |||
|         enableReplicaLoadBalancer: this.enableReplicaLoadBalancer, | ||||
|         enableConnectionPooler: this.enableConnectionPooler, | ||||
|         volumeSize: this.volumeSize, | ||||
|         iops: this.iops, | ||||
|         throughput: this.throughput, | ||||
|         users: this.users.valids, | ||||
|         databases: this.databases.valids, | ||||
|         ranges: this.ranges, | ||||
|  | @ -624,6 +659,14 @@ new | |||
|       this.volumeSize = +e.target.value | ||||
|     } | ||||
| 
 | ||||
|     this.iopsChange = e => { | ||||
|       this.iops = +e.target.value | ||||
|     } | ||||
| 
 | ||||
|     this.throughputChange = e => { | ||||
|       this.throughput = +e.target.value | ||||
|     } | ||||
| 
 | ||||
|     this.updateDNSName = () => { | ||||
|       this.dnsName = this.config.dns_format_string.format( | ||||
|         this.name, | ||||
|  |  | |||
|  | @ -69,7 +69,7 @@ postgresqls | |||
|             td { cpu } / { cpu_limit } | ||||
|             td { memory } / { memory_limit } | ||||
|             td { volume_size } | ||||
|             td { calcCosts(nodes, cpu, memory, volume_size) }$ | ||||
|             td { calcCosts(nodes, cpu, memory, volume_size, iops, throughput) }$ | ||||
| 
 | ||||
|             td | ||||
| 
 | ||||
|  | @ -152,7 +152,7 @@ postgresqls | |||
|             td { cpu } / { cpu_limit } | ||||
|             td { memory } / { memory_limit } | ||||
|             td { volume_size } | ||||
|             td { calcCosts(nodes, cpu, memory, volume_size) }$ | ||||
|             td { calcCosts(nodes, cpu, memory, volume_size, iops, throughput) }$ | ||||
| 
 | ||||
|             td | ||||
| 
 | ||||
|  | @ -227,9 +227,22 @@ postgresqls | |||
|       + '/' + encodeURI(cluster.name) | ||||
|     ) | ||||
| 
 | ||||
|     const calcCosts = this.calcCosts = (nodes, cpu, memory, disk) => { | ||||
|         costs = Math.max(nodes, opts.config.min_pods) * (toCores(cpu) * opts.config.cost_core + toMemory(memory) * opts.config.cost_memory + toDisk(disk) * opts.config.cost_ebs) | ||||
|         return costs.toFixed(2) | ||||
|     const calcCosts = this.calcCosts = (nodes, cpu, memory, disk, iops, throughput) => { | ||||
|       podcount = Math.max(nodes, opts.config.min_pods) | ||||
|       corecost = toCores(cpu) * opts.config.cost_core | ||||
|       memorycost = toMemory(memory) * opts.config.cost_memory | ||||
|       diskcost = toDisk(disk) * opts.config.cost_ebs | ||||
|       iopscost = 0 | ||||
|       if (iops !== undefined && iops > 3000) { | ||||
|         iopscost = (iops - 3000) * opts.config.cost_iops | ||||
|       } | ||||
|       throughputcost = 0 | ||||
|       if (throughput !== undefined && throughput > 125) { | ||||
|         throughputcost = (throughput - 125) * opts.config.cost_throughput | ||||
|       } | ||||
| 
 | ||||
|       costs = podcount * (corecost + memorycost + diskcost + iopscost + throughputcost) | ||||
|        return costs.toFixed(2) | ||||
|     } | ||||
| 
 | ||||
|     const toDisk = this.toDisk = value => { | ||||
|  | @ -253,6 +266,11 @@ postgresqls | |||
|         value = Number(value) | ||||
|         return value | ||||
|       } | ||||
|       else if(value.endsWith("Ti")) { | ||||
|         value = value.substring(0, value.length-2) | ||||
|         value = Number(value) * 1000 | ||||
|         return value | ||||
|       } | ||||
| 
 | ||||
|       return value | ||||
|     } | ||||
|  |  | |||
|  | @ -62,7 +62,9 @@ spec: | |||
|                   "replica_load_balancer_visible": true, | ||||
|                   "resources_visible": true, | ||||
|                   "users_visible": true, | ||||
|                   "cost_ebs": 0.119, | ||||
|                   "cost_ebs": 0.0952, | ||||
|                   "cost_iops": 0.006, | ||||
|                   "cost_throughput": 0.0476, | ||||
|                   "cost_core": 0.0575, | ||||
|                   "cost_memory": 0.014375, | ||||
|                   "postgresql_versions": [ | ||||
|  |  | |||
|  | @ -89,8 +89,10 @@ TARGET_NAMESPACE = getenv('TARGET_NAMESPACE') | |||
| GOOGLE_ANALYTICS = getenv('GOOGLE_ANALYTICS', False) | ||||
| MIN_PODS= getenv('MIN_PODS', 2) | ||||
| 
 | ||||
| # storage pricing, i.e. https://aws.amazon.com/ebs/pricing/ | ||||
| COST_EBS = float(getenv('COST_EBS', 0.119))  # GB per month | ||||
| # storage pricing, i.e. https://aws.amazon.com/ebs/pricing/ (e.g. Europe - Franfurt) | ||||
| COST_EBS = float(getenv('COST_EBS', 0.0952))  # GB per month | ||||
| COST_IOPS = float(getenv('COST_IOPS', 0.006))  # IOPS per month above 3000 baseline | ||||
| COST_THROUGHPUT = float(getenv('COST_THROUGHPUT', 0.0476))  # MB/s per month above 125 MB/s baseline | ||||
| 
 | ||||
| # compute costs, i.e. https://www.ec2instances.info/?region=eu-central-1&selected=m5.2xlarge | ||||
| COST_CORE = 30.5 * 24 * float(getenv('COST_CORE', 0.0575))  # Core per hour m5.2xlarge / 8. | ||||
|  | @ -308,6 +310,8 @@ DEFAULT_UI_CONFIG = { | |||
|     'pgui_link': '', | ||||
|     'static_network_whitelist': {}, | ||||
|     'cost_ebs': COST_EBS, | ||||
|     'cost_iops': COST_IOPS, | ||||
|     'cost_throughput': COST_THROUGHPUT, | ||||
|     'cost_core': COST_CORE, | ||||
|     'cost_memory': COST_MEMORY, | ||||
|     'min_pods': MIN_PODS | ||||
|  | @ -487,6 +491,8 @@ def get_postgresqls(): | |||
|             'cpu': spec.get('resources', {}).get('requests', {}).get('cpu', 0), | ||||
|             'cpu_limit': spec.get('resources', {}).get('limits', {}).get('cpu', 0), | ||||
|             'volume_size': spec.get('volume', {}).get('size', 0), | ||||
|             'iops': spec.get('volume', {}).get('iops', 3000), | ||||
|             'throughput': spec.get('volume', {}).get('throughput', 125), | ||||
|             'team': ( | ||||
|                 spec.get('teamId') or | ||||
|                 metadata.get('labels', {}).get('team', '') | ||||
|  | @ -614,6 +620,28 @@ def update_postgresql(namespace: str, cluster: str): | |||
| 
 | ||||
|         spec['volume'] = {'size': size} | ||||
| 
 | ||||
|     if ( | ||||
|         'volume' in postgresql['spec'] | ||||
|         and 'iops' in postgresql['spec']['volume'] | ||||
|         and postgresql['spec']['volume']['iops'] != None | ||||
|     ): | ||||
|         iops = int(postgresql['spec']['volume']['iops']) | ||||
|         if not 'volume' in spec: | ||||
|             spec['volume'] = {} | ||||
| 
 | ||||
|         spec['volume']['iops'] = iops | ||||
| 
 | ||||
|     if ( | ||||
|         'volume' in postgresql['spec'] | ||||
|         and 'throughput' in postgresql['spec']['volume'] | ||||
|         and postgresql['spec']['volume']['throughput'] != None | ||||
|     ): | ||||
|         throughput = int(postgresql['spec']['volume']['throughput']) | ||||
|         if not 'volume' in spec: | ||||
|             spec['volume'] = {} | ||||
| 
 | ||||
|         spec['volume']['throughput'] = throughput | ||||
| 
 | ||||
|     if 'enableConnectionPooler' in postgresql['spec']: | ||||
|         cp = postgresql['spec']['enableConnectionPooler'] | ||||
|         if not cp: | ||||
|  | @ -758,6 +786,27 @@ def update_postgresql(namespace: str, cluster: str): | |||
|                     owner_username=owner_username, | ||||
|                 ) | ||||
| 
 | ||||
|     resource_types = ["cpu","memory"] | ||||
|     resource_constraints = ["requests","limits"] | ||||
|     if "resources" in postgresql["spec"]: | ||||
|         spec["resources"] = {} | ||||
| 
 | ||||
|         res = postgresql["spec"]["resources"] | ||||
|         for rt in resource_types: | ||||
|             for rc in resource_constraints: | ||||
|                 if rc in res: | ||||
|                     if rt in res[rc]: | ||||
|                         if not rc in spec["resources"]: | ||||
|                             spec["resources"][rc] = {} | ||||
|                         spec["resources"][rc][rt] = res[rc][rt] | ||||
| 
 | ||||
|     if "postgresql" in postgresql["spec"]: | ||||
|         if "version" in postgresql["spec"]["postgresql"]: | ||||
|             if "postgresql" not in spec: | ||||
|                 spec["postgresql"]={} | ||||
| 
 | ||||
|             spec["postgresql"]["version"] = postgresql["spec"]["postgresql"]["version"] | ||||
| 
 | ||||
|     o['spec'].update(spec) | ||||
| 
 | ||||
|     apply_postgresql(get_cluster(), namespace, cluster, o) | ||||
|  |  | |||
|  | @ -19,7 +19,9 @@ default_operator_ui_config='{ | |||
|   "nat_gateways_visible": false, | ||||
|   "resources_visible": true, | ||||
|   "users_visible": true, | ||||
|   "cost_ebs": 0.119, | ||||
|   "cost_ebs": 0.0952, | ||||
|   "cost_iops": 0.006, | ||||
|   "cost_throughput": 0.0476, | ||||
|   "cost_core": 0.0575, | ||||
|   "cost_memory": 0.014375, | ||||
|   "postgresql_versions": [ | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue