Basic setup of a Multi Node Apache Kafka/Zookeeper Cluster

Prerequesites

Install three nodes with CentOS 7 with at least 20GB Disk, 2 GB RAM and two CPU Cores.

Install JDK

yum install -y java-1.8.0-openjdkl java-1.8.0-openjdk-devel net-tools

Set JAVA_HOME in ~/.bashrc

# Set Java-Home
export JAVA_HOME="/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.151-5.b12.el7_4.x86_64/jre"
export PATH=$JAVA_HOME/bin:$PATH

Disable SELinux, Firewall and IPv6

systemctl disable firewalld
systemctl stop firewalld

echo "net.ipv6.conf.all.disable_ipv6 = 1" >> /etc/sysctl.conf

[root@kafka3 ~]# cat /etc/selinux/config | grep "^SELINUX="
SELINUX=permissive

Reboot Server

Installing Kafka

Download Kafka and unpack it under /opt

https://www.apache.org/dyn/closer.cgi?path=/kafka/0.11.0.2/kafka_2.11-0.11.0.2.tgz

tar zxvf kafka_2.11-0.11.0.2.tgz

Starting Zookeeper

On each node create a zookeeper directory and a file ‚myid‘ with a unique number:

mkdir /zookeeper
echo '1' > /zookeeper/myid

On all three Server go to Kafka home folder /opt/kafka_2.11-0.11.0.1 and setup zookeeper like this

vi config/zookeeper.properties

# the directory where the snapshot is stored.
dataDir=/zookeeper
# the port at which the clients will connect
clientPort=2181
clientPortAddress=192.168.2.56
# disable the per-ip limit on the number of connections since this is a non-production config
maxClientCnxns=0

# The number of milliseconds of each tick
tickTime=2000
  
# The number of ticks that the initial synchronization phase can take
initLimit=10
  
# The number of ticks that can pass between 
# sending a request and getting an acknowledgement
syncLimit=5
 
# zoo servers
server.1=kafka1.fritz.box:2888:3888
server.2=kafka2.fritz.box:2888:3888
server.3=kafka3.fritz.box:2888:3888
#add here more servers if you want

Start Zookeeper on all three servers

./bin/zookeeper-server-start.sh -daemon config/zookeeper.properties

Change the Kafka server.properties on all three servers (set a unique broker id on each server)

vi config/server.properties

# The id of the broker. This must be set to a unique integer for each broker.
broker.id=2

#     listeners = PLAINTEXT://your.host.name:9092
listeners=PLAINTEXT://:9093

# A comma seperated list of directories under which to store log files
log.dirs=/tmp/kafka-logs-2

# Zookeeper connection string (see zookeeper docs for details).
# This is a comma separated host:port pairs, each corresponding to a zk
# server. e.g. "127.0.0.1:3000,127.0.0.1:3001,127.0.0.1:3002".
# You can also append an optional chroot string to the urls to specify the
# root directory for all kafka znodes.
zookeeper.connect=kafka1.fritz.box:2181,kafka2.fritz.box:2181,kafka3.fritz.box

Start Kafka on all three nodes:

./bin/kafka-server-start.sh -daemon config/server.properties

Verify kafka and zookeper are running:

jps
4150 Jps
2365 QuorumPeerMain
1743 Kafka

Verify also all brokers are registered to zookeeper:

# ./bin/zookeeper-shell.sh kafka1:2181 ls /brokers/ids
Connecting to kafka1:2181

WATCHER::

WatchedEvent state:SyncConnected type:None path:null
[1, 2, 3]

Create a example Topic with three partitions and replicationfactor 3

# ./bin/kafka-topics.sh --create --zookeeper kafka1:2181 --topic example-topic --partitions 3 --replication-factor 3
Created topic "example-topic".

# ./bin/kafka-topics.sh --list --zookeeper kafka1:2181 --topic example-topic
example-topic

