د کوبرنیټس په عملیاتو کې د ساتیرۍ سیسټم 6 بګونه [او د دوی حل]

د کوبرنیټس په عملیاتو کې د ساتیرۍ سیسټم 6 بګونه [او د دوی حل]

په تولید کې د Kubernetes کارولو په کلونو کې، موږ ډیری په زړه پورې کیسې راټولې کړې چې څنګه د سیسټم په مختلفو برخو کې بګونه د ناخوښ او / یا د پوهیدو وړ پایلو لامل شوي چې د کانټینرونو او پوډونو عملیات اغیزه کوي. په دې مقاله کې موږ د ځینو خورا عام یا په زړه پورې انتخابونو انتخاب کړی دی. حتی که تاسو هیڅکله دومره بختور نه یاست چې د داسې شرایطو سره مخ شئ ، د داسې لنډو جاسوسي کیسو په اړه لوستل - په ځانګړي توګه "لومړی لاس" - تل په زړه پوري وي ، ایا دا نه ده؟ ..

کیسه 1. Supercronic او Docker ځړول

په یوه کلستر کې، موږ په دوره توګه یو منجمد ډاکر ترلاسه کړ، کوم چې د کلستر نورمال فعالیت سره مداخله وکړه. په ورته وخت کې، لاندې د ډاکر لاګونو کې لیدل شوي:

level=error msg="containerd: start init process" error="exit status 2: "runtime/cgo: pthread_create failed: No space left on device
SIGABRT: abort
PC=0x7f31b811a428 m=0

goroutine 0 [idle]:

goroutine 1 [running]:
runtime.systemstack_switch() /usr/local/go/src/runtime/asm_amd64.s:252 fp=0xc420026768 sp=0xc420026760
runtime.main() /usr/local/go/src/runtime/proc.go:127 +0x6c fp=0xc4200267c0 sp=0xc420026768
runtime.goexit() /usr/local/go/src/runtime/asm_amd64.s:2086 +0x1 fp=0xc4200267c8 sp=0xc4200267c0

goroutine 17 [syscall, locked to thread]:
runtime.goexit() /usr/local/go/src/runtime/asm_amd64.s:2086 +0x1

…

هغه څه چې موږ ته د دې تېروتنې په اړه خورا علاقه لري هغه پیغام دی: pthread_create failed: No space left on device. چټکه مطالعه اسناد څرګنده کړه چې ډاکر نشي کولی یوه پروسه رامینځته کړي ، له همدې امله دا وخت په وخت کنګل کیږي.

په نظارت کې، لاندې انځور د هغه څه سره مطابقت لري چې پیښیږي:

د کوبرنیټس په عملیاتو کې د ساتیرۍ سیسټم 6 بګونه [او د دوی حل]

ورته حالت په نورو نوډونو کې لیدل کیږي:

د کوبرنیټس په عملیاتو کې د ساتیرۍ سیسټم 6 بګونه [او د دوی حل]

د کوبرنیټس په عملیاتو کې د ساتیرۍ سیسټم 6 بګونه [او د دوی حل]

په ورته نوډونو کې موږ ګورو:

root@kube-node-1 ~ # ps auxfww | grep curl -c
19782
root@kube-node-1 ~ # ps auxfww | grep curl | head
root     16688  0.0  0.0      0     0 ?        Z    Feb06   0:00      |       _ [curl] <defunct>
root     17398  0.0  0.0      0     0 ?        Z    Feb06   0:00      |       _ [curl] <defunct>
root     16852  0.0  0.0      0     0 ?        Z    Feb06   0:00      |       _ [curl] <defunct>
root      9473  0.0  0.0      0     0 ?        Z    Feb06   0:00      |       _ [curl] <defunct>
root      4664  0.0  0.0      0     0 ?        Z    Feb06   0:00      |       _ [curl] <defunct>
root     30571  0.0  0.0      0     0 ?        Z    Feb06   0:00      |       _ [curl] <defunct>
root     24113  0.0  0.0      0     0 ?        Z    Feb06   0:00      |       _ [curl] <defunct>
root     16475  0.0  0.0      0     0 ?        Z    Feb06   0:00      |       _ [curl] <defunct>
root      7176  0.0  0.0      0     0 ?        Z    Feb06   0:00      |       _ [curl] <defunct>
root      1090  0.0  0.0      0     0 ?        Z    Feb06   0:00      |       _ [curl] <defunct>

