TL;DR: një artikull udhëzues krahasues për ambjentet e nisjes së aplikacioneve në konteinerë. Do të shqyrtohen mundësitë e Docker dhe sistemeve të ngjashme.

Pak histori, nga ku erdhi gjithçka
Historia
Mënyra e parë e njohur e izolimit të aplikacioneve është chroot. Thirrja sistemike e njëjtë siguron ndryshimin e direktorisë rrënjësore - duke siguruar kështu që programi që e thirri, ka akses vetëm në skedarët brenda kësaj direktorie. Por nëse programit brenda i jepet e drejta e superpërdoruesit, potencialisht ai mund të "dalë" nga chroot dhe të fitojë qasje në sistemin operativ kryesor. Po ashtu, përveç ndryshimit të direktorisë rrënjësore, burimet e tjera (memoria, procesori) nuk kufizohen, ashtu siç nuk kufizohet aksesimi në rrjet.
Mënyra tjetër është nisja e një sistemi operativ të plotë brenda një konteineri, përmes mekanizmave të bërthamës së sistemit operativ. Në sisteme të ndryshme operative, ky proces quhet ndryshe, por thelbi është i njëjtë - nisja e disa sistemeve të pavarura operative, secila nga të cilat punon me të njëjtën bërthamë, mbi të cilën punon edhe sistemi operativ kryesor. Këtu përfshihet FreeBSD Jails, Solaris Zones, OpenVZ dhe LXC për Linux. Sigurohet izolimi jo vetëm sipas hapësirës disk, por edhe burimeve të tjera, veçanërisht çdo konteiner mund të ketë kufizime në kohën e procesorit, memorien e rastit, dhe gjerësinë e brezit të rrjetit. Krahasuar me chroot, është më e vështirë të dalesh nga një konteiner, pasi superpërdoruesi në konteiner ka qasje vetëm në brendësinë e konteinerit, megjithatë, për shkak të nevojës për të mbajtur sistemin operativ brenda konteinerit në gjendje të azhurnuar dhe për përdorimin e versioneve të vjetra të bërthamës (e rëndësishme për Linux, në një masë më të vogël FreeBSD), ka një probabilitet të pamohueshëm të "kalimit" të sistemit të izolimit të bërthamës dhe të fitosh qasje në sistemin operativ kryesor.
Në vend të nisjes së një sistemi operativ të plotë në konteiner (me sistemin e inicializimit, menaxherin e paketave, etj.), mund të nisësh menjëherë aplikacione, e rëndësishme është të sigurosh që aplikacionet të kenë mundësi të tilla (prania e librarive të nevojshme dhe skedarëve të tjerë). Kjo ide shërbeu si bazë për virtualizimin e aplikacioneve në konteiner, 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ë integruar për rrjetet virtuale midis konteinerëve dhe monitorimin e gjendjes së aplikacionit brenda konteinerit, ofruan në fund mundësinë e ndërtimit të një ambienti të plotë nga një numër të madh serverash fizikë për nisjen e konteinerëve - pa nevojën për menaxhimin manual të burimeve.
Docker
Docker është software më i njohur për konteinerizimin e aplikacioneve. I shkruar në gjuhën Go, përdor mundësitë standarde të bërthamës së Linux - cgroups, namespaces, capabilities, etj., si dhe sisteme skedarësh Aufs dhe të tjera të ngjashme për kursimin e hapësirës disk.

Burimi: wikimedia
Arkitektura
Derisa të versionit 1.11, Docker funksiononte si një shërbim unik, i cili kryente të gjitha operacionet me konteinerët: shkarkimin e imazheve për konteinerët, nisjen e konteinerëve, trajtimin e kërkesave API. Duke filluar nga versioni 1.11, Docker është ndarë në disa pjesë që bashkëpunojnë me njëra-tjetrën: containerd, për të përpunuar të gjithë ciklin e jetës së konteinerëve (ndarje e hapësirës disk, shkarkimi i imazheve, funksionimi me rrjetin, nisja, instalimi dhe monitorimi i gjendjes së konteinerëve) dhe runC, mjedisi i ekzekutimit të konteinerëve, që bazohet në përdorimin e cgroups dhe mundësive të tjera të bërthamës së Linux. Shërbimi vetë Docker mbeti, por tani ai shërben vetëm për të trajtuar kërkesat API, që 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ë serverë të largët (përfshirë cloud të ndryshme) ofron mundësinë e punës me sistemet e skedarëve të serverëve të largët, gjithashtu mund të ekzekutojë komanda të ndryshme.
MegjithatĂ«, qĂ« nga viti 2018, projekti pothuajse nuk po zhvillohet, kĂ«shtu qĂ« instalimin do ta bĂ«jmĂ« nĂ« mĂ«nyrĂ«n standarde pĂ«r shumicĂ«n e shpĂ«rndarjeve Linux â duke shtuar repo dhe instaluar paketat e nevojshme.
Kjo mënyrë po ashtu përdoret edhe për instalimin automatizuar, për shembull me ndihmën e Ansible ose sistemeve të ngjashme, por në këtë artikull nuk do ta shqyrtoj atë.
Instalimi do të bëhet në CentOS 7, dhe si server do të përdor një makinë virtuale, për instalimin mjafton të ekzekutoni komandat e mëposhtme:
# 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ë nisni shërbimin, ta vendosni në ngarkesë automatik:
# systemctl enable docker
# systemctl start docker
# firewall-cmd --zone=public --add-port=2377/tcp --permanentGjithashtu, mund tĂ« krijoni njĂ« grup docker, pĂ«rdoruesit e tĂ« cilit do tĂ« jenĂ« nĂ« gjendje tĂ« punojnĂ« me docker pa sudo, tĂ« konfiguroni regjistrimin, tĂ« aktivizoni aksesin nĂ« API nga jashtĂ«, mos harroni tĂ« konfiguroni mĂ« saktĂ« firewall-in (ndalohet gjithçka qĂ« nuk lejohet, nĂ« shembujt mĂ« sipĂ«r dhe mĂ« poshtĂ« â unĂ« kĂ«tĂ« e kam lĂ«nĂ« jashtĂ« pĂ«r thjeshtĂ«si dhe qartĂ«si), por kĂ«tu nuk do tĂ« hyjĂ« nĂ« detaje mĂ« shumĂ«.
Mundësi të tjera
PĂ«rveç docker machine tĂ« pĂ«rmendur mĂ« lart, ekziston gjithashtu docker registry, njĂ« mjet pĂ«r ruajtjen e imazheve pĂ«r kontenierĂ«t, si dhe docker compose â njĂ« mjet pĂ«r automatizimin e hapjes sĂ« aplikacioneve nĂ« kontenierĂ«, pĂ«rdoren skedarĂ«t YAML pĂ«r ndĂ«rtimin dhe konfigurimin e kontenierĂ«ve dhe gjĂ«rave tĂ« tjera pĂ«rkatĂ«se (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 është e mundur të organizoni konvencionet për CICD. Një mundësi tjetër interesante është funksionimi në modalitetin e grupit, i njohur si swarm mode (para versionit 1.12 quhej docker swarm), që lejon krijimin e një infrastrukture të vetme për të lançuar kontenierë nga disa serverë. Ka mbështetje për rrjetin virtual mbi të gjithë serverët, ka një balancues të ngarkesës të integruar, si dhe mbështetje për sekretet për kontenierët.
Skedarët YAML nga docker compose me disa ndryshime mund të përdoren për këto grupe, duke automatizuar plotësisht shërbimin e grupeve të vogla dhe të mesme për qëllime të ndryshme. Për grupe më të mëdha preferohet të përdoret Kubernetes, pasi kostot për shërbimin e swarm mode mund të tejkalojnë ato me Kubernetes. Përveç runC si mjedis ekzekutimi për kontenierët, mund të instaloni për shembull
Puna me Docker
Pas instalimit dhe konfigurimit, do të përpiqemi të ndërtojmë një grup, në të cilin do të hapim GitLab dhe Docker Registry për ekipin e zhvilluesve. Përdor do të kemi tre makina virtuale, në të cilat gjithashtu do të hapim një FS të shpërndarë GlusterFS, që do ta përdor për ruajtjen e docker volumes, për shembull për të hapur një version të besueshëm të docker registry. Komponentët kryesorë për hapjen: Docker Registry, Postgresql, Redis, GitLab me mbështetje për GitLab Runner mbi Swarm. Postgresql do ta hapim me klasterizim , kështu që për ruajtjen e të dhënave Postgresql nuk duhen përdorur GlusterFS. Të dhënat e tjera kritike do të ruhen në GlusterFS.
Për të hapur GlusterFS në të gjithë serverët (të quajtur node1, node2, node3) duhet të instaloni paketat, të lejoni punën e firewall-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, duhet të vazhdojmë me konfigurimin e GlusterFS 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 dockerAtëherë duhet të montoni volume-n e krijuar (komandën duhet ta ekzekutoni në të gjithë serverët):
# mount /srv/dockerKonfigurimi i swarm mode bëhet në një nga serverët, i cili do të jetë Lider, të tjerët duhet të bashkohen në grup, kështu që rezultatin e ekzekutimit të komandës në serverin e parë duhet ta kopjoni dhe ta ekzekutoni në të tjerët.
Konfigurimi fillestar i grupit, komandën e nis unë 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.Me këtë, parakonfigurimi i serverëve mbaron, kalojmë në konfigurimin e shërbimeve, komandat për ekzekutim do të ekzekutohen nga node1, nëse nuk specifikohet ndryshe.
Së pari, do të krijojmë rrjetet për kontenierë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 gitlabAtëherë do të shenojmë serverët, kjo është e nevojshme për të lidhur disa shërbime me serverët:
# docker node update --label-add nodename=node1 node1
# docker node update --label-add nodename=node2 node2
# docker node update --label-add nodename=node3 node3Pastaj krijojmë katalogët për ruajtjen e të dhënave etcd, një ruajtje KV, që është e nevojshme për Traefik dhe Stolon. Në mënyrë të ngjashme me Postgresql, këto do të jenë kontenierë të lidhur me serverët, kështu që këtë komandë e kryejmë në të gjithë serverët:
# mkdir -p /srv/etcdMë pas krijojmë një skedar 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 disa kohësh kontrollojmë nëse 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ë katalogë për Postgresql, komandën e ekzekutojmë në të gjitha serverat:
# mkdir -p /srv/pgsqlMë pas krijojmë skedarin për konfigurimin e Postgresql:
01pgsql.yml
version: '3.7'
services:
pgsentinel:
image: sorintlab/stolon:master-pg10
command:
- 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
networks:
- etcd
- pgsql
deploy:
replicas: 3
update_config:
parallelism: 1
delay: 30s
order: stop-first
failure_action: pause
pgkeeper1:
image: sorintlab/stolon:master-pg10
hostname: pgkeeper1
command:
- 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
networks:
- etcd
- pgsql
environment:
- PGDATA=/var/lib/postgresql/data
volumes:
- pgkeeper1:/var/lib/postgresql/data
secrets:
- pgsql
- pgsql_repl
deploy:
replicas: 1
placement:
constraints: [node.labels.nodename == node1]
pgkeeper2:
image: sorintlab/stolon:master-pg10
hostname: pgkeeper2
command:
- 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
networks:
- etcd
- pgsql
environment:
- PGDATA=/var/lib/postgresql/data
volumes:
- pgkeeper2:/var/lib/postgresql/data
secrets:
- pgsql
- pgsql_repl
deploy:
replicas: 1
placement:
constraints: [node.labels.nodename == node2]
pgkeeper3:
image: sorintlab/stolon:master-pg10
hostname: pgkeeper3
command:
- 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
networks:
- etcd
- pgsql
environment:
- PGDATA=/var/lib/postgresql/data
volumes:
- pgkeeper3:/var/lib/postgresql/data
secrets:
- pgsql
- pgsql_repl
deploy:
replicas: 1
placement:
constraints: [node.labels.nodename == node3]
postgresql:
image: sorintlab/stolon:master-pg10
command: 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
networks:
- etcd
- pgsql
deploy:
replicas: 3
update_config:
parallelism: 1
delay: 30s
order: stop-first
failure_action: rollback
volumes:
pgkeeper1:
driver: local
driver_opts:
type: none
o: bind
device: "/srv/pgsql"
pgkeeper2:
driver: local
driver_opts:
type: none
o: bind
device: "/srv/pgsql"
pgkeeper3:
driver: local
driver_opts:
type: none
o: bind
device: "/srv/pgsql"
secrets:
pgsql:
file: "/srv/docker/postgres"
pgsql_repl:
file: "/srv/docker/replica"
networks:
etcd:
external: true
pgsql:
external: trueGjeni sekretet, aplikoni 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 disa kohësh (shohim daljen e komandës docker service ls, që janë ngritur të gjitha shërbimet) inicializojmë klasën 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 klasës 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-in për të hapur qasjen 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 traefikPo fillojmë Redis Cluster, për këtë krijojmë në të gjitha nodet 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 nĂ« fund â 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Ă« tjetĂ«r mund tĂ« pĂ«rmirĂ«sohet? Sigurohuni tĂ« konfiguroni nĂ« Traefik funksionimin e kontejnerĂ«ve me https, tĂ« shtoni enkriptimin tls pĂ«r Postgresql dhe Redis. Por nĂ« pĂ«rgjithĂ«si, tashmĂ« mund ta ofrojmĂ« zhvilluesve si PoC. Tani le tĂ« shohim alternativat e Docker.
Podman
Një engine tjetër mjaft i njohur për ekzekutimin e kontejnerëve, të grupuar në pods (grupet e kontejnerëve, të vendosura së bashku). Ndryshe nga Docker nuk kërkon ndonjë shërbim për të ekzekutuar kontejnerët, tërë puna kryhet përmes bibliotekës libpod. Po ashtu, është shkruar në Go, kërkon një runtime të përputhshëm me OCI për të ekzekutuar kontejnerët, për shembull runC.

Puna me Podman është ngjashëm me atë për Docker, deri në atë pikë sa mund të bëni këtë (ka qenë e deklaruar nga shumë të tjerë që e kanë provuar, përfshirë autorin e këtij artikulli):
$ alias docker=podmandhe mund tĂ« vazhdoni tĂ« punoni. NĂ« pĂ«rgjithĂ«si, situata me Podman Ă«shtĂ« shumĂ« interesante, sepse nĂ«se versionet e hershme tĂ« Kubernetes punonin me Docker, qĂ« nga viti 2015, pas standardizimit tĂ« botĂ«s sĂ« kontejnerĂ«ve (OCI â Open Container Initiative) dhe ndarjes sĂ« Docker nĂ« containerd dhe runC, Ă«shtĂ« zhvilluar njĂ« alternativĂ« e Docker pĂ«r fillimin nĂ« Kubernetes: CRI-O. Podman, nĂ« kĂ«tĂ« aspekt, Ă«shtĂ« njĂ« alternativĂ« ndaj Docker, e ndĂ«rtuar mbi parimet e Kubernetes, duke pĂ«rfshirĂ« grupimin e kontejnerĂ«ve, por qĂ«llimi kryesor i ekzistencĂ«s sĂ« projektit Ă«shtĂ« tĂ« nisĂ« kontejnerĂ«t nĂ« stilin Docker pa shĂ«rbime tĂ« tjera shtesĂ«. PĂ«r arsye tĂ« kuptueshme, nuk ka mod tĂ« grupimeve, pasi zhvilluesit e thonĂ« qartĂ« se nĂ«se duhet klaster â merrni Kubernetes.
Instalimi
Për të instaluar në Centos 7, mjafton të aktivizoni repositorin Extras, dhe më pas të instaloni gjithçka me komandën:
# yum -y install podmanMundësi të tjera
Podman mund tĂ« krijojĂ« njĂ«si pĂ«r systemd, kĂ«shtu duke zgjidhur problemin e nisjes sĂ« kontejnerĂ«ve pas rinisjes sĂ« serverit. PĂ«r mĂ« tepĂ«r, Ă«shtĂ« deklaruar se systemd funksionon si pid 1 nĂ« kontejner. PĂ«r ndĂ«rtimin e kontejnerĂ«ve pĂ«rdoret njĂ« mjet i veçantĂ« buildah, ka gjithashtu mjete tĂ« tjera tĂ« jashtme â analoge tĂ« docker-compose qĂ« krijojnĂ« pĂ«rfshirĂ« skedarĂ« konfigurimi, tĂ« qĂ«ndrueshĂ«m me Kubernetes, kĂ«shtu qĂ« kalimi nga Podman nĂ« Kubernetes Ă«shtĂ« sa mĂ« i lehtĂ« tĂ« jetĂ« e mundur.
Puna me Podman
Pasi nuk ka mod tĂ« grupimeve (parashikohet kalimi nĂ« Kubernetes, nĂ«se kĂ«rkohet klaster) â do t'i mbledhim kontejnerĂ«t e veçantĂ«.
Instalojmë podman-compose:
# yum -y install python3-pip
# pip3 install podman-composeSkedari i rezultuar i konfigurimit për podman është paksa ndryshe, si për shembull është dashur të çojmë 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ë krijojë për systemd dhe kubernetes, për këtë duhet të dimë emrin ose id 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.targetFatkeqësisht, përveç nisjes së kontejnerëve, njësia e krijuar për systemd nuk bën asgjë tjetër (për shembull, nuk pastron kontejnerët e vjetër gjatë rinisjes së një shërbimi të tillë), kështu që këto gjëra do të duhet t'i shtoni vetë.
Në përgjithësi, Podman është më se i mjaftueshëm për të provuar se çfarë janë kontejnerët, të transferoni konfigurimet e vjetra për docker-compose dhe më pas të kaloni në Kubernetes, nëse nevojitet një klaster, ose të merrni një alternativë më të thjeshtë për t'u punuar me Docker.
rkt
Projekt rreth gjashtë muaj më parë për shkak se e bleu RedHat, prandaj nuk do të ndalem më gjatë mbi të. Në përgjithësi, ai la një përshtypje mjaft të mirë, megjithatë, krahasuar me Docker dhe sidomos me Podman duket si një kombinator. Po ashtu ka ekzistuar një distribucion CoreOS, i ndërtuar mbi rkt (sidoqoftë fillimisht kishin Docker), megjithatë mbështetja e tij gjithashtu përfundojë pas blerjes nga RedHat.
Plash
MĂ« shumĂ« , autori i tĂ« cilit donte thjesht tĂ« ndĂ«rtonte dhe niste kontejnerĂ«t. NĂ« bazĂ« tĂ« dokumentacionit dhe kodit â autori nuk ka ndjekur standardet, por thjesht vendosi tĂ« shkruajĂ« implementimin e tij, dhe kjo nĂ« tĂ« vĂ«rtetĂ« e bĂ«ri.
Përfundimet
Situata në prani të Kubernetes është mjaft interesante: nga njëra anë, me Docker mund të krijoni një klaster (në modin swarm), me të cilin mund të nisen mjedise produktive për klientët, kjo është veçanërisht e rëndësishme për ekipet e vogla (3-5 persona), ose nëse nuk ka një ngarkesë të madhe të përbashkët, ose mungesës së dëshirës për të hetuar hollësitë e konfigurimit të Kubernetes, përfshirë për ngarkesa të larta.
Podman nuk siguron pĂ«rputhshmĂ«ri tĂ« plotĂ«, por ka njĂ« avantazh tĂ« rĂ«ndĂ«sishĂ«m â pĂ«rputhshmĂ«rinĂ« me Kubernetes, pĂ«rfshirĂ« edhe pĂ«r mjetet e tjera shtesĂ« (buildah dhe tĂ« tjera). Prandaj, do tĂ« qaset kĂ«saj tĂ« zgjedhje mjeti pĂ«r tĂ« punuar kĂ«shtu: pĂ«r ekipe tĂ« vogla, ose me njĂ« buxhet tĂ« kufizuar â Docker (me mundĂ«sinĂ« e modit swarm), pĂ«r zhvillimin pĂ«r vete nĂ« localhostin personal â Podman me shokĂ«, dhe pĂ«r tĂ« tjerĂ«t â Kubernetes.
Nuk jam i sigurt se situata me Docker nuk do tĂ« ndryshojĂ« nĂ« tĂ« ardhmen, megjithatĂ« ata janĂ« pionierĂ« dhe gjithashtu po standardizohen hap pas hapi, por me Podman pĂ«r tĂ« gjitha disavantazhet e tij (puna vetĂ«m nĂ« Linux, pa klasterizim, ndĂ«rtimi dhe veprime tĂ« tjera â zgjidhje tĂ« jashtme) e ardhmja Ă«shtĂ« mĂ« e qartĂ«, prandaj ftoj tĂ« gjithĂ« tĂ« interesuarit tĂ« diskutojnĂ« kĂ«to pĂ«rfundime nĂ« komentet.
P.S. Më 3 gusht fillojmë "», ku mund të mësoni më shumë rreth funksionimit të tij. Ne do të shqyrtojmë të gjitha mjetet e tij: nga abstraksionet bazë deri te parametrat e rrjetit, nuancat e punës me sisteme të ndryshme operative dhe gjuhët e programimit. Do të njihni teknologjinë dhe do të kuptoni se ku dhe si është më mirë të përdoret Docker. Gjithashtu, do të ndajmë praktikat më të mira.
Ămimi i parakohshĂ«m deri nĂ« publikim: 5000 r. Mund tĂ« njiheni me programin "Video Kursit pĂ«r Docker" .
Burimi: habr.com
