This guide provides a complete Ansible playbook to install Performance Co-Pilot (PCP) from official packages with proper configuration for system metrics collection, visualization, and alerting.
Current PCP version: 6.0+ (varies by distribution)
Create a file named pcp.yml:
---
- name: Install and Configure Performance Co-Pilot
hosts: pcp
become: true
vars:
pcp_port: 44321
pcp_web_port: 44322
pcp_config_dir: "/etc/pcp"
pcp_data_dir: "/var/log/pcp"
tasks:
- name: Install PCP (Debian/Ubuntu)
apt:
name:
- pcp
- pcp-system-tools
- pcp-webapp-grafana
- pcp-webapp-vector
state: present
update_cache: true
when: ansible_os_family == "Debian"
- name: Install PCP (RHEL/CentOS)
yum:
name:
- pcp
- pcp-system-tools
- pcp-webapp-grafana
- pcp-webapp-vector
state: present
when: ansible_os_family == "RedHat"
- name: Enable and start PCP services
systemd:
name: "{{ item }}"
enabled: true
state: started
daemon_reload: true
loop:
- pmcd
- pmlogger
- pmie
- name: Configure PCP web interface
lineinfile:
path: "{{ pcp_config_dir }}/webapp/webconfig.json"
regexp: '"port":'
line: ' "port": {{ pcp_web_port }},'
failed_when: false
- name: Configure firewall (UFW)
ufw:
rule: allow
port: "{{ item }}"
proto: tcp
comment: "PCP service"
loop:
- "{{ pcp_port }}"
- "{{ pcp_web_port }}"
when: ansible_os_family == "Debian"
failed_when: false
- name: Configure firewall (firewalld)
firewalld:
port: "{{ item }}/tcp"
permanent: true
immediate: true
state: enabled
loop:
- "{{ pcp_port }}"
- "{{ pcp_web_port }}"
when: ansible_os_family == "RedHat"
failed_when: false
- name: Verify PMCD is running
command: pmcd -v
register: pmcd_check
changed_when: false
failed_when: false
- name: Display PCP status
debug:
msg: |
Performance Co-Pilot installed successfully!
PMCD Port: {{ pcp_port }}
Web Interface: http://{{ ansible_default_ipv4.address | default(ansible_host) }}:{{ pcp_web_port }}
Data directory: {{ pcp_data_dir }}
Configuration directory: {{ pcp_config_dir }}
Useful commands:
- pminfo: List available metrics
- pmval: Display metric values
- pmchart: Graphical metrics display
- pmlogger: Metrics logging
---
pcp:
hosts:
pcp-server:
ansible_host: 192.168.1.115
ansible_user: ansible
ansible_become: true
# Test connectivity
ansible all -i inventory.yml -m ping
# Run the PCP playbook
ansible-playbook -i inventory.yml pcp.yml
# Check PMCD status
ssh pcp-server "sudo systemctl status pmcd"
# List available metrics
ssh pcp-server "pminfo -f"
# Display metric values
ssh pcp-server "pmval kernel.all.load"
# Access web UI
# http://pcp-server:44322
- name: Configure PCP alerting with PMIE
hosts: pcp
become: true
tasks:
- name: Create PMIE configuration directory
file:
path: /etc/pcp/pmie
state: directory
owner: root
group: root
mode: '0755'
- name: Create high CPU alert rule
copy:
dest: /etc/pcp/pmie/cpu-high.rule
owner: root
group: root
mode: '0644'
content: |
# High CPU Usage Alert
# Trigger when CPU usage exceeds 80% for 5 minutes
if (kernel.all.load > 4)
then
@send_mail("admin@example.com", "High CPU Load Alert",
"CPU load on {{ ansible_hostname }} is {{ kernel.all.load }}")
end
- name: Create high memory alert rule
copy:
dest: /etc/pcp/pmie/memory-high.rule
owner: root
group: root
mode: '0644'
content: |
# High Memory Usage Alert
# Trigger when memory usage exceeds 90%
if (mem.util.available < 10 * mem.physmem)
then
@send_mail("admin@example.com", "High Memory Usage Alert",
"Memory usage on {{ ansible_hostname }} is critical")
end
- name: Create disk space alert rule
copy:
dest: /etc/pcp/pmie/disk-full.rule
owner: root
group: root
mode: '0644'
content: |
# Disk Space Alert
# Trigger when disk usage exceeds 90%
if (filesystem.full.used > 90 * filesystem.full.total / 100)
then
@send_mail("admin@example.com", "Disk Space Alert",
"Disk usage on {{ ansible_hostname }} is above 90%")
end
- name: Enable PMIE service
systemd:
name: pmie
enabled: true
state: restarted
- name: Configure email for PMIE alerts
lineinfile:
path: /etc/pcp/config
regexp: "^PCP_MAIL_TO="
line: 'PCP_MAIL_TO="admin@example.com"'
failed_when: false
- name: Configure PCP metrics logging
hosts: pcp
become: true
tasks:
- name: Create PMLOGGER configuration
copy:
dest: /etc/pcp/pmlogger/control.d/local
owner: root
group: root
mode: '0644'
content: |
# Local PMLOGGER configuration
# Format: host server port archive-dir options
localhost localhost {{ pcp_port }} y -r -T24h10m -c /etc/pcp/pmlogger/config.default
- name: Configure metrics retention
copy:
dest: /etc/pcp/pmlogger/config.default
owner: root
group: root
mode: '0644'
content: |
# Metrics to log
# Log all metrics at 60 second intervals
log mandatory on 60 {
kernel.all.load
kernel.all.runnable
mem.util.used
mem.util.free
mem.util.available
disk.all.total
disk.all.read
disk.all.write
network.interface.in.bytes
network.interface.out.bytes
proc.nprocs
proc.run
}
- name: Restart PMLOGGER
systemd:
name: pmlogger
state: restarted
- name: Install Grafana with PCP datasource
hosts: pcp
become: true
tasks:
- name: Install Grafana
apt:
name: grafana
state: present
when: ansible_os_family == "Debian"
- name: Install PCP Grafana datasource
command: pcp-import-grafana-dashboard
failed_when: false
- name: Enable and start Grafana
systemd:
name: grafana-server
enabled: true
state: started
- name: Configure firewall for Grafana
ufw:
rule: allow
port: 3000
proto: tcp
comment: "Grafana web interface"
when: ansible_os_family == "Debian"
failed_when: false
- name: Configure PCP for remote monitoring
hosts: pcp_agents
become: true
vars:
pcp_server: "192.168.1.115"
tasks:
- name: Install PCP client
apt:
name: pcp
state: present
update_cache: true
when: ansible_os_family == "Debian"
- name: Configure PMCD to allow remote connections
lineinfile:
path: /etc/pcp/pmcd/pmcd.options
regexp: "^#?-n"
line: "-n 0.0.0.0"
failed_when: false
- name: Configure firewall for PMCD
ufw:
rule: allow
from_ip: "{{ pcp_server }}"
port: 44321
proto: tcp
comment: "PCP PMCD from server"
when: ansible_os_family == "Debian"
failed_when: false
- name: Enable and start PMCD
systemd:
name: pmcd
enabled: true
state: started
- name: Query PCP metrics
hosts: pcp
become: false
tasks:
- name: Get current CPU load
command: pmval kernel.all.load
register: cpu_load
changed_when: false
- name: Get memory usage
command: pmval mem.util.used
register: mem_used
changed_when: false
- name: Get disk I/O stats
command: pmval disk.all.total
register: disk_io
changed_when: false
- name: Get network stats
command: pmval network.interface.in.bytes
register: net_in
changed_when: false
- name: Display metrics summary
debug:
msg: |
PCP Metrics Summary for {{ ansible_hostname }}:
CPU Load (1 min): {{ cpu_load.stdout_lines | last | default('N/A') }}
Memory Used: {{ mem_used.stdout_lines | last | default('N/A') }}
Disk I/O: {{ disk_io.stdout_lines | last | default('N/A') }}
Network In: {{ net_in.stdout_lines | last | default('N/A') }}
# Check PMCD logs
sudo tail -f /var/log/pcp/pmcd.log
# Check service status
sudo systemctl status pmcd
# Test PMCD connection
pminfo -f
# List available metrics
pminfo
# Check specific metric
pminfo kernel.all.load
# Verify PMCD is running
systemctl status pmcd
# Check webapp status
sudo systemctl status pcp-webapi
# Check webapp logs
sudo tail -f /var/log/pcp/webapi.log
# Test web interface
curl http://localhost:44322
# Check firewall
sudo ufw status | grep 44321
# Test remote connection
pminfo -h remote-host kernel.all.load
# Check PMCD options
cat /etc/pcp/pmcd/pmcd.options
We develop tailored automation solutions for:
Let’s discuss your requirements: office@linux-server-admin.com | Contact