Docker lan kabeh, kabeh, kabeh

TL; DR: Artikel ringkesan - pandhuan kanggo mbandhingake lingkungan kanggo mbukak aplikasi ing wadhah. Kemungkinan Docker lan sistem liyane sing padha bakal dianggep.

Docker lan kabeh, kabeh, kabeh

A Sajarah sethitik saka ngendi iku kabeh teka saka

История

Cara pisanan sing kondhang kanggo ngisolasi aplikasi yaiku chroot. Panggilan sistem kanthi jeneng sing padha nyedhiyakake owah-owahan menyang direktori root - saéngga nyedhiyakake akses menyang program sing diarani, mung ngakses file ing direktori iki. Nanging yen program kasebut diwenehi hak superuser ing njero, bisa uga "uwal" saka chroot lan entuk akses menyang sistem operasi utama. Uga, saliyane ngganti direktori root, sumber daya liyane (RAM, prosesor), uga akses menyang jaringan, ora diwatesi.

Cara sabanjure yaiku ngluncurake sistem operasi lengkap ing wadhah kasebut, nggunakake mekanisme kernel sistem operasi. Cara iki diarani beda ing sistem operasi sing beda-beda, nanging intine padha - mlaku sawetara sistem operasi independen, sing saben-saben nganggo kernel sing padha karo sistem operasi utama. Iki kalebu FreeBSD Jails, Solaris Zones, OpenVZ, lan LXC kanggo Linux. Isolasi diwenehake ora mung kanggo ruang disk, nanging uga kanggo sumber daya liyane, utamane, saben wadhah bisa duwe watesan ing wektu prosesor, RAM, bandwidth jaringan. Dibandhingake karo chroot, ninggalake wadhah luwih angel, amarga superuser ing wadhah mung duwe akses menyang njero wadhah, nanging amarga kudu njaga sistem operasi ing wadhah kasebut lan nggunakake kernel lawas. versi (relevan kanggo Linux, kanggo ombone rodok kurang FreeBSD), ana non-nol kemungkinan bejat liwat sistem isolasi kernel lan entuk akses menyang sistem operasi utama.

Tinimbang ngluncurake sistem operasi lengkap ing wadhah (kanthi sistem inisialisasi, manajer paket, lan liya-liyane), aplikasi bisa langsung diluncurake, sing utama yaiku nyedhiyakake aplikasi kanthi kesempatan iki (anane perpustakaan sing dibutuhake lan file liyane). Ide iki dadi basis kanggo virtualisasi aplikasi containerized, wakil sing paling misuwur lan kondhang yaiku Docker. Dibandhingake karo sistem sadurunge, mekanisme isolasi luwih fleksibel, bebarengan karo support dibangun ing jaringan virtual antarane kontaner lan statefulness aplikasi nang wadhah, ngasilaken ing kemampuan kanggo mbangun lingkungan sakabehe siji saka nomer akeh server fisik kanggo mbukak kontaner - tanpa perlu kanggo manajemen sumber daya manual.

docker

Docker minangka piranti lunak containerisasi aplikasi sing paling kondhang. Ditulis ing basa Go, nggunakake kapabilitas biasa kernel Linux - cgroups, namespaces, kapabilitas, lan sapiturute, uga sistem file Aufs lan liya-liyane sing padha kanggo ngirit ruang disk.

Docker lan kabeh, kabeh, kabeh
Sumber: wikimedia

arsitektur

Sadurunge versi 1.11, Docker makarya minangka layanan siji sing nindakake kabeh operasi karo kontaner: ndownload gambar kanggo wadhah, mbukak wadhah, ngolah panjalukan API. Wiwit versi 1.11, Docker wis dipérang dadi sawetara bagéan sing sesambungan karo saben liyane: containerd, kanggo nangani kabeh siklus urip saka wadhah (alokasi ruang disk, download gambar, jaringan, diluncurake, nginstal lan ngawasi kahanan wadhah) lan runC , runtimes wadhah, adhedhasar panggunaan cgroups lan fitur liyane saka kernel Linux. Layanan docker dhewe tetep, nanging saiki mung ngolah panjaluk API sing disiarkan menyang containerd.

Docker lan kabeh, kabeh, kabeh

Instalasi lan konfigurasi

Cara sing paling disenengi kanggo nginstal docker yaiku docker-machine, sing, saliyane langsung nginstal lan ngonfigurasi docker ing server remot (kalebu macem-macem awan), sampeyan bisa nggarap sistem file server remot, lan uga bisa mbukak macem-macem perintah.

