Kubernetes 1.15.5 и romana 2.0.2 получают сетевые ошибки при добавлении или удалении ЛЮБЫХ модулей - PullRequest
3 голосов
/ 31 октября 2019

Я столкнулся с некоторыми загадочными сетевыми ошибками в нашем кластере kubernetes. Хотя я изначально сталкивался с этими ошибками при использовании входа, есть еще больше ошибок, когда я обходил наш балансировщик нагрузки, обходил kube-proxy и обходил nginx-ingress. Большинство ошибок присутствуют при переходе непосредственно к сервисам и напрямую к IP-адресам модуля. Я полагаю, что это потому, что балансировщик нагрузки и nginx имеют лучшую обработку ошибок, чем необработанная маршрутизация iptable.

Чтобы проверить ошибку, я использую тест Apache из ВМ в той же подсети, любой уровень параллелизма, без поддержки активности,подключитесь к IP-адресу модуля и используйте достаточно большой номер запроса, чтобы дать мне время либо увеличить, либо уменьшить развертывание. Странно то, что не имеет значения, какое развертывание я изменяю, поскольку оно всегда вызывает одни и те же наборы ошибок, даже если оно не связано с модулем, который я изменяю. ЛЮБОЕ добавление или удаление модулей вызовет ошибки теста Apache. Удаление вручную, масштабирование вверх / вниз, автоматическое масштабирование всех ошибок триггера. Если во время выполнения теста ab нет изменений в модуле, об ошибках не сообщается. Примечание: поддержка активности, по-видимому, значительно сокращает, если не устраняет ошибки, но я только несколько раз проверял это и никогда не видел ошибки.

За исключением какого-то странного конфликта между ними, я действительно не понимаю, какудаление модуля A может повлиять на сетевые подключения модуля B. Поскольку ошибки кратковременны и исчезают в течение нескольких секунд, это больше похоже на кратковременное отключение сети.

Пример теста ab: ab -n 5000 -c 2 https://10.112.0.24/

Ошибкипри использовании HTTPS:

SSL handshake failed (5).
SSL read failed (5) - closing connection

Ошибки при использовании HTTP:

apr_socket_recv: Connection reset by peer (104)
apr_socket_recv: Connection refused (111)

Пример ab output. Я обнаружил ctl-C после появления первых ошибок:

$ ab -n 5000 -c 2 https://10.112.0.24/
This is ApacheBench, Version 2.3 <$Revision: 1826891 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking 10.112.0.24 (be patient)
Completed 500 requests
Completed 1000 requests
SSL read failed (5) - closing connection
Completed 1500 requests
^C

Server Software:        nginx
Server Hostname:        10.112.0.24
Server Port:            443
SSL/TLS Protocol:       TLSv1.2,ECDHE-RSA-AES256-GCM-SHA384,2048,256

Document Path:          /
Document Length:        2575 bytes

Concurrency Level:      2
Time taken for tests:   21.670 seconds
Complete requests:      1824
Failed requests:        2
   (Connect: 0, Receive: 0, Length: 1, Exceptions: 1)
Total transferred:      5142683 bytes
HTML transferred:       4694225 bytes
Requests per second:    84.17 [#/sec] (mean)
Time per request:       23.761 [ms] (mean)
Time per request:       11.881 [ms] (mean, across all concurrent requests)
Transfer rate:          231.75 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        5   15   9.8     12      82
Processing:     1    9   9.0      6     130
Waiting:        0    8   8.9      6     129
Total:          7   23  14.4     19     142

Percentage of the requests served within a certain time (ms)
  50%     19
  66%     24
  75%     28
  80%     30
  90%     40
  95%     54
  98%     66
  99%     79
 100%    142 (longest request)

Текущие настройки sysctl, которые могут иметь значение:

net.netfilter.nf_conntrack_tcp_be_liberal = 1
net.nf_conntrack_max = 131072
net.netfilter.nf_conntrack_buckets = 65536
net.netfilter.nf_conntrack_count = 1280
net.ipv4.ip_local_port_range = 27050    65500

Я не увидел никаких ошибок "полного" conntrack. Лучше всего я могу сказать, что нет потери пакетов. Мы недавно обновились с 1.14 и не заметили проблему, но я не могу точно сказать, что ее там не было. Я полагаю, что вскоре нас заставят мигрировать из Романы, поскольку она, похоже, больше не поддерживается, и при обновлении до куба 1.16.x у нас возникают проблемы с его запуском.

Я искалСегодня весь день в интернете ищут похожие проблемы, и ближайшая, которая напоминает нашу проблему, - https://tech.xing.com/a-reason-for-unexplained-connection-timeouts-on-kubernetes-docker-abd041cf7e02, но я понятия не имею, как реализовать опцию iptable masquerade --random-full, учитывая, что мы используем романа и я читаю (https://github.com/kubernetes/kubernetes/pull/78547#issuecomment-527578153) это случайное-полностью значение по умолчанию для ядра Linux 5, которое мы используем. Есть идеи?

  • kubernetes 1.15.5
  • romana 2.0.2
  • centos7
  • Linux kube-master01 5.0.7-1.el7.elrepo.x86_64 # 1 SMP пт 5 апреля 18:07:52 EDT 2019 x86_64 x86_64 x86_64 GNU / Linux

====== Обновление 5 ноября 2019 г. ======

Было предложено протестировать альтернативный CNI. Я выбрал calico, поскольку мы использовали его в более старом кластерном кубе на основе Debian. Я перестроил виртуальную машину с нашим самым основным шаблоном Centos 7 (vSphere)так что из наших настроек есть небольшой багаж. Я не могу перечислить все, что мы настроили в нашем шаблоне, но самое заметное изменение - это обновление ядра 5 yum --enablerepo=elrepo-kernel -y install kernel-ml.

После запуска виртуальной машины это минимальные шаги для установки kubernetes и запуска теста:

yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

yum -y install docker-ce-3:18.09.6-3.el7.x86_64

systemctl start docker

cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
EOF

# Set SELinux in permissive mode (effectively disabling it)
setenforce 0
sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config

echo '1' > /proc/sys/net/bridge/bridge-nf-call-iptables

yum install -y kubeadm-1.15.5-0 kubelet-1.15.5-0 kubectl-1.15.5-0

systemctl enable --now kubelet

kubeadm init --pod-network-cidr=192.168.0.0/16

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config

kubectl taint nodes --all node-role.kubernetes.io/master-

kubectl apply -f https://docs.projectcalico.org/v3.8/manifests/calico.yaml

cat <<EOF > /tmp/test-deploy.yml
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
  name: test
spec:
  selector:
    matchLabels:
      app: test
  replicas: 1
  template:
    metadata:
      labels:
        app: test
    spec:
      containers:
      - name: nginx
        image: nginxdemos/hello
        ports:
        - containerPort: 80
EOF

# wait for control plane to become healthy

kubectl apply -f /tmp/test-deploy.yml

Теперь установка готова, и это тест ab:

$ docker run --rm jordi/ab -n 100 -c 1  http://192.168.4.4/
This is ApacheBench, Version 2.3 <$Revision: 1826891 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking 192.168.4.4 (be patient)...apr_pollset_poll: The timeout specified has expired (70007)
Total of 11 requests completed

Тест ab сдается после этой ошибки. Если я уменьшу количество запросов, чтобы увидеть время ожидания, то это то, что вы увидите:

$ docker run --rm jordi/ab -n 10 -c 1  http://192.168.4.4/
This is ApacheBench, Version 2.3 <$Revision: 1826891 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking 192.168.4.4 (be patient).....done


Server Software:        nginx/1.13.8
Server Hostname:        192.168.4.4
Server Port:            80

Document Path:          /
Document Length:        7227 bytes

Concurrency Level:      1
Time taken for tests:   0.029 seconds
Complete requests:      10
Failed requests:        0
Total transferred:      74140 bytes
HTML transferred:       72270 bytes
Requests per second:    342.18 [#/sec] (mean)
Time per request:       2.922 [ms] (mean)
Time per request:       2.922 [ms] (mean, across all concurrent requests)
Transfer rate:          2477.50 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    1   0.8      1       3
Processing:     1    2   1.2      1       4
Waiting:        0    1   1.3      0       4
Total:          1    3   1.4      3       5

Percentage of the requests served within a certain time (ms)
  50%      3
  66%      3
  75%      4
  80%      5
  90%      5
  95%      5
  98%      5
  99%      5
 100%      5 (longest request)

Эта проблема технически отличается от первоначальной проблемы, о которой я сообщил, но это другой CNI, и все еще есть сетьвопросы. Обычно возникает ошибка тайм-аута, когда я запускаю тот же тест в кластере kube / romana: запускаю тест ab на том же узле, что и модуль. Оба столкнулись с одной и той же ошибкой тайм-аута, но в романе я мог получить несколько тысяч запросов, чтобы завершить работу до истечения времени ожидания. Калико сталкивается с ошибкой тайм-аута до достижения дюжины запросов.

Другие варианты или примечания:- net.netfilter.nf_conntrack_tcp_be_liberal = 0/1, похоже, не имеет значения - более высокие значения -n иногда работают, но в значительной степени случайны. - запуск теста 'ab' при низких значениях -n несколько раз подряд может иногда вызвать тайм-аут

На данный момент я почти уверен, что это какая-то проблема с нашей установкой centos, но я не могу дажеугадай, что это может бытьСуществуют ли какие-либо другие ограничения, sysctl или другие конфиги, которые могут вызвать это?

====== Обновление 6 ноября 2019 года ======

Я наблюдаю, что у нас былостарое ядро ​​установлено в, так что я обновил мою тестовую виртуальную машину kube / calico тем же более новым ядром 5.3.8-1.el7.elrepo.x86_64. После обновления и нескольких перезагрузок я больше не могу воспроизвести ошибки тайм-аута «apr_pollset_poll: указанное время истекло (70007)».

Теперь, когда ошибка истекла, я смог повторить первоначальный тест, гдеЯ загружаю тестовый модуль A и уничтожаю модуль B на своих виртуальных машинах vSphere. В средах Романа проблема все еще существовала, но только в том случае, когда нагрузочное тестирование проводилось на другом хосте, чем там, где находится модуль А. Если я запускаю тест на том же хосте, никаких ошибок вообще нет. При использовании Calico вместо romana на каждом хосте нет ошибок нагрузочного теста, поэтому проблема исчезла. Возможно, еще есть некоторые настройки, которые могут помочь романе, но я думаю, что это «удар 3» для романа, поэтому я начну переводить полную среду на Calico и проведу там некоторые приемочные испытания, чтобы убедиться, что нет скрытых ошибок.

1 Ответ

0 голосов
/ 04 ноября 2019

Вы упомянули, что если во время выполнения теста ab нет изменений в модуле, об ошибках не сообщается. Таким образом, это означает, что ошибки возникают при добавлении или удалении модуля pod.

Это нормальное поведение, как при удалении модуля pod;для распространения приемлемых изменений требуется время. Может случиться, что контейнер удален, но правила iptable не изменились, но конечные пакеты пересылаются в несуществующий контейнер, и это вызывает ошибки (это похоже на состояние гонки).

Первыйчто вы можете сделать, это всегда создать readiness probe, так как он будет гарантировать, что трафик не будет перенаправлен в контейнер, пока он не будет готов обрабатывать запросы.

Второе, что нужно сделать, - это обработать удаление контейнера. должным образом. Это немного сложнее, потому что она может быть обработана на многих уровнях, но самое простое, что вы можете сделать, это добавить хук PreStop к вашему контейнеру следующим образом:

lifecycle:
 preStop:
  exec:
   command:
   - sh
   - -c
   - "sleep 5"

PreStop hook выполняется в моментзапрос на удаление пакета. С этого момента k8s начинают изменять правила iptable и должны прекратить пересылку нового трафика в контейнер, который собирается удалить. В то время как sleep ing, вы даете k8s некоторое время для распространения приемлемых изменений в кластере, не прерывая уже существующие соединения. После выхода PreStop handle контейнер получит сигнал SIGTERM.

Я бы предложил применить оба этих механизма вместе и проверить, помогает ли это.

Вы также упомянули, что обход входа вызываетбольше ошибок. Я предполагаю, что это связано с тем, что во входе реализован механизм повторных попыток. Если не удается открыть соединение с контейнером, он попытается несколько раз и, надеюсь, попадет в контейнер, который может обработать его запрос.

...