Kubernetes Cluster with Kubespray

Minikube is all well and good for developing Kubernetes pods and deployments and testing them locally. But how can you install a real Kubernetes cluster in your own data center?

Of course, this can be done the hard way or via the installation with kubeadm. Especially the first variant is very complex and error-prone.

The installation is particularly easy with kubespray. This is an Ansible-based solution that creates a Kubernetes cluster with certain predefined parameters.

As a starting point, you should have the following system:

  • At least 3 hosts on which Kubernetes is to run (3x Node with master and worker role).
  • A bastion host from which Ansible is run

The hosts can be virtual machines, of course.

To create a cluster with kubespray, proceed as follows:

Set up SSH key access from Bastion host to all nodes
Install Ansible and Git on the Bastion host
Clone the Kubespray repository
Prepare inventory files for Kubespray
Run Ansible Playbook

Set up SSH key access

To do this, an SSH keypair is first created on the Bastion host:

ssh-keygen

Here the default values can be confirmed and no password should be assigned for the key. After that the private and public key is located under ~/.ssh/id_rsa und ~/.ssh/id_rsa.pub.

Now the public key in id_rsa.pub must be distributed to all nodes. To do this, a file ~/.ssh/authorized_keys is created on each node if it does not already exist. The content from id_rsa.pub can simply be copied into it.

Afterwards, the SSH access without password, with the key from the Bastion host to all other nodes should be tested once.

Installing Ansible and Git on the Bastion Host

To install Ansible on a CentOS 7 server, the appropriate repository must be enabled.

sudo yum install centos-release-ansible-29.noarch

Ansible can then be installed.

sudo yum install ansible.noarch

Git can be installed as well.

sudo yum install git.x86_64

After that, python-pip must also be installed.

sudo yum install python3-pip

Cloning the kubespray repository

Now the Git repository of kubespray must be cloned. To do this, copy the link from the GitHub page, or execute the following directly:

git clone https://github.com/kubernetes-sigs/kubespray.git

Perpare installation

When that’s done, we navigate to the directory:

cd kubespray

After that, we need to install the prerequisites for the Ansible Kubernetes installation using kubespray.

sudo pip3 install -r requirements.txt

Then we copy the sample inventory into a new inventory, which we call „mycluster“.

cp -rfp inventory/sample inventory/mycluster

Now we create the inventory, according to our host IP addresses.

declare -a IPS=(10.90.1.11 10.90.1.12 10.90.1.13 10.90.1.14 10.90.1.15)
CONFIG_FILE=inventory/mycluster/hosts.yaml python3 contrib/inventory_builder/inventory.py ${IPS[@]}

Now we need to change one more value in the „inventory/mycluster/group_vars/k8s-cluster/k8s-cluster.yml“ if we use CentOS 7 hosts.

vi inventory/mycluster/group_vars/k8s-cluster/k8s-cluster.yml

We search for the entry „kube_proxy_mode: ipvs“ and change it to

kube_proxy_mode: iptables

Install cluster

Now we can start with the cluster installation. We run the Ansible playbook from the Bastion host.

ansible-playbook -i inventory/mycluster/hosts.yaml --become cluster.yml

After that, the playbook should run through. This can take up to 45 minutes. Depending on how many hosts are configured and how fast the hardware is.

Manage Kubernetes clusters

To be able to manage the cluster with kubectl, we have to set the config file. For this we connect to the first master, in my case „node-11“ and copy the Kubernetes config to „~/.kube/config“.

sudo cat /etc/kubernetes/admin.conf >> ~/.kube/config

After that we can manage the cluster via kubectl.

kubectl get nodes
kubectl get pod -n kube-system

Kubernetes / OpenShift Fehler „layer not known“

Heute gab es wieder einen nicht gleich nachvollziehbaren Fehler im Kubernetes Cluster. Ich habe hier einen OKD (OpenShift) Cluster 4.5 mit 3 Mastern und 2 Workern laufen.

Nachdem vermehrt Knoten nicht mehr verfügbar waren, habe ich den kompletten Cluster einmal durchgestartet. Leider hat bei einigen Knoten der initiierte Reboot sehr lang gebraucht. Daher habe ich einzelne Knoten kurzerhand per Hardreset durchgestartet.

Nachdem alle Knoten neu gestartet und im Status „Ready“ waren, konnte einer der Knoten keine Pods starten :-/

Also ging es zum Troubleshooting auf dem Node und im Cluster. Zunächst schaue ich welche Pods nicht gestartet werden können:

oc get pod --all-namespaces -o wide

Und sehe, dass alle auf dem gleichen Host nicht gestartet werden können. Also etwas genauer auf den Pod schauen:

oc describe pod -n <namespacevompod> <podname>

Und sehe hier folgenden Fehler:

Failed to create pod sandbox: rpc error: code = Unknown desc = error creating pod sandbox with name "XXXX": layer not known

Das bringt mich jetzt noch nicht viel weiter. Also gehe ich per SSH auf den Knoten. Hier schaue ich ob alle Dienste laufen