Nanging, wiwit 2018, proyek kasebut meh ora dikembangake, mula kita bakal nginstal kanthi cara sing biasa kanggo umume distribusi Linux - kanthi nambah repositori lan nginstal paket sing dibutuhake.

Cara iki uga digunakake kanggo instalasi otomatis, contone, nggunakake Ansible utawa sistem padha, nanging aku ora bakal nimbang ing artikel iki.

Instalasi bakal ditindakake ing Centos 7, aku bakal nggunakake mesin virtual minangka server, kanggo nginstal, mung nglakokake perintah ing ngisor iki:

# 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

Sawise instalasi, sampeyan kudu miwiti layanan, sijine ing autoload:

# systemctl enable docker
# systemctl start docker
# firewall-cmd --zone=public --add-port=2377/tcp --permanent

Kajaba iku, sampeyan bisa nggawe grup docker, sing pangguna bakal bisa nggarap docker tanpa sudo, nyiyapake logging, ngaktifake akses menyang API saka njaba, aja lali nyetel firewall (kabeh sing ora diidini yaiku dilarang ing conto ing ndhuwur lan ing ngisor iki - Aku ngilangi iki kanggo kesederhanaan lan visualisasi), nanging aku ora bakal luwih rinci ing kene.

Fitur liyane

Saliyane mesin docker ing ndhuwur, ana uga registri docker, alat kanggo nyimpen gambar kanggo wadhah, uga docker compose - alat kanggo ngotomatisasi panyebaran aplikasi ing wadhah, file YAML digunakake kanggo mbangun lan ngatur kontainer lan bab liyane sing gegandhengan (contone, jaringan, sistem file ngengkel kanggo nyimpen data).

Uga bisa digunakake kanggo ngatur pipelines kanggo CICD. Fitur liyane sing menarik digunakake ing mode kluster, sing diarani mode swarm (sadurunge versi 1.12 dikenal minangka swarm docker), sing ngidini sampeyan ngumpulake infrastruktur siji saka sawetara server kanggo mbukak wadhah. Ana dhukungan kanggo jaringan virtual ing ndhuwur kabeh server, ana keseimbangan beban sing dibangun, uga dhukungan kanggo rahasia kanggo wadhah.

File YAML saka docker compose bisa digunakake kanggo klompok kasebut kanthi modifikasi cilik, kanthi ngotomatisasi pangopènan klompok cilik lan medium kanggo macem-macem tujuan. Kanggo klompok gedhe, Kubernetes luwih disenengi amarga biaya pangopènan mode swarm bisa luwih gedhe tinimbang Kubernetes. Saliyane runC, minangka lingkungan eksekusi kanggo kontaner, sampeyan bisa nginstal, contone Wadhah kata

Nggarap Docker

Sawise instalasi lan konfigurasi, kita bakal nyoba mbangun kluster ing ngendi kita bakal masang GitLab lan Docker Registry kanggo tim pangembangan. Minangka server, Aku bakal nggunakake telung mesin virtual, kang tambahan bakal masang GlusterFS mbagekke FS, Aku bakal nggunakake minangka panyimpenan volume docker, Contone, kanggo mbukak versi gagal-aman saka pendaptaran docker. Komponen utama kanggo mbukak: Docker Registry, Postgresql, Redis, GitLab kanthi dhukungan kanggo GitLab Runner ing ndhuwur Swarm. Postgresql bakal diluncurake kanthi clustering Stolon, dadi sampeyan ora perlu nggunakake GlusterFS kanggo nyimpen data Postgresql. Data kritis liyane bakal disimpen ing GlusterFS.

Kanggo nyebarake GlusterFS ing kabeh server (disebut node1, node2, node3), sampeyan kudu nginstal paket, ngaktifake firewall, nggawe direktori sing dibutuhake:

# 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

Sawise instalasi, nggarap konfigurasi GlusterFS kudu diterusake saka siji simpul, contone 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

Banjur sampeyan kudu masang volume sing diasilake (prentah kudu ditindakake ing kabeh server):

# mount /srv/docker

Mode Swarm dikonfigurasi ing salah sawijining server, sing bakal dadi Pemimpin, sing liyane kudu melu kluster, saengga asil printah ing server pisanan kudu disalin lan dieksekusi ing liyane.

Persiyapan kluster awal, aku mbukak printah ing 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

Salin asil printah kapindho, eksekusi ing node2 lan node3:

# docker swarm join --token SWMTKN-x-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-xxxxxxxxx xx.xx.xx.xx:2377
This node joined a swarm as a manager.

