Host server-side GTM volledig bulletproof met logging
Sinds mijn blog over het zelf hosten van server-side Google Tag Manager (sGTM) is er een hoop veranderd in mijn setup. De afgelopen tijd heb ik enkele essentiële aanpassingen doorgevoerd die de 'self-hosted' setup een stuk robuuster maken. Met verbeterde logging en enkele slimme aanpassingen, is sGTM nu echt 'bulletproof'. Ik neem je mee in de (meest essentiële) aanpassingen!
Dit blog bouwt voort op de kennis van ‘Host server-side GTM voor een paar euro per maand’. Ik sta daarom niet zo nadrukkelijk stil bij de Docker commands, maar wel bij de configuratie van de Caddy proxy en Docker.Mijn sGTM-setup is met name wat robuuster geworden, doordat ik logging heb toegevoegd. Een ander punt waarmee ik worstelde was het weergeven van het remote IP-adres van de cliënt. Dit is een specifiek Caddy + Docker Swarm probleem. Het remote IP-adres heb je nodig om bijvoorbeeld een geolocatie vast te stellen.Een korte leeswijzer:
Het is noodzakelijk om gebruik te maken van de configuratie ‘mode: host’ binnen de poortconfiguraties. Door deze modus te gebruiken, kan de Caddy-proxy direct toegang krijgen tot het netwerk van de host, waardoor het in staat is om de werkelijke client IP-adressen vast te leggen en correct door te geven aan de services die achter de proxy draaien.Dit ziet er dan als volgt uit voor wat betreft de configuratie in je yaml-bestand:Enkele kernpunten in de configuratie:Met deze labels heb je op een eenvoudige manier zeer gedetailleerde monitoring en logging zonder de noodzaak van ingewikkelde configuraties. Dit zorgt niet alleen voor betere inzichten maar verhoogt ook de stabiliteit en betrouwbaarheid van onze sGTM-setup.Vervang vervolgens de placeholders met de relevante waarden voor jouw setup. Herhaal deze stap voor de map data-docker-stack. Note: dat DNS mapping naar je server al goed moet staan (zie wederom mijn eerdere blog).
- Client-side IP-adres doorgeven aan sGTM
- Integreren van logging met Datadog
- Het eindresultaat
Remote IP-adres (van de client) doorgeven aan sGTM
Bij het implementeren van een server-side oplossing zoals sGTM is het essentieel dat het remote IP-adres van je bezoeker (de cliënt) correct wordt doorgegeven. Dit is van cruciaal belang voor functionaliteiten als:- geolocatie
- gepersonaliseerde content
- beveiligingstoepassingen
Het is noodzakelijk om gebruik te maken van de configuratie ‘mode: host’ binnen de poortconfiguraties. Door deze modus te gebruiken, kan de Caddy-proxy direct toegang krijgen tot het netwerk van de host, waardoor het in staat is om de werkelijke client IP-adressen vast te leggen en correct door te geven aan de services die achter de proxy draaien.Dit ziet er dan als volgt uit voor wat betreft de configuratie in je yaml-bestand:
...
proxy:
image: caddy:2.7.4-alpine
deploy:
mode: global
placement:
constraints:
- node.role==manager
restart_policy:
condition: any
ports:
- target: 443
published: 443
protocol: tcp
mode: host
- target: 80
published: 80
protocol: tcp
mode: host
...
Integreren van logging met Datadog
In een moderne tech-stack is het monitoren van je applicaties en services geen luxe, maar een noodzaak. Datadog is een populair platform dat uitgebreide inzichten biedt in de prestaties, beschikbaarheid en gezondheid van je services. Het integreren van Datadog is vrij eenvoudig. Het spreekt bijna voor zich, maar je een Datadog account Een account maak je aan op de website van Datadog door te klikken op 'get started for free'! Kies vervolgens voor hosting in Europa. nodig. Dit kost je om het uit te to proberen verder niks met een ‘free plan’.(1) Configureren van Datadog als docker stack
Datadog draait binnen het Docker cluster als een apart stack. Het stack bestaat enkel uit één service: de Datadog agent. Deze agent fungeert als een tussenlaag tussen je Docker services in sGTM stack en het Datadog-platform. De agent verzamelt en verzendt metrieken, events en logs vanuit je containers. Het docker stack yml bestand ziet er als volgt uit:version: '3.9'
services:
agent:
image: datadog/agent:latest
deploy:
replicas: 2 # amount is identical to the number of nodes in the cluster.
placement:
max_replicas_per_node: 1
restart_policy:
condition: on-failure
environment:
- DD_API_KEY=$DD_API_KEY
- DD_LOGS_ENABLED=true
- DD_LOGS_CONFIG_CONTAINER_COLLECT_ALL=true
- DD_CONTAINER_EXCLUDE=image:datadog/agent:*
- DD_SITE=datadoghq.eu
volumes:
- '/var/run/docker.sock:/var/run/docker.sock:ro'
- '/proc/:/host/proc/:ro'
- datadog:/opt/datadog-agent/run:rw
- '/sys/fs/cgroup/:/host/sys/fs/cgroup:ro'
volumes:
datadog:
- Image: We gebruiken datadog/agent:latest om ervoor te zorgen dat we de nieuwste versie van de Datadog-agent hebben.
- Environment variabelen:
- DD_API_KEY: Je unieke Datadog API-sleutel, nodig voor authenticatie. De sleutel kan je hier aanmaken.
- DD_LOGS_ENABLED en DD_LOGS_CONFIG_CONTAINER_COLLECT_ALL: Deze zorgen ervoor dat logs van alle containers worden verzameld en naar Datadog worden verzonden.
- DD_CONTAINER_EXCLUDE: Met deze variabele zorgen we ervoor dat logs van de Datadog-agent zelf worden uitgesloten, om ruis in je logs te voorkomen.
- DD_SITE: Dit verwijst naar de specifieke Datadog-instantie waarmee je wilt integreren. In het geval van Europese opslag is datadoghq.eu de juiste waarde.
- Volumes: Hier binden we een aantal cruciale paden van de host naar de agent-container:
- /var/run/docker.sock: Geeft de agent toegang tot de Docker API, wat essentieel is voor het verzamelen van containermetrieken en logs.
- /proc/ en /sys/fs/cgroup/: Deze geven inzicht in systeem- en processtatistieken van de host.
(2) Toevoegen van Datadog labels aan sGTM services
De sGTM services zijn niet automatisch zichtbaar voor de Datadog agent. De agent kan de service ontdekken middels specifieke labels in het docker-yml bestand. Deze labels spelen een sleutelrol in hoe Datadog informatie interpreteert en visualiseert:- com.datadoghq.ad.check_names: Dit label definieert de naam van de service zoals deze zal verschijnen in Datadog. Bijvoorbeeld, voor de tag-server-service is het ingesteld op '["tag-server"]'.
- com.datadoghq.ad.init_configs: Dit label is meestal ingesteld op een lege array '[{}]', wat betekent dat er geen initiële configuratie is vereist voordat Datadog metrieken en logs begint te verzamelen.
- com.datadoghq.ad.instances: Met dit label kunnen we de host en poort dynamisch instellen waar Datadog naar informatie moet zoeken. Door gebruik te maken van '%%host%%' en '%%port%%', vraagt het de actuele host en poort van de service op.
- com.datadoghq.ad.logs: Hiermee geven we aan hoe de logs moeten worden ingedeeld in Datadog. De 'source' is de naam van de service, en 'service' helpt bij het groeperen van logs onder een gemeenschappelijke noemer, in dit geval 'sgtm'.
version: '3.9'
services:
tag-server:
image: 'gcr.io/cloud-tagging-10302018/gtm-cloud-image:stable'
deploy:
replicas: 3
placement:
max_replicas_per_node: 2
update_config:
parallelism: 2
delay: 10s
restart_policy:
condition: any
resources:
limits:
cpus: '1'
memory: 512M
environment:
- CONTAINER_CONFIG=$CONTAINER_CONFIG
- PREVIEW_SERVER_URL=https://${PREVIEW_SERVER_DOMAIN}
- RUN_AS_PREVIEW_SERVER=false
labels:
com.datadoghq.ad.check_names: '["tag-server"]'
com.datadoghq.ad.init_cdoconfigs: '[{}]'
com.datadoghq.ad.instances: '[{"host": "%%host%%","port":"%%port%%"}]'
com.datadoghq.ad.logs: '[{"source": "tag-server", "service": "sgtm"}]'
preview-server:
image: 'gcr.io/cloud-tagging-10302018/gtm-cloud-image:stable'
deploy:
replicas: 1
placement:
constraints:
- node.role==worker
restart_policy:
condition: any
resources:
limits:
cpus: '1'
memory: 512M
environment:
- CONTAINER_CONFIG=$CONTAINER_CONFIG
- RUN_AS_PREVIEW_SERVER=true
labels:
com.datadoghq.ad.check_names: '["preview-server"]'
com.datadoghq.ad.init_configs: '[{}]'
com.datadoghq.ad.instances: '[{"host": "%%host%%","port":"%%port%%"}]'
com.datadoghq.ad.logs: '[{"source": "preview-server", "service": "sgtm"}]'
proxy:
image: caddy:2.7.4-alpine
deploy:
mode: global
placement:
constraints:
- node.role==manager
restart_policy:
condition: any
ports:
- target: 443
published: 443
protocol: tcp
mode: host
- target: 80
published: 80
protocol: tcp
mode: host
volumes:
- $PWD/proxy/Caddyfile:/etc/caddy/Caddyfile
- caddy:/data
environment:
TAG_SERVER_DOMAIN: $TAG_SERVER_DOMAIN
PREVIEW_SERVER_DOMAIN: $PREVIEW_SERVER_DOMAIN
labels:
com.datadoghq.ad.check_names: '["caddy-proxy"]'
com.datadoghq.ad.init_configs: '[{}]'
com.datadoghq.ad.instances: '[{"host": "%%host%%","port":"%%port%%"}]'
com.datadoghq.ad.logs: '[{"source": "caddy-proxy", "service": "sgtm"}]'
volumes:
caddy:
Eindresultaat: configureer je eigen server
Tot slot nog een kort stappenplan om deze setup te implementeren. Ik ga ervan uit dat je al een docker swam hebt draaien (lees anders mijn eerdere blog).- (1) Clone deze twee repositories:
git clone https://github.com/frankdevlabs/sgtm-manual-server
git clone https://github.com/frankdevlabs/datadog-docker-stack
- (2) Maak per folder een .env bestand aan:
cd sgtm-manual-server
cp .env.template .env
vim .env
- (3) Start de stacks
cd $HOME
cd datadog-docker-stack
env $(cat ./.env | xargs) envsubst < ./docker-compose.yml | docker stack deploy --compose-file - datadog
cd $HOME
cd sgtm-manual-server
git checkout feat/logging-with-datadog
env $(cat ./.env | xargs) envsubst < ./docker-compose.yml | docker stack deploy --compose-file - sgtm