systemctl

Und sehe, dass der Dienst „nodeip-configuration.service“ failed ist. Also hier genauer nachschauen:

systemctl status nodeip-configuration.service

Und hier kommt folgende Fehlermeldung zum Vorschein:

podman[11387]: Error: error creating container storage: layer not known

Jetzt wird zumindes schon einmal klarer, welcher „layer“ hier gemeint ist. Soltle also ein storage layer sein. Also nochmal Google gefragt und einen Eintrag gefunden:

https://bugzilla.redhat.com/show_bug.cgi?id=1857224

Ok. Anscheinend hat der Knoten den Hard Reset übel genommen und es ist unter „/var/lib/containers“ nicht mehr alles sauber. Also folge ich der Empfehlung:

systemctl stop kubelet
systemctl stop crio
rm -rf /var/lib/containers/
systemctl start crio
systemctl start kubelet

Und voila, die Pods auf dem Knoten können wieder starten!

Kubernetes Cluster mit Kubespray

Hier geht es zum passenden Video Tutorial: https://youtu.be/NyHJ8k5CRVg

Minikube ist schön und gut um Kubernetes Pods und Deployments zu entwickeln und lokal zu testen. Aber wie kann man denn nun einen richtigen Kubernetes Cluster im eigenen Rechenzentrum installieren?

Das geht natürlich auf die harte Tour oder auch über die Installation mit kubeadm. Vor Allem die erste Variante ist aber sehr aufwändig und auch fehleranfällig.

Besonders leicht von der Hand geht die Installation mit kubespray. Das ist eine, auf Ansible basierende Lösung, die einen Kubernetes Cluster mit bestimmten, vorher festgelegten Parametern erstellt.

Als Ausgangssituation solltest du folgendes System haben:

  • Mindestens 3 Hosts, auf denen Kubernetes laufen soll (2x Master, 1x Worker)
  • Einen Bastion Host, von dem aus Ansible ausgeführt wird

Die Hosts können natürlich virtuelle Maschinen sein.

Um einen Cluster mit kubespray zu erstellen, gehst Du so vor:

  1. SSH Key Zugang vom Bastion Host auf alle Knoten einrichten
  2. Ansible und Git auf dem Bastion Host installieren
  3. Klonen des Kubespray Repository
  4. Vorbereiten der Inventory Dateien für Kubespray
  5. Ansible Playbook ausführen

SSH Key Zugang einrichten

Dazu wird auf dem Bastion Host zunächst ein SSH Keypair erzeugt:

ssh-keygen

Hier können die Standardwerte bestätigt werden und es sollte auch kein Kennwort für den Key vergeben werden. Danach befindet sich der private und öffentliche Schlüssel unter ~/.ssh/id_rsa und ~/.ssh/id_rsa.pub.

Nun muss der öffentliche Schlüssel in id_rsa.pub auf alle Knoten verteilt werden. Dazu wird auf jedem Knoten eine Datei ~/.ssh/authorized_keys angelegt, falls noch nicht vorhanden. Der Inhalt aus id_rsa.pub kann einfach hineinkopiert werden.

Anschließend sollte der SSH Zugang ohne Kennwort, mit dem Key vom Bastion Host auf alle anderen Knoten einmal getestet werden.

Ansible und Git auf dem Bastion Host installieren

Um Ansible auf einem CentOS 7 Server zu installieren, muss das entsprechende Repository aktiviert werden.

sudo yum install centos-release-ansible-29.noarch

Anschließend kann Ansible installiert werden.

sudo yum install ansible.noarch

Ebenso kann Git installiert werden.

sudo yum install git.x86_64

Danach muss auch python-pip installiert werden.

sudo yum install python3-pip

Klonen des kubespray Repository

Jetzt muss das Git Repository von kubespray geklont werden. Dazu den Link von der GitHub Seite kopieren, oder direkt folgendes ausführen:

git clone https://github.com/kubernetes-sigs/kubespray.git

Installation vorbereiten

Wenn das fertig ist, navigieren wir in das Directory:

cd kubespray

Danach müssen wir die Voraussetzungen für die Ansible Kubernetes Installation mit kubespray installiert werden.

sudo pip3 install -r requirements.txt

Anschließend kopieren wir das Beispiel Inventory in ein neuen Inventory, was wir „mycluster“ nennen.

cp -rfp inventory/sample inventory/mycluster

Jetzt erstellen wir das Inventory, entsprechend unserer Host IP Adressen.

declare -a IPS=(10.90.1.11 10.90.1.12 10.90.1.13 10.90.1.14 10.90.1.15)
CONFIG_FILE=inventory/mycluster/hosts.yaml python3 contrib/inventory_builder/inventory.py ${IPS[@]}

Jetzt müssen wir noch einen Wert in der „inventory/mycluster/group_vars/k8s-cluster/k8s-cluster.yml“ ändern, wenn wir CentOS 7 Hosts benutzen.

