Sanitized mirror from private repository - 2026-04-19 09:44:40 UTC
This commit is contained in:
369
ansible/automation/playbooks/container_resource_optimizer.yml
Normal file
369
ansible/automation/playbooks/container_resource_optimizer.yml
Normal file
@@ -0,0 +1,369 @@
|
||||
---
|
||||
- name: Container Resource Optimization
|
||||
hosts: all
|
||||
gather_facts: yes
|
||||
vars:
|
||||
optimization_timestamp: "{{ ansible_date_time.iso8601 }}"
|
||||
optimization_report_dir: "/tmp/optimization_reports"
|
||||
cpu_threshold_warning: 80
|
||||
cpu_threshold_critical: 95
|
||||
memory_threshold_warning: 85
|
||||
memory_threshold_critical: 95
|
||||
|
||||
tasks:
|
||||
- name: Create optimization reports directory
|
||||
file:
|
||||
path: "{{ optimization_report_dir }}"
|
||||
state: directory
|
||||
mode: '0755'
|
||||
delegate_to: localhost
|
||||
run_once: true
|
||||
|
||||
- name: Check if Docker is available
|
||||
shell: command -v docker >/dev/null 2>&1
|
||||
register: docker_available
|
||||
changed_when: false
|
||||
ignore_errors: yes
|
||||
|
||||
- name: Skip Docker tasks if not available
|
||||
set_fact:
|
||||
skip_docker: "{{ docker_available.rc != 0 }}"
|
||||
|
||||
- name: Collect container resource usage
|
||||
shell: |
|
||||
if ! command -v docker >/dev/null 2>&1; then
|
||||
echo "Docker not available"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "=== CONTAINER RESOURCE USAGE ==="
|
||||
|
||||
# Get current resource usage
|
||||
echo "Current Resource Usage:"
|
||||
docker stats --no-stream --format "table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.MemPerc}}\t{{.NetIO}}\t{{.BlockIO}}" 2>/dev/null || echo "No running containers"
|
||||
echo ""
|
||||
|
||||
# Get container limits
|
||||
echo "Container Resource Limits:"
|
||||
docker ps --format "{{.Names}}" 2>/dev/null | while read container; do
|
||||
if [ -n "$container" ]; then
|
||||
echo "Container: $container"
|
||||
|
||||
# CPU limits
|
||||
cpu_limit=$(docker inspect "$container" --format '{{.HostConfig.CpuQuota}}' 2>/dev/null)
|
||||
cpu_period=$(docker inspect "$container" --format '{{.HostConfig.CpuPeriod}}' 2>/dev/null)
|
||||
if [ "$cpu_limit" != "0" ] && [ "$cpu_period" != "0" ]; then
|
||||
cpu_cores=$(echo "scale=2; $cpu_limit / $cpu_period" | bc 2>/dev/null || echo "N/A")
|
||||
echo " CPU Limit: $cpu_cores cores"
|
||||
else
|
||||
echo " CPU Limit: unlimited"
|
||||
fi
|
||||
|
||||
# Memory limits
|
||||
mem_limit=$(docker inspect "$container" --format '{{.HostConfig.Memory}}' 2>/dev/null)
|
||||
if [ "$mem_limit" != "0" ]; then
|
||||
mem_mb=$(echo "scale=0; $mem_limit / 1024 / 1024" | bc 2>/dev/null || echo "N/A")
|
||||
echo " Memory Limit: ${mem_mb}MB"
|
||||
else
|
||||
echo " Memory Limit: unlimited"
|
||||
fi
|
||||
|
||||
# Restart policy
|
||||
restart_policy=$(docker inspect "$container" --format '{{.HostConfig.RestartPolicy.Name}}' 2>/dev/null)
|
||||
echo " Restart Policy: $restart_policy"
|
||||
|
||||
echo ""
|
||||
fi
|
||||
done
|
||||
register: resource_usage
|
||||
changed_when: false
|
||||
when: not skip_docker
|
||||
|
||||
- name: Analyze resource efficiency
|
||||
shell: |
|
||||
if ! command -v docker >/dev/null 2>&1; then
|
||||
echo "Docker not available"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "=== RESOURCE EFFICIENCY ANALYSIS ==="
|
||||
|
||||
# Identify resource-heavy containers
|
||||
echo "High Resource Usage Containers:"
|
||||
docker stats --no-stream --format "{{.Container}}\t{{.CPUPerc}}\t{{.MemPerc}}" 2>/dev/null | while IFS=$'\t' read container cpu mem; do
|
||||
if [ -n "$container" ] && [ "$container" != "CONTAINER" ]; then
|
||||
cpu_num=$(echo "$cpu" | sed 's/%//' | cut -d'.' -f1)
|
||||
mem_num=$(echo "$mem" | sed 's/%//' | cut -d'.' -f1)
|
||||
|
||||
if [ "$cpu_num" -gt "{{ cpu_threshold_warning }}" ] 2>/dev/null || [ "$mem_num" -gt "{{ memory_threshold_warning }}" ] 2>/dev/null; then
|
||||
echo "⚠️ $container - CPU: $cpu, Memory: $mem"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
echo ""
|
||||
|
||||
# Check for containers without limits
|
||||
echo "Containers Without Resource Limits:"
|
||||
docker ps --format "{{.Names}}" 2>/dev/null | while read container; do
|
||||
if [ -n "$container" ]; then
|
||||
cpu_limit=$(docker inspect "$container" --format '{{.HostConfig.CpuQuota}}' 2>/dev/null)
|
||||
mem_limit=$(docker inspect "$container" --format '{{.HostConfig.Memory}}' 2>/dev/null)
|
||||
|
||||
if [ "$cpu_limit" = "0" ] && [ "$mem_limit" = "0" ]; then
|
||||
echo "⚠️ $container - No CPU or memory limits"
|
||||
elif [ "$cpu_limit" = "0" ]; then
|
||||
echo "⚠️ $container - No CPU limit"
|
||||
elif [ "$mem_limit" = "0" ]; then
|
||||
echo "⚠️ $container - No memory limit"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
echo ""
|
||||
|
||||
# Identify idle containers
|
||||
echo "Low Usage Containers (potential over-provisioning):"
|
||||
docker stats --no-stream --format "{{.Container}}\t{{.CPUPerc}}\t{{.MemPerc}}" 2>/dev/null | while IFS=$'\t' read container cpu mem; do
|
||||
if [ -n "$container" ] && [ "$container" != "CONTAINER" ]; then
|
||||
cpu_num=$(echo "$cpu" | sed 's/%//' | cut -d'.' -f1)
|
||||
mem_num=$(echo "$mem" | sed 's/%//' | cut -d'.' -f1)
|
||||
|
||||
if [ "$cpu_num" -lt "5" ] 2>/dev/null && [ "$mem_num" -lt "10" ] 2>/dev/null; then
|
||||
echo "💡 $container - CPU: $cpu, Memory: $mem (consider downsizing)"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
register: efficiency_analysis
|
||||
changed_when: false
|
||||
when: not skip_docker
|
||||
|
||||
- name: System resource analysis
|
||||
shell: |
|
||||
echo "=== SYSTEM RESOURCE ANALYSIS ==="
|
||||
|
||||
# Overall system resources
|
||||
echo "System Resources:"
|
||||
echo "CPU Cores: $(nproc)"
|
||||
echo "Total Memory: $(free -h | awk 'NR==2{print $2}')"
|
||||
echo "Available Memory: $(free -h | awk 'NR==2{print $7}')"
|
||||
echo "Memory Usage: $(free | awk 'NR==2{printf "%.1f%%", $3*100/$2}')"
|
||||
echo "Load Average: $(uptime | awk -F'load average:' '{print $2}')"
|
||||
echo ""
|
||||
|
||||
# Docker system resource usage
|
||||
if command -v docker >/dev/null 2>&1; then
|
||||
echo "Docker System Usage:"
|
||||
docker system df 2>/dev/null || echo "Docker system info not available"
|
||||
echo ""
|
||||
|
||||
# Count containers by status
|
||||
echo "Container Status Summary:"
|
||||
echo "Running: $(docker ps -q 2>/dev/null | wc -l)"
|
||||
echo "Stopped: $(docker ps -aq --filter status=exited 2>/dev/null | wc -l)"
|
||||
echo "Total: $(docker ps -aq 2>/dev/null | wc -l)"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# Disk usage for Docker
|
||||
if [ -d "/var/lib/docker" ]; then
|
||||
echo "Docker Storage Usage:"
|
||||
du -sh /var/lib/docker 2>/dev/null || echo "Docker storage info not accessible"
|
||||
fi
|
||||
register: system_analysis
|
||||
changed_when: false
|
||||
|
||||
- name: Generate optimization recommendations
|
||||
shell: |
|
||||
echo "=== OPTIMIZATION RECOMMENDATIONS ==="
|
||||
|
||||
# System-level recommendations
|
||||
total_mem_mb=$(free -m | awk 'NR==2{print $2}')
|
||||
used_mem_mb=$(free -m | awk 'NR==2{print $3}')
|
||||
mem_usage_percent=$(echo "scale=1; $used_mem_mb * 100 / $total_mem_mb" | bc 2>/dev/null || echo "0")
|
||||
|
||||
echo "System Recommendations:"
|
||||
if [ "$(echo "$mem_usage_percent > 85" | bc 2>/dev/null)" = "1" ]; then
|
||||
echo "🚨 High memory usage (${mem_usage_percent}%) - consider adding RAM or optimizing containers"
|
||||
elif [ "$(echo "$mem_usage_percent > 70" | bc 2>/dev/null)" = "1" ]; then
|
||||
echo "⚠️ Moderate memory usage (${mem_usage_percent}%) - monitor closely"
|
||||
else
|
||||
echo "✅ Memory usage acceptable (${mem_usage_percent}%)"
|
||||
fi
|
||||
|
||||
# Load average check
|
||||
load_1min=$(uptime | awk -F'load average:' '{print $2}' | awk -F',' '{print $1}' | xargs)
|
||||
cpu_cores=$(nproc)
|
||||
if [ "$(echo "$load_1min > $cpu_cores" | bc 2>/dev/null)" = "1" ]; then
|
||||
echo "🚨 High CPU load ($load_1min) exceeds core count ($cpu_cores)"
|
||||
else
|
||||
echo "✅ CPU load acceptable ($load_1min for $cpu_cores cores)"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# Docker-specific recommendations
|
||||
if command -v docker >/dev/null 2>&1; then
|
||||
echo "Container Recommendations:"
|
||||
|
||||
# Check for containers without health checks
|
||||
echo "Containers without health checks:"
|
||||
docker ps --format "{{.Names}}" 2>/dev/null | while read container; do
|
||||
if [ -n "$container" ]; then
|
||||
health_check=$(docker inspect "$container" --format '{{.Config.Healthcheck}}' 2>/dev/null)
|
||||
if [ "$health_check" = "<nil>" ] || [ -z "$health_check" ]; then
|
||||
echo "💡 $container - Consider adding health check"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
echo ""
|
||||
|
||||
# Check for old images
|
||||
echo "Image Optimization:"
|
||||
old_images=$(docker images --filter "dangling=true" -q 2>/dev/null | wc -l)
|
||||
if [ "$old_images" -gt "0" ]; then
|
||||
echo "🧹 $old_images dangling images found - run 'docker image prune'"
|
||||
fi
|
||||
|
||||
unused_volumes=$(docker volume ls --filter "dangling=true" -q 2>/dev/null | wc -l)
|
||||
if [ "$unused_volumes" -gt "0" ]; then
|
||||
echo "🧹 $unused_volumes unused volumes found - run 'docker volume prune'"
|
||||
fi
|
||||
fi
|
||||
register: recommendations
|
||||
changed_when: false
|
||||
|
||||
- name: Create optimization report
|
||||
set_fact:
|
||||
optimization_report:
|
||||
timestamp: "{{ optimization_timestamp }}"
|
||||
hostname: "{{ inventory_hostname }}"
|
||||
docker_available: "{{ not skip_docker }}"
|
||||
resource_usage: "{{ resource_usage.stdout if not skip_docker else 'Docker not available' }}"
|
||||
efficiency_analysis: "{{ efficiency_analysis.stdout if not skip_docker else 'Docker not available' }}"
|
||||
system_analysis: "{{ system_analysis.stdout }}"
|
||||
recommendations: "{{ recommendations.stdout }}"
|
||||
|
||||
- name: Display optimization report
|
||||
debug:
|
||||
msg: |
|
||||
|
||||
==========================================
|
||||
⚡ RESOURCE OPTIMIZATION - {{ inventory_hostname }}
|
||||
==========================================
|
||||
|
||||
📊 DOCKER AVAILABLE: {{ 'Yes' if optimization_report.docker_available else 'No' }}
|
||||
|
||||
🔍 RESOURCE USAGE:
|
||||
{{ optimization_report.resource_usage }}
|
||||
|
||||
📈 EFFICIENCY ANALYSIS:
|
||||
{{ optimization_report.efficiency_analysis }}
|
||||
|
||||
🖥️ SYSTEM ANALYSIS:
|
||||
{{ optimization_report.system_analysis }}
|
||||
|
||||
💡 RECOMMENDATIONS:
|
||||
{{ optimization_report.recommendations }}
|
||||
|
||||
==========================================
|
||||
|
||||
- name: Generate JSON optimization report
|
||||
copy:
|
||||
content: |
|
||||
{
|
||||
"timestamp": "{{ optimization_report.timestamp }}",
|
||||
"hostname": "{{ optimization_report.hostname }}",
|
||||
"docker_available": {{ optimization_report.docker_available | lower }},
|
||||
"resource_usage": {{ optimization_report.resource_usage | to_json }},
|
||||
"efficiency_analysis": {{ optimization_report.efficiency_analysis | to_json }},
|
||||
"system_analysis": {{ optimization_report.system_analysis | to_json }},
|
||||
"recommendations": {{ optimization_report.recommendations | to_json }},
|
||||
"optimization_actions": [
|
||||
"Review containers without resource limits",
|
||||
"Monitor high-usage containers for optimization opportunities",
|
||||
"Consider downsizing low-usage containers",
|
||||
"Implement health checks for better reliability",
|
||||
"Regular cleanup of unused images and volumes"
|
||||
]
|
||||
}
|
||||
dest: "{{ optimization_report_dir }}/{{ inventory_hostname }}_optimization_{{ ansible_date_time.epoch }}.json"
|
||||
delegate_to: localhost
|
||||
|
||||
- name: Apply optimizations (when optimize_action is specified)
|
||||
block:
|
||||
- name: Validate optimization action
|
||||
fail:
|
||||
msg: "Invalid action. Supported actions: cleanup, restart_high_usage, add_limits"
|
||||
when: optimize_action not in ['cleanup', 'restart_high_usage', 'add_limits']
|
||||
|
||||
- name: Execute optimization action
|
||||
shell: |
|
||||
case "{{ optimize_action }}" in
|
||||
"cleanup")
|
||||
echo "Performing Docker cleanup..."
|
||||
docker image prune -f 2>/dev/null || echo "Image prune failed"
|
||||
docker volume prune -f 2>/dev/null || echo "Volume prune failed"
|
||||
docker container prune -f 2>/dev/null || echo "Container prune failed"
|
||||
echo "Cleanup completed"
|
||||
;;
|
||||
"restart_high_usage")
|
||||
echo "Restarting high CPU/memory usage containers..."
|
||||
docker stats --no-stream --format "{{.Container}}\t{{.CPUPerc}}\t{{.MemPerc}}" 2>/dev/null | while IFS=$'\t' read container cpu mem; do
|
||||
if [ -n "$container" ] && [ "$container" != "CONTAINER" ]; then
|
||||
cpu_num=$(echo "$cpu" | sed 's/%//' | cut -d'.' -f1)
|
||||
mem_num=$(echo "$mem" | sed 's/%//' | cut -d'.' -f1)
|
||||
|
||||
if [ "$cpu_num" -gt "{{ cpu_threshold_critical }}" ] 2>/dev/null || [ "$mem_num" -gt "{{ memory_threshold_critical }}" ] 2>/dev/null; then
|
||||
echo "Restarting high-usage container: $container (CPU: $cpu, Memory: $mem)"
|
||||
docker restart "$container" 2>/dev/null || echo "Failed to restart $container"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
;;
|
||||
"add_limits")
|
||||
echo "Adding resource limits requires manual Docker Compose file updates"
|
||||
echo "Recommended limits based on current usage:"
|
||||
docker stats --no-stream --format "{{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}" 2>/dev/null | while IFS=$'\t' read container cpu mem; do
|
||||
if [ -n "$container" ] && [ "$container" != "CONTAINER" ]; then
|
||||
echo "$container:"
|
||||
echo " deploy:"
|
||||
echo " resources:"
|
||||
echo " limits:"
|
||||
echo " cpus: '1.0' # Adjust based on usage: $cpu"
|
||||
echo " memory: 512M # Adjust based on usage: $mem"
|
||||
echo ""
|
||||
fi
|
||||
done
|
||||
;;
|
||||
esac
|
||||
register: optimization_action_result
|
||||
when: not skip_docker
|
||||
|
||||
- name: Display optimization action result
|
||||
debug:
|
||||
msg: |
|
||||
|
||||
⚡ Optimization action '{{ optimize_action }}' completed on {{ inventory_hostname }}
|
||||
|
||||
Result:
|
||||
{{ optimization_action_result.stdout }}
|
||||
|
||||
{% if optimization_action_result.stderr %}
|
||||
Errors:
|
||||
{{ optimization_action_result.stderr }}
|
||||
{% endif %}
|
||||
|
||||
when: optimize_action is defined and not skip_docker
|
||||
|
||||
- name: Summary message
|
||||
debug:
|
||||
msg: |
|
||||
|
||||
⚡ Resource optimization analysis complete for {{ inventory_hostname }}
|
||||
📄 Report saved to: {{ optimization_report_dir }}/{{ inventory_hostname }}_optimization_{{ ansible_date_time.epoch }}.json
|
||||
|
||||
{% if optimize_action is defined %}
|
||||
🔧 Action performed: {{ optimize_action }}
|
||||
{% endif %}
|
||||
|
||||
💡 Use -e optimize_action=<action> for optimization operations
|
||||
💡 Supported actions: cleanup, restart_high_usage, add_limits
|
||||
💡 Monitor resource usage regularly for optimal performance
|
||||
Reference in New Issue
Block a user