دا معلومه شوه چې دا چلند د پوډ سره د کار کولو پایله ده سپرکرونیک (د Go یوټیلیټ چې موږ یې په پوډونو کې د کرون دندې چلولو لپاره کاروو):

 _ docker-containerd-shim 833b60bb9ff4c669bb413b898a5fd142a57a21695e5dc42684235df907825567 /var/run/docker/libcontainerd/833b60bb9ff4c669bb413b898a5fd142a57a21695e5dc42684235df907825567 docker-runc
|   _ /usr/local/bin/supercronic -json /crontabs/cron
|       _ /usr/bin/newrelic-daemon --agent --pidfile /var/run/newrelic-daemon.pid --logfile /dev/stderr --port /run/newrelic.sock --tls --define utilization.detect_aws=true --define utilization.detect_azure=true --define utilization.detect_gcp=true --define utilization.detect_pcf=true --define utilization.detect_docker=true
|       |   _ /usr/bin/newrelic-daemon --agent --pidfile /var/run/newrelic-daemon.pid --logfile /dev/stderr --port /run/newrelic.sock --tls --define utilization.detect_aws=true --define utilization.detect_azure=true --define utilization.detect_gcp=true --define utilization.detect_pcf=true --define utilization.detect_docker=true -no-pidfile
|       _ [newrelic-daemon] <defunct>
|       _ [curl] <defunct>
|       _ [curl] <defunct>
|       _ [curl] <defunct>
…

ستونزه دا ده: کله چې یو کار په سوپرکرونیک کې پرمخ وړل کیږي، پروسه د هغې لخوا رامینځته کیږي نشي کولی په سمه توګه پای ته ورسويپه بدلېدل زومبی.

تبصره: د دې لپاره چې ډیر دقیق وي، پروسې د کرون دندو لخوا رامینځته کیږي، مګر سوپرکرونیک یو ابتدايي سیسټم نه دی او نشي کولی هغه پروسې "اپن کړي" چې ماشومان یې رامینځته کړي. کله چې د SIGHUP یا SIGTERM سیګنالونه پورته کیږي، دوی د ماشوم پروسو ته نه لیږدول کیږي، په پایله کې د ماشوم پروسې پای ته نه رسیږي او د زومبي حالت کې پاتې کیږي. تاسو کولی شئ د دې ټولو په اړه نور ولولئ، د بیلګې په توګه، په کې داسې یوه مقاله.

د ستونزو د حل لپاره څو لارې شتون لري:

  1. د لنډمهاله کار په توګه - په یو وخت کې په سیسټم کې د PIDs شمیر زیات کړئ:
           /proc/sys/kernel/pid_max (since Linux 2.5.34)
                  This file specifies the value at which PIDs wrap around (i.e., the value in this file is one greater than the maximum PID).  PIDs greater than this  value  are  not  allo‐
                  cated;  thus, the value in this file also acts as a system-wide limit on the total number of processes and threads.  The default value for this file, 32768, results in the
                  same range of PIDs as on earlier kernels
  2. یا په سوپر کرونیک کې دندې په مستقیم ډول نه پیل کړئ ، مګر د ورته کارولو سره ټینی، کوم چې د دې وړتیا لري چې پروسې په سمه توګه پای ته ورسوي او زومبي نه سپان کړي.

کیسه 2. "زومبیز" کله چې د C ګروپ حذف کول

کوبیلټ د ډیری CPU مصرف پیل کړ:

د کوبرنیټس په عملیاتو کې د ساتیرۍ سیسټم 6 بګونه [او د دوی حل]

