Автор: Ронг Бин, внутренний архитектор Kuzha Online, специализирующийся на управлении микросервисами, технологии контейнеризации, Service Mesh и других технических областях.
Рекомендация проекта с открытым исходным кодом
Pepper Metricsэто инструмент с открытым исходным кодом, разработанный мной и моими коллегами (GitHub.com/live-actioncool/pep…), который собирает текущую статистику производительности jedis/mybatis/httpservlet/dubbo/motan и предоставляет ее для основных данных, совместимых с базой данных временных рядов, таких как prometheus, и отображает тенденции через grafana. Его подключаемая архитектура также очень удобна для пользователей, позволяющих расширять и интегрировать другие компоненты с открытым исходным кодом.
Пожалуйста, поставьте звезду и пригласите всех стать разработчиками и отправить PR, чтобы вместе улучшить проект.
Задний план
статус кво
Предыдущая статья в основном посвящена исследованию и тестированию производительности основных сетевых компонентов перед внедрением контейнеризации.Для заинтересованных студентов, пожалуйста, обратитесь к:Тест производительности сети Aliyun K8S CNI с открытым исходным кодом
В настоящее время серверная архитектура компании представляет собой модель микросервисной архитектуры, как показано на рисунке ниже. Весь входящий трафик поступает во внутреннюю службу через шлюз API. Шлюз API действует как «защитник» и контролирует весь входящий трафик, запросы и имеет важные функции, такие как защита от кистей, мониторинг производительности интерфейса и оповещение.После того, как трафик проходит через шлюз, вызовы между сервисами — это все вызовы RPC.
переходный период
После трансформации микросервиса микросервисная архитектура хоть и принесла нам много дивидендов, но и создает некоторые проблемы:
- Разделение сервисов приводит к увеличению количества машин
- Чтобы сократить потери ресурсов, стоимость управления портами, вызванная развертыванием нескольких служб на одном хосте.
- Несогласованная среда доставки, что приводит к затратам на устранение неполадок
Чтобы решить вышеуказанные проблемы, после исследования мы сосредоточимся на контейнерной службе Kubernetes для решения наших проблем.Эта статья в основном посвящена части nginx-ingress-controller (далее именуемой NGINX IC), поэтому следующая архитектура в основном выделяет шлюз API и IC. На картинке ниже показан наш план перехода: Путем введения внутрисетевого SLB для решения проблемы обнаружения сервисов, когда IC является вышестоящим по отношению к нашему шлюзу API. Кроме того, эффекта постепенной миграции можно добиться за счет постепенного переключения интерфейса на SLB, а гранулярность может быть на уровне интерфейс+процент. Схема архитектуры в переходный период выглядит следующим образом:
конечное состояние
После завершения всех миграций все машины перезапускаются, как показано на следующем рисунке:
На самом деле, два слоя SLB будут расточительны, но поскольку наш API-шлюз в настоящее время играет важную роль, мы должны найти альтернативу его удалению. Мы также попытались исследовать решение Istio с пользовательской архитектурой IC или Service Mesh.Поскольку Istio 1.1 еще не был выпущен в то время, а масштабных вариантов использования было слишком мало, мы консервативно выбрали текущее компромиссное решение.Это не очень хлопотно перейти на Istio в будущем.Групповые интеграторы по направлениям деятельности
По умолчанию весь трафик Kubernetes ложится на набор IC по умолчанию, мы с самого начала отказались от этого решения, поэтому необходимо добиться определенной изоляции, развернув несколько наборов IC. Это закончится в форме, показанной выше.Упражняться
Как включить Multi-IC
Глядя на параметры команды запуска ИС, можно найти:
Это означает, что нужно обращать внимание только на определение Ingress с аннотацией «kubernetes.io/ingress.class» и тем же значением, что и параметр параметра запуска IC --ingress-class, если он не совпадает, он будет проигнорирован. , так что достигается несколько групп IC. , изоляция между определениями Ingress. Например:containers:
- args:
- /nginx-ingress-controller
- --ingress-class=xwz #看这里
- --configmap=$(POD_NAMESPACE)/xwz-nginx-configuration
- --tcp-services-configmap=$(POD_NAMESPACE)/xwz-tcp-services
- --udp-services-configmap=$(POD_NAMESPACE)/xwz-udp-services
- --annotations-prefix=nginx.ingress.kubernetes.io
- --publish-service=$(POD_NAMESPACE)/xwz-nginx-ingress-lb
- --v=2
так же как
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: "xwz" #看这里
labels:
app: tap-revision-ing
wayne-app: tap-revision
wayne-ns: coohua
name: tap-revision-ing
namespace: coohua
spec:
rules:
- host: staging.coohua.com
http:
paths:
- backend:
serviceName: tap-revision-stable
servicePort: 80
path: /
Далее давайте взглянем на структуру ресурсов IC, развернутых в Kubernetes, как показано на рисунке:
Видно, что группа ИС фактически состоит из следующих частей:- ServiceAccount, ClusterRole, ClusterRoleBinding: определение разрешений RBAC
- Развертывание: управляет развертыванием контроллера и зависит от ServiceAccount, Configmap, Service
- ConfigMap: три карты конфигурации используются для сохранения пользовательских конфигураций контроллера.
- Служба: здесь используется svc, тип которого LoadBalancer, в основном использует функцию автоматической привязки к экземпляру SLB, реализованную базовыми службами Alibaba Cloud.
Наш сценарий не требует специальной настройки разрешений, поэтому мы просто копируем несколько ресурсов в красное поле и изменяем несколько конфигураций (например, --ingress-class=xwz), а затем напрямую ссылаемся на значение по умолчанию. ServiceAccount IC завершает развертывание. нового набора микросхем и изолирован от микросхем, поставляемых с Kubernetes. Здесь я помещаю конфигурацию, которую написал на своем github, читатели могут обратиться к:ingress resources
После создания новой ИС, если вы обнаружите, что ИС имеет следующие ошибки
E0416 11:31:50.831279 6 leaderelection.go:304] Failed to update lock: configmaps "ingress-controller-leader-xwz" is forbidden: User "system:serviceaccount:kube-system:nginx-ingress-controller" cannot update resource "configmaps" in API group "" in the namespace "kube-system"
Ссылаться наissue, вам нужно изменить кластерную роль: nginx-ingress-controller, добавить следующее содержимое
...
- apiGroups:
- ""
resourceNames:
- ingress-controller-leader-nginx
- ingress-controller-leader-xwz #将新增加的configmap增加进来,不然会报上面提到的错误
resources:
- configmaps
...
Как автоматически добавить расширенный экземпляр IC в список серверных служб SLB
Способ 1 externalTrafficPolicy=Cluster
Когда spec.externalTrafficPolicy of Service имеет значение Cluster: Каждый хост в кластере может действовать как маршрутизатор уровня 3, выполняя роль балансировки нагрузки и пересылки, но поскольку он выполняет операцию SNAT для пакета запроса, как показано на рисунке:
Таким образом, клиентский ip, полученный в POD IC, будет IP рабочего узла, который переслал пакет, поэтому в этом режиме мы не можем получить реальный IP клиента.Если мы не заботимся о реальном IP-адрес клиента, который мы можем использовать. Таким образом, все IP-адреса рабочих узлов могут быть добавлены в список серверных служб SLB.Метод 2 externalTrafficPolicy=Local
Когда spec.externalTrafficPolicy службы является локальной: Узел будет пересылать запрос только на POD IC в узле.Поскольку IC не проходит операцию SNAT, IC может получить реальный IP клиента.Если узел не имеет POD, ошибка будет сообщено. Таким образом, нам нужно вручную поддерживать связь между IC POD, узлом и серверной службой SLB. Так есть ли способ автоматически управлять и поддерживать эти отношения? На самом деле это так.Alibaba Cloud Container Service сделал все это за нас.Поскольку следующие аннотации добавлены к сервису, тип которого LoadBalancer, он может автоматически добавить порт и IP рабочего узла, который запустил POD, в В серверной службе SLB расширение и сокращение емкости обновляются автоматически, как показано ниже (обратите внимание, что мы используем внутрисетевой SLB, тип — интранет, вы можете изменить его в соответствии с реальной ситуацией):
metadata:
annotations:
service.beta.kubernetes.io/alicloud-loadbalancer-address-type: intranet
service.beta.kubernetes.io/alicloud-loadbalancer-force-override-listeners: "true"
service.beta.kubernetes.io/alicloud-loadbalancer-id: lb-2zec8x×××××××××965vt
Режим 1 (кластер) и режим 2 (локальный)
В сравнении | Cluster | Local |
---|---|---|
преимущество | Простой, стандартный способ K8S | Уменьшите переадресацию сети, хорошую производительность и можете получить реальный IP-адрес клиента. |
недостаток | Маскировка адреса SNAT добавляет к сети один переход, производительность снижается, и реальный IP-адрес клиента не может быть получен. | Вам нужно проверить, открыт ли порт узла, и вам нужно настроить обнаружение службы (Alibaba Cloud уже интегрировалась с SLB) |
Вокруг ямы
Проблема количества рабочих процессов nginx
Мы знаем, что когда конфигурация worker_processes по умолчанию для nginx установлена автоматически, она будет автоматически рассчитываться в соответствии с текущей информацией о процессоре хоста, но nginx не является приложением, поддерживающим контрольные группы, поэтому он будет слепо «высокомерен», что доступно «много» процессоров. , здесь Нам нужно указать его, мы можем задать параметры в конфигмапе:
apiVersion: v1
data:
worker-processes: "8"
kind: ConfigMap
metadata:
annotations:
labels:
app: ingress-nginx
name: xwz-nginx-configuration
namespace: kube-system
Настройки параметров ядра
В этом блоке мы временно используем параметры, заданные в развертывании по умолчанию, и будем корректировать их в зависимости от ситуации при последующей настройке.
initContainers:
- command:
- /bin/sh
- -c
- |
sysctl -w net.core.somaxconn=65535
sysctl -w net.ipv4.ip_local_port_range="1024 65535"
sysctl -w fs.file-max=1048576
sysctl -w fs.inotify.max_user_instances=16384
sysctl -w fs.inotify.max_user_watches=524288
sysctl -w fs.inotify.max_queued_events=16384
Проблема с реальным IP клиента
В период низкого трафика в оттенках серого студенты-бизнесмены сообщили, что сторонние античитерские службы обнаружили, что интерфейс, который мы им назвали, был ненормальным.После анализа выяснилось, что IP-адрес клиента содержался в запросе, отправленном третьему -party был записан как IP-адрес хоста нашего API-шлюза. Помните приведенную ранее архитектурную диаграмму?
Причина этой проблемы в том, что наша ИС находится за OpenResty, а кодовая часть настройки X-REAL-IP в шаблоне ИС выглядит следующим образом:Откуда взялся этот the_real_ip?Видно, что по умолчанию он получается из переменной remote_addr.В нашем сценарии remote_addr будет IP-адресом хоста API-шлюза, поэтому нам нужно изменить его для заголовка с именем X_REAL_IP, который API-шлюз установил для нас. . Наш подход заключается в том, чтобы экспортировать и изменить файл шаблона и смонтировать его в образ в виде configmap, перезаписав исходную конфигурацию.Конфигурация выглядит следующим образом:apiVersion: extensions/v1beta1
kind: Deployment
metadata:
...
spec:
template:
spec:
containers:
name: nginx-ingress-controller
...
volumeMounts:
- mountPath: /etc/nginx/template
name: nginx-template-volume
readOnly: true
....
volumes:
- name: nginx-template-volume
configMap:
name: xwz-nginx-template
items:
- key: nginx.tmpl
path: nginx.tmpl
Пока проблема решена
Мониторинг статей
На существующем API-шлюзе CooHua уже ведется подробный мониторинг различных показателей.Поскольку ingress-контроллер также выставляет метрики prometheus, также очень просто напрямую развернуть версию панели управления для сообщества и выполнить простую модификацию, т.к. показано ниже:
Справочная документация по мониторингу развертываний включает:пожалуйста, нажмите на меняПользовательская панель инструментов загружена на мой личный github:пожалуйста, нажмите на меняПоиск проблемы
дамп файла nginx.conf
Пожалуйста, обратитесь к этой статьеdocs.Nginx.com/Nginx/admin…
Refs
Особенно Aliyun.com/articles/69… Особенно Aliyun.com/articles/64… Богдан-Али by.blogspot.com/2017/09/guest… Daniel FM: Что /posts/ отправило вас на… Woohoo.a, так что Kim.com/blog/deep- of…