vi inventory/mycluster/group_vars/k8s-cluster/k8s-cluster.yml

Wir suchen nach dem Eintrag „kube_proxy_mode: ipvs“ und ändern diesen in

kube_proxy_mode: iptables

Cluster installieren

Jetzt kann es mit der Cluster Installation losgehen. Wir führen das Ansible Playbook vom Bastion Host aus.

ansible-playbook -i inventory/mycluster/hosts.yaml --become cluster.yml

Danach sollte das Playbook durchlaufen. Das kann durchaus bis zu 45 Minuten dauern. Je nachdem wie viele Hosts konfiguriert sind und wie schnell die Hardware ist.

Kubernetes Cluster verwalten

Damit wir den Cluster mit kubectl verwalten können, müssen wir das config file einstellen. Dazu verbinden wir uns auf den ersten master, in meinem Fall „node-11“ und kopieren die Kubernetes Config in „~/.kube/config“

sudo cat /etc/kubernetes/admin.conf >> ~/.kube/config

Danach können wir den Cluster über kubectl verwalten.

kubectl get nodes
kubectl get pod -n kube-system

Nextcloud und Collabora mit Docker

Want the english version?? Here you go

Hier zeige ich meine „alles-in-einem“ Lösung für Nextcloud und Collabora auf Docker mit Docker Compose.

Dazu gibt es ebenfalls ein Youtube Video: https://youtu.be/K6R-0l9iWBM

Was brauchen wir?

  • CentOS 7 Server (Azure, AWS, Hetzner, whatever)
  • Installiertes Docker und docker-compose
  • Domäne mit 2 zum Server zeigenden DNS A Records (admin-schule.de z.B.)
    • einen für Nextcloud „cloud.admin-schule.de“
    • einen für Collabora „office.admin-schule.de“

Vorbereitung

Logge dich auf der Server per SSH ein. Schaue danach ob Docker installiert und erreichbar ist.

docker ps

Prüfe ob „docker-compose“ installiert ist.

docker-compose version

Ein Verzeichnis „docker_nextcloud“ erstellen, oder mein Repository clonen – https://github.com/bohlrich/docker_nextcloud

Die „docker-compose.yml“ erstellen

version: '2.1'
services:

  nginx-proxy:
    image: jwilder/nginx-proxy
    restart: always
    volumes:
      - nginx-proxy-certs:/etc/nginx/certs:ro
      - nginx-proxy-vhost:/etc/nginx/vhost.d
      - /opt/docker-files/nginx-proxy/network_internal.conf:/etc/nginx/network_internal.conf
      - /opt/docker-files/nginx-proxy/uploadsize.conf:/etc/nginx/conf.d/uploadsize.conf
      - /usr/share/nginx/html
      - /var/run/docker.sock:/tmp/docker.sock:ro
    ports:
      - 80:80
      - 443:443
    labels:
      - "com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy"
    networks:
      cloud-network:

  nginx-letsencrypt:
    image: jrcs/letsencrypt-nginx-proxy-companion      
    restart: always
    volumes:
      - nginx-proxy-certs:/etc/nginx/certs:rw
      - /var/run/docker.sock:/var/run/docker.sock:ro
    volumes_from:
      - nginx-proxy
    networks:
      cloud-network:

  ncdb:
    image: mariadb:10.5.4
    restart: always
    environment:
      - MYSQL_ROOT_PASSWORD=qLwsPX9g4vQq
      - MYSQL_DATABASE=nextcloud
      - MYSQL_USER=ncuser
      - MYSQL_PASSWORD=B7JtnBvv6rSg6Dug
    volumes:
      - ncdb-data:/var/lib/mysql
    networks:
      cloud-network:

  nc:
    image: nextcloud:19.0.1-apache
    restart: always
    depends_on:
      - ncdb
    volumes:
      - nc-nextcloud:/var/www/html
      - nc-apps:/var/www/html/custom_apps
      - nc-config:/var/www/html/config
      - nc-data:/var/www/html/data
    environment:
      - MYSQL_DATABASE=nextcloud
      - MYSQL_USER=ncuser
      - MYSQL_PASSWORD=B7JtnBvv6rSg6Dug
      - MYSQL_HOST=ncdb
      - VIRTUAL_HOST=cloud.admin-schule.de
      - VIRTUAL_PORT=80
      - VIRTUAL_PROTO=http
      - LETSENCRYPT_HOST=cloud.admin-schule.de
      - LETSENCRYPT_EMAIL=info@admin-schule.de
      - RESOLVE_TO_PROXY_IP=true
    networks:
      cloud-network:
          
  office:
    image: collabora/code:4.2.6.2
    restart: always
    environment:
      - "domain=cloud\.admin-schule\.de"
      - "username=admin"
      - "password="
      - "SLEEPFORDEBUGGER=0"
      - VIRTUAL_HOST=office.admin-schule.de
      - VIRTUAL_PORT=9980
      - VIRTUAL_PROTO=https
      - LETSENCRYPT_HOST=office.admin-schule.de
      - LETSENCRYPT_EMAIL=info@admin-schule.de
      - RESOLVE_TO_PROXY_IP=true
      - NETWORK_ACCESS=internal
    expose:
      - 9980
    cap_add:
      - MKNOD
    networks:
      cloud-network:    
          
networks:
  cloud-network:
    driver: bridge
          
volumes:
  nginx-proxy-certs:
  nginx-proxy-vhost:
  ncdb-data:
  nc-nextcloud:
  nc-apps:
  nc-config:
  nc-data:

Erstelle ein Verzeichnis „/opt/docker-files/nginx-proxy/“

mkdir -p /opt/docker-files/nginx-proxy/
cd /opt/docker-files/nginx-proxy/

Und erstelle eine Datei „network_internal.conf“. Diese wird benötigt, damit der Nginx Container den Traffic zwischen den Containern durchlässt.

echo "allow all;" >> /opt/docker-files/nginx-proxy/network_internal.conf

Ganz wichtig ist ebenfalls die Konfigurationsdatei für die Uploadgröße. Diese legt ihr folgendermaßen an:

echo "client_max_body_size 10G;" >> /opt/docker-files/nginx-proxy/uploadsize.conf

Nun zurück zum „docker_nextcloud“ Ordner. Jetzt können die Docker Images mit docker-compose geladen werden.

docker-compose pull

Bitte prüfe, ob die DNS Einträge „cloud.domainname.com“ und „office.domainname.com“ schon auf die öffentliche IP Adresse des Servers auflösen.

Nach erfolgreichen pull, kann die Lösung gestartet werden.

docker-compose up -d

Prüfe ob alles läuft und gehe anschließend mit einem Webbrowser auf die konfigurierte Adresse des Nextcloud Servers.

https://cloud.domainname.com/

Jetzt muss ein Administrator Account für die Nextcloud angelegt werden. Vergib einen Benutzernamen und ein starkes Passwort. Die Checkbox für empfohlene Apps bitte NICHT anklicken. Das verbaut uns sonst die Konfiguration mit unserem Collabora Container.

Danach kann es sein, dass eine Warnung angezeigt wird und man die Checkbox erneut deaktivieren muss. Die Warnung für die Datenbankverbindung und Leistungseinbußen können an der Stelle ignoriert werden.

Nach ein paar Sekunden der Einrichtung müsste dann das Nextcloud Startfenster zu sehen sein.

Bitte zu „Apps“ und „Büro & Text“ navigieren. Hier die App „Collabora Online“ suchen und „Herunterladen und aktivieren“ klicken.

Nun kann unter „Einstellungen“ im Hauptmenü der Punkt „Collabora Online“ gesucht werden. Dort bitte den obersten Punkt „Verwende deinen eigenen Server“ wählen und diesen eintragen:

https://office.domainname.com

Danach „Save“.

Oooops, hier läuft etwas schief und wir bekommen einen Verbindungsfehler!

Lösung des Verbindungsfehlers

Um den Verbindungsfehler zu beheben, müssen wir die CentOS 7 Firewall konfigurieren. Dafür passen wir das Zone File der Public Zone an. Navigiere zu „/etc/firewalld/zones/“

cd /etc/firewalld/zones/

Bearbeite die Datei „public.xml“, damit sie wie unten zu sehen aussieht.

<?xml version="1.0" encoding="utf-8"?>
<zone>
  <short>Public</short>
  <description>For use in public areas. You do not trust the other computers on networks to not harm your computer. Only selected incoming connections are accepted.</description>
  <service name="dhcpv6-client"/>
  <service name="ssh"/>
  <rule family="ipv4">
     <source address="172.19.0.0/16"/>
     <accept/>
  </rule>
</zone>

Wir fügen eine Regel für das Subnetz „172.19.0.0./16“ hinzu. Das ist das Subnetz unserer Dockercontainer. Das kann bei dir anders sein. Um das richtige Subnetz herauszufinden, kannst du folgenden Befehl verwenden:

docker inspect docker_nextcloud_cloud-network | grep Subnet

Wenn die public.xml angepasst ist, muss der Firewall Dienst neu gestartet werden

systemctl restart firewalld

Anschließend testen wir die Verbindung erneut und es funktioniert! Nun ist die Nextcloud Umgebung einsatzbereit.

Nextcloud and Collabora on Docker

I want to share my complete out-of-the-box solution for Nextcloud with Collabora on Docker with „docker-compose“.

What do we need

  • CentOS 7 Server (Azure, AWS, Hetzner, whatever)
  • Installed Docker and docker-compose
  • Domain with 2 DNS A Records (admin-schule.de for example) configured to the server ip address
    • one for Nextcloud „cloud.admin-schule.de“
    • one for Collabora „office.admin-schule.de“

Preparation

Sign in to the server with your SSH client. Check if Docker is installed and up and running.

docker ps

Check if „docker-compose“ is installed.

docker-compose version

Create a directory „docker_nextcloud“ or clone my repository – https://github.com/bohlrich/docker_nextcloud

Create the „docker-compose.yml“

version: '2.1'
services:

  nginx-proxy:
    image: jwilder/nginx-proxy
    restart: always
    volumes:
      - nginx-proxy-certs:/etc/nginx/certs:ro
      - nginx-proxy-vhost:/etc/nginx/vhost.d
      - /opt/docker-files/nginx-proxy/network_internal.conf:/etc/nginx/network_internal.conf
      - /opt/docker-files/nginx-proxy/uploadsize.conf:/etc/nginx/conf.d/uploadsize.conf
      - /usr/share/nginx/html
      - /var/run/docker.sock:/tmp/docker.sock:ro
    ports:
      - 80:80
      - 443:443
    labels:
      - "com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy"
    networks:
      cloud-network:

  nginx-letsencrypt:
    image: jrcs/letsencrypt-nginx-proxy-companion      
    restart: always
    volumes:
      - nginx-proxy-certs:/etc/nginx/certs:rw
      - /var/run/docker.sock:/var/run/docker.sock:ro
    volumes_from:
      - nginx-proxy
    networks:
      cloud-network:

  ncdb:
    image: mariadb:10.5.4
    restart: always
    environment:
      - MYSQL_ROOT_PASSWORD=qLwsPX9g4vQq
      - MYSQL_DATABASE=nextcloud
      - MYSQL_USER=ncuser
      - MYSQL_PASSWORD=B7JtnBvv6rSg6Dug
    volumes:
      - ncdb-data:/var/lib/mysql
    networks:
      cloud-network:

  nc:
    image: nextcloud:19.0.1-apache
    restart: always
    depends_on:
      - ncdb
    volumes:
      - nc-nextcloud:/var/www/html
      - nc-apps:/var/www/html/custom_apps
      - nc-config:/var/www/html/config
      - nc-data:/var/www/html/data
    environment:
      - MYSQL_DATABASE=nextcloud
      - MYSQL_USER=ncuser
      - MYSQL_PASSWORD=B7JtnBvv6rSg6Dug
      - MYSQL_HOST=ncdb
      - VIRTUAL_HOST=cloud.admin-schule.de
      - VIRTUAL_PORT=80
      - VIRTUAL_PROTO=http
      - LETSENCRYPT_HOST=cloud.admin-schule.de
      - LETSENCRYPT_EMAIL=info@admin-schule.de
      - RESOLVE_TO_PROXY_IP=true
    networks:
      cloud-network:
          
  office:
    image: collabora/code:4.2.6.2
    restart: always
    environment:
      - "domain=cloud\\.admin-schule\\.de"
      - "username=admin"
      - "password="
      - "SLEEPFORDEBUGGER=0"
      - VIRTUAL_HOST=office.admin-schule.de
      - VIRTUAL_PORT=9980
      - VIRTUAL_PROTO=https
      - LETSENCRYPT_HOST=office.admin-schule.de
      - LETSENCRYPT_EMAIL=info@admin-schule.de
      - RESOLVE_TO_PROXY_IP=true
      - NETWORK_ACCESS=internal
    expose:
      - 9980
    cap_add:
      - MKNOD
    networks:
      cloud-network:    
          
networks:
  cloud-network:
    driver: bridge
          
volumes:
  nginx-proxy-certs:
  nginx-proxy-vhost:
  ncdb-data:
  nc-nextcloud:
  nc-apps:
  nc-config:
  nc-data:

Create the directory „/opt/docker-files/nginx-proxy/“

mkdir -p /opt/docker-files/nginx-proxy/
cd /opt/docker-files/nginx-proxy/

And create the configuration file „network_internal.conf“

echo "allow all;" >> /opt/docker-files/nginx-proxy/network_internal.conf

Also very important is the configuration file for the maximal upload size.

echo "client_max_body_size 10G;" >> /opt/docker-files/nginx-proxy/uploadsize.conf

Go back to your „docker_nextcloud“ folder. Now you can pull the images with docker-compose.

docker-compose pull

Please check if your domain names „cloud.domainname.com“ and „office.domainname.com“ are resolving to your servers public ip address.

After pulling the images, you can start the solution.

docker-compose up -d

Please check if all is up and running. After a few minutes you can connect to the Nextcloud website with your browser.

https://cloud.domainname.com/

Now you must create an administrator account for Nextcloud. Give an username and a strong password. Please do NOT check the box with recommended apps. This would break the configuration with Collabora.

After that it is possible to unclick the checkbox again. You can ignore warnings about the database connection and proceed.

After a few seconds or minutes, you can see your Nextcloud dashboard.

Please go to „Apps“ and „Office“ to install the „Collabora Online“ App.

Now you can navigate to preferences and „Collabora Online“. Choose to use your own server and type

https://office.domainname.com

And than click on „Save“.

Oooops, here is something wrong! You got a connection error!!

Solution for connection error

