Տեղական ֆայլեր՝ հավելվածը Kubernetes տեղափոխելիս

Տեղական ֆայլեր՝ հավելվածը Kubernetes տեղափոխելիս

Kubernetes-ի միջոցով CI/CD գործընթաց կառուցելիս երբեմն առաջանում է նոր ենթակառուցվածքի պահանջների և դրան փոխանցվող հավելվածի անհամատեղելիության խնդիր։ Մասնավորապես, հավելվածի կառուցման փուլում կարևոր է ստանալ մեկ պատկեր, որը կօգտագործվի Ամբողջ նախագծային միջավայրեր և կլաստերներ: Այս սկզբունքն է ընկած ճիշտի հիմքում ըստ Google-ի բեռնարկղերի կառավարում (այս մասին մեկից ավելի անգամ խոսեց և մեր տեխնիկական բաժինը):

Այնուամենայնիվ, դուք ոչ ոքի չեք տեսնի այն իրավիճակներում, երբ կայքի կոդը օգտագործում է պատրաստի շրջանակ, որի օգտագործումը սահմանափակումներ է դնում դրա հետագա օգտագործման համար: Եվ չնայած «նորմալ միջավայրում» դրանով զբաղվելը հեշտ է, Kubernetes-ում այս պահվածքը կարող է խնդիր դառնալ, հատկապես, երբ առաջին անգամ եք հանդիպում դրան: Թեև հնարամիտ միտքը կարող է ենթակառուցվածքային լուծումներ գտնել, որոնք առաջին հայացքից ակնհայտ կամ նույնիսկ լավ են թվում... կարևոր է հիշել, որ իրավիճակների մեծ մասը կարող է և պետք է: լուծվի ճարտարապետական.

Եկեք նայենք ֆայլերի պահպանման հանրաճանաչ լուծումներին, որոնք կարող են հանգեցնել տհաճ հետևանքների կլաստերի գործարկման ժամանակ, ինչպես նաև մատնանշել ավելի ճիշտ ճանապարհ:

Ստատիկ պահեստավորում

Պատկերացնելու համար դիտարկենք մի վեբ հավելված, որն օգտագործում է ինչ-որ ստատիկ գեներատոր՝ պատկերների, ոճերի և այլ բաների հավաքածու ստանալու համար: Օրինակ, Yii PHP շրջանակն ունի ներկառուցված ակտիվների կառավարիչ, որը ստեղծում է յուրօրինակ գրացուցակների անուններ: Համապատասխանաբար, ելքը ստատիկ կայքի համար ուղիների մի շարք է, որոնք ակնհայտորեն չեն հատվում միմյանց հետ (դա արվել է մի քանի պատճառով, օրինակ՝ կրկնօրինակները վերացնելու համար, երբ մի քանի բաղադրիչներ օգտագործում են նույն ռեսուրսը): Այսպիսով, արկղից դուրս, երբ առաջին անգամ մուտք եք գործում վեբ ռեսուրսի մոդուլ, ստատիկ ֆայլերը (իրականում, հաճախ սիմհղումներ, բայց ավելի ուշ) ձևավորվում և տեղադրվում են այս տեղակայման համար եզակի ընդհանուր արմատային գրացուցակով.

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

Ի՞նչ է սա նշանակում կլաստերի առումով:

Ամենապարզ օրինակը

Վերցնենք բավականին սովորական դեպք, երբ PHP-ին նախորդում է nginx-ը՝ ստատիկ տվյալներ բաշխելու և պարզ հարցումներ մշակելու համար։ Ամենահեշտ ճանապարհը - տեղակայումը երկու կոնտեյներով.

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

Պարզեցված ձևով nginx կազմաձևը հանգում է հետևյալին.

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;
        }
    }

Երբ առաջին անգամ մուտք եք գործում կայք, ակտիվները հայտնվում են PHP կոնտեյներով: Բայց մեկ պատի մեջ երկու կոնտեյներների դեպքում nginx-ը ոչինչ չգիտի այս ստատիկ ֆայլերի մասին, որոնք (ըստ կազմաձևի) պետք է տրվեն նրանց։ Արդյունքում, հաճախորդը կտեսնի 404 սխալ CSS և JS ֆայլերի բոլոր հարցումների համար: Այստեղ ամենապարզ լուծումը կլինի կոնտեյներների համար ընդհանուր գրացուցակի կազմակերպումը: Պրիմիտիվ տարբերակ՝ ընդհանուր 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

Այժմ կոնտեյներով ստեղծված ստատիկ ֆայլերը nginx-ի կողմից ճիշտ սպասարկվում են: Բայց հիշեցնեմ, որ սա պարզունակ լուծում է, ինչը նշանակում է, որ այն հեռու է իդեալականից և ունի իր նրբություններն ու թերությունները, որոնք կքննարկվեն ստորև։

Ավելի առաջադեմ պահեստավորում

Հիմա պատկերացրեք մի իրավիճակ, երբ օգտատերը այցելեց կայք, բեռնեց էջը կոնտեյների մեջ առկա ոճերով, և մինչ նա կարդում էր այս էջը, մենք նորից տեղակայեցինք կոնտեյները: Ակտիվների կատալոգը դատարկ է դարձել, և պահանջվում է հարցում PHP-ին՝ նորերը ստեղծելու համար: Այնուամենայնիվ, նույնիսկ դրանից հետո հին ստատիկների հղումներն անտեղի կլինեն, ինչը կհանգեցնի ստատիկ ցուցադրման սխալների:

Բացի այդ, մենք, ամենայն հավանականությամբ, ունենք քիչ թե շատ բեռնված նախագիծ, ինչը նշանակում է, որ հավելվածի մեկ օրինակը բավարար չի լինի.

  • Եկեք այն մեծացնենք տեղակայումը մինչև երկու կրկնօրինակ:
  • Երբ կայքը առաջին անգամ մուտք գործեց, ակտիվները ստեղծվեցին մեկ կրկնօրինակով:
  • Ինչ-որ պահի, ingress-ը որոշեց (բեռների հավասարակշռման նպատակով) հարցում ուղարկել երկրորդ կրկնօրինակին, և այդ ակտիվները դեռ այնտեղ չէին: Կամ գուցե նրանք այլեւս չկան, քանի որ մենք օգտագործում ենք RollingUpdate և այս պահին մենք տեղակայում ենք։

Ընդհանուր առմամբ, արդյունքը կրկին սխալներ են։

Հին ակտիվները չկորցնելու համար կարող եք փոխել emptyDir մասին hostPath, ավելացնելով ստատիկ ֆիզիկապես կլաստերային հանգույցին: Այս մոտեցումը վատ է, քանի որ մենք իրականում ստիպված ենք դա անել կապվել որոշակի կլաստերային հանգույցի հետ ձեր դիմումը, քանի որ - այլ հանգույցներ տեղափոխվելու դեպքում գրացուցակը չի պարունակի անհրաժեշտ ֆայլերը: Կամ անհրաժեշտ է ինչ-որ ֆոնային գրացուցակի համաժամացում հանգույցների միջև:

Որո՞նք են լուծումները:

  1. Եթե ​​սարքավորումներն ու ռեսուրսները թույլ են տալիս, կարող եք օգտագործել cephfs ստատիկ կարիքների համար հավասարապես մատչելի գրացուցակ կազմակերպելու համար: Պաշտոնական փաստաթղթեր խորհուրդ է տալիս SSD կրիչներ, առնվազն եռակի կրկնօրինակում և կայուն «հաստ» կապ կլաստերային հանգույցների միջև:
  2. Ավելի քիչ պահանջկոտ տարբերակ կլինի NFS սերվերի կազմակերպումը: Այնուամենայնիվ, այնուհետև դուք պետք է հաշվի առնեք վեբ սերվերի կողմից հարցումների մշակման ժամանակի հնարավոր աճը, և սխալների հանդուրժողականությունը շատ բան կթողնի: Անհաջողության հետևանքները աղետալի են. լեռան կորուստը մահապատժի է ենթարկում կլաստերին երկինք շտապող LA բեռի ճնշման ներքո:

Ի թիվս այլ բաների, կպահանջվեն մշտական ​​պահեստ ստեղծելու բոլոր տարբերակները ֆոնի մաքրում որոշակի ժամանակահատվածում կուտակված ֆայլերի հնացած հավաքածուներ: PHP-ով բեռնարկղերի դիմաց կարող եք տեղադրել DaemonSet nginx-ի քեշից, որը սահմանափակ ժամանակով կպահի ակտիվների պատճենները: Այս վարքագիծը հեշտությամբ կարգավորելի է օգտագործելով proxy_cache պահեստավորման խորությամբ օրերով կամ գիգաբայթ սկավառակի տարածությամբ:

Այս մեթոդի համադրումը վերը նշված բաշխված ֆայլային համակարգերի հետ տալիս է հսկայական երևակայության դաշտ, որը սահմանափակվում է միայն նրանց բյուջեով և տեխնիկական ներուժով, ովքեր կիրականացնեն և կաջակցեն այն: Փորձից կարելի է ասել, որ որքան պարզ է համակարգը, այնքան կայուն է այն աշխատում։ Երբ ավելացվում են նման շերտեր, շատ ավելի դժվար է դառնում ենթակառուցվածքի պահպանումը, և միևնույն ժամանակ ավելանում է ցանկացած խափանումներից ախտորոշման և վերականգնման վրա ծախսվող ժամանակը։

Առաջարկություն

Եթե ​​պահեստավորման առաջարկվող տարբերակների իրականացումը նույնպես ձեզ անհիմն է թվում (բարդ, թանկ...), ապա արժե իրավիճակին նայել մյուս կողմից։ Մասնավորապես, խորամուխ լինել նախագծի ճարտարապետության մեջ և լուծել խնդիրը կոդի մեջ, կապված պատկերի որոշ ստատիկ տվյալների կառուցվածքի հետ, պատկերի հավաքման փուլում «տաքացման» և/կամ ակտիվների նախնական կազմման բովանդակության կամ ընթացակարգի միանշանակ սահմանում: Այս կերպ մենք ստանում ենք բացարձակապես կանխատեսելի վարքագիծ և ֆայլերի նույն փաթեթը բոլոր միջավայրերի և գործող հավելվածի կրկնօրինակների համար:

Եթե ​​վերադառնանք Yii շրջանակի կոնկրետ օրինակին և չխորանանք դրա կառուցվածքի մեջ (ինչը հոդվածի նպատակը չէ), բավական է նշել երկու հանրաճանաչ մոտեցում.

  1. Փոխեք պատկերի ստեղծման գործընթացը՝ ակտիվները կանխատեսելի վայրում տեղադրելու համար: Սա առաջարկվում է/իրագործվում է նման ընդլայնումների մեջ yii2-static-assets.
  2. Սահմանեք հատուկ հեշեր ակտիվների գրացուցակների համար, ինչպես քննարկվել է օրինակ. այս ներկայացումը (սկսած թիվ 35 սլայդից): Ի դեպ, հաշվետվության հեղինակը ի վերջո (և ոչ առանց պատճառի) խորհուրդ է տալիս, որ ակտիվները build սերվերի վրա հավաքելուց հետո դրանք վերբեռնեք կենտրոնական պահեստում (ինչպես S3), որի դիմաց տեղադրեք CDN:

Ներբեռնումներ

Մեկ այլ դեպք, որն անկասկած գործի կդրվի հավելվածը Kubernetes կլաստեր տեղափոխելիս, օգտատիրոջ ֆայլերը ֆայլային համակարգում պահելն է: Օրինակ, մենք կրկին ունենք PHP հավելված, որն ընդունում է ֆայլերը վերբեռնման ձևի միջոցով, ինչ-որ բան անում դրանց հետ աշխատանքի ընթացքում և հետ է ուղարկում դրանք:

Kubernetes-ում այն ​​վայրը, որտեղ պետք է տեղադրվեն այս ֆայլերը, պետք է ընդհանուր լինի հավելվածի բոլոր կրկնօրինակների համար: Կախված հավելվածի բարդությունից և այս ֆայլերի կայունությունը կազմակերպելու անհրաժեշտությունից, վերը նշված ընդհանուր սարքի տարբերակները կարող են նման տեղ լինել, բայց, ինչպես տեսնում ենք, նրանք ունեն իրենց թերությունները:

Առաջարկություն

Լուծումը մեկն է օգտագործելով S3-ի հետ համատեղելի պահեստ (նույնիսկ եթե դա ինչ-որ ինքնակառավարվող կատեգորիա է, ինչպիսին է minio-ն): S3-ին անցնելու համար փոփոխություններ կպահանջվեն կոդի մակարդակով, և թե ինչպես բովանդակությունը կմատակարարվի ճակատային մասում, մենք արդեն ունենք писали.

Օգտագործողի նիստեր

Առանձին-առանձին, հարկ է նշել օգտվողների նիստերի պահպանման կազմակերպումը: Հաճախ դրանք նաև սկավառակի վրա գտնվող ֆայլեր են, որոնք Kubernetes-ի համատեքստում կհանգեցնեն օգտվողի կողմից մշտական ​​թույլտվության հարցումների, եթե նրա հարցումն ավարտվի մեկ այլ կոնտեյներով:

Խնդիրը մասամբ լուծվում է միացնելով stickySessions մուտքի վրա (հատկանիշն աջակցվում է բոլոր հանրաճանաչ մուտքի կարգավորիչներում. լրացուցիչ մանրամասների համար տե՛ս մեր վերանայումը)օգտատիրոջը հավելվածով կոնկրետ պատիճին կապելու համար.

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: /

Բայց դա չի վերացնի կրկնակի տեղակայման հետ կապված խնդիրները:

Առաջարկություն

Ավելի ճիշտ միջոց կլինի դիմումը փոխանցել նիստերի պահպանում memcached, Redis և նմանատիպ լուծումներում - ընդհանուր առմամբ, ամբողջովին հրաժարվել ֆայլի ընտրանքներից:

Ամփոփում

Տեքստում քննարկված ենթակառուցվածքային լուծումներն արժանի են օգտագործման միայն ժամանակավոր «հենակների» ձևաչափով (որը անգլերենում ավելի գեղեցիկ է հնչում որպես լուծում): Դրանք կարող են տեղին լինել Kubernetes հավելված տեղափոխելու առաջին փուլերում, բայց չպետք է արմատավորվեն:

Ընդհանուր առաջարկվող ուղին դրանցից ազատվելն է՝ հօգուտ հավելվածի ճարտարապետական ​​փոփոխության՝ շատերին արդեն հայտնիին համապատասխան։ 12-Factor հավելված. Այնուամենայնիվ, սա՝ դիմումը քաղաքացիություն չունեցող ձևի բերելը, անխուսափելիորեն նշանակում է, որ կպահանջվեն փոփոխություններ կոդի մեջ, և այստեղ կարևոր է հավասարակշռություն գտնել բիզնեսի հնարավորությունների/պահանջների և ընտրված ուղու իրականացման և պահպանման հեռանկարների միջև։ .

PS

Կարդացեք նաև մեր բլոգում.

Source: www.habr.com

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