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

TRITON-2456 Want loadbalancer for Triton tenants #1

Merged
merged 24 commits into from
Jan 22, 2025
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
bits
node_modules
proto

dehydrated
dehydrated.tar.gz
9 changes: 9 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[submodule "deps/eng"]
path = deps/eng
url = https://github.com/TritonDataCenter/eng.git
[submodule "deps/jsstyle"]
path = deps/jsstyle
url = https://github.com/TritonDataCenter/jsstyle.git
[submodule "deps/javascriptlint"]
path = deps/javascriptlint
url = https://github.com/TritonDataCenter/javascriptlint.git
50 changes: 50 additions & 0 deletions Jenkinsfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

/*
* Copyright 2022 Joyent, Inc.
* Copyright 2024 MNX Cloud, Inc.
*/

@Library('[email protected]') _

pipeline {

agent {
label joyCommonLabels(image_ver: '21.4.0', pi:'20210826T002459Z')
}

options {
buildDiscarder(logRotator(numToKeepStr: '30'))
timestamps()
}

stages {
stage('check') {
steps{
sh('make check')
}
}
// avoid bundling devDependencies
stage('re-clean') {
steps {
sh('git clean -fdx')
}
}
stage('build image and upload') {
steps {
joyBuildImageAndUpload()
}
}
}

post {
always {
joySlackNotifications(channel: 'jenkins')
}
}

}
155 changes: 155 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#

#
# Copyright 2024 MNX Cloud, Inc.
#


# The prebuilt sdcnode version we want. See
# "tools/mk/Makefile.node_prebuilt.targ" for details.
NODE_PREBUILT_VERSION=v6.17.1
ifeq ($(shell uname -s),SunOS)
NODE_PREBUILT_TAG=zone64
# [email protected]
NODE_PREBUILT_IMAGE=a7199134-7e94-11ec-be67-db6f482136c2
endif

NAME = cloud-load-balancer
DIR_NAME = clb
#
# Tools
#
NODEUNIT := ./node_modules/.bin/nodeunit

#
# Files
#
#JS_FILES := $(shell find lib -name '*.js') parser.js
JS_FILES := parser.js
ESLINT_FILES = $(JS_FILES)
JSSTYLE_FILES = $(JS_FILES)
JSSTYLE_FLAGS = -o indent=4,doxygen,unparenthesized-return=0,leading-right-paren-ok=1
SMF_MANIFESTS = smf/manifests/postboot.xml

ENGBLD_USE_BUILDIMAGE = true
ENGBLD_REQUIRE := $(shell git submodule update --init deps/eng)
include ./deps/eng/tools/mk/Makefile.defs
TOP ?= $(error Unable to access eng.git submodule Makefiles.)

BUILD_PLATFORM = 20210826T002459Z

ifeq ($(shell uname -s),SunOS)
include ./deps/eng/tools/mk/Makefile.node_prebuilt.defs
# include ./deps/eng/tools/mk/Makefile.agent_prebuilt.defs
else
NPM=npm
NODE=node
NPM_EXEC=$(shell which npm)
NODE_EXEC=$(shell which node)
endif
include ./deps/eng/tools/mk/Makefile.smf.defs

ROOT := $(shell pwd)
RELEASE_TARBALL := $(NAME)-pkg-$(STAMP).tar.gz
RELSTAGEDIR := /tmp/$(NAME)-$(STAMP)

#
# Repo-specific targets
#
DEHYDRATED = v1.5.4.1

CLEAN_FILES += bits node_modules dehydrated dehydrated.tar.gz

# triton-origin-x86_64-21.4.0
BASE_IMAGE_UUID = 502eeef2-8267-489f-b19c-a206906f57ef
BUILDIMAGE_NAME = $(NAME)
BUILDIMAGE_DESC = Triton Cloud Load Balancer
BUILDIMAGE_PKGSRC = \
openssl-1.1.1t \
haproxy-2.6.1

dehydrated:
mkdir $@
curl --progress-bar -L -O https://github.com/TritonDataCenter/triton-dehydrated/releases/download/$(DEHYDRATED)/dehydrated.tar.gz
gtar -zxvf dehydrated.tar.gz -C dehydrated

.PHONY: all
all: dehydrated

.PHONY: release
release: all $(NODE_EXEC)
@echo "Building $(RELEASE_TARBALL)"
@mkdir -p $(RELSTAGEDIR)/root/opt/triton/boot
@mkdir -p $(RELSTAGEDIR)/root/opt/triton/$(DIR_NAME)/build
@mkdir -p ${RELSTAGEDIR}/root/opt/triton/tls
@mkdir -p ${RELSTAGEDIR}/root/opt/local/etc/haproxy.cfg
@mkdir -p ${RELSTAGEDIR}/root/opt/custom/smf
@mkdir -p $(RELSTAGEDIR)/site
@touch $(RELSTAGEDIR)/site/.do-not-delete-me
cp -PR $(NODE_INSTALL) $(RELSTAGEDIR)/root/opt/triton/$(DIR_NAME)/build/node
cp -PR $(ROOT)/dehydrated/ $(RELSTAGEDIR)/root/opt/triton/
cp ${ROOT}/dehydrated.cfg ${RELSTAGEDIR}/root/opt/triton/dehydrated/config.overrides
cp ${ROOT}/dehydrated-hook ${RELSTAGEDIR}/root/opt/triton/dehydrated/override-hook
cp ${ROOT}/dhparam.pem ${RELSTAGEDIR}/root/opt/triton/tls
cp -r \
$(ROOT)/reconfigure \
$(ROOT)/parser.js \
$(ROOT)/haproxy.cfg \
$(ROOT)/package.json \
$(RELSTAGEDIR)/root/opt/triton/$(DIR_NAME)/
cp -PR $(ROOT)/smf/* ${RELSTAGEDIR}/root/opt/custom/smf/
cp -PR ${ROOT}/haproxy.cfg/* ${RELSTAGEDIR}/root/opt/local/etc/haproxy.cfg
cp -PR $(ROOT)/boot/* $(RELSTAGEDIR)/root/opt/triton/boot/
(cd $(RELSTAGEDIR) && $(TAR) -I pigz -cf $(ROOT)/$(RELEASE_TARBALL) root site)
@rm -rf $(RELSTAGEDIR)

.PHONY: publish
publish: release
mkdir -p $(ENGBLD_BITS_DIR)/$(NAME)
cp $(ROOT)/$(RELEASE_TARBALL) $(ENGBLD_BITS_DIR)/$(NAME)/$(RELEASE_TARBALL)

include ./deps/eng/tools/mk/Makefile.deps
ifeq ($(shell uname -s),SunOS)
include ./deps/eng/tools/mk/Makefile.node_prebuilt.targ
# include ./deps/eng/tools/mk/Makefile.agent_prebuilt.targ
endif
include ./deps/eng/tools/mk/Makefile.smf.targ
include ./deps/eng/tools/mk/Makefile.targ


































129 changes: 129 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1 +1,130 @@
<!--
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
-->

<!--
Copyright 2024 MNX Cloud, Inc.
-->

# triton-moirai

This repository is part of the Triton Data Center project. See the [contribution
guidelines](https://github.com/TritonDataCenter/triton/blob/master/CONTRIBUTING.md)
and general documentation at the main
[Triton project](https://github.com/TritonDataCenter/triton) page.

Moirai is an HAProxy based load balancer for Triton.

## Features

* Automatic certificate generation via [triton-dehydrated][1]
* Automatic configuration of backends

[1]: https://github.com/TritonDataCenter/triton-dehydrated

## Backend configuration

Moirai supports the following keys:

* `cloud.tritoncompute:loadbalancer` - This must be set to `true` and will be
used by node-triton and/or CloudAPI at a later date.
* `cloud.tritoncompute:portmap` - This configures the listening ports to
backend mappings. This is comma separated list of service designations.
See below for service designation syntax.
* `cloud.tritoncompute:max_rs` - By default up to 32 backend servers are
supported. If you need to scale larger than 32 backend instances, set this
to the desired value.
* `cloud.tritoncompute:certificate_name` - Comma separated list of certificate
subjects. The first in the list will be the subject `CN`. The rest of the
names will be Subject Alternate Names (SAN).

Metadata keys can be added post-provision. The load balancer will reconfigure
itself shortly after the metadata is updated.

All other metadata keys used by Triton are also supported (e.g.,
`triton.cns.services`, `tritoncli.ssh.proxy`, etc.).

## Service Designations

The `cloud.tritoncompute:portmap` metadata key is a list of service designations
separated by commas or spaces.

A service designation uses the following syntax:

<type>://<listen port>:<backend name>[:<backend port>]

* `type` - Must be one of `http`, `https`, or `tcp`.
* `http` - Configures a Layer-7 proxy using the HTTP protocol. The backend
server(s) must not use SSL/TLS. `X-Forwarded-For` header will be added to
requests.
* `https` - Configures a Layer-7 proxy using the HTTP protocol. The backend
server(s) must use SSL/TLS. The backend certficate will not be verified. The
front end services will use a certificate issued by Let's Encrypt if
the `cloud.tritoncompute:certificate_name` metadata key is also provided.
Otherwise, a self-signed certificate will be generated. `X-Forwarded-For`
header will be added to requests.
* `tcp` - Configures a Layer-4 proxy. The backend can use any port. If SSL/TLS
is desired, the backend must configure its own certificate.
* `listen port` - This designates the front end listening port.
* `backend name` - This is a DNS name that must be resolvable. This **SHOULD**
be a CNS name, but can be any fully qualified DNS domain name.
* `backend port` - Optional. This designates the back end port that servers will
be listening on. If provided, the back end will be configured to use A record
lookups. If a not provided then the back end will be configured to use SRV
record lookup.

Examples:

http://80:my-backend.svc.my-login.us-west-1.cns.example.com:80
https://443:my-backend.svc.my-login.us-west-1.cns.example.com:8443
tcp://636:my-backend.svc.my-login.us-west-1.cns.example.com

## Certificate setup

In order to properly generate a certificate you must have DNS CNAME records
pointing to the load balancer instance's CNS records. See the
[`triton-dehydrated`][2] documentation for how to properly configure this.

[2]: https://github.com/TritonDataCenter/triton-dehydrated?tab=readme-ov-file#how-to-use-inside-a-user-container-on-triton

## Development

Typically development is done by:

* making edits to a clone of triton-moirai.git on a Mac (likely Linux too, but
that's untested) or a SmartOS development zone,

git clone [email protected]:TritonDataCenter/triton-moirai.git
cd triton-moirai
git submodule update --init # not necessary first time
vi

* building:

make all
make check

* then testing changes.

## Notes

* Once a named certificate is used, the load balancer instance can't go back to
a self-signed certificate. Continue to use the expired certificate or
deploy a replacement loadbalancer.

## Testing

* Prerequisites:
* Set up fabrics on the Triton deployment.
* Ensure there are no existing NAT zones provisioned.
* Execute `sdcadm post-setup dev-headnode-prov`.

* To sync local changes to a running COAL and run the test suite there use:

make test-coal

* To run tests while logged into a running VMAPI instance:

/opt/smartdc/vmapi/test/runtests
Loading