Translate

понеділок, 15 травня 2017 р.

Cloud Foundry. Part III: BOSH 2 Lite/Cloud Foundry (Diego)

Декілька тижнів тому я опублікував другу статтю про PAAS-платформу Cloud Foundry, а цього разу мова піде про установку нового Cloud Foundry з Diego runtime. Нагадаю, що Diego має купу вдосконалень в порівнянні з DEA, а саме нова система менеджменту контейнерів Garden, що підтримує деплой Docker-контейнерів, новий алгоритм розміщення задач Diego Auction та інші оптимізації.

Підтримка DEA буде припинена 22 травня 2017 року, останні релізи stemcell вже не працюють з DEA, тому практичне знайомство з Cloud Foundry ліпше починати з цієї статті. Цього разу буде описана установка BOSH2 Lite (так, існує ще і друга версія), Cloud Foundry з Diego runtime.

1. BOSH 2 LITE INSTALLATION (BOSH 2 DIRECTOR)


BOSH Lite - це реліз системи виливки Cloud Foundry для системи VirtualBox. Тож останній має бути встановлений в хост-системі:

$ VBoxManage --version
5.1.22r115126

Для інсталяції BOSH 2 Lite більше не потрібен Vagrant, адже його установочні скрипти вміють працювати з VirtualBox напряму.

BOSH 2 CLI написаний на мові Go і його установка для macOS заключається в завантаженні готового бінарного файлу:

$ cd ~/Downloads
$ wget https://s3.amazonaws.com/bosh-cli-artifacts/bosh-cli-2.0.16-darwin-amd64
$ chmod +x bosh-cli-*
# mv bosh-cli-* /usr/local/bin/bosh2

$ bosh2 -v
version 2.0.16-88aa790-2017-05-02T01:12:20Z

За релізами версій BOSH2 CLI можна слідкувати за наступним посиланням https://bosh.io/docs/cli-v2.html. Там же можна завантажити останню версію BOSH2 CLI для ОС Linux.

Клонуємо репозиторій BOSH:

$ cd -
$ git clone https://github.com/cloudfoundry/bosh-deployment
$ cd bosh-deployment

Створимо інсталяцію BOSH2:

$ bosh2 create-env bosh.yml \
    --state ./state.json \
    -o virtualbox/cpi.yml \
    -o virtualbox/outbound-network.yml \
    -o bosh-lite.yml \
    -o bosh-lite-runc.yml \
    -o jumpbox-user.yml \
    --vars-store ./creds.yml \
    -v director_name="Bosh Lite Director" \
    -v internal_ip=192.168.50.6 \
    -v internal_gw=192.168.50.1 \
    -v internal_cidr=192.168.50.0/24 \
    -v outbound_network_name=NatNetwork

Deployment manifest: '/Users/yuby/workspace/bosh-deployment/bosh.yml'
Deployment state: './state.json'

Started validating
  Downloading release 'bosh'... Finished (00:00:25)
  Validating release 'bosh'... Finished (00:00:00)
...
  Validating deployment manifest... Finished (00:00:00)
  Downloading stemcell... Finished (00:01:09)
  Validating stemcell... Finished (00:00:00)
Finished validating (00:02:40)

Started installing CPI
  Compiling package 'golang_1.7/21609f611781e8586e713cfd7ceb389cee429c5a'... Finished (00:00:15)
  Compiling package 'virtualbox_cpi/b088193439d01014a46711523fbcfa00073c6b36'... Finished (00:00:11)
  Installing packages... Finished (00:00:02)
  Rendering job templates... Finished (00:00:00)
  Installing job 'virtualbox_cpi'... Finished (00:00:00)
Finished installing CPI (00:00:29)

Starting registry... Finished (00:00:00)
Uploading stemcell 'bosh-vsphere-esxi-ubuntu-trusty-go_agent/3312.15'... Finished (00:00:08)

Started deploying
  Creating VM for instance 'bosh/0' from stemcell 'sc-ce0dfc6f-7d46-46b6-4d0f-1e56234200de'... Finished (00:00:01)
  Waiting for the agent on VM 'vm-57b88257-8262-4c28-6be1-c82d8cc21930' to be ready... Finished (00:01:01)
  Creating disk... Finished (00:00:00)
  Attaching disk 'disk-e3bc69f2-039a-4a2d-4428-35a819d3759c' to VM 'vm-57b88257-8262-4c28-6be1-c82d8cc21930'... Finished (00:00:04)
  Rendering job templates... Finished (00:00:07)
  Compiling package 'libseccomp/7a54b27a61b42980935e863d7060dc5a076b44d0'... Skipped [Package already compiled] (00:00:00)
...
  Compiling package 'virtualbox_cpi/b088193439d01014a46711523fbcfa00073c6b36'... Finished (00:00:16)
  Updating instance 'bosh/0'... Finished (00:00:22)
  Waiting for instance 'bosh/0' to be running... Finished (00:00:11)
  Running the post-start scripts 'bosh/0'... Finished (00:00:01)
Finished deploying (00:02:31)

Stopping registry... Finished (00:00:00)
Cleaning up rendered CPI jobs... Finished (00:00:00)

Succeeded

bosh.yml буде використано, як базовий шаблон для релізу, інші yml-файли описують додаткові маніпуляції/змінні, котрі будуть застосовані до нього. Використовуючи опцію '-v', можна передати змінні напряму під час інсталяції BOSH. Таким чином, ми передаємо IP-адресу, мережу та адресу шлюзу. Після виконання команди вище, також буде створено creds.yml з даними авторизації та state.json, котрий зберігатиме проміжну інформацію, щодо стану роботи BOSH.

Додатково буде створено Host-only віртуальну мережу 192.168.50.0/24 у котрій знаходитиметься BOSH Director та NatNetwork з увімкненим DHCP для майбутніх вузлів Cloud Foundry.

Створимо псевдонім 'vbox' та автентифікуємось до щойно створеного BOSH Director:

$ bosh2 -e 192.168.50.6 --ca-cert <(bosh2 int ./creds.yml --path /director_ssl/ca) alias-env vbox

Using environment '192.168.50.6' as anonymous user

Name      Bosh Lite Director
UUID      62435f05-0870-488b-bed8-afda42223a72
Version   261.4.0 (00000000)
CPI       warden_cpi
Features  compiled_package_cache: disabled
          config_server: disabled
          dns: disabled
          snapshots: disabled
User      (not logged in)

Succeeded

$ export BOSH_CLIENT=admin
$ export BOSH_CLIENT_SECRET=`bosh2 int ./creds.yml --path /admin_password`

Перевірити статус BOSH 2 можна наступною командою:

$ bosh2 -e vbox env

У BOSH 1 цю ж інформацію можна було вивести командою 'bosh status'. Зі змінами в синтаксисі BOSH 2 клієнта можна ознайомитись за наступним посиланням https://bosh.io/docs/cli-v2-diff.html

У залежності від операційної системи на хост-машині, додамо маршрут для доступу до підмережі майбутніх вузлів Cloud Foundry:

# route add -net 10.244.0.0/16    192.168.50.6   # Mac OS X
# route add -net 10.244.0.0/16 gw 192.168.50.6   # Linux
# route add      10.244.0.0/16    192.168.50.6   # Windows

За необхідності, до BOSH Director можна підключитись по ssh:

# bosh2 int ./creds.yml --path /jumpbox_ssh/private_key > ~/.ssh/bosh-virtualbox.key
# chmod 600 ~/.ssh/bosh-virtualbox.key
# ssh -i ~/.ssh/bosh-virtualbox.key -o 'IdentitiesOnly yes' jumpbox@192.168.50.6


2. DEPLOYING CLOUD FOUNDRY


Повторно автентифікуємось до BOSH Director на випадок якщо були розлогінені:

$ cd -
$ cd bosh-deployment
$ export BOSH_CLIENT=admin
$ export BOSH_CLIENT_SECRET=`bosh2 int ./creds.yml --path /admin_password`

Зклонуємо репозиторій cf-deployment:

$ cd -
$ git clone https://github.com/cloudfoundry/cf-deployment
$ cd cf-deployment

Дізнаємось яка версія stemcell необхідна для останнього релізу:

$ bosh2 int ./cf-deployment.yml --path /stemcells

- alias: default
  os: ubuntu-trusty
  version: "3363.20"

Succeeded

Саме цю версію для BOSH Lite і завантажимо:

$ bosh2 -e vbox upload-stemcell https://bosh.io/d/stemcells/bosh-warden-boshlite-ubuntu-trusty-go_agent?v=3363.20

Using environment '192.168.50.6' as client 'admin'

Task 29

13:18:41 | Update stemcell: Downloading remote stemcell (00:02:33)
13:21:14 | Update stemcell: Extracting stemcell archive (00:00:03)
13:21:17 | Update stemcell: Verifying stemcell manifest (00:00:00)
13:21:17 | Update stemcell: Checking if this stemcell already exists (00:00:00)
13:21:17 | Update stemcell: Uploading stemcell bosh-warden-boshlite-ubuntu-trusty-go_agent/3363.20 to the cloud (00:00:11)
13:21:28 | Update stemcell: Save stemcell bosh-warden-boshlite-ubuntu-trusty-go_agent/3363.20 (433811f6-9101-4fa4-4f9b-221e7422c487) (00:00:00)

Started  Sat May 13 13:18:41 UTC 2017
Finished Sat May 13 13:21:28 UTC 2017
Duration 00:02:47

Task 29 done

Succeeded

Активуємо cloud-config для майбутньої інсталяції:

$ bosh2 -e vbox update-cloud-config bosh-lite/cloud-config.yml

cloud-config.yml - конфігураційний файл, що описує підмережі, IP-діапазони, що стосуються цих підмереж, типи майбутніх вузлів (на зразок тих, що в AWS) і т.п.

Наразі ми готові до виливки Cloud Foundry:

$ bosh2 -e vbox -d cf deploy cf-deployment.yml \
  -o operations/bosh-lite.yml \
  --vars-store deployment-vars.yml \
  -v system_domain=bosh-lite.com

Using environment '192.168.50.6' as client 'admin'

Using deployment 'cf'

Release 'binary-buildpack/1.0.11' already exists.
...
Release 'postgres/13' already exists.

+ stemcells:
+ - alias: default
+   os: ubuntu-trusty
+   version: '3363.20'

+ releases:
+ - name: binary-buildpack
+   sha1: 09965333c3897aad5b935ec510382c8cbd9e5380
+   url: https://bosh.io/d/github.com/cloudfoundry/binary-buildpack-release?v=1.0.11
+   version: 1.0.11
...
+ - name: postgres
+   sha1: db1b34e15edef77fac68d1b55fac6cd22841d2ff
+   url: https://bosh.io/d/github.com/cloudfoundry/postgres-release?v=13
+   version: '13'

+ update:
+   canaries: 1
+   canary_watch_time: 30000-1200000
+   max_in_flight: 5
+   serial: false
+   update_watch_time: 5000-1200000

+ instance_groups:
+ - azs:
+   - z1
+   instances: 1
+   jobs:
+   - name: smoke_tests
...
+   vm_extensions:
+   - 10GB_ephemeral_disk
+   vm_type: t2.small

+ name: cf

+ variables:
+ - name: blobstore_admin_users_password
+   type: password
...
+ - name: cc_bridge_cc_uploader_server
+   options:
+     ca: service_cf_internal_ca
+     common_name: cc-uploader.service.cf.internal
+     extended_key_usage:
+     - server_auth
+   type: certificate

Continue? [yN]: y

Task 30

14:15:23 | Preparing deployment: Preparing deployment (00:00:01)
14:15:27 | Preparing package compilation: Finding packages to compile (00:00:00)
14:15:27 | Compiling packages: tar/f2ea61c537d8eb8cb2d691ce51e8516b28fa5bb7
...
14:36:14 | Compiling packages: cloud_controller_ng/e761c95ee3939fcc91d287d455813d4bc1d4c049 (00:02:43)
14:36:15 | Creating missing vms: consul/e60da5c3-19bc-4b71-acb5-b8a7263ed6ba (0)
...
14:37:15 | Creating missing vms: cc-clock/aac15c71-1eb3-4874-aa3f-e763ed42204f (0) (00:01:00)
14:37:15 | Updating instance consul: consul/e60da5c3-19bc-4b71-acb5-b8a7263ed6ba (0) (canary) (00:00:52)
...
14:50:43 | Updating instance log-api: log-api/234c505c-cddf-49c0-8b7c-782f6d89a293 (0) (canary) (00:00:54)

Started  Sat May 13 14:15:23 UTC 2017
Finished Sat May 13 14:51:37 UTC 2017
Duration 00:36:14

Task 30 done

Succeeded

Врешті-решт Cloud Foundry буде встановлено і кожен вузол отримає такі адреси:

$ bosh2 -e vbox -d cf instances

Using environment '192.168.50.6' as client 'admin'

Task 48. Done

Deployment 'cf'

Instance                                          Process State  AZ  IPs
api/04d38477-d71d-4830-b297-2fa495ad4151          running        z1  10.244.0.135
blobstore/f5a26327-0fdc-4371-a14a-6be784d06298    running        z1  10.244.0.134
cc-bridge/e62a27b4-662b-48f2-a4d0-a7b2ea0aa0ba    running        z1  10.244.0.140
cc-clock/aac15c71-1eb3-4874-aa3f-e763ed42204f     running        z1  10.244.0.139
cc-worker/6d99bb9a-2160-4cd7-b0d0-b30ebd49681b    running        z1  10.244.0.136
consul/e60da5c3-19bc-4b71-acb5-b8a7263ed6ba       running        z1  10.244.0.128
diego-bbs/29a8555d-bb02-4c76-9785-47eaa745b79c    running        z1  10.244.0.132
diego-brain/64a08b71-47e2-44a6-b631-c6666242e0b8  running        z1  10.244.0.137
diego-cell/90878b1d-781a-4b4e-9f10-2d94ff522aae   running        z1  10.244.0.138
doppler/0600d407-3e9b-46c3-8c3a-572aaca8a77b      running        z1  10.244.0.141
etcd/a9cd33e5-a119-451f-b6a0-2cfb05c06cc1         running        z1  10.244.0.130
log-api/234c505c-cddf-49c0-8b7c-782f6d89a293      running        z1  10.244.0.142
nats/eafe983f-2fcd-41e2-b410-d9f77e2dafe1         running        z1  10.244.0.129
postgres/1072949a-81ce-4b82-8fe1-f61cbaf77295     running        z1  10.244.0.131
router/4ad8c353-7dd8-41a0-b50a-c0b70a435eac       running        z1  10.244.0.34
smoke-tests/14db272c-a374-4381-a88d-a5306b0bb891  -              z1  -
uaa/ac30fcd2-2813-460b-8ad4-8902f190cd25          running        z1  10.244.0.133

17 instances

Succeeded

Про роль кожного вузла в PAAS-платформі можна почитати за посиланням http://blog.ipeacocks.info/2017/04/cloud-foundry-part-i-basics.html

Як я вже згадував, синтаксис клієнта BOSH змінився, але не функціонал. Наприклад, перегляд списку активних задач, їх історії та вивід інформації про виконання задачі (та debug-вивід) виконується так:

$ bosh2 -e vbox tasks
$ bosh2 -e vbox tasks --recent
$ bosh2 -e vbox task 30
$ bosh2 -e vbox task 30 --debug

До кожного вузла Cloud Foundry можна підключитись по ssh:

$ bosh2 -e vbox -d cf ssh postgres/1072949a-81ce-4b82-8fe1-f61cbaf7729

Якщо трішки приділити часу дослідженню інстансів Cloud Foundry/BOSH, то можна помітити, що в кожному із них насправді працює monit, більш того, його версія ~5 річної давнини. Monit моніторить роботу компонентів (процесів бази, якщо це інстанс бази, і т.п.) і по змозі може приймати рішення щодо їх перевантаження. Більш того він може інформувати вузол BOSH Director щодо необхідності перестворення окремих, більш проблемних інстансів.

Після підключення по ssh, за допомогою monit можна на власні очі пересвідчитись у тому як працюють основні процеси інстансу:

# monit summary

The Monit daemon 5.2.4 uptime: 1d 22h 7m

Process 'nats'                      running
Process 'redis'                     running
Process 'postgres'                  running
Process 'powerdns'                  running
Process 'blobstore_nginx'           running
Process 'director'                  running
Process 'worker_1'                  running
Process 'worker_2'                  running
Process 'worker_3'                  running
Process 'director_scheduler'        running
Process 'director_nginx'            running
Process 'registry'                  running
Process 'health_monitor'            running

System 'system_bm-24638eb6-55b9-4670-bb1a-23c9e3f77d91' running

# monit status

The Monit daemon 5.2.4 uptime: 1d 22h 8m

Process 'nats'
  status                            running
  monitoring status                 monitored
  pid                               2951
  parent pid                        1
  uptime                            1d 22h 8m
  children                          0
  memory kilobytes                  24420
  memory kilobytes total            24420
  memory percent                    0.6%
  memory percent total              0.6%
  cpu percent                       0.0%
  cpu percent total                 0.0%
  data collected                    Thu Dec  4 22:44:36 2014

...

У разі проблем якогось із сервісів, можна спробувати перезапустити його власноруч:

# monit restart PROCESS_NAME

Чи перевантажити одразу всі процеси, за котрими слідкує monit:

# monit restart all

Логи усіх процесів зазвичай зберігаються в /var/vcap/sys/log/, а всі описи конфігураційних файлів запуску процесів monit знаходяться за адресою /var/vcap/jobs/.

Доступ і управління вузлами Cloud Foundry, деплой додатків та управління ними відбувається через клієнт cf_cli. Його необхідно проінсталювати, приклад його установки для усіх популярних ОС описаний за посиланням https://docs.cloudfoundry.org/cf-cli/install-go-cli.html

$ cf -v
cf version 6.26.0+9c9a261fd.2017-04-06

Пройдемо аутентифікацію в Cloud Foundry:

$ cf api https://api.bosh-lite.com --skip-ssl-validation
Setting api endpoint to https://api.bosh-lite.com...
OK

api endpoint:   https://api.bosh-lite.com
api version:    2.81.0
Not logged in. Use 'cf login' to log in.

$ export CF_ADMIN_PASSWORD=$(bosh2 int ./deployment-vars.yml --path /cf_admin_password)

$ cf auth admin $CF_ADMIN_PASSWORD
API endpoint: https://api.bosh-lite.com
Authenticating...
OK
Use 'cf target' to view or set your target org and space

Для деплою нового додатку в Cloud Foundry, створимо нову організацію (org) та простір (space):

$ cf create-org org
Creating org org as admin...
OK
Assigning role OrgManager to user admin in org org ...
OK

TIP: Use 'cf target -o org' to target new org

$ cf create-space space -o org
Creating space space in org org as admin...
OK
Assigning role RoleSpaceManager to user admin in org org / space space as admin...
OK
Assigning role RoleSpaceDeveloper to user admin in org org / space space as admin...
OK

TIP: Use 'cf target -o "org" -s "space"' to target new space

Як і порадили, перемикаємось в новостворений space та org:

$ cf target -o org -s space
api endpoint:   https://api.bosh-lite.com
api version:    2.80.0
user:           admin
org:            org
space:          space

Спробуємо завантажити базовий додаток до Cloud Foundry, що не потребує додаткових сервісів https://github.com/cloudfoundry-samples/test-app:

$ git clone git@github.com:cloudfoundry-samples/test-app.git
$ cd test-app

$ cf push test-app
Using manifest file /tmp/test-app/manifest.yml

Creating app test-app in org org / space space as admin...
OK

Creating route test-app-dulotic-joust.bosh-lite.com...
OK

Binding test-app-dulotic-joust.bosh-lite.com to test-app...
OK

Uploading test-app...
Uploading app files from: /private/tmp/test-app
Uploading 85.2K, 116 files
Done uploading
OK

Starting app test-app in org org / space space as admin...
Downloading staticfile_buildpack...
Downloading java_buildpack...
Downloading binary_buildpack...
...
Uploaded droplet (3.1M)
Uploading complete
Destroying container
Successfully destroyed container

1 of 1 instances running

App started

OK

App test-app was started using this command `test-app`

Showing health and status for app test-app in org org / space space as admin...
OK

requested state: started
instances: 1/1
usage: 256M x 1 instances
urls: test-app-dulotic-joust.bosh-lite.com
last uploaded: Sun May 14 09:22:43 UTC 2017
stack: cflinuxfs2
buildpack: Go

     state     since                    cpu    memory         disk          details
#0   running   2017-05-14 12:24:56 PM   0.0%   8.5M of 256M   13.4M of 1G

$ cf apps
Getting apps in org org / space space as admin...
OK

name       requested state   instances   memory   disk   urls
test-app   started           1/1         256M     1G     test-app-dulotic-joust.bosh-lite.com

Роботу нового додатку можна перевірити в браузері:


Завдяки Diego, наразі є можливість підключення по ssh до контейнеру з додатком задля, наприклад, debug цілей:

$ cf ssh test-app

BusyBox v1.21.1 (Ubuntu 1:1.21.0-1ubuntu1) built-in shell (ash)
Enter 'help' for a list of built-in commands.

~ #

Масштабуються додатки аналогічним чином, як це відбувалось раніше з DEA runtime:

$ cf scale test-app -m 2G -k 2G -i 2

Додатково можна спробувати задеплоїти Redis Broker, приклад виливки якого я приводив в попередній статті. Не зважаючи на те, що цього разу ми використовуємо нову версію BOSH та Cloud Foundry з Diego runtime, процедура його виливки не має особливо відрізнятись.

2.1. DOCKER CONTAINER INTEGRATION (OCI)


З міграцією на Diego runtime, в Cloud Foundry з'явилась підтримка контейнерів Docker. Мається на увазі, що Cloud Foundry може читати Docker-контейнери (або будь-які ОСІ-контейнери) і після перетворення їх у зрозумілі для себе Garden-контейнери, завдяки бекенду Garden-runC, запускати.

Активувати цю можливість зовсім не складно:

$ cf enable-feature-flag diego_docker
Setting status of diego_docker as admin...

OK

Feature diego_docker Enabled.

Завантажимо тестовий додаток з Docker Hub:

$ cf push lattice-app -o cloudfoundry/lattice-app
Using manifest file /tmp/test-app/manifest.yml

Creating app lattice-app in org org / space space as admin...
OK

Creating route lattice-app-pulmonary-unetherealness.bosh-lite.com...
OK

Binding lattice-app-pulmonary-unetherealness.bosh-lite.com to lattice-app...
OK

Starting app lattice-app in org org / space space as admin...
Creating container
Successfully created container
Staging...
Staging process started ...
Staging process finished
Exit status 0
Staging Complete
Destroying container
Successfully destroyed container

0 of 1 instances running, 1 starting
...
1 of 1 instances running

App started

OK

App lattice-app was started using this command `/lattice-app `

Showing health and status for app lattice-app in org org / space space as admin...
OK

requested state: started
instances: 1/1
usage: 256M x 1 instances
urls: lattice-app-pulmonary-unetherealness.bosh-lite.com
last uploaded: Sun May 14 19:47:29 UTC 2017
stack: cflinuxfs2
buildpack: unknown

     state     since                    cpu    memory      disk      details
#0   running   2017-05-14 10:47:57 PM   0.0%   0 of 256M   0 of 1G

$ cf apps
Getting apps in org org / space space as admin...
OK

name          requested state   instances   memory   disk   urls
lattice-app   started           1/1         256M     1G     lattice-app-pulmonary-unetherealness.bosh-lite.com

Перевірити, що додаток стартував успішно, можна за посиланням вказаним в полі urls.

Цього разу Cloud Foundry не буде за допомогою buildpack-у створювати droplet з додатком, адже він буде вважати, що в контейнер вже додано всі необхідні залежності. У випадку ж оновлення додатку необіхідно буде залити новий контейнер.

Звісно, можна скористатись і приватним docker-registry для деплою додатків. В такому випадку команда матиме приблизно наступний вигляд:

$ cf push APP-NAME --docker-image MY-PRIVATE-REGISTRY.DOMAIN:PORT/REPO/IMAGE:TAG

Посилання:
https://github.com/cloudfoundry/bosh-deployment/blob/master/docs/bosh-lite-on-vbox.md
https://www.starkandwayne.com/blog/bosh-lite-on-virtualbox-with-bosh2/
https://starkandwayne.com/blog/running-cloud-foundry-locally-on-bosh-lite-with-bosh2/
https://docs.pivotal.io/pivotalcf/1-7/concepts/docker.html
http://dojoblog.emc.com/cloud-foundry/using-docker-container-cloud-foundry/
https://github.com/cloudfoundry/diego-design-notes/blob/master/docker-support.md
https://www.slideshare.net/gwennetourneau/bosh-20reloaded
https://blog.altoros.com/cloud-foundry-containers-warden-docker-garden.html
https://docs.cloudfoundry.org/devguide/deploy-apps/cf-networking.html
https://content.pivotal.io/blog/cloud-foundrys-container-technology-a-garden-overview
https://docs.cloudfoundry.org/running/troubleshooting.html

1 коментар:

  1. Добрый день, очень хотел бы с вами пообщаться на предмет совместных статей. пожалуйста напишите в скайп - vkarabedyants

    ВідповістиВидалити