10 Kasagarang mga Sayop Sa Paggamit sa Kubernetes

Nota. transl.: Ang mga tagsulat niini nga artikulo mga inhenyero gikan sa gamay nga kompanya sa Czech, pipetail. Nahimo nila ang paghiusa sa usa ka matahum nga lista sa [usahay banal, apan sa gihapon] mga dinalian nga mga problema ug sayup nga pagsabut nga may kalabotan sa operasyon sa mga pungpong sa Kubernetes.

10 Kasagarang mga Sayop Sa Paggamit sa Kubernetes

Sulod sa mga katuigan sa paggamit sa Kubernetes, kami nagtrabaho uban sa usa ka dako nga gidaghanon sa mga clusters (parehong gidumala ug wala madumala - sa GCP, AWS ug Azure). Sa paglabay sa panahon, namatikdan namo nga ang pipila ka mga sayop kanunay nga gisubli. Bisan pa, wala’y kaulaw niini: nahimo namon ang kadaghanan niini sa among kaugalingon!

Ang artikulo naglangkob sa labing kasagaran nga mga sayup ug naghisgot usab kung giunsa kini pagtul-id.

1. Mga Kapanguhaan: mga hangyo ug mga limitasyon

Kini nga butang siguradong takus sa labing duol nga atensyon ug una nga lugar sa lista.

