-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
[New feature] Load balancer customization (haproxy-based) #4141
Conversation
025d214
to
1447ac4
Compare
@andrijapanicsb @svenvogel @rhtyd @DaanHoogland @onitake Any suggestions and comments are welcome ! |
@weizhouapache Can you provide test packages or should we build the PR ourselves? |
@onitake we can provide the packages. could you please tell me what os version you use ? |
@blueorangutan package |
@rhtyd a Jenkins job has been kicked to build packages. I'll keep you posted as I make progress. |
Packaging result: ✖centos7 ✔debian. JID-1606 |
@weizhouapache will this require a new systemvmtemplate? |
@rhtyd it requires haproxy 1.8+ for http2 support. As I remember haproxy 1.8 is installed in debian10 systemvm template. No other changes is needed in systemvm template |
@blueorangutan test |
@DaanHoogland a Trillian-Jenkins test job (centos7 mgmt + kvm-centos7) has been kicked to run smoke tests |
Trillian test result (tid-2382)
|
@weizhouapache can you look at failures? Thanks |
@blueorangutan package |
@rhtyd a Jenkins job has been kicked to build packages. I'll keep you posted as I make progress. |
@rhtyd I will do |
@rhtyd pushed a commit to fix it. can you re-kick off the tests ? |
@blueorangutan package |
@rhtyd a Jenkins job has been kicked to build packages. I'll keep you posted as I make progress. |
Packaging result: ✔centos7 ✔debian. JID-1752 |
It's a nice feature, is it possible to have it in 4.15 ? |
let's revisit this @weizhouapache with other VR agent/template improvements (if this is necessary or something new we should explore for ex https://wiki.nftables.org/wiki-nftables/index.php/Load_balancing) |
@weizhouapache can you please fix the conflicts here. thanks. |
@blueorangutan package |
@weizhouapache a Jenkins job has been kicked to build packages. I'll keep you posted as I make progress. |
Packaging result: ✔️ centos7 ✔️ centos8 ✔️ debian. SL-JID 419 |
} | ||
|
||
public void setLbConfigs(List<? extends LoadBalancerConfig> lbConfigs) { | ||
if (lbConfigs == null || lbConfigs.size() == 0) { |
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.
We could use org.apache.commons.lang3.ArrayUtils
here:
...
if (ArrayUtils.isEmpty(lbConfigs)) {
...
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.
@GutoVeronezi org.apache.commons.lang3.ArrayUtils
package don't have isEmpty method which accepts List object. I have to override it like:
...
ArrayUtils.isEmpty(new List[]{lbConfigs})
...
It imposes unnecessary conversion. What do you think?
@@ -103,4 +110,32 @@ public Long getCertId() { | |||
public Long getLbRuleId() { | |||
return lbRuleId; | |||
} | |||
|
|||
public boolean isForced() { | |||
return (forced != null) ? forced : false; |
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.
We could use org.apache.commons.lang3.BooleanUtils
here:
...
return BooleanUtils.toBoolean(forced);
...
if (lb == null) { | ||
return null; | ||
} | ||
return lb.getNetworkId(); |
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.
We could implement a ternary here.
} | ||
|
||
public boolean isForced() { | ||
return (forced != null) ? forced : false; |
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.
We could use org.apache.commons.lang3.BooleanUtils
here:
...
return BooleanUtils.toBoolean(forced);
...
LoadBalancerConfig config = null; | ||
try { | ||
config = _entityMgr.findById(LoadBalancerConfig.class, getEntityId()); |
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 config
is not referenced outside the try block, we could declare it inside.
if (lbMaxConn != null) { | ||
loadBalancingData.append(",lb.maxconn=").append(lbMaxConn); | ||
} | ||
if (lbFullConn != null) { | ||
loadBalancingData.append(",lb.fullconn=").append(lbFullConn); | ||
} | ||
if (lbTimeoutConnect != null) { | ||
loadBalancingData.append(",lb.timeout.connect=").append(lbTimeoutConnect); | ||
} | ||
if (lbTimeoutServer != null) { | ||
loadBalancingData.append(",lb.timeout.server=").append(lbTimeoutServer); | ||
} | ||
if (lbTimeoutClient != null) { | ||
loadBalancingData.append(",lb.timeout.client=").append(lbTimeoutClient); | ||
} | ||
if (lbBackendHttps != null) { | ||
loadBalancingData.append(",lb.backend.https=").append(lbBackendHttps); | ||
} | ||
if (lbHttp2 != null) { | ||
loadBalancingData.append(",http2=").append(lbHttp2); | ||
} | ||
if (serverMaxconn != null) { | ||
loadBalancingData.append(",server.maxconn=").append(serverMaxconn); | ||
} | ||
if (serverMinconn != null) { | ||
loadBalancingData.append(",server.minconn=").append(serverMinconn); | ||
} | ||
if (serverMaxqueue != null) { | ||
loadBalancingData.append(",server.maxqueue=").append(serverMaxqueue); | ||
} |
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 code seems repeated, but changing parameters; We could extract it to a method.
if (id != null) { | ||
sc.addAnd("id", SearchCriteria.Op.EQ, id); | ||
} | ||
if (scope != null) { | ||
sc.addAnd("scope", SearchCriteria.Op.EQ, scope); | ||
} | ||
if (networkId != null) { | ||
sc.addAnd("networkId", SearchCriteria.Op.EQ, networkId); | ||
} | ||
if (vpcId != null) { | ||
sc.addAnd("vpcId", SearchCriteria.Op.EQ, vpcId); | ||
} | ||
if (loadBalancerId != null) { | ||
sc.addAnd("loadBalancerId", SearchCriteria.Op.EQ, loadBalancerId); | ||
} | ||
if (name != null) { | ||
sc.addAnd("name", SearchCriteria.Op.EQ, name); | ||
} |
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 code seems repeated, but changing parameters; We could extract it to a method or create an addAndNotNull
to SearchCriteria
.
sc.addAnd("name", SearchCriteria.Op.EQ, name); | ||
} | ||
List<LoadBalancerConfigVO> configs = new ArrayList<LoadBalancerConfigVO>(); | ||
if (id != null || networkId != null || vpcId != null || loadBalancerId != null) { |
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.
We could use org.apache.commons.lang3.ObjectUtils
here:
...
if (ObjectUtils.anyNotNull(id, networkId...
...
} | ||
throw new InvalidParameterValueException("networkId is required"); | ||
} | ||
if (vpcId != null || loadBalancerId != null) { |
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.
We could use org.apache.commons.lang3.ObjectUtils
here:
...
ObjectUtils.anyNotNull(...
...
if (scope == Scope.Network) { | ||
if (networkId == null) { | ||
if (listAll) { | ||
return; | ||
} | ||
throw new InvalidParameterValueException("networkId is required"); | ||
} | ||
if (vpcId != null || loadBalancerId != null) { | ||
throw new InvalidParameterValueException("vpcId and loadBalancerId should be null if scope is Network"); | ||
} | ||
if (networkId == null) { | ||
throw new InvalidParameterValueException("networkId is required"); | ||
} | ||
NetworkVO network = _networkDao.findById(networkId); | ||
if (network == null) { | ||
throw new InvalidParameterValueException("Cannot find network by id " + networkId); | ||
} | ||
// Perform permission check | ||
_accountMgr.checkAccess(caller, null, true, network); | ||
if (network.getVpcId() != null) { | ||
throw new InvalidParameterValueException("network " + network.getName() + " is a VPC tier, please add LB configs to VPC instead"); | ||
} | ||
} else if (scope == Scope.Vpc) { | ||
if (vpcId == null) { | ||
if (listAll) { | ||
return; | ||
} | ||
throw new InvalidParameterValueException("vpcId is required"); | ||
} | ||
if (networkId != null || loadBalancerId != null) { | ||
throw new InvalidParameterValueException("networkId and loadBalancerId should be null if scope is Vpc"); | ||
} | ||
VpcVO vpc = _vpcDao.findById(vpcId); | ||
if (vpc == null) { | ||
throw new InvalidParameterValueException("Cannot find vpc by id " + vpcId); | ||
} | ||
// Perform permission check | ||
_accountMgr.checkAccess(caller, null, true, vpc); | ||
} else if (scope == Scope.LoadBalancerRule) { | ||
if (loadBalancerId == null) { | ||
if (listAll) { | ||
return; | ||
} | ||
throw new InvalidParameterValueException("loadBalancerId is required"); | ||
} | ||
if (networkId != null || vpcId != null) { | ||
throw new InvalidParameterValueException("networkId and vpcId should be null if scope is LoadBalancerRule"); | ||
} | ||
LoadBalancerVO rule = _lbDao.findById(loadBalancerId); | ||
if (rule == null) { | ||
throw new InvalidParameterValueException("Cannot find load balancer rule by id " + loadBalancerId); | ||
} | ||
if (networkId != null) { | ||
// Perform permission check | ||
checkPermission(Scope.Network, rule.getNetworkId(), null, null); | ||
} | ||
} |
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 code seems repeated, but changing parameters; We could extract it to a method.
There is a lot of code addition, but none unit testing or javadoc. IMHO we should add they. |
@ravening @soreana |
@weizhouapache Sure! I asked Neven to make a room for it. |
@soreana can you resolve that confict, please? |
ping @soreana can you please fix the conflicting files. |
Ping @weizhouapache I think some more work may be needed on this as now Debian 11 has moved to haproxy 2.x, should this be targeted for next milestone. I worry it may not be stable within two weeks, ie current tentative RC date. |
@rhtyd it is ok to me. |
@rhtyd @weizhouapache yes lets move it out of this milestone as this will not make it in time |
@rhtyd @weizhouapache Sure let's do this. |
@weizhouapache @rhtyd I have created a new pr for this in #5799 |
@ravening |
Description
As discussed in mailing list, create this PR for haproxy config customization.
FS: https://cwiki.apache.org/confluence/display/CLOUDSTACK/VR+haproxy+customization+in+CloudStack
Fixes #3789
It supports (or will support)
haproxy statistics uri, auth, enable/disable
global maxconn and maxpipes
timeout connection, client ,server globally and per rule
http, httpalive per rule
maxconn, fullconn per rule
maxconn, minconn, maxqueue per server in rule
transparent load balancer
SSL offloading
http2 support
Variable SSL configurations
TODO:
Types of changes
Screenshots (if appropriate):
How Has This Been Tested?