هیڅوک به دا خوښ نه کړي، نو موږ خپل ځانونه وسله کړل کامل او د ستونزې سره معامله پیل کړه. د څېړنې پایلې په لاندې ډول وې:

  • کوبیلټ د خپل CPU وخت له دریمې برخې څخه ډیر مصرف کوي د ټولو cgroups څخه د حافظې ډیټا ایستل:

    د کوبرنیټس په عملیاتو کې د ساتیرۍ سیسټم 6 بګونه [او د دوی حل]

  • د کرنل پراختیا کونکو د بریښنالیک لیست کې تاسو موندلی شئ د ستونزې بحث. په لنډه توګه، دا ټکی ته راځي: د tmpfs مختلف فایلونه او نور ورته شیان په بشپړ ډول له سیسټم څخه ندي لرې شوي کله چې د c ګروپ حذف کول، په نوم یادیږي memcg zombie. ډیر ژر یا وروسته به دوی د پا pageې کیچ څخه حذف شي ، مګر په سرور کې خورا حافظه شتون لري او کرنل د دوی په حذف کولو کې د وخت ضایع کولو نقطه نه ګوري. له همدې امله دوی راټولیږي. ولې دا حتی پیښیږي؟ دا د کرون دندو سره سرور دی چې په دوامداره توګه نوي دندې رامینځته کوي ، او د دوی سره نوي پوډونه. پدې توګه ، په دوی کې د کانټینرونو لپاره نوي cgroups رامینځته شوي ، کوم چې ډیر ژر حذف کیږي.
  • ولې په کبلیټ کې د مشر سلاکار دومره وخت ضایع کوي؟ دا د ساده اجرا کولو سره لیدل اسانه دي time cat /sys/fs/cgroup/memory/memory.stat. که چیرې په صحي ماشین کې عملیات 0,01 ثانیې وخت ونیسي، نو په ستونزمن کرون 02 کې دا 1,2 ثانیې وخت نیسي. خبره دا ده چې cAdvisor ، کوم چې د sysfs ډیټا خورا ورو لوستل کوي ، هڅه کوي هغه حافظه په پام کې ونیسي چې په زومبي cgroups کې کارول کیږي.
  • په زور سره د زومبیانو لرې کولو لپاره، موږ هڅه وکړه چې د کیچ پاکولو هڅه وکړو لکه څنګه چې په LKML کې وړاندیز شوي: sync; echo 3 > /proc/sys/vm/drop_caches, - مګر دانه نوره پیچلې شوه او موټر یې ټکر کړ.

چې څه کول پکار دي؟ ستونزه حل کیږي (ژمن، او د وضاحت لپاره وګورئ پیغام خپور کړئ) د لینکس کرنل نسخه 4.16 ته تازه کول.

تاریخ 3. Systemd او د هغې غره

یوځل بیا ، کبلیټ په ځینو نوډونو کې ډیرې سرچینې مصرفوي ، مګر دا ځل دا خورا ډیر حافظه مصرفوي:

د کوبرنیټس په عملیاتو کې د ساتیرۍ سیسټم 6 بګونه [او د دوی حل]

دا معلومه شوه چې په اوبنټو 16.04 کې کارول شوي سیسټم کې ستونزه شتون لري ، او دا پیښیږي کله چې د ماونټونو اداره کول چې د اتصال لپاره رامینځته شوي subPath د ConfigMap یا رازونو څخه. وروسته له دې چې پوډ خپل کار بشپړ کړ د سیسټمډ خدمت او د دې خدماتو ماونټ پاتې دي په سیسټم کې. د وخت په تیریدو سره، د دوی لوی شمیر راټولیږي. په دې موضوع کې حتی ستونزې شتون لري:

  1. #5916;
  2. kubernetes #57345.

... وروستی چې په سیسټم کې PR ته اشاره کوي: #7811 (په سیسټم کې مسله - #7798).

ستونزه نور په اوبنټو 18.04 کې شتون نلري ، مګر که تاسو غواړئ د اوبنټو 16.04 کارولو ته دوام ورکړئ ، نو تاسو ممکن پدې موضوع کې زموږ کاري حل ګټور ومومئ.

نو موږ لاندې ډیمون سیټ جوړ کړ:

---
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
  labels:
    app: systemd-slices-cleaner
  name: systemd-slices-cleaner
  namespace: kube-system
spec:
  updateStrategy:
    type: RollingUpdate
  selector:
    matchLabels:
      app: systemd-slices-cleaner
  template:
    metadata:
      labels:
        app: systemd-slices-cleaner
    spec:
      containers:
      - command:
        - /usr/local/bin/supercronic
        - -json
        - /app/crontab
        Image: private-registry.org/systemd-slices-cleaner/systemd-slices-cleaner:v0.1.0
        imagePullPolicy: Always
        name: systemd-slices-cleaner
        resources: {}
        securityContext:
          privileged: true
        volumeMounts:
        - name: systemd
          mountPath: /run/systemd/private
        - name: docker
          mountPath: /run/docker.sock
        - name: systemd-etc
          mountPath: /etc/systemd
        - name: systemd-run
          mountPath: /run/systemd/system/
        - name: lsb-release
          mountPath: /etc/lsb-release-host
      imagePullSecrets:
      - name: antiopa-registry
      priorityClassName: cluster-low
      tolerations:
      - operator: Exists
      volumes:
      - name: systemd
        hostPath:
          path: /run/systemd/private
      - name: docker
        hostPath:
          path: /run/docker.sock
      - name: systemd-etc
        hostPath:
          path: /etc/systemd
      - name: systemd-run
        hostPath:
          path: /run/systemd/system/
      - name: lsb-release
        hostPath:
          path: /etc/lsb-release

... او دا لاندې سکریپټ کاروي:

#!/bin/bash

# we will work only on xenial
hostrelease="/etc/lsb-release-host"
test -f ${hostrelease} && grep xenial ${hostrelease} > /dev/null || exit 0

# sleeping max 30 minutes to dispense load on kube-nodes
sleep $((RANDOM % 1800))

stoppedCount=0
# counting actual subpath units in systemd
countBefore=$(systemctl list-units | grep subpath | grep "run-" | wc -l)
# let's go check each unit
for unit in $(systemctl list-units | grep subpath | grep "run-" | awk '{print $1}'); do
  # finding description file for unit (to find out docker container, who born this unit)
  DropFile=$(systemctl status ${unit} | grep Drop | awk -F': ' '{print $2}')
  # reading uuid for docker container from description file
  DockerContainerId=$(cat ${DropFile}/50-Description.conf | awk '{print $5}' | cut -d/ -f6)
  # checking container status (running or not)
  checkFlag=$(docker ps | grep -c ${DockerContainerId})
  # if container not running, we will stop unit
  if [[ ${checkFlag} -eq 0 ]]; then
    echo "Stopping unit ${unit}"
    # stoping unit in action
    systemctl stop $unit
    # just counter for logs
    ((stoppedCount++))
    # logging current progress
    echo "Stopped ${stoppedCount} systemd units out of ${countBefore}"
  fi
done

... او دا په هر 5 دقیقو کې د مخکینۍ ذکر شوي سوپرکرونیک په کارولو سره چلیږي. د دې ډاکر فایل داسې ښکاري:

FROM ubuntu:16.04
COPY rootfs /
WORKDIR /app
RUN apt-get update && 
    apt-get upgrade -y && 
    apt-get install -y gnupg curl apt-transport-https software-properties-common wget
RUN add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu xenial stable" && 
    curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add - && 
    apt-get update && 
    apt-get install -y docker-ce=17.03.0*
RUN wget https://github.com/aptible/supercronic/releases/download/v0.1.6/supercronic-linux-amd64 -O 
    /usr/local/bin/supercronic && chmod +x /usr/local/bin/supercronic
ENTRYPOINT ["/bin/bash", "-c", "/usr/local/bin/supercronic -json /app/crontab"]

کیسه 4. سیالي د پوډونو مهالویش کولو پر مهال

دا یادونه وشوه چې: که موږ یو پوډ په نوډ کې ځای په ځای کړو او د هغې عکس د ډیر وخت لپاره پمپ شي ، نو یو بل پوډ چې ورته نوډ "ټیټ" کوي په ساده ډول د نوي پوډ عکس ایستل پیل نه کوي. پرځای یې، دا انتظار کوي تر هغه چې د مخکینۍ پوډ عکس راښکته شي. د پایلې په توګه ، یو پوډ چې دمخه ټاکل شوی و او عکس یې یوازې په یوه دقیقه کې ډاونلوډ کیدی شي د حالت حالت کې به پای ته ورسیږي. containerCreating.

پیښې به داسې ښکاري:

Normal  Pulling    8m    kubelet, ip-10-241-44-128.ap-northeast-1.compute.internal  pulling image "registry.example.com/infra/openvpn/openvpn:master"

دا دا معلومه شوه د ورو راجسټری څخه یو واحد عکس کولی شي ځای پرځای کول بند کړي هر نوډ

