Change timings
This commit is contained in:
parent
7ce59d633b
commit
4719864c78
5 changed files with 68 additions and 31 deletions
21
config.go
21
config.go
|
|
@ -21,9 +21,6 @@ const (
|
|||
// Время ожидания перед удалением контейнера при миграции между хостами (в секундах)
|
||||
// Увеличенное время для безопасного переключения трафика на новый хост
|
||||
MigrationDrainTimeout = 3600 // 1 час
|
||||
|
||||
// Максимальное количество контейнеров на одного клиента
|
||||
MaxContainersPerClient = 20
|
||||
)
|
||||
|
||||
// Константы диапазонов портов для Docker
|
||||
|
|
@ -46,7 +43,7 @@ const (
|
|||
DefaultPrimaryDBHost = "10.100.10.8"
|
||||
DefaultSecondaryDBHost = "10.100.13.5"
|
||||
DefaultDockerImage = "ptaf-core-nginx-agent:release-4.1.6.409465"
|
||||
DefaultDockerImageURL = "" // пустой дефолт — не скачивать если не задан в env
|
||||
DefaultDockerImageURL = ""
|
||||
DefaultWorkerProcesses = 4
|
||||
DefaultWorkerConnections = 64000
|
||||
)
|
||||
|
|
@ -65,7 +62,7 @@ type Config struct {
|
|||
WorkerProcesses int
|
||||
WorkerConnections int
|
||||
DockerImage string
|
||||
DockerImageURL string // URL для скачивания tar-архива образа если отсутствует локально
|
||||
DockerImageURL string // URL для скачивания tar-архива образа
|
||||
}
|
||||
|
||||
// loadEnvFile загружает переменные окружения из файла /etc/magos/magos.env
|
||||
|
|
@ -113,15 +110,15 @@ func getDefaultConfig() Config {
|
|||
SecondaryDBHost: getEnv("SECONDARY_DB_HOST", DefaultSecondaryDBHost),
|
||||
APIToken: getEnv("API_TOKEN", ""),
|
||||
AntibotNetworks: []string{
|
||||
"185.66.23.0/24",
|
||||
"185.66.25.0/24",
|
||||
"185.35.26.0/24",
|
||||
"185.35.26.0/24",
|
||||
"212.67.25.0/24",
|
||||
"185.66.85.0/24",
|
||||
"185.66.86.0/24",
|
||||
"185.35.5.0/24",
|
||||
"185.35.6.0/24",
|
||||
"212.67.26.0/24",
|
||||
},
|
||||
WAFNetworks: []string{
|
||||
"109.238.9.0/24",
|
||||
"89.20.3.0/24",
|
||||
"109.238.89.0/24",
|
||||
"89.20.63.0/24",
|
||||
},
|
||||
WorkerProcesses: getEnvInt("WORKER_PROCESSES", DefaultWorkerProcesses),
|
||||
WorkerConnections: getEnvInt("WORKER_CONNECTIONS", DefaultWorkerConnections),
|
||||
|
|
|
|||
|
|
@ -395,7 +395,7 @@ http {
|
|||
gzip on;
|
||||
server_names_hash_bucket_size 512;
|
||||
server_tokens off;
|
||||
ptaf_fallback 503;
|
||||
ptaf_fallback 418;
|
||||
proxy_read_timeout 120s;
|
||||
proxy_send_timeout 120s;
|
||||
send_timeout 60s;
|
||||
|
|
|
|||
40
drain.go
40
drain.go
|
|
@ -12,6 +12,35 @@ import (
|
|||
|
||||
var _ = sql.ErrNoRows // ensure import
|
||||
|
||||
// getActualContainerCount возвращает реальное количество контейнеров клиента —
|
||||
// максимум из: существующих директорий на диске и drain-маркеров в /tmp.
|
||||
// Используется вместо захардкоженного MaxContainersPerClient.
|
||||
func getActualContainerCount(clientTitle string) int {
|
||||
max := 0
|
||||
|
||||
// Считаем по директориям на диске
|
||||
baseDir := filepath.Join("/home/install/ptaf", clientTitle)
|
||||
for num := 1; ; num++ {
|
||||
containerName := fmt.Sprintf("%s-ptaf-agent%03d", clientTitle, num)
|
||||
containerDir := filepath.Join(baseDir, containerName)
|
||||
if _, err := os.Stat(containerDir); err != nil {
|
||||
break
|
||||
}
|
||||
max = num
|
||||
}
|
||||
|
||||
// Считаем по drain-маркерам в /tmp (контейнеры могли быть уже удалены с диска)
|
||||
for num := max + 1; ; num++ {
|
||||
markerFile := fmt.Sprintf("/tmp/ptaf-drain-ptaf_%s_%03d", clientTitle, num)
|
||||
if _, err := os.Stat(markerFile); err != nil {
|
||||
break
|
||||
}
|
||||
max = num
|
||||
}
|
||||
|
||||
return max
|
||||
}
|
||||
|
||||
func processDrainingAngieConfigs() {
|
||||
currentTime := time.Now().Unix()
|
||||
timeout := int64(MigrationDrainTimeout)
|
||||
|
|
@ -117,7 +146,8 @@ func processAllDrainingContainersGlobally(db *sql.DB, hostname string) {
|
|||
if !shouldBeHere && !skipDrainCheck {
|
||||
log.Printf(" ⚠ Клиент %s не должен быть на этом хосте (waf_instance='%s')", clientTitle, clientInfo.WAFInstance)
|
||||
hasExistingMarkers := false
|
||||
for containerNum := 1; containerNum <= MaxContainersPerClient; containerNum++ {
|
||||
actualCount := getActualContainerCount(clientTitle)
|
||||
for containerNum := 1; containerNum <= actualCount; containerNum++ {
|
||||
if _, err := os.Stat(fmt.Sprintf("/tmp/ptaf-drain-ptaf_%s_%03d", clientTitle, containerNum)); err == nil {
|
||||
hasExistingMarkers = true
|
||||
break
|
||||
|
|
@ -125,7 +155,7 @@ func processAllDrainingContainersGlobally(db *sql.DB, hostname string) {
|
|||
}
|
||||
if !hasExistingMarkers {
|
||||
log.Printf(" → Помечаю контейнеры для миграции")
|
||||
for containerNum := 1; containerNum <= MaxContainersPerClient; containerNum++ {
|
||||
for containerNum := 1; containerNum <= actualCount; containerNum++ {
|
||||
containerFullName := fmt.Sprintf("ptaf_%s_%03d", clientTitle, containerNum)
|
||||
exists, _ := checkContainerStatus(containerFullName)
|
||||
if exists {
|
||||
|
|
@ -167,7 +197,8 @@ func processAllDrainingContainersGlobally(db *sql.DB, hostname string) {
|
|||
|
||||
func checkAndProcessExistingDrainMarkers(clientTitle string, containersCount int, processedCount *int) {
|
||||
hasAnyDrainMarkers := false
|
||||
for containerNum := 1; containerNum <= MaxContainersPerClient; containerNum++ {
|
||||
actualCount := getActualContainerCount(clientTitle)
|
||||
for containerNum := 1; containerNum <= actualCount; containerNum++ {
|
||||
if _, err := os.Stat(fmt.Sprintf("/tmp/ptaf-drain-ptaf_%s_%03d", clientTitle, containerNum)); err == nil {
|
||||
hasAnyDrainMarkers = true
|
||||
break
|
||||
|
|
@ -197,7 +228,8 @@ func processDrainingContainers(clientTitle string, maxContainerNum int) {
|
|||
db := connectToDB(tempConfig)
|
||||
defer db.Close()
|
||||
|
||||
for containerNum := maxContainerNum + 1; containerNum <= MaxContainersPerClient; containerNum++ {
|
||||
actualCount := getActualContainerCount(clientTitle)
|
||||
for containerNum := maxContainerNum + 1; containerNum <= actualCount; containerNum++ {
|
||||
containerName := fmt.Sprintf("%s-ptaf-agent%03d", clientTitle, containerNum)
|
||||
containerFullName := fmt.Sprintf("ptaf_%s_%03d", clientTitle, containerNum)
|
||||
containerDir := filepath.Join(baseDir, containerName)
|
||||
|
|
|
|||
22
main.go
22
main.go
|
|
@ -71,7 +71,8 @@ func main() {
|
|||
// Проверка наличия Docker образа только если на хосте есть PTAF-клиенты
|
||||
if hasPTAFClients(db, instanceNames) {
|
||||
if err := ensureDockerImageExists(config); err != nil {
|
||||
log.Fatalf("❌ Ошибка подготовки Docker образа: %v", err)
|
||||
log.Printf("⚠ Ошибка подготовки Docker образа: %v", err)
|
||||
log.Printf(" → Продолжаем работу, но новые PTAF-контейнеры могут не запуститься")
|
||||
}
|
||||
} else {
|
||||
log.Printf("ℹ PTAF-клиентов на хосте нет, проверка Docker образа пропускается")
|
||||
|
|
@ -175,8 +176,6 @@ func ensureDockerImageExists(config Config) error {
|
|||
}
|
||||
|
||||
// downloadFile скачивает файл по URL и сохраняет в destPath.
|
||||
// Использует общий apiClient с таймаутом 120 сек (для больших tar-архивов может быть мало —
|
||||
// при необходимости увеличь таймаут в apiClient или создай отдельный клиент).
|
||||
func downloadFile(destPath, url string) error {
|
||||
client := &http.Client{
|
||||
Timeout: 30 * time.Minute, // образы могут быть большими
|
||||
|
|
@ -188,10 +187,6 @@ func downloadFile(destPath, url string) error {
|
|||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return fmt.Errorf("HTTP %d при скачивании %s", resp.StatusCode, url)
|
||||
}
|
||||
|
||||
f, err := os.Create(destPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("ошибка создания файла %s: %w", destPath, err)
|
||||
|
|
@ -204,7 +199,12 @@ func downloadFile(destPath, url string) error {
|
|||
return fmt.Errorf("ошибка записи файла: %w", err)
|
||||
}
|
||||
|
||||
log.Printf(" → Скачано: %.1f МБ", float64(written)/1024/1024)
|
||||
if written == 0 {
|
||||
os.Remove(destPath)
|
||||
return fmt.Errorf("скачан пустой файл (HTTP %d)", resp.StatusCode)
|
||||
}
|
||||
|
||||
log.Printf(" → Скачано: %.1f МБ (HTTP %d)", float64(written)/1024/1024, resp.StatusCode)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -287,7 +287,8 @@ func handleClientMigration(clientInfo ClientInfo, hostname string) {
|
|||
clientInfo.ClientTitle, clientInfo.WAFInstance, hostname)
|
||||
log.Printf(" Инициирую удаление контейнеров с текущего хоста (миграция)")
|
||||
|
||||
for containerNum := 1; containerNum <= MaxContainersPerClient; containerNum++ {
|
||||
actualCount := getActualContainerCount(clientInfo.ClientTitle)
|
||||
for containerNum := 1; containerNum <= actualCount; containerNum++ {
|
||||
containerFullName := fmt.Sprintf("ptaf_%s_%03d", clientInfo.ClientTitle, containerNum)
|
||||
exists, _ := checkContainerStatus(containerFullName)
|
||||
if exists {
|
||||
|
|
@ -321,7 +322,8 @@ func cleanStaleDrainMarkers(clientInfo ClientInfo) {
|
|||
cleanedContainers := 0
|
||||
cleanedAngieMarker := false
|
||||
|
||||
for containerNum := 1; containerNum <= MaxContainersPerClient; containerNum++ {
|
||||
actualCount := getActualContainerCount(clientInfo.ClientTitle)
|
||||
for containerNum := 1; containerNum <= actualCount; containerNum++ {
|
||||
containerFullName := fmt.Sprintf("ptaf_%s_%03d", clientInfo.ClientTitle, containerNum)
|
||||
markerFile := fmt.Sprintf("/tmp/ptaf-drain-%s", containerFullName)
|
||||
|
||||
|
|
|
|||
14
nginx.go
14
nginx.go
|
|
@ -153,9 +153,11 @@ func writeAngieResourceConfig(f *os.File, config Config, res ResourceData, conta
|
|||
for _, customPort := range httpsPortsToListen {
|
||||
upstreamName := fmt.Sprintf("secure%d_%d_%s", res.L7ResourceID, customPort, res.ServerName)
|
||||
f.WriteString(fmt.Sprintf("upstream %s {\n", upstreamName))
|
||||
maxFails := getMaxFails(res.AppsSettings)
|
||||
failTimeout := getFailTimeout(res.AppsSettings)
|
||||
for _, ports := range containerPorts {
|
||||
if dockerPort, ok := ports.HTTPSPorts[customPort]; ok {
|
||||
f.WriteString(fmt.Sprintf(" server 127.0.0.1:%d weight=50;\n", dockerPort))
|
||||
f.WriteString(fmt.Sprintf(" server 127.0.0.1:%d weight=50 max_fails=%d fail_timeout=%ds;\n", dockerPort, maxFails, failTimeout))
|
||||
}
|
||||
}
|
||||
writeCustomUpstreamOrDefault(f, res.AppsSettings.UpstreamAngieCustom, res.AppsSettings.SNI)
|
||||
|
|
@ -166,9 +168,11 @@ func writeAngieResourceConfig(f *os.File, config Config, res ResourceData, conta
|
|||
for _, customPort := range httpPortsToListen {
|
||||
upstreamName := fmt.Sprintf("unsecure%d_%d_%s", res.L7ResourceID, customPort, res.ServerName)
|
||||
f.WriteString(fmt.Sprintf("upstream %s {\n", upstreamName))
|
||||
maxFails := getMaxFails(res.AppsSettings)
|
||||
failTimeout := getFailTimeout(res.AppsSettings)
|
||||
for _, ports := range containerPorts {
|
||||
if dockerPort, ok := ports.HTTPPorts[customPort]; ok {
|
||||
f.WriteString(fmt.Sprintf(" server 127.0.0.1:%d weight=50;\n", dockerPort))
|
||||
f.WriteString(fmt.Sprintf(" server 127.0.0.1:%d weight=50 max_fails=%d fail_timeout=%ds;\n", dockerPort, maxFails, failTimeout))
|
||||
}
|
||||
}
|
||||
writeCustomUpstreamOrDefault(f, res.AppsSettings.UpstreamAngieCustom, res.AppsSettings.SNI)
|
||||
|
|
@ -186,6 +190,8 @@ func writeAngieResourceConfig(f *os.File, config Config, res ResourceData, conta
|
|||
len(customServerBlocks), res.L7ResourceID)
|
||||
for _, block := range customServerBlocks {
|
||||
var upstreamName string
|
||||
maxFails := getMaxFails(res.AppsSettings)
|
||||
failTimeout := getFailTimeout(res.AppsSettings)
|
||||
if block.IsHTTPS {
|
||||
upstreamName = fmt.Sprintf("secure%d_%d_%s", res.L7ResourceID, block.Port, block.ServerName)
|
||||
f.WriteString(fmt.Sprintf("upstream %s {\n", upstreamName))
|
||||
|
|
@ -205,7 +211,7 @@ func writeAngieResourceConfig(f *os.File, config Config, res ResourceData, conta
|
|||
}
|
||||
for _, ports := range containerPorts {
|
||||
if dockerPort, ok := ports.HTTPSPorts[resolvedHTTPSPort]; ok {
|
||||
f.WriteString(fmt.Sprintf(" server 127.0.0.1:%d weight=50;\n", dockerPort))
|
||||
f.WriteString(fmt.Sprintf(" server 127.0.0.1:%d weight=50 max_fails=%d fail_timeout=%ds;\n", dockerPort, maxFails, failTimeout))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
@ -226,7 +232,7 @@ func writeAngieResourceConfig(f *os.File, config Config, res ResourceData, conta
|
|||
}
|
||||
for _, ports := range containerPorts {
|
||||
if dockerPort, ok := ports.HTTPPorts[resolvedHTTPPort]; ok {
|
||||
f.WriteString(fmt.Sprintf(" server 127.0.0.1:%d weight=50;\n", dockerPort))
|
||||
f.WriteString(fmt.Sprintf(" server 127.0.0.1:%d weight=50 max_fails=%d fail_timeout=%ds;\n", dockerPort, maxFails, failTimeout))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue