TL;DR: apžvalginis straipsnis – vadovas, kaip palyginti programas konteineriuose. Bus svarstomos Docker ir kitų panašių sistemų galimybės.
Šiek tiek istorijos, iš kur visa tai atsirado
Istorija
Pirmasis gerai žinomas būdas atskirti programą yra chroot. To paties pavadinimo sistemos iškvietimas suteikia pakeitimą šakniniam katalogui – taip suteikiama prieiga prie ją iškvietusios programos, prieiga tik prie šiame kataloge esančių failų. Bet jei programai bus suteiktos supervartotojo teisės, ji gali „pabėgti“ iš chroot ir gauti prieigą prie pagrindinės operacinės sistemos. Taip pat, be šakninio katalogo keitimo, neribojami ir kiti ištekliai (RAM, procesorius), taip pat prieiga prie tinklo.
Kitas būdas yra paleisti visavertę operacinę sistemą konteinerio viduje, naudojant operacinės sistemos branduolio mechanizmus. Šis metodas skirtingose operacinėse sistemose vadinamas skirtingai, tačiau esmė ta pati – veikia kelios nepriklausomos operacinės sistemos, kurių kiekviena veikia tame pačiame branduolyje, kuriame veikia pagrindinė operacinė sistema. Tai apima „FreeBSD Jails“, „Solaris Zones“, „OpenVZ“ ir „LXC“, skirtą „Linux“. Atskyrimas numatytas ne tik vietai diske, bet ir kitiems ištekliams, visų pirma kiekvienam konteineriui gali būti taikomi procesoriaus laiko, RAM, tinklo pralaidumo apribojimai. Palyginti su chroot, išeiti iš konteinerio yra sunkiau, nes konteinerio supervartotojas turi prieigą tik prie konteinerio vidaus, tačiau dėl būtinybės atnaujinti konteinerio operacinę sistemą ir naudojant seną branduolį versijose (tinka Linux, kiek mažiau FreeBSD), tikimybė „pralaužti“ branduolio izoliavimo sistemą ir gauti prieigą prie pagrindinės operacinės sistemos yra ne nulis.
Užuot paleidus visavertę operacinę sistemą konteineryje (su inicijavimo sistema, paketų tvarkykle ir pan.), programas galima paleisti iš karto, svarbiausia yra suteikti programoms tokią galimybę (būtinų bibliotekų ir Kiti failai). Ši idėja buvo konteinerinio programų virtualizavimo pagrindas, kurio ryškiausias ir žinomiausias atstovas yra Docker. Palyginti su ankstesnėmis sistemomis, lankstesni atskyrimo mechanizmai, kartu su integruotu virtualių tinklų tarp konteinerių palaikymu ir programos būsenos nustatymu konteineryje, leido sukurti vieną holistinę aplinką iš daugybės fizinių serverių, kad būtų galima paleisti konteinerius – be jų. rankinio išteklių valdymo poreikis.
dokininkas
„Docker“ yra labiausiai žinoma programų konteinerių talpinimo programinė įranga. Parašyta Go kalba, jame naudojamos įprastos Linux branduolio galimybės – cgroups, vardų erdvės, galimybės ir kt., taip pat Aufs failų sistemos ir kitos panašios vietos diske taupymui.
Šaltinis: wikimedia
Architektūra
Iki 1.11 versijos Docker dirbo kaip viena paslauga, kuri atliko visas operacijas su konteineriais: atsisiuntė konteinerių vaizdus, paleido konteinerius, apdorojo API užklausas. Nuo 1.11 versijos „Docker“ buvo padalintas į kelias dalis, kurios sąveikauja viena su kita: talpyklą, kad būtų galima valdyti visą konteinerių gyvavimo ciklą (diske vietos paskirstymas, vaizdų atsisiuntimas, tinklo kūrimas, konteinerių paleidimas, diegimas ir stebėjimas) ir runC. , konteinerio vykdymo laikas, pagrįstas cgroups ir kitų Linux branduolio funkcijų naudojimu. Pati docker paslauga išlieka, bet dabar ji skirta tik API užklausoms, transliuojamoms į konteinerius, apdoroti.
Diegimas ir konfigūravimas
Mano mėgstamiausias būdas įdiegti docker yra docker-machine, kuris, be tiesioginio docker diegimo ir konfigūravimo nuotoliniuose serveriuose (įskaitant įvairius debesis), leidžia dirbti su nuotolinių serverių failų sistemomis, taip pat gali vykdyti įvairias komandas.
Tačiau nuo 2018 metų projektas beveik nevykdomas, todėl jį diegsime įprastu daugumai Linux distribucijos būdų – pridėdami saugyklą ir įdiegdami reikiamus paketus.
Šis metodas taip pat naudojamas automatizuotam diegimui, pavyzdžiui, naudojant Ansible ar kitas panašias sistemas, tačiau šiame straipsnyje to nenagrinėsiu.
Diegimas bus atliktas „Centos 7“, kaip serverį naudosiu virtualią mašiną, norėdami įdiegti, tiesiog paleiskite toliau pateiktas komandas:
# 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.io
Įdiegę turite paleisti paslaugą, įdėti ją į automatinį įkėlimą:
# systemctl enable docker
# systemctl start docker
# firewall-cmd --zone=public --add-port=2377/tcp --permanent
Be to, galite sukurti docker grupę, kurios vartotojai galės dirbti su docker be sudo, nustatyti registravimą, įgalinti prieigą prie API iš išorės, nepamirškite sureguliuoti ugniasienės (viskas, kas neleidžiama, yra draudžiama aukščiau ir toliau pateiktuose pavyzdžiuose – dėl paprastumo ir aiškumo tai praleidau), bet čia daugiau nenagrinėsiu.
Kitos funkcijos
Be aukščiau nurodyto doko įrenginio, taip pat yra dokų registras, konteinerių vaizdų saugojimo įrankis, taip pat dokų kūrimo įrankis - įrankis, skirtas automatizuoti programų diegimą konteineriuose, YAML failai naudojami konteineriams kurti ir konfigūruoti. kiti susiję dalykai (pavyzdžiui, tinklai, nuolatinės failų sistemos duomenims saugoti).
Jis taip pat gali būti naudojamas CICD vamzdynams organizuoti. Dar viena įdomi funkcija – darbas klasterio režimu, vadinamasis spiečiaus režimas (iki 1.12 versijos jis buvo žinomas kaip docker swarm), leidžiantis surinkti vieną infrastruktūrą iš kelių serverių, kad būtų galima paleisti konteinerius. Visų serverių viršuje palaikomas virtualus tinklas, yra įmontuotas apkrovos balansavimo įrankis, taip pat konteinerių paslapčių palaikymas.
YAML failai iš docker compose gali būti naudojami tokiems klasteriams su nedideliais pakeitimais, visiškai automatizuojant mažų ir vidutinių grupių priežiūrą įvairiems tikslams. Didelėms grupėms geriau naudoti Kubernetes, nes spiečių režimo priežiūros išlaidos gali viršyti Kubernetes. Be runC, kaip konteinerių vykdymo aplinką, galite įdiegti, pvz
Darbas su Docker
Įdiegę ir sukonfigūravę bandysime sukurti klasterį, kuriame diegsime GitLab ir Docker registrą kūrimo komandai. Kaip serverius naudosiu tris virtualias mašinas, kuriose papildomai diegsiu GlusterFS paskirstytą FS, naudosiu kaip docker tomų saugyklą, pavyzdžiui, paleisti saugią docker registro versiją. Pagrindiniai paleisti komponentai: „Docker Registry“, „Postgresql“, „Redis“, „GitLab“ su „GitLab Runner“ palaikymu „Swarm“ viršuje. Postgresql bus paleistas su klasterizavimu
Norėdami įdiegti GlusterFS visuose serveriuose (jie vadinami node1, node2, node3), turite įdiegti paketus, įjungti užkardą, sukurti reikiamus katalogus:
# 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/fstab
Įdiegę GlusterFS konfigūravimo darbus reikia tęsti iš vieno mazgo, pavyzdžiui, 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 docker
Tada turite prijungti gautą tomą (komandą reikia paleisti visuose serveriuose):
# mount /srv/docker
Swarm režimas sukonfigūruotas viename iš serverių, kuris bus Leader, likusieji turės prisijungti prie klasterio, todėl komandos vykdymo pirmame serveryje rezultatą reikės nukopijuoti ir vykdyti likusiuose.
Pradinė klasterio sąranka, aš paleidžiu komandą 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 manager
Nukopijuojame antrosios komandos rezultatą ir vykdome node2 ir node3:
# docker swarm join --token SWMTKN-x-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-xxxxxxxxx xx.xx.xx.xx:2377
This node joined a swarm as a manager.
Taip baigiama preliminari serverių konfigūracija, pradėkime konfigūruoti paslaugas, vykdomos komandos bus paleistos iš node1, jei nenurodyta kitaip.
Pirmiausia sukurkime konteinerių tinklus:
# 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 gitlab
Tada pažymime serverius, tai būtina norint susieti kai kurias paslaugas su serveriais:
# docker node update --label-add nodename=node1 node1
# docker node update --label-add nodename=node2 node2
# docker node update --label-add nodename=node3 node3
Tada sukuriame katalogus etcd duomenims saugoti, KV saugyklą, kurios reikia „Traefik“ ir „Stolon“. Panašiai kaip Postgresql, tai bus konteineriai, susieti su serveriais, todėl šią komandą vykdome visuose serveriuose:
# mkdir -p /srv/etcd
Tada sukurkite failą, kad sukonfigūruotumėte etcd, ir pritaikykite jį:
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 etcd
Po kurio laiko patikriname, ar veikia etcd klasteris:
# 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 healthy
Sukurkite „Postgresql“ katalogus, vykdykite komandą visuose serveriuose:
# mkdir -p /srv/pgsql
Tada sukurkite failą, kad sukonfigūruotumėte 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: true
Sugeneruojame paslaptis, taikome failą:
# </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 pgsql
Po kurio laiko (pažiūrėkite į komandos išvestį dokerių paslauga lskad visos paslaugos veikia) inicijuojame Postgresql klasterį:
# 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 init
„Postgresql“ klasterio parengties tikrinimas:
# 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
Mes sukonfigūruojame traefik, kad atidarytumėte prieigą prie konteinerių iš išorės:
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 traefik
Paleidžiame Redis Cluster, tam sukuriame saugojimo katalogą visuose mazguose:
# mkdir -p /srv/redis
05redis.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 <<EOF > /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 redis
Pridėti „Docker“ registrą:
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 registry
Ir galiausiai - 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'] = "[email protected]"
gitlab_rails['smtp_password'] = "xxxxxxxxx"
gitlab_rails['smtp_domain'] = "example.com"
gitlab_rails['gitlab_email_from'] = '[email protected]'
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 gitlab
Galutinė klasterio ir paslaugų būsena:
# 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
Ką dar galima patobulinti? Būtinai sukonfigūruokite „Traefik“, kad jis veiktų su https konteineriais, pridėkite „tls“ šifravimą „Postgresql“ ir „Redis“. Bet apskritai jau galite duoti kūrėjams kaip PoC. Dabar pažvelkime į „Docker“ alternatyvas.
Podmanas
Kitas gana gerai žinomas variklis, skirtas paleisti konteinerius, sugrupuotus pagal ankštis (ankštes, konteinerių grupes, išdėstytas kartu). Skirtingai nei Docker, konteineriams paleisti nereikia jokių paslaugų, visas darbas atliekamas per libpod biblioteką. Taip pat parašyta Go, reikalingas OCI suderinamas vykdymo laikas, kad būtų galima paleisti konteinerius, tokius kaip runC.
Darbas su „Podman“ apskritai panašus į „Docker“ darbą tiek, kiek galite tai padaryti taip (teigė daugelis jį išbandžiusių, įskaitant šio straipsnio autorių):
$ alias docker=podman
ir tu gali dirbti toliau. Apskritai situacija su Podman yra labai įdomi, nes jei ankstyvosios Kubernetes versijos dirbo su Docker, tai maždaug nuo 2015 m., standartizavus konteinerių pasaulį (OCI – Open Container Initiative) ir suskaidžius Docker į konteinerį ir runC, atsirado alternatyva „Docker“ kuriamas veikti Kubernetes: CRI-O. „Podman“ šiuo atžvilgiu yra „Docker“ alternatyva, sukurta pagal „Kubernetes“ principus, įskaitant konteinerių grupavimą, tačiau pagrindinis projekto tikslas – paleisti „Docker“ tipo konteinerius be papildomų paslaugų. Dėl akivaizdžių priežasčių nėra spiečiaus režimo, nes kūrėjai aiškiai sako, kad jei jums reikia klasterio, pasiimkite „Kubernetes“.
Montavimas
Norėdami įdiegti „Centos 7“, tiesiog suaktyvinkite „Extras“ saugyklą ir įdiekite viską naudodami komandą:
# yum -y install podman
Kitos funkcijos
„Podman“ gali generuoti „systemd“ vienetus, taip išspręsdama konteinerių paleidimo problemą po serverio perkrovimo. Be to, deklaruojama, kad systemd tinkamai veikia kaip pid 1 konteineryje. Konteineriams kurti yra atskiras buildah įrankis, yra ir trečiųjų šalių įrankių – docker-compose analogų, kurie taip pat generuoja su Kubernetes suderinamus konfigūracijos failus, todėl perėjimas iš Podman į Kubernetes yra kuo paprastesnis.
Darbas su Podmanu
Kadangi spiečiaus režimo nėra (jei reikia klasterio turi persijungti į Kubernetes), tai jį surinksime į atskirus konteinerius.
Įdiekite „podman-compose“:
# yum -y install python3-pip
# pip3 install podman-compose
Gautas podman konfigūracijos failas šiek tiek skiriasi, nes, pavyzdžiui, turėjome perkelti atskirą tomų skyrių tiesiai į paslaugų skyrių.
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 up
Darbo rezultatas:
# 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_1
Pažiūrėkime, ką jis sugeneruos „systemd“ ir „kubernetes“, tam turime sužinoti podelio pavadinimą arba ID:
# podman pod ls
POD ID NAME STATUS CREATED # OF CONTAINERS INFRA ID
71fc2b2a5c63 root Running 11 minutes ago 3 db40ab8bf84b
Kubernetes:
# 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: {}
sistema:
# 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.target
Deja, išskyrus konteinerių paleidimą, sugeneruotas systemd blokas nieko daugiau nedaro (pvz., išvalo senus konteinerius, kai tokia paslauga paleidžiama iš naujo), todėl tokius dalykus turėsite pridėti patys.
Iš esmės užtenka Podman išbandyti, kas yra konteineriai, perkelti senas konfigūracijas docker-compose ir tada, jei reikia, eiti link Kubernetes į klasterį arba gauti lengviau naudojamą Docker alternatyvą.
rkt
Projektas
Blykstė
Daugiau
išvados
Situacija su Kubernetes yra labai įdomi: viena vertus, naudojant Docker, galite surinkti klasterį (spiečiaus režimu), su kuriuo netgi galite paleisti gamybines aplinkas klientams, tai ypač pasakytina apie mažas komandas (3-5 žmonės). ), arba esant nedidelei bendrai apkrovai, arba trūkstant noro suprasti „Kubernetes“ nustatymo subtilybes, įskaitant ir didelėms apkrovoms.
„Podman“ neužtikrina visiško suderinamumo, tačiau turi vieną svarbų pranašumą - suderinamumą su „Kubernetes“, įskaitant papildomus įrankius („buildah“ ir kitus). Todėl į įrankį darbui pasirinksiu taip: mažoms komandoms arba turintiems ribotą biudžetą - „Docker“ (su galimu spiečiaus režimu), tobulėjimui sau asmeniniame „localhost“ - „Podman“ draugai ir visiems kitiems - Kubernetes.
Nesu tikras, kad su Docker situacija nepasikeis ateityje, juk jie yra pionieriai, taip pat pamažu žingsnis po žingsnio standartizuojasi, bet Podman su visais savo trūkumais (veikia tik ant Linux, nėra klasterizacijos, surinkimo o kiti veiksmai yra trečiųjų šalių sprendimai) ateitis aiškesnė, todėl kviečiu visus šias išvadas aptarti komentaruose.
PS Rugpjūčio 3 d.
Išankstinio užsakymo kaina prieš išleidimą: 5000 RUB. Galite peržiūrėti Docker Video Course programą
Šaltinis: www.habr.com