V minulém článku [1] jsem se zmínil, že pro testy “standalone” kontejnerů lze použít Meta-Test-Family, zkráceně MTF [2]. Bez testů bychom neměli vydávat kontejnery, neboť potřebujeme zaručit, že daná služba v kontejneru skutečně běží.
Další možností jak spouštět kontejnery lze pomocí OpenShiftu [3] a obzvláště testování kontejnerů v OpenShift prostředí.
Tento článek Vám popíše, jak otestovat, zda-li kontejner je schopný běžet v “orchestrovaném” prostředí, tedy v OpenShiftu.
Jen tak mimochodem, Fedora obsahuje nemalé množství kontejnerů[4].
Instalace MTF
Před samotným testování kontejnerů, je potřeba nainstalovat MTF. Za tímto účelem lze použít tři možné způsoby.
Instalace z Fedořích repositářů, jež obsahuje stabilní verzi, včetně EPELu příkazem:
sudo dnf install -y meta-test-family
Instalace z COPR repositáře, jež obsahuje vývojovou verzi a nedoporučujeme ji používat na produkční prostředí.
sudo dnf copr enable phracek/meta-test-family sudo dnf install -y meta-test-family
Instalace přímo z GIT repositáře příkazem [5]
git clone git@github.com:fedora-modularity/meta-test-family.git sudo python setup.py install
Nyní můžeme začít testovat kontejner v OpenShiftu.
Příprava testů pro OpenShift
Před samotnou přípravou prostředí pro OpenShift a spuštěním testů, je nutné nejprve vytvořit konfigurační soubor v YAML formátu a samotné testy.
Konfigurační soubor pro testy v OpenShiftu vypadá přibližně následovně
document: modularity-testing version: 1 name: memcached service: port: 11211 module: openshift: container: docker.io/modularitycontainers/memcached
Co v tomto YAML konfigurační souboru jednotlivé části znamenají:
service.port – port, který kontejner „exposuje“ do systemu. module.openshift – konfigurační část relevantní pouze pro testování kontejneru v OpenShiftu module.openshift.container – Reference na contejner, který bude použit v OpenShiftu.
Příprava prostředí pro testování v OpenShiftu
Spouštění Vašich kontejnerů lokálně je extrémně jednoduché - pouze spusťte docker run
. Ale to není to co chcete, pokud Vaše aplikace má běžet v produkčním prostředí - to je věc OpenShiftu. Abychom si byly jisti, jestli Vaše kontejnery správně fungují jako orchestrované, měli bychom je v takovém prostředí také otestovat. Je vhodné poznamenat, že standalone kontejnery jsou od orchestrovaných kontejnerů výrazně odlišné.
Jaký je vlastně rozdíl mezi standalone kontejnery a orchestrovanými?
Standalone kontejnerymlze spustit jednoduše jednoduchým příkazem. Zpravování takových kontejnerů jení jednoduché, musíte vyřešit uložiště, bakupy, updaty, škálování - všechny tyto věci jsou dostupné v orchestrovaném řešení.
OpenShift prostředí má bezpečnostní omezení, odlišnosti v uložištích, očekává že Openshift PODy bude tzv. “stateless”, bude podporovat aktualizace,nativní podporu source-to-image a mnohem více. Nasazení orchestrátoru není snadný úkol. To je důvod, proč jsme se rozhodli přidat podporu pro OpenShift do MTF, abyste mohli snadno otestovat vaši kontejnerovou aplikaci v organizovaném prostředí. V tomto článku Vám ukážu, jak lze toto provést.
Pokud nemáme na svém počítači či notebooku OpenShift, můžeme prostředí připravit pomocí MTF.
MTF poskytuje příkaz mtf-env-setup.
$ sudo MODULE=openshift OPENSHIFT_LOCAL=yes mtf-env-set Setting environment for module: openshift Preparing environment ... Loaded config for name: memcached Starting OpenShift Starting OpenShift using openshift/origin:v3.6.0 ... OpenShift server started. The server is accessible via web console at: https://127.0.0.1:8443 You are logged in as: User: developer Password:To login as administrator: oc login -u system:admin
Co příkaz ve skutečnosti provádí? V případě, že je zadán parameter OPENSHIFT_LOCAL, pak zkontroluje, zda-li jsou v prostředí nainstalovány balíčky origin a origin-clients a pakliže ne, dané balíčky nainstaluje. Test kontejneru v OpenShiftu bude prováděn v tomto případě na lokální na počítači. Součástí toho kroku je i nastartování OpenShiftu příkazem oc cluster up.
Pro případ, že bychom rádi otestovali kontejner na vzdálené instanci OpenShiftu, tento krok odpadá. V případě, že tento parameter nebude uveden, pak se test kontejneru bude provádět na instanci OpenShiftu specifikované OPENSHIFT_IP parameterem. O tom, ale budu psát později.
Tím je prostředí pro testování kontejnerů v OpenShiftu připraveno.
Testy pro kontejner
Test pro náš ukázkový memcached kontejner vypadá následovně:
sanity1.py
import pexpect
from avocado import main
from avocado.core import exceptions
from moduleframework import module_framework
from moduleframework import common
class SanityCheck1(module_framework.AvocadoTest):
"""
:avocado: enable
"""
def test_smoke(self):
self.start()
session = pexpect.spawn("telnet %s %s " % (self.ip_address,
self.getConfig()['service']['port']))
session.sendline('set Test 0 100 4\r\n\n')
session.sendline('JournalDev\r\n\n')
common.print_info('Expecting STORED')
session.expect('STORED')
common.print_info('STORED was catched')
session.close()
if __name__ == '__main__':
main()
Tento test se pomocí příkazu telnet připojí na danou ip_addressu a port. Port je specifikován v configuračním souboru pro MTF. O proměnné ip_address se zmíním v následující sekci.
Samotné testování kontejnerů
Nyní budeme testovat kontejner budťo lokálně nebo na vzdálené instanci. K testům slouží samotný příkaz mtf.
Testování kontejnerů lokálně či na vzdálené instanci se liší pouze parametry, jež předáme mtf příkazu.
Testy na lokální instanci OpenShiftu
$ sudo MODULE=openshift OPENSHIFT_LOCAL=yes mtf sanity1.py
V tomto případě se v sanity1.py použije self.ip_address adresa 127.0.0.1.
Testování na vzdálené instanci OpenShiftu
$ sudo OPENSHIFT_IP=OPENSHIFT_USER=developer OPENSHIFT_PASSWD=developer mtf sanity1.py
V tomto případě se v sanity1.py použije self.ip_address adresa OPENSHIFT_IP.
Vše ostatní zůstává stejné.
Testy se budou spouštět z prostředí, v našem případě z notebooku či PC a připojovat se budou na danou OpenShift instanci, kterou jsme specifikovali.
Výstup z testu
$ sudo MODULE=openshift OPENSHIFT_LOCAL=yes mtf sanity1.py JOB ID : c2b0877ca52a14c6c740582c76f60d4f19eb2d4d JOB LOG : /root/avocado/job-results/job-2017-12-18T12.32-c2b0877/job.log (1/1) sanity1.py:SanityCheck1.test_smoke: PASS (13.19 s) RESULTS : PASS 1 | ERROR 0 | FAIL 0 | SKIP 0 | WARN 0 | INTERRUPT 0 | CANCEL 0 JOB TIME : 13.74 s JOB HTML : /root/avocado/job-results/job-2017-12-18T12.32-c2b0877/results.html
Jestliže otevřeme log zvýrazněný tučně, můžeme vidět následující:
[...snip...]['/var/log/messages', '/var/log/syslog', '/var/log/system.log']) 2017-12-18 14:29:36,208 job L0321 INFO | Command line: /bin/avocado run --json /tmp/tmppfZpNe sanity1.py 2017-12-18 14:29:36,208 job L0322 INFO | 2017-12-18 14:29:36,208 job L0326 INFO | Avocado version: 55.0 2017-12-18 14:29:36,208 job L0342 INFO | 2017-12-18 14:29:36,208 job L0346 INFO | Config files read (in order): 2017-12-18 14:29:36,208 job L0348 INFO | /etc/avocado/avocado.conf 2017-12-18 14:29:36,208 job L0348 INFO | /etc/avocado/conf.d/gdb.conf 2017-12-18 14:29:36,208 job L0348 INFO | /root/.config/avocado/avocado.conf 2017-12-18 14:29:36,208 job L0353 INFO | 2017-12-18 14:29:36,208 job L0355 INFO | Avocado config: 2017-12-18 14:29:36,209 job L0364 INFO | Section.Key [...snip...] :::::::::::::::::::::::: SETUP :::::::::::::::::::::::: 2017-12-18 14:29:36,629 avocado_test L0069 DEBUG| :::::::::::::::::::::::: START MODULE ::::::::::::::::::::::::
MTF nejprve ověří, jestli aplikace skutečně neexistuje v OpenShift prostředí
2017-12-18 14:29:36,629 process L0389 INFO | Running 'oc get dc memcached -o json' 2017-12-18 14:29:36,842 process L0479 DEBUG| [stderr] Error from server (NotFound): deploymentconfigs.apps.openshift.io "memcached" not found 2017-12-18 14:29:36,846 process L0499 INFO | Command 'oc get dc memcached -o json' finished with 1 after 0.213222980499s Následně MTF ověří, jestli neexistuje žádný POD pod OpenShiftem. 2017-12-18 14:29:36,847 process L0389 INFO | Running 'oc get pods -o json' 2017-12-18 14:29:37,058 process L0479 DEBUG| [stdout] { 2017-12-18 14:29:37,059 process L0479 DEBUG| [stdout] "apiVersion": "v1", 2017-12-18 14:29:37,059 process L0479 DEBUG| [stdout] "items": [], 2017-12-18 14:29:37,059 process L0479 DEBUG| [stdout] "kind": "List", 2017-12-18 14:29:37,059 process L0479 DEBUG| [stdout] "metadata": {}, 2017-12-18 14:29:37,059 process L0479 DEBUG| [stdout] "resourceVersion": "", 2017-12-18 14:29:37,059 process L0479 DEBUG| [stdout] "selfLink": "" 2017-12-18 14:29:37,060 process L0479 DEBUG| [stdout] } 2017-12-18 14:29:37,064 process L0499 INFO | Command 'oc get pods -o json' finished with 0 after 0.211796045303s
V následujícím kroku vytvoříme aplikaci s labelem mtf_testing a jménem, který získáme z hodnoty poskytnuté v config.yaml souboru jako container.
2017-12-18 14:29:37,064 process L0389 INFO | Running 'oc new-app -l mtf_testing=true docker.io/modularitycontainers/memcached --name=memcached' 2017-12-18 14:29:39,022 process L0479 DEBUG| [stdout] --> Found Docker image bbc8bba (5 weeks old) from docker.io for "docker.io/modularitycontainers/memcached" 2017-12-18 14:29:39,022 process L0479 DEBUG| [stdout] 2017-12-18 14:29:39,022 process L0479 DEBUG| [stdout] memcached is a high-performance, distributed memory object caching system, generic in nature, but intended for use in speeding up dynamic web applications by alleviating database load. 2017-12-18 14:29:39,022 process L0479 DEBUG| [stdout] 2017-12-18 14:29:39,022 process L0479 DEBUG| [stdout] Tags: memcached 2017-12-18 14:29:39,023 process L0479 DEBUG| [stdout] 2017-12-18 14:29:39,023 process L0479 DEBUG| [stdout] * An image stream will be created as "memcached:latest" that will track this image 2017-12-18 14:29:39,023 process L0479 DEBUG| [stdout] * This image will be deployed in deployment config "memcached" 2017-12-18 14:29:39,023 process L0479 DEBUG| [stdout] * Port 11211/tcp will be load balanced by service "memcached" 2017-12-18 14:29:39,023 process L0479 DEBUG| [stdout] * Other containers can access this service through the hostname "memcached" 2017-12-18 14:29:39,023 process L0479 DEBUG| [stdout] 2017-12-18 14:29:39,023 process L0479 DEBUG| [stdout] --> Creating resources with label mtf_testing=true ... 2017-12-18 14:29:39,032 process L0479 DEBUG| [stdout] imagestream "memcached" created 2017-12-18 14:29:39,043 process L0479 DEBUG| [stdout] deploymentconfig "memcached" created 2017-12-18 14:29:39,063 process L0479 DEBUG| [stdout] service "memcached" created 2017-12-18 14:29:39,064 process L0479 DEBUG| [stdout] --> Success 2017-12-18 14:29:39,064 process L0479 DEBUG| [stdout] Run 'oc status' to view your app. 2017-12-18 14:29:39,069 process L0499 INFO | Command 'oc new-app -l mtf_testing=true docker.io/modularitycontainers/memcached --name=memcached' finished with 0 after 2.00025391579s
Následně ověříme jestli aplikace skutečně běží a na jaké IP adrese je dostupná.
2017-12-18 14:29:46,201 process L0389 INFO | Running 'oc get service -o json' 2017-12-18 14:29:46,416 process L0479 DEBUG| [stdout] { 2017-12-18 14:29:46,417 process L0479 DEBUG| [stdout] "apiVersion": "v1", 2017-12-18 14:29:46,417 process L0479 DEBUG| [stdout] "items": [ 2017-12-18 14:29:46,417 process L0479 DEBUG| [stdout] { 2017-12-18 14:29:46,417 process L0479 DEBUG| [stdout] "apiVersion": "v1", 2017-12-18 14:29:46,417 process L0479 DEBUG| [stdout] "kind": "Service", 2017-12-18 14:29:46,417 process L0479 DEBUG| [stdout] "metadata": { 2017-12-18 14:29:46,417 process L0479 DEBUG| [stdout] "annotations": { 2017-12-18 14:29:46,417 process L0479 DEBUG| [stdout] "openshift.io/generated-by": "OpenShiftNewApp" 2017-12-18 14:29:46,417 process L0479 DEBUG| [stdout] }, 2017-12-18 14:29:46,418 process L0479 DEBUG| [stdout] "creationTimestamp": "2017-12-18T13:29:39Z", 2017-12-18 14:29:46,418 process L0479 DEBUG| [stdout] "labels": { 2017-12-18 14:29:46,418 process L0479 DEBUG| [stdout] "app": "memcached", 2017-12-18 14:29:46,418 process L0479 DEBUG| [stdout] "mtf_testing": "true" 2017-12-18 14:29:46,418 process L0479 DEBUG| [stdout] }, 2017-12-18 14:29:46,418 process L0479 DEBUG| [stdout] "name": "memcached", 2017-12-18 14:29:46,418 process L0479 DEBUG| [stdout] "namespace": "myproject", 2017-12-18 14:29:46,418 process L0479 DEBUG| [stdout] "resourceVersion": "2121", 2017-12-18 14:29:46,419 process L0479 DEBUG| [stdout] "selfLink": "/api/v1/namespaces/myproject/services/memcached", 2017-12-18 14:29:46,419 process L0479 DEBUG| [stdout] "uid": "7f50823d-e3f7-11e7-be28-507b9d4150cb" 2017-12-18 14:29:46,419 process L0479 DEBUG| [stdout] }, 2017-12-18 14:29:46,419 process L0479 DEBUG| [stdout] "spec": { 2017-12-18 14:29:46,419 process L0479 DEBUG| [stdout] "clusterIP": "172.30.255.42", 2017-12-18 14:29:46,419 process L0479 DEBUG| [stdout] "ports": [ 2017-12-18 14:29:46,419 process L0479 DEBUG| [stdout] { 2017-12-18 14:29:46,419 process L0479 DEBUG| [stdout] "name": "11211-tcp", 2017-12-18 14:29:46,419 process L0479 DEBUG| [stdout] "port": 11211, 2017-12-18 14:29:46,420 process L0479 DEBUG| [stdout] "protocol": "TCP", 2017-12-18 14:29:46,420 process L0479 DEBUG| [stdout] "targetPort": 11211 2017-12-18 14:29:46,420 process L0499 INFO | Command 'oc get service -o json' finished with 0 after 0.213701963425s 2017-12-18 14:29:46,420 process L0479 DEBUG| [stdout] } 2017-12-18 14:29:46,420 process L0479 DEBUG| [stdout] ], 2017-12-18 14:29:46,420 process L0479 DEBUG| [stdout] "selector": { 2017-12-18 14:29:46,420 process L0479 DEBUG| [stdout] "app": "memcached", 2017-12-18 14:29:46,421 process L0479 DEBUG| [stdout] "deploymentconfig": "memcached", 2017-12-18 14:29:46,421 process L0479 DEBUG| [stdout] "mtf_testing": "true" 2017-12-18 14:29:46,421 process L0479 DEBUG| [stdout] }, 2017-12-18 14:29:46,421 process L0479 DEBUG| [stdout] "sessionAffinity": "None", 2017-12-18 14:29:46,421 process L0479 DEBUG| [stdout] "type": "ClusterIP" 2017-12-18 14:29:46,421 process L0479 DEBUG| [stdout] }, 2017-12-18 14:29:46,421 process L0479 DEBUG| [stdout] "status": { 2017-12-18 14:29:46,421 process L0479 DEBUG| [stdout] "loadBalancer": {} 2017-12-18 14:29:46,421 process L0479 DEBUG| [stdout] } 2017-12-18 14:29:46,422 process L0479 DEBUG| [stdout] } 2017-12-18 14:29:46,422 process L0479 DEBUG| [stdout] ], 2017-12-18 14:29:46,422 process L0479 DEBUG| [stdout] "kind": "List", 2017-12-18 14:29:46,422 process L0479 DEBUG| [stdout] "metadata": {}, 2017-12-18 14:29:46,422 process L0479 DEBUG| [stdout] "resourceVersion": "", 2017-12-18 14:29:46,422 process L0479 DEBUG| [stdout] "selfLink": "" 2017-12-18 14:29:46,422 process L0479 DEBUG| [stdout] }
V poslední fázi se spustí testy nad daným kontejnerem.
2017-12-18 14:29:46,530 output L0655 DEBUG| Expecting STORED 2017-12-18 14:29:46,531 output L0655 DEBUG| STORED was catched 2017-12-18 14:29:46,632 avocado_test L0069 DEBUG| :::::::::::::::::::::::: TEARDOWN :::::::::::::::::::::::: 2017-12-18 14:29:46,632 process L0389 INFO | Running 'oc get dc memcached -o json' 2017-12-18 14:29:46,841 process L0479 DEBUG| [stdout] { 2017-12-18 14:29:46,841 process L0479 DEBUG| [stdout] "apiVersion": "v1", 2017-12-18 14:29:46,841 process L0479 DEBUG| [stdout] "kind": "DeploymentConfig", 2017-12-18 14:29:46,841 process L0479 DEBUG| [stdout] "metadata": {
Na konci testů zkontrolujeme, jestli služba ještě neběží v OpenShiftu, toto můžeme ověřit příkazem oc status:
$ sudo oc status In project My Project (myproject) on server https://127.0.0.1:8443 You have no services, deployment configs, or build configs. Run 'oc new-app' to create an application.
Závěr
Jak z předešlého, tak i z tohoto článku, lze vidět, že psaní testů a testování samotných kontejnerů není vůbec složité a můžeme tedy zaručit, že kontejner je plně funkční.
Do budoucna bychom rádi rozšířili testování S2I kontejnerů a testování kontejnerů pomocí tzv. OpenShift template.
MTF dokumentace
MTF je relativně dobře dokumentovaná a snažíme se ji neustále vylepšovat. Online dokumentace je dostupná na readthedocs.io webpage.
Více informací lze nalézt zde [6].
Links
[1] https://mojefedora.cz/testovani-modulu-a-kontejneru-s-modularity-testing-frameworkem/
[2] https://admin.fedoraproject.org/pkgdb/package/rpms/meta-test-family/
[3] https://www.openshift.com/
[4] https://src.fedoraproject.org/projects/container/*
[5] https://github.com/fedora-modularity/meta-test-family
[6] http://meta-test-family.readthedocs.io/en/latest/
4. 2. 2018 at 14:30
Ahoj.
hekzy clanek. Jen male prudeni – mozna by ty linky mohly byt v textu jako stare dobre hyprlinky?
cili misto text [n]…[n]link pouzit „text“ 🙂 Ten clanek je dost douhy, a ty linky maji vyznam v ramci sveho kontextu. nez sem doskroloval dolu zapomel jsme na co byli….
Diky!