Tətbiqi Kubernetes-ə köçürərkən yerli fayllar

Tətbiqi Kubernetes-ə köçürərkən yerli fayllar

Kubernetes-dən istifadə edərək CI/CD prosesi qurarkən bəzən yeni infrastrukturun tələbləri ilə ona ötürülən tətbiq arasında uyğunsuzluq problemi yaranır. Xüsusilə, tətbiqin qurulması mərhələsində əldə etmək vacibdir bir istifadə olunacaq şəkil Bütün layihə mühitləri və klasterlər. Bu prinsip doğruluğun əsasını təşkil edir Google-a görə konteyner idarəetməsi (bu barədə bir dəfədən çox говорил və texniki şöbəmiz).

Bununla belə, sayt kodunun istifadəsi onun sonrakı istifadəsinə məhdudiyyətlər qoyan hazır çərçivədən istifadə etdiyi hallarda heç kimi görməyəcəksiniz. “Normal mühitdə” bununla məşğul olmaq asan olsa da, Kubernetesdə bu davranış problemə çevrilə bilər, xüsusən də ilk dəfə qarşılaşdığınız zaman. İxtiraçı bir ağıl ilk baxışda açıq və ya yaxşı görünən infrastruktur həlləri ilə çıxış edə bilsə də... yadda saxlamaq vacibdir ki, əksər vəziyyətlər memarlıq yolu ilə həll edilməlidir.

Bir klaster işlədərkən xoşagəlməz nəticələrə səbəb ola biləcək faylların saxlanması üçün məşhur həll yollarına nəzər salaq, həmçinin daha düzgün yolu göstərək.

Statik saxlama

Nümunə etmək üçün bir sıra şəkillər, üslublar və başqa şeylər əldə etmək üçün bir növ statik generatordan istifadə edən veb tətbiqini nəzərdən keçirək. Məsələn, Yii PHP çərçivəsi unikal kataloq adlarını yaradan daxili aktiv menecerinə malikdir. Müvafiq olaraq, çıxış bir-biri ilə açıq şəkildə kəsişməyən statik sayt üçün yollar toplusudur (bu bir neçə səbəbə görə edildi - məsələn, birdən çox komponent eyni resursdan istifadə edərkən dublikatları aradan qaldırmaq üçün). Beləliklə, qutudan kənarda, veb resurs moduluna ilk dəfə daxil olduqda, statik fayllar (əslində, tez-tez simvolik bağlantılar, lakin daha sonra daha çox) bu yerləşdirmə üçün unikal olan ümumi kök kataloqu ilə formalaşır və yerləşdirilir:

  • webroot/assets/2072c2df/css/…
  • webroot/assets/2072c2df/images/…
  • webroot/assets/2072c2df/js/…

Bu, klaster baxımından nə deməkdir?

Ən sadə misal

Statik məlumatları yaymaq və sadə sorğuları emal etmək üçün PHP-dən əvvəl nginx olduğu kifayət qədər ümumi bir hadisəni götürək. Ən asan yol - Deployment iki konteyner ilə:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: site
spec:
  selector:
    matchLabels:
      component: backend
  template:
    metadata:
      labels:
        component: backend
    spec:
      volumes:
        - name: nginx-config
          configMap:
            name: nginx-configmap
      containers:
      - name: php
        image: own-image-with-php-backend:v1.0
        command: ["/usr/local/sbin/php-fpm","-F"]
        workingDir: /var/www
      - name: nginx
        image: nginx:1.16.0
        command: ["/usr/sbin/nginx", "-g", "daemon off;"]
        volumeMounts:
        - name: nginx-config
          mountPath: /etc/nginx/conf.d/default.conf
          subPath: nginx.conf

Sadələşdirilmiş formada nginx konfiqurasiyası aşağıdakılara qədər azalır:

apiVersion: v1
kind: ConfigMap
metadata:
  name: "nginx-configmap"
data:
  nginx.conf: |
    server {
        listen 80;
        server_name _;
        charset utf-8;
        root  /var/www;

        access_log /dev/stdout;
        error_log /dev/stderr;

        location / {
            index index.php;
            try_files $uri $uri/ /index.php?$args;
        }

        location ~ .php$ {
            fastcgi_pass 127.0.0.1:9000;
            fastcgi_index index.php;
            include fastcgi_params;
        }
    }

Sayta ilk daxil olduğunuz zaman aktivlər PHP konteynerində görünür. Ancaq bir podda iki konteyner olması halında, nginx bu statik fayllar haqqında heç nə bilmir, (konfiqurasiyaya görə) onlara verilməlidir. Nəticədə müştəri CSS və JS fayllarına edilən bütün sorğular üçün 404 xətası görəcək.Burada ən sadə həll yolu konteynerlər üçün ümumi kataloq təşkil etmək olardı. Primitiv seçim - ümumi emptyDir:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: site
spec:
  selector:
    matchLabels:
      component: backend
  template:
    metadata:
      labels:
        component: backend
    spec:
      volumes:
        - name: assets
          emptyDir: {}
        - name: nginx-config
          configMap:
            name: nginx-configmap
      containers:
      - name: php
        image: own-image-with-php-backend:v1.0
        command: ["/usr/local/sbin/php-fpm","-F"]
        workingDir: /var/www
        volumeMounts:
        - name: assets
          mountPath: /var/www/assets
      - name: nginx
        image: nginx:1.16.0
        command: ["/usr/sbin/nginx", "-g", "daemon off;"]
        volumeMounts:
        - name: assets
          mountPath: /var/www/assets
        - name: nginx-config
          mountPath: /etc/nginx/conf.d/default.conf
          subPath: nginx.conf

İndi konteynerdə yaradılan statik fayllar nginx tərəfindən düzgün şəkildə xidmət göstərir. Ancaq sizə xatırlatmaq istəyirəm ki, bu, primitiv bir həlldir, yəni idealdan uzaqdır və aşağıda müzakirə olunan öz nüansları və çatışmazlıqları var.

Daha təkmil yaddaş

İndi bir vəziyyəti təsəvvür edin ki, istifadəçi sayta daxil olub, konteynerdə mövcud üslublarla səhifə yükləyib və o, bu səhifəni oxuyarkən biz konteyneri yenidən yerləşdirdik. Aktivlər kataloqu boşalıb və yenilərinin yaradılmasına başlamaq üçün PHP-yə sorğu tələb olunur. Bununla belə, bundan sonra da köhnə statiklərə keçidlər əhəmiyyətsiz olacaq və bu, statiklərin göstərilməsində səhvlərə səbəb olacaq.

Bundan əlavə, çox güman ki, az və ya çox yüklənmiş layihəmiz var, yəni tətbiqin bir nüsxəsi kifayət etməyəcək:

  • Gəlin onu genişləndirək Deployment iki replikaya qədər.
  • Sayta ilk giriş zamanı aktivlər bir replikada yaradılmışdır.
  • Bir nöqtədə, giriş (yük balansı məqsədləri üçün) ikinci replikaya sorğu göndərmək qərarına gəldi və bu aktivlər hələ orada deyildi. Və ya bəlkə də istifadə etdiyimiz üçün onlar artıq yoxdur RollingUpdate və hazırda yerləşdirmə işlərini həyata keçiririk.

Ümumiyyətlə, nəticə yenə səhvlərdir.

Köhnə aktivləri itirməmək üçün dəyişə bilərsiniz emptyDir haqqında hostPath, klaster qovşağına fiziki olaraq statik əlavə. Bu yanaşma pisdir, çünki əslində məcburuq xüsusi klaster node ilə əlaqə tətbiqiniz, çünki - digər qovşaqlara köçürsəniz - kataloq lazımi faylları ehtiva etməyəcək. Və ya qovşaqlar arasında bir növ fon kataloqu sinxronizasiyası tələb olunur.

