Skip to content
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

Closed
wants to merge 83 commits into from

Conversation

weizhouapache
Copy link
Member

@weizhouapache weizhouapache commented Jun 10, 2020

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)

  • Basic haproxy configurations:
    haproxy statistics uri, auth, enable/disable
    global maxconn and maxpipes
  • Basic configurations on rule
    timeout connection, client ,server globally and per rule
    http, httpalive per rule
    maxconn, fullconn per rule
    maxconn, minconn, maxqueue per server in rule
  • advanced features
    transparent load balancer
    SSL offloading
    http2 support
    Variable SSL configurations

TODO:

  • UI change on primate
  • unit tests

Types of changes

  • Breaking change (fix or feature that would cause existing functionality to change)
  • New feature (non-breaking change which adds functionality)
  • Bug fix (non-breaking change which fixes an issue)
  • Enhancement (improves an existing feature and functionality)
  • Cleanup (Code refactoring and cleanup, that may add test cases)

Screenshots (if appropriate):

How Has This Been Tested?

@weizhouapache weizhouapache reopened this Jul 21, 2020
@weizhouapache weizhouapache changed the title [WIP] Load balancer customization (haproxy-based) [New feature] Load balancer customization (haproxy-based) Jul 21, 2020
@weizhouapache weizhouapache marked this pull request as ready for review July 21, 2020 07:51
@weizhouapache
Copy link
Member Author

@andrijapanicsb @svenvogel @rhtyd @DaanHoogland @onitake
This PR is ready for review and testing !

Any suggestions and comments are welcome !

@onitake
Copy link
Contributor

onitake commented Jul 21, 2020

@weizhouapache Can you provide test packages or should we build the PR ourselves?
I haven't done a custom CloudStack build in a while, I'm not sure if I even have the necessary build/packaging environment any more...

@weizhouapache
Copy link
Member Author

weizhouapache commented Jul 21, 2020

@weizhouapache Can you provide test packages or should we build the PR ourselves?
I haven't done a custom CloudStack build in a while, I'm not sure if I even have the necessary build/packaging environment any more...

@onitake we can provide the packages. could you please tell me what os version you use ?

@rohityadavcloud
Copy link
Member

@blueorangutan package

@blueorangutan
Copy link

@rhtyd a Jenkins job has been kicked to build packages. I'll keep you posted as I make progress.

@blueorangutan
Copy link

Packaging result: ✖centos7 ✔debian. JID-1606

@rohityadavcloud
Copy link
Member

@weizhouapache will this require a new systemvmtemplate?

@weizhouapache
Copy link
Member Author

@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

@DaanHoogland
Copy link
Contributor

@blueorangutan test

@blueorangutan
Copy link

@DaanHoogland a Trillian-Jenkins test job (centos7 mgmt + kvm-centos7) has been kicked to run smoke tests

@blueorangutan
Copy link

Trillian test result (tid-2382)
Environment: kvm-centos7 (x2), Advanced Networking with Mgmt server 7
Total time taken: 50655 seconds
Marvin logs: https://github.com/blueorangutan/acs-prs/releases/download/trillian/pr4141-t2382-kvm-centos7.zip
Intermittent failure detected: /marvin/tests/smoke/test_loadbalance.py
Intermittent failure detected: /marvin/tests/smoke/test_network.py
Intermittent failure detected: /marvin/tests/smoke/test_usage.py
Intermittent failure detected: /marvin/tests/smoke/test_vpc_redundant.py
Smoke tests completed. 80 look OK, 3 have error(s)
Only failed tests results shown below:

Test Result Time (s) Test File
test_01_create_lb_rule_src_nat Error 0.10 test_loadbalance.py
test_02_create_lb_rule_non_nat Error 0.04 test_loadbalance.py
test_assign_and_removal_lb Error 0.06 test_loadbalance.py
test_delete_account Error 79.75 test_network.py
test_reboot_router Error 179.46 test_network.py
test_releaseIP Error 60.47 test_network.py
test_network_rules_acquired_public_ip_3_Load_Balancer_Rule Error 3.23 test_network.py
test_01_lb_usage Error 0.05 test_usage.py

@rohityadavcloud
Copy link
Member

@weizhouapache can you look at failures? Thanks

@rohityadavcloud
Copy link
Member

@blueorangutan package

@blueorangutan
Copy link

@rhtyd a Jenkins job has been kicked to build packages. I'll keep you posted as I make progress.

@weizhouapache
Copy link
Member Author

@weizhouapache can you look at failures? Thanks

@rhtyd I will do

@weizhouapache
Copy link
Member Author

@weizhouapache can you look at failures? Thanks

@rhtyd pushed a commit to fix it. can you re-kick off the tests ?

@rohityadavcloud
Copy link
Member

@blueorangutan package

@blueorangutan
Copy link

@rhtyd a Jenkins job has been kicked to build packages. I'll keep you posted as I make progress.

@blueorangutan
Copy link

Packaging result: ✔centos7 ✔debian. JID-1752

@luhaijiao
Copy link

It's a nice feature, is it possible to have it in 4.15 ?

@rohityadavcloud
Copy link
Member

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)

@sureshanaparti
Copy link
Contributor

@weizhouapache can you please fix the conflicts here. thanks.

@weizhouapache
Copy link
Member Author

@blueorangutan package

@blueorangutan
Copy link

@weizhouapache a Jenkins job has been kicked to build packages. I'll keep you posted as I make progress.

@blueorangutan
Copy link

Packaging result: ✔️ centos7 ✔️ centos8 ✔️ debian. SL-JID 419

}

public void setLbConfigs(List<? extends LoadBalancerConfig> lbConfigs) {
if (lbConfigs == null || lbConfigs.size() == 0) {
Copy link
Contributor

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)) {
...

Copy link
Member

@soreana soreana Jul 12, 2021

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;
Copy link
Contributor

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);
...

Comment on lines 136 to 139
if (lb == null) {
return null;
}
return lb.getNetworkId();
Copy link
Contributor

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;
Copy link
Contributor

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);
...

Comment on lines 141 to 143
LoadBalancerConfig config = null;
try {
config = _entityMgr.findById(LoadBalancerConfig.class, getEntityId());
Copy link
Contributor

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.

Comment on lines 1857 to 1886
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);
}
Copy link
Contributor

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.

Comment on lines +114 to +131
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);
}
Copy link
Contributor

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) {
Copy link
Contributor

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) {
Copy link
Contributor

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(...
...

Comment on lines 277 to 333
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);
}
}
Copy link
Contributor

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.

@GutoVeronezi
Copy link
Contributor

There is a lot of code addition, but none unit testing or javadoc. IMHO we should add they.

@weizhouapache
Copy link
Member Author

@ravening @soreana
could you have a look at @GutoVeronezi 's remarks ?

@soreana
Copy link
Member

soreana commented Jun 30, 2021

@weizhouapache Sure! I asked Neven to make a room for it.

@DaanHoogland
Copy link
Contributor

@soreana can you resolve that confict, please?

@sureshanaparti
Copy link
Contributor

ping @soreana can you please fix the conflicting files.

@rohityadavcloud
Copy link
Member

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.

@weizhouapache
Copy link
Member Author

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.
@ravening @soreana what do you think ?

@ravening
Copy link
Member

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.
@ravening @soreana what do you think ?

@rhtyd @weizhouapache yes lets move it out of this milestone as this will not make it in time

@soreana
Copy link
Member

soreana commented Sep 14, 2021

@rhtyd @weizhouapache Sure let's do this.

@ravening
Copy link
Member

@weizhouapache @rhtyd I have created a new pr for this in #5799

@weizhouapache
Copy link
Member Author

@weizhouapache @rhtyd I have created a new pr for this in #5799

@ravening
great. closing this ticket then.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

TCP load balancer ability to set custom connect/client/server timeout