fix: kube-vip leader election + Gunicorn gevent, bump 1.0.8→1.0.9
Deploy loadtest / validate (push) Waiting to run
Deploy loadtest / validate (push) Waiting to run
This commit is contained in:
@@ -0,0 +1,37 @@
|
|||||||
|
# 2026-07-10 — Комбинированный фикс
|
||||||
|
|
||||||
|
## Два корня
|
||||||
|
1. kube-vip ARP без лидера → флаппинг между 4 нодами при каждом новом TCP
|
||||||
|
2. Werkzeug всегда `Connection: close` → новый TCP на каждый запрос
|
||||||
|
|
||||||
|
По отдельности не чинят. Вместе должны.
|
||||||
|
|
||||||
|
## План
|
||||||
|
### 1. kube-vip: vip_leaderelection=true
|
||||||
|
```bash
|
||||||
|
kubectl set env ds/shturval-vip -n kube-vip vip_leaderelection=true
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Flask: Gunicorn + gevent
|
||||||
|
```python
|
||||||
|
# app.py
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import gunicorn.app.base
|
||||||
|
class StandaloneApp(gunicorn.app.base.BaseApplication):
|
||||||
|
def __init__(self, app, options=None):
|
||||||
|
self.application = app; self.options = options or {}
|
||||||
|
super().__init__()
|
||||||
|
def load_config(self):
|
||||||
|
for k, v in self.options.items(): self.cfg.set(k, v)
|
||||||
|
def load(self): return self.application
|
||||||
|
StandaloneApp(app, {
|
||||||
|
'bind': '0.0.0.0:5000', 'workers': 2,
|
||||||
|
'worker_class': 'gevent', 'timeout': 120, 'keepalive': 75,
|
||||||
|
}).run()
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. requirements.txt
|
||||||
|
flask, gunicorn, gevent
|
||||||
|
|
||||||
|
### 4. ingress
|
||||||
|
proxy_request_buffering: off (уже)
|
||||||
@@ -1,2 +1,3 @@
|
|||||||
flask
|
flask
|
||||||
gunicorn
|
gunicorn
|
||||||
|
gevent
|
||||||
|
|||||||
+23
-2
@@ -4,7 +4,7 @@ from flask import Flask, render_template, request
|
|||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
|
||||||
VERSION = '1.0.8'
|
VERSION = '1.0.9'
|
||||||
|
|
||||||
|
|
||||||
@app.route('/')
|
@app.route('/')
|
||||||
@@ -51,4 +51,25 @@ def upload():
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
app.run(host='0.0.0.0', port=5000, debug=False, threaded=True)
|
import gunicorn.app.base
|
||||||
|
|
||||||
|
class StandaloneApp(gunicorn.app.base.BaseApplication):
|
||||||
|
def __init__(self, app, options=None):
|
||||||
|
self.application = app
|
||||||
|
self.options = options or {}
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
def load_config(self):
|
||||||
|
for k, v in self.options.items():
|
||||||
|
self.cfg.set(k, v)
|
||||||
|
|
||||||
|
def load(self):
|
||||||
|
return self.application
|
||||||
|
|
||||||
|
StandaloneApp(app, {
|
||||||
|
'bind': '0.0.0.0:5000',
|
||||||
|
'workers': 2,
|
||||||
|
'worker_class': 'gevent',
|
||||||
|
'timeout': 120,
|
||||||
|
'keepalive': 75,
|
||||||
|
}).run()
|
||||||
|
|||||||
Reference in New Issue
Block a user