Снайперская точность: как научиться убивать процессы по шаблону
Можно использовать
История из жизни: на продакшн-сервере
Всегда проверяй что убиваешь:
🌐 @helcode | #bash
Можно использовать
killall как дробовик - стрелять по площади. Но зачастую это будет опасно:# Дробовик (опасно!):
killall python # Убьет ВСЕ python процессы
# Более точно:
pkill -f "python data_processor.py" # Только конкретный скрипт
# Еще точнее — с проверкой:
pgrep -f "python data_processor.py" | xargs kill -TERM # Вежливая просьба :)
sleep 5
pgrep -f "python data_processor.py" | xargs kill -KILL # Принудительно :(
История из жизни: на продакшн-сервере
killall java остановил не только проблемное приложение, но и три критичных сервиса. Минутная паника научила меня точности...Всегда проверяй что убиваешь:
pgrep -fl "pattern" покажет список целей.🌐 @helcode | #bash
🔥7👌2
Цирк с конвейерами: обработка логов
Начальник попросил "быстро посчитать статистику по логам"? Коллеги судорожно открывают Excel? Сделаем это в терминале:
Комбинируйте
🌐 @helcode | #bash
Начальник попросил "быстро посчитать статистику по логам"? Коллеги судорожно открывают Excel? Сделаем это в терминале:
# Анализ access.log:
cat access.log | awk '{print $1}' | sort | uniq -c | sort -nr | head -10
# Топ-10 самых частых ошибок:
grep "ERROR" app.log | awk -F']' '{print $2}' | sort | uniq -c | sort -nr | head -10
# Время ответа по процентам
cat access.log | awk '{print $NF}' | sort -n |
awk '{
data[NR] = $1
} END {
print "50%: " data[int(NR*0.5)]
print "95%: " data[int(NR*0.95)]
print "99%: " data[int(NR*0.99)]
}'
Комбинируйте
grep, awk, sort, uniq, это значительно ускорит и упростит работу с логами!🌐 @helcode | #bash
👍5❤1
Гадалка для сервера: как предсказывать проблемы до их появления
Системный администратор - словно метеоролог. Лучше предсказать бурю, чем тушить последствия.
Кейс из жизни: подобная "гадалка" предупредила о заполнении диска за 2 для до "катастрофы". Вовремя почистили логи и избежали простоя.
🌐 @helcode | #bash
Системный администратор - словно метеоролог. Лучше предсказать бурю, чем тушить последствия.
#!/bin/bash
# crystal_ball.sh - мой хрустальный шар
# Предсказание дисковых проблем:
df -h | awk '$5 > 80 {print "ВНИМАНИЕ: " $6 " заполнен на " $5}'
# Предсказание нехватки памяти:
free -h | grep Mem | awk '{if ($3/$2 * 100 > 85) print "Скоро закончится память!"}'
# Предсказание сетевых проблем:
netstat -an | grep :80 | wc -l |
awk '{if ($1 > 1000) print "Слишком много подключений к порту 80"}'
# Предсказание перегруза CPU:
uptime | awk '{if ($(NF-2) > 5.0) print "Система перегружена! Load average: " $(NF-2)}'
Кейс из жизни: подобная "гадалка" предупредила о заполнении диска за 2 для до "катастрофы". Вовремя почистили логи и избежали простоя.
🌐 @helcode | #bash
👍9❤🔥1
Театр одного актера: автоматизируем рутину с tmux
Зачем судорожно переключаться между 10 терминалами. Глянем на tmux:
Одно подключение по SSH - и все нужные окна уже работают. Выход из сервера - сессия сохраняется. Возвращение - всё на своих местах!
🌐 @helcode | #bash
Зачем судорожно переключаться между 10 терминалами. Глянем на tmux:
# Создаем рабочее пространство:
tmux new-session -s "monitoring" -d
tmux new-window -t "monitoring:1" -n "logs"
tmux new-window -t "monitoring:2" -n "metrics"
# Настраиваем панели:
tmux split-window -h -t "monitoring:logs"
tmux split-window -v -t "monitoring:logs.0"
# Запускаем команды в панелях:
tmux send-keys -t "monitoring:logs.0" "tail -f /var/log/nginx/access.log" Enter
tmux send-keys -t "monitoring:logs.1" "htop" Enter
tmux send-keys -t "monitoring:logs.2" "docker ps -a" Enter
# Подключаемся к сессии:
tmux attach -t "monitoring"
Одно подключение по SSH - и все нужные окна уже работают. Выход из сервера - сессия сохраняется. Возвращение - всё на своих местах!
🌐 @helcode | #bash
👍5🥰1
"Шпионские страсти": как я отлаживал таинственные сетевые проблемы
Приложение периодически "зависало". Логи чистые. Что происходит?
Оказалось, приложение раз в 5 минут делало DNS-запрос, который иногда таймаутился на 30 секунд!
Когда логи молчат - слушаем сеть!
🌐 @helcode | #bash
Приложение периодически "зависало". Логи чистые. Что происходит?
# Прослушивание сети (требует прав):
tcpdump -i any -w capture.pcap host 192.168.1.100 and port 5432
# Анализ трафика:
tcpflow -r capture.pcap -C
# Или проще - в реальном времени:
ngrep -d any port 8080
# Мониторинг конкретного процесса:
strace -f -p 1234 -e trace=network
# Проверка DNS:
dig @8.8.8.8 myapi.com # Обход локального кеша
Оказалось, приложение раз в 5 минут делало DNS-запрос, который иногда таймаутился на 30 секунд!
strace показал вызовы connect(), которые висели подозрительно долго.Когда логи молчат - слушаем сеть!
🌐 @helcode | #bash
🔥6👍2🥰1
Искусство седа
Представим, что необходимо обработать 1000 CSV файлов, а именно: удалить столбцы, переименовать заголовки, фильтровать строки. Ручной труд = недели работы, а с
Бонусный "трюк":
🌐 @helcode | #bash
Представим, что необходимо обработать 1000 CSV файлов, а именно: удалить столбцы, переименовать заголовки, фильтровать строки. Ручной труд = недели работы, а с
sed - вполне реализуемо за 1 вечер.# Удаляем столбцы 2 и 4 из CSV:
sed -i 's/^\([^,]*\),[^,]*,\("[^"]*"\|[^,]*\),[^,]*/\1,\3/' file.csv
# Переименовываем заголовки:
sed -i '1s/old_name/new_name/g; 1s/another_old/another_new/g' *.csv
# Фильтруем строки по дате:
sed -n '/2024-01-15/p' large_file.log > filtered.log
# Массовая замена в файлах проекта:
find . -name "*.py" -exec sed -i 's/MySQL/PostgreSQL/g' {} +
Бонусный "трюк":
# Конвертируем JSON в CSV (упрощенно):
echo '{"name":"John","age":30}' | sed 's/{//g; s/}//g; s/":"/,/g; s/","/\n/g'
sed - это не просто "замена текста", это полноценный текстовый трансформер!🌐 @helcode | #bash
👍12❤1
Защита SSH: практические меры безопасности
Коллеги, хочу попробовать новый "формат" постов, аля "практический кейс". Следующие 4 поста будут подобны данному, в качестве эксперимента. Буду рад получить обратную реакцию по подобному "формату"! Приступим...
Цель: повысить безопасность SSH-доступа к серверам
Проблема: стандартные настройки SSH уязвимы для брут-форс атак и несанкционированного доступа
Решение: многоуровневая защита SSH
Проверка настроек:
Рекомендации:
- Регулярно обновлять SSH-ключи
- Использовать ключи длиной не менее 4096 бит
- Настроить мониторинг неудачных попыток входа
🌐 @helcode | #bash
Коллеги, хочу попробовать новый "формат" постов, аля "практический кейс". Следующие 4 поста будут подобны данному, в качестве эксперимента. Буду рад получить обратную реакцию по подобному "формату"! Приступим...
Цель: повысить безопасность SSH-доступа к серверам
Проблема: стандартные настройки SSH уязвимы для брут-форс атак и несанкционированного доступа
Решение: многоуровневая защита SSH
# 1. Смена порта и ограничение доступа
# /etc/ssh/sshd_config
Port 58222 # Нестандартный порт
PermitRootLogin no
PasswordAuthentication no # Только по ключам
MaxAuthTries 3
ClientAliveInterval 300
# 2. Настройка fail2ban для блокировки атак
# /etc/fail2ban/jail.local
[sshd]
enabled = true
port = 58222
maxretry = 3
bantime = 3600
# 3. Ограничение доступа по IP
iptables -A INPUT -p tcp --dport 58222 -s 192.168.1.0/24 -j ACCEPT
iptables -A INPUT -p tcp --dport 58222 -j DROP
# 4. Двухфакторная аутентификация (Google Authenticator)
# Установка и настройка:
sudo apt install libpam-google-authenticator
google-authenticator # Следуйте инструкциям
# Добавить в /etc/ssh/sshd_config:
AuthenticationMethods publickey,keyboard-interactive
Проверка настроек:
# Тестирование конфигурации
sshd -t
systemctl reload sshd
# Мониторинг подключений
netstat -tulpn | grep :58222
fail2ban-client status sshd
Рекомендации:
- Регулярно обновлять SSH-ключи
- Использовать ключи длиной не менее 4096 бит
- Настроить мониторинг неудачных попыток входа
🌐 @helcode | #bash
❤8👍6
Мониторинг производительности: от сбора метрик до визуализации
Цель: настроить полноценную систему мониторинга серверной инфраструктуры
Архитектура: Node Exporter + Prometheus + Grafana
Установка Node Exporter
Настройка Prometheus
Дашборды Grafana
Полезные запросы PromQL:
🌐 @helcode
Цель: настроить полноценную систему мониторинга серверной инфраструктуры
Архитектура: Node Exporter + Prometheus + Grafana
Установка Node Exporter
# Скачивание и установка
wget https://github.com/prometheus/node_exporter/releases/download/v1.6.1/node_exporter-1.6.1.linux-amd64.tar.gz
tar xzf node_exporter-*.tar.gz
sudo mv node_exporter-*/node_exporter /usr/local/bin/
# Создание systemd сервиса
sudo cat > /etc/systemd/system/node_exporter.service << EOF
[Unit]
Description=Node Exporter
After=network.target
[Service]
User=node_exporter
ExecStart=/usr/local/bin/node_exporter
[Install]
WantedBy=multi-user.target
EOF
# Запуск
sudo systemctl daemon-reload
sudo systemctl enable node_exporter
sudo systemctl start node_exporter
Настройка Prometheus
# prometheus.yml
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'node'
static_configs:
- targets: ['node1:9100', 'node2:9100']
metrics_path: /metrics
Дашборды Grafana
# Импорт готовых дашбордов
# Node Exporter Full: id 1860
# Kubernetes cluster monitoring: id 315
Полезные запросы PromQL:
# Использование CPU
100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
# Доступная память
node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes * 100
# Использование диска
100 - (node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"} * 100)
🌐 @helcode
❤1👍1
Продвинутая работа с Git: от базовых команд до эффективного workflow
Цель: освоить профессиональные техники работы с Git
1. Интерактивный rebase для чистой истории
2. Поиск изменений в истории
3. Работа с изменениями
4. Эффективный workflow
Лучшие практики:
➤ Коммитить часто, пушить редко
➤ Использовать semantic commit messages
➤ Регулярно синхронизироваться с upstream
➤ Проверять историю перед мержем
🌐 @helcode | #git
Цель: освоить профессиональные техники работы с Git
1. Интерактивный rebase для чистой истории
# Перебазирование последних 5 коммитов
git rebase -i HEAD~5
# Команды для rebase:
# pick - использовать коммит
# reword - изменить сообщение коммита
# edit - остановиться для редактирования
# squash - объединить с предыдущим коммитом
# fixup - объединить, отбросив сообщение
# Пример использования:
git rebase -i HEAD~3
# Редактируем файл:
pick a1b2c3d Добавить функцию X
squash b2c3d4e Исправить опечатку
reword c3d4e5f Обновить документацию
2. Поиск изменений в истории
# Поиск по сообщениям коммитов
git log --grep="bugfix" --oneline
# Поиск изменений в коде
git log -S "function_name" --oneline
# Поиск автора
git log --author="john" --since="2024-01-01"
# Визуализация истории
git log --graph --oneline --all
3. Работа с изменениями
# Интерактивное добавление изменений
git add -p
# Просмотр изменений перед коммитом
git diff --staged
# Исправление последнего коммита
git commit --amend
# Временное сохранение изменений
git stash push -m "WIP: работа над функцией X"
git stash list
git stash pop
4. Эффективный workflow
# Создание feature ветки
git checkout -b feature/new-authentication
# Регулярные коммиты с понятными сообщениями
git commit -m "feat(auth): добавить OAuth2 провайдеры
- Реализована поддержка Google OAuth
- Добавлена поддержка GitHub OAuth
- Написаны тесты для новых провайдеров"
# Синхронизация с основной веткой
git fetch origin
git rebase origin/main
# Разрешение конфликтов
git mergetool
git rebase --continue
# Пулл-реквест с чистой историей
git push origin feature/new-authentication
Лучшие практики:
➤ Коммитить часто, пушить редко
➤ Использовать semantic commit messages
➤ Регулярно синхронизироваться с upstream
➤ Проверять историю перед мержем
🌐 @helcode | #git
👍4❤1👌1
Docker в продакшене: безопасность и оптимизация
Цель: настроить безопасные и эффективные Docker-окружения для production
1. Безопасность образов
2. Безопасная оркестрация
3. Сканирование уязвимостей
4. Мониторинг и логирование
Production рекомендации:
➤ Регулярно обновлять базовые образы
➤ Использовать сканирование в CI/CD
➤ Ограничивать ресурсы контейнеров
➤ Настроить централизованное логирование
➤ Использовать секреты для конфиденциальных данных
🌐 @helcode
Цель: настроить безопасные и эффективные Docker-окружения для production
1. Безопасность образов
# Безопасный Dockerfile
FROM python:3.9-slim as builder
# Использование не-root пользователя
RUN groupadd -r appuser && useradd -r -g appuser appuser
# Копирование с правильными правами
COPY --chown=appuser:appuser . /app
WORKDIR /app
# Установка зависимостей безопасно
RUN pip install --no-cache-dir -r requirements.txt && \
pip check # Проверка конфликтов зависимостей
# Запуск от non-root пользователя
USER appuser
# Использование healthcheck
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost:8080/health || exit 1
# Безопасные переменные окружения
ENV PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1
CMD ["gunicorn", "app:app", "-b", "0.0.0.0:8080"]
2. Безопасная оркестрация
# docker-compose.prod.yml
version: '3.8'
services:
app:
build: .
restart: unless-stopped
security_opt:
- no-new-privileges:true
read_only: true
tmpfs:
- /tmp
environment:
- NODE_ENV=production
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 30s
timeout: 10s
retries: 3
nginx:
image: nginx:alpine
ports:
- "80:80"
depends_on:
- app
security_opt:
- no-new-privileges:true
3. Сканирование уязвимостей
# Установка и использование Trivy
wget https://github.com/aquasecurity/trivy/releases/download/v0.45.1/trivy_0.45.1_Linux-64bit.tar.gz
tar -xzf trivy*.tar.gz
sudo mv trivy /usr/local/bin/
# Сканирование образа
trivy image myapp:latest
# Сканирование с экспортом результатов
trivy image --format json --output scan-report.json myapp:latest
# Интеграция в CI/CD
trivy image --exit-code 1 --severity HIGH,CRITICAL myapp:latest
4. Мониторинг и логирование
# Просмотр логов с фильтрацией
docker logs -f --tail 100 container_name | grep -i error
# Мониторинг ресурсов
docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}"
# Аудит безопасности
docker bench-security
# Анализ образов
docker image history myapp:latest
docker inspect myapp:latest
Production рекомендации:
➤ Регулярно обновлять базовые образы
➤ Использовать сканирование в CI/CD
➤ Ограничивать ресурсы контейнеров
➤ Настроить централизованное логирование
➤ Использовать секреты для конфиденциальных данных
🌐 @helcode
👍10
Коллеги, рад всех приветствовать! Отвлеку Вас буквально на минуту... В связи положительными реакциями на новый формат - продолжаем. Если вдруг есть какие-то пожелания/советы по доработке - буду рад обратной связи!
Также, попробую вводить некие "рубрики", к концу недели будет серия обучающих постов по Git и всем вытекающим. Аналогично предыдущему абзацу, если у Вас есть какие-то интересные идеи по контенту - делитесь, постараюсь реализовать! В целом, всегда радуют предложения и мысли, Вы помогаете делать контент качественнее и интереснее, спасибо!
HashiCorp Vault: централизованное управление секретами
Цель: настроить безопасное хранение и управление секретами в инфраструктуре
Проблема: секреты в коде, конфигах и переменных окружения создают риски безопасности
Решение: внедрение HashiCorp Vault для централизованного управления
1. Установка и запуск Vault
2. Работа с секретами
3. Интеграция с приложениями
4. Политики доступа
Рекомендации:
➤ Использовать разные движки для разных типов секретов
➤ Настроить автоматическую ротацию секретов
➤ Регулярно аудировать доступы
➤ Использовать Namespaces для изоляции окружений
🌐 @helcode
Также, попробую вводить некие "рубрики", к концу недели будет серия обучающих постов по Git и всем вытекающим. Аналогично предыдущему абзацу, если у Вас есть какие-то интересные идеи по контенту - делитесь, постараюсь реализовать! В целом, всегда радуют предложения и мысли, Вы помогаете делать контент качественнее и интереснее, спасибо!
HashiCorp Vault: централизованное управление секретами
Цель: настроить безопасное хранение и управление секретами в инфраструктуре
Проблема: секреты в коде, конфигах и переменных окружения создают риски безопасности
Решение: внедрение HashiCorp Vault для централизованного управления
1. Установка и запуск Vault
# Установка
wget https://releases.hashicorp.com/vault/1.15.0/vault_1.15.0_linux_amd64.zip
unzip vault_1.15.0_linux_amd64.zip
sudo mv vault /usr/local/bin/
# Запуск в dev режиме (для тестирования)
vault server -dev -dev-root-token-id="root"
# Настройка окружения
export VAULT_ADDR='http://127.0.0.1:8200'
export VAULT_TOKEN='root'
2. Работа с секретами
# Включение движка секретов
vault secrets enable -path=secret kv-v2
# Запись секретов
vault kv put secret/app/database \
username="app_user" \
password="s3cr3t-p@ssw0rd" \
host="db.example.com"
# Чтение секретов
vault kv get secret/app/database
# Генерация динамических секретов для БД
vault secrets enable database
vault write database/config/postgres \
plugin_name=postgresql-database-plugin \
connection_url="postgresql://{{username}}:{{password}}@localhost:5432/postgres?sslmode=disable" \
allowed_roles="app"
vault write database/roles/app \
db_name=postgres \
creation_statements="CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}';" \
default_ttl="1h" \
max_ttl="24h"
3. Интеграция с приложениями
# Python пример
import hvac
import os
client = hvac.Client(
url=os.getenv('VAULT_ADDR'),
token=os.getenv('VAULT_TOKEN')
)
# Чтение секретов
secret = client.secrets.kv.v2.read_secret_version(
path='app/database'
)
db_password = secret['data']['data']['password']
4. Политики доступа
# app-policy.hcl
path "secret/data/app/*" {
capabilities = ["read"]
}
path "database/creds/app" {
capabilities = ["read"]
}
# Создание политики
vault policy write app app-policy.hcl
# Создание токена с политикой
vault token create -policy=app
Рекомендации:
➤ Использовать разные движки для разных типов секретов
➤ Настроить автоматическую ротацию секретов
➤ Регулярно аудировать доступы
➤ Использовать Namespaces для изоляции окружений
🌐 @helcode
👍3❤2🔥1
Prometheus Alertmanager: настройка интеллектуального алертинга
Цель: создать эффективную систему оповещений о проблемах в инфраструктуре
Проблема: отсутствие своевременных уведомлений о критических инцидентах
Решение: настройка Alertmanager с группировкой и фильтрацией алертов
1. Конфигурация Alertmanager
2. Правила алертинга в Prometheus
3. Интеграция с Prometheus
4. Полезные выражения для алертов
Best Practices:
➤ Использовать осмысленные временные интервалы
➤ Настраивать эскалацию для критичных алертов
➤ Регулярно пересматривать и настраивать пороги
➤ Тестировать алерты в staging окружении
🌐 @helcode
Цель: создать эффективную систему оповещений о проблемах в инфраструктуре
Проблема: отсутствие своевременных уведомлений о критических инцидентах
Решение: настройка Alertmanager с группировкой и фильтрацией алертов
1. Конфигурация Alertmanager
# alertmanager.yml
global:
smtp_smarthost: 'smtp.example.com:587'
smtp_from: 'alerts@example.com'
smtp_auth_username: 'alertmanager'
smtp_auth_password: 'password'
route:
group_by: ['alertname', 'cluster']
group_wait: 10s
group_interval: 10s
repeat_interval: 1h
receiver: 'slack-notifications'
routes:
- match:
severity: critical
receiver: 'pager-duty'
- match:
severity: warning
receiver: 'email-notifications'
receivers:
- name: 'slack-notifications'
slack_configs:
- api_url: 'https://hooks.slack.com/services/TOKEN'
channel: '#alerts'
send_resolved: true
- name: 'pager-duty'
pagerduty_configs:
- service_key: 'PAGER_DUTY_KEY'
- name: 'email-notifications'
email_configs:
- to: 'admin@example.com'
headers:
subject: '[ALERT] {{ .GroupLabels.alertname }}'
2. Правила алертинга в Prometheus
# alerts.yml
groups:
- name: infrastructure
rules:
- alert: HighCPUUsage
expr: 100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80
for: 5m
labels:
severity: warning
annotations:
summary: "High CPU usage on {{ $labels.instance }}"
description: "CPU usage is above 80% for more than 5 minutes"
- alert: DiskSpaceLow
expr: (node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"} * 100) < 10
for: 2m
labels:
severity: critical
annotations:
summary: "Low disk space on {{ $labels.instance }}"
description: "Disk space is below 10% on mountpoint {{ $labels.mountpoint }}"
- alert: ServiceDown
expr: up == 0
for: 1m
labels:
severity: critical
annotations:
summary: "Service {{ $labels.job }} on {{ $labels.instance }} is down"
3. Интеграция с Prometheus
# prometheus.yml
rule_files:
- "alerts.yml"
alerting:
alertmanagers:
- static_configs:
- targets:
- alertmanager:9093
4. Полезные выражения для алертов
# Память заканчивается
(node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) / node_memory_MemTotal_bytes * 100 > 90
# Сетевые ошибки
rate(node_network_receive_errs_total[5m]) > 0
# Высокая загрузка диска
rate(node_disk_read_time_seconds_total[5m]) > 0.1
# Доступность сервиса
avg_over_time(up[5m]) < 0.8
Best Practices:
➤ Использовать осмысленные временные интервалы
➤ Настраивать эскалацию для критичных алертов
➤ Регулярно пересматривать и настраивать пороги
➤ Тестировать алерты в staging окружении
🌐 @helcode
👍3❤1
PostgreSQL: оптимизация производительности и мониторинг
Цель: повысить производительность PostgreSQL и настроить мониторинг ключевых метрик
Проблема: медленные запросы, блокировки и неоптимальные настройки БД
Решение: комплексная оптимизация и мониторинг
1. Критические настройки postgresql.conf
2. Мониторинг ключевых метрик
3. Оптимизация запросов
4. Интеграция с Prometheus
Рекомендации:
➤ Регулярно проводить VACUUM и ANALYZE
➤ Мониторить соотношение hit/miss в кеше
➤ Настроить логирование медленных запросов
➤ Использовать connection pooling
➤ Регулярно обновлять статистику
🌐 @helcode
Цель: повысить производительность PostgreSQL и настроить мониторинг ключевых метрик
Проблема: медленные запросы, блокировки и неоптимальные настройки БД
Решение: комплексная оптимизация и мониторинг
1. Критические настройки postgresql.conf
-- Основные настройки
shared_buffers = '1GB' -- 25% от общей памяти
effective_cache_size = '3GB' -- 75% от общей памяти
work_mem = '64MB' -- Память для операций сортировки
maintenance_work_mem = '256MB' -- Память для обслуживания
max_connections = 200 -- Оптимальное количество подключений
-- Настройки производительности
random_page_cost = 1.1 -- Для SSD дисков
effective_io_concurrency = 200 -- Для SSD дисков
wal_buffers = '16MB'
checkpoint_completion_target = 0.9
-- Логирование медленных запросов
log_min_duration_statement = 1000 -- Запросы дольше 1 секунды
2. Мониторинг ключевых метрик
-- Активные запросы
SELECT
pid,
usename,
application_name,
client_addr,
state,
query,
now() - query_start as duration
FROM pg_stat_activity
WHERE state = 'active'
AND now() - query_start > interval '5 seconds';
-- Статистика по индексам
SELECT
schemaname,
tablename,
indexname,
idx_scan as index_scans,
idx_tup_read as tuples_read,
idx_tup_fetch as tuples_fetched
FROM pg_stat_user_indexes
WHERE idx_scan = 0; -- Неиспользуемые индексы
-- Размеры таблик и индексов
SELECT
tablename,
pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) as total_size,
pg_size_pretty(pg_relation_size(schemaname||'.'||tablename)) as table_size,
pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename) -
pg_relation_size(schemaname||'.'||tablename)) as index_size
FROM pg_tables
WHERE schemaname NOT IN ('information_schema', 'pg_catalog')
ORDER BY pg_total_relation_size(schemaname||'.'||tablename) DESC;
3. Оптимизация запросов
-- Поиск медленных запросов
SELECT
query,
calls,
total_time,
mean_time,
rows,
100.0 * shared_blks_hit / nullif(shared_blks_hit + shared_blks_read, 0) AS hit_percent
FROM pg_stat_statements
ORDER BY mean_time DESC
LIMIT 10;
-- Анализ планов запросов
EXPLAIN (ANALYZE, BUFFERS)
SELECT * FROM orders WHERE customer_id = 123 AND created_at > NOW() - INTERVAL '30 days';
-- Создание индексов для частых запросов
CREATE INDEX CONCURRENTLY idx_orders_customer_created
ON orders(customer_id, created_at DESC);
CREATE INDEX CONCURRENTLY idx_orders_status_created
ON orders(status, created_at) WHERE status IN ('pending', 'processing');
4. Интеграция с Prometheus
# postgres_exporter configuration
# Запуск экспортера
./postgres_exporter --extend.query-path=queries.yaml
# Пример queries.yaml
pg_stat_database:
query: "SELECT datname, numbackends, xact_commit, xact_rollback, blks_read, blks_hit, tup_returned, tup_fetched, tup_inserted, tup_updated, tup_deleted FROM pg_stat_database"
metrics:
- datname:
usage: "LABEL"
description: "Name of the database"
- numbackends:
usage: "GAUGE"
description: "Number of backends connected to this database"
Рекомендации:
➤ Регулярно проводить VACUUM и ANALYZE
➤ Мониторить соотношение hit/miss в кеше
➤ Настроить логирование медленных запросов
➤ Использовать connection pooling
➤ Регулярно обновлять статистику
🌐 @helcode
👍6❤2🤔1
GitLab CI/CD: создание эффективных пайплайнов
Цель: Настроить автоматизированные пайплайны для тестирования и деплоя
Проблема: Ручные процессы деплоя, отсутствие автоматического тестирования
Решение: Внедрение GitLab CI/CD с многостадийными пайплайнами
1. Базовый .gitlab-ci.yml
2. Стадия тестирования
3. Стадия сборки и безопасности
4. Стадия деплоя
5. Расширенные возможности
Best Practices:
➤ Использовать кеширование для ускорения
➤ Разделять тесты на unit/integration/e2e
➤ Настраивать артефакты между стадиями
➤ Использовать manual деплой на production
➤ Мониторить производительность пайплайнов
🌐 @helcode
Цель: Настроить автоматизированные пайплайны для тестирования и деплоя
Проблема: Ручные процессы деплоя, отсутствие автоматического тестирования
Решение: Внедрение GitLab CI/CD с многостадийными пайплайнами
1. Базовый .gitlab-ci.yml
# .gitlab-ci.yml
stages:
- test
- build
- security
- deploy
variables:
DOCKER_HOST: tcp://docker:2375
DOCKER_DRIVER: overlay2
# Кеширование для ускорения сборок
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- node_modules/
- .cache/pip/
- vendor/bundle
# Общие настройки для всех job'ов
.default_job: &default_job
image: docker:latest
services:
- docker:dind
before_script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
2. Стадия тестирования
unit_tests:
<<: *default_job
stage: test
image: python:3.9
script:
- pip install -r requirements.txt
- pytest tests/unit/ --cov=app --cov-report=xml
artifacts:
reports:
cobertura: coverage.xml
paths:
- coverage/
coverage: '/TOTAL.*\s+(\d+%)$/'
integration_tests:
<<: *default_job
stage: test
script:
- docker-compose -f docker-compose.test.yml up -d
- sleep 30
- ./wait-for-service.sh http://app:8000/health
- pytest tests/integration/
- docker-compose -f docker-compose.test.yml down
e2e_tests:
<<: *default_job
stage: test
image: node:16
script:
- npm install
- npm run test:e2e
artifacts:
paths:
- cypress/screenshots/
- cypress/videos/
3. Стадия сборки и безопасности
build:
<<: *default_job
stage: build
script:
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
only:
- main
- develop
security_scan:
<<: *default_job
stage: security
image: aquasec/trivy:latest
script:
- trivy image --exit-code 0 --format template --template "@/contrib/html.tpl" -o gl-dependency-scan-report.html $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
- trivy image --exit-code 1 --severity HIGH,CRITICAL $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
artifacts:
paths:
- gl-dependency-scan-report.html
allow_failure: true
sast:
stage: security
image:
name: "golang:1.19"
script:
- git clone https://github.com/securego/gosec.git
- cd gosec/cmd/gosec && go install
- gosec ./...
4. Стадия деплоя
deploy_staging:
<<: *default_job
stage: deploy
environment:
name: staging
url: https://staging.example.com
script:
- echo "Deploying to staging..."
- kubectl set image deployment/app app=$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA -n staging
- kubectl rollout status deployment/app -n staging
only:
- develop
deploy_production:
<<: *default_job
stage: deploy
environment:
name: production
url: https://example.com
script:
- echo "Deploying to production..."
- kubectl set image deployment/app app=$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA -n production
- kubectl rollout status deployment/app -n production
when: manual
only:
- main
5. Расширенные возможности
# Параллельное выполнение тестов
parallel_tests:
<<: *default_job
stage: test
parallel: 5
script:
- pytest tests/ -n auto --dist=loadfile
# Кросс-платформенные сборки
multi_arch_build:
<<: *default_job
stage: build
script:
- docker buildx create --use
- docker buildx build --platform linux/amd64,linux/arm64 -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA --push .
# Сканирование зависимостей
dependency_scan:
stage: security
image: ruby:3.1
script:
- gem install bundler-audit
- bundle audit check --update
Best Practices:
➤ Использовать кеширование для ускорения
➤ Разделять тесты на unit/integration/e2e
➤ Настраивать артефакты между стадиями
➤ Использовать manual деплой на production
➤ Мониторить производительность пайплайнов
🌐 @helcode
❤3👍2
Ansible: автоматизация настройки серверов
Цель: Автоматизировать настройку и управление серверной инфраструктурой
Проблема: Ручная настройка серверов, дрейф конфигураций
Решение: Внедрение Ansible для идемпотентного управления конфигурациями
1. Структура проекта Ansible
2. Базовый плейбук
3. Роль для настройки Nginx
4. Шаблоны конфигураций
5. Продвинутые техники
6. Использование Vault для секретов
Best Practices:
➤ Использовать роли для модульности
➤ Шифровать секреты с помощью ansible-vault
➤ Тестировать плейбуки в staging
➤ Использовать теги для выборочного выполнения
➤ Настраивать правильную обработку ошибок
🌐 @helcode
Цель: Автоматизировать настройку и управление серверной инфраструктурой
Проблема: Ручная настройка серверов, дрейф конфигураций
Решение: Внедрение Ansible для идемпотентного управления конфигурациями
1. Структура проекта Ansible
ansible-project/
├── inventory/
│ ├── production
│ ├── staging
│ └── group_vars/
├── roles/
│ ├── nginx/
│ ├── postgresql/
│ └── app/
├── playbooks/
│ ├── site.yml
│ ├── database.yml
│ └── deploy.yml
└── ansible.cfg
2. Базовый плейбук
# playbooks/site.yml
- name: Configure web servers
hosts: webservers
become: yes
vars:
nginx_worker_processes: 4
app_version: "1.2.3"
roles:
- role: nginx
- role: app
- name: Configure database servers
hosts: dbservers
become: yes
roles:
- role: postgresql
3. Роль для настройки Nginx
# roles/nginx/tasks/main.yml
- name: Install nginx
apt:
name: nginx
state: latest
update_cache: yes
- name: Configure nginx
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
backup: yes
notify: restart nginx
- name: Enable nginx service
systemd:
name: nginx
enabled: yes
state: started
# roles/nginx/handlers/main.yml
- name: restart nginx
systemd:
name: nginx
state: restarted
4. Шаблоны конфигураций
# roles/nginx/templates/nginx.conf.j2
user www-data;
worker_processes {{ nginx_worker_processes }};
pid /run/nginx.pid;
events {
worker_connections 1024;
use epoll;
}
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
gzip on;
gzip_types text/plain text/css application/json application/javascript;
server {
listen 80;
server_name {{ inventory_hostname }};
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
}
5. Продвинутые техники
# Динамический inventory для облачных провайдеров
- name: Configure AWS instances
hosts: localhost
gather_facts: false
tasks:
- ec2_instance_info:
region: us-east-1
filters:
"tag:Environment": production
register: ec2_instances
- add_host:
name: "{{ item.public_ip_address }}"
groups: aws_instances
loop: "{{ ec2_instances.instances }}"
# Обработка ошибок и повторные попытки
- name: Deploy application
command: /opt/app/deploy.sh
register: deploy_result
retries: 3
delay: 5
until: deploy_result.rc == 0
ignore_errors: yes
- name: Check deployment status
debug:
msg: "Deployment completed successfully"
when: deploy_result.rc == 0
- name: Handle deployment failure
debug:
msg: "Deployment failed after 3 attempts"
when: deploy_result.rc != 0
6. Использование Vault для секретов
# Шифрование секретов
ansible-vault encrypt_string 's3cr3t-p@ssw0rd' --name 'db_password'
# В плейбуке:
- name: Configure database
hosts: dbservers
vars:
db_password: !vault |
$ANSIBLE_VAULT;1.1;AES256
3132333435363738393031323334353637383930313233343536373839303132
tasks:
- name: Create database user
postgresql_user:
name: app_user
password: "{{ db_password }}"
Best Practices:
➤ Использовать роли для модульности
➤ Шифровать секреты с помощью ansible-vault
➤ Тестировать плейбуки в staging
➤ Использовать теги для выборочного выполнения
➤ Настраивать правильную обработку ошибок
🌐 @helcode
❤1
Elastic Stack: централизованное логирование и анализ
Цель: настроить сбор, анализ и визуализацию логов со всей инфраструктуры
Проблема: логи разбросаны по серверам, сложность анализа и поиска проблем
Решение: внедрение Elasticsearch, Logstash и Kibana (ELK Stack)
1. Установка и настройка Elasticsearch
2. Конфигурация Logstash
3. Filebeat для сбора логов
4. Kibana дашборды и визуализации
5. Мониторинг и алертинг
🌐 @helcode
Цель: настроить сбор, анализ и визуализацию логов со всей инфраструктуры
Проблема: логи разбросаны по серверам, сложность анализа и поиска проблем
Решение: внедрение Elasticsearch, Logstash и Kibana (ELK Stack)
1. Установка и настройка Elasticsearch
# docker-compose.yml для ELK
version: '3.8'
services:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:8.9.0
environment:
- discovery.type=single-node
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
- xpack.security.enabled=false
volumes:
- elasticsearch_data:/usr/share/elasticsearch/data
ports:
- "9200:9200"
logstash:
image: docker.elastic.co/logstash/logstash:8.9.0
volumes:
- ./logstash/pipeline:/usr/share/logstash/pipeline
- ./logstash/config:/usr/share/logstash/config
ports:
- "5044:5044"
depends_on:
- elasticsearch
kibana:
image: docker.elastic.co/kibana/kibana:8.9.0
environment:
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
ports:
- "5601:5601"
depends_on:
- elasticsearch
volumes:
elasticsearch_data:
2. Конфигурация Logstash
# logstash/pipeline/01-inputs.conf
input {
beats {
port => 5044
}
tcp {
port => 5000
codec => json
}
}
# logstash/pipeline/02-filters.conf
filter {
# Парсинг nginx логов
if [fileset][module] == "nginx" {
grok {
match => { "message" => "%{IPORHOST:remote_ip} - %{DATA:user_name} \[%{HTTPDATE:timestamp}\] \"%{WORD:method} %{DATA:url} HTTP/%{NUMBER:http_version}\" %{NUMBER:response_code} %{NUMBER:body_sent_bytes} \"%{DATA:referrer}\" \"%{DATA:agent}\"" }
}
date {
match => [ "timestamp", "dd/MMM/YYYY:HH:mm:ss Z" ]
}
geoip {
source => "remote_ip"
}
}
# Парсинг application логов
if [logger_name] == "app" {
grok {
match => { "message" => "\[%{TIMESTAMP_ISO8601:timestamp}\] %{LOGLEVEL:level} %{DATA:class} - %{GREEDYDATA:message}" }
}
}
}
# logstash/pipeline/03-outputs.conf
output {
elasticsearch {
hosts => ["elasticsearch:9200"]
index => "logs-%{+YYYY.MM.dd}"
}
}
3. Filebeat для сбора логов
# filebeat.yml
filebeat.inputs:
- type: log
paths:
- /var/log/nginx/access.log
fields:
type: nginx
environment: production
- type: log
paths:
- /var/log/app/app.log
fields:
type: application
environment: production
output.logstash:
hosts: ["logstash:5044"]
setup.template:
name: "logs"
pattern: "logs-*"
4. Kibana дашборды и визуализации
// Пример сохраненного поиска для ошибок
{
"query": {
"bool": {
"must": [
{
"match": {
"level": "ERROR"
}
},
{
"range": {
"@timestamp": {
"gte": "now-1h"
}
}
}
]
}
}
}
5. Мониторинг и алертинг
// Kibana Alert для мониторинга ошибок
{
"name": "High Error Rate",
"schedule": {
"interval": "5m"
},
"conditions": {
"agg_type": "count",
"threshold_comparator": ">",
"threshold": [100]
},
"actions": [
{
"type": "email",
"subject": "High Error Rate Detected",
"to": ["admin@example.com"],
"message": "Error count: {{context.conditions.0.agg_value}}"
}
]
}
🌐 @helcode
👍3❤2
6. Оптимизация производительности
Best Practices:
➤ Использовать структурированное логирование
➤ Настраивать ротацию индексов
➤ Мониторить производительность кластера
➤ Использовать index templates для консистентности
➤ Настраивать алертинг на аномалии в логах
🌐 @helcode
# Индекс-темплейты для оптимизации
PUT _template/logs_template
{
"index_patterns": ["logs-*"],
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1,
"refresh_interval": "30s"
},
"mappings": {
"properties": {
"@timestamp": {"type": "date"},
"message": {"type": "text"},
"level": {"type": "keyword"},
"remote_ip": {"type": "ip"}
}
}
}
# Политика управления индексами (ILM)
PUT _ilm/policy/logs_policy
{
"policy": {
"phases": {
"hot": {
"actions": {
"rollover": {
"max_size": "50gb",
"max_age": "7d"
}
}
},
"delete": {
"min_age": "30d",
"actions": {
"delete": {}
}
}
}
}
}
Best Practices:
➤ Использовать структурированное логирование
➤ Настраивать ротацию индексов
➤ Мониторить производительность кластера
➤ Использовать index templates для консистентности
➤ Настраивать алертинг на аномалии в логах
🌐 @helcode
👍2❤1
🐳 Kubernetes: Мониторинг и отладка приложений
Цель: настроить эффективный мониторинг и отладку приложений в Kubernetes
Проблема: сложность диагностики проблем в распределенной среде
Решение: комплексный подход к мониторингу и отладке
1. Установка Prometheus Stack
2. Конфигурация мониторинга приложений
3. Отладка и диагностика
4. Полезные PromQL запросы
5. Расширенная диагностика
6. Автоматическое масштабирование
Best Practices:
➤ Настраивать readiness и liveness пробы
➤ Использовать структурированное логирование
➤ Мониторить бизнес-метрики
➤ Настраивать автоматическое масштабирование
➤ Регулярно проводить chaos testing
🌐 @helcode
Цель: настроить эффективный мониторинг и отладку приложений в Kubernetes
Проблема: сложность диагностики проблем в распределенной среде
Решение: комплексный подход к мониторингу и отладке
1. Установка Prometheus Stack
# Добавление репозитория и установка
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
# Установка kube-prometheus-stack
helm install monitoring prometheus-community/kube-prometheus-stack \
--namespace monitoring \
--create-namespace \
--set grafana.adminPassword=admin \
--set prometheus.service.type=NodePort \
--set alertmanager.service.type=NodePort
2. Конфигурация мониторинга приложений
# ServiceMonitor для кастомного приложения
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: app-monitor
namespace: default
spec:
selector:
matchLabels:
app: my-app
endpoints:
- port: web
path: /metrics
interval: 30s
relabelings:
- sourceLabels: [__meta_kubernetes_pod_name]
targetLabel: pod
- sourceLabels: [__meta_kubernetes_namespace]
targetLabel: namespace
3. Отладка и диагностика
# Просмотр логов нескольких подов
kubectl logs -f deployment/app --all-containers=true --prefix=true --tail=100
# Отладка проблем с сетью
kubectl run debug-pod --image=nicolaka/netshoot --rm -i --tty -- /bin/bash
# Проверка DNS
nslookup kubernetes.default.svc.cluster.local
# Проверка сетевой связности
curl -v http://app-service:8080/health
# Анализ ресурсов
kubectl top pods --containers
kubectl describe pod app-pod-12345
kubectl get events --sort-by=.lastTimestamp
4. Полезные PromQL запросы
# Использование CPU по неймспейсам
sum(rate(container_cpu_usage_seconds_total{namespace="production"}[5m])) by (pod)
# Использование памяти
container_memory_working_set_bytes{container!="", container!="POD"}
# Rate HTTP ошибок
rate(http_requests_total{status=~"5.."}[5m])
# Latency перцентили
histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))
5. Расширенная диагностика
# Pod для отладки с полным доступом
apiVersion: v1
kind: Pod
metadata:
name: debug-pod
spec:
hostNetwork: true
hostPID: true
containers:
- name: debug
image: busybox
command: ["sleep", "3600"]
securityContext:
privileged: true
volumeMounts:
- name: host-root
mountPath: /host
volumes:
- name: host-root
hostPath:
path: /
6. Автоматическое масштабирование
# Horizontal Pod Autoscaler
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: app-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: app
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
behavior:
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Percent
value: 50
periodSeconds: 60
Best Practices:
➤ Настраивать readiness и liveness пробы
➤ Использовать структурированное логирование
➤ Мониторить бизнес-метрики
➤ Настраивать автоматическое масштабирование
➤ Регулярно проводить chaos testing
🌐 @helcode
Как не сжечь репозиторий и остаться в живых?
Случалось ли Вам делать
Вот три спасательных круга:
➤ Отмена последнего коммита (с сохранением изменений в рабочей директории):
➤ Полная отмена коммита и всех изменений (опасно!):
➤ Волшебная палочка для удаления одного файла из коммита (например,
🌐 @helcode
Случалось ли Вам делать
git commit и тут же понимать, что отправили в историю код, который ломает всё? Или закоммитить файл с паролями, который тут же надо спрятать? Паника? Не надо. У Git есть свои «Машина времени» и «Империус».Вот три спасательных круга:
➤ Отмена последнего коммита (с сохранением изменений в рабочей директории):
git reset --soft HEAD~1
➤ Полная отмена коммита и всех изменений (опасно!):
git reset --hard HEAD~1
➤ Волшебная палочка для удаления одного файла из коммита (например,
config.py с паролями):git reset HEAD~1 config.py # Вытаскиваем файл из коммита
git restore config.py # Откатываем его в рабочей директории
git commit --amend # Перезаписываем предыдущий коммит
git reset — это не кнопка удаления, а инструмент перемещения указателя HEAD на другой коммит. Флаг --soft оставляет изменения в индексе, --mixed (по умолчанию) — в рабочей директории, а --hard — безжалостно стирает.git reset --hard — это как «Авада Кедавра» для кода. Произносить с осторожностью.🌐 @helcode
👍6
Ветка — не дерево, или Как не заблудиться в трех соснах
Работа в одной ветке
Создаем и переключаемся на ветку для новой фичи:
Эквивалент новой модной команды:
Слияние ветки в
Ветка в Git — это всего лишь легковесный подвижный указатель на коммит. Когда мы создаем новую ветку, мы не копируем весь код, мы просто создаем новую метку, которая начинает двигаться вперед с коммитами.
Название ветки
🌐 @helcode
Работа в одной ветке
main — это как готовить завтрак, обед и ужин на одной сковородке, не помыв ее. Хаос, грязь и все ненавидят друг друга. Ветвление — основа цивилизованной разработки.Создаем и переключаемся на ветку для новой фичи:
git checkout -b feature/magic-button
Эквивалент новой модной команды:
git switch -c feature/magic-button
Слияние ветки в
main (после ПР):git switch main
git merge feature/magic-button
Ветка в Git — это всего лишь легковесный подвижный указатель на коммит. Когда мы создаем новую ветку, мы не копируем весь код, мы просто создаем новую метку, которая начинает двигаться вперед с коммитами.
Название ветки
patch-1 говорит о нашей фантазии так же много, как имя «Кот» для кота.🌐 @helcode
👍3❤1