TL;DR: Isang pangkalahatang-ideya na gabay sa paghahambing ng mga framework para sa pagpapatakbo ng mga application sa mga container. Isasaalang-alang ang mga kakayahan ng Docker at iba pang katulad na mga sistema.
Isang maliit na kasaysayan kung saan nanggaling ang lahat
Kuwento
Ang unang kilalang paraan upang ihiwalay ang isang application ay chroot. Ang system call na may parehong pangalan ay nagbibigay ng pagbabago sa root directory - kaya nagbibigay ng access sa program na tumawag dito, access lang sa mga file sa loob ng directory na ito. Ngunit kung ang programa ay bibigyan ng mga karapatan ng superuser sa loob, maaari itong potensyal na "makatakas" mula sa chroot at makakuha ng access sa pangunahing operating system. Gayundin, bilang karagdagan sa pagbabago ng direktoryo ng ugat, ang iba pang mga mapagkukunan (RAM, processor), pati na rin ang pag-access sa network, ay hindi limitado.
Ang susunod na paraan ay ang paglunsad ng isang ganap na operating system sa loob ng isang lalagyan, gamit ang mga mekanismo ng kernel ng operating system. Ang pamamaraang ito ay tinatawag na naiiba sa iba't ibang mga operating system, ngunit ang kakanyahan ay pareho - ang paglulunsad ng ilang mga independiyenteng operating system, na ang bawat isa ay tumatakbo sa parehong kernel kung saan tumatakbo ang pangunahing operating system. Kabilang dito ang FreeBSD Jails, Solaris Zones, OpenVZ at LXC para sa Linux. Tinitiyak ang paghihiwalay hindi lamang ng espasyo sa disk, kundi pati na rin ng iba pang mapagkukunan; sa partikular, ang bawat lalagyan ay maaaring may mga limitasyon sa oras ng processor, RAM, at bandwidth ng network. Kung ikukumpara sa chroot, ang pag-iwan sa container ay mas mahirap, dahil ang superuser sa container ay may access lang sa mga nilalaman ng container, gayunpaman, dahil sa pangangailangang panatilihing napapanahon ang operating system sa loob ng container at ang paggamit ng mga mas lumang bersyon. ng mga kernels (may-katuturan para sa Linux, sa mas mababang lawak ng FreeBSD), mayroong isang non-zero ang posibilidad na "masira" ang kernel isolation system at makakuha ng access sa pangunahing operating system.
Sa halip na maglunsad ng isang ganap na operating system sa isang lalagyan (na may isang initialization system, package manager, atbp.), Maaari mong ilunsad kaagad ang mga application, ang pangunahing bagay ay upang bigyan ang mga application ng ganoong pagkakataon (ang pagkakaroon ng mga kinakailangang aklatan at iba pang mga file). Ang ideyang ito ay nagsilbing batayan para sa containerized application virtualization, ang pinakakilala at kilalang kinatawan kung saan ay ang Docker. Kung ikukumpara sa mga nakaraang system, ang mas nababaluktot na mga mekanismo ng paghihiwalay, kasama ng built-in na suporta para sa mga virtual na network sa pagitan ng mga container at pagsubaybay sa estado ng aplikasyon sa loob ng container, ay nagresulta sa kakayahang bumuo ng isang magkakaugnay na kapaligiran mula sa isang malaking bilang ng mga pisikal na server para sa pagpapatakbo ng mga container - nang hindi nangangailangan ng manu-manong pamamahala ng mapagkukunan.
Manggagawa sa pantalan
Ang Docker ay ang pinakasikat na application containerization software. Nakasulat sa wikang Go, ginagamit nito ang mga karaniwang tampok ng kernel ng Linux - mga cgroup, namespace, kakayahan, atbp., pati na rin ang mga Aufs file system at iba pang katulad nito upang makatipid ng espasyo sa disk.
Pinagmulan: wikimedia
arkitektura
Bago ang bersyon 1.11, nagtrabaho ang Docker bilang isang solong serbisyo na nagsagawa ng lahat ng mga operasyon na may mga lalagyan: pag-download ng mga larawan para sa mga lalagyan, paglulunsad ng mga lalagyan, pagproseso ng mga kahilingan sa API. Simula sa bersyon 1.11, ang Docker ay nahahati sa ilang bahagi na nakikipag-ugnayan sa isa't isa: containerd, para sa pagproseso ng buong cycle ng buhay ng mga lalagyan (paglalaan ng espasyo sa disk, pag-download ng mga imahe, pagtatrabaho sa network, paglulunsad, pag-install at pagsubaybay sa estado ng mga lalagyan) at runC, ang container execution environment, batay sa paggamit ng mga cgroup at iba pang feature ng Linux kernel. Ang serbisyo ng docker mismo ay nananatili, ngunit ngayon ay nagsisilbi lamang itong iproseso ang mga kahilingan ng API na isinalin sa containerd.
Pag-install at pagsasaayos
Ang aking paboritong paraan ng pag-install ng docker ay ang docker-machine, na, bilang karagdagan sa direktang pag-install at pag-configure ng docker sa mga malalayong server (kabilang ang iba't ibang mga ulap), ay nagbibigay-daan sa iyo upang gumana sa mga file system ng mga malalayong server, at maaari ring magpatakbo ng iba't ibang mga utos.
Gayunpaman, mula noong 2018, ang proyekto ay halos hindi na binuo, kaya i-install namin ito sa karaniwang paraan para sa karamihan ng mga pamamahagi ng Linux - pagdaragdag ng isang repositoryo at pag-install ng mga kinakailangang pakete.
Ginagamit din ang paraang ito para sa awtomatikong pag-install, halimbawa, gamit ang Ansible o iba pang katulad na mga sistema, ngunit hindi ko ito isasaalang-alang sa artikulong ito.
Ang pag-install ay isasagawa sa Centos 7, gagamit ako ng isang virtual machine bilang isang server, upang mai-install, patakbuhin lamang ang mga utos sa ibaba:
# 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
Pagkatapos ng pag-install, kailangan mong simulan ang serbisyo, ilagay ito sa autoload:
# systemctl enable docker
# systemctl start docker
# firewall-cmd --zone=public --add-port=2377/tcp --permanent
Bukod pa rito, maaari kang lumikha ng pangkat ng docker, na ang mga user ay makakapagtrabaho sa docker nang walang sudo, mag-set up ng pag-log, paganahin ang access sa API mula sa labas, at huwag kalimutang i-configure ang firewall nang mas tumpak (lahat ng bagay na hindi pinapayagan ay ipinagbabawal sa mga halimbawa sa itaas at sa ibaba - Inalis ko ito para sa pagiging simple at visualization), ngunit hindi na ako magdetalye dito.
Iba pang mga tampok
Bilang karagdagan sa docker machine sa itaas, mayroon ding docker registry, isang tool para sa pag-iimbak ng mga imahe para sa mga container, pati na rin ang docker compose - isang tool para sa pag-automate ng pag-deploy ng mga application sa mga container, ang mga YAML file ay ginagamit upang bumuo at mag-configure ng mga container at iba pang mga kaugnay na bagay (halimbawa, mga network, paulit-ulit na file system para sa pag-iimbak ng data).
Maaari rin itong magamit upang ayusin ang mga conveyor para sa CICD. Ang isa pang kawili-wiling tampok ay gumagana sa cluster mode, ang tinatawag na swarm mode (bago ang bersyon 1.12 ito ay kilala bilang docker swarm), na nagbibigay-daan sa iyong mag-assemble ng isang solong imprastraktura mula sa ilang mga server para sa pagpapatakbo ng mga lalagyan. Mayroong suporta para sa isang virtual na network sa itaas ng lahat ng mga server, mayroong built-in na load balancer, pati na rin ang suporta para sa mga lihim para sa mga lalagyan.
Ang mga file ng YAML mula sa docker compose ay maaaring gamitin para sa mga naturang cluster na may maliliit na pagbabago, ganap na awtomatiko ang pagpapanatili ng maliliit at katamtamang mga cluster para sa iba't ibang layunin. Para sa malalaking cluster, mas mainam ang Kubernetes dahil ang mga gastos sa pagpapanatili ng swarm mode ay maaaring mas malaki kaysa sa mga gastos sa Kubernetes. Bilang karagdagan sa runC, bilang isang kapaligiran ng pagpapatupad para sa mga lalagyan, maaari mong i-install, halimbawa
Nagtatrabaho sa Docker
Pagkatapos ng pag-install at pagsasaayos, susubukan naming mag-assemble ng isang cluster kung saan kami ay magde-deploy ng GitLab at Docker Registry para sa development team. Gagamit ako ng tatlong virtual machine bilang mga server, kung saan ipapakalat ko rin ang ipinamahagi na FS GlusterFS; Gagamitin ko ito bilang isang docker volume storage, halimbawa, para magpatakbo ng fault-tolerant na bersyon ng docker registry. Mga pangunahing bahagi na tatakbo: Docker Registry, Postgresql, Redis, GitLab na may suporta para sa GitLab Runner sa ibabaw ng Swarm. Ilulunsad namin ang Postgresql na may clustering
Upang i-deploy ang GlusterFS sa lahat ng mga server (tinatawag silang node1, node2, node3), kailangan mong mag-install ng mga pakete, paganahin ang firewall, at lumikha ng mga kinakailangang direktoryo:
# 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
Pagkatapos ng pag-install, ang trabaho sa pag-configure ng GlusterFS ay dapat ipagpatuloy mula sa isang node, halimbawa 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
Pagkatapos ay kailangan mong i-mount ang nagresultang dami (ang utos ay dapat isagawa sa lahat ng mga server):
# mount /srv/docker
Ang swarm mode ay naka-configure sa isa sa mga server, na siyang magiging Leader, ang iba ay kailangang sumali sa cluster, kaya ang resulta ng pagpapatupad ng command sa unang server ay kailangang kopyahin at isagawa sa iba.
Paunang pag-setup ng kumpol, pinapatakbo ko ang utos sa 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
Kopyahin ang resulta ng pangalawang utos, isagawa sa node2 at node3:
# docker swarm join --token SWMTKN-x-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-xxxxxxxxx xx.xx.xx.xx:2377
This node joined a swarm as a manager.
Nakumpleto nito ang paunang pagsasaayos ng mga server, simulan natin ang pag-configure ng mga serbisyo, ang mga utos na isasagawa ay ilulunsad mula sa node1, maliban kung tinukoy.
Una sa lahat, gumawa tayo ng mga network para sa mga container:
# 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
Pagkatapos ay markahan namin ang mga server, ito ay kinakailangan upang itali ang ilang mga serbisyo sa mga server:
# docker node update --label-add nodename=node1 node1
# docker node update --label-add nodename=node2 node2
# docker node update --label-add nodename=node3 node3
Susunod, gumawa kami ng mga direktoryo para sa pag-iimbak ng etcd data, ang KV storage na kailangan ni Traefik at Stolon. Katulad ng Postgresql, ang mga ito ay mga lalagyan na nakatali sa mga server, kaya ipapatupad namin ang utos na ito sa lahat ng mga server:
# mkdir -p /srv/etcd
Susunod, lumikha ng isang file upang i-configure ang etcd at ilapat ito:
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
Pagkaraan ng ilang oras, tinitingnan namin na ang etcd cluster ay pataas:
# 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
Lumilikha kami ng mga direktoryo para sa Postgresql, isagawa ang utos sa lahat ng mga server:
# mkdir -p /srv/pgsql
Susunod, lumikha ng isang file upang i-configure ang Postgresql:
01pgsql.yml
version: '3.7'
services:
pgsentinel:
image: sorintlab/stolon:master-pg10
command:
- gosu
- stolon
- stolon-sentinel
- --cluster-name=stolon-cluster
- --store-backend=etcdv3
- --store-endpoints=http://etcd1:2379,http://etcd2:2379,http://etcd3:2379
- --log-level=debug
networks:
- etcd
- pgsql
deploy:
replicas: 3
update_config:
parallelism: 1
delay: 30s
order: stop-first
failure_action: pause
pgkeeper1:
image: sorintlab/stolon:master-pg10
hostname: pgkeeper1
command:
- gosu
- stolon
- stolon-keeper
- --pg-listen-address=pgkeeper1
- --pg-repl-username=replica
- --uid=pgkeeper1
- --pg-su-username=postgres
- --pg-su-passwordfile=/run/secrets/pgsql
- --pg-repl-passwordfile=/run/secrets/pgsql_repl
- --data-dir=/var/lib/postgresql/data
- --cluster-name=stolon-cluster
- --store-backend=etcdv3
- --store-endpoints=http://etcd1:2379,http://etcd2:2379,http://etcd3:2379
networks:
- etcd
- pgsql
environment:
- PGDATA=/var/lib/postgresql/data
volumes:
- pgkeeper1:/var/lib/postgresql/data
secrets:
- pgsql
- pgsql_repl
deploy:
replicas: 1
placement:
constraints: [node.labels.nodename == node1]
pgkeeper2:
image: sorintlab/stolon:master-pg10
hostname: pgkeeper2
command:
- gosu
- stolon
- stolon-keeper
- --pg-listen-address=pgkeeper2
- --pg-repl-username=replica
- --uid=pgkeeper2
- --pg-su-username=postgres
- --pg-su-passwordfile=/run/secrets/pgsql
- --pg-repl-passwordfile=/run/secrets/pgsql_repl
- --data-dir=/var/lib/postgresql/data
- --cluster-name=stolon-cluster
- --store-backend=etcdv3
- --store-endpoints=http://etcd1:2379,http://etcd2:2379,http://etcd3:2379
networks:
- etcd
- pgsql
environment:
- PGDATA=/var/lib/postgresql/data
volumes:
- pgkeeper2:/var/lib/postgresql/data
secrets:
- pgsql
- pgsql_repl
deploy:
replicas: 1
placement:
constraints: [node.labels.nodename == node2]
pgkeeper3:
image: sorintlab/stolon:master-pg10
hostname: pgkeeper3
command:
- gosu
- stolon
- stolon-keeper
- --pg-listen-address=pgkeeper3
- --pg-repl-username=replica
- --uid=pgkeeper3
- --pg-su-username=postgres
- --pg-su-passwordfile=/run/secrets/pgsql
- --pg-repl-passwordfile=/run/secrets/pgsql_repl
- --data-dir=/var/lib/postgresql/data
- --cluster-name=stolon-cluster
- --store-backend=etcdv3
- --store-endpoints=http://etcd1:2379,http://etcd2:2379,http://etcd3:2379
networks:
- etcd
- pgsql
environment:
- PGDATA=/var/lib/postgresql/data
volumes:
- pgkeeper3:/var/lib/postgresql/data
secrets:
- pgsql
- pgsql_repl
deploy:
replicas: 1
placement:
constraints: [node.labels.nodename == node3]
postgresql:
image: sorintlab/stolon:master-pg10
command: gosu stolon stolon-proxy --listen-address 0.0.0.0 --cluster-name stolon-cluster --store-backend=etcdv3 --store-endpoints http://etcd1:2379,http://etcd2:2379,http://etcd3:2379
networks:
- etcd
- pgsql
deploy:
replicas: 3
update_config:
parallelism: 1
delay: 30s
order: stop-first
failure_action: rollback
volumes:
pgkeeper1:
driver: local
driver_opts:
type: none
o: bind
device: "/srv/pgsql"
pgkeeper2:
driver: local
driver_opts:
type: none
o: bind
device: "/srv/pgsql"
pgkeeper3:
driver: local
driver_opts:
type: none
o: bind
device: "/srv/pgsql"
secrets:
pgsql:
file: "/srv/docker/postgres"
pgsql_repl:
file: "/srv/docker/replica"
networks:
etcd:
external: true
pgsql:
external: true
Bumubuo kami ng mga lihim at ginagamit ang file:
# </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
Pagkaraan ng ilang oras (tingnan ang output ng command serbisyo ng docker lsna ang lahat ng mga serbisyo ay tumaas) ay nagpasimula ng kumpol ng 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 init
Sinusuri ang kahandaan ng kumpol ng 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
Kino-configure namin ang traefik upang buksan ang access sa mga container mula sa labas:
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
Sinimulan namin ang Redis Cluster, para dito lumikha kami ng isang direktoryo ng imbakan sa lahat ng mga node:
# 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
Magdagdag ng 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
At sa wakas - 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
Ang huling estado ng cluster at mga serbisyo:
# 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
Ano pa ang maaaring pagbutihin? Tiyaking i-configure ang Traefik upang gumana sa mga container ng https, magdagdag ng tls encryption para sa Postgresql at Redis. Ngunit sa pangkalahatan, maaari mo na itong ibigay sa mga developer bilang PoC. Tingnan natin ngayon ang mga alternatibo sa Docker.
podman
Isa pang medyo kilalang makina para sa pagpapatakbo ng mga lalagyan na nakapangkat ayon sa mga pod (mga pod, mga pangkat ng mga lalagyan na pinagsama-sama). Hindi tulad ng Docker, hindi ito nangangailangan ng anumang serbisyo upang magpatakbo ng mga lalagyan; lahat ng gawain ay ginagawa sa pamamagitan ng library ng libpod. Nakasulat din sa Go, nangangailangan ng runtime na katugma sa OCI para magpatakbo ng mga container, gaya ng runC.
Ang pagtatrabaho sa Podman sa pangkalahatan ay kahawig ng sa Docker, hanggang sa magagawa mo ito tulad nito (inaangkin ng marami na sumubok nito, kasama ang may-akda ng artikulong ito):
$ alias docker=podman
at maaari kang magpatuloy sa pagtatrabaho. Sa pangkalahatan, ang sitwasyon sa Podman ay napaka-interesante, dahil kung ang mga unang bersyon ng Kubernetes ay nagtrabaho sa Docker, pagkatapos noong mga 2015, pagkatapos i-standardize ang mundo ng container (OCI - Open Container Initiative) at hatiin ang Docker sa containerd at runC, isang alternatibo sa Ang Docker ay binuo upang tumakbo sa Kubernetes: CRI-O. Ang Podman sa bagay na ito ay isang alternatibo sa Docker, na binuo sa mga prinsipyo ng Kubernetes, kabilang ang pagpapangkat ng container, ngunit ang pangunahing layunin ng proyekto ay ang magpatakbo ng mga container na may istilong Docker nang walang mga karagdagang serbisyo. Para sa mga malinaw na kadahilanan, walang swarm mode, dahil malinaw na sinasabi ng mga developer na kung kailangan mo ng isang kumpol, kunin ang Kubernetes.
Instalasyon
Upang mai-install sa Centos 7, i-activate lang ang Extras repository, at pagkatapos ay i-install ang lahat gamit ang command:
# yum -y install podman
Iba pang mga tampok
Ang Podman ay maaaring makabuo ng mga yunit para sa systemd, kaya malulutas ang problema sa pagsisimula ng mga lalagyan pagkatapos ng pag-reboot ng server. Bilang karagdagan, ang systemd ay idineklara na gumagana nang tama bilang pid 1 sa lalagyan. Upang bumuo ng mga lalagyan, mayroong isang hiwalay na tool sa buildah, mayroon ding mga tool ng third-party - mga analogue ng docker-compose, na bumubuo rin ng mga file ng pagsasaayos na katugma sa Kubernetes, kaya ang paglipat mula sa Podman patungo sa Kubernetes ay kasing simple hangga't maaari.
Nagtatrabaho sa Podman
Dahil walang swarm mode (ito ay dapat na lumipat sa Kubernetes kung kinakailangan ang isang cluster), isasama namin ito sa magkakahiwalay na mga lalagyan.
I-install ang podman-compose:
# yum -y install python3-pip
# pip3 install podman-compose
Ang nagreresultang config file para sa podman ay bahagyang naiiba, bilang halimbawa kailangan naming ilipat ang isang hiwalay na seksyon ng volume nang direkta sa seksyon ng mga serbisyo.
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
Resulta ng trabaho:
# 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
Tingnan natin kung ano ang bubuo nito para sa systemd at kubernetes, para dito kailangan nating malaman ang pangalan o id ng pod:
# 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
Sa kasamaang palad, bukod sa pagpapatakbo ng mga lalagyan, ang nabuong unit para sa systemd ay walang ibang ginagawa (halimbawa, paglilinis ng mga lumang lalagyan kapag ang naturang serbisyo ay na-restart), kaya ikaw mismo ang magdadagdag ng mga ganoong bagay.
Sa prinsipyo, sapat na ang Podman upang subukan kung ano ang mga container, ilipat ang mga lumang configuration para sa docker-compose, at pagkatapos ay pumunta sa Kubernetes, kung kinakailangan, sa isang cluster, o kumuha ng mas madaling gamitin na alternatibo sa Docker.
rkt
Proyekto
Flash
Pa
Natuklasan
Ang sitwasyon sa Kubernetes ay medyo kawili-wili: sa isang banda, sa Docker maaari kang bumuo ng isang kumpol (sa swarm mode), kung saan maaari ka ring magpatakbo ng mga kapaligiran ng produkto para sa mga kliyente, ito ay totoo lalo na para sa mga maliliit na koponan (3-5 tao) , o may maliit na kabuuang load , o kawalan ng pagnanais na maunawaan ang mga sali-salimuot ng pag-set up ng Kubernetes, kabilang ang para sa matataas na load.
Ang Podman ay hindi nagbibigay ng ganap na compatibility, ngunit mayroon itong isang mahalagang bentahe - compatibility sa Kubernetes, kabilang ang mga karagdagang tool (buildah at iba pa). Samakatuwid, lalapit ako sa pagpili ng isang tool para sa trabaho tulad ng sumusunod: para sa mga maliliit na koponan, o may limitadong badyet - Docker (na may posibleng swarm mode), para sa pagbuo para sa aking sarili sa isang personal na localhost - Podman comrades, at para sa lahat. - Kubernetes.
Hindi ako sigurado na ang sitwasyon sa Docker ay hindi magbabago sa hinaharap, pagkatapos ng lahat, sila ay mga pioneer, at dahan-dahan ding nag-standardize ng hakbang-hakbang, ngunit ang Podman, kasama ang lahat ng mga pagkukulang nito (gumagana lamang sa Linux, walang clustering, assembly. at ang iba pang mga aksyon ay mga desisyon ng third-party) mas malinaw ang hinaharap, kaya iniimbitahan ko ang lahat na talakayin ang mga natuklasang ito sa mga komento.
PS Sa Agosto 3 inilunsad namin ang "
Presyo ng pre-order bago ilabas: RUB 5000. Maaari mong tingnan ang programa ng Docker Video Course
Pinagmulan: www.habr.com