TL;DR: një artikull i përmbledhjes dhe udhëzimit për krahasimin e ambienteve për ekzekutimin e aplikacioneve në kontejnerë. Do të shqyrtohen mundësitë e Docker dhe sistemeve të tjera të ngjashme.

Pak histori, nga erdhi gjithçka
Historia
MĂ«nyra e parĂ« e njohur pĂ«r izolimin e aplikacionit Ă«shtĂ« chroot. Thirrja e sistemit me tĂ« njĂ«jtin emĂ«r siguron ndryshimin e katalogut rrĂ«njĂ«sor â kĂ«shtu duke i siguruar programit qĂ« e thirri akses vetĂ«m nĂ« skedarĂ«t brenda kĂ«tij katalogu. Por nĂ«se programit brenda i jepen tĂ« drejta superpĂ«rdoruesi, potencialisht ai mund tĂ« "dali" nga chroot dhe tĂ« ketĂ« qasje nĂ« sistemin operativ kryesor. Po ashtu, me ndĂ«rrimin e katalogut rrĂ«njĂ«sor nuk kufizohen burimet e tjera (memoria operative, procesori), si dhe qasja nĂ« rrjet.
MĂ«nyra tjetĂ«r Ă«shtĂ« ekzekutimi i njĂ« sistemi operativ tĂ« plotĂ« brenda kontejnerit, pĂ«rmes mekanizmave tĂ« bĂ«rthamĂ«s sĂ« sistemit operativ. NĂ« sisteme tĂ« ndryshme operative, kjo metodĂ« quhet ndryshe, por thelbi mbetet i njĂ«jtĂ« â ekzekutimi i disa sistemeve tĂ« pavarura operative, secila prej tĂ« cilave punon me tĂ« njĂ«jtin bĂ«rthame si ajo e sistemit operativ kryesor. KĂ«tu pĂ«rfshihen FreeBSD Jails, Solaris Zones, OpenVZ dhe LXC pĂ«r Linux. Sigurohet izolimi jo vetĂ«m nĂ« hapĂ«sirĂ«n e diskut, por edhe nĂ« burime tĂ« tjera, nĂ« veçanti çdo kontejner mund tĂ« ketĂ« kufizime nĂ« kohĂ«n e procesorit, memorjen operative, dhe gjerĂ«sinĂ« e rrjetit. NĂ« krahasim me chroot, dalja nga kontejneri Ă«shtĂ« mĂ« e vĂ«shtirĂ«, pasi superpĂ«rdoruesi nĂ« kontejner ka qasje vetĂ«m nĂ« pĂ«rbĂ«rĂ«sit e kontejnerit, megjithatĂ« pĂ«r shkak tĂ« nevojĂ«s pĂ«r tĂ« mbajtur sistemin operativ brenda kontejnerit nĂ« njĂ« gjendje tĂ« pĂ«rditĂ«suar dhe pĂ«rdorimin e versioneve tĂ« vjetra tĂ« bĂ«rthamave (e rĂ«ndĂ«sishme pĂ«r Linux, mĂ« pak pĂ«r FreeBSD) ekziston njĂ« probabilitet qĂ« nuk Ă«shtĂ« zero pĂ«r "thyerjen" e sistemit tĂ« izolimit tĂ« bĂ«rthamĂ«s dhe marrjen e aksesit nĂ« sistemin operativ kryesor.
Në vend të lançimit të një sistemi operativ të plotë në një kontejner (me sistemin e inicializimit, menaxherin e paketave etj.), është e mundur të iniciohen menjëherë aplikacione, gjëja kryesore është të sigurohet që aplikacionet të kenë këtë mundësi (prania e bibliotekave të nevojshme dhe skedarëve të tjerë). Kjo ide shërbeu si bazë për virtualizimin e aplikacioneve me kontejner, përfaqësuesi më i njohur dhe më i njohur i së cilës është Docker. Krahasuar me sistemet e mëparshme, mekanizmat më fleksibël të izolimit së bashku me mbështetje të ndërtuar për rrjete virtuale midis kontejnerëve dhe ndjekjen e gjendjes së aplikacionit brenda kontejnerit ofruan në fund mundësinë e ndërtimit të një mjedisi të vetëm të unifikuar nga një numër i madh serverësh fizikë për të drejtuar kontejnerët - pa nevojën për menaxhim manual të burimeve.
Docker
Docker është programi më i njohur për kontejnerizimin e aplikacioneve. I shkruar në gjuhën Go, përdor mundësitë standarde të bërthamës Linux - cgroups, namespaces, capabilities etj., si dhe sisteme të skedareve Aufs dhe të tjera të ngjashme për kursimin e hapësirës disk.

Burimi: wikimedia
Arkitektura
Para versionit 1.11, Docker funksiononte si një shërbim i vetëm, i cili kryente të gjitha operacionet me kontejnerët: shkarkimi i imazheve për kontejnerët, nisja e kontejnerëve, trajtimi i kërkesave përmes API. Duke filluar nga versioni 1.11, Docker u ndal në disa pjesë që bashkëveprojnë mes tyre: containerd, për të trajtuar gjithë ciklin e jetës së kontejnerëve (ndarjen e hapësirës disk, shkarkimin e imazheve, punën me rrjetin, nisjen, instalimin dhe mb monitoringun e gjendjes së kontejnerëve) dhe runC, mjedisi i ekzekutimit të kontejnerëve, i bazuar në përdorimin e cgroups dhe mundësive të tjera të bërthamës Linux. Shërbimi i vetë docker mbeti, por tani shërben vetëm për trajtimin e kërkesave përmes API, të cilat përkthehen në containerd.

