TL;DR: una guia general per comparar marcs per executar aplicacions en contenidors. Es tindran en compte les capacitats de Docker i altres sistemes similars.

Una petita història d'on va sortir tot
Història
El primer mètode conegut per aïllar una aplicació és chroot. La trucada del sistema del mateix nom garanteix que es canvia el directori arrel, assegurant així que el programa que l'ha cridat només té accés als fitxers d'aquest directori. Però si un programa té privilegis d'arrel internament, pot "escapar" del chroot i accedir al sistema operatiu principal. A més, a més de canviar el directori arrel, altres recursos (RAM, processador), així com l'accés a la xarxa, no estan limitats.
El següent mètode és executar un sistema operatiu complet dins d'un contenidor, utilitzant els mecanismes del nucli del sistema operatiu. Aquest mètode té noms diferents en diferents sistemes operatius, però l'essència és la mateixa: executar diversos sistemes operatius independents, cadascun executant el mateix nucli que el sistema operatiu principal. Això inclou FreeBSD Jails, Solaris Zones, OpenVZ i LXC per a LinuxL'aïllament no només es proporciona per l'espai en disc, sinó també per altres recursos; en particular, cada contenidor pot tenir límits de temps de CPU, RAM i amplada de banda de xarxa. En comparació amb chroot, sortir d'un contenidor és més difícil, ja que el superusuari del contenidor només té accés als components interns del contenidor. Tanmateix, a causa de la necessitat de mantenir el sistema operatiu dins del contenidor actualitzat i l'ús de versions del nucli més antigues (rellevant per a Linux, en menor mesura FreeBSD) hi ha una probabilitat diferent de zero de "trencar" el sistema d'aïllament del nucli i obtenir accés al sistema operatiu principal.
En lloc de llançar un sistema operatiu complet en un contenidor (amb un sistema d'inicialització, gestor de paquets, etc.), podeu llançar aplicacions immediatament, el més important és oferir a les aplicacions aquesta oportunitat (la presència de les biblioteques necessàries). i altres fitxers). Aquesta idea va servir de base per a la virtualització d'aplicacions en contenidors, el representant més destacat i conegut de les quals és Docker. En comparació amb els sistemes anteriors, els mecanismes d'aïllament més flexibles, juntament amb el suport integrat per a xarxes virtuals entre contenidors i el seguiment de l'estat de l'aplicació dins del contenidor, van donar com a resultat la capacitat de crear un únic entorn coherent a partir d'un gran nombre de servidors físics per executar contenidors. sense necessitat de gestió manual de recursos.
estibador
Docker és el programari de contenidorització d'aplicacions més conegut. Està escrit en el llenguatge Go i utilitza les capacitats natives del nucli. Linux — grups de control, espais de noms, capacitats, etc., així com sistemes de fitxers Aufs i altres similars per estalviar espai al disc.

Font: wikimedia
arquitectura
Abans de la versió 1.11, Docker funcionava com un únic servei que gestionava totes les operacions dels contenidors: la descàrrega d'imatges dels contenidors, el llançament de contenidors i la gestió de sol·licituds de l'API. A partir de la versió 1.11, Docker es va dividir en diverses parts que interactuaven: containerd, que gestiona tot el cicle de vida del contenidor (assignació de disc, descàrrega d'imatges, creació de xarxes, llançament, instal·lació i supervisió de l'estat del contenidor), i runC, un entorn d'execució de contenidors basat en grups de control i altres funcions del nucli. LinuxEl servei Docker en si mateix es manté, però ara només serveix per processar les sol·licituds API transmeses a containerd.

Instal·lació i configuració
La meva manera preferida d'instal·lar docker és docker-machine, que, a més d'instal·lar i configurar directament docker en servidors remots (inclosos diversos núvols), permet treballar amb sistemes de fitxers de servidors remots i també pot executar diverses ordres.
No obstant això, des del 2018 el projecte gairebé no s'ha desenvolupat, així que l'instal·larem utilitzant el mètode estàndard per a la majoria de distribucions. Linux mètode: afegint un repositori i instal·lant els paquets necessaris.
Aquest mètode també s'utilitza per a la instal·lació automatitzada, per exemple utilitzant Ansible o altres sistemes similars, però no ho tindré en compte en aquest article.
La instal·lació es durà a terme el Centos 7, utilitzaré una màquina virtual com a servidor, per a la instal·lació n'hi ha prou amb executar les ordres següents:
# 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.ioDesprés de la instal·lació, heu d'iniciar el servei i posar-lo a l'inici:
# systemctl enable docker
# systemctl start docker
# firewall-cmd --zone=public --add-port=2377/tcp --permanentA més, podeu crear un grup docker, els usuaris del qual podran treballar amb docker sense sudo, configurar el registre, habilitar l'accés a l'API des de l'exterior i no oblideu configurar el tallafoc amb més precisió (tot el que no estigui permès). està prohibit als exemples anteriors i següents; ho vaig ometre per simplicitat i claredat), però no entraré en més detalls aquí.
Altres característiques
A més de la màquina docker esmentada anteriorment, també hi ha el registre docker, una eina per emmagatzemar imatges per a contenidors, així com la composició docker, una eina per automatitzar el desplegament d'aplicacions en contenidors, els fitxers YAML s'utilitzen per construir i configurar contenidors. i altres coses relacionades (per exemple, xarxes, sistemes de fitxers persistents per a l'emmagatzematge de dades).
També es pot utilitzar per organitzar transportadors per CICD. Una altra característica interessant és treballar en mode clúster, l'anomenat mode swarm (abans de la versió 1.12 es coneixia com a docker swarm), que permet muntar una única infraestructura a partir de diversos servidors per executar contenidors. Hi ha suport per a una xarxa virtual a la part superior de tots els servidors, hi ha un equilibrador de càrrega integrat, així com suport per a secrets per als contenidors.
Els fitxers YAML de Docker Compose, amb petites modificacions, es poden utilitzar per a aquests clústers, automatitzant completament el manteniment de clústers petits i mitjans per a diversos propòsits. Per a clústers grans, Kubernetes és preferible perquè els costos de manteniment del mode eixam poden superar els de Kubernetes. A més de runC, podeu instal·lar, per exemple, com a entorn d'execució del contenidor
Treballant amb Docker
Després de la instal·lació i configuració, intentarem muntar un clúster en el qual desplegarem GitLab i Docker Registry per a l'equip de desenvolupament. Faré servir tres màquines virtuals com a servidors, en els quals, addicionalment, desplegaré el FS GlusterFS distribuït; el faré servir com a emmagatzematge de volums docker, per exemple, per executar una versió tolerant a errors del registre docker. Components clau per executar: Docker Registry, Postgresql, Redis, GitLab amb suport per a GitLab Runner a la part superior de Swarm. Llançarem Postgresql amb clustering , de manera que no cal que utilitzeu GlusterFS per emmagatzemar dades de Postgresql. La resta de dades crítiques s'emmagatzemaran a GlusterFS.
Per implementar GlusterFS a tots els servidors (s'anomenen node1, node2, node3), heu d'instal·lar paquets, habilitar el tallafoc i crear els directoris necessaris:
# 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/fstabDesprés de la instal·lació, el treball en la configuració de GlusterFS s'ha de continuar des d'un node, per exemple 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 dockerA continuació, heu de muntar el volum resultant (l'ordre s'ha d'executar a tots els servidors):
# mount /srv/dockerEl mode eixam es configura en un dels servidors, que serà el Leader, la resta s'haurà d'unir al clúster, per tant caldrà copiar i executar en els altres el resultat d'executar l'ordre al primer servidor.
Configuració inicial del clúster, executo l'ordre al 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 managerCopiem el resultat de la segona ordre i l'executem al node2 i al node3:
# docker swarm join --token SWMTKN-x-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-xxxxxxxxx xx.xx.xx.xx:2377
This node joined a swarm as a manager.En aquest punt, s'ha completat la configuració preliminar dels servidors, procedim a la configuració dels serveis; les ordres a executar s'executaran des del node1, tret que s'especifiqui el contrari.
En primer lloc, creem xarxes per als contenidors:
# 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 gitlabDesprés marquem els servidors, això és necessari per vincular alguns serveis als servidors:
# docker node update --label-add nodename=node1 node1
# docker node update --label-add nodename=node2 node2
# docker node update --label-add nodename=node3 node3A continuació, creem directoris per emmagatzemar dades etcd, emmagatzematge KV, que és necessari per a Traefik i Stolon. De manera similar a Postgresql, aquests seran contenidors lligats a servidors, de manera que executem aquesta ordre a tots els servidors:
# mkdir -p /srv/etcdA continuació, creeu un fitxer per configurar etcd i utilitzeu-lo:
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 etcdDesprés d'un temps, comprovem que el clúster etcd estigui activat:
# 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 healthyCreem directoris per a Postgresql, executem l'ordre a tots els servidors:
# mkdir -p /srv/pgsqlA continuació, creeu un fitxer per configurar 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: trueGenerem secrets i fem servir el fitxer:
# </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 pgsqlDesprés d'un temps (vegeu la sortida de l'ordre servei docker lsque tots els serveis estiguin activats) inicialitzem el clúster 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 initComprovació de la preparació del clúster 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
Configurem traefik per obrir l'accés als contenidors des de l'exterior:
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 traefikLlencem Redis Cluster, per fer-ho creem un directori d'emmagatzematge a tots els nodes:
# 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 <<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 redisAfegeix el registre Docker:
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 registryI finalment - 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 gitlabEstat final del clúster i dels serveis:
# 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/tcpQuè més es pot millorar? Assegureu-vos de configurar Traefik per executar contenidors sobre https, afegiu el xifratge tls per a Postgresql i Redis. Però, en general, ja es pot donar als desenvolupadors com a PoC. Vegem ara les alternatives a Docker.
Podman
Un altre motor força conegut per fer funcionar contenidors agrupats per beines (pods, grups de contenidors desplegats junts). A diferència de Docker, no requereix cap servei per executar contenidors; tot el treball es fa a través de la biblioteca libpod. També escrit a Go, requereix un temps d'execució compatible amb OCI per executar contenidors, com ara runC.

Treballar amb Podman en general recorda això de Docker, fins al punt que podeu fer-ho així (com diuen molts que ho han provat, inclòs l'autor d'aquest article):
$ alias docker=podmani pots continuar treballant. En general, la situació amb Podman és molt interessant, perquè si les primeres versions de Kubernetes funcionaven amb Docker, llavors cap al 2015, després de l'estandardització del món dels contenidors (OCI - Open Container Initiative) i la divisió de Docker en containerd i runC, s'ha desenvolupat una alternativa a Docker per executar-se a Kubernetes: CRI-O. Podman en aquest sentit és una alternativa a Docker, basada en els principis de Kubernetes, inclosa l'agrupació de contenidors, però l'objectiu principal del projecte és llançar contenidors a l'estil Docker sense serveis addicionals. Per raons òbvies, no hi ha mode eixam, ja que els desenvolupadors diuen clarament que si necessiteu un clúster, preneu Kubernetes.
Instal · lació
Per a la instal·lació en Centos 7, només cal activar el repositori d'Extres i instal·lar-ho tot amb l'ordre:
# yum -y install podmanAltres característiques
Podman pot generar unitats per a systemd, resolent així el problema d'iniciar contenidors després d'un reinici del servidor. A més, es declara que systemd funciona correctament com a pid 1 al contenidor. Hi ha una eina de construcció separada per construir contenidors, també hi ha eines de tercers: anàlegs de docker-compose, que també generen fitxers de configuració compatibles amb Kubernetes, de manera que la transició de Podman a Kubernetes es simplifica al màxim.
Treballant amb Podman
Com que no hi ha mode eixam (se suposa que hem de canviar a Kubernetes si cal un clúster), el recollirem en contenidors separats.
Instal·leu podman-compose:
# yum -y install python3-pip
# pip3 install podman-composeEl fitxer de configuració resultant per a podman és lleugerament diferent, de manera que, per exemple, hem hagut de moure una secció de volums independent directament a la secció amb serveis.
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 upResultat:
# 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_1Vegem què genera per a systemd i kubernetes, per això hem d'esbrinar el nom o id del pod:
# 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: {}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.targetMalauradament, a part de llançar contenidors, la unitat generada per a systemd no fa res més (per exemple, netejar contenidors antics quan es reinicia aquest servei), de manera que haureu d'escriure aquestes coses vosaltres mateixos.
En principi, Podman n'hi ha prou per provar què són els contenidors, transferir configuracions antigues per a docker-compose i després avançar cap a Kubernetes, si necessiteu un clúster, o obtenir una alternativa més fàcil d'utilitzar a Docker.
rkt
Projecte fa uns sis mesos a causa del fet que RedHat el va comprar, així que no m'hi aprofundiré amb més detall. En general, va deixar una molt bona impressió, però en comparació amb Docker i sobretot Podman, sembla una combinació. També hi havia una distribució CoreOS construïda a sobre de rkt (encara que originalment tenien Docker), però això també va acabar en suport després de la compra de RedHat.
Flash
Més , l'autor del qual només volia construir i executar contenidors. A jutjar per la documentació i el codi, l'autor no va seguir els estàndards, sinó que simplement va decidir escriure la seva pròpia implementació, cosa que, en principi, va fer.
Troballes
La situació amb Kubernetes és molt interessant: d'una banda, amb Docker es pot construir un clúster (en mode eixam), amb el qual fins i tot es poden executar entorns de producte per a clients, això és especialment cert per a equips petits (3-5 persones). , o amb una petita càrrega general o manca de ganes d'entendre les complexitats de la configuració de Kubernetes, fins i tot per a càrregues elevades.
Podman no ofereix una compatibilitat total, però té un avantatge important: la compatibilitat amb Kubernetes, incloses eines addicionals (buildah i altres). Per tant, abordaré l'elecció d'una eina per treballar de la següent manera: per a equips petits o amb un pressupost limitat: Docker (amb un possible mode d'eixam), per desenvolupar-me en un host local personal: camarades Podman i per a tots els altres. - Kubernetes.
No estic segur que la situació amb Docker no canviï en el futur, al cap i a la fi, són pioners i, a poc a poc, s'estan estandarditzant, però Podman, malgrat totes les seves deficiències (treballant només en Linux, no es duen a terme accions de clústering, assemblatge ni altres accions per part de solucions de tercers), el futur és més clar, així que convido a tothom a discutir aquestes troballes als comentaris.
PS El 3 d'agost estrenen “", on podreu conèixer més sobre la seva obra. Analitzarem totes les seves eines: des d'abstraccions bàsiques fins a paràmetres de xarxa, matisos de treball amb diversos sistemes operatius i llenguatges de programació. Us familiaritzareu amb la tecnologia i entendreu on i la millor manera d'utilitzar Docker. També compartirem casos de bones pràctiques.
Preu de reserva abans del llançament: 5000 RUB. Podeu veure el programa del curs de vídeo Docker .
Font: www.habr.com