Pangayo sa CPU kasagaran bisan wala gitino sa tanan o adunay gamay kaayo nga kantidad (aron ibutang ang daghang pod sa matag node kutob sa mahimo). Sa ingon, ang mga node mahimong sobra nga gibug-aton. Panahon sa taas nga load, ang gahum sa pagproseso sa node hingpit nga gigamit ug ang usa ka partikular nga workload makadawat lamang kung unsa ang "gihangyo" sa CPU throttling. Nagdala kini sa dugang nga latency sa aplikasyon, mga timeout, ug uban pang dili maayo nga mga sangputanan. (Basaha ang dugang bahin niini sa among ubang bag-ong hubad: “Mga limitasyon sa CPU ug agresibo nga pag-throttling sa Kubernetes"- gibanabana. transl.)

Labing Maayong Paningkamot (hilabihan dili girekomendar):

resources: {}

Ubos kaayo nga hangyo sa CPU (sobra dili girekomendar):

   resources:
      Requests:
        cpu: "1m"

Sa laing bahin, ang presensya sa usa ka limitasyon sa CPU mahimong mosangpot sa dili makatarunganon nga paglaktaw sa mga siklo sa orasan pinaagi sa mga pod, bisan kung ang node processor dili bug-os nga gikarga. Sa makausa pa, kini mahimong mosangpot sa dugang nga mga paglangan. Ang kontrobersiya nagpadayon sa palibot sa parameter CFS nga quota sa CPU sa Linux kernel ug CPU throttling depende sa gitakda nga mga limitasyon, ingon man ang pag-disable sa CFS quota... Ay, ang mga limitasyon sa CPU mahimong hinungdan sa daghang mga problema kay sa ilang masulbad. Dugang nga impormasyon bahin niini makita sa link sa ubos.

Sobra nga pagpili (sobra nga pasalig) Ang mga problema sa memorya mahimong mosangpot sa mas dagkong mga problema. Ang pagkab-ot sa limitasyon sa CPU nagkinahanglan sa paglaktaw sa mga siklo sa orasan, samtang ang pagkab-ot sa limitasyon sa memorya nagkinahanglan sa pagpatay sa pod. Nakabantay ka na ba OOMkill? Oo, mao gyud kana ang among gihisgutan.

Gusto ba nimo nga maminusan ang posibilidad nga kini mahitabo? Ayaw pag-over-allocate sa memorya ug gamita ang Guaranteed QoS (Quality of Service) pinaagi sa pagbutang sa memory request sa limit (sama sa pananglitan sa ubos). Basaha ang dugang bahin niini sa Mga presentasyon ni Henning Jacobs (Lead Engineer sa Zalando).

Burstable (mas taas nga kahigayonan nga mapatay ang OOM):

   resources:
      requests:
        memory: "128Mi"
        cpu: "500m"
      limits:
        memory: "256Mi"
        cpu: 2

Gigarantiya:

   resources:
      requests:
        memory: "128Mi"
        cpu: 2
      limits:
        memory: "128Mi"
        cpu: 2

Unsa ang posibleng makatabang sa pag-set up sa mga kapanguhaan?

Uban sa tabang sa metrics-server imong makita ang kasamtangan nga CPU resource konsumo ug memory paggamit sa pods (ug mga sudlanan sa sulod niini). Lagmit, gigamit na nimo kini. Pagdalagan lang ang mosunod nga mga sugo:

kubectl top pods
kubectl top pods --containers
kubectl top nodes

Bisan pa, gipakita ra nila ang karon nga paggamit. Makahatag kini kanimo usa ka dili maayo nga ideya sa han-ay sa kadako, apan sa katapusan kinahanglan nimo kasaysayan sa mga pagbag-o sa mga sukatan sa paglabay sa panahon (aron matubag ang mga pangutana sama sa: “Unsa ang peak nga load sa CPU?”, “Unsa ang load kagahapon sa buntag?”, etc.). Alang niini mahimo nimong gamiton Prometheus, DataDog ug uban pang mga himan. Nagkuha lang sila og mga metrics gikan sa metrics-server ug gitipigan kini, ug ang user makapangutana niini ug makaplano niini sumala niana.

VerticalPodAutoscaler kini nagtugot automate niini nga proseso. Gisubay niini ang kasaysayan sa paggamit sa CPU ug memorya ug nagtakda og bag-ong mga hangyo ug mga limitasyon base niini nga impormasyon.

Ang paggamit sa gahum sa pag-compute nga episyente dili sayon ​​nga buluhaton. Kini sama sa pagdula Tetris sa tanang panahon. Kung nagbayad ka ug sobra alang sa gahum sa pagkalkula nga adunay gamay nga average nga konsumo (ingon ~ 10%), girekomenda namon ang pagtan-aw sa mga produkto nga gibase sa AWS Fargate o Virtual Kubelet. Gitukod sila sa usa ka serverless/pay-per-usage billing model, nga mahimong mas barato sa maong mga kondisyon.

2. Kabuhi ug kaandam mga pagsusi

Sa kasagaran, ang liveness ug readiness checks wala gipagana sa Kubernetes. Ug usahay makalimot sila sa pag-on niini...

Apan unsaon pa nimo pagsugod ang pag-restart sa serbisyo kung adunay usa ka makamatay nga sayup? Ug giunsa pagkahibalo sa load balancer nga andam pod modawat ug traffic? O nga kini makahimo sa pagdumala sa dugang nga trapiko?

Kini nga mga pagsulay kanunay nga naglibog sa usag usa:

  • Kinabuhi — “survivability” check, nga magsugod pag-usab sa pod kon kini mapakyas;
  • Andam — pagsusi sa kaandam, kung mapakyas, gidiskonekta niini ang pod gikan sa serbisyo sa Kubernetes (mahimo kining susihon gamit ang kubectl get endpoints) ug ang trapiko dili moabot niini hangtod nga ang sunod nga pagsusi makompleto nga malampuson.

Ang duha niini nga mga tseke GIHIMO SA TIBUOK CYCLE SA KINABUHI SA POD. Importante kaayo kini.

Usa ka kasagarang sayop nga pagsabut mao nga ang mga pagsusi sa pagkaandam gipadagan lamang sa pagsugod aron mahibal-an sa balanse nga andam na ang pod (Ready) ug makasugod sa pagproseso sa trapiko. Bisan pa, kini usa lamang sa mga kapilian alang sa ilang paggamit.

Ang usa pa mao ang posibilidad nga mahibal-an nga ang trapiko sa pod sobra ra ug overloads kini (o ang pod naghimo sa mga kalkulasyon nga kusog sa kapanguhaan). Sa kini nga kaso, ang pagsusi sa pagkaandam makatabang pagpakunhod sa load sa pod ug "pabugnaw" kini. Ang malampuson nga pagkompleto sa usa ka pagsusi sa kaandam sa umaabot nagtugot dugangi ang load sa pod. Sa kini nga kaso (kung mapakyas ang pagsulay sa pagkaandam), ang pagkapakyas sa pagsulay sa liveness mahimong kontra-produktibo. Nganong i-restart pod ang himsog ug kugihan?

Busa, sa pipila ka mga kaso, wala'y mga tseke nga mas maayo kay sa pag-enable kanila sa dili husto nga pag-configure nga mga parameter. Sama sa giingon sa ibabaw, kung liveness check mga kopya sa ready check, unya anaa ka sa dakong kasamok. Posible nga kapilian mao ang pag-configure Readiness test nga langug delikado nga kinabuhi biyai sa daplin.

Ang duha ka matang sa mga tseke kinahanglan nga dili mapakyas kung ang kasagaran nga mga dependency mapakyas, kung dili kini mosangpot sa usa ka cascading (sama sa avalanche) nga kapakyasan sa tanan nga mga pod. Sa laing pagkasulti, ayaw pagdaot sa imong kaugalingon.

3. LoadBalancer alang sa matag serbisyo sa HTTP

Lagmit, aduna kay mga serbisyo sa HTTP sa imong cluster nga gusto nimong ipasa ngadto sa gawas nga kalibutan.

Kung ablihan nimo ang serbisyo ingon type: LoadBalancer, ang controller niini (depende sa service provider) mohatag ug makigsabot sa external LoadBalancer (dili kinahanglan nga modagan sa L7, kondili bisan sa L4), ug kini mahimong makaapekto sa gasto (external static IPv4 address, computing power, per-second billing ) tungod sa panginahanglan sa paghimo sa usa ka dako nga gidaghanon sa maong mga kapanguhaan.

Sa kini nga kaso, mas makataronganon ang paggamit sa usa ka external load balancer, pagbukas sa mga serbisyo ingon type: NodePort. O mas maayo pa, palapdan ang usa ka butang sama nginx-ingress-controller (o traefik), kinsa mahimong usa ra NodePort endpoint nga nalangkit sa external load balancer ug magruta sa trapiko sa cluster gamit ingress-Mga kapanguhaan sa Kubernetes.

Ang ubang mga intra-cluster (micro) nga mga serbisyo nga nakig-interact sa usag usa mahimong "magkomunikar" gamit ang mga serbisyo sama ClusterIP ug usa ka built-in nga mekanismo sa pagdiskobre sa serbisyo pinaagi sa DNS. Ayaw lang gamita ang ilang publiko nga DNS/IP, tungod kay kini makaapekto sa latency ug makadugang sa gasto sa mga serbisyo sa panganod.

4. Autoscaling sa usa ka cluster nga walay pagtagad sa mga bahin niini

Kung gidugangan ang mga node ug gitangtang kini gikan sa usa ka kumpol, dili ka kinahanglan magsalig sa pipila ka mga sukaranan nga sukatan sama sa paggamit sa CPU sa mga node. Ang pagplano sa pod kinahanglang tagdon ang daghan mga pagdili, sama sa pod/node affinity, taints ug tolerations, resource requests, QoS, etc. Ang paggamit sa usa ka eksternal nga autoscaler nga wala magtagad sa kini nga mga nuances mahimong hinungdan sa mga problema.

Hunahunaa nga ang usa ka piho nga pod kinahanglan nga naka-iskedyul, apan ang tanan nga magamit nga gahum sa CPU gihangyo / gidisassemble ug ang pod natanggong sa usa ka estado Pending. Ang eksternal nga autoscaler nakakita sa kasagaran nga kasamtangan nga load sa CPU (dili ang gihangyo) ug dili magsugod sa pagpalapad (scale-out) - dili makadugang ug laing node. Ingon usa ka sangputanan, kini nga pod dili ma-iskedyul.

Sa kini nga kaso, reverse scaling (scale-in) - Ang pagtangtang sa usa ka node gikan sa usa ka cluster kanunay nga mas lisud nga ipatuman. Hunahunaa nga ikaw adunay usa ka stateful pod (uban ang padayon nga pagtipig konektado). Nagpadayon nga mga volume kasagaran iya sa piho nga availability zone ug wala gisundog sa rehiyon. Busa, kung ang usa ka eksternal nga autoscaler magtangtang sa usa ka node nga adunay kini nga pod, ang scheduler dili makahimo sa pag-iskedyul niini nga pod sa laing node, tungod kay kini mahimo lamang sa availability zone diin nahimutang ang padayon nga pagtipig. Pod ma-stuck sa estado Pending.

Sikat kaayo sa komunidad sa Kubernetes cluster-autoscaler. Nagdagan kini sa usa ka cluster, nagsuporta sa mga API gikan sa mga dagkong cloud providers, gikonsiderar ang tanan nga mga pagdili ug mahimo’g sukdon sa mga kaso sa ibabaw. Makahimo usab kini sa pag-scale-in samtang gipadayon ang tanan nga gitakda nga mga limitasyon, sa ingon makatipig salapi (nga kung dili magamit sa wala magamit nga kapasidad).

5. Pagpasagad sa mga kapabilidad sa IAM/RBAC

Pagbantay sa paggamit sa IAM tiggamit uban sa padayon nga mga sekreto alang sa makina ug aplikasyon. Pag-organisar og temporaryo nga pag-access gamit ang mga tahas ug mga account sa serbisyo (mga account sa serbisyo).

Kanunay namong masugatan ang kamatuoran nga ang mga yawe sa pag-access (ug mga sekreto) gi-hardcode sa configuration sa aplikasyon, ingon man ang pagpasagad sa pagtuyok sa mga sekreto bisan pa adunay access sa Cloud IAM. Gamita ang mga tahas sa IAM ug mga account sa serbisyo imbes nga mga tiggamit kung angay.

10 Kasagarang mga Sayop Sa Paggamit sa Kubernetes

Kalimti ang bahin sa kube2iam ug diretso sa mga tahas sa IAM alang sa mga account sa serbisyo (sama sa gihulagway sa nota sa samang ngalan Štěpán Vraný):

apiVersion: v1
kind: ServiceAccount
metadata:
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/my-app-role
  name: my-serviceaccount
  namespace: default

Usa ka anotasyon. Dili kaayo lisud, di ba?

Usab, ayaw paghatag mga pribilehiyo sa mga account sa serbisyo ug mga profile sa pananglitan admin и cluster-adminkung dili nila kini kinahanglan. Kini usa ka gamay nga mas lisud nga ipatuman, labi na sa RBAC K8s, apan siguradong takus sa paningkamot.

6. Ayaw pagsalig sa automatic anti-affinity alang sa pods

Hunahunaa nga ikaw adunay tulo ka mga replika sa pipila nga pag-deploy sa usa ka node. Ang node nahulog, ug uban niini ang tanan nga mga replika. Dili maayo nga kahimtang, di ba? Apan ngano nga ang tanan nga mga replika sa parehas nga node? Dili ba ang Kubernetes kinahanglan nga maghatag taas nga magamit (HA)?!

Ikasubo, ang iskedyul sa Kubernetes, sa kaugalingon nga inisyatibo, wala magsunod sa mga lagda sa bulag nga paglungtad (anti-affinity) para pod. Kinahanglan nga sila tin-aw nga ipahayag:

// опущено для краткости
      labels:
        app: zk
// опущено для краткости
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            - labelSelector:
                matchExpressions:
                  - key: "app"
                    operator: In
                    values:
                    - zk
              topologyKey: "kubernetes.io/hostname"

Mao ra. Karon ang mga pod ma-iskedyul sa lainlaing mga node (kini nga kondisyon gisusi lamang sa panahon sa pag-iskedyul, apan dili sa panahon sa ilang operasyon - busa requiredDuringSchedulingIgnoredDuringExecution).

Dinhi atong gihisgutan podAntiAffinity sa lainlaing mga node: topologyKey: "kubernetes.io/hostname", - ug dili mahitungod sa lain-laing mga availability zones. Aron mapatuman ang usa ka hingpit nga HA, kinahanglan nimo nga magkalot og lawom sa kini nga hilisgutan.

7. Pagbaliwala sa PodDisruptionBudgets

Hunahunaa nga naa kay production load sa usa ka Kubernetes cluster. Matag karon ug unya, ang mga node ug ang cluster mismo kinahanglan nga i-update (o decommissioned). Ang PodDisruptionBudget (PDB) sama sa usa ka kasabutan sa garantiya sa serbisyo tali sa mga tagdumala sa cluster ug tiggamit.

Gitugotan ka sa PDB nga malikayan ang mga pagkabalda sa serbisyo tungod sa kakulang sa mga node:

apiVersion: policy/v1beta1
kind: PodDisruptionBudget
metadata:
  name: zk-pdb
spec:
  minAvailable: 2
  selector:
    matchLabels:
      app: zookeeper

Niini nga pananglitan, ikaw, isip usa ka tiggamit sa cluster, isulti ngadto sa mga admin: "Uy, ako adunay serbisyo sa zookeeper, ug bisan unsa pa ang imong buhaton, gusto ko nga labing menos 2 ka mga replika niini nga serbisyo nga magamit sa tanang panahon. .”

Makabasa ka ug dugang bahin niini dinhi.

8. Daghang tiggamit o palibot sa usa ka komon nga cluster

Mga namespace sa Kubernetes (mga namespace) ayaw paghatag og lig-on nga insulasyon.

Usa ka kasagarang sayop nga pagsabut mao nga kung imong i-deploy ang usa ka non-prod load sa usa ka namespace ug usa ka prod load sa lain, nan sila dili mag-impluwensya sa usag usa sa bisan unsang paagi... Bisan pa, ang usa ka lebel sa pagkahimulag mahimong makab-ot gamit ang mga hangyo sa kapanguhaan/limitasyon, pagtakda sa mga quota, ug pagtakda sa mga priorityClasses. Ang pipila ka "pisikal" nga pag-inusara sa data plane gihatag sa mga kalambigitan, pagtugot, mga hugaw (o nodeselectors), apan ang ingon nga panagbulag medyo lisud ipatuman.

Kadtong kinahanglan nga maghiusa sa duha nga mga klase sa mga buluhaton sa parehas nga kumpol kinahanglan nga atubangon ang pagkakomplikado. Kung wala'y ingon nga panginahanglan, ug mahimo nimo nga adunay usa usa pa ka cluster (ingon, sa usa ka publiko nga panganod), nan mas maayo nga buhaton kini. Makab-ot niini ang mas taas nga lebel sa insulasyon.

9. externalTrafficPolicy: Cluster

Kanunay namong makita nga ang tanan nga trapiko sa sulod sa cluster moabut pinaagi sa usa ka serbisyo sama sa NodePort, diin ang default nga palisiya gitakda externalTrafficPolicy: Cluster... Kini gipasabut nga NodePort bukas sa matag node sa cluster, ug mahimo nimong gamiton ang bisan kinsa niini aron makig-uban sa gusto nga serbisyo (set of pods).

10 Kasagarang mga Sayop Sa Paggamit sa Kubernetes

Sa samang higayon, ang tinuod nga mga pod nga nalangkit sa gihisgotan sa ibabaw nga serbisyo sa NodePort kasagarang anaa lamang sa usa ka piho subset niini nga mga node. Sa laing pagkasulti, kung magkonektar ko sa usa ka node nga walay gikinahanglan nga pod, kini mopasa sa trapiko ngadto sa laing node, pagdugang og hop ug nagkadaghang latency (kon ang mga node nahimutang sa lain-laing available zones/data centers, ang latency mahimong taas kaayo; dugang pa, motaas ang gasto sa egress traffic).

Sa laing bahin, kung ang usa ka serbisyo sa Kubernetes adunay gitakda nga palisiya externalTrafficPolicy: Local, unya ang NodePort moabli lamang sa mga node diin ang gikinahanglan nga mga pod nagdagan. Kung mogamit usa ka external load balancer nga nagsusi sa estado (pagsusi sa panglawas) endpoints (giunsa kini pagbuhat AWS ELB), Siya magpadala lamang sa trapiko sa gikinahanglan nga mga node, nga adunay usa ka mapuslanon nga epekto sa mga paglangan, mga panginahanglanon sa pag-compute, mga bayronon sa paggawas (ug ang sentido komon nagdiktar sa parehas).

Dako ang tsansa nga nagamit na nimo ang sama traefik o nginx-ingress-controller isip usa ka NodePort endpoint (o LoadBalancer, nga naggamit usab sa NodePort) sa pagruta sa trapiko sa pagsulod sa HTTP, ug ang pagbutang niini nga opsyon makapakunhod pag-ayo sa latency alang sa maong mga hangyo.

В niini nga publikasyon Makakat-on pa ka bahin sa externalTrafficPolicy, ang mga bentaha ug disbentaha niini.

10. Ayaw ihigot sa mga pungpong ug ayaw abusohi ang control plane

Kaniadto, naandan nga tawagan ang mga server sa tukma nga mga ngalan: Anton, HAL9000 ug Colossus... Karong adlawa gipulihan sila sa random nga namugna nga mga identifier. Bisan pa, ang batasan nagpabilin, ug karon ang tukma nga mga ngalan moadto sa mga pungpong.

Usa ka tipikal nga istorya (base sa tinuod nga mga panghitabo): ang tanan nagsugod sa usa ka pamatuod sa konsepto, mao nga ang cluster adunay usa ka mapahitas-on nga ngalan testing... Milabay ang mga tuig ug gigamit gihapon kini sa produksiyon, ug ang tanan nahadlok sa paghikap niini.

Wala’y makalingaw bahin sa mga kumpol nga nahimo nga mga binuhi, mao nga girekomenda namon nga tangtangon kini matag karon ug unya samtang nagpraktis pagkaayo sa katalagman (Kini makatabang chaos engineering - gibanabana. transl.). Dugang pa, dili kini makadaot sa pagtrabaho sa control layer (kontrol nga eroplano). Ang pagkahadlok sa paghikap kaniya dili maayong timailhan. etc patay? Guys, problema gyud mo!

Sa laing bahin, dili ka angay madala sa pagmaniobra niini. Uban sa panahon ang control layer mahimong hinay. Lagmit, tungod kini sa daghang mga butang nga gihimo nga wala ang ilang rotation (usa ka sagad nga kahimtang kung gigamit ang Helm nga adunay mga default nga setting, mao nga ang kahimtang niini sa mga configmaps/sekreto wala ma-update - ingon usa ka sangputanan, libu-libo nga mga butang ang natipon sa ang control layer) o uban ang kanunay nga pag-edit sa mga butang nga kube-api (para sa awtomatikong pag-scale, para sa CI/CD, para sa pagmonitor, mga log sa panghitabo, mga controller, ug uban pa).

Dugang pa, girekomenda namon nga susihon ang mga kasabutan sa SLA/SLO sa gidumala nga provider sa Kubernetes ug hatagan pagtagad ang mga garantiya. Makagarantiya ang vendor pagkontrol sa pagkaanaa sa layer (o ang mga subcomponents niini), apan dili ang p99 nga paglangan sa mga hangyo nga imong ipadala niini. Sa laing pagkasulti, makasulod ka kubectl get nodes, ug makadawat og tubag human lamang sa 10 minutos, ug dili kini usa ka paglapas sa mga termino sa kasabutan sa serbisyo.

11. Bonus: gamit ang pinakabag-o nga tag

Apan kini usa na ka klasiko. Karong bag-o nakit-an namon kini nga teknik nga dili kaayo kanunay, tungod kay daghan, nga nakakat-on gikan sa mapait nga kasinatian, mihunong sa paggamit sa tag :latest ug nagsugod sa pag-pin sa mga bersyon. Hooray!

ECR nagmintinar sa pagkadili mabag-o sa mga tag sa imahe; Girekomenda namon nga pamilyar ka sa imong kaugalingon niining talagsaon nga bahin.

Sumaryo

Ayaw pagdahum nga ang tanan molihok sa tibuok gabii: Ang Kubernetes dili usa ka panacea. Dili maayo nga app magpabilin niining paagiha bisan sa Kubernetes (ug lagmit mosamot kini). Ang pagkawalay pagtagad mosangpot sa sobra nga pagkakomplikado, hinay ug makapaguol nga trabaho sa control layer. Dugang pa, peligro ka nga mabiyaan nga wala’y estratehiya sa pagbawi sa katalagman. Ayaw pagdahum nga ang Kubernetes maghatag ug pag-inusara ug taas nga magamit sa gawas sa kahon. Paggahin ug panahon sa paghimo sa imong aplikasyon nga tinuod nga cloud native.

Mahimo nimong masinati ang dili malampuson nga mga kasinatian sa lainlaing mga team sa kini nga koleksyon sa mga istorya ni Henning Jacobs.

Kadtong gusto nga idugang sa lista sa mga sayup nga gihatag sa kini nga artikulo mahimong makontak kanamo sa Twitter (@MarekBartik, @MstrsObserver).

PS gikan sa tighubad

Basaha usab sa among blog:

Source: www.habr.com

Idugang sa usa ka comment