To solve the connection error between the Nextcloud and Collabora Container, we have to configure the CentOS 7 firewall daemon. To achive this, we navigate to the zonefile of the public zone.

cd /etc/firewalld/zones/

Open the zone file for the public zone and configure it like this

<?xml version="1.0" encoding="utf-8"?>
<zone>
  <short>Public</short>
  <description>For use in public areas. You do not trust the other computers on networks to not harm your computer. Only selected incoming connections are accepted.</description>
  <service name="dhcpv6-client"/>
  <service name="ssh"/>
  <rule family="ipv4">
     <source address="172.19.0.0/16"/>
     <accept/>
  </rule>
</zone>

As you can see, we have added a rule for the subnet „172.19.0.0./16“. You have to configure your subnet for the containers. You can get this by inspecting the container network.

docker inspect docker_nextcloud_cloud-network | grep Subnet

Now restart the firewall daemon

systemctl restart firewalld

And now the connection is ready. You can test it now by opening an office document in Nextcloud.

Docker und Docker Compose auf CentOS 7

Ich erstelle einen neuen CentOS 7 Server und stelle dort ein WordPress mit MySQL über Docker und „docker-compose“ zur Verfügung.

Für diese Installation habe ich ebenfalls ein YouTube Video erstellt: https://youtu.be/Vvavmu5XpYM

Für die Installation von CentOS 7, benutze ich JiffyBox, einen Dienst von DomainFactory. Das geht recht fix und ist einfach einzurichten. Der Server ist in ca. 2 Minuten aufgesetzt und ich kann mit der Docker Installation beginnen.

In dieser Variante benutze ich die offiziellen Installationsdateien von Docker. Dafür wird ein bequemes Installationsskript auf https://get.docker.com bereitgestellt. In den Skriptkommentaren kopiert man sich folgende Zeile:

curl -fsSL https://get.docker.com -o get-docker.sh

Und kann anschließend auf dem neuen CentOS 7 Server mittels

sh get-docker.sh

die Installation des Docker Daemons starten.

Das dauert ein paar Minuten. Wenn man kein „root“ Benutzer ist, sollte der „usermod“ Befehl, der am Ende der Installation angezeigt wird, für den jeweiligen Benutzer ausgeführt werden. Sonst kann der docker Daemon nur als „root“ bedient werden.

sudo usermod -aG docker $your_user

Danach muss der Dienst noch aktiviert und gestartet werden.

systemctl enable docker
systemctl start docker

Wenn der Dienst gestartet ist, kann sollte man prüfen, ob die Docker CLI funktioniert.

docker ps

Wenn kein Fehler kommt ist alles gut, es sind ja noch keine Container gestartet.

Anschließend wird Docker Compose, ebenfalls über die offiziellen Quellen von Docker installiert. Dazu gibt es einen Leitfaden auf https://docs.docker.com/compose/install/

Das richtige Betriebssystem auswählen, in diesem Fall Linux, und mittels des „curl“ Befehls auf den Server herunterladen.

sudo curl -L "https://github.com/docker/compose/releases/download/1.27.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

Damit wird das Binary gleich in einen Systemordner kopiert. Anschließend muss die Datei noch ausführbar gemacht werden:

sudo chmod +x /usr/local/bin/docker-compose

Somit ist „docker-compose“ installiert und kann getestet werden.

docker-compose --help

Zum Abschluß wird eine „docker-compose.yml“ Datei in einem Ordner auf dem System erstellt.

mkdir wp-docker
cd wp-docker
vi docker-compose.yml

Und hier wird der Inhalt des Beispiels aus der Compose Dokumentation auf https://docs.docker.com/compose/wordpress/ eingefügt.

version: '3.3'

services:
   db:
     image: mysql:5.7
     volumes:
       - db_data:/var/lib/mysql
     restart: always
     environment:
       MYSQL_ROOT_PASSWORD: somewordpress
       MYSQL_DATABASE: wordpress
       MYSQL_USER: wordpress
       MYSQL_PASSWORD: wordpress

   wordpress:
     depends_on:
       - db
     image: wordpress:latest
     ports:
       - "8000:80"
     restart: always
     environment:
       WORDPRESS_DB_HOST: db:3306
       WORDPRESS_DB_USER: wordpress
       WORDPRESS_DB_PASSWORD: wordpress
       WORDPRESS_DB_NAME: wordpress
volumes:
    db_data: {}

Danach werden die Images heruntergeladen und die ganze Lösung gestartet.

docker-compose pull
docker-compose up

Danach kann man über http://<<ipaddresse>&gt;:8000/ auf die WordPress Installation zugreifen.

Somit wurde ein CentOS 7 Server mit Docker und Docker Compose, sowie WordPress und MySQL in unter 10 Minuten installiert.

Docker Nextcloud Admin Kennwort zurücksetzen

Es war mal wieder soweit. Eine Docker Nextcloud Umgebung wurde erstellt, das Admin Kennwort ist aber leider nicht mehr auffindbar. Glücklicherweise gibt es das „occ“ Tool für Nextcloud, mit dem das Kennwort zurückgesetzt werden kann. Das geht auf normalen Nextcloud Installationen mit folgenden Befehl:

sudo -u www-data php /var/www/nextcloud/occ user:resetpassword admin

Leider funktioniert dieser Befehl so nicht in dem offiziellen Nextcloud Docker Container, da hier kein „sudo“ installiert ist. Das ist aber auch kein größeres Problem. Mit einem angepassten „docker exec“ kann auch der Nutzerwechsel erreicht werden:

docker exec -it -u www-data <<containername>> php /var/www/html/occ user:resetpassword admin

Danach zweimal ein neues Kennwort eingeben und schon kann man wieder auf die Nextcloud zugreifen.

Kubernetes YAML Templates mit kubectl

Das Verfassen von YAML Files für kubernetes kann mühsam und nervig sein. In vielen Fällen kann aber „kubectl“ dabei helfen, schnell und einfach ein Template für ein bestimmtes YAML File zu erstellen.

„kubectl“ ist das zentrale Management Tool für einen Kubernetes Cluster. Neben dem Abfragen und Erstellen von Clusterinformationen über die kubernetes API, kann kubectl auch YAML der gegebenen Befehle erzeugen.

Derzeit können folgende Ressourcen mit „kubectl create“ erzeugt werden:

  • clusterrole
  • clusterrolebinding
  • configmap
  • cronjob
  • deployment
  • job
  • namespace
  • poddisruptionbudget
  • priorityclass
  • quota
  • role
  • rolebinding
  • secret
  • secret docker-registry
  • secret generic
  • secret tls
  • service
  • service clusterip
  • service externalname
  • service loadbalancer
  • service nodeport
  • serviceaccount

Ein einfaches Beispiel ist die Erstellung eines YAML Files für die Erzeugung eines Deployments:

kubectl create deployment test-deployment --image=nginx --dry-run=client -o yaml > test-deployment.yaml

Das Ergebnis sieht dann folgendermaßen aus:

apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: test-deployment
  name: test-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: test-deployment
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: test-deployment
    spec:
      containers:
      - image: nginx
        name: nginx
        resources: {}
status: {}

Im YAML File können dann entsprechend weitere Parameter hinzugefügt oder angepasst werden. Bspw. könnte die Anzahl der Replicas auf 3 erhöht werden. Um das ganze auf den kubernetes Cluster anzuwenden, wird die Datei mit folgendem Befehl aufgerufen:

kubectl create -f test-deployment.yaml

Danach sollten sich die Pods entsprechend im Cluster erzeugen.

Autodiscover und Mailcow

Wer Mailcow als E-Mail Lösung nutzt, stößt evtl. einmal auf das Problem, dass Outlook Clients den Autodiscover nicht korrekt auflösen können. Das kann verschiedene Ursachen haben, ich möchte hier eine davon beschreiben.

Ein wichtiger Punkt, bei der Benutzung von Outlook Clients mit Mailcow ist, dass leider nicht alle Versionen und Editionen unterstützt werden. Selbst getestet und Bestätigt ist, dass Outlook 2016 mit Mailcow aktuell nicht funktioniert.

Wenn Autodiscover vom DNS her korrekt konfiguriert ist (läßt sich schön über den DNS? Button in der Mailcow Admin Konsole prüfen), könnte es dennoch sein, dass der Outlook Client nur ein IMAP Konto und kein Active Sync Konto konfigurieren möchte.

Da auch nur in einigen Outlook Versionen noch die, in der Dokumentation beschriebene, „OLCFG.exe“ zur Verfügung steht, muss hier leider Autodiscover funktionieren.

Der Trick ist hierbei ein bestimmter Eintrag in der data/web/inc/vars.local.inc.php im Ordner der mailcow-dockerized. Wenn man in dieser Datei in die Sektion $autodiscover_config geht, finden man einen Eintrag ‚useEASforOutlook‘.

Dieser sollte auf ‚yes‘ stehen, dann funktioniert auch die Konfiguration mit Autodiscover als Active Sync Postfach mit Outlook. Der Eintrag ‚autodiscoverType‘ sollte natürlich ebenfalls auf ‚activesync‘ stehen. Hier der komplette Abschnitt aus der Dokumentation:

$autodiscover_config = array(
  // General autodiscover service type: "activesync" or "imap"
  // emClient uses autodiscover, but does not support ActiveSync. mailcow excludes emClient from ActiveSync.
  'autodiscoverType' => 'activesync',
  // If autodiscoverType => activesync, also use ActiveSync (EAS) for Outlook desktop clients (>= Outlook 2013 on Windows)
  // Outlook for Mac does not support ActiveSync
  'useEASforOutlook' => 'yes',
  // Please don't use STARTTLS-enabled service ports in the "port" variable.
  // The autodiscover service will always point to SMTPS and IMAPS (TLS-wrapped services).
  // The autoconfig service will additionally announce the STARTTLS-enabled ports, specified in the "tlsport" variable.
  'imap' => array(
    'server' => $mailcow_hostname,
    'port' => array_pop(explode(':', getenv('IMAPS_PORT'))),
    'tlsport' => array_pop(explode(':', getenv('IMAP_PORT'))),
  ),
  'pop3' => array(
    'server' => $mailcow_hostname,
    'port' => array_pop(explode(':', getenv('POPS_PORT'))),
    'tlsport' => array_pop(explode(':', getenv('POP_PORT'))),
  ),
  'smtp' => array(
    'server' => $mailcow_hostname,
    'port' => array_pop(explode(':', getenv('SMTPS_PORT'))),
    'tlsport' => array_pop(explode(':', getenv('SUBMISSION_PORT'))),
  ),
  'activesync' => array(
    'url' => 'https://'.$mailcow_hostname.($https_port == 443 ? '' : ':'.$https_port).'/Microsoft-Server-ActiveSync',
  ),
  'caldav' => array(
    'server' => $mailcow_hostname,
    'port' => $https_port,
  ),
  'carddav' => array(
    'server' => $mailcow_hostname,
    'port' => $https_port,
  ),
);

Das optimale DevOps Tooling

Es scheint eine banale Sache zu sein, aber ich habe relativ viel Zeit für die Suche der für mich besten Tools verwendet. Nachfolgend möchte ich einen kleinen Einblick in meine DevOps Entwicklungsumgebung geben.

Betriebssystem

Ich verwende, wie wahrscheinlich einige von euch, mehrere Laptops und einen festen PC. Der feste PC besitzt 2 installierte Betriebssysteme.

Windows 10 HomeKubuntu 20.04 LTS
OfficeHauptsystem für DevOps Entwicklung
WSL und WSL2 EntwicklungNative Unterstützung für Docker
PowerShell Entwicklung
Cross Plattform testen

Für den DevOps und Softwareentwicklungsteil bin ich hauptsächlich im Ubuntu System unterwegs. Hier funktionieren viele Tools nativ und benötigen keiner weiteren Virtualisierung. Weiterhin laufen ja auch die meisten Zielsysteme mit einem Linux System. Das Windows wird für Office Dokumentationen und zum Teil für das Testen von Cross Plattform genutzt. Auch für die Entwicklung auf der WSL und mit PowerShell ist Windows das System der Wahl.

Code Editor

Seit ein paar Jahren hat sich ein Editor zum Platzhirsch erhoben und punktet durch einfache Bedienbarkeit, eine sehr große Extensions Auswahl und Cross Platform Fähigkeit: Microsoft Visual Studio Code.

Damit gelingt die Entwicklung in Scriptsprachen wie

  • Python
  • Ruby
  • Powershell
  • Powershell Core
  • Bash

Oder in Beschreibungssprachen wie

  • YAML
  • HTML

Oder auch in Hochsprachen wie

  • C++
  • C
  • C#
  • Java

Um nur ein paar Beispiele zu nennen. Die Integration der dafür benötigten Interpreter oder Compiler gelingt dabei meist sehr gut und die Unterstützung durch weitere nützliche Erweiterungen, wie Code Templates oder Auto Formatter, hilft beim Arbeitsfluss ungemein.

Eine detailliert Auseinandersetzung mit Visual Studio Code wird später noch folgen.

Code Repository

Wie es sehr viele machen, habe ich derzeit noch die meisten Projekte auf Github gehostet. Das ist super einfach und schnell eingerichtet. Man kann von jedem Client, der GIT installiert hat auf seine Repositories zugreifen.

Allerdings stelle ich aus Gründen der Integration mit anderen Tools und auch der Möglichkeit, viele private Repositories, ohne Mehrkosten zu haben, derzeit auf Azure DevOps um.

Hier hat man neben dem Repository mit der Code Basis, alle DevOps Tools beisammen

  • Ein Board für die Work Items (Tasks)
  • Eine Möglichkeit zur Erstellung von Sprints
  • Pipelines für das Deployment
  • Erstellen und Ausführen von Test Plänen
  • Speicher von generierten Artefakten für das Deployment

Und wenn die Aufgaben doch größer und größer werden, kann man hier auch einfach weitere Entwickler in seinen Space berechtigen (Microsoft Account vorausgesetzt).

Lokale Container Entwicklung

Um lokal Container bauen zu können, braucht man natürlich erst einmal eine Container Runtime. Die aktuell verbreitetste ist immer noch Docker. Andere Runtimes sind hier auf den Vormarsch. Man sollte ebenfalls einen Blick auf Podman und cri-o werfen.

Ich habe aktuell Docker installiert, in der Version 19.03. Die anderen Runtimes sind nahezu 100% mit der Docker Beschreibungssprache kompatibel.

Um das ganze, wie in der freien Wildbahn, mit einem Kubernetes Cluster zu testen, bedient man sich am besten Minikube.

Somit besitzt man eine vollständige Entwicklungsumgebung für Container und Kubernetes.