Skip to content

Instantly share code, notes, and snippets.

@oadiazm
Forked from DavainWhite/README.md
Created August 2, 2024 21:12
Show Gist options
  • Save oadiazm/fd2fbde6869c1dad0c8603a495a29148 to your computer and use it in GitHub Desktop.
Save oadiazm/fd2fbde6869c1dad0c8603a495a29148 to your computer and use it in GitHub Desktop.
Setting up Docker, Rancher, and Traefik with Monitoring Tools in a Secure Environment

Setting up Docker, Rancher, and Traefik with Monitoring Tools in a Secure Environment

This Cloud-Init script facilitates a robust deployment of Docker, Rancher, Traefik, and integrates Prometheus, Grafana, and Loki for comprehensive monitoring within an isolated environment, leveraging the ubuntu/jammy/cloud LXD image. Meticulous attention has been given to fortify the infrastructure, implementing strict access controls, minimal container permissions, and automated SSL provisioning via Traefik integrated with Cloudflare for seamless certificate renewal.

Requirements

  • Operational knowledge of LXD, Docker, Rancher, and Cloudflare.
  • Access to the ubuntu/jammy/cloud LXD image.
  • Additionally, refer to Monitoring Stack Gist for deploying the monitoring stack.

Instructions

  1. Environment Setup:

    Ensure availability of the ubuntu/jammy/cloud image in your LXD environment:

    lxc remote list

    If missing, import the image:

    lxc image copy images:ubuntu/jammy/cloud local: --alias=ubuntu-jammy-cloud
  2. Repository Cloning:

    Clone the repository housing the Cloud-Init script:

    git clone https://gist.github.com/9ba10e20df02e8ed278e0688cdc21f82.git
  3. Configuration Customization:

    Tailor the .env file with your specific configuration:

    RANCHER_HOSTNAME=rancher.example.com
    CLOUDFLARE_EMAIL=[email protected]
    CLOUDFLARE_API_KEY=your-cloudflare-api-key
  4. SSH Key Integration:

    Add your SSH public key to the ssh-authorized-keys section in cloud-config.yaml:

    ssh_authorized_keys:
      - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAB... user@host
  5. Loki Logging Configuration:

    Configure the loki-url in /etc/docker/daemon.json for Loki logging:

    {
      "log-driver": "loki",
      "log-opts": {
        "loki-url": "http://<LOKI-HOST>:<LOKI-PORT>/loki/api/v1/push"
      }
    }
  6. Infrastructure Deployment:

    Initiate the environment using the Cloud-Init script and ubuntu/jammy/cloud image:

    lxc launch ubuntu-jammy-cloud your-container-name --config user.user-data="$(cat cloud-config.yaml)"
  7. Post-Deployment Access:

    Access the deployed services and endpoints:

  8. Rancher Dashboard Login:

    Log in to the Rancher dashboard using:

    • Username: root
    • Password: Utilize CATTLE_BOOTSTRAP_PASSWORD generated during deployment.

Auto-Generated Configuration

Auto-generated values for seamless integration:

  • METRICS_AUTH_USER: Basic authentication username for Metrics endpoints.
  • METRICS_AUTH_PASS: Basic authentication password for Metrics endpoints.
  • CATTLE_BOOTSTRAP_PASSWORD: Password for Rancher dashboard access.

These credentials are essential for accessing and securing the Metrics endpoints within your deployed environment.

Post-Deployment Configuration Update

After creating the virtual machine, update the Prometheus scrape configurations for seamless integration with the deployed environment. Add the following scrape configuration to the prometheus.yml file in your monitoring stack, replacing <REPLACE_WITH_METRICS_AUTH_USER> and <REPLACE_WITH_METRICS_AUTH_PASS> with the auto-generated values for basic authentication:

scrape_configs:
- job_name: rancher.example.com
  scrape_interval: 5s
  scrape_timeout: 5s
  static_configs:
    - targets:
      - rancher.example.com
      labels:
        __metrics_path__: /traefik/metrics
    - targets:
      - rancher.example.com
      labels:
        __metrics_path__: /node-exporter/metrics
  basic_auth:
    username: <REPLACE_WITH_METRICS_AUTH_USER>
    password: <REPLACE_WITH_METRICS_AUTH_PASS>

Ensure to replace <REPLACE_WITH_METRICS_AUTH_USER> and <REPLACE_WITH_METRICS_AUTH_PASS> with the corresponding auto-generated values. This configuration ensures proper scraping of metrics from Traefik and Node Exporter with the specified basic authentication credentials.

Dashboard Views

Rancher Dashboard

Screenshot from 2024-01-08 12-53-38

The Rancher dashboard provides a comprehensive overview of your containerized environment, enabling easy management and monitoring of Docker containers.

Traefik Dashboard

Screenshot from 2024-01-08 12-55-24

The Traefik dashboard offers insights into your network infrastructure, routing, and HTTP services, ensuring efficient traffic management.

