Helcode | Хелкод | Скрипты и автоматизация
993 subscribers
52 photos
34 links
☎️ Контакты для связи: @helcodeadm
Download Telegram
Docker в продакшене: безопасность и оптимизация

Цель: настроить безопасные и эффективные 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
# Установка
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
👍32🔥1
Prometheus Alertmanager: настройка интеллектуального алертинга

Цель: создать эффективную систему оповещений о проблемах в инфраструктуре

Проблема: отсутствие своевременных уведомлений о критических инцидентах

Решение: настройка 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
👍31
PostgreSQL: оптимизация производительности и мониторинг

Цель: повысить производительность 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
👍62🤔1
GitLab CI/CD: создание эффективных пайплайнов

Цель: Настроить автоматизированные пайплайны для тестирования и деплоя

Проблема: Ручные процессы деплоя, отсутствие автоматического тестирования

Решение: Внедрение 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
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
# 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
👍32
6. Оптимизация производительности
# Индекс-темплейты для оптимизации
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
👍21
🐳 Kubernetes: Мониторинг и отладка приложений

Цель: настроить эффективный мониторинг и отладку приложений в 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
Как не сжечь репозиторий и остаться в живых?

Случалось ли Вам делать 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
Ветка — не дерево, или Как не заблудиться в трех соснах

Работа в одной ветке 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
👍31
Страшная сказка на ночь: мердж-конфликт

Вы с коллегой независимо изменили одну и ту же строку в одном файле. Вы оба делаете git merge и... Внезапно Git снимает с себя ответственность и показывает это душераздирающее сообщение: CONFLICT (content). Знакомо?

Вот как выглядит файл в состоянии конфликта:
print("Hello, World!")
<<<<<<< HEAD
print("Новая крутая фича от меня!")
=======
print("Исправление критического бага от коллеги!")
>>>>>>> branch-hotfix

Решение: необходимо вручную выбрать, что оставить, а что удалить, убрав маркеры <<<<<<<, ======= и >>>>>>>.

Конфликт — это не баг, это фича. Git не может решить, какое изменение более важное — наша новая фича или критический хотфикс коллеги. Он просит нас, как разумного разработчика, принять взвешенное решение.

Опишите в комментарии самый эпичный или смешной мердж-конфликт в своей практике. Кто победил: фича или багфикс?


🌐 @helcode
1
Stash: карманная заглушка для беспорядка

На полпути в грязной работе над фичей, а нам срочно нужно переключиться на другую ветку, чтобы пофиксить баг. Делать коммит с сообщением «wip» (work in progress) — моветон. Что делать?

Волшебная команда, которая прячет все незакоммиченные изменения:
git stash

Вернуть спрятанное обратно:
git stash pop

Посмотреть список своих «заначек»:
git stash list

Спрятать изменения, включая неотслеживаемые файлы:
git stash -u


git stash создает специальный коммит, который не привязан ни к какой ветке, и возвращает нашу рабочую директорию к состоянию последнего коммита. Это временное хранилище для черновиков.

Как часто вы используете stash? Это Ваш ежедневный инструмент или спасательный круг на крайний случай?

git stash — это аналог «быстро зашвырнуть все вещи в шкаф, когда звонит домофон и приехала теща». Главное — не забыть потом pop, иначе будем искать свои носки полгода.

🌐 @helcode
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 — это как отправить посылку, предварительно наклеив на нее всю пыль и мусор со склада.

🌐 @helcode
Please open Telegram to view this post
VIEW IN TELEGRAM
1
Rebase vs Merge: холивар, который мы заслужили

Нужно влить свою ветку в 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 на общей ветке - это как взять чужой паспорт и начать вклеивать в него новые фотографии.

🌐 @helcode
Please open Telegram to view this post
VIEW IN TELEGRAM
8🔥4
Git Hooks: Твой личный робот-помощник

Хотите, чтобы код автоматически прогонял тесты перед каждым коммитом? Или чтобы линтер проверял стиль? Или чтобы скрипт развертывания сам запускался после пуш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-commit

Git Hooks — это скрипты, которые Git запускает в ответ на определенные события (commit, push, rebase и т.д.). Они выполняются локально и позволяют автоматизировать рутину и внедрить контроль качества.

Какой самый полезный или безумный Git Hook Вы когда-либо использовали или хотели бы использовать? Поделитесь идеями!

Настроить pre-commit хук — это как нанять очень принципиального секьюрити, который не пустит Вас на работу в пижаме. Иногда раздражает, но в итоге все только выигрывают.

🌐 @helcode
Please open Telegram to view this post
VIEW IN TELEGRAM
👍61
Параллельное выполнение задач с xargs

Нужно обработать много файлов или выполнить много команд параллельно?

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 - передавать по одному аргументу

🌐 @helcode
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3👌3👍2
xargs: для тех, кто устал копировать вывод команд

Знакомо: 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 — это как шеф-повар, который берет ингредиенты (список файлов) и готовит из них блюдо (выполняет команду). Без него пришлось бы все делать вручную.


🌐 @helcode
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9
xargs -I: Когда нужно подставить аргумент именно В ТО САМОЕ МЕСТО

А что если команда ожидает аргумент не в конце, а в середине? Например, нужно переименовать файлы или выполнить сложную операцию? Обычный 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 {} — это как заказать бургер "все кроме котлеты" — полный контроль над тем, что и куда попадает.


🌐 @helcode
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8🤔1
xargs + parallel: скорость света для массовых операций

Нужно обработать 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 самому себе!


🌐 @helcode
Please open Telegram to view this post
VIEW IN TELEGRAM
👍81🔥1
xargs в бою: реальные сценарии из жизни DevOps

Теория — это хорошо, но давайте посмотрим, как 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 в руках опытного инженера — это как швейцарский нож: может и консервную банку открыть, и палатку поставить, и даже починить машину в крайнем случае. 🔧


🌐 @helcode
Please open Telegram to view this post
VIEW IN TELEGRAM
👍61