Getting container host metrics when running Telegraf inside Docker - telegraf

I've got a docker compose service with a bunch of containers and I am attempting to collect both the docker container metrics from these containers but also the container host metrics from the Ubuntu server the containers are running on. I'm getting the docker container stats but I am not getting the Ubuntu container host metrics. The stats from the non-docker based input plugins (inputs.diskio,inputs.mem, etc) are from the telegraf container.
I found this and opened up the volumes but still nothing: https://community.influxdata.com/t/how-can-we-collect-host-machine-metrics-while-telegraf-is-running-in-docker-container/12005
Here is my compose file:
version: "3"
services:
telegraf:
image: telegraf:1.20.3
volumes:
- ./telegraf.conf:/etc/telegraf/telegraf.conf:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- /sys:/rootfs/sys:ro
- /proc:/rootfs/proc:ro
- /etc:/rootfs/etc:ro
environment:
HOST_PROC: /rootfs/proc
HOST_SYS: /rootfs/sys
HOST_ETC: /rootfs/etc
vote:
build: ./vote
# use python rather than gunicorn for local dev
command: python app.py
depends_on:
- redis
volumes:
- ./vote:/app
ports:
- "5000:80"
networks:
- front-tier
- back-tier
result:
build: ./result
# use nodemon rather than node for local dev
command: nodemon server.js
depends_on:
- db
volumes:
- ./result:/app
ports:
- "5001:80"
- "5858:5858"
networks:
- front-tier
- back-tier
worker:
build:
context: ./worker
depends_on:
- redis
- db
networks:
- back-tier
redis:
image: redis:5.0-alpine3.10
volumes:
- "./healthchecks:/healthchecks"
healthcheck:
test: /healthchecks/redis.sh
interval: "5s"
ports: ["6379"]
networks:
- back-tier
db:
image: postgres:9.4
environment:
POSTGRES_USER: "postgres"
POSTGRES_PASSWORD: "postgres"
volumes:
- "db-data:/var/lib/postgresql/data"
- "./healthchecks:/healthchecks"
healthcheck:
test: /healthchecks/postgres.sh
interval: "5s"
networks:
- back-tier
volumes:
db-data:
networks:
front-tier:
back-tier:
Here is the agent config:
[agent]
interval = "10s"
[[inputs.mem]]
[[inputs.disk]]
## Ignore mount points by filesystem type.
ignore_fs = ["tmpfs", "devtmpfs", "devfs", "iso9660", "overlay", "aufs", "squashfs"]
[[inputs.diskio]]
[[inputs.kernel]]
[[inputs.ethtool]]
[[inputs.procstat]]
pattern = ".*"
[[inputs.docker]]
endpoint = "unix:///var/run/docker.sock"
gather_services = false
container_names = []
source_tag = true
container_name_include = []
container_name_exclude = []
timeout = "5s"
perdevice = true
docker_label_include = []
docker_label_exclude = []
[[inputs.cpu]]
percpu = true
totalcpu = true
collect_cpu_time = true
report_active = true
How do I get the container host metrics??

Related

fluent-bit to Loki - "log" field is not being parsed/filtered