Instalimi dhe konfigurimi
Mënyra ime e preferuar për të instaluar docker është docker-machine, e cila përveç instalimit dhe konfigurimit të docker në servera të largët (përfshirë nube të ndryshme) ofron mundësinë e punës me sistemet e skedareve të serverëve të largët, si dhe mund të kryejë ekzekutimin e komandave të ndryshme.
Megjithatë, që nga viti 2018 projekti ka almost ndaluar zhvillimin, prandaj instalimin do ta kryejmë në mënyrën standarde për shumicën e shpërndarjeve Linux - duke shtuar repository dhe duke instaluar paketat e nevojshme.
Ky ky po, kjo metode aplikohet gjithashtu kur bëhet instalimi automatizuar, për shembull me ndihmën e Ansible ose sistemeve të ngjashme, por në këtë artikull nuk do ta diskutoj.
Instalimi do të bëhet në CentOS 7, për server do të përdor një makinë virtuale, për instalimin mjafton të kryej komandat më poshtë:
# yum install -y yum-utils
# yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# yum install docker-ce docker-ce-cli containerd.ioPas instalimit, duhet të aktivizoni shërbimin, ta vendosni në ngarkesë automatikisht:
# systemctl enable docker
# systemctl start docker
# firewall-cmd --zone=public --add-port=2377/tcp --permanentShtesë mund të krijoni një grup docker, ku përdoruesit do të mund të punojnë me docker pa sudo, të konfiguroni regjistrimin, të aktivizoni qasjen në API nga jashtë, pa harruar të konfiguroni më saktë firewall-in (ndalohet gjithçka që nuk është e lejuar, në shembujt më sipër dhe më poshtë kam lënë këtë për thjeshtësi dhe qartësi), por këtu nuk do të ndalem më në detaje.
Mundësi të tjera
PĂ«rveç docker machine tĂ« pĂ«rmendur, ekziston gjithashtu docker registry, njĂ« mjet pĂ«r ruajtjen e imazheve pĂ«r kontejnerĂ«t, si dhe docker compose â njĂ« mjet pĂ«r automatizimin e shpĂ«rndarjes sĂ« aplikacioneve nĂ« konteinerĂ«, pĂ«rdoren skedarĂ«t YAML pĂ«r ndĂ«rtimin dhe konfigurimin e kontejnerĂ«ve dhe gjĂ«rave tĂ« tjera tĂ« lidhura (pĂ«r shembull rrjetet, sistemet e skedarĂ«ve tĂ« pĂ«rhershĂ«m pĂ«r ruajtjen e tĂ« dhĂ«nave).
Po ashtu, me ndihmën e tij mund të organizoni pipeline për CICD. Një mundësi tjetër interesante është puna në modin klaster, i njohur si swarm mode (deri në versionin 1.12 ishte i njohur si docker swarm), që lejon grumbullimin e disa serverëve në një infrastrukturë unike për ekzekutimin e kontejnerëve. Ka mbështetje për rrjetin virtual për të gjithë serverët, ekziston një balancues ngarkese i integruar dhe po ashtu mbështetje për sekrete për kontejnerët.
Skedarët YAML nga docker compose me disa ndryshime mund të përdoren për këto klasterë, duke automatizuar plotësisht mirëmbajtjen e klasterëve të vogla dhe të mesëm për qëllime të ndryshme. Për klasterët më të mëdhenj, preferohet përdorimi i Kubernetes, pasi kostot e mirëmbajtjes së swarm mode mund të kalojnë ato të Kubernetes. Përveç runC si mjedis ekzekutimi për kontejnerët, mund të instalohet, për shembull,
Puna me Docker
Pas instalimit dhe konfigurimit, do të përpiqemi të ndërtojmë një kluster, në të cilin do të vendosim GitLab dhe Docker Registry për ekipin e zhvilluesve. Si servera do të përdor tre makina virtuale, në të cilat gjithashtu do të vendos një sistem të shpërndarë dosjesh GlusterFS, të cilin do ta përdor si ruajtje për volumin e docker-it, për shembull për të nisur një version të qëndrueshëm të docker registry. Komponentët kyç për nisjen: Docker Registry, Postgresql, Redis, GitLab me mbështetje për GitLab Runner mbi Swarm. Postgresql do ta nisë me klasterizim. , prandaj për ruajtjen e të dhënave të Postgresql nuk duhet të përdorim GlusterFS. Të gjitha të dhënat e tjera kritike do të ruhen në GlusterFS.
Për vendosjen e GlusterFS në të gjitha serverat (të cilët quhen node1, node2, node3), duhet të instaloni paketat, të lejoni punën e firewal-it, të krijoni katalogët e nevojshëm:
# yum -y install centos-release-gluster7
# yum -y install glusterfs-server
# systemctl enable glusterd
# systemctl start glusterd
# firewall-cmd --add-service=glusterfs --permanent
# firewall-cmd --reload
# mkdir -p /srv/gluster
# mkdir -p /srv/docker
# echo "$(hostname):/docker /srv/docker glusterfs defaults,_netdev 0 0" >> /etc/fstabPas instalimit, puna për konfigurimin e GlusterFS duhet të vazhdojë nga një nod, për shembull node1:
# gluster peer probe node2
# gluster peer probe node3
# gluster volume create docker replica 3 node1:/srv/gluster node2:/srv/gluster node3:/srv/gluster force
# gluster volume start dockerPastaj duhet të montoni volumin e fituar (komandën duhet ta ekzekutoni në të gjithë serverat):
# mount /srv/dockerKonfigurimi i modalitetit swarm bëhet në një nga serverat, i cili do të jetë Lider, të tjerët do të duhet të bashkohen me klasterin, prandaj rezultatin e ekzekutimit të komandës në serverin e parë duhet ta kopjoni dhe ta ekzekutoni në të tjerët.
Konfigurimi fillestar i klasterit, komandën e nis në node1:
# docker swarm init
Swarm initialized: current node (a5jpfrh5uvo7svzz1ajduokyq) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-0c5mf7mvzc7o7vjk0wngno2dy70xs95tovfxbv4tqt9280toku-863hyosdlzvd76trfptd4xnzd xx.xx.xx.xx:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
# docker swarm join-token managerKopjojmë rezultatin e komandës së dytë, e ekzekutojmë në node2 dhe node3:
# docker swarm join --token SWMTKN-x-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-xxxxxxxxx xx.xx.xx.xx:2377
This node joined a swarm as a manager.Në këtë pikë, konfigurimi paraprak i serverave ka përfunduar, kalojmë në konfigurimin e shërbimeve, komandat për ekzekutim do të përfundojnë nga node1, përveç nëse tregohet ndryshe.
Së pari, do të krijojmë rrjetet për kontejnerët:
# docker network create --driver=overlay etcd
# docker network create --driver=overlay pgsql
# docker network create --driver=overlay redis
# docker network create --driver=overlay traefik
# docker network create --driver=overlay gitlabPastaj etiketojmë serverat, kjo është e nevojshme për lidhjen e disa shërbimeve me serverat:
# docker node update --label-add nodename=node1 node1
# docker node update --label-add nodename=node2 node2
# docker node update --label-add nodename=node3 node3Më pas krijojmë katalogë për ruajtjen e të dhënave etcd, një ruajtje KV që është e nevojshme për Traefik dhe Stolon. Njëlloj si Postgresql, këto do të jenë konteinerë të lidhur me serverat, prandaj këtë komandë e ekzekutojmë në të gjithë serverat:
# mkdir -p /srv/etcdMë pas krijojmë një skedë për konfigurimin e etcd dhe e aplikojmë atë:
00etcd.yml
version: '3.7'
services:
etcd1:
image: quay.io/coreos/etcd:latest
hostname: etcd1
command:
- etcd
- --name=etcd1
- --data-dir=/data.etcd
- --advertise-client-urls=http://etcd1:2379
- --listen-client-urls=http://0.0.0.0:2379
- --initial-advertise-peer-urls=http://etcd1:2380
- --listen-peer-urls=http://0.0.0.0:2380
- --initial-cluster=etcd1=http://etcd1:2380,etcd2=http://etcd2:2380,etcd3=http://etcd3:2380
- --initial-cluster-state=new
- --initial-cluster-token=etcd-cluster
networks:
- etcd
volumes:
- etcd1vol:/data.etcd
deploy:
replicas: 1
placement:
constraints: [node.labels.nodename == node1]
etcd2:
image: quay.io/coreos/etcd:latest
hostname: etcd2
command:
- etcd
- --name=etcd2
- --data-dir=/data.etcd
- --advertise-client-urls=http://etcd2:2379
- --listen-client-urls=http://0.0.0.0:2379
- --initial-advertise-peer-urls=http://etcd2:2380
- --listen-peer-urls=http://0.0.0.0:2380
- --initial-cluster=etcd1=http://etcd1:2380,etcd2=http://etcd2:2380,etcd3=http://etcd3:2380
- --initial-cluster-state=new
- --initial-cluster-token=etcd-cluster
networks:
- etcd
volumes:
- etcd2vol:/data.etcd
deploy:
replicas: 1
placement:
constraints: [node.labels.nodename == node2]
etcd3:
image: quay.io/coreos/etcd:latest
hostname: etcd3
command:
- etcd
- --name=etcd3
- --data-dir=/data.etcd
- --advertise-client-urls=http://etcd3:2379
- --listen-client-urls=http://0.0.0.0:2379
- --initial-advertise-peer-urls=http://etcd3:2380
- --listen-peer-urls=http://0.0.0.0:2380
- --initial-cluster=etcd1=http://etcd1:2380,etcd2=http://etcd2:2380,etcd3=http://etcd3:2380
- --initial-cluster-state=new
- --initial-cluster-token=etcd-cluster
networks:
- etcd
volumes:
- etcd3vol:/data.etcd
deploy:
replicas: 1
placement:
constraints: [node.labels.nodename == node3]
volumes:
etcd1vol:
driver: local
driver_opts:
type: none
o: bind
device: "/srv/etcd"
etcd2vol:
driver: local
driver_opts:
type: none
o: bind
device: "/srv/etcd"
etcd3vol:
driver: local
driver_opts:
type: none
o: bind
device: "/srv/etcd"
networks:
etcd:
external: true# docker stack deploy --compose-file 00etcd.yml etcdPas një kohë, kontrollojmë që klasteri etcd është ngritur:
# docker exec $(docker ps | awk '/etcd/ {print $1}') etcdctl member list
ade526d28b1f92f7: name=etcd1 peerURLs=http://etcd1:2380 clientURLs=http://etcd1:2379 isLeader=false
bd388e7810915853: name=etcd3 peerURLs=http://etcd3:2380 clientURLs=http://etcd3:2379 isLeader=false
d282ac2ce600c1ce: name=etcd2 peerURLs=http://etcd2:2380 clientURLs=http://etcd2:2379 isLeader=true
# docker exec $(docker ps | awk '/etcd/ {print $1}') etcdctl cluster-health
member ade526d28b1f92f7 is healthy: got healthy result from http://etcd1:2379
member bd388e7810915853 is healthy: got healthy result from http://etcd3:2379
member d282ac2ce600c1ce is healthy: got healthy result from http://etcd2:2379
cluster is healthyKrijojmë kataloge për Postgresql, komandën e ekzekutojmë në të gjitha serverat:
# mkdir -p /srv/pgsqlMë pas krijojmë një skedar për konfigurimin e Postgresql:
01pgsql.yml
version: '3.7'
shërbimet:
pgsentinel:
imazh: sorintlab/stolon:master-pg10
komandë:
- gosu
- stolon
- stolon-sentinel
- --cluster-name=stolon-cluster
- --store-backend=etcdv3
- --store-endpoints=http://etcd1:2379,http://etcd2:2379,http://etcd3:2379
- --log-level=debug
rrjetet:
- etcd
- pgsql
shpërndarje:
replika: 3
update_config:
parallelizmi: 1
vonesë: 30s
renditja: stop-first
veprimi në rast dështimi: pause
pgkeeper1:
imazh: sorintlab/stolon:master-pg10
hostname: pgkeeper1
komandë:
- gosu
- stolon
- stolon-keeper
- --pg-listen-address=pgkeeper1
- --pg-repl-username=replica
- --uid=pgkeeper1
- --pg-su-username=postgres
- --pg-su-passwordfile=/run/secrets/pgsql
- --pg-repl-passwordfile=/run/secrets/pgsql_repl
- --data-dir=/var/lib/postgresql/data
- --cluster-name=stolon-cluster
- --store-backend=etcdv3
- --store-endpoints=http://etcd1:2379,http://etcd2:2379,http://etcd3:2379
rrjetet:
- etcd
- pgsql
ambient:
- PGDATA=/var/lib/postgresql/data
volumat:
- pgkeeper1:/var/lib/postgresql/data
sekrete:
- pgsql
- pgsql_repl
shpërndarje:
replika: 1
vendosje:
kufizime: [node.labels.nodename == node1]
pgkeeper2:
imazh: sorintlab/stolon:master-pg10
hostname: pgkeeper2
komandë:
- gosu
- stolon
- stolon-keeper
- --pg-listen-address=pgkeeper2
- --pg-repl-username=replica
- --uid=pgkeeper2
- --pg-su-username=postgres
- --pg-su-passwordfile=/run/secrets/pgsql
- --pg-repl-passwordfile=/run/secrets/pgsql_repl
- --data-dir=/var/lib/postgresql/data
- --cluster-name=stolon-cluster
- --store-backend=etcdv3
- --store-endpoints=http://etcd1:2379,http://etcd2:2379,http://etcd3:2379
rrjetet:
- etcd
- pgsql
ambient:
- PGDATA=/var/lib/postgresql/data
volumat:
- pgkeeper2:/var/lib/postgresql/data
sekrete:
- pgsql
- pgsql_repl
shpërndarje:
replika: 1
vendosje:
kufizime: [node.labels.nodename == node2]
pgkeeper3:
imazh: sorintlab/stolon:master-pg10
hostname: pgkeeper3
komandë:
- gosu
- stolon
- stolon-keeper
- --pg-listen-address=pgkeeper3
- --pg-repl-username=replica
- --uid=pgkeeper3
- --pg-su-username=postgres
- --pg-su-passwordfile=/run/secrets/pgsql
- --pg-repl-passwordfile=/run/secrets/pgsql_repl
- --data-dir=/var/lib/postgresql/data
- --cluster-name=stolon-cluster
- --store-backend=etcdv3
- --store-endpoints=http://etcd1:2379,http://etcd2:2379,http://etcd3:2379
rrjetet:
- etcd
- pgsql
ambient:
- PGDATA=/var/lib/postgresql/data
volumat:
- pgkeeper3:/var/lib/postgresql/data
sekrete:
- pgsql
- pgsql_repl
shpërndarje:
replika: 1
vendosje:
kufizime: [node.labels.nodename == node3]
postgresql:
imazh: sorintlab/stolon:master-pg10
komandë: gosu stolon stolon-proxy --listen-address 0.0.0.0 --cluster-name stolon-cluster --store-backend=etcdv3 --store-endpoints http://etcd1:2379,http://etcd2:2379,http://etcd3:2379
rrjetet:
- etcd
- pgsql
shpërndarje:
replika: 3
update_config:
parallelizmi: 1
vonesë: 30s
renditja: stop-first
veprimi në rast dështimi: rollback
volumat:
pgkeeper1:
drejtues: lokal
opsionet_e_drejtuesit:
lloji: asnjë
o: lidhje
pajisja: "/srv/pgsql"
pgkeeper2:
drejtues: lokal
opsionet_e_drejtuesit:
lloji: asnjë
o: lidhje
pajisja: "/srv/pgsql"
pgkeeper3:
drejtues: lokal
opsionet_e_drejtuesit:
lloji: asnjë
o: lidhje
pajisja: "/srv/pgsql"
sekrete:
pgsql:
skedar: "/srv/docker/postgres"
pgsql_repl:
skedar: "/srv/docker/replica"
rrjetet:
etcd:
jashtë: e vërtetë
pgsql:
jashtë: e vërtetëKrijojmë sekrete, përdorim skedarin:
# </dev/urandom tr -dc 234567890qwertyuopasdfghjkzxcvbnmQWERTYUPASDFGHKLZXCVBNM | head -c $(((RANDOM%3)+15)) > /srv/docker/replica
# </dev/urandom tr -dc 234567890qwertyuopasdfghjkzxcvbnmQWERTYUPASDFGHKLZXCVBNM | head -c $(((RANDOM%3)+15)) > /srv/docker/postgres
# docker stack deploy --compose-file 01pgsql.yml pgsqlPas një kohe (shikojmë rezultatin e komandës docker service ls, që ngjiten të gjitha shërbimet) fillojmë klasterin Postgresql:
# docker exec $(docker ps | awk '/pgkeeper/ {print $1}') stolonctl --cluster-name=stolon-cluster --store-backend=etcdv3 --store-endpoints=http://etcd1:2379,http://etcd2:2379,http://etcd3:2379 initKontrollojmë gatishmërinë e klasterit Postgresql:
# docker exec $(docker ps | awk '/pgkeeper/ {print $1}') stolonctl --cluster-name=stolon-cluster --store-backend=etcdv3 --store-endpoints=http://etcd1:2379,http://etcd2:2379,http://etcd3:2379 status
=== Active sentinels ===
ID LEADER
26baa11d false
74e98768 false
a8cb002b true
=== Active proxies ===
ID
4d233826
9f562f3b
b0c79ff1
=== Keepers ===
UID HEALTHY PG LISTENADDRESS PG HEALTHY PG WANTEDGENERATION PG CURRENTGENERATION
pgkeeper1 true pgkeeper1:5432 true 2 2
pgkeeper2 true pgkeeper2:5432 true 2 2
pgkeeper3 true pgkeeper3:5432 true 3 3
=== Cluster Info ===
Master Keeper: pgkeeper3
===== Keepers/DB tree =====
pgkeeper3 (master)
ââpgkeeper2
ââpgkeeper1
Konfigurojmë traefik për të hapur aksesin në kontejnerët nga jashtë:
03traefik.yml
version: '3.7'
services:
traefik:
image: traefik:latest
command: >
--log.level=INFO
--providers.docker=true
--entryPoints.web.address=:80
--providers.providersThrottleDuration=2
--providers.docker.watch=true
--providers.docker.swarmMode=true
--providers.docker.swarmModeRefreshSeconds=15s
--providers.docker.exposedbydefault=false
--accessLog.bufferingSize=0
--api=true
--api.dashboard=true
--api.insecure=true
networks:
- traefik
ports:
- 80:80
volumes:
- /var/run/docker.sock:/var/run/docker.sock
deploy:
replicas: 3
placement:
constraints:
- node.role == manager
preferences:
- spread: node.id
labels:
- traefik.enable=true
- traefik.http.routers.traefik.rule=Host(`traefik.example.com`)
- traefik.http.services.traefik.loadbalancer.server.port=8080
- traefik.docker.network=traefik
networks:
traefik:
external: true# docker stack deploy --compose-file 03traefik.yml traefikNisni Klasterin Redis, për këtë krijoni në të gjitha nyjat një katalog për ruajtje:
# mkdir -p /srv/redis05redis.yml
version: '3.7'
services:
redis-master:
image: 'bitnami/redis:latest'
networks:
- redis
ports:
- '6379:6379'
environment:
- REDIS_REPLICATION_MODE=master
- REDIS_PASSWORD=xxxxxxxxxxx
deploy:
mode: global
restart_policy:
condition: any
volumes:
- 'redis:/opt/bitnami/redis/etc/'
redis-replica:
image: 'bitnami/redis:latest'
networks:
- redis
ports:
- '6379'
depends_on:
- redis-master
environment:
- REDIS_REPLICATION_MODE=slave
- REDIS_MASTER_HOST=redis-master
- REDIS_MASTER_PORT_NUMBER=6379
- REDIS_MASTER_PASSWORD=xxxxxxxxxxx
- REDIS_PASSWORD=xxxxxxxxxxx
deploy:
mode: replicated
replicas: 3
update_config:
parallelism: 1
delay: 10s
restart_policy:
condition: any
redis-sentinel:
image: 'bitnami/redis:latest'
networks:
- redis
ports:
- '16379'
depends_on:
- redis-master
- redis-replica
entrypoint: |
bash -c 'bash -s <<EOF
"/bin/bash" -c "cat < /opt/bitnami/redis/etc/sentinel.conf
port 16379
dir /tmp
sentinel monitor master-node redis-master 6379 2
sentinel down-after-milliseconds master-node 5000
sentinel parallel-syncs master-node 1
sentinel failover-timeout master-node 5000
sentinel auth-pass master-node xxxxxxxxxxx
sentinel announce-ip redis-sentinel
sentinel announce-port 16379
EOF"
"/bin/bash" -c "redis-sentinel /opt/bitnami/redis/etc/sentinel.conf"
EOF'
deploy:
mode: global
restart_policy:
condition: any
volumes:
redis:
driver: local
driver_opts:
type: 'none'
o: 'bind'
device: "/srv/redis"
networks:
redis:
external: true# docker stack deploy --compose-file 05redis.yml redisShtojmë Docker Registry:
06registry.yml
version: '3.7'
services:
registry:
image: registry:2.6
networks:
- traefik
volumes:
- registry_data:/var/lib/registry
deploy:
replicas: 1
placement:
constraints: [node.role == manager]
restart_policy:
condition: on-failure
labels:
- traefik.enable=true
- traefik.http.routers.registry.rule=Host(`registry.example.com`)
- traefik.http.services.registry.loadbalancer.server.port=5000
- traefik.docker.network=traefik
volumes:
registry_data:
driver: local
driver_opts:
type: none
o: bind
device: "/srv/docker/registry"
networks:
traefik:
external: true# mkdir /srv/docker/registry
# docker stack deploy --compose-file 06registry.yml registryDhe dhe final â GitLab:
08gitlab-runner.yml
version: '3.7'
services:
gitlab:
image: gitlab/gitlab-ce:latest
networks:
- pgsql
- redis
- traefik
- gitlab
ports:
- 22222:22
environment:
GITLAB_OMNIBUS_CONFIG: |
postgresql['enable'] = false
redis['enable'] = false
gitlab_rails['registry_enabled'] = false
gitlab_rails['db_username'] = "gitlab"
gitlab_rails['db_password'] = "XXXXXXXXXXX"
gitlab_rails['db_host'] = "postgresql"
gitlab_rails['db_port'] = "5432"
gitlab_rails['db_database'] = "gitlab"
gitlab_rails['db_adapter'] = 'postgresql'
gitlab_rails['db_encoding'] = 'utf8'
gitlab_rails['redis_host'] = 'redis-master'
gitlab_rails['redis_port'] = '6379'
gitlab_rails['redis_password'] = 'xxxxxxxxxxx'
gitlab_rails['smtp_enable'] = true
gitlab_rails['smtp_address'] = "smtp.yandex.ru"
gitlab_rails['smtp_port'] = 465
gitlab_rails['smtp_user_name'] = "noreply@example.com"
gitlab_rails['smtp_password'] = "xxxxxxxxx"
gitlab_rails['smtp_domain'] = "example.com"
gitlab_rails['gitlab_email_from'] = 'noreply@example.com'
gitlab_rails['smtp_authentication'] = "login"
gitlab_rails['smtp_tls'] = true
gitlab_rails['smtp_enable_starttls_auto'] = true
gitlab_rails['smtp_openssl_verify_mode'] = 'peer'
external_url 'http://gitlab.example.com/'
gitlab_rails['gitlab_shell_ssh_port'] = 22222
volumes:
- gitlab_conf:/etc/gitlab
- gitlab_logs:/var/log/gitlab
- gitlab_data:/var/opt/gitlab
deploy:
mode: replicated
replicas: 1
placement:
constraints:
- node.role == manager
labels:
- traefik.enable=true
- traefik.http.routers.gitlab.rule=Host(`gitlab.example.com`)
- traefik.http.services.gitlab.loadbalancer.server.port=80
- traefik.docker.network=traefik
gitlab-runner:
image: gitlab/gitlab-runner:latest
networks:
- gitlab
volumes:
- gitlab_runner_conf:/etc/gitlab
- /var/run/docker.sock:/var/run/docker.sock
deploy:
mode: replicated
replicas: 1
placement:
constraints:
- node.role == manager
volumes:
gitlab_conf:
driver: local
driver_opts:
type: none
o: bind
device: "/srv/docker/gitlab/conf"
gitlab_logs:
driver: local
driver_opts:
type: none
o: bind
device: "/srv/docker/gitlab/logs"
gitlab_data:
driver: local
driver_opts:
type: none
o: bind
device: "/srv/docker/gitlab/data"
gitlab_runner_conf:
driver: local
driver_opts:
type: none
o: bind
device: "/srv/docker/gitlab/runner"
networks:
pgsql:
external: true
redis:
external: true
traefik:
external: true
gitlab:
external: true# mkdir -p /srv/docker/gitlab/conf
# mkdir -p /srv/docker/gitlab/logs
# mkdir -p /srv/docker/gitlab/data
# mkdir -p /srv/docker/gitlab/runner
# docker stack deploy --compose-file 08gitlab-runner.yml gitlabGjendja përfundimtare e klasterit dhe shërbimeve:
# docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
lef9n3m92buq etcd_etcd1 replicated 1/1 quay.io/coreos/etcd:latest
ij6uyyo792x5 etcd_etcd2 replicated 1/1 quay.io/coreos/etcd:latest
fqttqpjgp6pp etcd_etcd3 replicated 1/1 quay.io/coreos/etcd:latest
hq5iyga28w33 gitlab_gitlab replicated 1/1 gitlab/gitlab-ce:latest *:22222->22/tcp
dt7s6vs0q4qc gitlab_gitlab-runner replicated 1/1 gitlab/gitlab-runner:latest
k7uoezno0h9n pgsql_pgkeeper1 replicated 1/1 sorintlab/stolon:master-pg10
cnrwul4r4nse pgsql_pgkeeper2 replicated 1/1 sorintlab/stolon:master-pg10
frflfnpty7tr pgsql_pgkeeper3 replicated 1/1 sorintlab/stolon:master-pg10
x7pqqchi52kq pgsql_pgsentinel replicated 3/3 sorintlab/stolon:master-pg10
mwu2wl8fti4r pgsql_postgresql replicated 3/3 sorintlab/stolon:master-pg10
9hkbe2vksbzb redis_redis-master global 3/3 bitnami/redis:latest *:6379->6379/tcp
l88zn8cla7dc redis_redis-replica replicated 3/3 bitnami/redis:latest *:30003->6379/tcp
1utp309xfmsy redis_redis-sentinel global 3/3 bitnami/redis:latest *:30002->16379/tcp
oteb824ylhyp registry_registry replicated 1/1 registry:2.6
qovrah8nzzu8 traefik_traefik replicated 3/3 traefik:latest *:80->80/tcp, *:443->443/tcpĂfarĂ« mund tĂ« pĂ«rmirĂ«sohet akoma? Sigurohuni tĂ« konfiguroni Traefik pĂ«r tĂ« punuar me kontejnerĂ«t pĂ«rmes https, shtoni enkriptimin tls pĂ«r Postgresql dhe Redis. Por nĂ« pĂ«rgjithĂ«si, mund t'ua dorĂ«zojmĂ« tashmĂ« zhvilluesve si PoC. Tani do tĂ« shqyrtojmĂ« alternativat ndaj Docker.
Podman
Një motor tjetër mjaft i njohur për të lançuar kontejnerë, të grupuar në Pod-e (pods, grupe kontejnerësh të vendosur së bashku). Në dallim nga Docker, nuk kërkon asnjë shërbim për të lançuar kontejnerët; e gjithë puna bëhet përmes bibliotekës libpod. Po ashtu është shkruar në Go, dhe kërkon një runtime të përputhshëm me OCI për të lançuar kontejnerët, për shembull runC.

Puna me Podman në përgjithësi i ngjan asaj për Docker, deri në pikën që dikush mund ta bëjë këtë (sipërmarrë nga shumë që e kanë provuar, përfshirë autorin e këtij artikulli):
$ alias docker=podmandhe mund tĂ« vazhdojme tĂ« punojmĂ«. NĂ« pĂ«rgjithĂ«si, situata me Podman Ă«shtĂ« mjaft interesante, sepse nĂ«se versionet e hershme tĂ« Kubernetes punonin me Docker, qĂ« nga rreth vitit 2015, pas standardizimit tĂ« botĂ«s sĂ« kontejnerĂ«ve (OCI â Open Container Initiative) dhe ndarjen e Docker nĂ« containerd dhe runC, Ă«shtĂ« zhvilluar njĂ« alternativĂ« e Docker pĂ«r tĂ« ankoruar nĂ« Kubernetes: CRI-O. Podman nĂ« kĂ«tĂ« pĂ«rputhje Ă«shtĂ« njĂ« alternativĂ« e Docker, e ndĂ«rtuar sipas parimeve tĂ« Kubernetes, pĂ«rfshirĂ« dhe grupimin e kontejnerĂ«ve, por qĂ«llimi kryesor i ekzistencĂ«s sĂ« projektit Ă«shtĂ« lançimi i kontejnerĂ«ve nĂ« stilin Docker pa shĂ«rbime shtesĂ«. PĂ«r arsye tĂ« qarta, nuk ka modalitetin swarm, pasi zhvilluesit thjesht thonĂ« se nĂ«se keni nevojĂ« pĂ«r klaster â merrni Kubernetes.
Instalimi
Për të instaluar në Centos 7 mjafton të aktivizoni repository-n Extras, pas së cilës mund ta instaloni me komandën:
# yum -y install podmanMundësi të tjera
Podman mund tĂ« gjenerojĂ« njĂ«sitĂ« pĂ«r systemd, duke zgjidhur kĂ«shtu problemin e lançimit tĂ« kontejnerĂ«ve pas rinisjes sĂ« serverit. Gjithashtu, Ă«shtĂ« deklaruar funksionimi korrekt i systemd si pid 1 nĂ« kontejner. PĂ«r ndĂ«rtimin e kontejnerĂ«ve ka njĂ« mjet tĂ« veçantĂ« buildah, ka gjithashtu mjete tĂ« tjera tĂ« jashtme â ekuivalente me docker-compose, qĂ« gjithashtu gjenerojnĂ« skedarĂ« konfigurimi tĂ« pĂ«rputhshĂ«m me Kubernetes, kĂ«shtu qĂ« kalimi nga Podman nĂ« Kubernetes sa Ă«shtĂ« e mundur, Ă«shtĂ« e thjeshtĂ«.
Puna me Podman
Pasi nuk ka modalitetin swarm (parashikohet kalimi nĂ« Kubernetes, nĂ«se nevojitet klaster) â do tĂ« grumbullojmĂ« me kontejnerĂ« tĂ« ndarĂ«.
Instalojmë podman-compose:
# yum -y install python3-pip
# pip3 install podman-composeSkedari rezultues i konfigurimit për podman paksa ndryshon, kështu që për shembull, na duhej të transferonim një seksion të veçantë volumes direkt në seksionin me shërbimet.
gitlab-podman.yml
version: '3.7'
services:
gitlab:
image: gitlab/gitlab-ce:latest
hostname: gitlab.example.com
restart: unless-stopped
environment:
GITLAB_OMNIBUS_CONFIG: |
gitlab_rails['gitlab_shell_ssh_port'] = 22222
ports:
- "80:80"
- "22222:22"
volumes:
- /srv/podman/gitlab/conf:/etc/gitlab
- /srv/podman/gitlab/data:/var/opt/gitlab
- /srv/podman/gitlab/logs:/var/log/gitlab
networks:
- gitlab
gitlab-runner:
image: gitlab/gitlab-runner:alpine
restart: unless-stopped
depends_on:
- gitlab
volumes:
- /srv/podman/gitlab/runner:/etc/gitlab-runner
- /var/run/docker.sock:/var/run/docker.sock
networks:
- gitlab
networks:
gitlab:# podman-compose -f gitlab-runner.yml -d upRezultati i punës:
# podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
da53da946c01 docker.io/gitlab/gitlab-runner:alpine run --user=gitlab... About a minute ago Up About a minute ago 0.0.0.0:22222->22/tcp, 0.0.0.0:80->80/tcp root_gitlab-runner_1
781c0103c94a docker.io/gitlab/gitlab-ce:latest /assets/wrapper About a minute ago Up About a minute ago 0.0.0.0:22222->22/tcp, 0.0.0.0:80->80/tcp root_gitlab_1Le të shohim se çfarë do të generohet për systemd dhe kubernetes, për këtë duhet të dimë emrin ose ID-në e pod-it:
# podman pod ls
POD ID NAME STATUS CREATED # OF CONTAINERS INFRA ID
71fc2b2a5c63 root Running 11 minutes ago 3 db40ab8bf84bKubernetes:
# podman generate kube 71fc2b2a5c63
# Generation of Kubernetes YAML is still under development!
#
# Save the output of this file and use kubectl create -f to import
# it into Kubernetes.
#
# Created with podman-1.6.4
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: "2020-07-29T19:22:40Z"
labels:
app: root
name: root
spec:
containers:
- command:
- /assets/wrapper
env:
- name: PATH
value: /opt/gitlab/embedded/bin:/opt/gitlab/bin:/assets:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
- name: TERM
value: xterm
- name: HOSTNAME
value: gitlab.example.com
- name: container
value: podman
- name: GITLAB_OMNIBUS_CONFIG
value: |
gitlab_rails['gitlab_shell_ssh_port'] = 22222
- name: LANG
value: C.UTF-8
image: docker.io/gitlab/gitlab-ce:latest
name: rootgitlab1
ports:
- containerPort: 22
hostPort: 22222
protocol: TCP
- containerPort: 80
hostPort: 80
protocol: TCP
resources: {}
securityContext:
allowPrivilegeEscalation: true
capabilities: {}
privileged: false
readOnlyRootFilesystem: false
volumeMounts:
- mountPath: /var/opt/gitlab
name: srv-podman-gitlab-data
- mountPath: /var/log/gitlab
name: srv-podman-gitlab-logs
- mountPath: /etc/gitlab
name: srv-podman-gitlab-conf
workingDir: /
- command:
- run
- --user=gitlab-runner
- --working-directory=/home/gitlab-runner
env:
- name: PATH
value: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
- name: TERM
value: xterm
- name: HOSTNAME
- name: container
value: podman
image: docker.io/gitlab/gitlab-runner:alpine
name: rootgitlab-runner1
resources: {}
securityContext:
allowPrivilegeEscalation: true
capabilities: {}
privileged: false
readOnlyRootFilesystem: false
volumeMounts:
- mountPath: /etc/gitlab-runner
name: srv-podman-gitlab-runner
- mountPath: /var/run/docker.sock
name: var-run-docker.sock
workingDir: /
volumes:
- hostPath:
path: /srv/podman/gitlab/runner
type: Directory
name: srv-podman-gitlab-runner
- hostPath:
path: /var/run/docker.sock
type: File
name: var-run-docker.sock
- hostPath:
path: /srv/podman/gitlab/data
type: Directory
name: srv-podman-gitlab-data
- hostPath:
path: /srv/podman/gitlab/logs
type: Directory
name: srv-podman-gitlab-logs
- hostPath:
path: /srv/podman/gitlab/conf
type: Directory
name: srv-podman-gitlab-conf
status: {}Systemd:
# podman generate systemd 71fc2b2a5c63
# pod-71fc2b2a5c6346f0c1c86a2dc45dbe78fa192ea02aac001eb8347ccb8c043c26.service
# autogenerated by Podman 1.6.4
# Thu Jul 29 15:23:28 EDT 2020
[Unit]
Description=Podman pod-71fc2b2a5c6346f0c1c86a2dc45dbe78fa192ea02aac001eb8347ccb8c043c26.service
Documentation=man:podman-generate-systemd(1)
Requires=container-781c0103c94aaa113c17c58d05ddabf8df4bf39707b664abcf17ed2ceff467d3.service container-da53da946c01449f500aa5296d9ea6376f751948b17ca164df438b7df6607864.service
Before=container-781c0103c94aaa113c17c58d05ddabf8df4bf39707b664abcf17ed2ceff467d3.service container-da53da946c01449f500aa5296d9ea6376f751948b17ca164df438b7df6607864.service
[Service]
Restart=on-failure
ExecStart=/usr/bin/podman start db40ab8bf84bf35141159c26cb6e256b889c7a98c0418eee3c4aa683c14fccaa
ExecStop=/usr/bin/podman stop -t 10 db40ab8bf84bf35141159c26cb6e256b889c7a98c0418eee3c4aa683c14fccaa
KillMode=none
Type=forking
PIDFile=/var/run/containers/storage/overlay-containers/db40ab8bf84bf35141159c26cb6e256b889c7a98c0418eee3c4aa683c14fccaa/userdata/conmon.pid
[Install]
WantedBy=multi-user.target
# container-da53da946c01449f500aa5296d9ea6376f751948b17ca164df438b7df6607864.service
# autogenerated by Podman 1.6.4
# Thu Jul 29 15:23:28 EDT 2020
[Unit]
Description=Podman container-da53da946c01449f500aa5296d9ea6376f751948b17ca164df438b7df6607864.service
Documentation=man:podman-generate-systemd(1)
RefuseManualStart=yes
RefuseManualStop=yes
BindsTo=pod-71fc2b2a5c6346f0c1c86a2dc45dbe78fa192ea02aac001eb8347ccb8c043c26.service
After=pod-71fc2b2a5c6346f0c1c86a2dc45dbe78fa192ea02aac001eb8347ccb8c043c26.service
[Service]
Restart=on-failure
ExecStart=/usr/bin/podman start da53da946c01449f500aa5296d9ea6376f751948b17ca164df438b7df6607864
ExecStop=/usr/bin/podman stop -t 10 da53da946c01449f500aa5296d9ea6376f751948b17ca164df438b7df6607864
KillMode=none
Type=forking
PIDFile=/var/run/containers/storage/overlay-containers/da53da946c01449f500aa5296d9ea6376f751948b17ca164df438b7df6607864/userdata/conmon.pid
[Install]
WantedBy=multi-user.target
# container-781c0103c94aaa113c17c58d05ddabf8df4bf39707b664abcf17ed2ceff467d3.service
# autogenerated by Podman 1.6.4
# Thu Jul 29 15:23:28 EDT 2020
[Unit]
Description=Podman container-781c0103c94aaa113c17c58d05ddabf8df4bf39707b664abcf17ed2ceff467d3.service
Documentation=man:podman-generate-systemd(1)
RefuseManualStart=yes
RefuseManualStop=yes
BindsTo=pod-71fc2b2a5c6346f0c1c86a2dc45dbe78fa192ea02aac001eb8347ccb8c043c26.service
After=pod-71fc2b2a5c6346f0c1c86a2dc45dbe78fa192ea02aac001eb8347ccb8c043c26.service
[Service]
Restart=on-failure
ExecStart=/usr/bin/podman start 781c0103c94aaa113c17c58d05ddabf8df4bf39707b664abcf17ed2ceff467d3
ExecStop=/usr/bin/podman stop -t 10 781c0103c94aaa113c17c58d05ddabf8df4bf39707b664abcf17ed2ceff467d3
KillMode=none
Type=forking
PIDFile=/var/run/containers/storage/overlay-containers/781c0103c94aaa113c17c58d05ddabf8df4bf39707b664abcf17ed2ceff467d3/userdata/conmon.pid
[Install]
WantedBy=multi-user.targetPër fat të keq, përveç nisjes së konteinerëve, një njësi e gjeneruar për systemd nuk bën asgjë tjetër (për shembull, pastrimin e konteinerëve të vjetër gjatë rinisjes së një shërbimi të tillë), prandaj këto gjëra do të duhet t'i shkruani vetë.
Në parim, Podman është mjaftueshëm për të provuar se çfarë janë konteinerët, për të transferuar konfigurimet e vjetra për docker-compose, pas së cilës mund të kaloni në Kubernetes nëse nevojitet për një grumbull, ose të merrni një alternativë më të thjeshtë për t'u punuar me Docker.
rkt
Projekti rreth gjashtë muaj më parë sepse u ble nga RedHat, prandaj nuk do të ndalem në të më hollësisht. Në përgjithësi, ai la një përshtypje mjaft të mirë, por krahasuar me Docker dhe sidomos me Podman, duket si një kombajn. Ekzistonte gjithashtu një shpërndarje CoreOS, e ndërtuar mbi bazën e rkt (pavarësisht se fillimisht kishin Docker), por mbështetja e saj gjithashtu përfundoi pas blerjes nga RedHat.
Plash
MĂ« shumĂ« , autori i tĂ« cilit dĂ«shiroi thjesht tĂ« mbledhĂ« dhe tĂ« nisĂ« konteinerĂ«t. Sipas dokumentacionit dhe kodit â autori nuk ndoqi standardet, por thjesht vendosi tĂ« shkruajĂ« implementimin e tij, gjĂ« qĂ« nĂ« parim e bĂ«ri.
Përfundimet
Situata kur ka Kubernetes është shumë interesante: nga njëra anë, me Docker mund të ndërtohet një grumbull (në modin swarm), me të cilin madje mund të nisen mjedise produkti për klientët, kjo është veçanërisht relevante për ekipet e vogla (3-5 persona), ose në rastin e një ngarkese të vogël të përgjithshme, ose mungesës së dëshirës për të kuptuar nuancat e konfigurimit të Kubernetes, përfshirë edhe për ngarkesa të larta.
Podman nuk ofron pajtueshmĂ«ri tĂ« plotĂ«, por ka njĂ« pĂ«rparĂ«si tĂ« rĂ«ndĂ«sishme â pajtueshmĂ«rinĂ« me Kubernetes, pĂ«rfshirĂ« edhe mjetet shtesĂ« (buildah dhe tĂ« tjerĂ«). Prandaj, pĂ«r tĂ« zgjedhur mjetin pĂ«r punĂ« do ta qas kĂ«shtu: pĂ«r ekipe tĂ« vogla, ose me buxhet tĂ« kufizuar â Docker (me mode tĂ« mundshme swarm), pĂ«r zhvillim pĂ«r usevet personal nĂ« localhost â Podman me shokĂ«, dhe pĂ«r tĂ« gjithĂ« tĂ« tjerĂ«t â Kubernetes.
Nuk jam i sigurt se situata me Docker do të ndryshojë në të ardhmen, pas të gjithash ata janë pionierë, dhe gjithashtu po standardizohen ngadalë për çdo hap, por e ardhmja e Podman, përkundër të gjitha mangësive të tij (funksionon vetëm në Linux, nuk ka klasterizim, ndërtimi dhe veprime të tjera janë me zgjidhje të jashtme) është më e qartë, prandaj ftoj të gjithë të interesuarit të diskutojnë këto përfundime në komente.
P.S. 3 gusht, nisemi me "", ku do të mund të mësoni më shumë rreth funksionimit të tij. Ne do të analizojmë të gjitha mjetet e tij: nga abstraksionet kryesore deri te parametrat e rrjetit, nuancat e punës me sisteme të ndryshme operative dhe gjuhët e programimit. Do të njiheni me teknologjinë dhe do të kuptoni se ku dhe si është më mirë të përdorni Docker. Gjithashtu do të ndajmë best practice rastet.
Ămimi i parakohshĂ«m deri nĂ« lĂ«shim: 5000 r. Mund tĂ« njiheni me programin "Videokursit pĂ«r Docker" .
Burimi: habr.com
