[UI] include load balancer in the monthly cost calculation (#1977)
This commit is contained in:
parent
529cdfc0b6
commit
18908e6097
|
|
@ -139,6 +139,9 @@ edit
|
||||||
o.spec.enableMasterLoadBalancer = i.spec.enableMasterLoadBalancer || false
|
o.spec.enableMasterLoadBalancer = i.spec.enableMasterLoadBalancer || false
|
||||||
o.spec.enableReplicaLoadBalancer = i.spec.enableReplicaLoadBalancer || false
|
o.spec.enableReplicaLoadBalancer = i.spec.enableReplicaLoadBalancer || false
|
||||||
o.spec.enableConnectionPooler = i.spec.enableConnectionPooler || false
|
o.spec.enableConnectionPooler = i.spec.enableConnectionPooler || false
|
||||||
|
o.spec.enableReplicaConnectionPooler = i.spec.enableReplicaConnectionPooler || false
|
||||||
|
o.spec.enableMasterPoolerLoadBalancer = i.spec.enableMasterPoolerLoadBalancer || false
|
||||||
|
o.spec.enableReplicaPoolerLoadBalancer = i.spec.enableReplicaPoolerLoadBalancer || false
|
||||||
|
|
||||||
o.spec.volume = {
|
o.spec.volume = {
|
||||||
size: i.spec.volume.size,
|
size: i.spec.volume.size,
|
||||||
|
|
|
||||||
|
|
@ -216,40 +216,73 @@ new
|
||||||
)
|
)
|
||||||
|
|
||||||
tr(if='{ [undefined, true].includes(config.master_load_balancer_visible) }')
|
tr(if='{ [undefined, true].includes(config.master_load_balancer_visible) }')
|
||||||
td Master load balancer
|
td Enable load balancer
|
||||||
td
|
td
|
||||||
label
|
ul.ips
|
||||||
input(
|
li
|
||||||
type='checkbox'
|
label
|
||||||
value='{ enableMasterLoadBalancer }'
|
input(
|
||||||
onchange='{ toggleEnableMasterLoadBalancer }'
|
type='checkbox'
|
||||||
)
|
value='{ enableMasterLoadBalancer }'
|
||||||
|
|
onchange='{ toggleEnableMasterLoadBalancer }'
|
||||||
| Enable master ELB
|
)
|
||||||
|
|
|
||||||
|
| Master
|
||||||
|
li(if='{ [undefined, true].includes(config.replica_load_balancer_visible) && instanceCount > 1 }')
|
||||||
|
label
|
||||||
|
input(
|
||||||
|
type='checkbox'
|
||||||
|
value='{ enableReplicaLoadBalancer }'
|
||||||
|
onchange='{ toggleEnableReplicaLoadBalancer }'
|
||||||
|
)
|
||||||
|
|
|
||||||
|
| Replica
|
||||||
|
|
||||||
tr(if='{ [undefined, true].includes(config.replica_load_balancer_visible) }')
|
tr(if='{ [undefined, true].includes(config.connection_pooler_visible) }')
|
||||||
td Replica load balancer
|
td Enable connection pooler
|
||||||
td
|
td
|
||||||
label
|
ul.ips
|
||||||
input(
|
li
|
||||||
type='checkbox'
|
label
|
||||||
value='{ enableReplicaLoadBalancer }'
|
input(
|
||||||
onchange='{ toggleEnableReplicaLoadBalancer }'
|
type='checkbox'
|
||||||
)
|
value='{ enableConnectionPooler }'
|
||||||
|
|
onchange='{ toggleEnableConnectionPooler }'
|
||||||
| Enable replica ELB
|
)
|
||||||
|
|
|
||||||
|
| Master
|
||||||
|
li(if='{ [undefined, true].includes(config.replica_connection_pooler_visible) && instanceCount > 1 }')
|
||||||
|
label
|
||||||
|
input(
|
||||||
|
type='checkbox'
|
||||||
|
value='{ enableReplicaConnectionPooler }'
|
||||||
|
onchange='{ toggleEnableReplicaConnectionPooler }'
|
||||||
|
)
|
||||||
|
|
|
||||||
|
| Replica
|
||||||
|
|
||||||
tr
|
tr(if='{ [undefined, true].includes(config.master_pooler_load_balancer_visible) }')
|
||||||
td Enable Connection Pool
|
td Enable connection pooler load balancer
|
||||||
td
|
td
|
||||||
label
|
ul.ips
|
||||||
input(
|
li
|
||||||
type='checkbox'
|
label
|
||||||
value='{ enableConnectionPooler }'
|
input(
|
||||||
onchange='{ toggleEnableConnectionPooler }'
|
type='checkbox'
|
||||||
)
|
value='{ enableMasterPoolerLoadBalancer }'
|
||||||
|
|
onchange='{ toggleEnableMasterPoolerLoadBalancer }'
|
||||||
| Enable Connection Pool (using PGBouncer)
|
)
|
||||||
|
|
|
||||||
|
| Master
|
||||||
|
li(if='{ [undefined, true].includes(config.replica_pooler_load_balancer_visible) && instanceCount > 1 }')
|
||||||
|
label
|
||||||
|
input(
|
||||||
|
type='checkbox'
|
||||||
|
value='{ enableReplicaPoolerLoadBalancer }'
|
||||||
|
onchange='{ toggleEnableReplicaPoolerLoadBalancer }'
|
||||||
|
)
|
||||||
|
|
|
||||||
|
| Replica
|
||||||
|
|
||||||
tr
|
tr
|
||||||
td Volume size
|
td Volume size
|
||||||
|
|
@ -539,6 +572,15 @@ new
|
||||||
{{#if enableConnectionPooler}}
|
{{#if enableConnectionPooler}}
|
||||||
enableConnectionPooler: true
|
enableConnectionPooler: true
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
{{#if enableReplicaConnectionPooler}}
|
||||||
|
enableReplicaConnectionPooler: true
|
||||||
|
{{/if}}
|
||||||
|
{{#if enableMasterPoolerLoadBalancer}}
|
||||||
|
enableMasterPoolerLoadBalancer: true
|
||||||
|
{{/if}}
|
||||||
|
{{#if enableReplicaPoolerLoadBalancer}}
|
||||||
|
enableReplicaPoolerLoadBalancer: true
|
||||||
|
{{/if}}
|
||||||
volume:
|
volume:
|
||||||
size: "{{ volumeSize }}Gi"{{#if iops}}
|
size: "{{ volumeSize }}Gi"{{#if iops}}
|
||||||
iops: {{ iops }}{{/if}}{{#if throughput}}
|
iops: {{ iops }}{{/if}}{{#if throughput}}
|
||||||
|
|
@ -592,6 +634,9 @@ new
|
||||||
enableMasterLoadBalancer: this.enableMasterLoadBalancer,
|
enableMasterLoadBalancer: this.enableMasterLoadBalancer,
|
||||||
enableReplicaLoadBalancer: this.enableReplicaLoadBalancer,
|
enableReplicaLoadBalancer: this.enableReplicaLoadBalancer,
|
||||||
enableConnectionPooler: this.enableConnectionPooler,
|
enableConnectionPooler: this.enableConnectionPooler,
|
||||||
|
enableReplicaConnectionPooler: this.enableReplicaConnectionPooler,
|
||||||
|
enableMasterPoolerLoadBalancer: this.enableMasterPoolerLoadBalancer,
|
||||||
|
enableReplicaPoolerLoadBalancer: this.enableReplicaPoolerLoadBalancer,
|
||||||
volumeSize: this.volumeSize,
|
volumeSize: this.volumeSize,
|
||||||
iops: this.iops,
|
iops: this.iops,
|
||||||
throughput: this.throughput,
|
throughput: this.throughput,
|
||||||
|
|
@ -655,6 +700,18 @@ new
|
||||||
this.enableConnectionPooler = !this.enableConnectionPooler
|
this.enableConnectionPooler = !this.enableConnectionPooler
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.toggleEnableReplicaConnectionPooler = e => {
|
||||||
|
this.enableReplicaConnectionPooler = !this.enableReplicaConnectionPooler
|
||||||
|
}
|
||||||
|
|
||||||
|
this.toggleEnableMasterPoolerLoadBalancer = e => {
|
||||||
|
this.enableMasterPoolerLoadBalancer = !this.enableMasterPoolerLoadBalancer
|
||||||
|
}
|
||||||
|
|
||||||
|
this.toggleEnableReplicaPoolerLoadBalancer = e => {
|
||||||
|
this.enableReplicaPoolerLoadBalancer = !this.enableReplicaPoolerLoadBalancer
|
||||||
|
}
|
||||||
|
|
||||||
this.volumeChange = e => {
|
this.volumeChange = e => {
|
||||||
this.volumeSize = +e.target.value
|
this.volumeSize = +e.target.value
|
||||||
}
|
}
|
||||||
|
|
@ -692,6 +749,11 @@ new
|
||||||
|
|
||||||
this.instanceCountChange = e => {
|
this.instanceCountChange = e => {
|
||||||
this.instanceCount = +e.target.value
|
this.instanceCount = +e.target.value
|
||||||
|
if (this.instanceCount < 2) {
|
||||||
|
this.enableReplicaLoadBalancer = false
|
||||||
|
this.enableReplicaConnectionPooler = false
|
||||||
|
this.enableReplicaPoolerLoadBalancer = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.checkClusterExists = () => (
|
this.checkClusterExists = () => (
|
||||||
|
|
@ -957,6 +1019,9 @@ new
|
||||||
this.enableMasterLoadBalancer = false
|
this.enableMasterLoadBalancer = false
|
||||||
this.enableReplicaLoadBalancer = false
|
this.enableReplicaLoadBalancer = false
|
||||||
this.enableConnectionPooler = false
|
this.enableConnectionPooler = false
|
||||||
|
this.enableReplicaConnectionPooler = false
|
||||||
|
this.enableMasterPoolerLoadBalancer = false
|
||||||
|
this.enableReplicaPoolerLoadBalancer = false
|
||||||
|
|
||||||
this.postgresqlVersion = this.postgresqlVersion = (
|
this.postgresqlVersion = this.postgresqlVersion = (
|
||||||
this.config.postgresql_versions[0]
|
this.config.postgresql_versions[0]
|
||||||
|
|
|
||||||
|
|
@ -168,10 +168,12 @@ postgresql
|
||||||
this.progress.dnsName = data.metadata.name + '.' + data.metadata.namespace
|
this.progress.dnsName = data.metadata.name + '.' + data.metadata.namespace
|
||||||
}
|
}
|
||||||
|
|
||||||
jQuery.get('/pooler/' + this.cluster_path).done(data => {
|
if (this.progress.poolerEnabled == true) {
|
||||||
this.progress.pooler = {"url": ""}
|
jQuery.get('/pooler/' + this.cluster_path).done(data => {
|
||||||
this.update()
|
this.progress.pooler = {"url": ""}
|
||||||
})
|
this.update()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
this.update()
|
this.update()
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,8 @@ postgresqls
|
||||||
| IOPS (-3000 baseline): 0.006$
|
| IOPS (-3000 baseline): 0.006$
|
||||||
br
|
br
|
||||||
| Throughput (-125 baseline): 0.0476$
|
| Throughput (-125 baseline): 0.0476$
|
||||||
|
br
|
||||||
|
| 1 ELB: 21.96$
|
||||||
th(stlye='width: 120px')
|
th(stlye='width: 120px')
|
||||||
|
|
||||||
tbody
|
tbody
|
||||||
|
|
@ -87,7 +89,7 @@ postgresqls
|
||||||
td { volume_size }
|
td { volume_size }
|
||||||
td { iops }
|
td { iops }
|
||||||
td { throughput }
|
td { throughput }
|
||||||
td { calcCosts(nodes, cpu, memory, volume_size, iops, throughput) }$
|
td { calcCosts(nodes, cpu, memory, volume_size, iops, throughput, num_elb) }$
|
||||||
|
|
||||||
td
|
td
|
||||||
|
|
||||||
|
|
@ -167,7 +169,9 @@ postgresqls
|
||||||
| IOPS (-3000 baseline): 0.006$
|
| IOPS (-3000 baseline): 0.006$
|
||||||
br
|
br
|
||||||
| Throughput (-125 baseline): 0.0476$
|
| Throughput (-125 baseline): 0.0476$
|
||||||
th(stlye='width: 120px')
|
br
|
||||||
|
| 1 ELB: 21.96$
|
||||||
|
th(style='width: 120px')
|
||||||
|
|
||||||
tbody
|
tbody
|
||||||
tr(
|
tr(
|
||||||
|
|
@ -188,7 +192,7 @@ postgresqls
|
||||||
td { volume_size }
|
td { volume_size }
|
||||||
td { iops }
|
td { iops }
|
||||||
td { throughput }
|
td { throughput }
|
||||||
td { calcCosts(nodes, cpu, memory, volume_size, iops, throughput) }$
|
td { calcCosts(nodes, cpu, memory, volume_size, iops, throughput, num_elb) }$
|
||||||
|
|
||||||
td
|
td
|
||||||
|
|
||||||
|
|
@ -263,10 +267,11 @@ postgresqls
|
||||||
+ '/' + encodeURI(cluster.name)
|
+ '/' + encodeURI(cluster.name)
|
||||||
)
|
)
|
||||||
|
|
||||||
const calcCosts = this.calcCosts = (nodes, cpu, memory, disk, iops, throughput) => {
|
const calcCosts = this.calcCosts = (nodes, cpu, memory, disk, iops, throughput, num_elb) => {
|
||||||
podcount = Math.max(nodes, opts.config.min_pods)
|
podcount = Math.max(nodes, opts.config.min_pods)
|
||||||
corecost = toCores(cpu) * opts.config.cost_core * 30.5 * 24
|
corecost = toCores(cpu) * opts.config.cost_core * 30.5 * 24
|
||||||
memorycost = toMemory(memory) * opts.config.cost_memory * 30.5 * 24
|
memorycost = toMemory(memory) * opts.config.cost_memory * 30.5 * 24
|
||||||
|
elbcost = num_elb * opts.config.cost_elb * 30.5 * 24
|
||||||
diskcost = toDisk(disk) * opts.config.cost_ebs
|
diskcost = toDisk(disk) * opts.config.cost_ebs
|
||||||
iopscost = 0
|
iopscost = 0
|
||||||
if (iops !== undefined && iops > opts.config.free_iops) {
|
if (iops !== undefined && iops > opts.config.free_iops) {
|
||||||
|
|
@ -283,7 +288,7 @@ postgresqls
|
||||||
throughputcost = (throughput - opts.config.free_throughput) * opts.config.cost_throughput
|
throughputcost = (throughput - opts.config.free_throughput) * opts.config.cost_throughput
|
||||||
}
|
}
|
||||||
|
|
||||||
costs = podcount * (Math.max(corecost, memorycost) + diskcost + iopscost + throughputcost)
|
costs = podcount * (Math.max(corecost, memorycost) + diskcost + iopscost + throughputcost) + elbcost
|
||||||
return costs.toFixed(2)
|
return costs.toFixed(2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -101,6 +101,7 @@ COST_THROUGHPUT = float(getenv('COST_THROUGHPUT', 0.0476)) # MB/s per month abo
|
||||||
# compute costs, i.e. https://www.ec2instances.info/?region=eu-central-1&selected=m5.2xlarge
|
# compute costs, i.e. https://www.ec2instances.info/?region=eu-central-1&selected=m5.2xlarge
|
||||||
COST_CORE = float(getenv('COST_CORE', 0.0575)) # Core per hour m5.2xlarge / 8.
|
COST_CORE = float(getenv('COST_CORE', 0.0575)) # Core per hour m5.2xlarge / 8.
|
||||||
COST_MEMORY = float(getenv('COST_MEMORY', 0.014375)) # Memory GB m5.2xlarge / 32.
|
COST_MEMORY = float(getenv('COST_MEMORY', 0.014375)) # Memory GB m5.2xlarge / 32.
|
||||||
|
COST_ELB = float(getenv('COST_ELB', 0.03)) # per hour
|
||||||
|
|
||||||
# maximum and limitation of IOPS and throughput
|
# maximum and limitation of IOPS and throughput
|
||||||
FREE_IOPS = float(getenv('FREE_IOPS', 3000))
|
FREE_IOPS = float(getenv('FREE_IOPS', 3000))
|
||||||
|
|
@ -334,6 +335,7 @@ DEFAULT_UI_CONFIG = {
|
||||||
'cost_throughput': COST_THROUGHPUT,
|
'cost_throughput': COST_THROUGHPUT,
|
||||||
'cost_core': COST_CORE,
|
'cost_core': COST_CORE,
|
||||||
'cost_memory': COST_MEMORY,
|
'cost_memory': COST_MEMORY,
|
||||||
|
'cost_elb': COST_ELB,
|
||||||
'min_pods': MIN_PODS,
|
'min_pods': MIN_PODS,
|
||||||
'free_iops': FREE_IOPS,
|
'free_iops': FREE_IOPS,
|
||||||
'free_throughput': FREE_THROUGHPUT,
|
'free_throughput': FREE_THROUGHPUT,
|
||||||
|
|
@ -523,6 +525,8 @@ def get_postgresqls():
|
||||||
'namespaced_name': namespace + '/' + name,
|
'namespaced_name': namespace + '/' + name,
|
||||||
'full_name': namespace + '/' + name + ('/' + uid if uid else ''),
|
'full_name': namespace + '/' + name + ('/' + uid if uid else ''),
|
||||||
'status': status,
|
'status': status,
|
||||||
|
'num_elb': spec.get('enableMasterLoadBalancer', 0) + spec.get('enableReplicaLoadBalancer', 0) + \
|
||||||
|
spec.get('enableMasterPoolerLoadBalancer', 0) + spec.get('enableReplicaPoolerLoadBalancer', 0),
|
||||||
}
|
}
|
||||||
for cluster in these(
|
for cluster in these(
|
||||||
read_postgresqls(
|
read_postgresqls(
|
||||||
|
|
@ -662,49 +666,20 @@ def update_postgresql(namespace: str, cluster: str):
|
||||||
|
|
||||||
spec['volume']['throughput'] = throughput
|
spec['volume']['throughput'] = throughput
|
||||||
|
|
||||||
if 'enableConnectionPooler' in postgresql['spec']:
|
additional_specs = ['enableMasterLoadBalancer',
|
||||||
cp = postgresql['spec']['enableConnectionPooler']
|
'enableReplicaLoadBalancer',
|
||||||
if not cp:
|
'enableConnectionPooler',
|
||||||
if 'enableConnectionPooler' in o['spec']:
|
'enableReplicaConnectionPooler',
|
||||||
del o['spec']['enableConnectionPooler']
|
'enableMasterPoolerLoadBalancer',
|
||||||
else:
|
'enableReplicaPoolerLoadBalancer',
|
||||||
spec['enableConnectionPooler'] = True
|
]
|
||||||
else:
|
|
||||||
if 'enableConnectionPooler' in o['spec']:
|
|
||||||
del o['spec']['enableConnectionPooler']
|
|
||||||
|
|
||||||
if 'enableReplicaConnectionPooler' in postgresql['spec']:
|
for var in additional_specs:
|
||||||
cp = postgresql['spec']['enableReplicaConnectionPooler']
|
if postgresql['spec'].get(var):
|
||||||
if not cp:
|
spec[var] = True
|
||||||
if 'enableReplicaConnectionPooler' in o['spec']:
|
|
||||||
del o['spec']['enableReplicaConnectionPooler']
|
|
||||||
else:
|
else:
|
||||||
spec['enableReplicaConnectionPooler'] = True
|
if var in o['spec']:
|
||||||
else:
|
del o['spec'][var]
|
||||||
if 'enableReplicaConnectionPooler' in o['spec']:
|
|
||||||
del o['spec']['enableReplicaConnectionPooler']
|
|
||||||
|
|
||||||
if 'enableReplicaLoadBalancer' in postgresql['spec']:
|
|
||||||
rlb = postgresql['spec']['enableReplicaLoadBalancer']
|
|
||||||
if not rlb:
|
|
||||||
if 'enableReplicaLoadBalancer' in o['spec']:
|
|
||||||
del o['spec']['enableReplicaLoadBalancer']
|
|
||||||
else:
|
|
||||||
spec['enableReplicaLoadBalancer'] = True
|
|
||||||
else:
|
|
||||||
if 'enableReplicaLoadBalancer' in o['spec']:
|
|
||||||
del o['spec']['enableReplicaLoadBalancer']
|
|
||||||
|
|
||||||
if 'enableMasterLoadBalancer' in postgresql['spec']:
|
|
||||||
rlb = postgresql['spec']['enableMasterLoadBalancer']
|
|
||||||
if not rlb:
|
|
||||||
if 'enableMasterLoadBalancer' in o['spec']:
|
|
||||||
del o['spec']['enableMasterLoadBalancer']
|
|
||||||
else:
|
|
||||||
spec['enableMasterLoadBalancer'] = True
|
|
||||||
else:
|
|
||||||
if 'enableMasterLoadBalancer' in o['spec']:
|
|
||||||
del o['spec']['enableMasterLoadBalancer']
|
|
||||||
|
|
||||||
if 'users' in postgresql['spec']:
|
if 'users' in postgresql['spec']:
|
||||||
spec['users'] = postgresql['spec']['users']
|
spec['users'] = postgresql['spec']['users']
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue