TL;DR: Konteynerlerde uygulama çalıştırmaya yönelik çerçeveleri karşılaştırmaya yönelik genel bakış kılavuzu. Docker ve benzeri sistemlerin yetenekleri dikkate alınacaktır.

Her şeyin nereden geldiğine dair küçük bir tarih
Öykü
Bir uygulamayı izole etmek için iyi bilinen ilk yöntem chroot'tur. Aynı isimdeki sistem çağrısı, kök dizinin değiştirilmesini sağlar; böylece onu çağıran programın yalnızca o dizin içindeki dosyalara erişebilmesini sağlar. Ancak bir programa dahili olarak kök ayrıcalıkları verilirse, potansiyel olarak chroot'tan "kaçabilir" ve ana işletim sistemine erişim sağlayabilir. Ayrıca kök dizini değiştirmenin yanı sıra diğer kaynaklar (RAM, işlemci) ve ağ erişimi de sınırlı değildir.
Bir sonraki yöntem, işletim sistemi çekirdek mekanizmalarını kullanarak tam teşekküllü bir işletim sistemini bir konteyner içinde çalıştırmaktır. Bu yöntem farklı işletim sistemlerinde farklı isimlerle anılsa da özü aynıdır: her biri ana işletim sistemiyle aynı çekirdeği çalıştıran birden fazla bağımsız işletim sistemi çalıştırmak. Buna FreeBSD Jails, Solaris Zones, OpenVZ ve LXC dahildir. Linuxİzolasyon yalnızca disk alanı ile değil, diğer kaynaklarla da sağlanır; özellikle, her konteynerin CPU süresi, RAM ve ağ bant genişliği konusunda sınırları olabilir. Chroot'a kıyasla, konteynerden çıkmak daha zordur, çünkü konteyner içindeki süper kullanıcının yalnızca konteynerin iç yapısına erişimi vardır. Bununla birlikte, konteyner içindeki işletim sisteminin güncel tutulması ve eski çekirdek sürümlerinin kullanılması (ilgili olduğu için) nedeniyle Linux(FreeBSD'de daha az oranda olsa da) çekirdek izolasyon sistemini "aşma" ve ana işletim sistemine erişim sağlama olasılığı sıfırdan farklıdır.
Bir kapta tam teşekküllü bir işletim sistemini başlatmak yerine (bir başlatma sistemi, paket yöneticisi vb. ile), uygulamaları hemen başlatabilirsiniz, asıl önemli olan uygulamalara böyle bir fırsat sağlamaktır (gerekli kitaplıkların varlığı) ve diğer dosyalar). Bu fikir, en önde gelen ve tanınmış temsilcisi Docker olan konteynerleştirilmiş uygulama sanallaştırmasının temelini oluşturdu. Önceki sistemlerle karşılaştırıldığında, daha esnek izolasyon mekanizmaları, konteynerler arasındaki sanal ağlar için yerleşik destek ve konteyner içindeki uygulama durumu takibi ile birleştiğinde, konteynerleri çalıştırmak için çok sayıda fiziksel sunucudan tek bir tutarlı ortam oluşturma becerisiyle sonuçlandı. manuel kaynak yönetimine gerek kalmadan.
liman işçisi
Docker, en bilinen uygulama konteynerleştirme yazılımıdır. Go dilinde yazılmıştır ve yerel çekirdek özelliklerini kullanır. Linux — Disk alanından tasarruf etmek için cgroup'lar, ad alanları, yetenekler vb. ile Aufs dosya sistemleri ve diğer benzer sistemler.

Kaynak: wikimedia
Mimari
1.11 sürümünden önce Docker, tüm konteyner işlemlerini (konteyner imajlarını indirme, konteynerleri başlatma ve API isteklerini işleme) yöneten tek bir servis olarak çalışıyordu. 1.11 sürümünden itibaren Docker, etkileşimli birkaç parçaya ayrıldı: tüm konteyner yaşam döngüsünü (disk tahsisi, imaj indirme, ağ iletişimi, başlatma, yükleme ve konteyner durumunu izleme) yöneten containerd ve cgroups ve diğer çekirdek özelliklerine dayalı bir konteyner çalışma ortamı olan runC. LinuxDocker servisinin kendisi varlığını sürdürüyor, ancak artık yalnızca containerd'e iletilen API isteklerini işlemek için kullanılıyor.

Kurulum ve konfigürasyon
Docker'ı kurmanın en sevdiğim yolu, docker'ı uzak sunuculara (çeşitli bulutlar dahil) doğrudan kurup yapılandırmanın yanı sıra, uzak sunucuların dosya sistemleriyle çalışmayı mümkün kılan ve ayrıca çeşitli komutları çalıştırabilen docker-machine'dir.
Ancak 2018'den beri proje neredeyse hiç geliştirilmedi, bu nedenle çoğu dağıtım için standart yöntemi kullanarak kuracağız. Linux Yöntem - bir depo ekleyerek ve gerekli paketleri kurarak.
Bu yöntem, örneğin Ansible veya diğer benzer sistemler kullanılarak otomatik kurulum için de kullanılır, ancak bu makalede bunu dikkate almayacağım.
Kurulum şu tarihte gerçekleştirilecektir: Centos 7. Sanal makineyi sunucu olarak kullanacağım, kurulum için aşağıdaki komutları çalıştırmak yeterli olacaktır:
# 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.ioKurulumdan sonra hizmeti başlatmanız ve başlangıç durumuna getirmeniz gerekir:
# systemctl enable docker
# systemctl start docker
# firewall-cmd --zone=public --add-port=2377/tcp --permanentEk olarak, kullanıcıları sudo olmadan docker ile çalışabilecek, günlük kaydı ayarlayabilecek, API'ye dışarıdan erişimi etkinleştirebilecek ve güvenlik duvarını daha hassas bir şekilde yapılandırmayı unutmayın (izin verilmeyen her şeye) sahip olacak bir docker grubu oluşturabilirsiniz. Yukarıdaki ve aşağıdaki örneklerde yasaklanmıştır - basitlik ve netlik açısından bunu atladım), ancak burada daha fazla ayrıntıya girmeyeceğim.
Diğer özellikleri
Yukarıda belirtilen docker makinesine ek olarak, konteynerler için görüntüleri depolamak için bir araç olan docker kayıt defteri ve ayrıca konteynerlerdeki uygulamaların dağıtımını otomatikleştirmek için bir araç olan docker compose da vardır, YAML dosyaları konteynerler oluşturmak ve yapılandırmak için kullanılır ve diğer ilgili şeyler (örneğin ağlar, verilerin depolanması için kalıcı dosya sistemleri).
Ayrıca CICD'ye yönelik konveyörleri organize etmek için de kullanılabilir. Bir başka ilginç özellik de, konteynerleri çalıştırmak için birkaç sunucudan tek bir altyapı oluşturmanıza olanak tanıyan, sürü modu adı verilen (sürüm 1.12'den önce, docker sürüsü olarak biliniyordu) küme modunda çalışmaktır. Tüm sunucuların üstünde bir sanal ağ desteği var, yerleşik bir yük dengeleyicinin yanı sıra konteynerler için sırlar desteği de var.
Docker compose'un YAML dosyaları, küçük değişikliklerle bu tür kümeler için kullanılabilir ve çeşitli amaçlar için küçük ve orta ölçekli kümelerin bakımını tamamen otomatikleştirir. Büyük kümeler için Kubernetes tercih edilir çünkü sürü modunun bakım maliyetleri Kubernetes'inkini aşabilir. RunC'ye ek olarak, örneğin konteyner yürütme ortamı olarak da kurulum yapabilirsiniz.
Docker'la çalışma
Kurulum ve konfigürasyonun ardından geliştirme ekibi için GitLab ve Docker Registry’yi konuşlandıracağımız bir küme oluşturmaya çalışacağız. Sunucu olarak üç sanal makine kullanacağım ve bunlara ek olarak dağıtılmış FS GlusterFS'yi dağıtacağım; bunu, örneğin docker kayıt defterinin hataya dayanıklı bir sürümünü çalıştırmak için docker birimleri depolama alanı olarak kullanacağım. Çalıştırılacak temel bileşenler: Swarm'ın yanı sıra GitLab Runner desteğiyle Docker Registry, Postgresql, Redis, GitLab. Postgresql'i kümeleme ile başlatacağız , böylece Postgresql verilerini depolamak için GlusterFS kullanmanıza gerek kalmaz. Kalan kritik veriler GlusterFS'de saklanacaktır.
GlusterFS'yi tüm sunuculara dağıtmak için (bunlara düğüm1, düğüm2, düğüm3 denir), paketleri kurmanız, güvenlik duvarını etkinleştirmeniz ve gerekli dizinleri oluşturmanız gerekir:
# 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/fstabKurulumdan sonra GlusterFS'yi yapılandırma çalışmalarına bir düğümden, örneğin düğüm1'den devam edilmelidir:
# 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 dockerDaha sonra ortaya çıkan birimi bağlamanız gerekir (komutun tüm sunucularda yürütülmesi gerekir):
# mount /srv/dockerSürü modu, Lider olacak sunuculardan birinde yapılandırılmıştır, geri kalanının kümeye katılması gerekecektir, bu nedenle komutun ilk sunucuda yürütülmesinin sonucunun diğerlerine kopyalanması ve yürütülmesi gerekecektir.
İlk küme kurulumunda, düğüm1'de komutu çalıştırıyorum:
# 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İkinci komutun sonucunu kopyalayıp düğüm2 ve düğüm3'te çalıştırıyoruz:
# docker swarm join --token SWMTKN-x-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-xxxxxxxxx xx.xx.xx.xx:2377
This node joined a swarm as a manager.Bu noktada sunucuların ön konfigürasyonu tamamlandı, servislerin kurulumuna geçelim; çalıştırılacak komutlar aksi belirtilmediği sürece node1’den çalıştırılacaktır.
Öncelikle konteynerler için ağlar oluşturalım:
# 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 gitlabDaha sonra sunucuları işaretliyoruz, bu bazı hizmetleri sunuculara bağlamak için gereklidir:
# docker node update --label-add nodename=node1 node1
# docker node update --label-add nodename=node2 node2
# docker node update --label-add nodename=node3 node3Daha sonra Traefik ve Stolon için gerekli olan KV depolama alanı olan etcd verilerini depolamak için dizinler oluşturuyoruz. Postgresql'e benzer şekilde bunlar sunuculara bağlı kaplar olacaktır, dolayısıyla bu komutu tüm sunucularda çalıştırıyoruz:
# mkdir -p /srv/etcdDaha sonra, etcd'yi yapılandırmak ve kullanmak için bir dosya oluşturun:
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 etcdBir süre sonra etcd kümesinin çalışır durumda olup olmadığını kontrol ediyoruz:
# 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 healthyPostgresql için dizinler oluşturuyoruz, komutu tüm sunucularda yürütüyoruz:
# mkdir -p /srv/pgsqlArdından Postgresql'i yapılandırmak için bir dosya oluşturun:
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: trueSırları oluşturuyoruz ve dosyayı kullanıyoruz:
# </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 pgsqlBir süre sonra (komutun çıktısına bakın) Liman işçisi hizmeti lstüm hizmetlerin çalıştığından emin olun) Postgresql kümesini başlatıyoruz:
# 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 initPostgresql kümesinin hazır olup olmadığının kontrol edilmesi:
# docker exec $(docker ps | awk '/pgkeeper/ {print $1}') stolonctl --cluster-name=stolon-cluster --store-backend=etcdv3 --store-endpoints=http://etcd1:2379,http://etcd2:2379,http://etcd3:2379 status
=== Active sentinels ===
ID LEADER
26baa11d false
74e98768 false
a8cb002b true
=== Active proxies ===
ID
4d233826
9f562f3b
b0c79ff1
=== Keepers ===
UID HEALTHY PG LISTENADDRESS PG HEALTHY PG WANTEDGENERATION PG CURRENTGENERATION
pgkeeper1 true pgkeeper1:5432 true 2 2
pgkeeper2 true pgkeeper2:5432 true 2 2
pgkeeper3 true pgkeeper3:5432 true 3 3
=== Cluster Info ===
Master Keeper: pgkeeper3
===== Keepers/DB tree =====
pgkeeper3 (master)
├─pgkeeper2
└─pgkeeper1
Traefik'i konteynerlere dışarıdan erişim açacak şekilde yapılandırıyoruz:
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 traefikRedis Cluster'ı başlatıyoruz, bunu yapmak için tüm düğümlerde bir depolama dizini oluşturuyoruz:
# 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 redisDocker Kaydı Ekle:
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 registryVe son olarak - 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 gitlabCluster ve servislerin son durumu:
# 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/tcpBaşka ne geliştirilebilir? Traefik'i konteynerleri https üzerinden çalıştıracak şekilde yapılandırdığınızdan, Postgresql ve Redis için tls şifrelemesi eklediğinizden emin olun. Ancak genel olarak geliştiricilere zaten PoC olarak verilebiliyor. Şimdi Docker'ın alternatiflerine bakalım.
podman
Bölmelere (bölmeler, birlikte konuşlandırılan konteyner grupları) göre gruplandırılmış kapları çalıştırmak için oldukça iyi bilinen bir başka motor. Docker'ın aksine, konteynerleri çalıştırmak için herhangi bir hizmete ihtiyaç duymaz; tüm işler libpod kütüphanesi aracılığıyla yapılır. Ayrıca Go'da yazılmış olup, kapsayıcıları çalıştırmak için runC gibi OCI uyumlu bir çalışma zamanı gerektirir.

Podman'la çalışmak genel olarak Docker'ınkine benziyor, o kadar ki bunu şu şekilde yapabilirsiniz (bu makalenin yazarı da dahil olmak üzere bunu deneyen birçok kişi tarafından belirtildiği gibi):
$ alias docker=podmanve çalışmaya devam edebilirsiniz. Genel olarak Podman'ın durumu çok ilginç çünkü Kubernetes'in ilk sürümleri Docker ile çalıştıysa, o zaman 2015 civarında, konteyner dünyasının standartlaştırılmasından (OCI - Açık Konteyner Girişimi) ve Docker'ın konteynerd ve runC olarak bölünmesinden sonra, Kubernetes'te çalıştırmak için Docker'a bir alternatif geliştiriliyor: CRI-O. Bu bakımdan Podman, konteynerlerin gruplandırılması da dahil olmak üzere Kubernetes ilkeleri üzerine inşa edilmiş Docker'a bir alternatiftir, ancak projenin asıl amacı Docker tarzı konteynerleri ek hizmetler olmadan başlatmaktır. Açık nedenlerden dolayı, sürü modu yoktur, çünkü geliştiriciler bir kümeye ihtiyacınız varsa Kubernetes'i almanızı açıkça söylüyorlar.
Montaj
Kurulum için Centos 7. Öncelikle Extras deposunu etkinleştirin ve ardından şu komutu kullanarak her şeyi yükleyin:
# yum -y install podmanDiğer özellikleri
Podman, systemd için birimler oluşturabilir, böylece sunucu yeniden başlatıldıktan sonra kapsayıcıları başlatma sorununu çözebilir. Ek olarak, systemd'nin kapta pid 1 olarak düzgün çalıştığı bildirildi. Kapsayıcılar oluşturmak için ayrı bir buildah aracı var, ayrıca Kubernetes ile uyumlu yapılandırma dosyaları oluşturan docker-compose analogları gibi üçüncü taraf araçlar da var, böylece Podman'dan Kubernetes'e geçiş mümkün olduğu kadar basitleştirildi.
Podman'la çalışmak
Swarm modu olmadığı için (cluster ihtiyacı varsa Kubernetes'e geçmemiz gerekiyor) ayrı konteynerlerde toplayacağız.
Podman-compose'u yükleyin:
# yum -y install python3-pip
# pip3 install podman-composePodman için ortaya çıkan konfigürasyon dosyası biraz farklıdır, bu nedenle örneğin ayrı bir hacimler bölümünü doğrudan hizmetlerin bulunduğu bölüme taşımak zorunda kaldık.
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 upSonuç:
# 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_1Systemd ve kubernetes için neler ürettiğini görelim, bunun için pod'un adını veya kimliğini bulmamız gerekiyor:
# podman pod ls
POD ID NAME STATUS CREATED # OF CONTAINERS INFRA ID
71fc2b2a5c63 root Running 11 minutes ago 3 db40ab8bf84bKubernet'ler:
# 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: {}Sistemd:
# 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.targetNe yazık ki, systemd için oluşturulan birim, konteynerleri başlatmak dışında başka hiçbir şey yapmaz (örneğin, böyle bir hizmet yeniden başlatıldığında eski konteynerleri temizlemek), dolayısıyla bu tür şeyleri kendiniz yazmanız gerekecektir.
Prensip olarak Podman, konteynerlerin ne olduğunu denemek, docker-compose için eski yapılandırmaları aktarmak ve ardından bir kümeye ihtiyacınız varsa Kubernetes'e geçmek veya Docker'a kullanımı daha kolay bir alternatif almak için yeterlidir.
rkt
Proje Yaklaşık altı ay önce RedHat'in satın alması nedeniyle üzerinde daha fazla durmayacağım. Genel olarak çok iyi bir izlenim bıraktı ancak Docker ve özellikle Podman ile karşılaştırıldığında bir kombin gibi görünüyor. Ayrıca rkt üzerine kurulu bir CoreOS dağıtımı da vardı (başlangıçta Docker'a sahip olmalarına rağmen), ancak bu da RedHat satın alındıktan sonra destekle sonuçlandı.
çarpma
başka , yazarı sadece konteynerler oluşturmak ve çalıştırmak istiyordu. Dokümantasyona ve koda bakılırsa, yazar standartlara uymadı, sadece kendi uygulamasını yazmaya karar verdi ve prensipte de öyle yaptı.
Bulgular
Kubernetes ile ilgili durum çok ilginç: bir yandan Docker ile müşteriler için ürün ortamlarını bile çalıştırabileceğiniz bir küme (sürü modunda) oluşturabilirsiniz, bu özellikle küçük ekipler (3-5 kişi) için geçerlidir. veya küçük bir toplam yük ile veya yüksek yükler de dahil olmak üzere Kubernetes kurulumunun inceliklerini anlama arzusunun olmaması.
Podman tam uyumluluk sağlamaz, ancak önemli bir avantajı vardır: ek araçlar (buildah ve diğerleri) dahil olmak üzere Kubernetes ile uyumluluk. Bu nedenle, iş için bir araç seçimine şu şekilde yaklaşacağım: küçük ekipler için veya sınırlı bir bütçeyle - Docker (olası bir sürü moduyla), kişisel bir yerel ana bilgisayarda kendim geliştirmek için - Podman yoldaşlar ve diğer herkes için - Kubernet'ler.
Docker ile ilgili durumun gelecekte değişmeyeceğinden emin değilim, sonuçta onlar öncüler ve adım adım standartlaşıyorlar, ancak Podman, tüm eksikliklerine rağmen (sadece üzerinde çalışıyor olması gibi) Linux(Kümeleme, birleştirme ve diğer işlemler üçüncü taraf çözümler tarafından gerçekleştirilmediği için) gelecek daha net görünüyor, bu nedenle herkesi bu bulguları yorumlarda tartışmaya davet ediyorum.
PS 3 Ağustos'ta başlıyoruz "", çalışmaları hakkında daha fazla bilgi edinebileceğiniz yer. Tüm araçlarını analiz edeceğiz: temel soyutlamalardan ağ parametrelerine, çeşitli işletim sistemleri ve programlama dilleriyle çalışmanın nüanslarına kadar. Teknolojiye aşina olacak ve Docker'ı en iyi nerede ve nasıl kullanacağınızı anlayacaksınız. Ayrıca en iyi uygulama örneklerini de paylaşacağız.
Yayınlanmadan önce ön sipariş fiyatı: 5000 RUB. Docker Video Course programını görüntüleyebilirsiniz .
Kaynak: habr.com
