TL;DR: Edukiontzietan aplikazioak exekutatzeko esparruak alderatzeko ikuspegi orokorra. Dockerren eta antzeko beste sistema batzuen gaitasunak kontuan hartuko dira.
Dena nondik datorren jakiteko historia txiki bat
Story
Aplikazio bat isolatzeko lehen metodo ezaguna chroot da. Izen bereko sistema-deiak erro-direktorioa aldatzen dela bermatzen du, horrela deitzen duen programak direktorio horretako fitxategietara soilik sarbidea duela ziurtatzen du. Baina programa bati barnean root pribilegioak ematen badio, potentzialki "ihes" dezake chroot-etik eta sistema eragile nagusirako sarbidea lor dezake. Era berean, erro direktorioa aldatzeaz gain, beste baliabide batzuk (RAM, prozesadorea), baita sarerako sarbidea ere, ez dira mugatuak.
Hurrengo metodoa edukiontzi baten barruan sistema eragile oso bat abiarazteko da, sistema eragilearen nukleoaren mekanismoak erabiliz. Metodo honi modu ezberdinean deitzen zaio sistema eragile ezberdinetan, baina funtsa berdina da: hainbat sistema eragile independente abiarazten ditu, eta horietako bakoitzak sistema eragile nagusiak exekutatzen duen nukleo bera exekutatzen du. Horien artean daude FreeBSD Jails, Solaris Zones, OpenVZ eta LXC Linuxerako. Isolamendua diskoko espazioak ez ezik, beste baliabide batzuek ere bermatzen du; bereziki, edukiontzi bakoitzak prozesadorearen denboran, RAMan eta sareko banda zabaleran mugak izan ditzake. Chroot-arekin alderatuta, edukiontzia uztea zailagoa da, edukiontzian dagoen supererabiltzaileak edukiontziaren edukirako sarbidea baitu soilik, hala ere, edukiontzi barruan sistema eragilea eguneratuta eduki beharragatik eta bertsio zaharragoak erabiltzeagatik. nukleoen (Linux-erako garrantzitsua, neurri txikiagoan FreeBSD), nukleoa isolatzeko sistema "hautsi" eta sistema eragile nagusirako sarbidea izateko probabilitatea ez da nulua.
Edukiontzi batean sistema eragile oso bat abiarazi beharrean (hasierako sistema batekin, paketeen kudeatzailearekin, etab.), aplikazioak berehala abiarazi ditzakezu, gauza nagusia aplikazioei aukera hori eskaintzea da (beharrezko liburutegien presentzia). eta beste fitxategi batzuk). Ideia hau edukiontzidun aplikazioen birtualizazioaren oinarri izan zen, eta horien ordezkaririk nabarmenena eta ezagunena Docker da. Aurreko sistemekin alderatuta, isolamendu-mekanismo malguagoak, edukiontzien arteko sare birtualen euskarria integratuta eta edukiontziaren barruan aplikazio-egoeraren jarraipenarekin batera, edukiontziak exekutatzeko zerbitzari fisiko kopuru handi batetik ingurune koherente bakarra eraikitzeko gaitasuna izan zuten. eskuzko baliabideen kudeaketaren beharrik gabe.
Docker
Docker aplikazioen edukiontzien software ospetsuena da. Go hizkuntzan idatzita, Linux kernelaren ezaugarri estandarrak erabiltzen ditu - cgroups, namespaces, gaitasunak, etab., baita Aufs fitxategi sistemak eta horrelakoak diskoko lekua aurrezteko.
Iturria: wikimedia
arkitektura
1.11 bertsioaren aurretik, Docker-ek edukiontziekin eragiketa guztiak egiten zituen zerbitzu bakar gisa funtzionatzen zuen: edukiontzietarako irudiak deskargatu, edukiontziak abiarazi, API eskaerak prozesatu. 1.11 bertsiotik hasita, Docker elkarren artean elkarreragiten duten hainbat zatitan banatu zen: containerd, edukiontzien bizi-ziklo osoa prozesatzeko (diskoko espazioa esleitzea, irudiak deskargatzea, sarearekin lan egitea, edukiontzien egoera abiarazi, instalatzea eta kontrolatzea) eta runC, edukiontzien exekuzio ingurunea, cgroups eta Linux kernelaren beste ezaugarri batzuen erabileran oinarrituta. Docker zerbitzuak berak jarraitzen du, baina orain containerd-era itzulitako API eskaerak prozesatzeko baino ez du balio.
Instalazioa eta konfigurazioa
Docker instalatzeko gehien gustatzen zaidan modua docker-machine da, zeinak, urruneko zerbitzarietan docker zuzenean instalatzea eta konfiguratzeaz gain (hainbat hodei barne), urruneko zerbitzarietako fitxategi-sistemekin lan egiteko aukera ematen du eta hainbat komando ere exekutatu ditzake.
Hala ere, 2018az geroztik, proiektua ez da ia garatu, beraz, Linux banaketa gehienetarako modu estandarrean instalatuko dugu - biltegi bat gehituz eta beharrezko paketeak instalatuz.
Metodo hau instalazio automatizaturako ere erabiltzen da, adibidez Ansible edo antzeko beste sistema batzuk erabiliz, baina ez dut artikulu honetan kontuan hartuko.
Instalazioa Centos 7-n egingo da, makina birtual bat erabiliko dut zerbitzari gisa, instalatzeko, exekutatu beheko komandoak:
# 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
Instalatu ondoren, zerbitzua hasi eta abian jarri behar duzu:
# systemctl enable docker
# systemctl start docker
# firewall-cmd --zone=public --add-port=2377/tcp --permanent
Gainera, docker talde bat sor dezakezu, zeinen erabiltzaileek dockerrekin sudorik gabe lan egin ahal izango dute, erregistroa konfiguratu, kanpotik APIrako sarbidea gaitu eta ez ahaztu suebakia zehatzago konfiguratzea (onartzen ez den guztia). goiko eta beheko adibideetan debekatuta dago - sinpletasun eta argitasunerako utzi dut hau), baina ez dut hemen xehetasun gehiagorik sartuko.
Beste ezaugarri batzuk
Aipatutako docker makinaz gain, docker erregistroa ere badago, edukiontzietarako irudiak gordetzeko tresna, baita docker compose ere, aplikazioak edukiontzietan hedatzea automatizatzeko tresna, YAML fitxategiak edukiontziak eraiki eta konfiguratzeko erabiltzen dira. eta erlazionatutako beste gauza batzuk (adibidez, sareak, datuak biltegiratzeko fitxategi sistema iraunkorrak).
CICDrako zinta garraiatzaileak antolatzeko ere erabil daiteke. Beste ezaugarri interesgarri bat kluster moduan lan egitea da, swarm modua deritzona (1.12 bertsioaren aurretik docker swarm izenez ezagutzen zen), eta horrek edukiontziak exekutatzeko hainbat zerbitzarietatik azpiegitura bakarra muntatzeko aukera ematen du. Zerbitzari guztien gainean sare birtual baterako laguntza dago, karga-orekatzailea integratuta dago, baita edukiontzientzako sekretuen laguntza ere.
Docker compose-ko YAML fitxategiak, aldaketa txikiekin, horrelako klusterretarako erabil daitezke, kluster txiki eta ertainen mantentze-lanak erabat automatizatuz hainbat helburutarako. Kluster handietarako, Kubernetes hobe da swarm moduaren mantentze-kostuak Kubernetesenak gainditu ditzakeelako. RunC gain, adibidez, edukiontzien exekuzio ingurune gisa instala dezakezu
Docker-ekin lan egiten
Instalatu eta konfiguratu ondoren, garapen-taldearentzat GitLab eta Docker Registry zabalduko ditugun kluster bat muntatzen saiatuko gara. Hiru makina birtual zerbitzari gisa erabiliko ditut, eta horietan banatutako FS GlusterFS ere zabalduko dut; Docker bolumen biltegiratze gisa erabiliko dut, adibidez, docker erregistroaren akats-tolerantea exekutatzeko. Exekutatu beharreko funtsezko osagaiak: Docker Registry, Postgresql, Redis, GitLab Swarm-en gainean GitLab Runner-erako laguntzarekin. Postgresql clustering-arekin abiaraziko dugu
GlusterFS zerbitzari guztietan zabaltzeko (node1, node2, node3 deitzen zaie), paketeak instalatu, suebakia gaitu eta beharrezko direktorioak sortu behar dituzu:
# 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
Instalatu ondoren, GlusterFS konfiguratzeko lanak nodo batetik jarraitu behar dira, adibidez, 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
Ondoren, ondoriozko bolumena muntatu behar duzu (komandoa zerbitzari guztietan exekutatu behar da):
# mount /srv/docker
Swarm modua zerbitzarietako batean konfiguratuta dago, liderra izango dena, gainerakoak klusterra sartu beharko dira, beraz, komandoa lehen zerbitzarian exekutatzeko emaitza besteetan kopiatu eta exekutatu beharko da.
Hasierako kluster konfigurazioa, komandoa exekutatzen dut node1-en:
# 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
Bigarren komandoaren emaitza kopiatzen dugu eta node2 eta node3-n exekutatzen dugu:
# docker swarm join --token SWMTKN-x-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-xxxxxxxxx xx.xx.xx.xx:2377
This node joined a swarm as a manager.
Une honetan, zerbitzarien aurretiazko konfigurazioa amaitu da, ekin gaitezen zerbitzuak konfiguratzen; exekutatu beharreko komandoak nodo1etik abiaraziko dira, kontrakoa zehaztu ezean.
Lehenik eta behin, sor ditzagun edukiontzientzako sareak:
# 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
Gero zerbitzariak markatzen ditugu, hau beharrezkoa da zerbitzu batzuk zerbitzariekin lotzeko:
# docker node update --label-add nodename=node1 node1
# docker node update --label-add nodename=node2 node2
# docker node update --label-add nodename=node3 node3
Ondoren, etcd datuak gordetzeko direktorioak sortzen ditugu, KV biltegiratzea, Traefik eta Stolon-entzat beharrezkoak direnak. Postgresql-en antzera, hauek zerbitzariei lotuta dauden edukiontziak izango dira, beraz, komando hau zerbitzari guztietan exekutatzen dugu:
# mkdir -p /srv/etcd
Ondoren, sortu fitxategi bat etcd konfiguratzeko eta erabili:
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
Denbora pixka bat igaro ondoren, etcd cluster-a martxan dagoela egiaztatuko dugu:
# 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
Postgresql-erako direktorioak sortzen ditugu, komandoa zerbitzari guztietan exekutatzen dugu:
# mkdir -p /srv/pgsql
Ondoren, sortu fitxategi bat Postgresql konfiguratzeko:
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
Sekretuak sortzen ditugu eta fitxategia erabiltzen dugu:
# </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
Denbora pixka bat igaro ondoren (ikus komandoaren irteera docker zerbitzua lszerbitzu guztiak martxan daudela) Postgresql klusterra hasieratzen dugu:
# 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 klusterren prest dagoen egiaztatzea:
# 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
Traefik konfiguratzen dugu edukiontzietarako sarbidea irekitzeko kanpotik:
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
Redis Cluster abiarazten dugu, horretarako biltegiratze direktorio bat sortzen dugu nodo guztietan:
# 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
Gehitu Docker Erregistroa:
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
Eta azkenik - 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
Klusterren eta zerbitzuen azken egoera:
# 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
Zer gehiago hobetu daiteke? Ziurtatu Traefik konfiguratzen duzula edukiontziak https-ren bidez exekutatzeko, gehitu tls enkriptatzea Postgresql eta Redis-entzat. Baina, oro har, dagoeneko garatzaileei eman diezaieke PoC gisa. Ikus ditzagun orain Dockerren alternatibak.
podman
Beste motor nahiko ezagun bat lekaren arabera multzokatutako edukiontziak martxan jartzeko (podak, elkarrekin zabaldutako edukiontzi taldeak). Docker-ek ez bezala, ez du inolako zerbitzurik behar edukiontziak exekutatzeko; lan guztiak libpod liburutegiaren bidez egiten dira. Go-n ere idatzita, OCI-rekin bateragarria den exekuzio-denbora behar da edukiontziak exekutatzeko, runC adibidez.
Podman-ekin lan egiteak, oro har, hori gogorarazten du Dockerrentzat, horrela egin dezakezun punturaino (probatu duten askok, artikulu honen egilea barne):
$ alias docker=podman
eta lanean jarraitu dezakezu. Oro har, Podman-en egoera oso interesgarria da, izan ere, Kubernetes-en lehen bertsioek Dockerrekin funtzionatzen bazuten, 2015 inguruan, edukiontzien mundua estandarizatu ondoren (OCI - Open Container Initiative) eta Docker-en containerd eta runC-tan banatu ondoren, Kubernetesen exekutatzeko Dockerren alternatiba bat garatzen ari da: CRI-O. Zentzu honetan Podman Dockerren alternatiba da, Kubernetesen printzipioetan eraikia, edukiontziak taldekatzea barne, baina proiektuaren helburu nagusia Docker estiloko edukiontziak zerbitzu gehigarririk gabe abian jartzea da. Arrazoi bistakoengatik, ez dago swarm modurik, garatzaileek argi esaten baitute kluster bat behar baduzu, hartu Kubernetes.
Instalazio-
Centos 7-n instalatzeko, aktibatu Extras biltegia eta, ondoren, dena instalatu komandoarekin:
# yum -y install podman
Beste ezaugarri batzuk
Podman-ek sistemarako unitateak sor ditzake, horrela zerbitzaria berrabiarazi ondoren edukiontziak abiarazteko arazoa konpontzeko. Gainera, systemd ontzian pid 1 bezala funtzionatzen duela deklaratu da. Ontziak eraikitzeko buildah tresna bereizi bat dago, hirugarrenen tresnak ere badaude - docker-compose-ren analogoak, Kubernetesekin bateragarriak diren konfigurazio-fitxategiak ere sortzen dituztenak, beraz, Podman-etik Kubernetes-erako trantsizioa ahalik eta gehien errazten da.
Podman-ekin lan egiten
Swarm modurik ez dagoenez (kluster bat behar izanez gero Kubernetesera aldatu behar dugu), edukiontzi bereizietan bilduko dugu.
Instalatu podman-compose:
# yum -y install python3-pip
# pip3 install podman-compose
Ondorioz, podman-en konfigurazio-fitxategia zertxobait desberdina da, beraz, adibidez, bolumenen atal bereizi bat zuzenean zerbitzuen atalera eraman behar izan dugu.
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
Emaitza:
# 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
Ikus dezagun zer sortzen duen systemd eta kubernetesentzat, horretarako pod-aren izena edo id-a aurkitu behar dugu:
# 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
Zoritxarrez, edukiontziak abiarazteaz gain, systemd-erako sortutako unitateak ez du beste ezer egiten (adibidez, edukiontzi zaharrak garbitzen ditu zerbitzu bat berrabiarazten denean), beraz, zuk zeuk idatzi beharko dituzu horrelakoak.
Printzipioz, Podman nahikoa da edukiontziak zer diren probatzeko, docker-compose-rako konfigurazio zaharrak transferitzeko eta, gero, Kubernetesera joateko, kluster bat behar baduzu, edo Dockerren alternatiba errazagoa lortzeko.
rkt
Proiektu
Peluxa
Gehiago
Findings
Kubernetes-en egoera oso interesgarria da: alde batetik, Docker-ekin kluster bat eraiki dezakezu (swirm moduan), eta horrekin bezeroentzako produktu-inguruneak ere exekutatu ditzakezu, hau bereziki egia da talde txikientzat (3-5 pertsona). , edo karga orokor txiki batekin, edo Kubernetes konfiguratzeko zailtasunak ulertzeko gogorik eza, karga handietarako barne.
Podman-ek ez du bateragarritasun osoa eskaintzen, baina abantaila garrantzitsu bat du: Kubernetesekin bateragarritasuna, tresna osagarriak barne (buildah eta beste). Hori dela eta, honela planteatuko dut lanerako tresna bat aukeratzera: talde txikietarako edo aurrekontu mugatu batekin - Docker (swirm modu posible batekin), neure burua lokaleko ostalari pertsonal batean garatzeko - Podman adiskideak eta beste guztientzat. - Kubernetes.
Ez nago ziur Dockerren egoera etorkizunean aldatuko ez denik, azken finean, aitzindariak dira, eta, gainera, pixkanaka-pixkanaka estandarizatzen ari dira, baina Podmanek, dituen gabezi guztiengatik (Linux-en bakarrik funtzionatzen du, clustering gabe, muntaia eta beste ekintza batzuk hirugarrenen irtenbideak dira) etorkizuna argiagoa da, beraz, guztioi gonbidatzen dut aurkikuntza hauek iruzkinetan eztabaidatzera.
PS Abuztuaren 3an "
Erreserbaren prezioa kaleratu aurretik: 5000 RUB. Docker Bideo Ikastaroaren programa ikus dezakezu
Iturria: www.habr.com