# ./bin/kafka-topics.sh --describe --zookeeper kafka1:2181 --topic example-topic
Topic:example-topic	PartitionCount:3	ReplicationFactor:3	Configs:
	Topic: example-topic	Partition: 0	Leader: 2	Replicas: 2,3,1	Isr: 2,3,1
	Topic: example-topic	Partition: 1	Leader: 3	Replicas: 3,1,2	Isr: 3,2,1
	Topic: example-topic	Partition: 2	Leader: 1	Replicas: 1,2,3	Isr: 1,2,3

Test the Topic

Start a Producer on one node:

# ./bin/kafka-console-producer.sh --broker-list kafka1:9093,kafka2:9093,kafka3:9093 --topic example-topic

Start also a Consumer on a different node:

# ./bin/kafka-console-consumer.sh --zookeeper kafka1:2181 --topic example-topic --from-beginning

Write some text in the producer console. You should then see the Text on the Consumer Console.

Stop a node and write again some messages in the producer console to verify the high availability is working.

 

 

 

Migration Owncloud 9.1 nach Nextcloud 11.0 mit CentOS 7

Über die Vorteile von Nextcloud gegenüber Owncloud wurde ja im Netz schon viel geschrieben. Das hat mich letztendlich auch dazu bewogen mit meiner privaten Home-Cloud umzusteigen.

Mir geht es in diesem Artikel hauptsächlich um die Beschreibung der Migrationsschritte. Wer mehr über Owncloud bzw. Nextcloud wissen möchte, sollte einfach googlen.

Ich wollte bewusst kein sogenanntes „In-Place-Upgrade“ machen, also die neue Installation über die alte „drüberbügeln“, sondern parallel eine komplett neue Serverinstanz mit Nextcloud 11.0 stable hochziehen. So kann ich bequem erst den Server vorbereiten und kann auch gleich veraltete Software wie z.B. php5.4 gegen neue Stände ablösen, ohne den aktiven Owncloud-Server zu beeinflussen.

Owncloud läuft bei mir als VM unter KVM auf einem Fedora25 Server. Das Datenverzeichnis (/data) wird per NFS vom Hostsystem an die VM durchgereicht. Das hat den Vorteil, dass ich bei der Migration den NFS-Export einfach nur als Mountpoint in der neuen VM einhängen kann und keine Daten umkopieren muss. Außerdem bleibt damit die Nextcloud VM relativ schlank und ich kann zusätzlich die Daten bequem vom Hostsystem aus sichern.

Für die Nextcloud VM unter KVM hab ich folgendes Setup gewählt:

  • KVM Virtual Disk (qcow2) dynamisch wachsend mit 25 GB (LVM: / ~10GB, /var ~10GB)
  • CentOS 7.3.1611 Core (Minimal Installation)
  • PHP 7.1.4, Apache httpd 2.4, MariaDB (mysql) 5.5
  • Nextcloud 11.0.2 manual Installation (tar.bz)

CentOS habe ich wegen der sehr konservativen Update Politik gewählt, um eine stabile Basis für meinen Server zu haben. Leider bringt CentOS nur ein veraltetes PHP 5.6 mit. Da die Empfehlung für Nextcloud aber PHP 7.x ist, habe ich ein zusätzliches externes Repository angebunden. Der Apache Server und MariaDB werden dann aber aus dem CentOS Standard Repo installiert. Zwar stellt CentOS über das Epel-Repo auch eigene Nextcloud Pakete zur Verfügung, aber diese sind ziemlich veraltet, deswegen habe ich mich für die manuelle Installation von der Nextcloud.com Webseite entschieden.

Los geht’s!

Nach der Minimal Installation von CentOS 7.3 ziehen wir uns noch die Voraussetzungen für Nextcloud.

Zuerst die zusätzlich benötigten Repositories:

rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY*
yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
yum install http://rpms.remirepo.net/enterprise/remi-release-7.rpm
yum install yum-utils
yum update

Anschließend installieren wir MariaDB und den Apache Webserver:

yum -y install mariadb-server mariadb
systemctl start mariadb.service
systemctl enable mariadb.service
mysql_secure_installation

yum -y install httpd
systemctl start httpd.service
systemctl enable httpd.service
firewall-cmd --permanent --zone=public --add-service=http
firewall-cmd --permanent --zone=public --add-service=https
firewall-cmd --reload

Mit „mysql_secure_installation“ wird die Datenbank-Installation abgesichert. Hier kann man alle Defaultwerte übernehmen. Wichtig: Zugriff nur von Localhost zulassen!

Anschließend wird PHP 7.1 aus dem remi-repo installiert was wir mit yum-config-manager entsprechend als Standard aktivieren.

yum-config-manager --enable remi-php71
yum install php
yum install php-gd
yum install php-json
yum install php-mysql
yum install php-curl
yum install php-mbstring
yum install php-intl
yum install php-mcrypt
yum install php-imagick

yum install php-xml php-pecl-zip php-bcmath php-dba php-process php-soap

Auf der Nextcloud Webseite werden leider nur die als Voraussetzung benötigten Pakete für Ubuntu beschrieben. Ich hoffe also, dass ich bei meiner Aufstellung nichts vergessen habe.

Anschließend machen wir uns daran, eine neue, leere Datenbank für Nextcloud unter MariaDB anzulegen:

[root@nextcloud ~]# mysql -u root -p
Enter password:
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 12
Server version: 5.5.52-MariaDB MariaDB Server

Copyright (c) 2000, 2016, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> CREATE DATABASE nextcloud;
Query OK, 1 row affected (0.00 sec)

