i made myself a test environment in icinga2 with a tomcat server. I would like to combine the two softwares rundeck and icinga. My idea is to start a rundeck job, when icinga detects a problem. In my case I have a tomcat server, where i fill up the swap memory, which should start the rundeck job to clear the swap.
I am using the Icinga2 Director for managing. I created an event plugin command, which should execute the rundeck api command as a script, called "rundeckapi". It looks like this:
#/usr/lib64/nagios/plugins/rundeckapi
#!/bin/bash
curl --location --request POST 'rundeck-server:4440/api/38/job/9f04657a-eaab-4e79-a5f3-00d3053f6cb0/run' \
--header 'X-Rundeck-Auth-Token: GuaoD6PtH5BhobhE3bAPo4mGyfByjNya' \
--header 'Content-Type: application/json' \
--header 'Cookie: JSESSIONID=node01tz8yvp4gjkly8kpj18h8u5x42.node0' \
--data-raw '{
"options": {
"IP":"192.168.4.13"
}
}'
(I also tried to just paste the command in the command field in the director, but this didn't work either.)
I placed it in the /usr/lib64/nagios/plugins/ directory and set the configuration in icinga for the command as following:
#zones.d/director-global/command.conf
object EventCommand "SWAP clear" {
import "plugin-event-command"
command = [ PluginDir + "/rundeckapi" ]
}
The service template looks like this:
#zones.d/master/service_templates.conf
template Service "SWAP" {
check_command = "swap"
max_check_attempts= "5"
check_interval = 1m
retry_interval = 15s
check_timeout = 10s
enable_notifications = true
enable_active_checks = true
enable_passive_checks = true
enable_event_handler = true
enable_flapping = true
enable_perfdata = true
event_command = "SWAP clear"
command_endpoint = host_name
}
Then I added the service to the host.
I enabled the debug mode and started to fill the SWAP and watched at the debug.log, with tail -f /var/log/icinga2/debug.log | grep 'event handler' and found this:
notice/Checkable: Executing event handler 'SWAP clear' for checkable 'centos_tomcat_3!SWAP'
The centos_tomcat_3 is the host for testing. IT seems like the event handler is executing the the script, but when I look at the rundeck server, i can't find a running job. When i start the rundeckapi script manually it works and i can see the job on rundeck.
I already read the documentation from icinga, but i didn't help.
I would be very thankful if someone could help me.
Thanks in advance.
Define the plugin as an event handler and assign it to the host.
I tested using this docker environment modified with Rundeck official image + a NGINX host:
version: '2'
services:
icinga2:
#image: jordan/icinga2
build:
context: ./
dockerfile: Dockerfile
restart: on-failure:5
# Set your hostname to the FQDN under which your
# sattelites will reach this container
hostname: icinga2
env_file:
- secrets_sql.env
environment:
- ICINGA2_FEATURE_GRAPHITE=1
# Important:
# keep the hostname graphite the same as
# the name of the graphite docker-container
- ICINGA2_FEATURE_GRAPHITE_HOST=graphite
- ICINGA2_FEATURE_GRAPHITE_PORT=2003
- ICINGA2_FEATURE_GRAPHITE_URL=http://graphite
# - ICINGA2_FEATURE_GRAPHITE_SEND_THRESHOLDS=true
# - ICINGA2_FEATURE_GRAPHITE_SEND_METADATA=false
- ICINGAWEB2_ADMIN_USER=admin
- ICINGAWEB2_ADMIN_PASS=admin
#- ICINGA2_USER_FULLNAME=Icinga2 Docker Monitoring Instance
- DEFAULT_MYSQL_HOST=mysql
volumes:
- ./data/icinga/cache:/var/cache/icinga2
- ./data/icinga/certs:/etc/apache2/ssl
- ./data/icinga/etc/icinga2:/etc/icinga2
- ./data/icinga/etc/icingaweb2:/etc/icingaweb2
- ./data/icinga/lib/icinga:/var/lib/icinga2
- ./data/icinga/lib/php/sessions:/var/lib/php/sessions
- ./data/icinga/log/apache2:/var/log/apache2
- ./data/icinga/log/icinga2:/var/log/icinga2
- ./data/icinga/log/icingaweb2:/var/log/icingaweb2
- ./data/icinga/log/mysql:/var/log/mysql
- ./data/icinga/spool:/var/spool/icinga2
# Sending e-mail
# See: https://github.com/jjethwa/icinga2#sending-notification-mails
# If you want to enable outbound e-mail, edit the file mstmp/msmtprc
# and configure to your corresponding mail setup. The default is a
# Gmail example but msmtp can be used for any MTA configuration.
# Change the aliases in msmtp/aliases to your recipients.
# Then uncomment the rows below
# - ./msmtp/msmtprc:/etc/msmtprc:ro
# - ./msmtp/aliases:/etc/aliases:ro
ports:
- "80:80"
- "443:443"
- "5665:5665"
graphite:
image: graphiteapp/graphite-statsd:latest
container_name: graphite
restart: on-failure:5
hostname: graphite
volumes:
- ./data/graphite/conf:/opt/graphite/conf
- ./data/graphite/storage:/opt/graphite/storage
- ./data/graphite/log/graphite:/var/log/graphite
- ./data/graphite/log/carbon:/var/log/carbon
mysql:
image: mariadb
container_name: mysql
env_file:
- secrets_sql.env
volumes:
- ./data/mysql/data:/var/lib/mysql
# If you have previously used the container's internal DB use:
#- ./data/icinga/lib/mysql:/var/lib/mysql
rundeck:
image: rundeck/rundeck:3.3.12
hostname: rundeck
ports:
- '4440:4440'
nginx:
image: nginx:alpine
hostname: nginx
ports:
- '81:80'
Rundeck side:
To access Rundeck open a new tab in your browser using the http://localhost:4440 web address. You can access with user: admin and password: admin.
Create a new project and create a new job, I created the following one, you can import it to your instance:
- defaultTab: nodes
description: ''
executionEnabled: true
id: c3e0860c-8f69-42f9-94b9-197d0706a915
loglevel: INFO
name: RestoreNGINX
nodeFilterEditable: false
options:
- name: opt1
plugins:
ExecutionLifecycle: null
scheduleEnabled: true
sequence:
commands:
- exec: echo "hello ${option.opt1}"
keepgoing: false
strategy: node-first
uuid: c3e0860c-8f69-42f9-94b9-197d0706a915
Now go to the User Icon (up to right) > Profile, now click on the + icon ("User API Tokens" section) and save the API key string, useful to create the API call script from the Icinga2 container.
Go to the Activity page (left menu) and click on the "Auto Refresh" checkbox.
Incinga2 side:
You can enter Icinga 2 by opening a new tab in your browser using the http://localhost URL, I defined username: admin and password: admin in the docker-compose file.
Add the following script as a command at /usr/lib/nagios/plugins path with the following content (it's a curl api call like your scenario, the API key is the same generated in the third step from "Rundeck side" section of this step-by-step):
#!/bin/bash
curl --location --request POST 'rundeck:4440/api/38/job/c3e0860c-8f69-42f9-94b9-197d0706a915/run' --header 'X-Rundeck-Auth-Token: Zf41wIybwzYhbKD6PrXn01ZMsV2aT8BR' --header 'Content-Type: application/json' --data-raw '{ "options": { "opt1": "world" } }'
Also make the script executable: chmod +x /usr/lib/nagios/plugin/restorenginx
In the Icinga2 browser tab, go to the Icinga Director (Left Menu) > Commands. On the "Command Type" list select "Event Plugin Command", on the "Command Name" textbox type "restorenginx" and on the "Command" textbox put the full path of the script (/usr/lib/nagios/plugins/restorenginx). Then click on the "Store" button (bottom) and now click on Deploy (up).
Check how looks.
This is the config preview (at zones.d/director-global/commands.conf):
object EventCommand "restorenginx" {
import "plugin-event-command"
command = [ "/usr/lib/nagios/plugins/restorenginx" ]
}
Now, create the host template (In my example I'm using an Nginx container to monitoring), go to Icinga Director (Left Menu) > Hosts, and select "Host Templates". Then click on the + Add link (up). On the Name type the host template name, I used "nginxSERVICE", on the "check command" textbox put the command to check the host alive (I used "ping"). Now in the Event command textbox select the Command created in the previous step.
Check how looks.
Now it's time to create the host (based on the previous steps template). Go to Icinga Direcrector (Left Menu) > Hosts and select "Host". Then click on the + Add link (up). On the hostname type the server hostname (nginx, defined on the docker-compose file), In "Imports" select the template is created in the previous step ("nginxSERVICE"), type anything on the "Display name" textbox, and in the "Host address" add the Nginx container IP. Click on the "Store" button" and then on the "Deploy" link at the top.
Check how looks.
To enable the Event Hander on the host, go to the "Overview" (Left menu) > Hosts, select "NGINX", scroll down on the right section and enable "Event Handler" on the "Feature Commands" section.
Check how looks.
Nginx side (it's time to test the script):
Stop the container and go to the Rundeck Activity page browser tab, you'll see the job launched by the Icinga2 monitoring tool.
Related
PS: cross posted on drone forums here.
I'm trying to setup s3 like service for drone logs. i've tested that my AWS_* values are set correctly in the container and using aws-cli from inside container gives correct output for:
aws s3api list-objects --bucket drone-logs --endpoint-url=https://storage.googleapis.com
however, drone server itself is unable to upload logs to the bucket (with following error):
{"error":"InvalidArgument: Invalid argument.\n\tstatus code: 400, request id: , host id: ","level":"warning","msg":"manager: cannot upload complete logs","step-id":7,"time":"2023-02-09T12:26:16Z"}
drone server on startup shows that s3 related configuration was picked correctly:
rpc:
server: ""
secret: my-secret
debug: false
host: drone.XXXXXXXXXXXXXXXXXXXXXXXXXXXXX
proto: https
s3:
bucket: drone-logs
prefix: ""
endpoint: https://storage.googleapis.com
pathstyle: true
the env. vars inside droner server container are:
# env | grep -E 'DRONE|AWS' | sort
AWS_ACCESS_KEY_ID=GOOGXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
AWS_DEFAULT_REGION=us-east-1
AWS_REGION=us-east-1
AWS_SECRET_ACCESS_KEY=XXXXXXXXXXXXXXXXXXXXXXXXXXXXX
DRONE_COOKIE_SECRET=XXXXXXXXXXXXXXXXXXXXXXXXXXXXX
DRONE_DATABASE_DATASOURCE=postgres://drone:XXXXXXXXXXXXXXXXXXXXXXXXXXXXX#35.XXXXXX.XXXX:5432/drone?sslmode=disable
DRONE_DATABASE_DRIVER=postgres
DRONE_DATABASE_SECRET=XXXXXXXXXXXXXXXXXXXXXXXXXXXXX
DRONE_GITHUB_CLIENT_ID=XXXXXXXXXXXXXXXXXXXXXXXXXXXXX
DRONE_GITHUB_CLIENT_SECRET=XXXXXXXXXXXXXXXXXXXXXXXXXXXXX
DRONE_JSONNET_ENABLED=true
DRONE_LOGS_DEBUG=true
DRONE_LOGS_TRACE=true
DRONE_RPC_SECRET=XXXXXXXXXXXXXXXXXXXXXXXXXXXXX
DRONE_S3_BUCKET=drone-logs
DRONE_S3_ENDPOINT=https://storage.googleapis.com
DRONE_S3_PATH_STYLE=true
DRONE_SERVER_HOST=drone.XXXXXXXXXXXXXXXXXXXXXXXXXXXXX
DRONE_SERVER_PROTO=https
DRONE_STARLARK_ENABLED=true
the .drone.yaml that is being used is available here, on github.
the server is running using the nolimit flag:
go build -tags "nolimit" github.com/drone/drone/cmd/drone-server
I'm starting to learn Ansible and for this I copy and paste examples from the documentation. For example this one
- name: Check that a page returns a status 200 and fail if the word AWESOME is not in the page contents
ansible.builtin.uri:
url: http://www.example.com
return_content: yes
register: this
failed_when: "'AWESOME' not in this.content"
which I've found in uri module documentation.
Every single time I do this, whatever the module I get:
ERROR! 'ansible.builtin.uri' is not a valid attribute for a Play
The error appears to have been in '/home/alfrerra/test2.yml': line 1, column 3, but may
be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
- name: Check that a page returns a status 200 and fail if the word AWESOME is not in the page contents
^ here
I have only 2 playbooks that only ping successfully:
-
name: ping localhost
hosts: localhost
tasks:
- name: ping test
ping
and
---
- name: ping localhost
hosts: localhost
tasks:
- name: ping test
ping
So I adapted the example to match these 2 examples, but to no avail so far.
I'm sure it's nothing much but it's driving me crazy.
As already mentioned within the comments, the documentation are to show how to use certain parameter of certain modules within a single task. They are not mentioned to work in a copy and paste manner by itself or only.
You may have a look into the following minimal example playbook
---
- hosts: localhost
become: false
gather_facts: false
tasks:
- name: Check that a page returns a status 200 and fail if the word 'iana.org' is not in the page contents
uri:
url: http://www.example.com
return_content: yes
environment:
http_proxy: "localhost:3128"
https_proxy: "localhost:3128"
register: this
failed_when: "'iana.org' not in this.content"
- name: Show content
debug:
msg: "{{ this.content }}"
resulting into the output of the page content.
Please take note that the web page of the example domain is connected and delivers a valid result, but it does not contain the word AWESOME. To address this the string to lookup was changed to the page owner iana.org and to not let the task fail. Furthermore and since working behind a proxy it was necessary to address the proxy configuration and which you probably need to remove again.
Your first example is a single task and failing therefore with ERROR! ... not a valid attribute for a Play. Your second and
third examples are playbooks with a single task and therefore executing.
Documentation
Module format and documentation - EXAMPLES block
... show users how your module works with real-world examples in multi-line plain-text YAML format. The best examples are ready for the user to copy and paste into a playbook.
Ansible playbooks
failed_when must be a comparison or a boolean.
example :
- name: Check that a page returns AWESOME is not in the page contents
ansible.builtin.uri:
url: http://www.example.com
return_content: yes
register: this
failed_when: this.rc == 0;
It will execute the task only if the return value is equal to 0
I have an instance of MuleSoft's Flex Gateway (v 1.2.0) installed on a Linux machine in a podman container. I am trying to forward container as well as API logs to Splunk. Below is my log.yaml file in /home/username/app folder. Not sure what I am doing wrong, but the logs are not getting forwarded to Splunk.
apiVersion: gateway.mulesoft.com/v1alpha1
kind: Configuration
metadata:
name: logging-config
spec:
logging:
outputs:
- name: default
type: splunk
parameters:
host: <instance-name>.splunkcloud.com
port: "443"
splunk_token: xxxxx-xxxxx-xxxx-xxxx
tls: "on"
tls.verify: "off"
splunk_send_raw: "on"
runtimeLogs:
logLevel: info
outputs:
- default
accessLogs:
outputs:
- default
Please advise.
The endpoint for Splunk's HTTP Event Collector (HEC) is https://http-input.<instance-name>.splunkcloud.com:443/services/collector/raw. If you're using a free trial of Splunk Cloud then change the port number to 8088. See https://docs.splunk.com/Documentation/Splunk/latest/Data/UsetheHTTPEventCollector#Send_data_to_HTTP_Event_Collector_on_Splunk_Cloud_Platform for details.
I managed to get this work. The issue was that I had to give full permissions to the app folder using "chmod" command. After it was done, the fluent-bit.conf file had an entry for Splunk and logs started flowing.
Error: I won't open a connection to 127.0.0.1 (only to 172.20.0.1) (code=500)
My docker file is as below, I have tried passive ports range too but not sure about --expose here, I am able to connect at first through my code but at a second attempt or reusing it is throwing the above error.
I understand it has something with the passive mode but I have the configuration but not sure what is missing, please help.
version: '3'
services:
ftpd_server:
image: stilliard/pure-ftpd
container_name: pure-ftpd
privileged: true
ports:
- "21:21"
- "30000-30099:30000-30099"
volumes: # remember to replace /folder_on_disk/ with the path to where you want to store the files on the host machine
#- "/tmp/test/data:/home/username/"
#- "/tmp/test/passwd:/etc/pure-ftpd/passwd"
- "/upload:/home/upload"
#- "./certs:/etc/ssl/private"
environment:
PUBLICHOST: "localhost"
FTP_USER_NAME: lktransfer
FTP_USER_PASS: lktransfer
FTP_USER_HOME: /home/upload/
#FTP_PASSIVE_PORTS: "30000-30009"
FTP_MAX_CLIENTS: 50
FTP_PASSIVE_PORTS: 30000:30099
FTP_MAX_CONNECTIONS: 50
ADDED_FLAGS: "--tls=1"
#ADDED_FLAGS: "--tls=2"
TLS_USE_DSAPRAM: "true"
TLS_CN: "localhost"
TLS_ORG: "Ellkay"
TLS_C: "IN"
restart: always
Heroku currently provides the database credentials as one connection string i.e: postgres://foo:bar#baz/fubarDb.
My development environment consists of a PostgreSQL container and an app container orchestrated with a docker-compose file. The docker-compose file supplies environment variables from .env file which currently looks a little like this:
DB_USER=foo
DB_PASS=bar
DB_HOST=baz
These credentials are passed to my app as environment variables and all is well. The problem is that in order to make this work, I have to have a null check in my db connection info to see if there is a full database URL and use that...otherwise fall back to individual credentials....
D'oh! So, it turns out the solution, was to modify my docker-compose file to take the environment variables and concatenate them into a connection string thusly:
diff --git a/docker-compose.yml b/docker-compose.yml
index 21f0d47..74a574e 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
## -16,14 +16,10 ## services:
context: .
target: base
environment:
- - APP_NAME
- - DB_HOST
- - DB_PORT
- - DB_NAME
- - DB_USER
- - DB_PASS
- - NODE_ENV
- - PORT
+ APP_NAME: ${APP_NAME}
+ NODE_ENV: ${NODE_ENV}
+ PORT: ${PORT}
+ DATABASE_URL: postgres://${DB_USER}:${DB_PASS}#${DB_HOST}:${DB_PORT}/${DB_NAME}
user: "1000:1000"
ports:
- "127.0.0.1:${PORT}:${PORT}"
No more trying to guess which environment variables to look for!