Iki ngrampungake konfigurasi awal server, ayo miwiti konfigurasi layanan, printah sing bakal dieksekusi bakal diluncurake saka node1, kajaba wis ditemtokake.

Kaping pisanan, ayo nggawe jaringan kanggo wadhah:

# 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

Banjur kita menehi tandha server, iki perlu kanggo ngiket sawetara layanan menyang 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

Sabanjure, kita nggawe direktori kanggo nyimpen data etcd, panyimpenan KV sing Traefik lan Stolon perlu. Kaya Postgresql, iki bakal dadi wadah sing diikat menyang server, mula kita nglakokake perintah iki ing kabeh server:

# mkdir -p /srv/etcd

Sabanjure, gawe file kanggo ngatur etcd lan aplikasi:

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

Sawise sawetara wektu, priksa manawa kluster etcd wis munggah:

# 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

Nggawe direktori kanggo Postgresql, nglakokake printah ing kabeh server:

# mkdir -p /srv/pgsql

Sabanjure, gawe file kanggo ngatur 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

Kita nggawe rahasia, aplikasi 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

Sawetara wektu mengko (deleng output saka printah layanan docker lsyen kabeh layanan wis munggah) nginisialisasi kluster 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

Priksa kesiapan kluster 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

Kita ngatur traefik kanggo mbukak akses menyang kontaner saka njaba:

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

Kita miwiti Redis Cluster, kanggo iki kita nggawe direktori panyimpenan ing kabeh simpul:

# 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

Tambah Registry Docker:

06registry.yml

version: '3.7'

services:
  registry:
    image: registry:2.6
    networks:
      - traefik
    volumes:
      - registry_data:/var/lib/registry
    deploy:
      replicas: 1
      placement:
        constraints: [node.role == manager]
      restart_policy:
        condition: on-failure
      labels:
        - traefik.enable=true
        - traefik.http.routers.registry.rule=Host(`registry.example.com`)
        - traefik.http.services.registry.loadbalancer.server.port=5000
        - traefik.docker.network=traefik

volumes:
  registry_data:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: "/srv/docker/registry"

networks:
  traefik:
    external: true

# mkdir /srv/docker/registry
# docker stack deploy --compose-file 06registry.yml registry

Lan pungkasane - 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

Kahanan pungkasan kluster lan layanan:

# 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

Apa maneh sing bisa ditingkatake? Priksa manawa sampeyan ngatur Traefik kanggo nggarap wadah https, tambahake enkripsi tls kanggo Postgresql lan Redis. Nanging umume, sampeyan wis bisa menehi pangembang minangka PoC. Saiki ayo goleki alternatif kanggo Docker.

podho

Mesin liyane sing cukup kondhang kanggo mbukak wadhah sing diklompokaké miturut pods (pods, klompok wadhah sing dipasang bebarengan). Ora kaya Docker, ora mbutuhake layanan kanggo mbukak kontaner, kabeh karya ditindakake liwat perpustakaan libpod. Uga ditulis ing Go, mbutuhake runtime sing cocog karo OCI kanggo mbukak wadah kaya runC.

Docker lan kabeh, kabeh, kabeh

Nggarap Podman umume meh padha karo Docker, nganti sampeyan bisa nindakake kaya iki (klaim dening akeh sing wis nyoba, kalebu penulis artikel iki):

$ alias docker=podman

lan sampeyan bisa terus kerja. Umumé, kahanan karo Podman menarik banget, amarga yen versi awal Kubernetes makarya karo Docker, banjur wiwit babagan 2015, sawise standarisasi donya wadah (OCI - Open Container Initiative) lan pamisah Docker dadi containerd lan runC, alternatif kanggo Docker lagi dikembangake kanggo mbukak ing Kubernetes: CRI-O. Podman ing babagan iki minangka alternatif kanggo Docker, dibangun ing prinsip Kubernetes, kalebu klompok wadhah, nanging tujuan utama proyek kasebut yaiku kanggo mbukak wadhah gaya Docker tanpa layanan tambahan. Kanggo alasan sing jelas, ora ana mode swarm, amarga pangembang ujar manawa yen sampeyan butuh kluster, njupuk Kubernetes.

Instalasi

Kanggo nginstal ing Centos 7, aktifake repositori Extras, banjur instal kabeh nganggo printah:

# yum -y install podman

Fitur liyane

