====== Minimale Wordpress deployment op CHP4 ====== In deze handleiding leggen we uit wat er minimaal nodig is om een Wordpress applicatie uit te rollen op het OpenShift 4 cluster. Waarschuwing: Team Hosting & Streaming levert geen ondersteuning op deze handleiding, noch het gebruik hiervan. Deze handleiding is alleen maar bedoeld om inzicht te geven hoe een Wordpress site werkend te krijgen. De Wordpress site die in deze handleiding gebruikt wordt is een schone installatie zonder verdere configuratie, plugins of themes. Deze handleiding zorgt niet voor een Wordpress applicatie die productie klaar is. Helemaal onderaan de pagina staan een paar aanpassingen die minimaal uitgevoerd moeten worden om productie klaar te zijn, maar zijn zeker niet volledig. ===== Benodigdheden ===== Voor het uitrollen heb je een aantal benodigdheden nodig: * Een Git Repository met daarin de code van de applicatie. Deze repository moet private zijn. Voor deze handleiding is de sourcecode van Wordpress gedownload en deze in de root van de GitHub repository gezet. * Een SSH key om de Repository te benaderen, deze key mag niet met een wachtwoord beveiligd zijn. We adviseren om hiervoor een aparte [[https://docs.github.com/en/developers/overview/managing-deploy-keys | Deploy Key]] te gebruiken. * De wp-config.php file. Deze kan beter niet in de repository staan in verband met de database credentials. * Nginx en PHP configuratie files, later leggen we uit wat er minimaal nodig is. Note: in dit voorbeeld worden de configuratie bestanden in een mapje in de Git Repository opgeslagen met de naam ''config''. Het is niet verstandig om daar bestanden met credentials in op te slaan. Verder heb je nodig: * Een terminal * De ''oc'' [[https://docs.openshift.com/container-platform/4.8/cli_reference/openshift_cli/getting-started-cli.html | cli]] geïnstalleerd. * Een OpenShift account. * We gaan er vanuit dat je de Workshop hebt gedaan, heb je deze nog niet gedaan? Doe die dan eerst, deze kun je aanvragen via een ticket bij support.npohosting.nl. ===== Voorbereidingen ===== Voordat we kunnen beginnen met het installeren van de applicatie, moeten we een aantal voorbereidingen treffen: * Project aanmaken (als dat nog niet gedaan is). * Database aanmaken. * Configuratie bestanden aanmaken. * Storage aanmaken. * Scriptjes maken. ==== Project aanmaken ==== Het Project maken we aan via de cli. In dit voorbeeld maken we gebruik van de naam ''hens-wordpress-demo''. Zorg ervoor dat je bij het kiezen van de naam de juiste prefix (''xrtv-'') gebruikt: oc new-project hens-wordpress-demo Now using project "hens-wordpress-demo" on server "https://api.cluster.chp4.io:6443". You can add applications to this project with the 'new-app' command. For example, try: oc new-app rails-postgresql-example to build a new example application in Ruby. Or use kubectl to deploy a simple Kubernetes application: kubectl create deployment hello-node --image=k8s.gcr.io/serve_hostname ==== Database aanmaken ==== In deze handleiding maken we een MariaDB database aan met persistent storage op basis van de standaard OpenShift images, deze kan je aanmaken via de webinterface, of via de CLI: oc new-app --template=mariadb-persistent -p DATABASE_SERVICE_NAME=wordpress-db -p MYSQL_USER=wp_user -p MYSQL_PASSWORD= -p MYSQL_DATABASE=wpdb -p VOLUME_CAPACITY=1Gi --> Deploying template "openshift/mariadb-persistent" to project hens-wordpress-demo MariaDB --------- MariaDB database service, with persistent storage. For more information about using this template, including OpenShift considerations, see https://github.com/sclorg/mariadb-container/blob/master/10.3/root/usr/share/container-scripts/mysql/README.md. NOTE: Scaling to more than one replica is not supported. You must have persistent volumes available in your cluster to use this template. The following service(s) have been created in your project: test. Username: wp_user Password: Database Name: wpdb Connection URL: mysql://wordpress-db:3306/ ...... ==== Configuratie bestanden aanmaken ==== Er moeten 3 configuratiebestanden worden aangemaakt en een SSH key: * Nginx configuratie * PHP configuratie * Wordpress configuratie * SSH Key voor de Git Repository Maak eerst een file aan met de naam ''default.conf'' en zet daar de onderstaande configuratie in: # Make sure the real ip gets in the log set_real_ip_from 10.0.0.0/8; real_ip_header X-Forwarded-For; real_ip_recursive on; server { listen 8080; server_name localhost; access_log /dev/stdout main; error_log /dev/stderr; root /var/www/html; index index.php index.html; location ~\.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass php:9000; fastcgi_index index.php; include fastcgi.conf; } } Maak daarna een file aan met de naam ''specials.ini'' en zet daar de volgende configuratie in: extension=pdo.so extension=pdo_mysql.so extension=mysqlnd.so extension=mysqli.so extension=curl.so extension=dom.so extension=exif.so extension=fileinfo.so extension=hash.so extension=imagick.so extension=mbstring.so extension=openssl.so extension=pcre.so extension=xml.so extension=zip.so Maak vervolgens van elk van deze bestande een ''configMap'': oc create configmap nginx-config --from-file=default.conf oc create configmap php-config --from-file=specials.ini De 'wp-config.php' file heeft de volgende inhoud: define( 'DB_NAME', 'wpdb' ); define( 'DB_USER', 'wp_user' ); define( 'DB_PASSWORD', '' ); define( 'DB_HOST', 'wordpress-db' ) Omdat de ''wp-config.php'' credentials bevat, namelijk die van de zojuist aangemaakte database, stoppen we die in een ''secret'': oc create secret generic wp-config --from-file=config/wp-config.php Voor de SSH Key maken we ook een secret aan met de naam ''wpgit'': oc create secret generic wpgit --from-file=ssh-privatekey=wpgit --type=kubernetes.io/ssh-auth ==== Scriptjes maken ==== In verband met het deployproces wat we gebruiken, moeten er in de Repository twee scriptjes aanwezig zijn: * deploy.sh * run.sh Het ''deploy.sh'' script kan gebruikt worden om zaken als ''composer'' te draaien, maar in dit voorbeeld is het bestand leeg (het moet er wel zijn). Het bestand moet in dezelfde directory staan als de ''index.php'' van Wordpress. In mijn voorbeeld is dat de root van de Git Repository: #!/bin/sh echo "I'm just here to do nothing at all" Zorg ervoor dat het executable is: chmod a+x deploy.sh Het tweede script wat je nodig hebt is het ''run.sh'' script. Dit script kopieert uiteindelijk de data naar de DocumentRoot en is dus wel belangrijk. Maak het bestand aan met de naam ''run.sh'', net zoals de deploy.sh moet het in dezelfde directory als de ''index.php'' staan: #!/bin/sh docroot=/var/www/html/ if [ ! -d ${docroot} ]; then mkdir -p ${docroot} fi cp -Rv /tmp/src/* ${docroot} Maak het executable: chmod a+x run.sh En zorg er als laatste voor dat ze gecommit zijn in Git: git add deploy.sh run.sh git commit -m "" deploy.sh run.sh git push ==== Storage aanmaken ==== Als laatste maken we een stukje persistent storage aan waar de code op komt te liggen straks. Maak hiervoor een bestandje aan met de naam ''storage.yaml'' en zet daar de volgende code in (pas de namespace aan naar je eigen namespace): apiVersion: v1 kind: PersistentVolumeClaim metadata: name: wordpress namespace: hens-wordpress-demo spec: accessModes: - ReadWriteMany resources: requests: storage: 4Gi storageClassName: ocs-storagecluster-cephfs volumeMode: Filesystem Sla dit op, en maak vervolgens de storage aan: oc create -f storage.yaml Verifieer vervolgens dat hij is aangemaakt: oc get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE wordpress Bound pvc-268c5aa8-ad2a-41ba-9721-7683fa86d37a 4Gi RWX ocs-storagecluster-cephfs 24h wordpress-db Bound pvc-56ab0f2c-36ed-42bd-9dc1-542d06aa9b0b 2Gi RWO ocs-storagecluster-cephfs 24h ===== Uitrollen applicatie ==== Als we de voorbereidingen hebben gedaan, kunnen we de applicatie gaan uitrollen. We beginnen met de PHP Pods. ==== PHP ==== Voor PHP maken we gebruik van ons eigen Docker Image: ''registry.npohosting.nl/npohosting/php-fpm:latest''. Dit Image maakt gebruik van het zogeheten ''S2I'' concept (source-2-image), dit is een proces waarbij we de Docker Image combineren met de Git Repository en daarvan een nieuw image maken die uiteindelijk wordt opgestart. Als eerste maken we het aan met ''oc new-app'': oc new-app registry.npohosting.nl/npohosting/php-fpm~git@github.com:tsterk/wordpress-demo.git --source-secret=wpgit --name=php --> Found container image 9218ebc (7 days old) from registry.npohosting.nl for "registry.npohosting.nl/npohosting/php-fpm" php-fpm ------- PHP FPM Tags: builder, php, php-fpm * An image stream tag will be created as "php-fpm:latest" that will track the source image * A source build using source code from git@github.com:tsterk/wordpress-demo.git will be created * The resulting image will be pushed to image stream tag "php:latest" * Every time "php-fpm:latest" changes a new build will be triggered --> Creating resources ... imagestream.image.openshift.io "php" created buildconfig.build.openshift.io "php" created deployment.apps "php" created service "php" created --> Success Build scheduled, use 'oc logs -f buildconfig/php' to track its progress. Application is not exposed. You can expose services to the outside world by executing one or more of the commands below: 'oc expose service/php' Run 'oc status' to view your app. Na het aanmaken, moeten we de volgende items van de ''Deployment'' aanpassen: * Een ''command'' toevoegen. * De configuratie inladen. * De storage toevoegen. Het aanpassen van de ''Deployment'' doen we met het ''oc edit'' commando: oc edit deployment/php Dit opent je favoriete editor (in ons voorbeeld ''vim'') met de yaml file van de Deployment. Je kan de volgende dingen toevoegen: Het toevoegen van de ''command'' doe je binnen de ''spec'' onder ''name:php'': args: - /tmp/src/run.sh; /usr/libexec/s2i/run; command: - /bin/sh - -c Voor het inladen van de configuratie zet je binnen de ''spec'' onder ''terminationMessagePolicy: File'': volumeMounts: - mountPath: /var/www/html name: wordpress - mountPath: /usr/local/etc/php/conf.d name: php-config - mountPath: /var/www/html/wp-config.php name: wp-config subPath: wp-config.php Om de storage toe te voegen zet je binnen de ''spec'' onder ''terminationGracePeriodSeconds: 30'': volumes: - name: wordpress persistentVolumeClaim: claimName: wordpress - name: wp-config secret: secretName: wp-config - configMap: name: php-config name: php-config Het ''spec'' gedeelte van de ''Deployment'' ziet er als het goed is nu ongeveer zo uit: spec: containers: - args: - /tmp/src/run.sh; /usr/libexec/s2i/run; command: - /bin/sh - -c image: image-registry.openshift-image-registry.svc:5000/hens-wordpress-demo/php2@sha256:56ddb90f90828759a727eb0586b4941ef898fc6ae754953045cb770ed5920797 imagePullPolicy: IfNotPresent name: php2 ports: - containerPort: 9000 protocol: TCP resources: {} terminationMessagePath: /dev/termination-log terminationMessagePolicy: File volumeMounts: - mountPath: /var/www/html name: wordpress - mountPath: /usr/local/etc/php/conf.d name: php-config - mountPath: /var/www/html/wp-config.php name: wp-config subPath: wp-config.php dnsPolicy: ClusterFirst restartPolicy: Always schedulerName: default-scheduler securityContext: {} terminationGracePeriodSeconds: 30 volumes: - name: wordpress persistentVolumeClaim: claimName: wordpress - name: wp-config secret: secretName: wp-config - configMap: name: php-config name: php-config Als dat klopt, dan kan je de wijzigingen opslaan. Als het goed is gaat OpenShift gelijk een nieuwe Pod opstarten, controleer dit met ''oc get pods''. oc get pods NAME READY STATUS RESTARTS AGE php-1-build 0/1 Completed 0 33m php-5b8555f7bd-dfg55 1/1 Running 0 30m php-b64899ff-gltcv 0/1 ContainerCreating 0 23s wordpress-db-1-deploy 0/1 Completed 0 25h wordpress-db-1-dkz4g 1/1 Running 0 25h We zien hier een nieuwe ''ContainerCreating'' zo zien we dat het goed gaat. Deze moet uiteindelijk naar ''Running'' gaan (je moet het commando een paar keer opnieuw uitvoeren). Wanneer dat is gebeurd kan je controleren of de wijzigingen goed zijn doorgekomen: oc exec php-b64899ff-gltcv -- ls wp-config.php wp-config.php Als je bovenstaand terug krijgt kan je er vanuit gaan dat het goed is gegaan en kan je door naar de nginx deployment. ==== Nginx ==== Ook nginx rollen we uit met ''oc new-app'', alleen geven we deze niet de Git repository mee: oc new-app --name=nginx --docker-image=registry.npohosting.nl/npohosting/nginx:latest --> Found container image ab57938 (8 days old) from registry.npohosting.nl for "registry.npohosting.nl/npohosting/nginx:latest" nginx ----- NGiNX Tags: builder, webserver, nginx * An image stream tag will be created as "nginx:latest" that will track this image --> Creating resources ... imagestream.image.openshift.io "nginx" created deployment.apps "nginx" created service "nginx" created --> Success Application is not exposed. You can expose services to the outside world by executing one or more of the commands below: 'oc expose service/nginx' Run 'oc status' to view your app. Ook bij de nginx deployment moeten we hetzelfde drietal items aanpassen in de deployment: * Een command toevoegen. * De configuratie inladen. * De storage toevoegen. We beginnen wederom met ''oc edit'': oc edit deployment/nginx We voegen het ''command'' toe binnen de ''spec'' onder ''name'': command: - /usr/libexec/s2i/run Voor de storage zetten we binnen de ''spec'' onder ''terminationGracePeriodSeconds: 30'': volumes: - name: wordpress persistentVolumeClaim: claimName: wordpress - configMap: name: nginx-config name: nginx-config Het ''spec'' gedeelte van de ''Deployment'' ziet er als het goed is nu ongeveer zo uit: spec: containers: - command: - /usr/libexec/s2i/run image: registry.npohosting.nl/npohosting/nginx@sha256:1b3f72a21907b945b824baef75e574c3be7135c6698d2a72764d70b8b146cd9d imagePullPolicy: IfNotPresent name: nginx ports: - containerPort: 8080 protocol: TCP resources: {} terminationMessagePath: /dev/termination-log terminationMessagePolicy: File volumeMounts: - mountPath: /var/www/html name: wordpress - mountPath: /etc/nginx/conf.d name: nginx-config dnsPolicy: ClusterFirst restartPolicy: Always schedulerName: default-scheduler securityContext: {} terminationGracePeriodSeconds: 30 volumes: - name: wordpress persistentVolumeClaim: claimName: wordpress - configMap: name: nginx-config name: nginx-config Als dat klopt, dan kan je de wijzigingen opslaan. Als het goed is gaat OpenShift gelijk een nieuwe Pod opstarten, controleer dit met ''oc get pods'' oc get pods NAME READY STATUS RESTARTS AGE nginx-776b8d886c-cfkp8 0/1 CrashLoopBackOff 5 5m52s nginx-7ffd9898df-rrrxr 0/1 ContainerCreating 0 3s php-1-build 0/1 Completed 0 45m php-b64899ff-gltcv 1/1 Running 0 12m wordpress-db-1-deploy 0/1 Completed 0 25h wordpress-db-1-dkz4g 1/1 Running 0 25h Het klopt dat je daar een Pod ziet met ''CrashLoopBackOff'' als status, dat hebben we als het goed is opgelost met onze aanpassingen. Je ziet dan ook naar verloop van tijd de Pod met ''ContainerCreating'' status (in dit voorbeeld ''nginx-7ffd9898df-rrrxr'') naar ''Running'' gaan (je zult het commando wellicht een paar keer moeten uitvoeren voor je dit ziet), wanneer dit gebeurd is, kan je het controleren: oc exec nginx2-7ffd9898df-rrrxr -- ls /var/www/html/wp-config.php /var/www/html/wp-config.php Als het goed is draait nu de Wordpress applicatie, het enige wat we nu nog moeten doen is de applicatie bereikbaar maken. ==== Routes ==== In dit laatste hoofdstukje gaan we de applicatie voor de wereld bereikbaar maken. Dit doen we met het ''oc expose'' commando, waar we de service ''nginx'' exposen, controleer of die bestaat: oc get service nginx NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE nginx ClusterIP 172.30.239.158 8080/TCP 25h Voer het commando uit: oc expose service nginx --hostname=wordpress-demo.apps.hens.cluster.chp4.io Let goed op bij de ''hostname'' welke URL je gebruikt. In dit voorbeeld hebben we een subdomein van ''apps.hens.cluster.chp4.io'', maar vervang hierbij ''hens'' door de prefix van de omroep of afdeling waarvoor je bezig bent, bijvoorbeeld voor OmroepMax wordt dat ''apps.max.cluster.chp4.io''. Je kan natuurlijk ook een eigen domeinnaam gebruiken, denk dan wel aan de DNS instellingen. Als het goed is kan je nu naar de URL gaan. Als je een nieuwe site maakt krijg je de Wordpress installer te zien en kan je die doorlopen en krijg je aan het einde een werkende site. ===== Ter afsluiting ===== Je hebt nu een werkende Wordpress Installatie in OpenShift, maar nog lang niet productierijp. Er zijn een aantal dingen die ik niet heb laten terugkomen in deze handleiding, maar waar wel over nagedacht moet worden: * SSL. Er staat nu geen SSL certificaat geconfigureerd. Hoe je dat zou kunnen doen, kan je hier lezen: https://hosting.omroep.nl/chp:handleiding:letsencrypt. * Scaling. Er is nu geen enkele vorm van scaling gedaan. De Pods draaien allebei enkelvoudig. In een productie omgeving wil je gaan kijken naar autoscaling zodat je website meeschaalt met de vraag. * Caching. Er is geen caching geconfigureerd. * Liveness en Readiness Probers. Het kan verstandig zijn om Liveness en Readiness Probes te configureren voor de Deployment. Een Livenessprobe kijkt of een Pod nog wel goed functioneert en een Readinessprobe kijkt of een Pod volledig is opgestart. Meer informatie: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/ * Storage. We gebruiken in deze handleiding persistent storage in OpenShift, maar dit is niet de manier die we adviseren. Voor de statische data (alles wat normaal in ''wp-uploads'' staat) raden we aan om gebruik te maken van een S3 bucket met een CDN. Er zijn diverse plugins beschikbaar in Wordpress om dit te realiseren. * Loadtesten. Het is verstandig om een loadtest op je applicaties uit te voeren zodat je kan leren of de dingen die je doet ook efficiënt werken. Zeker bij het gebruik van nieuwe technieken kan dit belangrijk zijn. * Backups. Team Hosting & Streaming verzorgt geen backups. Het idee is dat de data van de database bij Amazon ligt waar Amazon backups van maakt; dat de code in een Git Repository staat; en de overige data in een S3 bucket. Zo heb je in principe geen persistent data in OpenShift staan. * Monitoring. Team Hosting & Streaming verzorgt geen monitoring op applicatieniveau. We kijken of het OpenShift cluster blijft draaien, maar niet of de website of webserver het nog doet. ==== Handige Links ==== * https://docs.openshift.com/container-platform/4.8/applications/creating_applications/creating-applications-using-cli.html * https://docs.openshift.com/container-platform/4.8/applications/deployments/what-deployments-are.html * https://docs.openshift.com/container-platform/4.8/applications/deployments/managing-deployment-processes.html * https://docs.openshift.com/container-platform/4.8/applications/config-maps.html * https://docs.openshift.com/container-platform/4.8/applications/application-health.html * https://docs.openshift.com/container-platform/4.8/applications/odc-monitoring-project-and-application-metrics-using-developer-perspective.html * https://hosting.omroep.nl/chp:faq * https://hosting.omroep.nl/chp:handleiding:static-cdn * https://hosting.omroep.nl/chp:handleiding:letsencrypt