I have:
a simple Python app ("iss-web") writing JSON log output to stdout
the Python app ("iss-web") is within a Docker Container
the Python app ("iss-web") Container logging driver is set to "fluentd"
a separate Container running "fluent/fluent-bit:1.7" to collect the Python app JSON log output
Loki 2.2.1 deployed via a Container to receive the Python app log output from fluent-bit
Grafana connected to Loki to visualize the log data
The issue is that the "log" field is not filtered/parsed by fluent-bit, therefore in Loki/Grafana the content of the "log" field is not parsed and used as "Detected fields".
"iss-web" docker-compose.yml
version: '3'
services:
iss-web:
build: ./iss-web
image: iss-web
container_name: iss-web
env_file:
- ./iss-web/app.env
ports:
- 46664:46664
logging:
driver: fluentd
options:
tag: iss.web
redis:
image: redis
container_name: redis
ports:
- 6379:6379
logging:
driver: "json-file"
options:
max-file: ${LOG_EXPIRE}
max-size: ${LOG_SEGMENT}
"fluent-bit" docker-compose.yml
version: '3'
services:
fluent-bit:
image: fluent/fluent-bit:1.7
container_name: fluent-bit
environment:
- LOKI_URL=http://135.86.186.75:3100/loki/api/v1/push
user: root
volumes:
- ./fluent-bit.conf:/fluent-bit/etc/fluent-bit.conf
- ./parsers.conf:/fluent-bit/etc/parsers.conf
ports:
- "24224:24224"
- "24224:24224/udp"
fluent-bit.conf
[SERVICE]
Flush 1
Daemon Off
log_level debug
Parsers_File /fluent-bit/etc/parsers.conf
[INPUT]
Name forward
Listen 0.0.0.0
port 24224
[FILTER]
Name parser
Match iss.web
Key_Name log
Parser docker
Reserve_Data On
Preserve_Key On
[OUTPUT]
Name loki
Match *
host 135.86.186.75
port 3100
labels job=fluentbit
[OUTPUT]
Name stdout
Match *
parsers.conf
I've tried with/without Time_Key, Time_Format, Time_Keep
[PARSER]
Name docker
Format json
#Time_Key time
#Time_Format %Y-%m-%dT%H:%M:%S.%L
#Time_Keep On
# Command | Decoder | Field | Optional Action
# =============|==================|=================
#Decode_Field_As escaped_utf8 log do_next
Decode_Field_As json log
fluent-bit log extract
[0] iss.web: [1620640820.000000000, {"log"=>"{'timestamp': '2021:05:10 11:00:20.439513', 'epoch': 1620640820.4395688, 'pid': 1, 'level': 'DEBUG', 'message': '/ping', 'data': {'message': 'PONG', 'timestamp': '1620640820.4394963', 'version': '0.1'}}", "container_id"=>"bffd720e9ac1e8c3992c1120eed37e00c536cd44ec99e9c13cf690d840363f80", "container_name"=>"/iss-web", "source"=>"stdout"}]
Grafana/Loki screen
I would expect the "Detected fields" to contain pid=1, message=/ping etc
I needed a "json.dumps" in my "logger":
def log(message, level="INFO", **extra):
out = {"timestamp": get_now(), "epoch": get_epoch(), "pid": get_pid(), "level": level, "message": message}
if extra: out |= extra
print(json.dumps(out), flush=True)
return True

docker-compose.yml, network must be a mapping, not an array

Not sure how the yaml indentation works , getting an error, while define an external network for the app to communicate
./docker-compose.yml', network must be a mapping, not an array
version : '3'
services:
zmq_sub:
image: zmq_sub
zmq_pub:
image: zmq_pub
depends_on:
- zmq_sub
networks:
- zmq_network:
external: true
Mind the difference in syntax between the stanzas for each container, versus the listing of volumes and networks at the end:
<...snip...>
volumes:
- "database-volume:/var/lib/postgresql/data" ## <---- dash !
networks:
- foo ### <---- dash!
- private ### <----- dash!
volumes:
foovol: # NO dash!
barvol: # NO dash!
networks:
dntp: # NO dash!
private: # NO dash!
version : '3'
services:
zmq_sub:
image: zmq_sub
zmq_pub:
image: zmq_pub
depends_on:
- zmq_sub
networks:
zmq_network:
external: true
It is expecting a key:value pair, but you have added a dash before zmq_network. So,removing it might help.
version: "3.8"
services:
my_app:
image: some_image
networks:
- ingress
networks:
ingress:
name: existing_docker_network
external: true
Or using default stack network name
version: "3.8"
services:
my_app:
image: some_image
networks:
default:
name: existing_docker_network
external: true
It seems to me that you are using old docker-compose format (~2) for new version (3)

Basic auth is not working for Traefik v2.1

my issue is that I cannot set the basic authentication for my frontend app throught traefik
This is how I have configured my traefik
traefik.yml
global:
checkNewVersion: true
sendAnonymousUsage: false
entryPoints:
https:
address: :443
http:
address: :80
traefik:
address: :8080
tls:
options:
foo:
minVersion: VersionTLS12
cipherSuites:
- "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"
- "TLS_RSA_WITH_AES_256_GCM_SHA384"
providers:
providersThrottleDuration: 2s
docker:
watch: true
endpoint: unix:///var/run/docker.sock
exposedByDefault: false
network: web
api:
insecure: true
dashboard: true
log:
level: INFO
certificatesResolvers:
default:
acme:
storage: /acme.json
httpChallenge:
entryPoint: http
docker-compose.yml
version: '3'
services:
traefik:
image: traefik:v2.0
restart: always
ports:
- "80:80"
- "443:443"
- "8080:8080"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
- "/srv/traefik/traefik.yml:/etc/traefik/traefik.yml"
- "/srv/traefik/acme.json:/acme.json"
networks:
- web
networks:
web:
external: true
And here is where I have my frontend app running as a traefik provider and where I have my basic auth label
version: '3.7'
services:
frontend:
image: git.xxxx.com:7000/dockerregistry/registry/xxxx
restart: "always"
networks:
- web
volumes:
- "/srv/config/api.js:/var/www/htdocs/api.js"
- "/srv/efs/workspace:/var/www/htdocs/stock"
labels:
- traefik.enable=true
- traefik.http.routers.frontend-http.rule=Host(`test.xxxx.com`)
- traefik.http.routers.frontend-http.service=frontend
- traefik.http.routers.frontend-http.entrypoints=http
- traefik.http.routers.frontend.tls=true
- traefik.http.routers.frontend.tls.certresolver=default
- traefik.http.routers.frontend.entrypoints=http
- traefik.http.routers.frontend.rule=Host(`test.xxxx.com`)
- traefik.http.routers.frontend.service=frontend
- traefik.http.middlewares.frontend.basicAuth.users=test:$$2y$$05$$c45HvbP0Sq9EzcfaXiGNsuuWMfPhyoFZVYgiTylpMMLtJY2nP1P6m
- traefik.http.services.frontend.loadbalancer.server.port=8080
networks:
web:
external: true
I cannot get the login prompt, so Im wondering if I missing some container label for this.
Thanks in advance! Joaquin
firstly , the labels should be in quotation marks like this ""
secondly, I think you are missing a label in the frontend app .
when using basic auth it takes two steps and should look like this :
- "traefik.http.routers.frontend.middlewares=frontend-auth"
- "traefik.http.middlewares.frontend-auth.basicauth.users=test:$$2y$$05$$c45HvbP0Sq9EzcfaXiGNsuuWMfPhyoFZVYgiTylpMMLtJY2nP1P6m"
In your Docker Compose file don't add the "middlewares" label for traefik, instead do it using a traefik.yml file passing the providers.file option, where you should define the routers, services, middlewares, etc. In that "providers file" you should set middlewares under http.routes.traefik – This may sound super confuse at the beginning but is not that hard, trust me.
Let's do a YAML case (you can convert it to "TOML" here).
This example assumes you have a Docker Compose file specifically for Traefik – I haven't tried using the same Docker Compose file with any other services in it (like Wordpress, databases or whatever) since I already have a different path for those files.
docker-compose.yml
version: '3.1'
services:
reverse-proxy:
image: traefik:v2.4
[ ... ]
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
# Map the dynamic conf into the container
- ./traefik/config.yml:/etc/traefik/config.yml:ro
# Map the static conf into the container
- ./traefik/traefik.yml:/etc/traefik/traefik.yml:ro
# Note you don't use "traefik.http.routers.<service>.middlewares etc." here
[ ... ]
In this case I set/get the config files for Traefik in ./traefik (relative to the docker-compose.yml file).
./traefik/config.yml
http:
routers:
traefik:
middlewares: "basicauth"
[ ... ]
middlewares:
basicauth:
basicAuth:
removeHeader: true
users:
- <user>:<password>
# password should be generated using `htpasswd` (md5, sha1 or bcrypt)
[ ... ]
Here you can set the basicauth name as you wish (since that's the middleware name you'll see in the Dashboard), so you could do:
http:
routers:
traefik:
middlewares: "super-dashboard-auth"
[ ... ]
middlewares:
super-dashboard-auth:
basicAuth:
removeHeader: true
users:
- <user>:<password>
# password should be generated using `htpasswd` (md5, sha1 or bcrypt)
[ ... ]
Note that basicAuth must remain as is. Also, here you don't need to use the "double dollar method" to scape it (as in the label approach), so after creating the user password you should enter it exactly like htpasswd created it.
# BAD
user:$$2y$$10$$nRLqyZT.64JI/CD/ym65UGDn8HaY0D6CBTxhe6JXf9u4wi5bEMdh.
# GOOD
user:$2y$10$nRLqyZT.64JI/CD/ym65UGDn8HaY0D6CBTxhe6JXf9u4wi5bEMdh.
Of course you may want to get this data from an .env file and not hardcode those strings, in that case you need to pass the environmental variable from the docker-compose.yml using environment like this:
services:
reverse-proxy:
image: traefik:v2.4
container_name: traefik
[ ... ]
environment:
TRAEFIK_DASHBOARD_USER: "${TRAEFIK_DASHBOARD_USER}"
TRAEFIK_DASHBOARD_PWD: "${TRAEFIK_DASHBOARD_PWD}"
# And any other env. var. you may need
[ ... ]
and use it like this in you traefik/config.yml file:
[ ... ]
middlewares:
super-dashboard-auth:
basicAuth:
removeHeader: true
users:
- "{{env "TRAEFIK_DASHBOARD_USER"}}:{{env "TRAEFIK_DASHBOARD_PWD"}}"
[ ... ]
After that include the previous file in the providers.file.filename
./traefik/traefik.yml
[ ... ]
api:
dashboard: true
insecure: false
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
[ ... ]
file:
filename: /etc/traefik/config.yml
watch: true
[ ... ]
And then simply docker-compose up -d
I configure it this way:
generate password by apache2-utils e.g.
htpasswd -nb admin secure_password
setup traefik.toml
[entryPoints]
[entryPoints.web]
address = ":80"
[entryPoints.web.http.redirections.entryPoint]
to = "websecure"
scheme = "https"
[entryPoints.websecure]
address = ":443"
[api]
dashboard = true
[certificatesResolvers.lets-encrypt.acme]
email = "your_email#your_domain"
storage = "acme.json"
[certificatesResolvers.lets-encrypt.acme.tlsChallenge]
[providers.docker]
watch = true
network = "web"
[providers.file]
filename = "traefik_dynamic.toml"
setup traefik_dynamic.toml
[http.middlewares.simpleAuth.basicAuth]
users = [
"admin:$apr1$ruca84Hq$mbjdMZBAG.KWn7vfN/SNK/"
]
[http.routers.api]
rule = "Host(`monitor.your_domain`)"
entrypoints = ["websecure"]
middlewares = ["simpleAuth"]
service = "api#internal"
[http.routers.api.tls]
certResolver = "lets-encrypt"
setup traefik service
services:
reverse-proxy:
image: traefik:v2.3
restart: always
command:
- --api.insecure=true
- --providers.docker
ports:
- "80:80"
- "443:443"
networks:
- web
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./traefik.toml:/traefik.toml
- ./traefik_dynamic.toml:/traefik_dynamic.toml
- ./acme.json:/acme.json
Regarding this part of the documentation.
If you are using Docker scripts for settings.
Configure as the following.
For example:
labels:
- "traefik.http.middlewares.foo-add-prefix.addprefix.prefix=/foo"
- "traefik.http.routers.router1.middlewares=foo-add-prefix#docker"
I had same issue and I was missing namespace name #docker in the middleware name.