Podman bisa ngasilake unit kanggo systemd, saéngga ngrampungake masalah miwiti wadhah sawise urip maneh server. Kajaba iku, systemd diumumake kanthi bener minangka pid 1 ing wadhah kasebut. Kanggo mbangun kontaner, ana alat buildah sing kapisah, ana uga alat pihak katelu - analog saka docker-compose, sing uga ngasilake file konfigurasi sing kompatibel karo Kubernetes, saengga transisi saka Podman menyang Kubernetes dadi gampang.

Nggarap Podman

Amarga ora ana mode grombolan (iku kudu ngalih menyang Kubernetes yen kluster dibutuhake), kita bakal ngumpulake ing wadhah sing kapisah.

Instal podman-compose:

# yum -y install python3-pip
# pip3 install podman-compose

File konfigurasi sing diasilake kanggo podman rada beda, kayata kita kudu mindhah bagean volume sing kapisah langsung menyang bagean layanan.

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

Hasil karya:

# 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

Ayo ndeleng apa sing bakal diasilake kanggo systemd lan kubernetes, mula kita kudu ngerteni jeneng utawa id 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: {}

sistem:

# 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

Sayange, kajaba ngluncurake kontainer, unit sing digawe kanggo systemd ora nindakake apa-apa (contone, ngresiki wadhah lawas nalika layanan kasebut diwiwiti maneh), dadi sampeyan kudu nambahake barang kasebut dhewe.

Ing asas, Podman cukup kanggo nyoba apa kontaner, nransfer konfigurasi lawas kanggo docker-ngarang, lan banjur menyang Kubernetes, yen perlu, ing kluster, utawa njaluk alternatif sing luwih gampang kanggo nggunakake Docker.

rkt

Proyek kasebut lunga menyang arsip udakara nem sasi kepungkur amarga kasunyatane RedHat tuku, mula aku ora bakal mikir babagan iki kanthi luwih rinci. Umumé, ninggalake kesan sing apik banget, nanging dibandhingake karo Docker, lan luwih-luwih Podman, katon kaya gabungan. Ana uga distribusi CoreOS dibangun ing ndhuwur rkt (sanajan padha Originally duwe Docker), nanging uga rampung sawise tuku RedHat.

lampu kilat

Liyane siji proyek, penulis kang mung wanted kanggo mbangun lan mbukak kontaner. Miturut dokumentasi lan kode, penulis ora ngetutake standar, nanging mung mutusake kanggo nulis implementasine dhewe, sing, ing prinsip, dheweke nindakake.

temonan

Kahanan karo Kubernetes menarik banget: ing tangan siji, karo Docker, sampeyan bisa ngumpulake kluster (ing mode swarm), sing sampeyan bisa uga mbukak lingkungan produksi kanggo klien, utamane kanggo tim cilik (3-5 wong). ), utawa kanthi beban sakabèhé cilik, utawa kurang kepinginan kanggo mangerteni seluk-beluk nyetel Kubernetes, kalebu kanggo beban dhuwur.

Podman ora menehi kompatibilitas lengkap, nanging nduweni kauntungan penting - kompatibilitas karo Kubernetes, kalebu alat tambahan (buildah lan liya-liyane). Mulane, aku bakal nyedhaki pilihan alat kanggo karya kaya ing ngisor iki: kanggo tim cilik, utawa kanthi anggaran winates - Docker (kanthi mode swarm bisa), kanggo ngembangake dhewe ing localhost pribadi - kanca Podman, lan kanggo wong liya. - Kubernetes.

Aku ora yakin yen kahanan karo Docker ora bakal owah ing mangsa ngarep, sawise kabeh, dheweke dadi pionir, lan uga alon-alon standarisasi langkah demi langkah, nanging Podman, kanthi kabeh kekurangane (mung dianggo ing Linux, ora ana clustering). , perakitan lan tumindak liyane minangka keputusan pihak katelu) masa depan luwih jelas, mula aku ngajak kabeh wong kanggo ngrembug temuan kasebut ing komentar.

PS Tanggal 3 Agustus kita miwiti "Kursus video Dockering ngendi sampeyan bisa sinau luwih akeh babagan karyane. Kita bakal nganalisa kabeh alat: saka abstraksi dhasar nganti paramèter jaringan, nuansa nggarap macem-macem sistem operasi lan basa pamrograman. Sampeyan bakal kenal karo teknologi kasebut lan ngerti ngendi lan cara paling apik nggunakake Docker. Kita uga bakal nuduhake kasus praktik paling apik.

Biaya pre-order sadurunge release: 5000 rubles. Program "Kursus Video Docker" bisa ditemokake ing kaca kursus.

Source: www.habr.com

Add a comment