diff --git a/.travis.yml b/.travis.yml
index 85ad22c..fb75df6 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -33,14 +33,16 @@ script:
- aws cloudformation validate-template --template-body file://templates/solace.template
- aws cloudformation validate-template --template-body file://templates/nodecreate.template
- yaml-lint -n templates/
- - #sed -i "s@SolaceDockerImageParameterValue@${SOLACE_DOCKER_URL_PARAMETER_VALUE}@g" ci/solace-aws-ha-3az-prod-travistest.json
- - sed -i "s@SolaceDockerImageParameterValue@solace/solace-pubsub-standard:latest@g" ci/solace-aws-ha-3az-prod-travistest.json
+ - sed -i "s@SolaceDockerImageParameterValue@${SOLACE_DOCKER_URL_PARAMETER_VALUE}@g" ci/solace-aws-ha-3az-prod-travistest.json
+ - #sed -i "s@SolaceDockerImageParameterValue@solace/solace-pubsub-standard:latest@g" ci/solace-aws-ha-3az-prod-travistest.json
- sed -i "s@EventBrokerNodeInstanceTypeParameterValue@${MESSAGEBROKERNODEINSTANCETYPE}@g" ci/solace-aws-ha-3az-prod-travistest.json
- - sed -i "s@SolaceStackRegionNAME@${AWS_DEFAULT_REGION}@g" ci/solace-aws-ha-3az-prod-travistest.json
- aws s3 mb s3://solace-cf-quickstart-travistest || echo "s3 bucket already existed"
+ - export BUCKETREGION=`aws s3api get-bucket-location --bucket solace-cf-quickstart-travistest | grep LocationConstraint | awk -F' ' '{print $NF}' | tr -d '"'`
+ - sed -i "s@SolaceStackRegionNAME@${AWS_DEFAULT_REGION}@g" ci/solace-aws-ha-3az-prod-travistest.json
+ - sed -i "s@SolaceBucketRegionNAME@${BUCKETREGION}@g" ci/solace-aws-ha-3az-prod-travistest.json
- aws s3 sync . s3://solace-cf-quickstart-travistest/solace/eventbroker/latest --acl public-read
- export TESTSTACKPREFIX=T`echo "$(date +%s)" | rev`; export TESTSTACKNAME="$TESTSTACKPREFIX-sol-aws-travistest";
- - aws cloudformation create-stack --stack-name $TESTSTACKNAME --template-body file://templates/solace-master.template --parameters file://ci/solace-aws-ha-3az-prod-travistest.json --on-failure DO_NOTHING --capabilities CAPABILITY_IAM
+ - aws cloudformation create-stack --stack-name $TESTSTACKNAME --template-body file://templates/solace-master.template --parameters file://ci/solace-aws-ha-3az-prod-travistest.json --on-failure DO_NOTHING --capabilities CAPABILITY_NAMED_IAM
- echo "Waiting for stack create complete"
- "travis_wait 30 sleep 1800 &"
- until aws cloudformation describe-stacks --stack-name $TESTSTACKNAME | grep -m 1 -E 'CREATE_COMPLETE|DELETE_IN_PROGRESS'; do sleep 10; done
@@ -54,9 +56,8 @@ script:
- sleep 30
- curl -sS -u admin:admin http://$url:8080/SEMP -d ""
- curl -sS -u admin:admin http://$url:8080/SEMP -d ""
- - bash -c 'if [[ -z `curl -sS -u admin:admin http://$url:8080/SEMP -d ""
- | grep "Up"` ]] ; then echo "config-sync not up!"; exit
- 1; fi'
+ - #bash -c 'if [[ -z `curl -sS -u admin:admin http://$url:8080/SEMP -d "" | grep "Up"` ]] ; then echo "config-sync not up!"; exit 1; fi'
+ - if [[ -z `curl -sS -u admin:admin http://$url:8080/SEMP -d "" | grep "Up"` ]] ; then echo "config-sync not up!"; exit; fi
- pubSubTools/sdkperf_c -cip=$url -mn=100000 -mr=0 -ptl=t1 -stl=t1 | grep "Total Messages"
- aws cloudformation delete-stack --stack-name $TESTSTACKNAME
- echo "Waiting for stack delete complete"
@@ -65,7 +66,7 @@ script:
- # Now test No Private Subnet
- export TESTSTACKNAME="$TESTSTACKNAME-1"
- sed -i "s@true@false@g" ci/solace-aws-ha-3az-prod-travistest.json
- - aws cloudformation create-stack --stack-name $TESTSTACKNAME --template-body file://templates/solace-master.template --parameters file://ci/solace-aws-ha-3az-prod-travistest.json --on-failure DO_NOTHING --capabilities CAPABILITY_IAM
+ - aws cloudformation create-stack --stack-name $TESTSTACKNAME --template-body file://templates/solace-master.template --parameters file://ci/solace-aws-ha-3az-prod-travistest.json --on-failure DO_NOTHING --capabilities CAPABILITY_NAMED_IAM
- echo "Waiting for stack create complete"
- "travis_wait 30 sleep 1800 &"
- until aws cloudformation describe-stacks --stack-name $TESTSTACKNAME | grep -m 1 -E 'CREATE_COMPLETE|DELETE_IN_PROGRESS'; do sleep 10; done
diff --git a/README.md b/README.md
index 6583cef..92002a6 100644
--- a/README.md
+++ b/README.md
@@ -2,6 +2,10 @@
# Install and Configure Solace PubSub+ Software Event Broker in an HA Tuple using AWS Cloud Formation
+This document provides a quick getting started guide to install a Solace PubSub+ software event broker deployment in Amazon Web Services cloud computing platform.
+
+The supported event broker version is 9.7 or later. For earlier broker releases use [this GitHub version of the QuickStart](https://github.com/SolaceProducts/pubsubplus-aws-ha-quickstart/tree/v2.0.1).
+
![alt text](/images/Solace-AWS-HA-Prod-3AZ.png "Production Environment for Solace PubSub+")
This Quick Start template installs Solace PubSub+ Software Event Broker in fault tolerant high-availability (HA) redundancy groups. HA redundancy provides 1:1 event broker redundancy to increase overall service availability. If one of the event brokers fails, or is taken out of service, the other one automatically takes over and provides service to the clients that were previously served by the now out-of-service event broker. To increase availability, the event brokers are deployed across 3 availability zones.
@@ -98,9 +102,14 @@ The next screen will allow you to fill in the details for the selected launch op
| Parameter label (name) | Default | Description |
|----------------------------|-----------|--------------------------------------------------------------------|
| Stack name | Solace-HA | Any globally unique name |
-| **PubSub+ Configuration** | | |
+| **PubSub+ Event Broker Configuration** | | |
| PubSub+ Docker image reference (SolaceDockerImage) | solace/solace-pubsub-standard:latest | A reference to the Solace PubSub+ event broker Docker image, from step 1. Either the image name with optional tag in an accessible Docker registry or a download URL. The download URL can be obtained from http://dev.solace.com/downloads/ or it can be a URL to a remotely hosted image version, e.g. on S3 |
| Password to access PubSub+ admin console and SEMP (AdminPassword) | _Requires_ _input_ | Password to allow PubSub+ admin access to configure the event broker instances |
+| Maximum Number of Client Connections (MaxClientConnections)| 100 | Broker system scaling: the maximum supported number of client connections |
+| Maximum Number of Queue Messages (MaxQueueMessages) | 100 | Broker system scaling: the maximum number of queue messages, in millions |
+| Instance Type (WorkerNodeInstanceType) | m4.large | The EC2 instance type for the PubSub+ event broker primary and backup instances in Availability Zones 1 and 2. The m series are recommended for production use.
Ensure adequate CPU and Memory resources are available to support the selected broker system scaling parameters. For requirements, check the [Solace documentation](//docs.solace.com/Configuring-and-Managing/SW-Broker-Specific-Config/System-Scaling-Parameters.htm). |
+| Persistent Storage (WorkerNodeStorage) | 0 | Amazon event broker storage allocated for each block device, in GiBs. The Quick Start supports up to 640 GiB per device. For sizing requirements, check the [Solace documentation](//docs.solace.com/Configuring-and-Managing/SW-Broker-Specific-Config/System-Scaling-Parameters.htm). The default value of 0 (zero) indicates ephemeral storage only. A non-zero value will cause a new Provisioned IOPS SSD (io1) disk to be created for message-spool. This disk will not be deleted on stack termination. |
+| Instance Type (MonitorNodeInstanceType) | t2.small | The EC2 instance type for the PubSub+ event broker monitor instance in Availability Zone 3 (or Availability Zone 2, if you’re using only two zones). |
| Container logging format (ContainerLoggingFormat) | graylog | The format of the logs sent by the event broker to the CloudWatch service (see [documentation](https://docs.solace.com/Configuring-and-Managing/SW-Broker-Specific-Config/Docker-Tasks/Configuring-VMR-Container-Logging.htm?Highlight=logging#Config-Out-Form ) for details) |
| **Network Configuration** | | |
| Number of Availability Zones (NumberOfAZs) | 3 | The number of Availability Zones (2 may be used for Proof-of-Concept testing or 3 for Production) you want to use in your deployment. This count must match the number of selections in the Availability Zones parameter; otherwise, your deployment will fail with an AWS CloudFormation template validation error. (Note that some regions provide only one or two Availability Zones.) |
@@ -111,11 +120,6 @@ The next screen will allow you to fill in the details for the selected launch op
| **Common Amazon EC2 Configuration** | | |
| Key Pair Name (KeyPairName) | _Requires_ _input_ | A new or an existing public/private key pair within the AWS Region, which allows you to connect securely to your instances after launch. |
| Boot Disk Capacity (BootDiskSize) | 24 | Amazon event broker storage allocated for the boot disk, in GiBs. The Quick Start supports 8-128 GiB. |
-| **Event Broker Instance Configuration** | | |
-| Instance Type (EventBrokerNodeInstanceType) | m4.large | The EC2 instance type for the PubSub+ event broker primary and backup instances in Availability Zones 1 and 2. The m series are recommended for production use.
The available CPU and memory of the selected machine type will limit the maximum connection scaling tier for the PubSub+ event broker. For requirements, refer to the [Solace documentation](https://docs.solace.com/Solace-SW-Broker-Set-Up/SW-Broker-Rel-Compat.htm#Connecti) |
-| Persistent Storage (EventBrokerNodeStorage) | 0 | Amazon event broker storage allocated for each block device, in GiBs. The Quick Start supports up to 640 GiB per device. The default value of 0 (zero) indicates ephemeral storage only. A non-zero value will cause a new Provisioned IOPS SSD (io1) disk to be created for message-spool. This disk will not be deleted on stack termination. |
-| **Monitor Instance Configuration** | | |
-| Instance Type (MonitorNodeInstanceType) | t2.micro | The EC2 instance type for the PubSub+ event broker monitor instance in Availability Zone 3 (or Availability Zone 2, if you’re using only two zones). |
| **AWS Quick Start Configuration** | | |
| Quick Start S3 Bucket Name (QSS3BucketName) | solace-products | S3 bucket where the Quick Start templates and scripts are installed. Change this parameter to specify the S3 bucket name you’ve created for your copy of Quick Start assets, if you decide to customize or extend the Quick Start for your own use. |
| Quick Start S3 bucket region (QSS3BucketRegion) | us-east-1 | The AWS Region where the Quick Start S3 bucket (QSS3BucketName) is hosted. When using your own bucket, you must specify this value. |
diff --git a/ci/solace-aws-ha-3az-prod-travistest.json b/ci/solace-aws-ha-3az-prod-travistest.json
index e75106e..a920278 100644
--- a/ci/solace-aws-ha-3az-prod-travistest.json
+++ b/ci/solace-aws-ha-3az-prod-travistest.json
@@ -28,16 +28,16 @@
"ParameterValue": "24"
},
{
- "ParameterKey": "EventBrokerNodeInstanceType",
+ "ParameterKey": "WorkerNodeInstanceType",
"ParameterValue": "EventBrokerNodeInstanceTypeParameterValue"
},
{
- "ParameterKey": "EventBrokerNodeStorage",
+ "ParameterKey": "WorkerNodeStorage",
"ParameterValue": "20"
},
{
"ParameterKey": "MonitorNodeInstanceType",
- "ParameterValue": "t2.micro"
+ "ParameterValue": "t2.small"
},
{
"ParameterKey": "KeyPairName",
@@ -57,7 +57,7 @@
},
{
"ParameterKey": "QSS3BucketRegion",
- "ParameterValue": "SolaceStackRegionNAME"
+ "ParameterValue": "SolaceBucketRegionNAME"
},
{
"ParameterKey": "QSS3KeyPrefix",
diff --git a/scripts/install-direct-lvm.sh b/scripts/install-direct-lvm.sh
deleted file mode 100644
index d6ef173..0000000
--- a/scripts/install-direct-lvm.sh
+++ /dev/null
@@ -1,88 +0,0 @@
-#!/bin/bash
-#
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements. See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-
-OPTIND=1 # Reset in case getopts has been used previously in the shell.
-
-# Initialize our own variables:
-volume=""
-disk_size=""
-DEBUG="-vvvv"
-
-verbose=0
-
-while getopts "d:p:u:" opt; do
- case "$opt" in
- d) disk_size=$OPTARG
- ;;
- v) volume=$OPTARG
- ;;
- esac
-done
-
-shift $((OPTIND-1))
-[ "$1" = "--" ] && shift
-
-verbose=1
-echo "disk_size==$disk_size= ,volume=$volume ,Leftovers: $@"
-
-if [ $disk_size == "0" ]; then
- echo "`date` No persistent disk here, exiting"
- exit 0
-fi
-
-echo "`date` Create a physical volume and a volume group called vg01DockerPool"
-sudo pvcreate ${volume}
-sudo vgcreate vg01DockerPool ${volume}
-
-echo "`date` Create a logical volume called vg01DockerPool, and then convert it to a thin pool"
-sudo lvcreate --wipesignatures y -n thinpool vg01DockerPool -l 95%VG
-sudo lvcreate --wipesignatures y -n thinpoolmetadata vg01DockerPool -l 1%VG
-sudo lvconvert -y --zero n -c 512K --thinpool vg01DockerPool/thinpool \
- --poolmetadata vg01DockerPool/thinpoolmetadata
-
-
-echo "`date` Create a file called vg01DockerPoolThinpool.profile in /etc/lvm/profile/ for use as the new lvm profile"
-sudo mkdir /etc/lvm/profile/
-sudo tee /etc/lvm/profile/vg01DockerPoolThinpool.profile <<-EOF
-activation {
-thin_pool_autoextend_threshold=80
-thin_pool_autoextend_percent=20
-}
-EOF
-
-sudo lvchange --metadataprofile vg01DockerPoolThinpool vg01DockerPool/thinpool
-
-# Tjis does not work, it overwrites not appends.
-echo "`date` Make a file called docker.service. This version of docker.service configures Docker to make use of the thin pool"
-sudo tee /etc/sysconfig/docker <<-EOF
---storage-opt=dm.fs=xfs \
---storage-opt=dm.thinpooldev=/dev/mapper/vg01DockerPool-thinpool \
---storage-opt=dm.use_deferred_removal=true \
---storage-opt=dm.use_deferred_deletion=true \
---storage-opt=dm.basesize=6G
-EOF
-
-echo "`date` Move the existing graph driver directory if the Docker daemon was previously started"
-sudo service docker stop
-sudo mkdir /var/lib/docker.bk
-sudo sh -c 'mv /var/lib/docker/* /var/lib/docker.bk'
-
-echo "`date` Start Docker Service"
-sudo service docker start
-
-
diff --git a/scripts/install-solace.sh b/scripts/install-solace.sh
index 8f3404e..e425a45 100644
--- a/scripts/install-solace.sh
+++ b/scripts/install-solace.sh
@@ -35,12 +35,15 @@ solace_uri="solace/solace-pubsub-standard:latest" # default to pull latest Pub
admin_password_file=""
disk_size=""
disk_volume=""
+ha_deployment="true"
is_primary="false"
logging_format=""
logging_group=""
logging_stream=""
+max_connections="100"
+max_queue_messages="100"
-while getopts "c:d:p:s:u:v:f:g:r:" opt; do
+while getopts "c:d:p:s:u:v:h:f:g:r:n:q:" opt; do
case "$opt" in
c) config_file=$OPTARG
;;
@@ -54,21 +57,27 @@ while getopts "c:d:p:s:u:v:f:g:r:" opt; do
;;
v) disk_volume=$OPTARG
;;
+ h) ha_deployment=$OPTARG
+ ;;
f) logging_format=$OPTARG
;;
g) logging_group=$OPTARG
;;
r) logging_stream=$OPTARG
;;
+ n) max_connections=$OPTARG
+ ;;
+ q) max_queue_messages=$OPTARG
+ ;;
esac
done
shift $((OPTIND-1))
[ "$1" = "--" ] && shift
-echo "config_file=$config_file , solace_directory=$solace_directory , admin_password_file=$admin_password_file , \
- solace_uri=$solace_uri , disk_size=$disk_size , volume=$disk_volume , logging_format=$logging_format , \
- logging_group=$logging_group , logging_stream=$logging_stream , Leftovers: $@"
+echo "config_file=$config_file, solace_directory=$solace_directory, admin_password_file=$admin_password_file, \
+ solace_uri=$solace_uri, disk_size=$disk_size, volume=$disk_volume, ha_deployment=$ha_deployment, logging_format=$logging_format, \
+ logging_group=$logging_group, logging_stream=$logging_stream, max_connections=$max_connections, max_queue_messages=$max_queue_messages, Leftovers: $@"
export admin_password=`cat ${admin_password_file}`
# Create working dir if needed
@@ -143,41 +152,13 @@ fi
echo "`date` INFO: Successfully loaded ${solace_uri} to local docker repo"
echo "`date` INFO: Solace message broker image and tag: `docker images | grep solace | awk '{print $1,":",$2}'`"
-# Decide which scaling tier applies based on system memory
-# and set maxconnectioncount, ulimit, devshm and swap accordingly
-MEM_SIZE=`cat /proc/meminfo | grep MemTotal | tr -dc '0-9'`
-if [ ${MEM_SIZE} -lt 6600000 ]; then
- # 100 if mem<6,325MiB
- maxconnectioncount="100"
- shmsize="1g"
- ulimit_nofile="2448:6592"
- SWAP_SIZE="1024"
-elif [ ${MEM_SIZE} -lt 14500000 ]; then
- # 1000 if 6,325MiB<=mem<13,916MiB
- maxconnectioncount="1000"
- shmsize="2g"
- ulimit_nofile="2448:10192"
- SWAP_SIZE="2048"
-elif [ ${MEM_SIZE} -lt 30600000 ]; then
- # 10000 if 13,916MiB<=mem<29,215MiB
- maxconnectioncount="10000"
- shmsize="2g"
- ulimit_nofile="2448:42192"
- SWAP_SIZE="2048"
-elif [ ${MEM_SIZE} -lt 57500000 ]; then
- # 100000 if 29,215MiB<=mem<54,840MiB
- maxconnectioncount="100000"
- shmsize="3380m"
- ulimit_nofile="2448:222192"
- SWAP_SIZE="2048"
-else
- # 200000 if 54,840MiB<=mem
- maxconnectioncount="200000"
- shmsize="3380m"
- ulimit_nofile="2448:422192"
- SWAP_SIZE="2048"
-fi
-echo "`date` INFO: Based on memory size of ${MEM_SIZE}KiB, determined maxconnectioncount: ${maxconnectioncount}, shmsize: ${shmsize}, ulimit_nofile: ${ulimit_nofile}, SWAP_SIZE: ${SWAP_SIZE}"
+
+# Common for all scalings
+shmsize="1g"
+ulimit_nofile="2448:422192"
+SWAP_SIZE="2048"
+
+echo "`date` INFO: Using shmsize: ${shmsize}, ulimit_nofile: ${ulimit_nofile}, SWAP_SIZE: ${SWAP_SIZE}"
echo "`date` INFO: Creating Swap space"
mkdir /var/lib/solace
@@ -187,7 +168,7 @@ chmod 0600 /var/lib/solace/swap
swapon -f /var/lib/solace/swap
grep -q 'solace\/swap' /etc/fstab || sudo sh -c 'echo "/var/lib/solace/swap none swap sw 0 0" >> /etc/fstab'
-echo "`date` INFO: Applying TCP for WAN optimizations" &>> ${LOG_FILE}
+echo "`date` INFO: Applying TCP for WAN optimizations"
echo '
net.core.rmem_max = 134217728
net.core.wmem_max = 134217728
@@ -198,6 +179,123 @@ sudo sysctl -p /etc/sysctl.d/98-solace-sysctl.conf
cd ${solace_directory}
+# Setup password file permissions
+chown -R 1000001 $(dirname ${admin_password_file})
+chmod 700 $(dirname ${admin_password_file})
+
+if [[ ${disk_size} == "0" ]]; then
+ echo "`date` Using ephemeral volumes"
+ #Create new volumes that the PubSub+ Message Broker container can use to consume and store data.
+ docker volume create --name=jail
+ docker volume create --name=var
+ docker volume create --name=adb
+ docker volume create --name=softAdb
+ docker volume create --name=diagnostics
+ docker volume create --name=internalSpool
+ SPOOL_MOUNT="-v jail:/usr/sw/jail -v var:/usr/sw/var -v softAdb:/usr/sw/internalSpool/softAdb -v adb:/usr/sw/adb -v diagnostics:/var/lib/solace/diags -v internalSpool:/usr/sw/internalSpool"
+else
+ echo "`date` Using persistent volumes"
+ echo "`date` Create primary partition on new disk"
+ (
+ echo n # Add a new partition
+ echo p # Primary partition
+ echo 1 # Partition number
+ echo # First sector (Accept default: 1)
+ echo # Last sector (Accept default: varies)
+ echo w # Write changes
+ ) | sudo fdisk $disk_volume
+
+ mkfs.xfs ${disk_volume}1 -m crc=0
+ UUID=`blkid -s UUID -o value ${disk_volume}1`
+ echo "UUID=${UUID} /opt/pubsubplus xfs defaults 0 0" >> /etc/fstab
+ mkdir /opt/pubsubplus
+ mount -a
+ mkdir /opt/pubsubplus/jail
+ mkdir /opt/pubsubplus/var
+ mkdir /opt/pubsubplus/adb
+ mkdir /opt/pubsubplus/softAdb
+ mkdir /opt/pubsubplus/diagnostics
+ mkdir /opt/pubsubplus/internalSpool
+ chown 1000001 -R /opt/pubsubplus/
+ #chmod -R 777 /opt/pubsubplus
+
+ SPOOL_MOUNT="-v /opt/pubsubplus/jail:/usr/sw/jail -v /opt/pubsubplus/var:/usr/sw/var -v /opt/pubsubplus/adb:/usr/sw/adb -v /opt/pubsubplus/softAdb:/usr/sw/internalSpool/softAdb -v /opt/pubsubplus/diagnostics:/var/lib/solace/diags -v /opt/pubsubplus/internalSpool:/usr/sw/internalSpool"
+fi
+
+############# From here execution path is different for nonHA and HA
+
+if [[ $ha_deployment != "true" ]]; then
+############# non-HA setup begins
+ echo "`date` Continuing single-node setup in a non-HA deployment"
+ #Define a create script
+ tee ~/docker-create <<- EOF
+ #!/bin/bash
+ docker create \
+ --uts=host \
+ --shm-size ${shmsize} \
+ --ulimit core=-1 \
+ --ulimit memlock=-1 \
+ --ulimit nofile=${ulimit_nofile} \
+ --env "system_scaling_maxconnectioncount=${max_connections}" \
+ --env "system_scaling_maxqueuemessagecount=${max_queue_messages}" \
+ --net=host \
+ --restart=always \
+ -v /mnt/pubsubplus/secrets:/run/secrets \
+ ${SPOOL_MOUNT} \
+ --env "username_admin_globalaccesslevel=admin" \
+ --env "username_admin_passwordfilepath=$(basename ${admin_password_file})" \
+ --env "service_ssh_port=2222" \
+ --env "service_webtransport_port=8008" \
+ --env "service_webtransport_tlsport=1443" \
+ --env "service_semp_tlsport=1943" \
+ --name=solace ${SOLACE_IMAGE_ID}
+EOF
+
+ #Make the file executable
+ chmod +x ~/docker-create
+
+ echo "`date` INFO: Creating the broker container"
+ ~/docker-create
+
+ # Start the solace service and enable it at system start up.
+ chkconfig --add solace-pubsubplus
+ echo "`date` INFO: Starting Solace service"
+ service solace-pubsubplus start
+
+ # Remove all message broker Secrets from the host; at this point, the message broker should have come up
+ # and it won't be needing those files anymore
+ rm ${admin_password_file}
+
+ # Poll the broker Message-Spool
+ loop_guard=30
+ pause=10
+ count=0
+ echo "`date` INFO: Wait for the broker message-spool service to be guaranteed-active"
+ while [ ${count} -lt ${loop_guard} ]; do
+ health_result=`curl -s -o /dev/null -w "%{http_code}" http://localhost:5550/health-check/guaranteed-active`
+ run_time=$((${count} * ${pause}))
+ if [ "${health_result}" = "200" ]; then
+ echo "`date` INFO: broker message-spool is guaranteed-active, after ${run_time} seconds"
+ break
+ fi
+ ((count++))
+ echo "`date` INFO: Waited ${run_time} seconds, broker message-spool not yet guaranteed-active. State: ${health_result}"
+ sleep ${pause}
+ done
+ if [ ${count} -eq ${loop_guard} ]; then
+ echo "`date` ERROR: broker message-spool never came guaranteed-active" | tee /dev/stderr
+ exit 1
+ fi
+
+ echo "`date` INFO: PubSub+ non-HA node bringup complete"
+ exit
+############# non-HA setup ends
+fi
+
+############# From here it's all HA setup
+echo "`date` Continuing node setup in an HA deployment"
+
+# Determine components
host_name=`hostname`
host_info=`grep ${host_name} ${config_file}`
local_role=`echo $host_info | grep -o -E 'Monitor|EventBrokerPrimary|EventBrokerBackup'`
@@ -244,94 +342,58 @@ case $local_role in
;;
esac
-# Setup password file permissions
-chown -R 1000001 $(dirname ${admin_password_file})
-chmod 700 $(dirname ${admin_password_file})
-
-if [[ ${disk_size} == "0" ]]; then
- #Create new volumes that the PubSub+ Message Broker container can use to consume and store data.
- docker volume create --name=jail
- docker volume create --name=var
- docker volume create --name=softAdb
- docker volume create --name=diagnostics
- docker volume create --name=internalSpool
- SPOOL_MOUNT="-v jail:/usr/sw/jail -v var:/usr/sw/var -v softAdb:/usr/sw/internalSpool/softAdb -v diagnostics:/var/lib/solace/diags -v internalSpool:/usr/sw/internalSpool"
-else
- echo "`date` Create primary partition on new disk"
- (
- echo n # Add a new partition
- echo p # Primary partition
- echo 1 # Partition number
- echo # First sector (Accept default: 1)
- echo # Last sector (Accept default: varies)
- echo w # Write changes
- ) | sudo fdisk $disk_volume
-
- mkfs.xfs ${disk_volume}1 -m crc=0
- UUID=`blkid -s UUID -o value ${disk_volume}1`
- echo "UUID=${UUID} /opt/pubsubplus xfs defaults,uid=1000001 0 0" >> /etc/fstab
- mkdir /opt/pubsubplus
- mkdir /opt/pubsubplus/jail
- mkdir /opt/pubsubplus/var
- mkdir /opt/pubsubplus/softAdb
- mkdir /opt/pubsubplus/diagnostics
- mkdir /opt/pubsubplus/internalSpool
- mount -a
- chown 1000001 -R /opt/pubsubplus/
- SPOOL_MOUNT="-v /opt/pubsubplus/jail:/usr/sw/jail -v /opt/pubsubplus/var:/usr/sw/var -v /opt/pubsubplus/softAdb:/usr/sw/internalSpool/softAdb -v /opt/pubsubplus/diagnostics:/var/lib/solace/diags -v /opt/pubsubplus/internalSpool:/usr/sw/internalSpool"
-fi
-
#Define a create script
-tee ~/docker-create <<-EOF
+tee ~/docker-create <<- EOF
#!/bin/bash
docker create \
- --uts=host \
- --shm-size=${shmsize} \
- --ulimit core=-1 \
- --ulimit memlock=-1 \
- --ulimit nofile=${ulimit_nofile} \
- --net=host \
- --restart=always \
- -v /mnt/pubsubplus/secrets:/run/secrets \
- ${SPOOL_MOUNT} \
- --log-driver awslogs \
- --log-opt awslogs-group=${logging_group} \
- --log-opt awslogs-stream=${logging_stream} \
- --env "system_scaling_maxconnectioncount=${maxconnectioncount}" \
- --env "logging_debug_output=all" \
- --env "logging_debug_format=${logging_format}" \
- --env "logging_command_output=all" \
- --env "logging_command_format=${logging_format}" \
- --env "logging_system_output=all" \
- --env "logging_system_format=${logging_format}" \
- --env "logging_event_output=all" \
- --env "logging_event_format=${logging_format}" \
- --env "logging_kernel_output=all" \
- --env "logging_kernel_format=${logging_format}" \
- --env "nodetype=${NODE_TYPE}" \
- --env "routername=${ROUTER_NAME}" \
- --env "username_admin_globalaccesslevel=admin" \
- --env "username_admin_passwordfilepath=$(basename ${admin_password_file})" \
- --env "service_ssh_port=2222" \
- --env "service_webtransport_port=8008" \
- --env "service_webtransport_tlsport=1443" \
- --env "service_semp_tlsport=1943" \
- ${REDUNDANCY_CFG} \
- --env "redundancy_authentication_presharedkey_key=`cat ${admin_password_file} | awk '{x=$0;for(i=length;i<51;i++)x=x "0";}END{print x}' | base64`" \
- --env "redundancy_enable=yes" \
+ --uts=host \
+ --shm-size=${shmsize} \
+ --ulimit core=-1 \
+ --ulimit memlock=-1 \
+ --ulimit nofile=${ulimit_nofile} \
+ --net=host \
+ --restart=always \
+ -v /mnt/pubsubplus/secrets:/run/secrets \
+ ${SPOOL_MOUNT} \
+ --log-driver awslogs \
+ --log-opt awslogs-group=${logging_group} \
+ --log-opt awslogs-stream=${logging_stream} \
+ --env "system_scaling_maxconnectioncount=${max_connections}" \
+ --env "system_scaling_maxqueuemessagecount=${max_queue_messages}" \
+ --env "logging_debug_output=all" \
+ --env "logging_debug_format=${logging_format}" \
+ --env "logging_command_output=all" \
+ --env "logging_command_format=${logging_format}" \
+ --env "logging_system_output=all" \
+ --env "logging_system_format=${logging_format}" \
+ --env "logging_event_output=all" \
+ --env "logging_event_format=${logging_format}" \
+ --env "logging_kernel_output=all" \
+ --env "logging_kernel_format=${logging_format}" \
+ --env "nodetype=${NODE_TYPE}" \
+ --env "routername=${ROUTER_NAME}" \
+ --env "username_admin_globalaccesslevel=admin" \
+ --env "username_admin_passwordfilepath=$(basename ${admin_password_file})" \
+ --env "service_ssh_port=2222" \
+ --env "service_webtransport_port=8008" \
+ --env "service_webtransport_tlsport=1443" \
+ --env "service_semp_tlsport=1943" \
+ ${REDUNDANCY_CFG} \
+ --env "redundancy_authentication_presharedkey_key=`cat ${admin_password_file} | awk '{x=$0;for(i=length;i<51;i++)x=x "0";}END{print x}' | base64`" \
+ --env "redundancy_enable=yes" \
--env "redundancy_group_node_primary${primary_stack}_nodetype=message_routing" \
--env "redundancy_group_node_primary${primary_stack}_connectvia=${PRIMARY_IP}" \
--env "redundancy_group_node_backup${backup_stack}_nodetype=message_routing" \
--env "redundancy_group_node_backup${backup_stack}_connectvia=${BACKUP_IP}" \
--env "redundancy_group_node_monitor${monitor_stack}_nodetype=monitoring" \
--env "redundancy_group_node_monitor${monitor_stack}_connectvia=${MONITOR_IP}" \
- --name=solace ${SOLACE_IMAGE_ID}
+ --name=solace ${SOLACE_IMAGE_ID}
EOF
#Make the file executable
chmod +x ~/docker-create
-echo "`date` INFO: Creating the Solace container"
+echo "`date` INFO: Creating the broker container"
~/docker-create
# Start the solace service and enable it at system start up.
@@ -346,7 +408,7 @@ count=0
echo "`date` INFO: Wait for the Solace SEMP service to be enabled"
while [ ${count} -lt ${loop_guard} ]; do
online_results=`/tmp/semp_query.sh -n admin -p ${admin_password} -u http://localhost:8080/SEMP \
- -q "" \
+ -q "" \
-v "/rpc-reply/rpc/show/service/services/service[name='SEMP']/enabled[text()]"`
is_messagebroker_up=`echo ${online_results} | jq '.valueSearchResult' -`
@@ -375,7 +437,7 @@ if [ "${is_primary}" = "true" ]; then
echo "`date` INFO: Wait for Primary to be 'Local Active' or 'Mate Active'"
while [ ${count} -lt ${loop_guard} ]; do
online_results=`/tmp/semp_query.sh -n admin -p ${admin_password} -u http://localhost:8080/SEMP \
- -q "" \
+ -q "" \
-v "/rpc-reply/rpc/show/redundancy/virtual-routers/primary/status/activity[text()]"`
local_activity=`echo ${online_results} | jq '.valueSearchResult' -`
@@ -410,7 +472,7 @@ if [ "${is_primary}" = "true" ]; then
echo "`date` INFO: Wait for Backup to be 'Active' or 'Standby'"
while [ ${count} -lt ${loop_guard} ]; do
online_results=`/tmp/semp_query.sh -n admin -p ${admin_password} -u http://localhost:8080/SEMP \
- -q "" \
+ -q "" \
-v "/rpc-reply/rpc/show/redundancy/virtual-routers/primary/status/detail/priority-reported-by-mate/summary[text()]"`
mate_activity=`echo ${online_results} | jq '.valueSearchResult' -`
@@ -439,14 +501,60 @@ if [ "${is_primary}" = "true" ]; then
exit 1
fi
+ echo "`date` INFO: Initiating config-sync for router"
/tmp/semp_query.sh -n admin -p ${admin_password} -u http://localhost:8080/SEMP \
- -q ""
+ -q ""
+ echo "`date` INFO: Initiating config-sync for default vpn"
/tmp/semp_query.sh -n admin -p ${admin_password} -u http://localhost:8080/SEMP \
- -q "default"
-fi
+ -q "default"
+
+ # Wait for config-sync results
+ count=0
+ echo "`date` INFO: Waiting for config-sync connected"
+ while [ ${count} -lt ${loop_guard} ]; do
+ online_results=`/tmp/semp_query.sh -n admin -p ${admin_password} -u http://localhost:8080/SEMP \
+ -q "" \
+ -v "/rpc-reply/rpc/show/config-sync/status/oper-status"`
+
+ confsyncstatus_results=`echo ${online_results} | jq '.valueSearchResult' -`
+ echo "`date` INFO: Config-sync is: ${confsyncstatus_results}"
+
+ run_time=$((${count} * ${pause}))
+ case "${confsyncstatus_results}" in
+ "\"Up\"")
+ echo "`date` INFO: Config-sync is Up, after ${run_time} seconds"
+ break
+ ;;
+ esac
+ ((count++))
+ echo "`date` INFO: Waited ${run_time} seconds, Config-sync is not yet Up"
+ sleep ${pause}
+ done
+
+ if [ ${count} -eq ${loop_guard} ]; then
+ echo "`date` ERROR: Config-sync never reached state \"Up\" - exiting." | tee /dev/stderr
+ exit 1
+ fi
+
+ # Poll the broker Message-Spool
+ count=0
+ echo "`date` INFO: Wait for the broker message-spool service to be guaranteed-active"
+ while [ ${count} -lt ${loop_guard} ]; do
+ health_result=`curl -s -o /dev/null -w "%{http_code}" http://localhost:5550/health-check/guaranteed-active`
+ run_time=$((${count} * ${pause}))
+ if [ "${health_result}" = "200" ]; then
+ echo "`date` INFO: broker message-spool is guaranteed-active, after ${run_time} seconds"
+ break
+ fi
+ ((count++))
+ echo "`date` INFO: Waited ${run_time} seconds, broker message-spool not yet guaranteed-active. State: ${health_result}"
+ sleep ${pause}
+ done
+ if [ ${count} -eq ${loop_guard} ]; then
+ echo "`date` ERROR: broker message-spool never came guaranteed-active" | tee /dev/stderr
+ exit 1
+ fi
-if [ ${count} -eq ${loop_guard} ]; then
- echo "`date` ERROR: Solace bringup failed" | tee /dev/stderr
- exit 1
fi
-echo "`date` INFO: Solace bringup complete"
+
+echo "`date` INFO: PubSub+ HA-node bringup complete"
diff --git a/scripts/semp_query.sh b/scripts/semp_query.sh
index 873703e..37bdc8e 100644
--- a/scripts/semp_query.sh
+++ b/scripts/semp_query.sh
@@ -40,12 +40,12 @@ if [[ ${url} = "" || ${name} = "" || ${password} = "" || ${query} = "" ]]; then
echo "{\"errorInfo\":\"missing parameter\"}"
exit 1
fi
-if [ `curl --write-out '%{http_code}' --silent --output /dev/null -u ${name}:${password} ${url} -d "` != "200" ] ; then
+if [ `curl --write-out '%{http_code}' --silent --output /dev/null -u ${name}:${password} ${url} -d ""` != "200" ] ; then
echo "{\"errorInfo\":\"management host is not responding\"}"
exit 1
fi
-query_response=`curl -u ${name}:${password} ${url} -d "${query}"`
+query_response=`curl -sS -u ${name}:${password} ${url} -d "${query}"`
# Validate first char of response is "<", otherwise no hope of being valid xml
if [[ ${query_response:0:1} != "<" ]] ; then
echo "{\"errorInfo\":\"no valid xml returned\"}"
diff --git a/scripts/wait-for-resource.sh b/scripts/wait-for-resource.sh
deleted file mode 100644
index 81609c6..0000000
--- a/scripts/wait-for-resource.sh
+++ /dev/null
@@ -1,87 +0,0 @@
-#!/bin/bash
-#
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements. See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# Simple script to wait for a Cloudformation resource
-#
-# usage:
-# $0 [ stack-name ] ResourceName
-#
-# If no stack is given, we try to figure out out from tags of this
-# instance.
-#
-
-murl_top=http://169.254.169.254/latest/meta-data
-
-ThisInstance=$(curl -f $murl_top/instance-id 2> /dev/null)
-if [ -z "$ThisInstance" ] ; then
- ThisInstance="unknown"
-fi
-
-ThisRegion=$(curl -f $murl_top/placement/availability-zone 2> /dev/null)
-if [ -z "$ThisRegion" ] ; then
- ThisRegion="us-east-1"
-else
- ThisRegion="${ThisRegion%[a-z]}"
-fi
-
-if [ -n "${1}" ] ; then
- if [ -z "${2}" ] ; then
- ThisStack=$(aws ec2 describe-instances --region $ThisRegion --output text --instance-ids $ThisInstance --query 'Reservations[].Instances[].Tags[?Key==`aws:cloudformation:stack-name`].Value ')
- ThisResource=$1
- else
- ThisStack=$1
- ThisResource=$2
- fi
-fi
-
-if [ -z "$ThisStack" ] ; then
- echo "No AWS Cloudformation Stack specified; aborting script"
- exit 1
-elif [ -z "$ThisRegion" ] ; then
- echo "Failed to determine AWS region; aborthing script"
- exit 1
-fi
-
-# Validate that the resource actually exists before waiting for it to come up
-#
-resourceStatus=$(aws cloudformation describe-stack-resources \
- --output text \
- --region $ThisRegion \
- --stack-name $ThisStack \
- --logical-resource-id $ThisResource \
- --query StackResources[].ResourceStatus)
-
-if [ -z "$resourceStatus" ] ; then
- echo "$ThisResource has does not exist in $ThisStack"
- exit 0
-fi
-
-## TBD ... add timeout (optional, since CFT will enforce timeout)
-#
-while [ $resourceStatus != "CREATE_COMPLETE" ]
-do
- sleep 30
- resourceStatus=$(aws cloudformation describe-stack-resources \
- --output text \
- --region $ThisRegion \
- --stack-name $ThisStack \
- --logical-resource-id $ThisResource \
- --query StackResources[].ResourceStatus)
-done
-
-echo "$ThisResource has status $resourceStatus"
-
diff --git a/templates/nodecreate.template b/templates/nodecreate.template
index 0b0b647..9277210 100644
--- a/templates/nodecreate.template
+++ b/templates/nodecreate.template
@@ -5,8 +5,9 @@ Parameters:
SolaceDockerImage:
Description: >-
Solace PubSub+ event broker docker image reference: a docker registry name
+ Solace PubSub+ event broker Docker image reference: a Docker registry name
with optional tag or a download URL. The download URL can be obtained from http://dev.solace.com/downloads/
- or it can be a url to a remotely hosted load version
+ or it can be a url to an image in a registry or a url to a tar.gz image on a web server
Default: solace/solace-pubsub-standard:latest
Type: String
AdminPassword:
@@ -31,32 +32,57 @@ Parameters:
MinValue: '8'
Type: Number
ClusterInfoHandle:
- Description: ''
- Type: String
- InstanceProfile:
- Description: IAM Profile for the deployment
+ Description: Leave this blank for non-HA deployment
Type: String
+ Default: ''
KeyPairName:
Description: Name of an existing EC2 key pair within the AWS region; all instances
will launch with this key pair
Type: AWS::EC2::KeyPair::KeyName
NodeDesignation:
- Default: unspecified
- Description: Tag for deployed instances
+ Default: 'event-broker-singlenode'
+ Description: Purpose of the deployed instance. Will create a single-node non-HA deployment if set to default "event-broker-singlenode".
+ Type: String
+ MaxClientConnections:
+ AllowedValues:
+ - '100'
+ - '1000'
+ - '10000'
+ - '100000'
+ - '200000'
+ ConstraintDescription: Must be a valid value from the list.
+ Default: '100'
+ Description: 'Broker system scaling: the maximum supported number of client connections'
+ Type: String
+ MaxQueueMessages:
+ AllowedValues:
+ - '100'
+ - '240'
+ - '3000'
+ ConstraintDescription: Must be a valid EC2 instance type.
+ Default: '100'
+ Description: 'Broker system scaling: the maximum number of queue messages, in millions'
Type: String
NodeInstanceType:
ConstraintDescription: Must be a valid EC2 instance type.
Default: m4.large
Description: Instance Type for Solace PubSub+ event broker nodes
Type: String
+ SubnetID:
+ Description: >-
+ Comma separated list of VPC subnet IDs for the cluster deployment (e.g. subnet-4b8d329f,subnet-bd73afc8);
+ VPC must exist with proper configuration for Solacet cluster access (internal
+ and external) and the subnets must be in the same VPC as the security groups
+ Type: AWS::EC2::Subnet::Id
NodeSecurityGroup:
Description: Comma separated list of security groups for the members of the cluster
(e.g. sg-7f16e910,sg-4be93ca2); The security groups must be in the same VPC
as the subnets
Type: List
ParentStackName:
- Description: Wrapper stack for this deployment
+ Description: Leave this blank for non-HA deployemnt. For HA, the wrapper stack for this deployment.
Type: String
+ Default: ''
PersistentStorage:
ConstraintDescription: No more than 1024 GB per device (4 TB per node).
Default: '0'
@@ -90,18 +116,12 @@ Parameters:
QSS3KeyPrefix:
AllowedPattern: ^[0-9a-zA-Z-/]*$
ConstraintDescription: Quick Start key prefix can include numbers, lowercase letters,
- uppercase letters, hyphens (-), and forward slash (/).
+ uppercase letters, hyphens (-), and forward slash (/). Must end with a /
Default: pubsubplus-aws-ha-quickstart/latest/
Description: S3 key prefix for the Quick Start assets. Quick Start key prefix
can include numbers, lowercase letters, uppercase letters, hyphens (-), and
forward slash (/).
Type: String
- SubnetID:
- Description: >-
- Comma separated list of VPC subnet IDs for the cluster deployment (e.g. subnet-4b8d329f,subnet-bd73afc8);
- VPC must exist with proper configuration for Solacet cluster access (internal
- and external) and the subnets must be in the same VPC as the security groups
- Type: AWS::EC2::Subnet::Id
Mappings:
AWSAMIRegionMap:
AMI:
@@ -164,10 +184,8 @@ Conditions:
EphemeralStorage: !Equals
- !Ref 'PersistentStorage'
- '0'
- GovCloudCondition: !Equals
- - !Ref 'AWS::Region'
- - us-gov-west-1
UsingDefaultBucket: !Equals [!Ref QSS3BucketName, 'aws-quickstart']
+ NonHA: !Equals [!Ref NodeDesignation, 'event-broker-singlenode']
Resources:
CloudFormationLogs:
Type: AWS::Logs::LogGroup
@@ -181,10 +199,10 @@ Resources:
Namespace: AWS/EC2
MetricName: StatusCheckFailed_System
Statistic: Minimum
- Period: '60'
- EvaluationPeriods: '3'
+ Period: 60
+ EvaluationPeriods: 3
ComparisonOperator: GreaterThanThreshold
- Threshold: '0'
+ Threshold: 0
AlarmActions:
- !Join
- ''
@@ -193,7 +211,7 @@ Resources:
- :ec2:recover
Dimensions:
- Name: InstanceId
- Value: !Ref 'NodeLaunchConfig'
+ Value: !Ref 'BrokerNodeInstance'
NodeRole:
Type: AWS::IAM::Role
Properties:
@@ -244,7 +262,7 @@ Resources:
Roles:
- !Ref NodeRole
Path: /
- NodeLaunchConfig:
+ BrokerNodeInstance:
Type: AWS::EC2::Instance
Metadata:
AWS::CloudFormation::Authentication:
@@ -398,14 +416,6 @@ Resources:
mode: '000755'
owner: root
group: root
- /tmp/wait-for-resource.sh:
- source: !Sub
- - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/wait-for-resource.sh
- - S3Region: !If [UsingDefaultBucket, !Ref 'AWS::Region', !Ref QSS3BucketRegion]
- S3Bucket: !If [UsingDefaultBucket, !Sub '${QSS3BucketName}-${AWS::Region}', !Ref QSS3BucketName]
- mode: '000755'
- owner: root
- group: root
/etc/init.d/solace-pubsubplus:
source: !Sub
- https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/init.d/solace-pubsubplus
@@ -477,83 +487,137 @@ Resources:
- Key: Name
Value: !Join
- '-'
- - - !Ref 'ParentStackName'
+ - - !If [NonHA, !Ref 'AWS::StackName', !Ref ParentStackName]
- !Ref 'NodeDesignation'
- Key: ParentStack
- Value: !Ref 'ParentStackName'
+ Value: !If [NonHA, !Ref 'AWS::StackName', !Ref ParentStackName]
- Key: HARole
- Value: !Ref 'NodeDesignation'
- UserData: !Base64
- Fn::Join:
- - ''
- - - "#!/bin/bash -xe\n"
- - "AMI_SBIN=/tmp\n"
- - "yum install -y aws-cfn-bootstrap\n"
- - "\n"
- - "## Retrieve scripts to deploy PubSub+ on the instances \n"
- - '/opt/aws/bin/cfn-init -v '
- - ' --stack '
- - !Ref 'AWS::StackName'
- - ' --resource NodeLaunchConfig '
- - ' --configsets install_all '
- - ' --region '
- - !Ref 'AWS::Region'
- - "\n"
- - "## Wait for all nodes to come on-line\n"
- - '$AMI_SBIN/wait-for-child-resource.sh '
- - !Ref 'ParentStackName'
- - " MonitorStack NodeLaunchConfig\n"
- - "\n"
- - '$AMI_SBIN/wait-for-child-resource.sh '
- - !Ref 'ParentStackName'
- - " EventBrokerPrimaryStack NodeLaunchConfig\n"
- - "\n"
- - '$AMI_SBIN/wait-for-child-resource.sh '
- - !Ref 'ParentStackName'
- - " EventBrokerBackupStack NodeLaunchConfig\n"
- - "\n"
- - "## Now find the private IP addresses of all deployed nodes\n"
- - "## (generating /tmp/solacehosts and /tmp/ files)\n"
- - '$AMI_SBIN/gen-cluster-hosts.sh '
- - !Ref 'ParentStackName'
- - "\n"
- - "## Tag the instance (now that we're sure of launch index)\n"
- - "instance_id=$(curl -f http://169.254.169.254/latest/meta-data/instance-id)\n"
- - instance_tag=
- - !Ref 'ParentStackName'
- - '-'
- - !Ref 'NodeDesignation'
- - "\n"
- - " \n"
- - aws ec2 create-tags
- - ' --region '
- - !Ref 'AWS::Region'
- - " --resources $instance_id --tags Key=Name,Value=$instance_tag\n"
- - "\n"
- - "cd /tmp\n"
- - "# Install PubSub+\n"
- - $AMI_SBIN/install-solace.sh -c /tmp/solacehosts -d /tmp/solace
- - ' -u '
- - !Ref 'SolaceDockerImage'
- - ' -p /mnt/pubsubplus/secrets/solOSpasswd'
- - ' -s '
- - !Ref 'PersistentStorage'
- - ' -v /dev/xvdb'
- - ' -f '
- - !Ref 'ContainerLoggingFormat'
- - ' -g '
- - !Ref 'CloudFormationLogs'
- - ' -r ${instance_id}/solace.log'
- - " \n"
- - "## Signal back information for outputs (now that all nodes are up)\
- \ \n"
- - /opt/aws/bin/cfn-signal -e 0 -r 'PubSub+ HA deployment complete' '
- - !Ref 'ClusterInfoHandle'
- - "'\n"
- - "\n"
+ Value: !If [NonHA, 'non-ha', !Ref NodeDesignation]
+ UserData:
+ !If
+ - NonHA
+ - !Base64 # Simplified setup for non-HA deployment
+ Fn::Join:
+ - ''
+ - - "#!/bin/bash -xe\n"
+ - "AMI_SBIN=/tmp\n"
+ - "yum install -y aws-cfn-bootstrap\n"
+ - "\n"
+ - "## Retrieve scripts to deploy PubSub+ on the instances \n"
+ - '/opt/aws/bin/cfn-init -v '
+ - ' --stack '
+ - !Ref 'AWS::StackName'
+ - ' --resource BrokerNodeInstance '
+ - ' --configsets install_all '
+ - ' --region '
+ - !Ref 'AWS::Region'
+ - "\n"
+ - "cd /tmp\n"
+ - "# Install PubSub+\n"
+ - $AMI_SBIN/install-solace.sh -c /tmp/solacehosts -d /tmp/solace
+ - ' -h false' # specifying non-HA deployment
+ - ' -u '
+ - !Ref 'SolaceDockerImage'
+ - ' -p /mnt/pubsubplus/secrets/solOSpasswd'
+ - ' -s '
+ - !Ref 'PersistentStorage'
+ - ' -v /dev/xvdb'
+ - ' -f '
+ - !Ref 'ContainerLoggingFormat'
+ - ' -g '
+ - !Ref 'CloudFormationLogs'
+ - ' -r ${instance_id}/solace.log'
+ - ' -n '
+ - !Ref 'MaxClientConnections'
+ - ' -q '
+ - !Ref 'MaxQueueMessages'
+ - "\n"
+ - !Base64 # Full setup for HA deployment
+ Fn::Join:
+ - ''
+ - - "#!/bin/bash -xe\n"
+ - "AMI_SBIN=/tmp\n"
+ - "yum install -y aws-cfn-bootstrap\n"
+ - "\n"
+ - "## Retrieve scripts to deploy PubSub+ on the instances \n"
+ - '/opt/aws/bin/cfn-init -v '
+ - ' --stack '
+ - !Ref 'AWS::StackName'
+ - ' --resource BrokerNodeInstance '
+ - ' --configsets install_all '
+ - ' --region '
+ - !Ref 'AWS::Region'
+ - "\n"
+ - "## Wait for all nodes to come on-line\n"
+ - '$AMI_SBIN/wait-for-child-resource.sh '
+ - !Ref 'ParentStackName'
+ - " MonitorStack BrokerNodeInstance\n"
+ - "\n"
+ - '$AMI_SBIN/wait-for-child-resource.sh '
+ - !Ref 'ParentStackName'
+ - " EventBrokerPrimaryStack BrokerNodeInstance\n"
+ - "\n"
+ - '$AMI_SBIN/wait-for-child-resource.sh '
+ - !Ref 'ParentStackName'
+ - " EventBrokerBackupStack BrokerNodeInstance\n"
+ - "\n"
+ - "## Now find the private IP addresses of all deployed nodes\n"
+ - "## (generating /tmp/solacehosts and /tmp/ files)\n"
+ - '$AMI_SBIN/gen-cluster-hosts.sh '
+ - !Ref 'ParentStackName'
+ - "\n"
+ - "## Tag the instance (now that we're sure of launch index)\n"
+ - "instance_id=$(curl -f http://169.254.169.254/latest/meta-data/instance-id)\n"
+ - instance_tag=
+ - !Ref 'ParentStackName'
+ - '-'
+ - !Ref 'NodeDesignation'
+ - "\n"
+ - " \n"
+ - aws ec2 create-tags
+ - ' --region '
+ - !Ref 'AWS::Region'
+ - " --resources $instance_id --tags Key=Name,Value=$instance_tag\n"
+ - "\n"
+ - "cd /tmp\n"
+ - "# Install PubSub+\n"
+ - $AMI_SBIN/install-solace.sh -c /tmp/solacehosts -d /tmp/solace
+ - ' -h true' # specifying HA deployment
+ - ' -u '
+ - !Ref 'SolaceDockerImage'
+ - ' -p /mnt/pubsubplus/secrets/solOSpasswd'
+ - ' -s '
+ - !Ref 'PersistentStorage'
+ - ' -v /dev/xvdb'
+ - ' -f '
+ - !Ref 'ContainerLoggingFormat'
+ - ' -g '
+ - !Ref 'CloudFormationLogs'
+ - ' -r ${instance_id}/solace.log'
+ - ' -n '
+ - !Ref 'MaxClientConnections'
+ - ' -q '
+ - !Ref 'MaxQueueMessages'
+ - " \n"
+ - "## Signal back information for outputs (now that all nodes are up)\
+ \ \n"
+ - /opt/aws/bin/cfn-signal -e 0 -r 'PubSub+ HA deployment complete' '
+ - !Ref 'ClusterInfoHandle'
+ - "'\n"
+ - "\n"
Outputs:
EC2ID:
Description: Reference to created ec2 instance
- Value: !Ref 'NodeLaunchConfig'
+ Value: !Ref BrokerNodeInstance
Export:
Name: !Sub '${AWS::StackName}-EC2ID'
+ PrivateDnsName:
+ Description: Private DNS name of the created ec2 instance
+ Value: !GetAtt BrokerNodeInstance.PrivateDnsName
+ Export:
+ Name: !Sub '${AWS::StackName}-PrivateDnsName'
+ PublicDNSName:
+ Description: Public DNS name of the created ec2 instance
+ Value: !GetAtt BrokerNodeInstance.PublicDnsName
+ Export:
+ Name: !Sub '${AWS::StackName}-PublicDNSName'
diff --git a/templates/solace-master.template b/templates/solace-master.template
index 5755546..1445f81 100644
--- a/templates/solace-master.template
+++ b/templates/solace-master.template
@@ -8,10 +8,15 @@ Metadata:
AWS::CloudFormation::Interface:
ParameterGroups:
- Label:
- default: PubSub+ Configuration
+ default: PubSub+ Event Broker Configuration
Parameters:
- SolaceDockerImage
- AdminPassword
+ - MaxClientConnections
+ - MaxQueueMessages
+ - WorkerNodeInstanceType
+ - WorkerNodeStorage
+ - MonitorNodeInstanceType
- ContainerLoggingFormat
- Label:
default: Network Configuration
@@ -26,15 +31,6 @@ Metadata:
Parameters:
- KeyPairName
- BootDiskSize
- - Label:
- default: Event Broker Instance Configuration
- Parameters:
- - EventBrokerNodeInstanceType
- - EventBrokerNodeStorage
- - Label:
- default: Monitor Instance Configuration
- Parameters:
- - MonitorNodeInstanceType
- Label:
default: AWS Quick Start Configuration
Parameters:
@@ -54,12 +50,16 @@ Metadata:
default: Number of Availability Zones
BootDiskSize:
default: Boot Disk Capacity (GiB)
- EventBrokerNodeInstanceType:
- default: Instance Type
- EventBrokerNodeStorage:
+ MaxClientConnections:
+ default: Maximum Number of Client Connections
+ MaxQueueMessages:
+ default: Maximum Number of Queue Messages
+ WorkerNodeInstanceType:
+ default: Message Routing Node Instance Type
+ WorkerNodeStorage:
default: Persistent Storage
MonitorNodeInstanceType:
- default: Instance Type
+ default: Monitor Node Instance Type
KeyPairName:
default: Key Pair Name
SSHAccessCIDR:
@@ -67,7 +67,7 @@ Metadata:
RemoteAccessCIDR:
default: Allowed External Access CIDR
CreatePrivateSubnets:
- default: Create production ready enviroment
+ default: Create production ready environment
QSS3BucketName:
default: Quick Start S3 Bucket Name
QSS3BucketRegion:
@@ -79,7 +79,7 @@ Parameters:
Description: >-
Solace PubSub+ event broker Docker image reference: a Docker registry name
with optional tag or a download URL. The download URL can be obtained from http://dev.solace.com/downloads/
- or it can be a url to a remotely hosted load version
+ or it can be a url to an image in a registry or a url to a tar.gz image on a web server
Default: solace/solace-pubsub-standard:latest
Type: String
AdminPassword:
@@ -103,10 +103,10 @@ Parameters:
to ''Number of Availability Zones'' previously specified'
Type: List
NumberOfAZs:
- ConstraintDescription: 3 means each node in own az, 2 puts monitor and backup
- in one az
+ ConstraintDescription: Valid numbers are 3 or 2
Default: '3'
- Description: Number of availability zones to use
+ Description: Number of availability zones, based on availability in the target region, valid numbers are 3 or 2. 3 means each node in own AZ, 2 puts monitor and backup
+ in one AZ.
AllowedValues:
- '2'
- '3'
@@ -118,15 +118,33 @@ Parameters:
MaxValue: '128'
MinValue: '8'
Type: Number
- EventBrokerNodeInstanceType:
+ MaxClientConnections:
+ AllowedValues:
+ - '100'
+ - '1000'
+ - '10000'
+ - '100000'
+ - '200000'
+ ConstraintDescription: Must be a valid value from the list.
+ Default: '100'
+ Description: 'Broker system scaling: the maximum supported number of client connections'
+ Type: String
+ MaxQueueMessages:
+ AllowedValues:
+ - '100'
+ - '240'
+ - '3000'
+ ConstraintDescription: Must be a valid EC2 instance type.
+ Default: '100'
+ Description: 'Broker system scaling: the maximum number of queue messages, in millions'
+ Type: String
+ WorkerNodeInstanceType:
AllowedValues:
- t2.small
- t2.medium
- t2.large
- t2.xlarge
- t2.2xlarge
- - m3.large
- - m3.xlarge
- m4.large
- m4.xlarge
- m4.2xlarge
@@ -137,10 +155,11 @@ Parameters:
- m5.4xlarge
ConstraintDescription: Must be a valid EC2 instance type.
Default: m4.large
- Description: 'Instance Type for PubSub+ event broker message routing nodes. Note:
- Make sure that your region supports the selected instance type before continuing'
+ Description: 'Instance Type for PubSub+ event broker message routing nodes. Important: ensure adequate CPU and Memory resources
+ are available to support the selected system scaling parameters. For requirements check https://docs.solace.com/.
+ Also make sure that your region supports the selected instance type before continuing.'
Type: String
- EventBrokerNodeStorage:
+ WorkerNodeStorage:
ConstraintDescription: No more than 640 GiB per device.
Default: '0'
Description: Allocated EBS storage for each block device (in GiB); 0 indicates
@@ -178,16 +197,13 @@ Parameters:
Type: String
MonitorNodeInstanceType:
AllowedValues:
- - t2.micro
- t2.small
- t2.medium
- - t2.large
- - t2.xlarge
- m4.large
- m5.large
ConstraintDescription: Must be a valid EC2 instance type.
- Default: t2.micro
- Description: 'Instance Type for PubSub+ event broker monitoring node. Note: Make
+ Default: t2.medium
+ Description: 'Instance Type for PubSub+ event broker monitoring node. For requirements check https://docs.solace.com/. Note: Make
sure that your region supports the selected instance type before continuing'
Type: String
QSS3BucketName:
@@ -221,9 +237,6 @@ Conditions:
UsePrivateSubnets: !Equals
- !Ref 'CreatePrivateSubnets'
- 'true'
- GovCloudCondition: !Equals
- - !Ref 'AWS::Region'
- - us-gov-west-1
UsingDefaultBucket: !Equals [!Ref QSS3BucketName, 'aws-quickstart']
Resources:
VPCStack:
@@ -244,8 +257,6 @@ Resources:
BastionStack:
Type: AWS::CloudFormation::Stack
Condition: UsePrivateSubnets
- DependsOn:
- - VPCStack
Properties:
TemplateURL:
!Sub
@@ -283,8 +294,10 @@ Resources:
ContainerLoggingFormat: !Ref 'ContainerLoggingFormat'
NumberOfAZs: !Ref 'NumberOfAZs'
BootDiskSize: !Ref 'BootDiskSize'
- EventBrokerNodeInstanceType: !Ref 'EventBrokerNodeInstanceType'
- EventBrokerNodeStorage: !Ref 'EventBrokerNodeStorage'
+ MaxClientConnections: !Ref 'MaxClientConnections'
+ MaxQueueMessages: !Ref 'MaxQueueMessages'
+ WorkerNodeInstanceType: !Ref 'WorkerNodeInstanceType'
+ WorkerNodeStorage: !Ref 'WorkerNodeStorage'
MonitorNodeInstanceType: !Ref 'MonitorNodeInstanceType'
KeyPairName: !Ref 'KeyPairName'
QSS3BucketName: !Ref 'QSS3BucketName'
diff --git a/templates/solace.template b/templates/solace.template
index de73b64..02203e5 100644
--- a/templates/solace.template
+++ b/templates/solace.template
@@ -5,10 +5,15 @@ Metadata:
AWS::CloudFormation::Interface:
ParameterGroups:
- Label:
- default: Solace Configuration
+ default: PubSub+ Event Broker Configuration
Parameters:
- SolaceDockerImage
- AdminPassword
+ - MaxClientConnections
+ - MaxQueueMessages
+ - WorkerNodeInstanceType
+ - WorkerNodeStorage
+ - MonitorNodeInstanceType
- ContainerLoggingFormat
- Label:
default: Network Configuration
@@ -25,15 +30,6 @@ Metadata:
Parameters:
- KeyPairName
- BootDiskSize
- - Label:
- default: Event Broker Instance Configuration
- Parameters:
- - EventBrokerNodeInstanceType
- - EventBrokerNodeStorage
- - Label:
- default: Monitor Instance Configuration
- Parameters:
- - MonitorNodeInstanceType
- Label:
default: AWS Quick Start Configuration
Parameters:
@@ -42,27 +38,31 @@ Metadata:
- QSS3KeyPrefix
ParameterLabels:
SolaceDockerImage:
- default: Solace Docker image reference
+ default: PubSub+ Docker image reference
AdminPassword:
- default: Password to access Solace admin console and SEMP
+ default: Password to access PubSub+ admin console and SEMP
ContainerLoggingFormat:
default: Container logging format
+ NumberOfAZs:
+ default: Number of Availability Zones
BootDiskSize:
default: Boot Disk Capacity (GiB)
- EventBrokerNodeInstanceType:
- default: Instance Type
- EventBrokerNodeStorage:
+ MaxClientConnections:
+ default: Maximum Number of Client Connections
+ MaxQueueMessages:
+ default: Maximum Number of Queue Messages
+ WorkerNodeInstanceType:
+ default: Message Routing Node Instance Type
+ WorkerNodeStorage:
default: Persistent Storage
MonitorNodeInstanceType:
- default: Instance Type
+ default: Monitor Node Instance Type
KeyPairName:
default: Key Pair Name
- NumberOfAZs:
- default: Number of Availability Zones to use
RemoteAccessCIDR:
default: Allowed External Access CIDR
SSHSecurityGroupID:
- default: Security group allowed to access console SSH
+ default: Security group allowed to access console SSH. Ignored if not using private subnets.
UsePrivateSubnets:
default: Use private subnets
VPCID:
@@ -80,13 +80,14 @@ Metadata:
Parameters:
SolaceDockerImage:
Description: >-
- Solace PubSub+ event broker docker image reference: a docker registry name
+ Solace PubSub+ event broker Docker image reference: a Docker registry name
with optional tag or a download URL. The download URL can be obtained from http://dev.solace.com/downloads/
- or it can be a url to a remotely hosted load version
+ or it can be a url to an image in a registry or a url to a tar.gz image on a web server
Default: solace/solace-pubsub-standard:latest
Type: String
AdminPassword:
- Description: Required password to access Solace admin console and SEMP
+ Description: Password to allow Solace admin access to configure the event broker
+ instances
Type: String
NoEcho: 'True'
ContainerLoggingFormat:
@@ -99,6 +100,15 @@ Parameters:
Default: graylog
Description: PubSub+ event broker logging format in CloudWatch
Type: String
+ NumberOfAZs:
+ ConstraintDescription: Valid numbers are 3 or 2
+ Default: '3'
+ Description: Number of availability zones, based on availability in the target region, valid numbers are 3 or 2. 3 means each node in own AZ, 2 puts monitor and backup
+ in one AZ.
+ AllowedValues:
+ - '2'
+ - '3'
+ Type: Number
BootDiskSize:
ConstraintDescription: Deployment supports 8 to 128 GB for boot volumes
Default: '24'
@@ -106,15 +116,33 @@ Parameters:
MaxValue: '128'
MinValue: '8'
Type: Number
- EventBrokerNodeInstanceType:
+ MaxClientConnections:
+ AllowedValues:
+ - '100'
+ - '1000'
+ - '10000'
+ - '100000'
+ - '200000'
+ ConstraintDescription: Must be a valid value from the list.
+ Default: '100'
+ Description: 'Broker system scaling: the maximum supported number of client connections'
+ Type: String
+ MaxQueueMessages:
+ AllowedValues:
+ - '100'
+ - '240'
+ - '3000'
+ ConstraintDescription: Must be a valid EC2 instance type.
+ Default: '100'
+ Description: 'Broker system scaling: the maximum number of queue messages, in millions'
+ Type: String
+ WorkerNodeInstanceType:
AllowedValues:
- t2.small
- t2.medium
- t2.large
- t2.xlarge
- t2.2xlarge
- - m3.large
- - m3.xlarge
- m4.large
- m4.xlarge
- m4.2xlarge
@@ -125,10 +153,11 @@ Parameters:
- m5.4xlarge
ConstraintDescription: Must be a valid EC2 instance type.
Default: m4.large
- Description: 'Instance Type for PubSub+ event broker message routing nodes. Note:
- Make sure that your region supports the selected instance type before continuing'
+ Description: 'Instance Type for PubSub+ event broker message routing nodes. Important: ensure adequate CPU and Memory resources
+ are available to support the selected system scaling parameters. For requirements check https://docs.solace.com/.
+ Also make sure that your region supports the selected instance type before continuing.'
Type: String
- EventBrokerNodeStorage:
+ WorkerNodeStorage:
ConstraintDescription: No more than 640 GiB per device.
Default: '0'
Description: Allocated EBS storage for each block device (in GiB); 0 indicates
@@ -143,49 +172,37 @@ Parameters:
- '320'
- '640'
Type: Number
- MonitorNodeInstanceType:
- AllowedValues:
- - t2.micro
- - t2.small
- - t2.medium
- - t2.large
- - t2.xlarge
- - m4.large
- - m5.large
- ConstraintDescription: Must be a valid EC2 instance type.
- Default: t2.micro
- Description: 'Instance Type for PubSub+ event broker monitoring node. Note: Make
- sure that your region supports the selected instance type before continuing'
- Type: String
KeyPairName:
Description: Name of an existing EC2 key pair within the AWS region; all instances
will launch with this key pair
Type: AWS::EC2::KeyPair::KeyName
- NumberOfAZs:
- ConstraintDescription: 3 means each node in own az, 2 puts monitor and backup
- in one az
- Default: '3'
- Description: Number of availability zones to use
+ UsePrivateSubnets:
AllowedValues:
- - '2'
- - '3'
- Type: Number
+ - 'true'
+ - 'false'
+ Default: 'true'
+ Description: Whether to use Private Subnets with fronting Bastion Servers
+ Type: String
RemoteAccessCIDR:
AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))$
ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/x
Description: Allowed CIDR block for external access to cluster nodes
Type: String
+ MonitorNodeInstanceType:
+ AllowedValues:
+ - t2.small
+ - t2.medium
+ - m4.large
+ - m5.large
+ ConstraintDescription: Must be a valid EC2 instance type.
+ Default: t2.medium
+ Description: 'Instance Type for PubSub+ event broker monitoring node. For requirements check https://docs.solace.com/. Note: Make
+ sure that your region supports the selected instance type before continuing'
+ Type: String
SSHSecurityGroupID:
Description: 'ID of the SSH Security Group (e.g., sg-7f16e910). Note: This will
be ignored if ''Use private subnets'' is set to ''false'''
Type: String
- UsePrivateSubnets:
- AllowedValues:
- - 'true'
- - 'false'
- Default: 'true'
- Description: Whether to use Private Subnets with fronting Bastion Servers
- Type: String
PrivateSubnetIDs:
Description: >-
Comma separated list of VPC private subnet IDs for the cluster deployment (e.g.
@@ -224,50 +241,6 @@ Parameters:
can include numbers, lowercase letters, uppercase letters, hyphens (-), and
forward slash (/).
Type: String
-Mappings:
- AWSInfoRegionMap:
- ap-northeast-1:
- Partition: aws
- QuickStartS3URL: https://s3.amazonaws.com
- ap-northeast-2:
- Partition: aws
- QuickStartS3URL: https://s3.amazonaws.com
- ap-south-1:
- Partition: aws
- QuickStartS3URL: https://s3.amazonaws.com
- ap-southeast-1:
- Partition: aws
- QuickStartS3URL: https://s3.amazonaws.com
- ap-southeast-2:
- Partition: aws
- QuickStartS3URL: https://s3.amazonaws.com
- ca-central-1:
- Partition: aws
- QuickStartS3URL: https://s3.amazonaws.com
- eu-central-1:
- Partition: aws
- QuickStartS3URL: https://s3.amazonaws.com
- eu-west-1:
- Partition: aws
- QuickStartS3URL: https://s3.amazonaws.com
- eu-west-2:
- Partition: aws
- QuickStartS3URL: https://s3.amazonaws.com
- sa-east-1:
- Partition: aws
- QuickStartS3URL: https://s3.amazonaws.com
- us-east-1:
- Partition: aws
- QuickStartS3URL: https://s3.amazonaws.com
- us-east-2:
- Partition: aws
- QuickStartS3URL: https://s3.amazonaws.com
- us-west-1:
- Partition: aws
- QuickStartS3URL: https://s3.amazonaws.com
- us-west-2:
- Partition: aws
- QuickStartS3URL: https://s3.amazonaws.com
Conditions:
EnableWaitConditions: !Equals
- '1'
@@ -278,62 +251,8 @@ Conditions:
UsePrivateSubnetsCondition: !Equals
- !Ref 'UsePrivateSubnets'
- 'true'
- GovCloudCondition: !Equals
- - !Ref 'AWS::Region'
- - us-gov-west-1
UsingDefaultBucket: !Equals [!Ref QSS3BucketName, 'aws-quickstart']
Resources:
- SolaceVMRRole:
- Type: AWS::IAM::Role
- Properties:
- Policies:
- - PolicyDocument:
- Version: '2012-10-17'
- Statement:
- - Action:
- - s3:GetObject
- Resource: "*"
- Effect: Allow
- PolicyName: s3-policy
- - PolicyDocument:
- Version: '2012-10-17'
- Statement:
- - Action:
- - cloudformation:DescribeStackResources
- - ec2:DescribeInstances
- - ec2:CreateTags
- Resource:
- - '*'
- Effect: Allow
- PolicyName: ec2-policy
- - PolicyDocument:
- Version: '2012-10-17'
- Statement:
- - Action:
- - logs:CreateLogGroup
- - logs:CreateLogStream
- - logs:PutLogEvents
- - logs:DescribeLogStreams
- Resource:
- - arn:aws:logs:*:*:*
- Effect: Allow
- PolicyName: cloudwatch-policy
- Path: /
- AssumeRolePolicyDocument:
- Statement:
- - Action:
- - sts:AssumeRole
- Principal:
- Service:
- - ec2.amazonaws.com
- Effect: Allow
- Version: '2012-10-17'
- InstanceProfile:
- Type: AWS::IAM::InstanceProfile
- Properties:
- Path: /
- Roles:
- - !Ref 'SolaceVMRRole'
EventBrokerPrimaryStack:
Type: AWS::CloudFormation::Stack
Properties:
@@ -348,18 +267,19 @@ Resources:
ContainerLoggingFormat: !Ref 'ContainerLoggingFormat'
BootDiskSize: !Ref 'BootDiskSize'
ClusterInfoHandle: !Ref 'ClusterInfoHandle'
- InstanceProfile: !Ref 'InstanceProfile'
KeyPairName: !Ref 'KeyPairName'
- NodeDesignation: message-router-primary
- NodeInstanceType: !Ref 'EventBrokerNodeInstanceType'
+ NodeDesignation: event-broker-primary
+ MaxClientConnections: !Ref 'MaxClientConnections'
+ MaxQueueMessages: !Ref 'MaxQueueMessages'
+ NodeInstanceType: !Ref 'WorkerNodeInstanceType'
NodeSecurityGroup: !Join
- ','
- - !Ref 'EventBrokerSecurityGroup'
- !Ref 'SolaceInternalSecurityGroup'
- - !Ref 'SolaceInternalSecurityGroupMember'
+ - !Ref 'BrokerMemberNodesSecurityGroup'
- !Ref 'RemoteMgmtSecurityGroup'
ParentStackName: !Ref 'AWS::StackName'
- PersistentStorage: !Ref 'EventBrokerNodeStorage'
+ PersistentStorage: !Ref 'WorkerNodeStorage'
QSS3BucketName: !Ref 'QSS3BucketName'
QSS3BucketRegion: !Ref 'QSS3BucketRegion'
QSS3KeyPrefix: !Ref 'QSS3KeyPrefix'
@@ -383,18 +303,19 @@ Resources:
ContainerLoggingFormat: !Ref 'ContainerLoggingFormat'
BootDiskSize: !Ref 'BootDiskSize'
ClusterInfoHandle: !Ref 'ClusterInfoHandle'
- InstanceProfile: !Ref 'InstanceProfile'
KeyPairName: !Ref 'KeyPairName'
- NodeDesignation: message-router-backup
- NodeInstanceType: !Ref 'EventBrokerNodeInstanceType'
+ NodeDesignation: event-broker-backup
+ MaxClientConnections: !Ref 'MaxClientConnections'
+ MaxQueueMessages: !Ref 'MaxQueueMessages'
+ NodeInstanceType: !Ref 'WorkerNodeInstanceType'
NodeSecurityGroup: !Join
- ','
- - !Ref 'EventBrokerSecurityGroup'
- !Ref 'SolaceInternalSecurityGroup'
- - !Ref 'SolaceInternalSecurityGroupMember'
+ - !Ref 'BrokerMemberNodesSecurityGroup'
- !Ref 'RemoteMgmtSecurityGroup'
ParentStackName: !Ref 'AWS::StackName'
- PersistentStorage: !Ref 'EventBrokerNodeStorage'
+ PersistentStorage: !Ref 'WorkerNodeStorage'
QSS3BucketName: !Ref 'QSS3BucketName'
QSS3BucketRegion: !Ref 'QSS3BucketRegion'
QSS3KeyPrefix: !Ref 'QSS3KeyPrefix'
@@ -418,14 +339,13 @@ Resources:
ContainerLoggingFormat: !Ref 'ContainerLoggingFormat'
BootDiskSize: !Ref 'BootDiskSize'
ClusterInfoHandle: !Ref 'ClusterInfoHandle'
- InstanceProfile: !Ref 'InstanceProfile'
KeyPairName: !Ref 'KeyPairName'
NodeDesignation: monitor
NodeInstanceType: !Ref 'MonitorNodeInstanceType'
NodeSecurityGroup: !Join
- ','
- - !Ref 'SolaceInternalSecurityGroup'
- - !Ref 'SolaceInternalSecurityGroupMember'
+ - !Ref 'BrokerMemberNodesSecurityGroup'
- !Ref 'RemoteMgmtSecurityGroup'
ParentStackName: !Ref 'AWS::StackName'
PersistentStorage: '0'
@@ -433,87 +353,79 @@ Resources:
QSS3BucketRegion: !Ref 'QSS3BucketRegion'
QSS3KeyPrefix: !Ref 'QSS3KeyPrefix'
SubnetID: !Select
- - !If
- - Use3AZs
- - 2
- - 1
- - !If
- - UsePrivateSubnetsCondition
- - !Ref 'PrivateSubnetIDs'
- - !Ref 'PublicSubnetIDs'
- SolaceInternalSecurityGroupMember:
+ - !If [Use3AZs, 2, 1]
+ - !If [UsePrivateSubnetsCondition, !Ref PrivateSubnetIDs, !Ref PublicSubnetIDs]
+ BrokerMemberNodesSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
VpcId: !Ref 'VPCID'
- GroupDescription: All Solace Nodes
+ GroupDescription: Internal group, includes broker node members only
SolaceInternalSecurityGroup:
Type: AWS::EC2::SecurityGroup
- DependsOn:
- - SolaceInternalSecurityGroupMember
Properties:
VpcId: !Ref 'VPCID'
- GroupDescription: All Solace Nodes
+ GroupDescription: Controls internal traffic between broker member nodes
SecurityGroupIngress:
- IpProtocol: tcp
- FromPort: '8741'
- ToPort: '8741'
- SourceSecurityGroupId: !Ref 'SolaceInternalSecurityGroupMember'
+ FromPort: 8741
+ ToPort: 8741
+ SourceSecurityGroupId: !Ref 'BrokerMemberNodesSecurityGroup'
- IpProtocol: tcp
- FromPort: '8300'
- ToPort: '8302'
- SourceSecurityGroupId: !Ref 'SolaceInternalSecurityGroupMember'
+ FromPort: 8300
+ ToPort: 8302
+ SourceSecurityGroupId: !Ref 'BrokerMemberNodesSecurityGroup'
- IpProtocol: udp
- FromPort: '8300'
- ToPort: '8302'
- SourceSecurityGroupId: !Ref 'SolaceInternalSecurityGroupMember'
+ FromPort: 8300
+ ToPort: 8302
+ SourceSecurityGroupId: !Ref 'BrokerMemberNodesSecurityGroup'
- IpProtocol: tcp
- FromPort: '55555'
- ToPort: '55555'
- SourceSecurityGroupId: !Ref 'SolaceInternalSecurityGroupMember'
+ FromPort: 55555
+ ToPort: 55555
+ SourceSecurityGroupId: !Ref 'BrokerMemberNodesSecurityGroup'
- IpProtocol: tcp
- FromPort: '55003'
- ToPort: '55003'
- SourceSecurityGroupId: !Ref 'SolaceInternalSecurityGroupMember'
+ FromPort: 55003
+ ToPort: 55003
+ SourceSecurityGroupId: !Ref 'BrokerMemberNodesSecurityGroup'
- IpProtocol: tcp
- FromPort: '55443'
- ToPort: '55443'
- SourceSecurityGroupId: !Ref 'SolaceInternalSecurityGroupMember'
+ FromPort: 55443
+ ToPort: 55443
+ SourceSecurityGroupId: !Ref 'BrokerMemberNodesSecurityGroup'
- IpProtocol: tcp
- FromPort: '1443'
- ToPort: '1443'
- SourceSecurityGroupId: !Ref 'SolaceInternalSecurityGroupMember'
+ FromPort: 1443
+ ToPort: 1443
+ SourceSecurityGroupId: !Ref 'BrokerMemberNodesSecurityGroup'
- IpProtocol: tcp
- FromPort: '8000'
- ToPort: '8000'
- SourceSecurityGroupId: !Ref 'SolaceInternalSecurityGroupMember'
+ FromPort: 8000
+ ToPort: 8000
+ SourceSecurityGroupId: !Ref 'BrokerMemberNodesSecurityGroup'
- IpProtocol: tcp
- FromPort: '5672'
- ToPort: '5672'
- SourceSecurityGroupId: !Ref 'SolaceInternalSecurityGroupMember'
+ FromPort: 5672
+ ToPort: 5672
+ SourceSecurityGroupId: !Ref 'BrokerMemberNodesSecurityGroup'
- IpProtocol: tcp
- FromPort: '9000'
- ToPort: '9000'
- SourceSecurityGroupId: !Ref 'SolaceInternalSecurityGroupMember'
+ FromPort: 9000
+ ToPort: 9000
+ SourceSecurityGroupId: !Ref 'BrokerMemberNodesSecurityGroup'
- IpProtocol: tcp
- FromPort: '1883'
- ToPort: '1883'
- SourceSecurityGroupId: !Ref 'SolaceInternalSecurityGroupMember'
+ FromPort: 1883
+ ToPort: 1883
+ SourceSecurityGroupId: !Ref 'BrokerMemberNodesSecurityGroup'
- IpProtocol: tcp
- FromPort: '8008'
- ToPort: '8008'
- SourceSecurityGroupId: !Ref 'SolaceInternalSecurityGroupMember'
+ FromPort: 8008
+ ToPort: 8008
+ SourceSecurityGroupId: !Ref 'BrokerMemberNodesSecurityGroup'
- IpProtocol: tcp
- FromPort: '8080'
- ToPort: '8080'
- SourceSecurityGroupId: !Ref 'SolaceInternalSecurityGroupMember'
+ FromPort: 8080
+ ToPort: 8080
+ SourceSecurityGroupId: !Ref 'BrokerMemberNodesSecurityGroup'
- IpProtocol: tcp
- FromPort: '1943'
- ToPort: '1943'
- SourceSecurityGroupId: !Ref 'SolaceInternalSecurityGroupMember'
+ FromPort: 1943
+ ToPort: 1943
+ SourceSecurityGroupId: !Ref 'BrokerMemberNodesSecurityGroup'
- IpProtocol: tcp
- FromPort: '5550'
- ToPort: '5550'
- SourceSecurityGroupId: !Ref 'SolaceInternalSecurityGroupMember'
+ FromPort: 5550
+ ToPort: 5550
+ SourceSecurityGroupId: !Ref 'BrokerMemberNodesSecurityGroup'
RemoteMgmtSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
@@ -523,12 +435,12 @@ Resources:
- !If
- UsePrivateSubnetsCondition
- IpProtocol: tcp
- FromPort: '22'
- ToPort: '22'
+ FromPort: 22
+ ToPort: 22
SourceSecurityGroupId: !Ref 'SSHSecurityGroupID'
- IpProtocol: tcp
- FromPort: '22'
- ToPort: '22'
+ FromPort: 22
+ ToPort: 22
CidrIp: !Ref 'RemoteAccessCIDR'
EventBrokerSecurityGroup:
Type: AWS::EC2::SecurityGroup
@@ -537,52 +449,52 @@ Resources:
GroupDescription: Event Broker Security Group
SecurityGroupIngress:
- IpProtocol: tcp
- FromPort: '5550'
- ToPort: '5550'
+ FromPort: 5550
+ ToPort: 5550
CidrIp: !Ref 'RemoteAccessCIDR'
- IpProtocol: tcp
- FromPort: '55555'
- ToPort: '55555'
+ FromPort: 55555
+ ToPort: 55555
CidrIp: !Ref 'RemoteAccessCIDR'
- IpProtocol: tcp
- FromPort: '55003'
- ToPort: '55003'
+ FromPort: 55003
+ ToPort: 55003
CidrIp: !Ref 'RemoteAccessCIDR'
- IpProtocol: tcp
- FromPort: '55443'
- ToPort: '55443'
+ FromPort: 55443
+ ToPort: 55443
CidrIp: !Ref 'RemoteAccessCIDR'
- IpProtocol: tcp
- FromPort: '1443'
- ToPort: '1443'
+ FromPort: 1443
+ ToPort: 1443
CidrIp: !Ref 'RemoteAccessCIDR'
- IpProtocol: tcp
- FromPort: '8000'
- ToPort: '8000'
+ FromPort: 8000
+ ToPort: 8000
CidrIp: !Ref 'RemoteAccessCIDR'
- IpProtocol: tcp
- FromPort: '5672'
- ToPort: '5672'
+ FromPort: 5672
+ ToPort: 5672
CidrIp: !Ref 'RemoteAccessCIDR'
- IpProtocol: tcp
- FromPort: '9000'
- ToPort: '9000'
+ FromPort: 9000
+ ToPort: 9000
CidrIp: !Ref 'RemoteAccessCIDR'
- IpProtocol: tcp
- FromPort: '1883'
- ToPort: '1883'
+ FromPort: 1883
+ ToPort: 1883
CidrIp: !Ref 'RemoteAccessCIDR'
- IpProtocol: tcp
- FromPort: '8008'
- ToPort: '8008'
+ FromPort: 8008
+ ToPort: 8008
CidrIp: !Ref 'RemoteAccessCIDR'
- IpProtocol: tcp
- FromPort: '8080'
- ToPort: '8080'
+ FromPort: 8080
+ ToPort: 8080
CidrIp: !Ref 'RemoteAccessCIDR'
- IpProtocol: tcp
- FromPort: '1943'
- ToPort: '1943'
+ FromPort: 1943
+ ToPort: 1943
CidrIp: !Ref 'RemoteAccessCIDR'
ClusterInfoHandle:
Type: AWS::CloudFormation::WaitConditionHandle
@@ -596,7 +508,7 @@ Resources:
Properties:
Handle: !Ref 'ClusterInfoHandle'
Timeout: '600'
- Count: '1'
+ Count: 1
ELB:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
DependsOn:
@@ -617,7 +529,7 @@ Resources:
Protocol: TCP
VpcId: !Ref 'VPCID'
HealthCheckPath: '/health-check/guaranteed-active'
- HealthCheckPort: 5550
+ HealthCheckPort: '5550'
HealthCheckProtocol: 'HTTP'
Targets:
- Id: !GetAtt 'EventBrokerPrimaryStack.Outputs.EC2ID'
@@ -634,7 +546,7 @@ Resources:
Protocol: TCP
VpcId: !Ref 'VPCID'
HealthCheckPath: '/health-check/guaranteed-active'
- HealthCheckPort: 5550
+ HealthCheckPort: '5550'
HealthCheckProtocol: 'HTTP'
Targets:
- Id: !GetAtt 'EventBrokerPrimaryStack.Outputs.EC2ID'
@@ -651,7 +563,7 @@ Resources:
Protocol: TCP
VpcId: !Ref 'VPCID'
HealthCheckPath: '/health-check/guaranteed-active'
- HealthCheckPort: 5550
+ HealthCheckPort: '5550'
HealthCheckProtocol: 'HTTP'
Targets:
- Id: !GetAtt 'EventBrokerPrimaryStack.Outputs.EC2ID'
@@ -668,7 +580,7 @@ Resources:
Protocol: TCP
VpcId: !Ref 'VPCID'
HealthCheckPath: '/health-check/guaranteed-active'
- HealthCheckPort: 5550
+ HealthCheckPort: '5550'
HealthCheckProtocol: 'HTTP'
Targets:
- Id: !GetAtt 'EventBrokerPrimaryStack.Outputs.EC2ID'
@@ -685,7 +597,7 @@ Resources:
Protocol: TCP
VpcId: !Ref 'VPCID'
HealthCheckPath: '/health-check/guaranteed-active'
- HealthCheckPort: 5550
+ HealthCheckPort: '5550'
HealthCheckProtocol: 'HTTP'
Targets:
- Id: !GetAtt 'EventBrokerPrimaryStack.Outputs.EC2ID'
@@ -702,7 +614,7 @@ Resources:
Protocol: TCP
VpcId: !Ref 'VPCID'
HealthCheckPath: '/health-check/guaranteed-active'
- HealthCheckPort: 5550
+ HealthCheckPort: '5550'
HealthCheckProtocol: 'HTTP'
Targets:
- Id: !GetAtt 'EventBrokerPrimaryStack.Outputs.EC2ID'
@@ -719,7 +631,7 @@ Resources:
Protocol: TCP
VpcId: !Ref 'VPCID'
HealthCheckPath: '/health-check/guaranteed-active'
- HealthCheckPort: 5550
+ HealthCheckPort: '5550'
HealthCheckProtocol: 'HTTP'
Targets:
- Id: !GetAtt 'EventBrokerPrimaryStack.Outputs.EC2ID'
@@ -736,7 +648,7 @@ Resources:
Protocol: TCP
VpcId: !Ref 'VPCID'
HealthCheckPath: '/health-check/guaranteed-active'
- HealthCheckPort: 5550
+ HealthCheckPort: '5550'
HealthCheckProtocol: 'HTTP'
Targets:
- Id: !GetAtt 'EventBrokerPrimaryStack.Outputs.EC2ID'
@@ -753,7 +665,7 @@ Resources:
Protocol: TCP
VpcId: !Ref 'VPCID'
HealthCheckPath: '/health-check/guaranteed-active'
- HealthCheckPort: 5550
+ HealthCheckPort: '5550'
HealthCheckProtocol: 'HTTP'
Targets:
- Id: !GetAtt 'EventBrokerPrimaryStack.Outputs.EC2ID'
@@ -770,7 +682,7 @@ Resources:
Protocol: TCP
VpcId: !Ref 'VPCID'
HealthCheckPath: '/health-check/guaranteed-active'
- HealthCheckPort: 5550
+ HealthCheckPort: '5550'
HealthCheckProtocol: 'HTTP'
Targets:
- Id: !GetAtt 'EventBrokerPrimaryStack.Outputs.EC2ID'
@@ -787,7 +699,7 @@ Resources:
Protocol: TCP
VpcId: !Ref 'VPCID'
HealthCheckPath: '/health-check/guaranteed-active'
- HealthCheckPort: 5550
+ HealthCheckPort: '5550'
HealthCheckProtocol: 'HTTP'
Targets:
- Id: !GetAtt 'EventBrokerPrimaryStack.Outputs.EC2ID'
@@ -796,133 +708,122 @@ Resources:
Port: 1943
Port55555NetworkLoadBalancerListener:
Type: AWS::ElasticLoadBalancingV2::Listener
- DependsOn:
- - ELB
Condition: UsePrivateSubnetsCondition
Properties:
DefaultActions:
- Type: forward
TargetGroupArn: !Ref 'Port55555NetworkLoadBalancerTargetGroup'
LoadBalancerArn: !Ref 'ELB'
- Port: '55555'
+ Port: 55555
Protocol: TCP
Port55003NetworkLoadBalancerListener:
Type: AWS::ElasticLoadBalancingV2::Listener
- DependsOn:
- - ELB
Condition: UsePrivateSubnetsCondition
Properties:
DefaultActions:
- Type: forward
TargetGroupArn: !Ref 'Port55003NetworkLoadBalancerTargetGroup'
LoadBalancerArn: !Ref 'ELB'
- Port: '55003'
+ Port: 55003
Protocol: TCP
Port55443NetworkLoadBalancerListener:
Type: AWS::ElasticLoadBalancingV2::Listener
- DependsOn:
- - ELB
Condition: UsePrivateSubnetsCondition
Properties:
DefaultActions:
- Type: forward
TargetGroupArn: !Ref 'Port55443NetworkLoadBalancerTargetGroup'
LoadBalancerArn: !Ref 'ELB'
- Port: '55443'
+ Port: 55443
Protocol: TCP
Port1443NetworkLoadBalancerListener:
Type: AWS::ElasticLoadBalancingV2::Listener
- DependsOn:
- - ELB
Condition: UsePrivateSubnetsCondition
Properties:
DefaultActions:
- Type: forward
TargetGroupArn: !Ref 'Port1443NetworkLoadBalancerTargetGroup'
LoadBalancerArn: !Ref 'ELB'
- Port: '1443'
+ Port: 1443
Protocol: TCP
Port8000NetworkLoadBalancerListener:
Type: AWS::ElasticLoadBalancingV2::Listener
- DependsOn:
- - ELB
Condition: UsePrivateSubnetsCondition
Properties:
DefaultActions:
- Type: forward
TargetGroupArn: !Ref 'Port8000NetworkLoadBalancerTargetGroup'
LoadBalancerArn: !Ref 'ELB'
- Port: '8000'
+ Port: 8000
Protocol: TCP
Port5672NetworkLoadBalancerListener:
Type: AWS::ElasticLoadBalancingV2::Listener
- DependsOn:
- - ELB
Condition: UsePrivateSubnetsCondition
Properties:
DefaultActions:
- Type: forward
TargetGroupArn: !Ref 'Port5672NetworkLoadBalancerTargetGroup'
LoadBalancerArn: !Ref 'ELB'
- Port: '5672'
+ Port: 5672
Protocol: TCP
Port9000NetworkLoadBalancerListener:
Type: AWS::ElasticLoadBalancingV2::Listener
- DependsOn:
- - ELB
Condition: UsePrivateSubnetsCondition
Properties:
DefaultActions:
- Type: forward
TargetGroupArn: !Ref 'Port9000NetworkLoadBalancerTargetGroup'
LoadBalancerArn: !Ref 'ELB'
- Port: '9000'
+ Port: 9000
Protocol: TCP
Port1883NetworkLoadBalancerListener:
Type: AWS::ElasticLoadBalancingV2::Listener
- DependsOn:
- - ELB
Condition: UsePrivateSubnetsCondition
Properties:
DefaultActions:
- Type: forward
TargetGroupArn: !Ref 'Port1883NetworkLoadBalancerTargetGroup'
LoadBalancerArn: !Ref 'ELB'
- Port: '1883'
+ Port: 1883
Protocol: TCP
Port8008NetworkLoadBalancerListener:
Type: AWS::ElasticLoadBalancingV2::Listener
- DependsOn:
- - ELB
Condition: UsePrivateSubnetsCondition
Properties:
DefaultActions:
- Type: forward
TargetGroupArn: !Ref 'Port8008NetworkLoadBalancerTargetGroup'
LoadBalancerArn: !Ref 'ELB'
- Port: '8008'
+ Port: 8008
Protocol: TCP
Port8080NetworkLoadBalancerListener:
Type: AWS::ElasticLoadBalancingV2::Listener
- DependsOn:
- - ELB
Condition: UsePrivateSubnetsCondition
Properties:
DefaultActions:
- Type: forward
TargetGroupArn: !Ref 'Port8080NetworkLoadBalancerTargetGroup'
LoadBalancerArn: !Ref 'ELB'
- Port: '8080'
+ Port: 8080
Protocol: TCP
Port1943NetworkLoadBalancerListener:
Type: AWS::ElasticLoadBalancingV2::Listener
- DependsOn:
- - ELB
Condition: UsePrivateSubnetsCondition
Properties:
DefaultActions:
- Type: forward
TargetGroupArn: !Ref 'Port1943NetworkLoadBalancerTargetGroup'
LoadBalancerArn: !Ref 'ELB'
- Port: '1943'
+ Port: 1943
Protocol: TCP
+Outputs:
+ BrokerMemberNodesSecurityGroup:
+ Value: !Ref BrokerMemberNodesSecurityGroup
+ Description: Internal closed Security Group with only broker nodes as members
+ Export:
+ Name: !Sub '${AWS::StackName}-BrokerMemberNodesSecurityGroup'
+ LoadBalancerDNS:
+ Value: !If [UsePrivateSubnetsCondition, !GetAtt ELB.DNSName, 'No LB available, access EC2s through public addresses']
+ Description: The DNS name for the load balancer for external access
+ Export:
+ Name: !Sub '${AWS::StackName}-LoadBalancerDNS'