Масштабирование инфраструктуры с помощью Kubernetes и RKE2: углубленный анализ производства
Руководство инженера-технолога по кластерной архитектуре RKE2, горизонтальному и вертикальному автомасштабированию, высокой доступности, управлению ресурсами и наблюдаемости Prometheus/Grafana.
Запуск кластера Kubernetes в производственной среде — это одно. Запуск такого решения, которое может поглощать непредсказуемые всплески трафика, выдерживать сбои плоскости управления, обеспечивать изоляцию клиентов и давать вашей операционной команде четкую видимость каждого уровня системы — это совершенно другая задача. RKE2, дистрибутив Kubernetes следующего поколения от Rancher, создан специально для сред, где эти требования не подлежат обсуждению.
В этой статье описан полный жизненный цикл развертывания RKE2 промышленного уровня: начальная архитектура кластера, автоматическое масштабирование на уровне модулей и узлов, плоскости управления высокой доступности, управление ресурсами и наблюдаемость с помощью Prometheus и Grafana.
Почему RKE2?
RKE2 отличается от предшествующего Kubernetes и от своего предшественника RKE1 в трех ключевых областях. Во-первых, он поставляется с конфигурацией, усиленной CIS Kubernetes Benchmark, — контроллеры доступа, ведение журнала аудита, безопасность модуля и настройки TLS предварительно настроены для прохождения сканирования CIS Level 1 без ручного вмешательства. Во-вторых, он соответствует стандарту FIPS 140-2, что делает его пригодным для использования в государственных учреждениях и регулируемых отраслях. В-третьих, он встраивает контейнер напрямую и поставляется со своим собственным CNI (Canal или Cilium в зависимости от выбора конфигурации), уменьшая площадь внешних зависимостей, которыми вам нужно управлять.
RKE2 также поддерживает воздушные зазоры. В установочный пакет входят все необходимые образы контейнеров, что имеет огромное значение при локальном и периферийном развертывании, где доступ к Интернету с узлов кластера ограничен или невозможен.
Кластерная архитектураРабочий кластер RKE2 разделен на узлы серверов (которые запускают плоскость управления и etcd) и узлы агентов (которые выполняют рабочие нагрузки). Рекомендуемая топология для обеспечения высокой доступности — три или пять серверных узлов и переменное количество узлов агентов, организованных в пулы узлов по классам рабочей нагрузки.
# /etc/rancher/rke2/config.yaml (server node)
token: <shared-cluster-token>
tls-san:
- 10.0.0.10 # VIP or load balancer address
- k8s.internal.example.com
cni: cilium
cluster-cidr: 10.42.0.0/16
service-cidr: 10.43.0.0/16
etcd-expose-metrics: true
kube-apiserver-arg:
- "audit-log-path=/var/log/kubernetes/audit.log"
- "audit-log-maxage=30"
- "audit-log-maxsize=100"# /etc/rancher/rke2/config.yaml (agent node)
server: https://10.0.0.10:9345
token: <shared-cluster-token>
node-label:
- "workload-class=general"
- "topology.kubernetes.io/zone=eu-west-1a"Установите сервер на своем первом узле плоскости управления, затем присоединитесь к остальным узлам сервера и всем узлам агентов, используя тот же токен и VIP-адрес. RKE2 автоматически выбирает лидеров etcd и управляет кворумом.
# Install and start RKE2 server
curl -sfL https://get.rke2.io | INSTALL_RKE2_TYPE=server sh -
systemctl enable --now rke2-server.service
# Retrieve the node token for joining additional nodes
cat /var/lib/rancher/rke2/server/node-token
# Install and start RKE2 agent (on worker nodes)
curl -sfL https://get.rke2.io | INSTALL_RKE2_TYPE=agent sh -
systemctl enable --now rke2-agent.serviceПулы узлови размещение рабочей нагрузки
Не все рабочие нагрузки имеют одинаковый профиль ресурсов. Веб-сервисы без сохранения состояния предъявляют другие требования к заданиям вывода GPU, аналитическим рабочим нагрузкам с интенсивным использованием памяти или базам данных, чувствительным к задержке. Организация узлов агентов в пулы с отдельными метками и метками позволяет Kubernetes планировать каждый класс рабочей нагрузки на оборудовании соответствующего размера.
# Label a node pool for memory-intensive workloads
kubectl label nodes worker-mem-{1..4} workload-class=memory-optimised
kubectl taint nodes worker-mem-{1..4} workload-class=memory-optimised:NoSchedule
# Label a separate pool for general compute
kubectl label nodes worker-gen-{1..8} workload-class=general# Deployment targeting the memory-optimised pool
apiVersion: apps/v1
kind: Deployment
metadata:
name: analytics-engine
spec:
template:
spec:
nodeSelector:
workload-class: memory-optimised
tolerations:
- key: workload-class
operator: Equal
value: memory-optimised
effect: NoSchedule
containers:
- name: analytics
image: registry.internal/analytics:v2.3.1
resources:
requests:
memory: "8Gi"
cpu: "2"
limits:
memory: "16Gi"
cpu: "4"Горизонтальный модуль автомасштабирования
Горизонтальный автомасштабирование модулей (HPA) корректирует количество реплик развертывания или набора состояний на основе наблюдаемых показателей. Использование CPU — это классический триггер, но современные конфигурации HPA также могут масштабироваться на основе пользовательских метрик, предоставляемых вашим приложением, или внешних метрик из таких источников, как глубина очереди сообщений.
Сначала убедитесь, что сервер метрик работает — RKE2 не включает его по умолчанию.
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yamlapiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: api-server-hpa
namespace: production
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: api-server
minReplicas: 3
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 65
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 70
behavior:
scaleDown:
stabilizationWindowSeconds: 300 # wait 5 minutes before scaling down
policies:
- type: Percent
value: 25
periodSeconds: 60
scaleUp:
stabilizationWindowSeconds: 0
policies:
- type: Percent
value: 100
periodSeconds: 30Блокbehaviorимеет решающее значение для стабильности. Без окна стабилизации с уменьшением масштаба кратковременное падение трафика приведет к преждевременному удалению модулей, что приведет к недостаточному обеспечению при возобновлении нагрузки. Асимметричная политика — агрессивное увеличение и консервативное уменьшение — является подходящим вариантом по умолчанию для большинства производственных рабочих нагрузок.
Вертикальный модуль автомасштабирования
Вертикальный модуль автомасштабирования (VPA) корректирует размер CPU и запросы памяти для отдельных модулей на основе наблюдаемого использования. Это решает распространенную проблему: разработчики устанавливают начальные запросы ресурсов на основе догадок, и эти значения никогда не обновляются, что приводит либо к расточительному выделению ресурсов, либо к OOMKilled модулям под нагрузкой.
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: worker-vpa
namespace: production
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: background-worker
updatePolicy:
updateMode: "Auto" # or "Off" to only view recommendations
resourcePolicy:
containerPolicies:
- containerName: worker
minAllowed:
cpu: 100m
memory: 256Mi
maxAllowed:
cpu: 4
memory: 8Gi
controlledResources: ["cpu", "memory"]Обратите внимание, что VPA в режимеAutoудаляет и перезапускает модули для применения новых значений ресурсов. Для сервисов, в которых текущие запросы не могут быть прерваны, запустите VPA в режимеOff, чтобы сгенерировать рекомендации, которые можно применить вручную или с помощью рабочего процесса GitOps во время периодов обслуживания.
Важно:HPA и VPA не должны одновременно управлять одним и тем же ресурсом (CPU или памятью) в одном и том же развертывании. Используйте HPA для горизонтального масштабирования на основе CPU и VPA в режимеOffдля правильного размера памяти или используйтеKEDAдля масштабирования на основе событий, где требуется детальный контроль.
работает в пределах существующей мощности узла. Когда эта емкость исчерпана — модули зависают вPending, поскольку ни один узел не имеет достаточных ресурсов — вам понадобится Cluster Autoscaler для подготовки новых узлов. И наоборот, когда узлы используются недостаточно, Cluster Autoscaler может опустошить и вывести их из эксплуатации, чтобы снизить затраты на инфраструктуру.
При развертывании на «голом железе» или локальном развертывании Cluster Autoscaler интегрируется с уровнем подготовки вашей инфраструктуры. Для развертываний в облаке такие поставщики, как AWS, GCP и Azure, предлагают встроенную интеграцию групп узлов. В следующем примере показана базовая конфигурация группы автоматического масштабирования AWS.
apiVersion: apps/v1
kind: Deployment
metadata:
name: cluster-autoscaler
namespace: kube-system
spec:
template:
spec:
containers:
- name: cluster-autoscaler
image: registry.k8s.io/autoscaling/cluster-autoscaler:v1.29.0
command:
- ./cluster-autoscaler
- --cloud-provider=aws
- --nodes=2:10:k8s-general-worker-asg
- --nodes=1:4:k8s-memory-worker-asg
- --scale-down-delay-after-add=10m
- --scale-down-unneeded-time=10m
- --scale-down-utilization-threshold=0.5
- --skip-nodes-with-local-storage=false
- --expander=least-waste
env:
- name: AWS_REGION
value: eu-west-1Опция--expander=least-wasteуказывает автомасштабирующему устройству отдать предпочтение группе узлов, которая будет иметь наименьшее количество неиспользуемых ресурсов после размещения ожидающего модуля, что минимизирует затраты. Альтернативные расширители включаютrandom,most-podsиpriority.
Плоскость управления высокой доступности
Трехузловая плоскость управления со встроенным etcd — это минимально жизнеспособная топология высокой доступности. etcd требует кворума — большинство участников должны быть работоспособны, чтобы кластер мог принимать записи. С тремя участниками вы можете стерпеть одну неудачу; с пятью участниками вы можете терпеть двоих.
Узлы плоскости управления должны находиться за балансировщиком нагрузки. Для облачных развертываний хорошо работает балансировщик нагрузки TCP, нацеленный на порты 6443 (kube-apiserver) и 9345 (регистрация RKE2). В локальных развертываниях обычно используется поддержка активности с виртуальным IP-адресом.
# keepalived.conf on control-plane nodes
vrrp_instance VI_1 {
state MASTER # BACKUP on the other two nodes
interface eth0
virtual_router_id 51
priority 100 # 90 and 80 on the other two nodes
advert_int 1
authentication {
auth_type PASS
auth_pass securepassword
}
virtual_ipaddress {
10.0.0.10/24 # VIP used in tls-san and agent server address
}
}Убедитесь, что etcd работоспособен после любой операции на уровне управления. RKE2 объединяетetcdctlи/var/lib/rancher/rke2/bin/etcdctl.
ETCDCTL_API=3 /var/lib/rancher/rke2/bin/etcdctl \
--endpoints=https://127.0.0.1:2379 \
--cacert=/var/lib/rancher/rke2/server/tls/etcd/server-ca.crt \
--cert=/var/lib/rancher/rke2/server/tls/etcd/client.crt \
--key=/var/lib/rancher/rke2/server/tls/etcd/client.key \
endpoint health --clusterКвоты ресурсов и предельные диапазоны
В мультитенантных кластерах, где разные команды или приложения используют одну и ту же физическую инфраструктуру, ResourceQuotas и LimitRanges являются важными барьерами. ResourceQuotas устанавливает жесткие ограничения на общее потребление ресурсов в пространстве имен. LimitRanges устанавливает значения по умолчанию и максимальные значения для отдельных контейнеров, предотвращая запрос неограниченных ресурсов неправильно настроенным развертыванием.
apiVersion: v1
kind: ResourceQuota
metadata:
name: team-alpha-quota
namespace: team-alpha
spec:
hard:
requests.cpu: "20"
requests.memory: 40Gi
limits.cpu: "40"
limits.memory: 80Gi
count/deployments.apps: "20"
count/services: "15"
persistentvolumeclaims: "10"
requests.storage: 500GiapiVersion: v1
kind: LimitRange
metadata:
name: team-alpha-limits
namespace: team-alpha
spec:
limits:
- type: Container
default:
cpu: 500m
memory: 512Mi
defaultRequest:
cpu: 100m
memory: 128Mi
max:
cpu: "8"
memory: 16Gi
- type: PersistentVolumeClaim
max:
storage: 100GiПрименение LimitRanges гарантирует, что разработчики, которые забывают указать запросы ресурсов, по-прежнему будут получать разумные значения по умолчанию, а не запрашивать нулевой CPU, что приведет к тому, что планировщик разместит модуль где угодно и потенциально приведет к прекращению других рабочих нагрузок на том же узле.
Мониторинг с помощью Prometheus и Grafana
Наблюдение в кластере Kubernetes имеет три основных компонента: метрики, журналы и трассировки. Prometheus занимается сбором показателей; Grafana обеспечивает визуализацию. Диаграммаkube-prometheus-stackHelm развертывает весь стек — оператор Prometheus, диспетчер оповещений, Grafana, экспортеры узлов и полный набор предварительно созданных информационных панелей — с помощью одной команды.
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
helm install kube-prometheus-stack prometheus-community/kube-prometheus-stack \
--namespace monitoring \
--create-namespace \
--set prometheus.prometheusSpec.retention=30d \
--set prometheus.prometheusSpec.storageSpec.volumeClaimTemplate.spec.storageClassName=longhorn \
--set prometheus.prometheusSpec.storageSpec.volumeClaimTemplate.spec.resources.requests.storage=100Gi \
--set grafana.adminPassword=<secure-password> \
--set alertmanager.alertmanagerSpec.storage.volumeClaimTemplate.spec.resources.requests.storage=10GiRKE2 предоставляет метрики etcd, еслиetcd-expose-metrics: trueустановлен в конфигурации сервера. Добавьте ServiceMonitor, чтобы Prometheus очищал их.
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: rke2-etcd
namespace: monitoring
labels:
release: kube-prometheus-stack
spec:
namespaceSelector:
matchNames: [kube-system]
selector:
matchLabels:
app.kubernetes.io/name: rke2-etcd
endpoints:
- port: metrics
scheme: https
tlsConfig:
caFile: /etc/prometheus/secrets/etcd-client-cert/ca.crt
certFile: /etc/prometheus/secrets/etcd-client-cert/client.crt
keyFile: /etc/prometheus/secrets/etcd-client-cert/client.keyОсновные правила оповещения
Предварительно созданные информационные панели — это отправная точка, но настраиваемые правила оповещений, адаптированные к вашей среде, позволяют дежурным инженерам действовать до того, как пользователи заметят проблему.
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: workload-alerts
namespace: monitoring
labels:
release: kube-prometheus-stack
spec:
groups:
- name: pod-health
rules:
- alert: PodCrashLooping
expr: rate(kube_pod_container_status_restarts_total[10m]) > 0.5
for: 5m
labels:
severity: critical
annotations:
summary: "Pod {{ $labels.namespace }}/{{ $labels.pod }} is crash-looping"
- alert: NodeMemoryPressure
expr: |
(node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) < 0.1
for: 2m
labels:
severity: warning
annotations:
summary: "Node {{ $labels.node }} memory below 10%"
- alert: HPAMaxedOut
expr: |
kube_horizontalpodautoscaler_status_current_replicas
== kube_horizontalpodautoscaler_spec_max_replicas
for: 15m
labels:
severity: warning
annotations:
summary: "HPA {{ $labels.namespace }}/{{ $labels.horizontalpodautoscaler }} at maximum replicas"ОповещениеHPAMaxedOutособенно ценно на практике. Когда HPA зафиксирован на максимуме в течение длительного периода времени, это означает, что трафик превысил ваш текущий потолок. Вам нужно либо поднять максимум, либо добавить емкость в пул узлов — и вы хотите знать об этом до следующего всплеска, а не во время него.
Лучшие практики производства
Бюджеты на нарушение работы модулей
PodDisruptionBudget (PDB) ограничивает количество модулей в развертывании, которые могут быть одновременно недоступны во время добровольных сбоев, таких как утечка узлов. Без PDB опорожнение узла для обслуживания может привести к отключению всего развертывания.
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: api-server-pdb
namespace: production
spec:
minAvailable: 2 # or use maxUnavailable: 1
selector:
matchLabels:
app: api-serverОграничения расширения топологии
По умолчанию планировщик распределяет реплики по узлам, используя алгоритм «наилучшего из возможных». Ограничения распространения топологии дают вам жесткие гарантии того, что реплики распределяются по зонам доступности или стойкам.
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: api-serverСтратегия обновленияRKE2 поддерживает последовательные обновления через контроллер обновления системы. Вы определяете план, нацеленный на узлы сервера или агента, и указываете целевую версию; контроллер последовательно истощает, обновляет и отключает узлы.
apiVersion: upgrade.cattle.io/v1
kind: Plan
metadata:
name: rke2-server-upgrade
namespace: system-upgrade
spec:
concurrency: 1
cordon: true
nodeSelector:
matchExpressions:
- { key: node-role.kubernetes.io/control-plane, operator: In, values: ["true"] }
serviceAccountName: system-upgrade
upgrade:
image: rancher/rke2-upgrade
version: v1.29.4+rke2r1и т. д. Резервное копирование и восстановление
RKE2 может автоматически создавать запланированные снимки etcd. Убедитесь, что они записаны в долговременное хранилище за пределами кластера — корзину S3 или удаленное подключение NFS, а не на локальный диск на узлах плоскости управления.
# /etc/rancher/rke2/config.yaml additions for automated snapshots
etcd-snapshot-schedule-cron: "0 */6 * * *" # every 6 hours
etcd-snapshot-retention: 10
etcd-snapshot-dir: /mnt/nfs/etcd-snapshots
# Manual snapshot
rke2 etcd-snapshot save --name pre-upgrade-$(date +%Y%m%d)
# Restore from snapshot (run on a single server node with cluster stopped)
rke2 server --cluster-reset --cluster-reset-restore-path=/path/to/snapshot.dbЗаключение
Масштабирование инфраструктуры с помощью RKE2 — это не простое изменение конфигурации — это система взаимосвязанных возможностей, которые необходимо проектировать и эксплуатировать совместно. Горизонтальное автоматическое масштабирование модулей обрабатывает кратковременные всплески трафика на уровне рабочей нагрузки. Вертикальное автоматическое масштабирование модулей обеспечивает честность запросов ресурсов с течением времени. Cluster Autoscaler гарантирует, что базовая мощность узла отслеживает совокупный спрос ваших автомасштабировщиков модулей. Пулы узлов и ограничения топологии гарантируют, что рабочие нагрузки будут выполняться на правильном оборудовании. Квоты ресурсов и диапазоны ограничений защищают арендаторов друг от друга. PodDisruptionBudgets и ограничения распространения топологии повышают доступность. А Prometheus с Grafana дает вашей команде возможность обнаружить ухудшение работы до того, как оно перерастет в сбой.
RKE2 заслужил свое место в производстве именно потому, что значительная часть этого стека поставляется предварительно защищенной и интегрированной. Ваша ответственность — разобраться в регуляторах, настроить их в соответствии с характеристиками вашей рабочей нагрузки и создать рабочую дисциплину — модули Runbook, маршрутизацию оповещений, периодичность обновлений, проверку резервных копий — которая превращает хорошо настроенный кластер в по-настоящему надежную платформу.