Grafana Dashboard

Screenshot from 2023-12-26 19-12-42

Grafana provides visually appealing and informative graphs and charts, presenting data collected by Prometheus, facilitating in-depth analysis and monitoring.

Customization & Further Enhancements

Tailor the setup according to specific requirements and incorporate additional functionalities as needed.

#cloud-config
timezone: America/New_York
package_update: true
package_upgrade: true
package_reboot_if_required: true
packages:
- openssh-server
- apache2-utils
- docker-ce
apt:
sources:
download-docker-com.list:
source: deb https://download.docker.com/linux/ubuntu $RELEASE stable
key: |
-----BEGIN PGP PUBLIC KEY BLOCK-----
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
YT90qFF93M3v01BbxP+EIY2/9tiIPbrd
=0YYh
-----END PGP PUBLIC KEY BLOCK-----
users:
- name: rancher
gecos: Rancher User
groups: docker
sudo: false
shell: /bin/bash
lock_passwd: true
ssh-authorized-keys:
- <REDACTED>
write_files:
- path: /etc/ssh/sshd_config
owner: root:root
permissions: '0644'
defer: true
content: |
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
UsePAM yes
X11Forwarding no
AllowUsers rancher
- path: /etc/docker/daemon.json
owner: root:root
permissions: '0644'
defer: true
content: |
{
"debug" : false,
"log-driver": "loki",
"log-opts": {
"loki-url": "<REDACTED>",
"loki-batch-size": "400"
}
}
- path: /home/rancher/.env
owner: rancher:rancher
permissions: '0600'
defer: true
content: |
RANCHER_HOSTNAME=<REDACTED>
CLOUDFLARE_EMAIL=<REDACTED>
CLOUDFLARE_API_KEY=<REDACTED>
- path: /home/rancher/docker-compose.yml
owner: rancher:rancher
permissions: '0600'
defer: true
content: |
networks:
traefik:
name: traefik-net
node-exporter:
name: node-exporter-net
internal: true
rancher:
name: rancher-net
services:
traefik:
image: docker.io/traefik:v2.10
container_name: traefik
hostname: traefik
restart: unless-stopped
security_opt:
- no-new-privileges:true
command:
- --api=true
- --ping=true
- --ping.manualrouting=true
- --global.checknewversion=false
- --global.sendanonymoususage=false
- --log.level=info
- --log.filepath=/logs/traefik.log
- --accesslog.filepath=/logs/access.log
- --accesslog.bufferingsize=100
- --metrics.prometheus=true
- --metrics.prometheus.manualrouting=true
- --metrics.prometheus.addentrypointslabels=true
- --metrics.prometheus.addrouterslabels=true
- --metrics.prometheus.addserviceslabels=true
- --providers.docker=true
- --providers.docker.exposedbydefault=false
- --providers.docker.endpoint=unix:///var/run/docker.sock
- --entrypoints.web.address=:80
- --entrypoints.websecure.address=:443
- --entrypoints.web.http.redirections.entrypoint.to=websecure
- --entrypoints.web.http.redirections.entrypoint.scheme=https
- --entrypoints.web.http.redirections.entrypoint.permanent=true
- --certificatesresolvers.cloudflare.acme.dnschallenge=true
- --certificatesresolvers.cloudflare.acme.dnschallenge.provider=cloudflare
- --certificatesresolvers.cloudflare.acme.dnschallenge.delaybeforecheck=0
- --certificatesresolvers.cloudflare.acme.dnschallenge.resolvers=1.1.1.1:53
- --certificatesresolvers.cloudflare.acme.dnschallenge.resolvers=1.0.0.1:53
- --certificatesresolvers.cloudflare.acme.email=$CLOUDFLARE_EMAIL
- --certificatesresolvers.cloudflare.acme.storage=/cloudflare/acme.json
ports:
- 80:80
- 443:443
networks:
- traefik
- node-exporter
- rancher
environment:
- PUID=1000
- PGID=1000
- CLOUDFLARE_EMAIL=$CLOUDFLARE_EMAIL
- CLOUDFLARE_API_KEY=$CLOUDFLARE_API_KEY
volumes:
- /logs:/logs:rw
- /cloudflare:/cloudflare:rw
- /home/rancher/.htpasswd:/.htpasswd:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- /etc/localtime:/etc/localtime:ro
- /etc/timezone:/etc/timezone:ro
labels:
- traefik.enable=true
- traefik.http.routers.traefik.rule=Host(`$RANCHER_HOSTNAME`) && (PathPrefix(`/traefik`) || HeadersRegexp(`Referer`, `.*/traefik/.*`))
- traefik.http.routers.traefik.service=api@internal
- traefik.http.routers.traefik.tls=true
- traefik.http.routers.traefik.entrypoints=websecure
- traefik.http.routers.traefik.tls.certresolver=cloudflare
- traefik.http.routers.traefik.middlewares=traefik-strip
- traefik.http.routers.traefik-ping.rule=Host(`$RANCHER_HOSTNAME`) && (PathPrefix(`/traefik/ping`) || HeadersRegexp(`Referer`, `.*/traefik/ping`))
- traefik.http.routers.traefik-ping.service=ping@internal
- traefik.http.routers.traefik-ping.tls=true
- traefik.http.routers.traefik-ping.entrypoints=websecure
- traefik.http.routers.traefik-ping.tls.certresolver=cloudflare
- traefik.http.routers.traefik-ping.middlewares=traefik-strip
- traefik.http.routers.traefik-metrics.rule=Host(`$RANCHER_HOSTNAME`) && (PathPrefix(`/traefik/metrics`) || HeadersRegexp(`Referer`, `.*/traefik/metrics`))
- traefik.http.routers.traefik-metrics.service=prometheus@internal
- traefik.http.routers.traefik-metrics.tls=true
- traefik.http.routers.traefik-metrics.entrypoints=websecure
- traefik.http.routers.traefik-metrics.tls.certresolver=cloudflare
- traefik.http.routers.traefik-metrics.middlewares=traefik-strip, metrics-auth
- traefik.http.middlewares.traefik-strip.stripprefix.prefixes=/traefik
- traefik.http.middlewares.metrics-auth.basicauth.usersfile=/.htpasswd
- traefik.http.middlewares.metrics-auth.basicauth.removeheader=true
- traefik.docker.network=traefik-net
node-exporter:
image: docker.io/prom/node-exporter:v1.7.0
container_name: node-exporter
hostname: node-exporter
restart: unless-stopped
security_opt:
- no-new-privileges:true
command:
- --path.rootfs=/rootfs
- --path.sysfs=/host/sys
- --path.procfs=/host/proc
- --collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)
networks:
- node-exporter
environment:
- PUID=1000
- PGID=1000
volumes:
- /:/rootfs:ro
- /sys:/host/sys:ro
- /proc:/host/proc:ro
- /etc/localtime:/etc/localtime:ro
- /etc/timezone:/etc/timezone:ro
labels:
- traefik.enable=true
- traefik.http.routers.node-exporter-metrics.rule=Host(`$RANCHER_HOSTNAME`) && (PathPrefix(`/node-exporter/metrics`) || HeadersRegexp(`Referer`, `.*/node-exporter/metrics`))
- traefik.http.routers.node-exporter-metrics.tls=true
- traefik.http.routers.node-exporter-metrics.entrypoints=websecure
- traefik.http.routers.node-exporter-metrics.tls.certresolver=cloudflare
- traefik.http.routers.node-exporter-metrics.middlewares=node-exporter-strip, metrics-auth
- traefik.http.middlewares.node-exporter-strip.stripprefix.prefixes=/node-exporter
- traefik.http.services.node-exporter.loadbalancer.server.port=9100
- traefik.docker.network=traefik-net
rancher:
image: docker.io/rancher/rancher:v2.8-head
container_name: rancher
hostname: rancher
restart: unless-stopped
privileged: true
security_opt:
- no-new-privileges:true
expose:
- 80
command:
- --no-cacerts
networks:
- rancher
environment:
- CATTLE_BOOTSTRAP_PASSWORD=$CATTLE_BOOTSTRAP_PASSWORD
volumes:
- /var/log:/var/log:rw
- /var/lib/cni:/var/lib/cni:rw
- /var/lib/rancher:/var/lib/rancher:rw
- /var/lib/kubelet:/var/lib/kubelet:rw
- /etc/localtime:/etc/localtime:ro
- /etc/timezone:/etc/timezone:ro
labels:
- traefik.enable=true
- traefik.http.routers.rancher.rule=Host(`$RANCHER_HOSTNAME`)
- traefik.http.routers.rancher.tls=true
- traefik.http.routers.rancher.entrypoints=websecure
- traefik.http.routers.rancher.tls.certresolver=cloudflare
- traefik.docker.network=traefik-net
runcmd:
- systemctl restart sshd
- cat <<EOT>> /home/rancher/.env
- METRICS_AUTH_USER=$(openssl rand -hex 32 | base64 | head -c 32)
- METRICS_AUTH_PASS=$(openssl rand -hex 32 | base64 | head -c 32)
- CATTLE_BOOTSTRAP_PASSWORD=$(openssl rand -hex 32 | base64 | head -c 32)
- EOT
- . /home/rancher/.env
- htpasswd -cb /home/rancher/.htpasswd $METRICS_AUTH_USER $METRICS_AUTH_PASS
- docker plugin install docker.io/grafana/loki-docker-driver:2.9.1 --alias loki --grant-all-permissions
- docker plugin enable loki
- dockerd --config-file /etc/docker/daemon.json
- docker compose -f /home/rancher/docker-compose.yml up -d --wait
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment