Автоматизация на мрежови услуги или как да изградим виртуална лаборатория с помощта на OpenDaylight, Postman и Vrnetlab

Автоматизация на мрежови услуги или как да изградим виртуална лаборатория с помощта на OpenDaylight, Postman и Vrnetlab

В тази статия ще ви покажа как да настроите отворена дневна светлина за работа с мрежово оборудване и също така показва как да се използва пощаджия и просто RESTCONF заявки, това оборудване може да се контролира. Няма да работим с хардуер, а вместо това ще разположим малки виртуални лаборатории с помощта на един рутер Vrnetlab над Ubuntu LTS 20.04.

Първо ще покажа подробните настройки на примера на рутер Juniper vMX 20.1R1.11и след това го сравняваме с настройката Cisco xRV9000 7.0.2.

Съдържание

  • Необходими знания
  • Часть 1: обсъдете накратко OpenDaylight (наричан по-долу ОДО), пощаджия и Vrnetlab и защо са ни нужни
  • Часть 2: описание на виртуалната лаборатория
  • Часть 3: персонализирайте отворена дневна светлина
  • Часть 4: персонализирайте Vrnetlab
  • Часть 5: като се използва пощаджия свържете виртуален рутер (Хвойна vMX) да се ОДО
  • Часть 6: вземете и променете конфигурацията на рутера с помощта на пощаджия и ОДО
  • Часть 7: добавете Cisco xRV9000
  • Заключение
  • PS
  • Библиография

Необходими знания

За да не се превърне статията в лист, пропуснах някои технически подробности (с връзки към литература, където можете да прочетете за тях).

В тази връзка ви предлагам теми, които би било добре (но почти не е задължително) да знаете преди да прочетете:

Част 1: малко теория

Автоматизация на мрежови услуги или как да изградим виртуална лаборатория с помощта на OpenDaylight, Postman и Vrnetlab

  • Отворена SDN платформа за управление и автоматизиране на всякакви мрежи, поддържана от Linux Foundation
  • Java вътре
  • Въз основа на ниво на абстракция на услуга, управлявана от модела (MD-SAL)
  • Използва YANG модели за автоматично генериране на RESTCONF API за мрежови устройства

Основният модул за управление на мрежата. Именно чрез него ще комуникираме със свързани устройства. Управлява се чрез собствен API.

Можете да прочетете повече за OpenDaylight тук.

Автоматизация на мрежови услуги или как да изградим виртуална лаборатория с помощта на OpenDaylight, Postman и Vrnetlab

  • Инструмент за тестване на API
  • Прост и лесен за използване интерфейс

В нашия случай ние се интересуваме от него като средство за изпращане на REST заявки към OpenDaylight API. Можете, разбира се, да изпращате заявки ръчно, но в Postman всичко изглежда много ясно и идеално отговаря на нашите цели.

За тези, които искат да копаят: на него са написани много учебни материали (например).

Автоматизация на мрежови услуги или как да изградим виртуална лаборатория с помощта на OpenDaylight, Postman и Vrnetlab

  • Инструмент за внедряване на виртуални рутери в Docker
  • Поддържа: Cisco XRv, Juniper vMX, Arista vEOS, Nokia VSR и др.
  • Open Source

Много интересен, но малко известен инструмент. В нашия случай ще го използваме за стартиране на Juniper vMX и Cisco xRV9000 на обикновен Ubuntu 20.04 LTS.

Можете да прочетете повече за това на страница на проекта.

Част 2: Лаб

В този урок ще настроим следната система:

Автоматизация на мрежови услуги или как да изградим виртуална лаборатория с помощта на OpenDaylight, Postman и Vrnetlab

Как работи

  • Хвойна vMX се издига докер контейнер (чрез Vrnetlab) и функционира като най-често срещания виртуален рутер.
  • ОДО свързан към рутера и ви позволява да го контролирате.
  • пощаджия стартира на отделна машина и през нея изпращаме команди ОДО: за свързване / премахване на рутера, промяна на конфигурацията и т.н.

Коментар на устройството на системата

Хвойна vMX и ОДО изискват доста ресурси за стабилната им работа. Само един vMX иска 6 Gb RAM и 4 ядра. Затова беше решено да се преместят всички "тежки тежести" на отделна машина (Heulett Packard Enterprise MicroServer ProLiant Gen8, Ubuntu 20.04 LTS). Рутерът, разбира се, не "лети" върху него, но производителността е достатъчна за малки експерименти.

Част 3: Настройте OpenDaylight

Автоматизация на мрежови услуги или как да изградим виртуална лаборатория с помощта на OpenDaylight, Postman и Vrnetlab

Текущата версия на ODL към момента на писане е Magnesium SR1

1) Инсталирайте Java Open JDK 11 (за по-подробна инсталация тук)

ubuntu:~$ sudo apt install default-jdk

2) Намерете и изтеглете най-новата версия ОДО следователно
3) Разархивирайте изтегления архив
4) Отидете в получената директория
5) Стартиране ./bin/karaf

На тази стъпка ОДО трябва да започне и ще се озовем в конзолата (порт 8181 се използва за достъп отвън, който ще използваме по-късно).

След това инсталирайте Функции на ODLпредназначени за работа с протоколи NETCONF и RESTCONF. За да направите това в конзолата ОДО ние изпълняваме:

opendaylight-user@root> feature:install odl-netconf-topology odl-restconf-all

Това е най-простата настройка. ОДО завършен. (За повече подробности вижте тук).

Част 4: Настройка на Vrnetlab

Автоматизация на мрежови услуги или как да изградим виртуална лаборатория с помощта на OpenDaylight, Postman и Vrnetlab

Подготовка на системата

Преди монтажа Vrnetlab трябва да инсталирате пакетите, необходими за работата му. Като докер, Git, sshpass:

ubuntu:~$ sudo apt update
ubuntu:~$ sudo apt -y install python3-bs4 sshpass make
ubuntu:~$ sudo apt -y install git
ubuntu:~$ sudo apt install -y 
    apt-transport-https ca-certificates 
    curl gnupg-agent software-properties-common
ubuntu:~$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
ubuntu:~$ sudo add-apt-repository 
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu 
   $(lsb_release -cs) 
   stable"
ubuntu:~$ sudo apt update
ubuntu:~$ sudo apt install -y docker-ce docker-ce-cli containerd.io

Инсталиране на Vrnetlab

За монтаж Vrnetlab клонирайте съответното хранилище от github:

ubuntu:~$ cd ~
ubuntu:~$ git clone https://github.com/plajjan/vrnetlab.git

Отидете в директорията vrnetlab:

ubuntu:~$ cd ~/vrnetlab

Тук можете да видите всички скриптове, необходими за изпълнение. Моля, обърнете внимание, че за всеки тип рутер е създадена съответна директория:

ubuntu:~/vrnetlab$ ls
CODE_OF_CONDUCT.md  config-engine-lite        openwrt           vr-bgp
CONTRIBUTING.md     csr                       routeros          vr-xcon
LICENSE             git-lfs-repo.sh           sros              vrnetlab.sh
Makefile            makefile-install.include  topology-machine  vrp
README.md           makefile-sanity.include   veos              vsr1000
ci-builder-image    makefile.include          vmx               xrv
common              nxos                      vqfx              xrv9k

Създайте изображение на рутера

Всеки рутер, който се поддържа Vrnetlab, има своя собствена уникална процедура за настройка. Кога Хвойна vMX просто трябва да качим .tgz архива с рутера (можете да го изтеглите от официалния сайт) към директорията vmx и изпълнете командата make:

ubuntu:~$ cd ~/vrnetlab/vmx
ubuntu:~$ # Копируем в эту директорию .tgz архив с роутером
ubuntu:~$ sudo make

Изграждане на имидж vMX ще отнеме около 10-20 минути. Време е да отидем да пием кафе!

Защо толкова време, ще попитате?

превод отговор автор на този въпрос:

„Това е така, защото първият път, когато VCP (Control Plane) се стартира, той чете конфигурационен файл, който определя дали ще работи като VRR VCP във vMX. Преди това стартирането беше направено по време на стартиране на Docker, но това означаваше, че VCP винаги се рестартира веднъж, преди виртуалният рутер да стане достъпен, което води до дълго време за зареждане (около 5 минути) Сега първото изпълнение на VCP се извършва по време на изграждането на изображението на Docker и тъй като изграждането на Docker не може да се изпълнява с - -привилегирована опция, това означава, че qemu работи без KVM хардуерно ускорение и по този начин изграждането отнема много дълго време. По време на този процес се извеждат много регистрационни файлове, така че поне можете да видите какво се случва. Мисля, че дългото изграждане е не е толкова страшно, защото създаваме изображение веднъж, но пускаме много."

