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

XDOCKER-51: Expose configuration options to configure an XWiki cluster #24

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 6 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
72 changes: 72 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,76 @@ secrets:
name: xwiki-db-root-password
```

## Configuring clustering

Read about [setting communication channels](https://www.xwiki.org/xwiki/bin/view/Documentation/AdminGuide/Clustering/).

#### Docker Compose example

```yaml
version: '2'
networks:
bridge:
driver: bridge
services:
web:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Idea: use web1 since there's web2 below.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

okay I would update that

build: .
container_name: xwiki-postgres-tomcat-web
depends_on:
- db
ports:
- "8080:8080"
environment:
- XWIKI_VERSION=${XWIKI_VERSION}
- DB_USER=${DB_USER}
- DB_PASSWORD=${DB_PASSWORD}
- DB_DATABASE=${DB_DATABASE}
- DB_HOST=xwiki-postgres-db
- CLUSTER=true
- CLUSTER_CHANNEL=udp
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if we shouldn't prefix all XWiki-related env properties with "XWIKI", WDYT?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does XWIKI-related include variable for DB and JGroups ?
like CLUSTER above?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CLUSTER and CLUSTER_CHANNEL are XWiki properties, not jgroups one. So I would prefix with XWiki.

Now just checked and I see that we recently introduced INDEX_HOST and INDEX_PORT for solr, see
https://github.com/xwiki-contrib/docker-xwiki/blob/4ebe570a79aeed8eabf7a8b6b834a179efc4b8b1/template/xwiki/docker-entrypoint.sh#L126 and they were not prefixed with XWiki.

New idea: why not use the same property name than in the xwiki config file? That could make it simpler maybe. The properties are:

  • observation.remote.enabled
  • observation.remote.channels

This would mean also deprecating INDEX_HOST and INDEX_PORT and instead introduce a solr.remote.url property (see https://github.com/xwiki-contrib/docker-xwiki/blob/4ebe570a79aeed8eabf7a8b6b834a179efc4b8b1/template/xwiki/docker-entrypoint.sh#L149).

In this manner, we would have a good strategy for any future properties that we need to add.

WDYT?

Also, we could it more generically so that the user would be able to pass any property from xwiki.cfg or xwiki.properties using docker run -e <property name> and the entry point script would set them in xwiki.cfg or xwiki.properties. To know in which file to add, we could search the file to see if it contains the property name.

WDYT?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using the same property name seems good.

I think for more generic property user should bind-mount it's property.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think for more generic property user should bind-mount it's property.

Actually I forgot that we already expose the properties files in the permanent directory so that's taken care of already. Well, except for the same reason as you're doing this PR, i.e. to be able to control it from a compose file and avoid using 2 lines of sed....

So IMO we should still implement the generic mechanism.

WDYT?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

okay we can do that, but in bash env variable naming we cannot have dot(.).
So solr.remote.url cannot be set as a variable name in bash
https://unix.stackexchange.com/questions/93532/exporting-a-variable-with-dot-in-it

So for generic mechanisim, we need a naming convention like replacing dot with dash, but they have also issues if some properties contain - in it's name

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, not easy. So we should probaby drop my idea and continue with what you did, i.e. CLUSTER and CLUSTER_CHANNEL. And for other cases, then the caller will simply need to modify the xwiki configuration files from the permanent directory.

Thanks for the discussion :)

volumes:
- xwiki-data-b:/usr/local/xwiki
networks:
- bridge
web2:
build: .
container_name: xwiki-postgres-tomcat-web2
depends_on:
- db
ports:
- "8081:8080"
environment:
- XWIKI_VERSION=${XWIKI_VERSION}
- DB_USER=${DB_USER}
- DB_PASSWORD=${DB_PASSWORD}
- DB_DATABASE=${DB_DATABASE}
- DB_HOST=xwiki-postgres-db
- CLUSTER=true
- CLUSTER_CHANNEL=udp
volumes:
- xwiki-data-b:/usr/local/xwiki
networks:
- bridge
db:
image: "postgres:9.5-alpine"
container_name: xwiki-postgres-db
volumes:
- postgres-data-b:/var/lib/postgresql/data
environment:
- POSTGRES_ROOT_PASSWORD=${POSTGRES_ROOT_PASSWORD}
- POSTGRES_PASSWORD=${DB_PASSWORD}
- POSTGRES_USER=${DB_USER}
- POSTGRES_DB=${DB_DATABASE}
- POSTGRES_INITDB_ARGS="--encoding=UTF8"
networks:
- bridge
volumes:
postgres-data-b: {}
xwiki-data-b: {}

```


## Using an external Solr service

From the [XWiki Solr Search API documentation](https://extensions.xwiki.org/xwiki/bin/view/Extension/Solr%20Search%20API):
Expand Down Expand Up @@ -516,6 +586,8 @@ The first time you create a container out of the xwiki image, a shell script (`/
- `DB_HOST`: The name of the host (or docker container) containing the database. Default is "db".
- `INDEX_HOST`: The hostname of an externally configured Solr instance. Defaults to "localhost", and configures an embedded Solr instance.
- `INDEX_PORT`: The port used by an externally configured Solr instance. Defaults to 8983.
- `CLUSTER`: Set it to "true" to enable clustering.
- `CLUSTER_CHANNEL`: The JGroups channel name.
ASHISH932 marked this conversation as resolved.
Show resolved Hide resolved

In order to support [Docker secrets](https://docs.docker.com/engine/swarm/secrets/), these configuration values can also be given to the container as files containing that value.

Expand Down
7 changes: 7 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,13 @@ task generate() {
expand(tokens[version])
filteringCharset = 'UTF-8'
}
// Copy JGroups files
copy {
from 'template'
into "${version}/${variant}"
include "jgroups/*"
filteringCharset = 'UTF-8'
}
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions template/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ COPY tomcat/setenv.sh /usr/local/tomcat/bin/
# Setup the XWiki Hibernate configuration
COPY xwiki/hibernate.cfg.xml /usr/local/tomcat/webapps/ROOT/WEB-INF/hibernate.cfg.xml

# Configure JGroups.
COPY jgroups/* /usr/local/tomcat/webapps/ROOT/WEB-INF/observation/remote/jgroups

# Set a specific distribution id in XWiki for this docker packaging.
RUN sed -i \'s/<id>org.xwiki.platform:xwiki-platform-distribution-war/<id>org.xwiki.platform:xwiki-platform-distribution-docker/\' \\
/usr/local/tomcat/webapps/ROOT/META-INF/extension.xed
Expand Down
101 changes: 101 additions & 0 deletions template/jgroups/udp.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
<!--
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-->

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be good to add license headers.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know about license headers much? Should it contain xwiki license headers? As I have taken the file from JGroups ->
https://github.com/belaban/JGroups/blob/master/conf/udp.xml

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm I thought I remembered that we were providing this xml file somewhere on xwiki.org but cannot find it. In any case we need a license header for all files we provide. We have 2 solutions:

  1. extract the default config file from the jgroups jar at execution time (on first run for example). This allows to be up to date and reduce maintenance cost.
  2. provide the file as you did and put our own license headers at the top. See https://dev.xwiki.org/xwiki/bin/view/Community/DevelopmentPractices#HForXMLfiles

I prefer option 1.

@tmortagne any opinion on this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This configuration file is not exactly the same with the jgroups jar. I have changed it for docker as documented in https://github.com/belaban/jgroups-docker. So I think option 2 would be better

<!--
Default stack using IP multicasting. It is similar to the "udp"
stack in stacks.xml, but doesn't use streaming state transfer and flushing
author: Bela Ban
-->

<config xmlns="urn:org:jgroups"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:org:jgroups http://www.jgroups.org/schema/JGroups-3.3.xsd">
<UDP
bind_addr="match-interface:eth0,match-interface:en0,site_local,loopback"

mcast_port="${jgroups.udp.mcast_port:45588}"
tos="8"
ucast_recv_buf_size="5M"
ucast_send_buf_size="640K"
mcast_recv_buf_size="5M"
mcast_send_buf_size="640K"
loopback="true"
max_bundle_size="64K"
max_bundle_timeout="30"
ip_ttl="${jgroups.udp.ip_ttl:8}"
enable_diagnostics="true"
thread_naming_pattern="cl"

timer_type="new3"
timer.min_threads="4"
timer.max_threads="10"
timer.keep_alive_time="3000"
timer.queue_max_size="500"

thread_pool.enabled="true"
thread_pool.min_threads="2"
thread_pool.max_threads="8"
thread_pool.keep_alive_time="5000"
thread_pool.queue_enabled="true"
thread_pool.queue_max_size="10000"
thread_pool.rejection_policy="discard"

oob_thread_pool.enabled="true"
oob_thread_pool.min_threads="1"
oob_thread_pool.max_threads="8"
oob_thread_pool.keep_alive_time="5000"
oob_thread_pool.queue_enabled="false"
oob_thread_pool.queue_max_size="100"
oob_thread_pool.rejection_policy="discard"/>

<PING timeout="2000"
num_initial_members="20"/>
<MERGE2 max_interval="30000"
min_interval="10000"/>
<FD_SOCK/>
<FD_ALL/>
<VERIFY_SUSPECT timeout="1500" />
<BARRIER />
<pbcast.NAKACK2 xmit_interval="500"
xmit_table_num_rows="100"
xmit_table_msgs_per_row="2000"
xmit_table_max_compaction_time="30000"
max_msg_batch_size="500"
use_mcast_xmit="false"
discard_delivered_msgs="true"/>
<UNICAST3 xmit_interval="500"
xmit_table_num_rows="100"
xmit_table_msgs_per_row="2000"
xmit_table_max_compaction_time="60000"
conn_expiry_timeout="0"
max_msg_batch_size="500"/>
<pbcast.STABLE stability_delay="1000" desired_avg_gossip="50000"
max_bytes="4M"/>
<pbcast.GMS print_local_addr="true" join_timeout="3000"
view_bundling="true"/>
<UFC max_credits="2M"
min_threshold="0.4"/>
<MFC max_credits="2M"
min_threshold="0.4"/>
<FRAG2 frag_size="60K" />
<RSVP resend_interval="2000" timeout="10000"/>
<pbcast.STATE_TRANSFER />
<!-- pbcast.FLUSH /-->
</config>
15 changes: 15 additions & 0 deletions template/xwiki/docker-entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,17 @@ function restoreConfigurationFile() {
fi
}

function enableClustering() {
echo 'Setting clustering...'
xwiki_set_properties 'observation.remote.enabled' 'true'
if [ \$CLUSTER_CHANNEL ]; then
echo "Setting cluster channel to \$CLUSTER_CHANNEL"
xwiki_set_properties 'observation.remote.channels' "\$CLUSTER_CHANNEL"
else
xwiki_set_properties 'observation.remote.channels' 'udp'
fi
}

function configure() {
echo 'Configuring XWiki...'

Expand Down Expand Up @@ -138,6 +149,10 @@ function configure() {
xwiki_set_properties 'solr.remote.url' "http://\$INDEX_HOST:\$INDEX_PORT/solr/xwiki"
fi

if [ \$CLUSTER ]; then
enableClustering
fi

# If the files already exist then copy them to the XWiki's WEB-INF directory. Otherwise copy the default config
# files to the permanent directory so that they can be easily modified by the user. They'll be synced at the next
# start.
Expand Down