MariaDB [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| nextcloud          |
| performance_schema |
MariaDB [(none)]> grant all privileges on nextcloud.* to ncuser@'%' identified by 'ncuser';
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> grant all privileges on nextcloud.* to ncuser@'localhost' identified by 'ncuser';
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> quit

Datenbankname: nextcloud
DB-User: ncuser
DB-Passwort: ncuser

Nextcloud Installation

Jetzt laden wir uns das Softwarepaket von der Nextcloud Webseite herunter und prüfen die Authentizität der gepackten Datei. Dann entpacken wir es und kopieren das entpackte Verzeichnis anschließend in den Web-Root Ordner (/var/www).
Siehe dazu auch die offizielle Installationsanleitung auf der Nextcloud Webseite: https://docs.nextcloud.com/server/11/admin_manual/installation/source_installation.html

yum install wget
wget https://download.nextcloud.com/server/releases/nextcloud-11.0.2.tar.bz2
wget https://download.nextcloud.com/server/releases/nextcloud-11.0.2.tar.bz2.md5
md5sum -c nextcloud-11.0.2.tar.bz2.md5 < nextcloud-11.0.2.tar.bz2
wget https://download.nextcloud.com/server/releases/nextcloud-11.0.2.tar.bz2.asc
wget https://nextcloud.com/nextcloud.asc
gpg --import nextcloud.asc
gpg --verify nextcloud-11.0.2.tar.bz2.asc nextcloud-11.0.2.tar.bz2
yum install bzip2
tar -xjf nextcloud-11.0.2.tar.bz2
cp -r nextcloud /var/www/
chown -R apache:apache /var/www/nextcloud

Apache für Nextcloud vorbereiten und HTTPS aktivieren

Mit openssl erstellen wir uns ein „Self-Signed-Certificate“, was für den Hausgebrauch durchaus ausreichend ist.

cd /etc/pki/tls/certs
openssl req -x509 -nodes -days 10000 -newkey rsa:2048 -keyout nextcloud.fritz.box.key -out nextcloud.fritz.box.crt

Anschließend konfigurieren wir das Zertifikat und den private Key in der Datei /etc/httpd/conf.d/ssl.conf von Apache. In diesem Zusammenhang können wir auch gleich die Strict-Transport-Security für den Header aktivieren, so wie es von Nextcloud empfohlen wird.

##
## SSL Virtual Host Context
##

<VirtualHost _default_:443>

  ServerName nextcloud.fritz.box
    <IfModule mod_headers.c>
      Header always set Strict-Transport-Security "max-age=15552000; includeSubDomains; preload"
    </IfModule>

/// AUSZUG ///

#   Server Certificate:
# Point SSLCertificateFile at a PEM encoded certificate.  If
# the certificate is encrypted, then you will be prompted for a
# pass phrase.  Note that a kill -HUP will prompt again.  A new
# certificate can be generated using the genkey(1) command.
SSLCertificateFile /etc/pki/tls/certs/nextcloud.fritz.box.crt

#   Server Private Key:
#   If the key is not combined with the certificate, use this
#   directive to point at the key file.  Keep in mind that if
#   you've both a RSA and a DSA private key you can configure
#   both in parallel (to also allow the use of DSA ciphers, etc.)
SSLCertificateKeyFile /etc/pki/tls/certs/nextcloud.fritz.box.key

Dann legen wir noch eine Apache-Definitionsdatei für unsere Nextcloud-Instanz unter  /etc/httpd/conf.d/nextcloud.conf an

Alias /nextcloud "/var/www/nextcloud/"

<Directory /var/www/nextcloud/>
  Options +FollowSymlinks
  AllowOverride All

 <IfModule mod_dav.c>
  Dav off
 </IfModule>

 SetEnv HOME /var/www/nextcloud
 SetEnv HTTP_HOME /var/www/nextcloud

</Directory>

Mit systemctl restart httpd wird der Webserver neugestartet. Danach sollten wir unter der URL https://nextcloud.fritz.box/nextcloud den Setup-Wizard von Nextcloud sehen. In meinem Fall hat der Setup-Wizard gleich mal gemeckert, dass ihm der Schreibzugriff auf das config Verzeichnis fehlt, obwohl das Webverzeichnis dem User „apache“ als Owner zugewiesen war. Das liegt dann aber an SELinux, was bei CentOS7 auf „enforced“ eingestellt ist und Zugriffe blockiert, die nicht explizit über entsprechende Policies erlaubt wurden. In der offiziellen Nextcloud Installationsanleitung wird zwar erklärt, wie man die SELinux-Policies entsprechend konfiguriert. Ich hab mich aber dazu entschieden SELinux global auf „permissive“ umzustellen, unter anderem auch deshalb, weil ich ja per NFS das Data-Verzeichnis außerhalb von Webroot einbinde. Somit werden keine Zugriffe mehr blockiert, sondern nur noch protokolliert (ändern unter /etc/selinux/config – anschließend Reboot).

Owncloud/Nextcloud Datenverzeichnis per NFS einbinden

Wie schon erwähnt, stelle ich das Datenverzeichnis (/data) per NFS-Export am Hostsystem zur Verfügung. Dazu installieren wir die NFS-Utils nach: yum install nfs-utils
Den Export binde ich über die /etc/fstab folgendermaßen ein:

### Owncloud Data Verzeichnis vom Hostsystem ###
192.168.xxx.yyy:/nfs/owncloud_data/data	/var/nextcloud/data 	nfs	auto 	0 0

Am Hostsystem (NFS-Server) sieht der Export (/etc/exports) so aus:

/nfs/owncloud_data 192.168.xxx.zzz(rw,sync,no_root_squash,no_subtree_check)

Migration der Owncloud Datenbank und config.php

Jetzt ist es soweit, dass wir den alten Server Offline nehmen können, um die Datenbank auf den neuen Server zu übertragen.
Dazu versetzen wir die Owncloud Instanz in den Maintenance Mode und machen anschließend ein Datenbank Backup.

sudo -u apache php occ maintenance:mode --on

/usr/bin/mysqldump --lock-tables --log-error=dbbackup-error.log -u <owncloud_dbuser> -p<oc_dbpassword> <oc_dbname> > owncloud-sqlbkp.bak

Das occ Programm befindet sich übrigens im Owncloud Webroot-Verzeichnis (z.B. /var/www/html/owncloud). Außerdem übertragen wir die config.php vom alten Server z.B. /var/www/html/owncloud/config/config.php in das ensprechende Verzeichnis auf dem neuen Server (z.B. /var/www/nextcloud/config/config.php). Die Zugriffsrechte müssen wieder entsprechend angepasst werden: 750 apache:apache.
Auf dem neuen Server wird die config.php an die neue Umgebung entsprechend angepasst:

<?php
$CONFIG = array (
  'instanceid' => '<automatisch_generiert>',
  'passwordsalt' => '<automatisch_generiert>',
  'datadirectory' => '/var/nextcloud/data',
  'dbtype' => 'mysql',
  'version' => '9.1.4.2',
  'dbname' => 'nextcloud',
  'dbhost' => 'localhost',
  'dbtableprefix' => 'oc_',
  'dbuser' => 'ncuser',
  'dbpassword' => 'ncuser',
  'installed' => true,
  'forcessl' => true,
  'theme' => '',
  'maintenance' => false,
  'trusted_domains' => 
  array (
    0 => 'nextcloud.fritz.box',
    1 => '192.168.xxx.zzz',
  ),
  'secret' => '<automatisch_generiert>',
  'memcache.local' => '\\OC\\Memcache\\APCu',
  'mail_from_address' => 'nextcloud',
  'mail_smtpmode' => 'smtp',
  'mail_domain' => 'your.domain',
  'loglevel' => 2,
  'trashbin_retention_obligation' => 'auto, 90',
  'updatechecker' => false,
  'mail_smtpauthtype' => 'LOGIN',
  'mail_smtpauth' => 1,
  'mail_smtphost' => 'your.mailhost',
  'mail_smtpport' => '587',
  'mail_smtpsecure' => 'tls',
  'mail_smtpname' => 'yoursmtpname',
  'mail_smtppassword' => 'yoursmtppassword',

/**
 * Use this configuration parameter to specify the base URL for any URLs which
 * are generated within Nextcloud using any kind of command line tools (cron or
 * occ). The value should contain the full base URL:
 * ``https://www.example.com/nextcloud``
 */
'overwrite.cli.url' => 'https://nextcloud.fritz.box/nextcloud',

);

Die config.php Datei kann bei eurer Installation natürlich auch etwas anders aussehen.

Achtung: Die automatisch generierten Keys/Salts/IDs nicht ändern und auch die ursprüngliche Versionsnummer von Owncloud hier auch nicht anpassen (9.1.4.2). Die Version dient dem Upgrade-Wizard später dazu, ein Upgrade der Datenbank auf die neue Version durchzuführen. Das dbtableprefix belassen wir ebenfalls bei oc_, weil wir die Tabellen der importierten Datenbank nicht extra anpassen wollen.
Wir ändern aber die Angaben für die Datenbank (Name/User/Passwort) und der Pfad für das „datadirectory“ wird auf den entsprechenden NFS-Mountpoint gesetzt.

Da ich den PHP APCu Memcache unter Owncloud aktiviert hatte, installiere ich noch folgendes Paket nach, damit dieser auch auf dem Nextcloud-Server wieder funktioniert:

sudo yum install php-pecl-apcu
systemctl restart httpd

Das Datenbank Backup wird ebenfalls zum neuen Server übertragen und dort in die MariaDB importiert.

mysql -u ncuser -p nextcloud < /pfad/zum/owncloud-sqlbkp.bak

Zu guter Letzt, wird der Upgrade Wizard auf dem neuen Nextcloud Server als User ‚apache‚ ausgeführt:

sudo -u apache php occ maintenance:mode --on
sudo -u apache php occ upgrade
sudo -u apache php occ maintenance:mode --off

Wenn das alles ohne Fehler durchgelaufen ist, sollte man sich über die WebUI der Nextcloud-Instanz erfolgreich mit den bisherigen Benutzern anmelden können.

Dort nehmen wir zunächst im Admin Bereich die empfohlenen Einstellungen vor und prüfen, ob alles korrekt konfiguriert ist. Vor allem die „Security & setup warnings“ sollte man ernst nehmen und beheben (siehe dazu die offizielle Nextcloud Dokumentation).

Ich hoffe ihr seid mit dieser Anleitung genauso erfolgreich wie ich. Über Anregungen und Verbesserungsvorschläge bin ich jederzeit dankbar.