Traefik not trusting ssl certificate

I have had success in both instantiating a traefik container, as well as 4 other nginx containers to serve applications that route my subdomains to each individual service. The routing works, and I am using [acme] for certificate generation, but everytime i try to go to any of my subdomains chrome still gives me an error saying "this connection isn't trusted", and then I have to hit advanced and proceed. The individual applications load fine, but there's something wrong with the certificates.
I have tried clearing the acme.json file to no avail. I had also played around with enabling onDemand in the traefick.toml but that didn't work either.
Please help?
traefik.toml
# defaultEntryPoints must be at the top
# because it should not be in any table below
defaultEntryPoints = ["http", "https"]
# Entrypoints, http and https
[entryPoints]
# http should be redirected to https
[entryPoints.http]
address = ":80"
[entryPoints.http.redirect]
entryPoint = "https"
# https is the default
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
# Enable ACME (Let's Encrypt): automatic SSL
[acme]
email = "chris#myubercode.com"
storage = "./acme.json"
entryPoint = "https"
OnHostRule = true
acmeLogging = true
caServer = "https://acme-v02.api.letsencrypt.org/directory"
[acme.httpChallenge]
entryPoint = "http"
[acme.dnsChallenge]
provider = "digitalocean"
delayBeforeCheck = 0
[[acme.domains]]
main = "cswilson.site"
sans = ["profile.cswilson.site", "ecommerce.cswilson.site", "fitness.cswilson.site", "biosite.cswilson.site"]
traefikLogsFile = "/tmp/traefik.log"
logLevel = "DEBUG"
[accessLog]
filePath = "/tmp/access.log"
[docker]
endpoint = "unix:///var/run/docker.sock"
domain = "cswilson.site"
watch = true
exposedbydefault = false
docker-compose.yml (for the traefik container):
version: '3'
services:
traefik:
image: traefik
command: --docker
ports:
- "80:80"
- "443:443"
restart: always
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
- "./traefik.toml:/traefik.toml"
- "./acme.json:/acme.json"
networks:
- default
And here is the docker-compose.yml for the 4 different application containers:
version: '3'
services:
profile:
build: .
image: nginx
labels:
- "traefik.enabled=true"
- "traefik.backend=profile"
- "traefik.frontend.rule=Host:profile.cswilson.site"
- "traefik.frontend.entryPoinst=http,https"
restart: always
networks:
- "traefik_default"
fitness:
build: .
image: nginx
labels:
- "traefik.enabled=true"
- "traefik.backend=fitness"
- "traefik.frontend.rule=Host:fitness.cswilson.site"
- "traefik.frontend.entryPoinst=http,https"
restart: always
networks:
- "traefik_default"
ecommerce:
build: .
image: nginx
labels:
- "traefik.enabled=true"
- "traefik.backend=ecommerce"
- "traefik.frontend.rule=Host:ecommerce.cswilson.site"
- "traefik.port=80"
restart: always
networks:
- "traefik_default"
biosite:
build: .
image: nginx
labels:
- "traefik.enabled=true"
- "traefik.backend=ecommerce"
- "traefik.frontend.rule=Host:biosite.cswilson.site"
- "traefik.port=80"
restart: always
networks:
- "traefik_default"
networks:
traefik_default:
external:
name: traefik_default
I am new to docker and just found traefik this morning, and I don't really know if I need some sort of a real certificate to put into
[[entryPoints.http.tls.certificates]]
Any help is greatly appreciated, thank you

How to resolve service names in a Docker Swarm?

I am playing around with Docker and stuff, using this docker-compose.yml:
version: '3.4'
services:
frontend:
image: apmimg:latest
networks:
- core-infra
ports:
- 8080:80
deploy:
replicas: 2
update_config:
parallelism: 2
delay: 10s
restart_policy:
condition: on-failure
backend:
image: productsapi:latest
volumes:
- myvol:/opt/myvol
networks:
- core-infra
deploy:
replicas: 2
update_config:
parallelism: 2
delay: 10s
restart_policy:
condition: on-failure
networks:
core-infra:
driver: overlay
volumes:
myvol:
driver: local
And when I ssh into frontend and ping backend "ping mysite_backend" it does work.
But when I try to make a HTTP request from my Node.js code:
private _productUrl = "http://mysite_backend/api/products";
getProducts(): Observable<IProduct[]>
{
let url = this._productUrl;
return this._http.get<IProduct[]>(url)
.do(data => console.log('All: ' + JSON.stringify(data)))
.catch(this.handleError);
}
I get a "Failed to load resource: net::ERR_NAME_NOT_RESOLVED", even in the same host.
Any ideas on what's wrong?

Resources