Həll yolları hansılardır?

  1. Aparat və resurslar imkan verirsə, istifadə edə bilərsiniz cephfs statik ehtiyaclar üçün eyni dərəcədə əlçatan kataloq təşkil etmək. Rəsmi sənədlər SSD sürücülərini, ən azı üç dəfə təkrarlamanı və klaster qovşaqları arasında sabit "qalın" əlaqəni tövsiyə edir.
  2. Daha az tələbkar bir seçim NFS serverini təşkil etmək olardı. Bununla belə, veb-server tərəfindən sorğuların işlənməsi üçün cavab müddətinin mümkün artımını nəzərə almalısınız və nasazlıqlara dözümlülük çox şey arzuolunmaz olacaq. Uğursuzluğun nəticələri fəlakətlidir: dağın itirilməsi, göyə qaçan LA yükünün təzyiqi altında çoxluğu ölümə məhkum edir.

Digər şeylər arasında, davamlı yaddaş yaratmaq üçün bütün seçimlər tələb olunacaq fon təmizləmə müəyyən bir müddət ərzində yığılmış köhnəlmiş fayl dəstləri. PHP ilə konteynerlərin qarşısına qoya bilərsiniz DaemonSet aktivlərin nüsxələrini məhdud müddətə saxlayacaq nginx-i keşləmədən. Bu davranış istifadə edərək asanlıqla konfiqurasiya edilə bilər proxy_cache günlərlə və ya gigabayt disk sahəsi ilə yaddaş dərinliyi.

Bu üsulu yuxarıda qeyd olunan paylanmış fayl sistemləri ilə birləşdirmək, yalnız onu həyata keçirəcək və dəstəkləyənlərin büdcəsi və texniki potensialı ilə məhdudlaşan təxəyyül üçün böyük bir sahə təmin edir. Təcrübədən deyə bilərik ki, sistem nə qədər sadə olsa, bir o qədər stabil işləyir. Belə təbəqələr əlavə olunduqda, infrastrukturun saxlanılması xeyli çətinləşir və eyni zamanda diaqnostikaya və hər hansı nasazlığın aradan qaldırılmasına sərf olunan vaxt artır.

Tövsiyə

Təklif olunan saxlama variantlarının həyata keçirilməsi də sizə əsassız görünürsə (mürəkkəb, bahalı ...), onda vəziyyətə digər tərəfdən baxmağa dəyər. Məhz, layihə arxitekturasını qazmaq və koddakı problemi həll edin, şəkildəki bəzi statik məlumat strukturu ilə əlaqələndirilir, məzmunun birmənalı tərifi və ya təsvirin yığılması mərhələsində aktivlərin “istiləşdirilməsi” və/və ya əvvəlcədən tərtib edilməsi proseduru. Beləliklə, biz tamamilə proqnozlaşdırıla bilən davranış və bütün mühitlər və işləyən tətbiqin replikaları üçün eyni fayl dəsti əldə edirik.

Yii çərçivəsi ilə konkret nümunəyə qayıdıb onun strukturunu araşdırmasaq (bu, məqalənin məqsədi deyil), iki məşhur yanaşmanı qeyd etmək kifayətdir:

  1. Aktivləri proqnozlaşdırıla bilən yerdə yerləşdirmək üçün təsvirin qurulması prosesini dəyişdirin. Bu, kimi uzantılarda təklif olunur/həyata keçirilir yii2-statik aktivlər.
  2. Məs.-də müzakirə edildiyi kimi aktiv kataloqları üçün xüsusi hashları müəyyənləşdirin. bu təqdimat (35 nömrəli slayddan başlayaraq). Yeri gəlmişkən, hesabatın müəllifi son nəticədə (və səbəbsiz deyil!) tövsiyə edir ki, aktivləri qurulan serverə yığdıqdan sonra onları mərkəzi yaddaşa (S3 kimi) yükləyin, onun qarşısında CDN yerləşdirin.

Yükləmələr

Bir tətbiqi Kubernetes klasterinə köçürərkən mütləq işə düşəcək başqa bir hal istifadəçi fayllarını fayl sistemində saxlamaqdır. Məsələn, bizdə yenidən yükləmə forması vasitəsilə faylları qəbul edən, əməliyyat zamanı onlarla nəsə edən və onları geri göndərən PHP proqramımız var.

Kubernetes-də bu faylların yerləşdirilməli olduğu yer tətbiqin bütün replikaları üçün ümumi olmalıdır. Tətbiqin mürəkkəbliyindən və bu faylların davamlılığını təşkil etmək ehtiyacından asılı olaraq, yuxarıda qeyd olunan paylaşılan cihaz seçimləri belə bir yer ola bilər, lakin gördüyümüz kimi, onların çatışmazlıqları var.

Tövsiyə

Bir həll S3 uyğun yaddaşdan istifadə etməklə (minio kimi bir növ özünə məxsus kateqoriya olsa belə). S3-ə keçid dəyişikliklər tələb edəcək kod səviyyəsində, və məzmunun ön tərəfə necə çatdırılacağını artıq bilirik писали.

İstifadəçi sessiyaları

Ayrı-ayrılıqda, istifadəçi sessiyalarının saxlanmasının təşkilini qeyd etmək lazımdır. Çox vaxt bunlar da diskdəki fayllardır, Kubernetes kontekstində onun sorğusu başqa konteynerdə başa çatarsa, istifadəçinin daimi avtorizasiya sorğularına səbəb olacaq.

Problem qismən işə salınmaqla həll olunur stickySessions girişdə (xüsusiyyət bütün məşhur giriş kontrollerlərində dəstəklənir - daha ətraflı məlumat üçün baxın nəzərdən keçirmə)istifadəçini proqramla müəyyən bir poda bağlamaq üçün:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: nginx-test
  annotations:
    nginx.ingress.kubernetes.io/affinity: "cookie"
    nginx.ingress.kubernetes.io/session-cookie-name: "route"
    nginx.ingress.kubernetes.io/session-cookie-expires: "172800"
    nginx.ingress.kubernetes.io/session-cookie-max-age: "172800"

spec:
  rules:
  - host: stickyingress.example.com
    http:
      paths:
      - backend:
          serviceName: http-svc
          servicePort: 80
        path: /

Lakin bu, təkrar yerləşdirmə ilə bağlı problemləri aradan qaldırmayacaq.

Tövsiyə

Daha düzgün bir yol tətbiqi köçürmək olardı seansları memcached, Redis və oxşar həllərdə saxlamaq - ümumiyyətlə, fayl seçimlərindən tamamilə imtina edin.

Nəticə

Mətndə müzakirə olunan infrastruktur həlləri yalnız müvəqqəti “dəyənək” formatında istifadəyə layiqdir (bu, ingiliscə həll yolu kimi daha gözəl səslənir). Onlar tətbiqin Kubernetes-ə köçürülməsinin ilk mərhələlərində müvafiq ola bilər, lakin kök atmamalıdır.

Ümumi tövsiyə olunan yol, çoxlarına yaxşı məlum olana uyğun olaraq tətbiqin memarlıq modifikasiyası lehinə onlardan qurtulmaqdır. 12 Faktor Tətbiqi. Bununla belə, bu - ərizənin vətəndaşlığı olmayan formaya gətirilməsi - istər-istəməz kodda dəyişikliklərin tələb olunacağı deməkdir və burada biznesin imkanları/tələbləri ilə seçilmiş yolun həyata keçirilməsi və saxlanılması perspektivləri arasında balans tapmaq vacibdir. .

PS

Bloqumuzda da oxuyun:

Mənbə: www.habr.com

Добавить комментарий