TL;DR: En Iwwerbléckguide fir Kaderen ze vergläichen fir Uwendungen a Container ze lafen. D'Kapazitéite vum Docker an aner ähnlech Systemer ginn berücksichtegt.
Eng kleng Geschicht vu wou et alles hierkënnt
Geschicht
Déi éischt bekannte Method fir eng Applikatioun ze isoléieren ass Chroot. De Systemruff mam selwechten Numm garantéiert datt de Root-Verzeichnis geännert gëtt - also garantéiert datt de Programm deen et genannt huet nëmmen Zougang zu Dateien an deem Verzeichnis huet. Awer wann e Programm intern root Privilegien gëtt, kann et potenziell de Chroot "entkommen" an Zougang zum Haaptbetribssystem kréien. Zousätzlech fir de Root-Verzeichnis z'änneren, sinn aner Ressourcen (RAM, Prozessor), souwéi Netzzougang net limitéiert.
Déi nächst Method ass e vollwäertege Betribssystem an engem Container ze starten, mat de Mechanismen vum Betribssystemkär. Dës Method gëtt anescht a verschiddene Betribssystemer genannt, awer d'Essenz ass d'selwecht - e puer onofhängeg Betribssystemer lancéieren, jidderee leeft deeselwechte Kernel op deem den Haaptbetribssystem leeft. Dozou gehéieren FreeBSD Jails, Solaris Zonen, OpenVZ an LXC fir Linux. D'Isolatioun gëtt net nëmmen duerch Disk Space gesuergt, awer och duerch aner Ressourcen; besonnesch all Container kann Aschränkungen op Prozessor Zäit, RAM an Netzwierkbandbreedung hunn. Am Verglach mam Chroot ass de Container méi schwéier ze verloossen, well de Superuser am Container nëmmen Zougang zum Inhalt vum Container huet, awer wéinst der Bedierfnes fir de Betribssystem am Container um neiste Stand ze halen an d'Benotzung vun eelere Versiounen vu Kernelen (relevant fir Linux, a mannerem Ausmooss FreeBSD), gëtt et eng net Null d'Wahrscheinlechkeet fir de Kernelisolatiounssystem ze "duerchbriechen" an Zougang zum Haaptbetribssystem ze kréien.
Amplaz e vollwäertege Betribssystem an engem Container ze lancéieren (mat engem Initialiséierungssystem, Package Manager, asw.), kënnt Dir Applikatiounen direkt starten, den Haapt Saach ass d'Applikatiounen esou eng Chance ze bidden (d'Präsenz vun den néidege Bibliothéiken an aner Dateien). Dës Iddi huet als Basis fir containeriséierter Applikatiounsvirtualiséierung gedéngt, dee prominentsten a bekanntste Vertrieder vun deem Docker ass. Am Verglach mat fréiere Systemer, méi flexibel Isolatiounsmechanismen, gekoppelt mat agebauter Ënnerstëtzung fir virtuell Netzwierker tëscht Container an Applikatiounszoustand Tracking am Container, hunn d'Fäegkeet gefouert fir en eenzegt kohärent Ëmfeld aus enger grousser Zuel vu kierperleche Servere fir Container ze bauen - ouni de Besoin fir manuell Ressource Gestioun.
Docker
Docker ass déi bekanntst Applikatioun Containeriséierungssoftware. Geschriwwen an der Go Sprooch, benotzt et d'Standardfeatures vum Linux Kernel - cgroups, Namespaces, Capabilities, etc., souwéi Aufs Dateisystemer an anerer wéi dat fir Disk Space ze spueren.
Source: Wikimedia
Architektur
Virun Versioun 1.11 huet Docker als eenzegen Service geschafft, deen all Operatioune mat Container duerchgefouert huet: Biller fir Container eroflueden, Container starten, API-Ufroen veraarbecht. Vun der Versioun 1.11 un, gouf Docker an e puer Deeler opgedeelt, déi matenee interagéieren: Containerd, fir de ganze Liewenszyklus vu Container ze veraarbechten (Disc Plaz verdeelen, Biller eroflueden, mam Netz schaffen, starten, installéieren an iwwerwaachen den Zoustand vun de Container) an runC, d'Container-Ausféierungsëmfeld, baséiert op der Benotzung vu cgroups an aner Features vum Linux Kernel. Den Docker Service selwer bleift, awer elo déngt et nëmmen fir API Ufroen ze veraarbecht, déi op Containerd iwwersat ginn.
Installatioun a Konfiguratioun
Mäi Liiblings Wee fir Docker z'installéieren ass Docker-Maschinn, déi, nieft dem direkten Installatioun an der Konfiguratioun vum Docker op Fernserveren (inklusiv verschidde Wolleken), et méiglech mécht mat Dateiesystemer vu Fernserveren ze schaffen an och verschidde Kommandoen auszeféieren.
Wéi och ëmmer, zënter 2018 ass de Projet kaum entwéckelt ginn, sou datt mir et op de Standard Manéier fir déi meescht Linux Verdeelungen installéieren - e Repository derbäisetzen an déi néideg Packagen installéieren.
Dës Method gëtt och fir automatiséiert Installatioun benotzt, zum Beispill mat Ansible oder aner ähnlech Systemer, awer ech wäert et net an dësem Artikel betruechten.
D'Installatioun gëtt op Centos 7 duerchgefouert, ech benotze eng virtuell Maschinn als Server, fir z'installéieren just d'Befehle hei ënnen:
# 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
No der Installatioun musst Dir de Service starten an en an de Startup setzen:
# systemctl enable docker
# systemctl start docker
# firewall-cmd --zone=public --add-port=2377/tcp --permanent
Zousätzlech kënnt Dir en Docker-Grupp erstellen, deem seng Benotzer fäeg sinn ouni Sudo mam Docker ze schaffen, Logbicher opzestellen, Zougang zu der API vu baussen z'erméiglechen, a vergiesst net d'Firewall méi präzis ze konfiguréieren (alles wat net erlaabt ass) ass an de Beispiller uewen an ënnen verbueden - ech hunn dëst fir Simplicitéit a Kloerheet ausgelooss), awer ech ginn net méi an Detailer hei.
Aner Funktiounen
Zousätzlech zu der uewen ernimmt Docker Maschinn gëtt et och Docker Registry, e Tool fir Biller fir Container ze späicheren, souwéi Docker compose, e Tool fir d'Deployment vun Uwendungen an Containeren ze automatiséieren, YAML Dateien gi benotzt fir Container ze bauen an ze konfiguréieren an aner Zesummenhang Saachen (Zum Beispill, Netzwierker, persistent Fichier Systemer fir Stockage Daten).
Et kann och benotzt ginn fir conveyors fir CICD ze organiséieren. Eng aner interessant Feature funktionnéiert am Clustermodus, de sougenannte Schwarmmodus (virun der Versioun 1.12 war et als Docker-Schwarm bekannt), wat Iech erlaabt eng eenzeg Infrastruktur vu verschiddene Serveren ze sammelen fir Container ze lafen. Et gëtt Ënnerstëtzung fir e virtuellt Netzwierk uewen op all Server, et gëtt en agebaute Lastbalancer, souwéi Ënnerstëtzung fir Geheimnisser fir Container.
YAML Dateien aus Docker compose, mat klengen Ännerungen, kënne fir sou Cluster benotzt ginn, komplett automatiséiert den Ënnerhalt vu klengen a mëttelgrousse Cluster fir verschidden Zwecker. Fir grouss Stärekéip ass Kubernetes léiwer well d'Ënnerhaltskäschte vum Schwarmmodus kënnen déi vu Kubernetes iwwerschreiden. Zousätzlech zu runC kënnt Dir zum Beispill als Container Ausféierungsëmfeld installéieren
Schafft mat Docker
No der Installatioun an der Konfiguratioun probéieren mir e Cluster ze sammelen an deem mir GitLab an Docker Registry fir d'Entwécklungsteam ofsetzen. Ech wäert dräi virtuell Maschinnen als Server benotzen, op deenen ech zousätzlech déi verdeelt FS GlusterFS ofsetzen; Ech wäert et als Docker Volumen Späichere benotzen, zum Beispill, fir eng Feelertolerant Versioun vum Docker Registry ze lafen. Schlësselkomponenten fir ze lafen: Docker Registry, Postgresql, Redis, GitLab mat Ënnerstëtzung fir GitLab Runner uewen op Swarm. Mir starten Postgresql mat Clustering
Fir GlusterFS op all Server z'installéieren (si ginn node1, node2, node3 genannt), musst Dir Packagen installéieren, d'Firewall aktivéieren an déi néideg Verzeichnisser erstellen:
# 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
No der Installatioun muss d'Aarbecht un der Konfiguratioun vu GlusterFS vun engem Node weidergefouert ginn, zum Beispill 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
Da musst Dir de resultéierende Volume montéieren (de Kommando muss op all Server ausgefouert ginn):
# mount /srv/docker
De Schwarmmodus ass op engem vun de Serveren konfiguréiert, deen de Leader wäert sinn, de Rescht muss de Cluster bäitrieden, sou datt d'Resultat vum Kommando op den éischte Server muss kopéiert an op deenen aneren ausgefouert ginn.
Initial Cluster Setup, ech lafen de Kommando op 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
Mir kopéieren d'Resultat vum zweete Kommando an ausféieren et op Node2 an Node3:
# docker swarm join --token SWMTKN-x-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-xxxxxxxxx xx.xx.xx.xx:2377
This node joined a swarm as a manager.
Zu dësem Zäitpunkt ass déi virleefeg Konfiguratioun vun de Serveren ofgeschloss, loosst eis weidergoen fir d'Servicer opzestellen; d'Befehle fir auszeféieren ginn vum Node1 gestart, wann net anescht uginn.
Als éischt, loosst eis Netzwierker fir Container erstellen:
# 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
Da markéiere mir d'Serveren, dëst ass néideg fir e puer Servicer un d'Serveren ze binden:
# docker node update --label-add nodename=node1 node1
# docker node update --label-add nodename=node2 node2
# docker node update --label-add nodename=node3 node3
Als nächst erstelle mir Verzeichnisser fir etcd Daten ze späicheren, KV Späicheren, déi fir Traefik a Stolon gebraucht ginn. Ähnlech wéi Postgresql, wäerten dës Container mat Serveren gebonne sinn, sou datt mir dëse Kommando op all Server lafen:
# mkdir -p /srv/etcd
Als nächst erstellt eng Datei fir etcd ze konfiguréieren a benotzt se:
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
No enger Zäit kontrolléiere mir datt den etcd Cluster erop ass:
# 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
Mir erstellen Verzeichnisser fir Postgresql, fuert de Kommando op all Server aus:
# mkdir -p /srv/pgsql
Als nächst erstellt eng Datei fir Postgresql ze konfiguréieren:
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
Mir generéieren Geheimnisser a benotzen d'Datei:
# </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
No enger Zäit (kuckt d'Ausgab vum Kommando docker service lsdatt all Servicer erop sinn) initialiséieren mir de Postgresql Cluster:
# 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
Iwwerpréift d'Bereetschaft vum Postgresql Cluster:
# 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
Mir konfiguréieren Traefik fir Zougang zu Container vu baussen opzemaachen:
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
Mir starten Redis Cluster, fir dëst ze maachen erstellen mir e Späicherverzeechnes op all Noden:
# 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
Add Docker Registry:
06registry.yml
version: '3.7'
services:
registry:
image: registry:2.6
networks:
- traefik
volumes:
- registry_data:/var/lib/registry
deploy:
replicas: 1
placement:
constraints: [node.role == manager]
restart_policy:
condition: on-failure
labels:
- traefik.enable=true
- traefik.http.routers.registry.rule=Host(`registry.example.com`)
- traefik.http.services.registry.loadbalancer.server.port=5000
- traefik.docker.network=traefik
volumes:
registry_data:
driver: local
driver_opts:
type: none
o: bind
device: "/srv/docker/registry"
networks:
traefik:
external: true
# mkdir /srv/docker/registry
# docker stack deploy --compose-file 06registry.yml registry
A schliisslech - 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
Den definitiven Zoustand vum Cluster a Servicer:
# 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
Wat kann nach verbessert ginn? Gitt sécher Traefik ze konfiguréieren fir Container iwwer https ze lafen, add tls Verschlësselung fir Postgresql a Redis. Awer am Allgemengen kann et scho fir Entwéckler als PoC ginn. Loosst eis elo Alternativen zum Docker kucken.
podman
En anere zimmlech bekannte Motor fir Container ze bedreiwen, gruppéiert vu Pods (Pods, Gruppe vu Container déi zesummen agesat ginn). Am Géigesaz zu Docker erfuerdert et kee Service fir Container ze lafen; all Aarbecht gëtt duerch d'libpod Bibliothéik gemaach. Och am Go geschriwwen, erfuerdert eng OCI-kompatibel Runtime fir Container ze lafen, wéi runC.
Mat Podman ze schaffen erënnert allgemeng un dat fir Docker, bis zum Punkt datt Dir et esou maache kënnt (wéi gesot vu villen déi et probéiert hunn, och den Auteur vun dësem Artikel):
$ alias docker=podman
an Dir kënnt weider schaffen. Am Allgemengen ass d'Situatioun mam Podman ganz interessant, well wann fréi Versioune vu Kubernetes mat Docker geschafft hunn, dann ëm 2015, no der Standardiséierung vun der Welt vu Container (OCI - Open Container Initiative) an der Divisioun vum Docker an Containerd a RunC, eng Alternativ zum Docker fir a Kubernetes ze lafen ass entwéckelt: CRI-O. Podman an dëser Hisiicht ass eng Alternativ zu Docker, gebaut op de Prinzipien vu Kubernetes, inklusiv Gruppéierungsbehälter, awer den Haaptzweck vum Projet ass Docker-Stil Container ouni zousätzlech Servicer ze lancéieren. Aus offensichtleche Grënn gëtt et kee Schwarmmodus, well d'Entwéckler kloer soen datt wann Dir e Stärekoup braucht, huelt Kubernetes.
Kader
Fir op Centos 7 z'installéieren, aktivéiert just den Extras Repository, an installéiert dann alles mam Kommando:
# yum -y install podman
Aner Funktiounen
Podman kann Unitéiten fir Systemd generéieren, sou datt de Problem vum Startbehälter no engem Server Neistart léist. Zousätzlech gëtt systemd deklaréiert fir richteg als Pid 1 am Container ze schaffen. Et gëtt e separat buildah-Tool fir Container ze bauen, et ginn och Drëtt-Partei-Tools - Analoge vum Docker-compose, déi och Konfiguratiounsdateien generéieren, déi mat Kubernetes kompatibel sinn, sou datt den Iwwergank vu Podman op Kubernetes sou vill wéi méiglech vereinfacht gëtt.
Schafft mat Podman
Well et kee Schwarmmodus gëtt (mir sollen op Kubernetes wiesselen wann e Cluster gebraucht gëtt), sammele mir et an getrennten Container.
Installéiert podman-compose:
# yum -y install python3-pip
# pip3 install podman-compose
Déi resultéierend Konfiguratiounsdatei fir Podman ass liicht anescht, also hu mir zum Beispill eng separat Volumen Sektioun direkt an d'Sektioun mat Servicer réckelen.
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
Resultat:
# 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
Loosst eis kucken wat et fir systemd a kubernetes generéiert, dofir musse mir den Numm oder d'ID vum Pod erausfannen:
# 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: {}
Systemd:
# podman generate systemd 71fc2b2a5c63
# pod-71fc2b2a5c6346f0c1c86a2dc45dbe78fa192ea02aac001eb8347ccb8c043c26.service
# autogenerated by Podman 1.6.4
# Thu Jul 29 15:23:28 EDT 2020
[Unit]
Description=Podman pod-71fc2b2a5c6346f0c1c86a2dc45dbe78fa192ea02aac001eb8347ccb8c043c26.service
Documentation=man:podman-generate-systemd(1)
Requires=container-781c0103c94aaa113c17c58d05ddabf8df4bf39707b664abcf17ed2ceff467d3.service container-da53da946c01449f500aa5296d9ea6376f751948b17ca164df438b7df6607864.service
Before=container-781c0103c94aaa113c17c58d05ddabf8df4bf39707b664abcf17ed2ceff467d3.service container-da53da946c01449f500aa5296d9ea6376f751948b17ca164df438b7df6607864.service
[Service]
Restart=on-failure
ExecStart=/usr/bin/podman start db40ab8bf84bf35141159c26cb6e256b889c7a98c0418eee3c4aa683c14fccaa
ExecStop=/usr/bin/podman stop -t 10 db40ab8bf84bf35141159c26cb6e256b889c7a98c0418eee3c4aa683c14fccaa
KillMode=none
Type=forking
PIDFile=/var/run/containers/storage/overlay-containers/db40ab8bf84bf35141159c26cb6e256b889c7a98c0418eee3c4aa683c14fccaa/userdata/conmon.pid
[Install]
WantedBy=multi-user.target
# container-da53da946c01449f500aa5296d9ea6376f751948b17ca164df438b7df6607864.service
# autogenerated by Podman 1.6.4
# Thu Jul 29 15:23:28 EDT 2020
[Unit]
Description=Podman container-da53da946c01449f500aa5296d9ea6376f751948b17ca164df438b7df6607864.service
Documentation=man:podman-generate-systemd(1)
RefuseManualStart=yes
RefuseManualStop=yes
BindsTo=pod-71fc2b2a5c6346f0c1c86a2dc45dbe78fa192ea02aac001eb8347ccb8c043c26.service
After=pod-71fc2b2a5c6346f0c1c86a2dc45dbe78fa192ea02aac001eb8347ccb8c043c26.service
[Service]
Restart=on-failure
ExecStart=/usr/bin/podman start da53da946c01449f500aa5296d9ea6376f751948b17ca164df438b7df6607864
ExecStop=/usr/bin/podman stop -t 10 da53da946c01449f500aa5296d9ea6376f751948b17ca164df438b7df6607864
KillMode=none
Type=forking
PIDFile=/var/run/containers/storage/overlay-containers/da53da946c01449f500aa5296d9ea6376f751948b17ca164df438b7df6607864/userdata/conmon.pid
[Install]
WantedBy=multi-user.target
# container-781c0103c94aaa113c17c58d05ddabf8df4bf39707b664abcf17ed2ceff467d3.service
# autogenerated by Podman 1.6.4
# Thu Jul 29 15:23:28 EDT 2020
[Unit]
Description=Podman container-781c0103c94aaa113c17c58d05ddabf8df4bf39707b664abcf17ed2ceff467d3.service
Documentation=man:podman-generate-systemd(1)
RefuseManualStart=yes
RefuseManualStop=yes
BindsTo=pod-71fc2b2a5c6346f0c1c86a2dc45dbe78fa192ea02aac001eb8347ccb8c043c26.service
After=pod-71fc2b2a5c6346f0c1c86a2dc45dbe78fa192ea02aac001eb8347ccb8c043c26.service
[Service]
Restart=on-failure
ExecStart=/usr/bin/podman start 781c0103c94aaa113c17c58d05ddabf8df4bf39707b664abcf17ed2ceff467d3
ExecStop=/usr/bin/podman stop -t 10 781c0103c94aaa113c17c58d05ddabf8df4bf39707b664abcf17ed2ceff467d3
KillMode=none
Type=forking
PIDFile=/var/run/containers/storage/overlay-containers/781c0103c94aaa113c17c58d05ddabf8df4bf39707b664abcf17ed2ceff467d3/userdata/conmon.pid
[Install]
WantedBy=multi-user.target
Leider, ausser d'Behälter lancéieren, mécht déi generéiert Eenheet fir systemd näischt anescht (zum Beispill al Container botzen wann esou e Service nei gestart gëtt), also musst Dir esou Saachen selwer schreiwen.
Am Prinzip ass Podman genuch fir ze probéieren wat Container sinn, al Konfiguratioune fir Docker-compose ze transferéieren, an dann a Richtung Kubernetes réckelen, wann Dir e Cluster braucht, oder eng méi einfach ze benotzen Alternativ zum Docker kréien.
rkt
De Projet
Plaatz
Méi
Conclusiounen
D'Situatioun mat Kubernetes ass ganz interessant: Engersäits, mat Docker kënnt Dir e Cluster bauen (am Schwarmmodus), mat deem Dir souguer Produktëmfeld fir Clienten ausféiere kënnt, dëst ass besonnesch wouer fir kleng Teams (3-5 Leit) , oder mat enger klenger Gesamtbelaaschtung, oder Mangel u Wonsch fir d'Intricacies vun der Opstellung vu Kubernetes ze verstoen, och fir héich Lasten.
Podman bitt keng voll Kompatibilitéit, awer et huet ee wichtege Virdeel - Kompatibilitéit mat Kubernetes, och zousätzlech Tools (buildah an anerer). Dofir wäert ech d'Wiel vun engem Tool fir Aarbecht wéi follegt Approche: fir kleng Équipen, oder mat engem limitéierten Budget - Docker (mat engem méigleche Schwarmmodus), fir mech selwer op engem perséinleche localhost z'entwéckelen - Podman Komeroden, a fir all aner - Kubernetes.
Ech sinn net sécher datt d'Situatioun mam Docker sech an Zukunft net ännert, schliisslech si se Pionéier, a ginn och lues a lues standardiséiert, Schrëtt fir Schrëtt, awer Podman, fir all seng Mängel (schafft nëmmen op Linux, kee Clustering, Assemblée an aner Aktiounen sinn Drëtt Partei Léisungen) d'Zukunft ass méi kloer, also ech invitéieren jiddereen dës Erkenntnisser an de Kommentaren ze diskutéieren.
PS Den 3. August lancéiere mir “
Pre-Order Präis virum Verëffentlechung: RUB 5000. Dir kënnt den Docker Video Course Programm kucken
Source: will.com