له بده مرغه، د وضعیت څخه ډیری لارې شتون نلري:

  1. هڅه وکړئ خپل د ډاکر راجستر په مستقیم ډول په کلستر کې یا مستقیم د کلستر سره وکاروئ (د مثال په توګه د GitLab راجستری، Nexus، او نور)؛
  2. د اسانتیاو څخه کار واخلئ لکه kraken.

کیسه 5. نوډونه د حافظې د نشتوالي له امله ځړول

د مختلف غوښتنلیکونو د عملیاتو په جریان کې ، موږ د داسې وضعیت سره هم مخ شو چې یو نوډ په بشپړ ډول د لاسرسي مخه نیسي: SSH ځواب نه ورکوي ، د څارنې ټول ډیمونونه له مینځه ځي ، او بیا په لاګونو کې هیڅ شی شتون نلري (یا نږدې هیڅ شی) غیر معمولي ندي.

زه به تاسو ته په عکسونو کې د یو نوډ مثال په کارولو سره ووایم چیرې چې MongoDB فعالیت کوي.

دا هغه څه دي چې پورته ښکاري پورې حادثې:

د کوبرنیټس په عملیاتو کې د ساتیرۍ سیسټم 6 بګونه [او د دوی حل]

او دا ډول - после حادثې:

د کوبرنیټس په عملیاتو کې د ساتیرۍ سیسټم 6 بګونه [او د دوی حل]

په څارنه کې، یو تیز کود هم شتون لري، په کوم کې چې نوډ شتون لري:

د کوبرنیټس په عملیاتو کې د ساتیرۍ سیسټم 6 بګونه [او د دوی حل]

په دې توګه، د سکرین شاټونو څخه دا روښانه ده چې:

  1. په ماشین کې رام پای ته نږدې دی؛
  2. د رام په مصرف کې ګړندی کود شتون لري ، وروسته له دې چې ټول ماشین ته لاسرسی ناڅاپه غیر فعال شوی؛
  3. په مونګو کې یو لوی کار راځي، کوم چې د DBMS پروسه مجبوروي چې ډیرې حافظې وکاروي او په فعاله توګه د ډیسک څخه لوستل شي.

دا معلومه شوه چې که لینوکس د وړیا حافظې څخه تیریږي (د حافظې فشار دننه کیږي) او هیڅ سویپ شتون نلري ، نو پورې کله چې د OOM وژونکي راشي، د پاڼې زیرمې ته د پاڼو اچولو او بیرته ډیسک ته د لیکلو تر منځ د توازن عمل رامنځته کیدی شي. دا د kswapd لخوا ترسره کیږي، کوم چې په زړورتیا سره د راتلونکي توزیع لپاره د امکان تر حده ډیری حافظې پاڼې خلاصوي.

له بده مرغه، د لوی I/O بار سره د لږ مقدار وړیا حافظې سره یوځای، kswapd د ټول سیسټم خنډ ګرځيځکه چې دوی ورسره تړلي دي ټول په سیسټم کې د حافظې مخونو تخصیص (د مخ غلطۍ). دا د ډیر وخت لپاره دوام کولی شي که چیرې پروسې نور نه غواړي حافظه وکاروي ، مګر د OOM وژونکي ابیس په څنډه کې ټاکل شوي.

طبیعي پوښتنه دا ده: ولې د OOM قاتل دومره ناوخته راځي؟ په خپل اوسني تکرار کې، د OOM وژونکی خورا احمق دی: دا به پروسه یوازې هغه وخت وژني کله چې د حافظې پاڼې تخصیص کولو هڅه ناکامه شي، د بیلګې په توګه. که د پاڼې غلطي ناکامه شي. دا د ډیر وخت لپاره نه پیښیږي، ځکه چې kswapd په زړورتیا سره د حافظې پاڼې خلاصوي، د پاڼې کیچ ډمپ کوي (په سیسټم کې ټول ډیسک I/O، په حقیقت کې) بیرته ډیسک ته. په ډیر تفصیل سره، په دانا کې د ورته ستونزو د له منځه وړلو لپاره اړین ګامونو توضیح سره، تاسو لوستلی شئ دلته.

دا چلند باید ښه شي د لینکس کرنل 4.6+ سره.

6 کیسه. پوزې په پاتې حالت کې بندیږي

په ځینو کلسترونو کې، په کوم کې چې واقعیا ډیری پوډونه کار کوي، موږ په دې پوهیدل پیل کړل چې ډیری یې په دولت کې د ډیر وخت لپاره "ځړول" دي. Pending، که څه هم د ډاکر کانټینرونه پخپله په نوډونو کې روان دي او په لاسي ډول کار کیدی شي.

سربیره پردې، په describe هیڅ شی نشته:

  Type    Reason                  Age                From                     Message
  ----    ------                  ----               ----                     -------
  Normal  Scheduled               1m                 default-scheduler        Successfully assigned sphinx-0 to ss-dev-kub07
  Normal  SuccessfulAttachVolume  1m                 attachdetach-controller  AttachVolume.Attach succeeded for volume "pvc-6aaad34f-ad10-11e8-a44c-52540035a73b"
  Normal  SuccessfulMountVolume   1m                 kubelet, ss-dev-kub07    MountVolume.SetUp succeeded for volume "sphinx-config"
  Normal  SuccessfulMountVolume   1m                 kubelet, ss-dev-kub07    MountVolume.SetUp succeeded for volume "default-token-fzcsf"
  Normal  SuccessfulMountVolume   49s (x2 over 51s)  kubelet, ss-dev-kub07    MountVolume.SetUp succeeded for volume "pvc-6aaad34f-ad10-11e8-a44c-52540035a73b"
  Normal  Pulled                  43s                kubelet, ss-dev-kub07    Container image "registry.example.com/infra/sphinx-exporter/sphinx-indexer:v1" already present on machine
  Normal  Created                 43s                kubelet, ss-dev-kub07    Created container
  Normal  Started                 43s                kubelet, ss-dev-kub07    Started container
  Normal  Pulled                  43s                kubelet, ss-dev-kub07    Container image "registry.example.com/infra/sphinx/sphinx:v1" already present on machine
  Normal  Created                 42s                kubelet, ss-dev-kub07    Created container
  Normal  Started                 42s                kubelet, ss-dev-kub07    Started container

د یو څه کیندلو وروسته، موږ دا انګیرنه وکړه چې کوبیلټ په ساده ډول وخت نلري چې د پوډونو حالت او د ژوندانه / چمتووالي ازموینې د API سرور ته واستوي.

او د مرستې مطالعې وروسته، موږ لاندې پیرامیټونه وموندل:

--kube-api-qps - QPS to use while talking with kubernetes apiserver (default 5)
--kube-api-burst  - Burst to use while talking with kubernetes apiserver (default 10) 
--event-qps - If > 0, limit event creations per second to this value. If 0, unlimited. (default 5)
--event-burst - Maximum size of a bursty event records, temporarily allows event records to burst to this number, while still not exceeding event-qps. Only used if --event-qps > 0 (default 10) 
--registry-qps - If > 0, limit registry pull QPS to this value.
--registry-burst - Maximum size of bursty pulls, temporarily allows pulls to burst to this number, while still not exceeding registry-qps. Only used if --registry-qps > 0 (default 10)

لکه څنګه چې لیدل کیږي، ډیفالټ ارزښتونه خورا کوچني دي، او په 90٪ کې دوی ټولې اړتیاوې پوښي ... په هرصورت ، زموږ په قضیه کې دا کافي ندي. له همدې امله، موږ لاندې ارزښتونه ټاکو:

--event-qps=30 --event-burst=40 --kube-api-burst=40 --kube-api-qps=30 --registry-qps=30 --registry-burst=40

... او کوبیلټونه یې بیا پیل کړل، وروسته له دې چې موږ د API سرور ته د زنګ وهلو په ګراف کې لاندې انځور ولید:

د کوبرنیټس په عملیاتو کې د ساتیرۍ سیسټم 6 بګونه [او د دوی حل]

... او هو، هرڅه په الوتلو پیل شول!

PS

د کیګونو په راټولولو او د دې مقالې چمتو کولو کې د دوی د مرستې لپاره، زه زموږ د شرکت ډیری انجینرانو او په ځانګړې توګه زموږ د R&D ټیم څخه زما همکار انډری کلیمینتییف څخه خپله ژوره مننه کوم.زوزا).

پی پی ایس

زموږ په بلاګ کې هم ولولئ:

سرچینه: www.habr.com

Add a comment