След това можете да видите изображението на нашия рутер докер:

ubuntu:~$ sudo docker image list
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
vrnetlab/vr-vmx     20.1R1.11           b1b2369b453c        3 weeks ago         4.43GB
debian              stretch             614bb74b620e        7 weeks ago         101MB

Стартирайте vr-vmx контейнер

Започваме с командата:

ubuntu:~$ sudo docker run -d --privileged --name jun01 b1b2369b453c

След това можем да видим информация за активните контейнери:

ubuntu:~$ sudo docker container list
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                     PORTS                                                 NAMES
120f882c8712        b1b2369b453c        "/launch.py"        2 minutes ago       Up 2 minutes (unhealthy)   22/tcp, 830/tcp, 5000/tcp, 10000-10099/tcp, 161/udp   jun01

Свързване към рутера

IP адресът на мрежовия интерфейс на рутера може да бъде получен със следната команда:

ubuntu:~$ sudo docker inspect --format '{{.NetworkSettings.IPAddress}}' jun01
172.17.0.2

По подразбиране, Vrnetlab създава потребител на рутера vrnetlab/VR-netlab9.
Свързване с ssh:

ubuntu:~$ ssh [email protected]
The authenticity of host '172.17.0.2 (172.17.0.2)' can't be established.
ECDSA key fingerprint is SHA256:g9Sfg/k5qGBTOX96WiCWyoJJO9FxjzXYspRoDPv+C0Y.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '172.17.0.2' (ECDSA) to the list of known hosts.
Password:
--- JUNOS 20.1R1.11 Kernel 64-bit  JNPR-11.0-20200219.fb120e7_buil
vrnetlab> show version
Model: vmx
Junos: 20.1R1.11

Това завършва настройката на рутера.

Препоръки за инсталиране на рутери на различни доставчици можете да намерите на github проект в съответните директории.

Част 5: Пощальон - свържете рутера към OpenDaylight

Пощальон монтаж

За да инсталирате, просто изтеглете приложението следователно.

Свързване на рутер към ODL

Да творим PUT разследване:

Автоматизация на мрежови услуги или как да изградим виртуална лаборатория с помощта на OpenDaylight, Postman и Vrnetlab

  1. Низ на заявка:
    PUT http://10.132.1.202:8181/restconf/config/network-topology:network-topology/topology/topology-netconf/node/jun01
  2. Основен текст на заявката (раздел Основен текст):
    <node xmlns="urn:TBD:params:xml:ns:yang:network-topology">
    <node-id>jun01</node-id>
    <host xmlns="urn:opendaylight:netconf-node-topology">172.17.0.2</host>
    <port xmlns="urn:opendaylight:netconf-node-topology">22</port>
    <username xmlns="urn:opendaylight:netconf-node-topology">vrnetlab</username>
    <password xmlns="urn:opendaylight:netconf-node-topology">VR-netlab9</password>
    <tcp-only xmlns="urn:opendaylight:netconf-node-topology">false</tcp-only>
    <schema-cache-directory xmlns="urn:opendaylight:netconf-node-topology">jun01_cache</schema-cache-directory>
    </node>
  3. В раздела Упълномощаване трябва да зададете параметъра Basic Auth и вход/парола: admin/admin. Това е необходимо за достъп до ODL:
    Автоматизация на мрежови услуги или как да изградим виртуална лаборатория с помощта на OpenDaylight, Postman и Vrnetlab
  4. В раздела Заглавки трябва да добавите две заглавки:
    • Приемете приложение/xml
    • Content-Type приложение/xml

Нашата молба е направена. Изпращаме. Ако всичко е конфигурирано правилно, тогава трябва да върнем статуса „201 Създаден“:

Автоматизация на мрежови услуги или как да изградим виртуална лаборатория с помощта на OpenDaylight, Postman и Vrnetlab

Какво прави това искане?

Ние създаваме възел вътре ОДО с параметрите на реалния рутер, до който искаме да имаме достъп.

xmlns="urn:TBD:params:xml:ns:yang:network-topology"
xmlns="urn:opendaylight:netconf-node-topology"

Това са вътрешни пространства от имена XML (XML пространство от имена) за ОДО според който създава възел.

Освен това, съответно, името на рутера е node-id, адрес на рутер - домакин и така нататък.

Най-интересната линия е последната. Схема-кеш-директория създава директория, където се изтеглят всички файлове ЯН схема свързан рутер. Можеш да ги намериш в $ODL_ROOT/cache/jun01_cache.

Проверка на връзката на рутера

Да творим GET разследване:

  1. Низ на заявка:
    GET http://10.132.1.202:8181/restconf/operational/network-topology:network-topology/topology/topology-netconf/
  2. В раздела Упълномощаване трябва да зададете параметъра Basic Auth и вход/парола: admin/admin.

Изпращаме. Трябва да получи статус "200 OK" и списък на всички поддържани от устройството ЯН схема:

Автоматизация на мрежови услуги или как да изградим виртуална лаборатория с помощта на OpenDaylight, Postman и Vrnetlab

Коментар: За да видя последното, в моя случай беше необходимо да изчакам около 10 минути след изпълнението PUTдокато всички ЯН схема разтоварвам на ОДО. До този момент, когато изпълнявате това GET заявката ще покаже следното:

Автоматизация на мрежови услуги или как да изградим виртуална лаборатория с помощта на OpenDaylight, Postman и Vrnetlab

Изтрийте рутера

Да творим ИЗТРИЙ разследване:

  1. Низ на заявка:
    DELETE http://10.132.1.202:8181/restconf/config/network-topology:network-topology/topology/topology-netconf/node/jun01
  2. В раздела Упълномощаване трябва да зададете параметъра Basic Auth и вход/парола: admin/admin.

Част 6: Променете конфигурацията на рутера

Получаване на конфигурацията

Да творим GET разследване:

  1. Низ на заявка:
    GET http://10.132.1.202:8181/restconf/config/network-topology:network-topology/topology/topology-netconf/node/jun01/yang-ext:mount/
  2. В раздела Упълномощаване трябва да зададете параметъра Basic Auth и вход/парола: admin/admin.

Изпращаме. Трябва да получи статус "200 OK" и конфигурацията на рутера:

Автоматизация на мрежови услуги или как да изградим виртуална лаборатория с помощта на OpenDaylight, Postman и Vrnetlab

Създайте конфигурация

Като пример, нека създадем следната конфигурация и да я променим:

protocols {
    bgp {
        disable;
        shutdown;
    }
}

Да творим ПУСНИ разследване:

  1. Низ на заявка:
    POST http://10.132.1.202:8181/restconf/config/network-topology:network-topology/topology/topology-netconf/node/jun01/yang-ext:mount/junos-conf-root:configuration/junos-conf-protocols:protocols
  2. Основен текст на заявката (раздел Основен текст):
    <bgp xmlns="http://yang.juniper.net/junos/conf/protocols">
    <disable/>
    <shutdown>
    </shutdown>
    </bgp>
  3. В раздела Упълномощаване трябва да зададете параметъра Basic Auth и вход/парола: admin/admin.
  4. В раздела Заглавки трябва да добавите две заглавки:
    • Приемете приложение/xml
    • Content-Type приложение/xml

След изпращане те трябва да получат статус "204 Няма съдържание"

За да проверите дали конфигурацията се е променила, можете да използвате предишната заявка. Но например ще създадем друг, който ще показва информация само за протоколите, конфигурирани на рутера.

Да творим GET разследване:

  1. Низ на заявка:
    GET http://10.132.1.202:8181/restconf/config/network-topology:network-topology/topology/topology-netconf/node/jun01/yang-ext:mount/junos-conf-root:configuration/junos-conf-protocols:protocols
  2. В раздела Упълномощаване трябва да зададете параметъра Basic Auth и вход/парола: admin/admin.

След като изпълним заявката, ще видим следното:

Автоматизация на мрежови услуги или как да изградим виртуална лаборатория с помощта на OpenDaylight, Postman и Vrnetlab

Променете конфигурацията

Нека променим информацията за BGP протокола. След нашите действия ще изглежда така:

protocols {
    bgp {
        disable;
    }
}

Да творим PUT разследване:

  1. Низ на заявка:
    PUT http://10.132.1.202:8181/restconf/config/network-topology:network-topology/topology/topology-netconf/node/jun01/yang-ext:mount/junos-conf-root:configuration/junos-conf-protocols:protocols
  2. Основен текст на заявката (раздел Основен текст):
    <protocols xmlns="http://yang.juniper.net/junos/conf/protocols">
    <bgp>
        <disable/>
    </bgp>
    </protocols>
  3. В раздела Упълномощаване трябва да зададете параметъра Basic Auth и вход/парола: admin/admin.
  4. В раздела Заглавки трябва да добавите две заглавки:
    • Приемете приложение/xml
    • Content-Type приложение/xml

Използвайки предишното GET заявка, виждаме промените:

Автоматизация на мрежови услуги или как да изградим виртуална лаборатория с помощта на OpenDaylight, Postman и Vrnetlab

Изтрийте конфигурацията

Да творим ИЗТРИЙ разследване:

  1. Низ на заявка:
    DELETE http://10.132.1.202:8181/restconf/config/network-topology:network-topology/topology/topology-netconf/node/jun01/yang-ext:mount/junos-conf-root:configuration/junos-conf-protocols:protocols
  2. В раздела Упълномощаване трябва да зададете параметъра Basic Auth и вход/парола: admin/admin.

При обаждане GET заявка с информация за протоколите, ще видим следното:

Автоматизация на мрежови услуги или как да изградим виртуална лаборатория с помощта на OpenDaylight, Postman и Vrnetlab

допълни:

За да промените конфигурацията, не е необходимо да изпращате тялото на заявката във формат XML. Това може да стане и във формата JSON.

За да направите това, например, в заявката PUT за да промените конфигурацията, заменете тялото на заявката с:

{
    "junos-conf-protocols:protocols": {
        "bgp": {
            "description" : "Changed in postman" 
        }
    }
}

Не забравяйте да промените заглавките в раздела Заглавки на:

  • Приемете приложение/json
  • Content-Type application/json

След изпращане ще получим следния резултат (Ние разглеждаме отговора с помощта на GET заявка):

Автоматизация на мрежови услуги или как да изградим виртуална лаборатория с помощта на OpenDaylight, Postman и Vrnetlab

Част 7: Добавяне на Cisco xRV9000

Какво сме всички за Juniper, да Juniper? Да поговорим за Cisco!
Намерих xRV9000 версия 7.0.2 (звяр, който се нуждае от 8 Gb RAM и 4 ядра. Не е свободно достъпен, така че се свържете Cisco) - нека го стартираме.

Изпълнение на контейнер

Процесът на създаване на Docker контейнер на практика не се различава от Juniper. По същия начин пускаме файла .qcow2 с рутера в директорията, съответстваща на неговото име (в този случай xrv9k) и изпълняваме командата make docker-image.

След няколко минути виждаме, че изображението е създадено:

ubuntu:~$ sudo docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
vrnetlab/vr-xrv9k   7.0.2               54debc7973fc        4 hours ago         1.7GB
vrnetlab/vr-vmx     20.1R1.11           b1b2369b453c        4 weeks ago         4.43GB
debian              stretch             614bb74b620e        7 weeks ago         101MB

Стартираме контейнера:

ubuntu:~$ sudo docker run -d --privileged --name xrv01 54debc7973fc

След известно време виждаме, че контейнерът е започнал:

ubuntu:~$ sudo docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                 PORTS                                                      NAMES
058c5ecddae3        54debc7973fc        "/launch.py"        4 hours ago         Up 4 hours (healthy)   22/tcp, 830/tcp, 5000-5003/tcp, 10000-10099/tcp, 161/udp   xrv01

Свързване чрез ssh:

ubuntu@ubuntu:~$ ssh [email protected]
Password:

RP/0/RP0/CPU0:ios#show version
Mon Jul  6 12:19:28.036 UTC
Cisco IOS XR Software, Version 7.0.2
Copyright (c) 2013-2020 by Cisco Systems, Inc.

Build Information:
 Built By     : ahoang
 Built On     : Fri Mar 13 22:27:54 PDT 2020
 Built Host   : iox-ucs-029
 Workspace    : /auto/srcarchive15/prod/7.0.2/xrv9k/ws
 Version      : 7.0.2
 Location     : /opt/cisco/XR/packages/
 Label        : 7.0.2

cisco IOS-XRv 9000 () processor
System uptime is 3 hours 22 minutes

Свързване на рутера към OpenDaylight

Добавянето става по напълно подобен начин с vMX. Просто трябва да променим имената.
PUT разследване:
Автоматизация на мрежови услуги или как да изградим виртуална лаборатория с помощта на OpenDaylight, Postman и Vrnetlab

Обадете се след малко GET заявка, за да проверите дали всичко е свързано:
Автоматизация на мрежови услуги или как да изградим виртуална лаборатория с помощта на OpenDaylight, Postman и Vrnetlab

Променете конфигурацията

Нека настроим следната конфигурация:

!
router ospf LAB
 mpls ldp auto-config
!

Да творим ПУСНИ разследване:

  1. Низ на заявка:
    POST http://10.132.1.202:8181/restconf/config/network-topology:network-topology/topology/topology-netconf/node/xrv01/yang-ext:mount/Cisco-IOS-XR-ipv4-ospf-cfg:ospf
  2. Основен текст на заявката (раздел Основен текст):
    {
        "processes": {
            "process": [
                {
                    "process-name": "LAB",
                    "default-vrf": {
                        "process-scope": {
                            "ldp-auto-config": [
                                null
                            ]
                        }
                    }
                }
            ]
        }
    }
  3. В раздела Упълномощаване трябва да зададете параметъра Basic Auth и вход/парола: admin/admin.
  4. В раздела Заглавки трябва да добавите две заглавки:
    • Приемете приложение/json
    • Content-Type application/json

След изпълнението му те трябва да получат статус „204 Няма съдържание“.

Нека проверим какво имаме.
За да направим това, ние ще създадем GET разследване:

  1. Низ на заявка:
    GET http://10.132.1.202:8181/restconf/config/network-topology:network-topology/topology/topology-netconf/node/xrv01/yang-ext:mount/Cisco-IOS-XR-ipv4-ospf-cfg:ospf
  2. В раздела Упълномощаване трябва да зададете параметъра Basic Auth и вход/парола: admin/admin.

След изпълнението трябва да видите следното:

Автоматизация на мрежови услуги или как да изградим виртуална лаборатория с помощта на OpenDaylight, Postman и Vrnetlab

За да премахнете конфигурацията, използвайте ИЗТРИЙ:

  1. Низ на заявка:
    DELETE http://10.132.1.202:8181/restconf/config/network-topology:network-topology/topology/topology-netconf/node/xrv01/yang-ext:mount/Cisco-IOS-XR-ipv4-ospf-cfg:ospf
  2. В раздела Упълномощаване трябва да зададете параметъра Basic Auth и вход/парола: admin/admin.

Заключение

Като цяло, както може би сте забелязали, процедурите за свързване на Cisco и Juniper към OpenDaylight не се различават - това отваря доста широко поле за творчество. Започвайки от управление на конфигурацията на всички мрежови компоненти и завършвайки със създаването на собствени мрежови политики.
В този урок дадох най-простите примери за това как можете да взаимодействате с мрежово оборудване с помощта на OpenDaylight. Без съмнение, заявките от горните примери могат да бъдат направени много по-сложни и да настроите цели услуги с едно щракване на мишката - всичко е ограничено само от вашето въображение *

За да се продължи ...

PS

Ако изведнъж вече знаете всичко това или, напротив, сте преминали и сте потънали в душата на ODL, тогава препоръчвам да погледнете към разработването на приложения на ODL контролера. Можете да започнете следователно.

Успешни експерименти!

Позоваването

  1. Vrnetlab: Емулирайте мрежи с помощта на KVM и Docker / Брайън Линклетър
  2. Готварска книга OpenDaylight / Mathieu Lemay, Alexis de Talhouet, Et al
  3. Мрежова програмируемост с YANG / Benoît Claise, Loe Clarke, Jan Lindblad
  4. Изучаване на XML, второ издание / Ерик Т. Рей
  5. Effective DevOps / Дженифър Дейвис, Рин Даниелс

Източник: www.habr.com

Добавяне на нов коментар