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
Страшная сказка на ночь: мердж-конфликт
Вы с коллегой независимо изменили одну и ту же строку в одном файле. Вы оба делаете
Вот как выглядит файл в состоянии конфликта:
Решение: необходимо вручную выбрать, что оставить, а что удалить, убрав маркеры
Конфликт — это не баг, это фича. Git не может решить, какое изменение более важное — наша новая фича или критический хотфикс коллеги. Он просит нас, как разумного разработчика, принять взвешенное решение.
Опишите в комментарии самый эпичный или смешной мердж-конфликт в своей практике. Кто победил: фича или багфикс?
🌐 @helcode
Вы с коллегой независимо изменили одну и ту же строку в одном файле. Вы оба делаете
git merge и... Внезапно Git снимает с себя ответственность и показывает это душераздирающее сообщение: CONFLICT (content). Знакомо?Вот как выглядит файл в состоянии конфликта:
print("Hello, World!")
<<<<<<< HEAD
print("Новая крутая фича от меня!")
=======
print("Исправление критического бага от коллеги!")
>>>>>>> branch-hotfixРешение: необходимо вручную выбрать, что оставить, а что удалить, убрав маркеры
<<<<<<<, ======= и >>>>>>>.Конфликт — это не баг, это фича. Git не может решить, какое изменение более важное — наша новая фича или критический хотфикс коллеги. Он просит нас, как разумного разработчика, принять взвешенное решение.
Опишите в комментарии самый эпичный или смешной мердж-конфликт в своей практике. Кто победил: фича или багфикс?
🌐 @helcode
❤1
Stash: карманная заглушка для беспорядка
На полпути в грязной работе над фичей, а нам срочно нужно переключиться на другую ветку, чтобы пофиксить баг. Делать коммит с сообщением «wip» (work in progress) — моветон. Что делать?
Волшебная команда, которая прячет все незакоммиченные изменения:
Вернуть спрятанное обратно:
Посмотреть список своих «заначек»:
Спрятать изменения, включая неотслеживаемые файлы:
Как часто вы используете
🌐 @helcode
На полпути в грязной работе над фичей, а нам срочно нужно переключиться на другую ветку, чтобы пофиксить баг. Делать коммит с сообщением «wip» (work in progress) — моветон. Что делать?
Волшебная команда, которая прячет все незакоммиченные изменения:
git stash
Вернуть спрятанное обратно:
git stash pop
Посмотреть список своих «заначек»:
git stash list
Спрятать изменения, включая неотслеживаемые файлы:
git stash -u
git stash создает специальный коммит, который не привязан ни к какой ветке, и возвращает нашу рабочую директорию к состоянию последнего коммита. Это временное хранилище для черновиков.Как часто вы используете
stash? Это Ваш ежедневный инструмент или спасательный круг на крайний случай?git stash — это аналог «быстро зашвырнуть все вещи в шкаф, когда звонит домофон и приехала теща». Главное — не забыть потом pop, иначе будем искать свои носки полгода.Please open Telegram to view this post
VIEW IN TELEGRAM
❤5🔥1
.gitignore: искусство прятать концы в водуСколько раз Вы видели коммиты с файлами
node_modules/, .DS_Store, *.pyc или, не дай бог, .env с продакшн-ключами? Это мусор, который не должен быть в репозитории. Файл .gitignore — наш лучший друг и санитар.Создаем в корне проекта файл
.gitignore и добавляем в него шаблоны:# Логи и кэш
*.log
.npm/
# Файлы ОС
.DS_Store
Thumbs.db
# Файлы окружения (НЕ КОММИТИТЬ НИКОГДА!)
.env
config.ini
# Зависимости (для Node.js)
node_modules/
# Артефакты сборки (для Python)
__pycache__/
*.pyc
Git проверяет файл
.gitignore перед тем, как отслеживать изменения. Если имя файла или папки совпадает с шаблоном внутри — Git делает вид, что этого объекта не существует. Это экономит место, время и нервы.Поделитесь своим самым ценным или неочевидным правилом в
.gitignore! Что такого Вы добавили, о чем другие могут не знать?Закоммитить
node_modules — это как отправить посылку, предварительно наклеив на нее всю пыль и мусор со склада.Please open Telegram to view this post
VIEW IN TELEGRAM
❤1
Rebase vs Merge: холивар, который мы заслужили
Нужно влить свою ветку в
➤ Merge (слияние): cоздает коммит с двумя родителями.
История:
➤ Rebase (перебазирование): перемещает наши коммиты на верхушку
История:
➤ Merge сохраняет всю историю разработки, включая факт ветвления. Безопасен для публичных веток.
➤ Rebase переписывает историю, делая ее линейной и чистой. Отлично подходит для локальной чистки перед пулл-реквестом. Опасно использовать на общих ветках.
Ставьте реакцию:
❤️ — за Merge (история должна быть правдой!).
🔥 — за Rebase (чистота и порядок превыше всего!).
Использовать
🌐 @helcode
Нужно влить свою ветку в
main. Два лагеря, две религии. Одни кричат: «Rebase — чистая история!». Другие: «Merge — правдивая история!». Кто прав? Давайте без драки, только хардкор.➤ Merge (слияние): cоздает коммит с двумя родителями.
git checkout main
git merge feature/branch
История:
--o--o--o--m (где m — merge-коммит)➤ Rebase (перебазирование): перемещает наши коммиты на верхушку
main, как будто мы начали работу только что.git checkout feature/branch
git rebase main
История:
--o--o--o--o--o (идеально прямая линия)➤ Merge сохраняет всю историю разработки, включая факт ветвления. Безопасен для публичных веток.
➤ Rebase переписывает историю, делая ее линейной и чистой. Отлично подходит для локальной чистки перед пулл-реквестом. Опасно использовать на общих ветках.
Ставьте реакцию:
❤️ — за Merge (история должна быть правдой!).
🔥 — за Rebase (чистота и порядок превыше всего!).
Использовать
git rebase на общей ветке - это как взять чужой паспорт и начать вклеивать в него новые фотографии.Please open Telegram to view this post
VIEW IN TELEGRAM
❤8🔥4
Git Hooks: Твой личный робот-помощник
Хотите, чтобы код автоматически прогонял тесты перед каждым коммитом? Или чтобы линтер проверял стиль? Или чтобы скрипт развертывания сам запускался после пушa в
Хуки лежат в папке
Не забудьте дать файлу права на выполнение:
Git Hooks — это скрипты, которые Git запускает в ответ на определенные события (commit, push, rebase и т.д.). Они выполняются локально и позволяют автоматизировать рутину и внедрить контроль качества.
Какой самый полезный или безумный Git Hook Вы когда-либо использовали или хотели бы использовать? Поделитесь идеями!
Настроить
🌐 @helcode
Хотите, чтобы код автоматически прогонял тесты перед каждым коммитом? Или чтобы линтер проверял стиль? Или чтобы скрипт развертывания сам запускался после пушa в
main? Пора познакомиться с Git Hooks.Хуки лежат в папке
.git/hooks/. Пример пре-коммит хука (.git/hooks/pre-commit), который не даст закоммитить код, не прошедший линтинг:#!/bin/sh
echo "Запуск линтера..."
if ! eslint --cache --fix .; then
echo "Линтер нашел ошибки! Коммит отменен."
exit 1
fi
git add . # Добавляем исправления, сделанные линтером
Не забудьте дать файлу права на выполнение:
chmod +x .git/hooks/pre-commitGit Hooks — это скрипты, которые Git запускает в ответ на определенные события (commit, push, rebase и т.д.). Они выполняются локально и позволяют автоматизировать рутину и внедрить контроль качества.
Какой самый полезный или безумный Git Hook Вы когда-либо использовали или хотели бы использовать? Поделитесь идеями!
Настроить
pre-commit хук — это как нанять очень принципиального секьюрити, который не пустит Вас на работу в пижаме. Иногда раздражает, но в итоге все только выигрывают.Please open Telegram to view this post
VIEW IN TELEGRAM
👍6❤1
Параллельное выполнение задач с xargs
Нужно обработать много файлов или выполнить много команд параллельно?
Ключевые параметры:
➤
➤
➤
➤
🌐 @helcode
Нужно обработать много файлов или выполнить много команд параллельно?
xargs с параллельным выполнением# Поиск и удаление старых логов параллельно
find /var/log -name "*.log" -mtime +30 | xargs -P 4 -I {} rm -v {}
# Параллельная загрузка URL из файла
cat urls.txt | xargs -P 8 -I {} curl -O {}
# Массовое конвертирование изображений
find ./images -name "*.jpg" | xargs -P 2 -I {} convert {} -resize 50% resized/{}
# Обработка с пробелами в именах файлов
find . -name "*.txt" -print0 | xargs -0 -P 4 -I {} wc -l {}
Ключевые параметры:
➤
-P N - количество параллельных процессов➤
-I {} - замена входящих данных➤
-0 - для работы с именами с пробелами➤
-n 1 - передавать по одному аргументуPlease open Telegram to view this post
VIEW IN TELEGRAM
🔥3👌3👍2
xargs: для тех, кто устал копировать вывод команд
Знакомо:
Найдем все
Или более безопасный вариант с обработкой пробелов в именах:
А вы часто используете xargs? Или предпочитаете другие способы (циклы for, -exec в find)?
🌐 @helcode
Знакомо:
ls | grep .txt показывает файлы, а чтобы удалить их все, приходится либо копировать каждый, либо писать сложную конструкцию? xargs — это мост между stdout одной команды и аргументами другой.Найдем все
.tmp файлы и удалим их одной командой:find . -name "*.tmp" | xargs rm
Или более безопасный вариант с обработкой пробелов в именах:
find . -name "*.tmp" -print0 | xargs -0 rm
xargs берет поток данных с входа (например, список файлов от find) и превращает его в аргументы для указанной команды (rm). Без xargs команда rm не знала бы, что делать со списком файлов из stdin.А вы часто используете xargs? Или предпочитаете другие способы (циклы for, -exec в find)?
xargs — это как шеф-повар, который берет ингредиенты (список файлов) и готовит из них блюдо (выполняет команду). Без него пришлось бы все делать вручную.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9
xargs -I: Когда нужно подставить аргумент именно В ТО САМОЕ МЕСТО
А что если команда ожидает аргумент не в конце, а в середине? Например, нужно переименовать файлы или выполнить сложную операцию? Обычный
Допустим, хотим создать бэкапы всех
Или переименовать файлы, добавив префикс:
Флаг
Попробуйте сами! Создайте тестовые файлы и переименуйте их с помощью xargs -I. Какой placeholder Вы используете?
1. {} — классика
2. FILE — для ясности
3. Что-то свое — напишите в комментах!
🌐 @helcode
А что если команда ожидает аргумент не в конце, а в середине? Например, нужно переименовать файлы или выполнить сложную операцию? Обычный
xargs не справится — тут нужен флаг -I.Допустим, хотим создать бэкапы всех
.py файлов:find . -name "*.py" | xargs -I {} cp {} {}.backupИли переименовать файлы, добавив префикс:
ls *.txt | xargs -I FILE mv FILE PREFIX_FILE
Флаг
-I позволяет задать placeholder (обычно {}), который будет заменен на каждый элемент входа. Это дает полный контроль над тем, куда подставляются аргументы в команде.Попробуйте сами! Создайте тестовые файлы и переименуйте их с помощью xargs -I. Какой placeholder Вы используете?
1. {} — классика
2. FILE — для ясности
3. Что-то свое — напишите в комментах!
xargs -I {} — это как заказать бургер "все кроме котлеты" — полный контроль над тем, что и куда попадает.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8🤔1
xargs + parallel: скорость света для массовых операций
Нужно обработать 1000 файлов, но делать это последовательно — слишком долго?
Скачаем несколько URL параллельно (4 процесса одновременно):
Или обработаем изображения параллельно:
-
-
Это превращает линейную обработку в конвейерную, ускоряя работу в разы!
А вы используете параллельное выполнение? Поделитесь своими кейсами!
🌐 @helcode
Нужно обработать 1000 файлов, но делать это последовательно — слишком долго?
xargs может запускать процессы параллельно, используя все ядра процессора!Скачаем несколько URL параллельно (4 процесса одновременно):
cat urls.txt | xargs -n 1 -P 4 wget
Или обработаем изображения параллельно:
find . -name "*.jpg" | xargs -n 1 -P 8 convert -resize 50%
-
-P N — запускает N процессов параллельно-
-n 1 — передает по одному аргументу каждому процессуЭто превращает линейную обработку в конвейерную, ускоряя работу в разы!
А вы используете параллельное выполнение? Поделитесь своими кейсами!
Параллельный xargs — это как нанять бригаду рабочих вместо одного. Главное — не переборщить, а то устроите DDoS самому себе!
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8❤1🔥1
xargs в бою: реальные сценарии из жизни DevOps
Теория — это хорошо, но давайте посмотрим, как
Сценарий 1: массовый деплой на несколько серверов
Сценарий 2: поиск и убийство заблокированных процессов
Сценарий 3: пакетное обновление Docker контейнеров
Сила
Поделитесь своим самым крутым или неочевидным использованием xargs! Какой пайплайн с xargs вы считаете своим козырем?
🌐 @helcode
Теория — это хорошо, но давайте посмотрим, как
xargs спасает в реальных рабочих ситуациях. От массового деплоя до экстренного фикса проблем.Сценарий 1: массовый деплой на несколько серверов
cat servers.txt | xargs -I SERVER ssh SERVER "cd /app && git pull && systemctl restart myapp"
Сценарий 2: поиск и убийство заблокированных процессов
ps aux | grep "zombie_process" | awk '{print $2}' | xargs kill -9Сценарий 3: пакетное обновление Docker контейнеров
docker ps -aq | xargs docker stop
docker ps -aq | xargs docker rm
Сила
xargs в комбинации с другими утилитами: find, grep, awk, docker. Он становится клеем, который связывает отдельные команды в мощные автоматизированные пайплайны.Поделитесь своим самым крутым или неочевидным использованием xargs! Какой пайплайн с xargs вы считаете своим козырем?
xargs в руках опытного инженера — это как швейцарский нож: может и консервную банку открыть, и палатку поставить, и даже починить машину в крайнем случае. 🔧
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6❤1