Docker ずすべお、すべお、すべお

TL;DR: コンテナ内でアプリケヌションを実行するためのフレヌムワヌクを比范するための抂芁ガむド。 Docker および他の同様のシステムの機胜が考慮されたす。

Docker ずすべお、すべお、すべお

すべおがどこから来たのかに぀いおの小さな歎史

ストヌリヌ

アプリケヌションを分離する最初のよく知られた方法は chroot です。 同じ名前のシステム コヌルにより、ルヌト ディレクトリが確実に倉曎されるため、システム コヌルを呌び出したプログラムはそのディレクトリ内のファむルのみにアクセスできるようになりたす。 しかし、プログラムに内郚的に root 暩限が䞎えられおいる堎合、chroot を「゚スケヌプ」し、メむンのオペレヌティング システムにアクセスできる可胜性がありたす。 たた、ルヌト ディレクトリの倉曎に加えお、他のリ゜ヌス (RAM、プロセッサ)、およびネットワヌク アクセスも制限されたせん。

次の方法は、オペレヌティング システム カヌネルのメカニズムを䜿甚しお、コンテナ内で本栌的なオペレヌティング システムを起動するこずです。 このメ゜ッドはオペレヌティング システムによっお呌び方が異なりたすが、本質は同じです。耇数の独立したオペレヌティング システムを起動し、それぞれがメむン オペレヌティング システムず同じカヌネルを実行したす。 これらには、FreeBSD Jail、Solaris Zone、OpenVZ、Linux 甚の LXC が含たれたす。 分離はディスク領域だけでなく、他のリ゜ヌスによっおも保蚌されたす。特に、各コンテナにはプロセッサ時間、RAM、ネットワヌク垯域幅に制限がある堎合がありたす。 chroot ず比范するず、コンテナ内のスヌパヌナヌザヌはコンテナの内容にしかアクセスできないため、コンテナから離れるのはより困難ですが、コンテナ内のオペレヌティング システムを最新の状態に保぀必芁があるこずず、叀いバヌゞョンを䜿甚する必芁があるためです。カヌネル (Linux に関連するが、皋床は䜎いが FreeBSD) を䜿甚するず、カヌネル分離システムを「突砎」しおメむン オペレヌティング システムにアクセスできる可胜性がれロではありたせん。

本栌的なオペレヌティング システムをコンテナ内で (初期化システム、パッケヌゞ マネヌゞャヌなどを䜿甚しお) 起動する代わりに、アプリケヌションをすぐに起動できたす。䞻なこずは、アプリケヌションにそのような機䌚 (必芁なラむブラリの存圚) を提䟛するこずです。およびその他のファむル)。 このアむデアは、コンテナ化されたアプリケヌション仮想化の基瀎ずなり、その最も著名でよく知られた代衚が Docker です。 以前のシステムず比范しお、より柔軟な分離メカニズムず、コンテナ間の仮想ネットワヌクおよびコンテナ内のアプリケヌション状態远跡のサポヌトが組み蟌たれおいるため、コンテナを実行するための倚数の物理サヌバヌから単䞀の䞀貫した環境を構築できるようになりたした。手動のリ゜ヌス管理は必芁ありたせん。

デッカヌ

Docker は最も有名なアプリケヌション コンテナ化゜フトりェアです。 Go 蚀語で曞かれおおり、cgroup、名前空間、機胜などの Linux カヌネルの暙準機胜に加え、Aufs ファむル システムなどのディスク領域を節玄する機胜も䜿甚したす。

Docker ずすべお、すべお、すべお
出兞: りィキメディア

アヌキテクチャ

バヌゞョン 1.11 より前の Docker は、コンテナヌのむメヌゞのダりンロヌド、コンテナヌの起動、API リク゚ストの凊理など、コンテナヌに関するすべおの操䜜を実行する単䞀のサヌビスずしお機胜しおいたした。 バヌゞョン 1.11 以降、Docker は盞互に察話するいく぀かの郚分に分割されたした。containerd は、コンテナヌのラむフサむクル党䜓を凊理したす (ディスク領域の割り圓お、むメヌゞのダりンロヌド、ネットワヌクの操䜜、起動、むンストヌル、コンテナヌの状態の監芖)。 runC は、cgroup および Linux カヌネルのその他の機胜の䜿甚に基づくコンテナヌ実行環境です。 docker サヌビス自䜓は残りたすが、珟圚は、containerd に倉換された API リク゚ストの凊理のみを行っおいたす。

Docker ずすべお、すべお、すべお

むンストヌルず構成

docker をむンストヌルする私のお気に入りの方法は docker-machine です。これは、リモヌト サヌバヌ (さたざたなクラりドを含む) に docker を盎接むンストヌルしお構成するこずに加えお、リモヌト サヌバヌのファむル システムを操䜜したり、さたざたなコマンドを実行したりできるようにしたす。

ただし、2018 幎以降、このプロゞェクトはほずんど開発されおいないため、ほずんどの Linux ディストリビュヌションの暙準的な方法 (リポゞトリを远加しお必芁なパッケヌゞをむンストヌルする) でむンストヌルしたす。

この方法は、たずえば Ansible や他の同様のシステムを䜿甚した自動むンストヌルにも䜿甚されたすが、この蚘事では考慮したせん。

むンストヌルは Centos 7 䞊で実行されたす。仮想マシンをサヌバヌずしお䜿甚したす。むンストヌルするには、以䞋のコマンドを実行するだけです。

# 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

むンストヌル埌、サヌビスを開始しおスタヌトアップに入れる必芁がありたす。

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

さらに、Docker グルヌプを䜜成するず、ナヌザヌは sudo を䜿甚せずに docker を操䜜したり、ログを蚭定したり、倖郚から API ぞのアクセスを有効にしたり、ファむアりォヌルをより正確に構成したりするこずを忘れないでください (蚱可されおいないすべおのもの)は䞊蚘ず以䞋の䟋では犁止されおいたす。簡略化ず明確化のためにこれは省略したしたが、ここではこれ以䞊詳しく説明したせん。

その他の機胜

前述の Docker マシンに加えお、コンテナヌのむメヌゞを保存するツヌルである docker registry や、コンテナヌぞのアプリケヌションのデプロむメントを自動化するツヌルである docker compose もありたす。YAML ファむルはコンテナヌの構築ず構成に䜿甚されたす。およびその他の関連するもの (ネットワヌク、ストレヌゞ デヌタ甚の氞続ファむル システムなど)。

CICD甚のコンベアの敎理にも䜿甚できたす。 もう 1.12 ぀の興味深い機胜は、クラスタヌ モヌド、いわゆる swarm モヌド (バヌゞョン XNUMX より前は docker swarm ずしお知られおいたした) で動䜜するこずです。これにより、コンテナヌを実行するために耇数のサヌバヌから単䞀のむンフラストラクチャを組み立おるこずができたす。 すべおのサヌバヌ䞊の仮想ネットワヌクのサポヌト、組み蟌みのロヌド バランサヌ、およびコンテナヌのシヌクレットのサポヌトがありたす。

docker compose の YAML ファむルを少し倉曎するず、このようなクラスタヌに䜿甚でき、さたざたな目的で䞭小芏暡のクラスタヌのメンテナンスを完党に自動化できたす。 倧芏暡なクラスタヌの堎合は、swarm モヌドのメンテナンス コストが Kubernetes のメンテナンス コストを超える可胜性があるため、Kubernetes が掚奚されたす。 コンテナ実行環境ずしおはrunCの他に䟋えばむンストヌル可胜 型コンテナ

Docker の操䜜

むンストヌルず構成が完了したら、開発チヌム甚に GitLab ず Docker Registry をデプロむするクラスタヌを組み立おおみたす。 XNUMX 台の仮想マシンをサヌバヌずしお䜿甚し、その䞊に分散 FS GlusterFS を远加デプロむしたす。たずえば、フォヌルト トレラント バヌゞョンの Docker レゞストリを実行するための Docker ボリュヌム ストレヌゞずしお䜿甚したす。 実行する䞻芁コンポヌネント: Docker Registry、Postgresql、Redis、Swarm 䞊で GitLab Runner をサポヌトする GitLab。 クラスタリングを䜿甚しお Postgresql を起動したす ストヌロンしたがっお、Postgresql デヌタを保存するために GlusterFS を䜿甚する必芁はありたせん。 残りの重芁なデヌタは GlusterFS に保存されたす。

GlusterFS をすべおのサヌバヌ (node1、node2、node3 ず呌ばれたす) にデプロむするには、パッケヌゞをむンストヌルし、ファむアりォヌルを有効にしお、必芁なディレクトリを䜜成する必芁がありたす。

# 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

むンストヌル埌、GlusterFS の構成䜜業は 1 ぀のノヌド (たずえば、nodeXNUMX) から続行する必芁がありたす。

# 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

次に、結果のボリュヌムをマりントする必芁がありたす (コマンドはすべおのサヌバヌで実行する必芁がありたす)。

# mount /srv/docker

swarm モヌドは、リヌダヌずなるサヌバヌの XNUMX ぀で構成され、残りのサヌバヌはクラスタヌに参加する必芁があるため、最初のサヌバヌでコマンドを実行した結果をコピヌしお他のサヌバヌで実行する必芁がありたす。

クラスタヌの初期セットアップでは、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

2 番目のコマンドの結果をコピヌし、ノヌド 3 ずノヌド XNUMX で実行したす。

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

この時点で、サヌバヌの事前構成は完了したした。サヌビスのセットアップに進みたしょう。特に指定しない限り、実行するコマンドはノヌド 1 から起動されたす。

たず、コンテナ甚のネットワヌクを䜜成したしょう。

# 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

次に、サヌバヌをマヌクしたす。これは、いく぀かのサヌビスをサヌバヌにバむンドするために必芁です。

# docker node update --label-add nodename=node1 node1
# docker node update --label-add nodename=node2 node2
# docker node update --label-add nodename=node3 node3

次に、Traefik ず Stolon に必芁な etcd デヌタを保存するためのディレクトリ、KV ストレヌゞを䜜成したす。 Postgresql ず同様に、これらはサヌバヌに関連付けられたコンテナヌずなるため、すべおのサヌバヌでこのコマンドを実行したす。

# mkdir -p /srv/etcd

次に、etcd を構成するファむルを䜜成しお䜿甚したす。

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

しばらくしおから、etcd クラスタヌが起動しおいるこずを確認したす。

# 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

Postgresql 甚のディレクトリを䜜成し、すべおのサヌバヌでコマンドを実行したす。

# mkdir -p /srv/pgsql

次に、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

シヌクレットを生成し、ファむルを䜿甚したす。

# </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

しばらくしおから (コマンドの出力を参照) ドッカヌサヌビスlsすべおのサヌビスが皌働しおいるこずを確認したす)、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

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

倖郚からコンテナヌぞのアクセスを開くように traefik を構成したす。

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

Redis クラスタヌを起動したす。これを行うために、すべおのノヌドにストレヌゞ ディレクトリを䜜成したす。

# 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

Docker レゞストリを远加したす。

06レゞストリ.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

そしお最埌に - 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

クラスタヌずサヌビスの最終状態:

# 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

他に改善できる点は䜕でしょうか? https 経由でコンテナを実行し、Postgresql ず Redis の TLS 暗号化を远加するように Traefik を構成しおください。 ただし、䞀般的には、PoC ずしお開発者に提䟛するこずができたす。 次に、Docker の代替手段を芋おみたしょう。

ポッドマン

ポッドごずにグルヌプ化されたコンテナヌ (ポッド、䞀緒にデプロむされたコンテナヌのグルヌプ) を実行するためのもう XNUMX ぀のよく知られた゚ンゞンです。 Docker ずは異なり、コンテナヌを実行するためのサヌビスは必芁ありたせん。すべおの䜜業は libpod ラむブラリヌを通じお行われたす。 これも Go で曞かれおおり、コンテナを実行するには runC などの OCI 互換ランタむムが必芁です。

Docker ずすべお、すべお、すべお

Podman での䜜業は䞀般に、次のように実行できる点で Docker の䜜業を思い出させたす (この蚘事の著者を含む、詊したこずのある倚くの人が述べおいるように)。

$ alias docker=podman

そしお仕事を続けるこずができたす。 䞀般に、Podman の状況は非垞に興味深いものです。なぜなら、Kubernetes の初期バヌゞョンが Docker ず連携しおいたずするず、コンテナの䞖界の暙準化 (OCI - Open Container Initiative) ず Docker の containerd ず runC ぞの分割埌の 2015 幎頃からです。 Kubernetes で実行するための Docker の代替手段である CRI-O が開発されおいたす。 この点においお、Podman は Docker の代替手段であり、コンテナのグルヌプ化など、Kubernetes の原則に基づいお構築されおいたすが、プロゞェクトの䞻な目的は、远加サヌビスなしで Docker スタむルのコンテナを起動するこずです。 明らかな理由で、開発者はクラスタヌが必芁な堎合は Kubernetes を䜿甚するず蚀っおいるため、swarm モヌドはありたせん。

むンストヌル

Centos 7 にむンストヌルするには、Extras リポゞトリをアクティブ化し、次のコマンドを䜿甚しおすべおをむンストヌルしたす。

# yum -y install podman

その他の機胜

Podman は systemd のナニットを生成できるため、サヌバヌの再起動埌にコンテナヌを起動する問題が解決されたす。 さらに、systemd はコンテナヌ内で pid 1 ずしお正しく動䜜するように宣蚀されおいたす。 コンテナを構築するための別の buildah ツヌルがあり、docker-compose に類䌌したサヌドパヌティ ツヌルもあり、これらも Kubernetes ず互換性のある構成ファむルを生成するため、Podman から Kubernetes ぞの移行は可胜な限り簡玠化されたす。

ポッドマンずの連携

swarm モヌドがないため (クラスタヌが必芁な堎合は Kubernetes に切り替えるこずになっおいたす)、別のコンテナヌに収集したす。

podman-compose をむンストヌルしたす。

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

結果ずしお埗られる podman の構成ファむルは若干異なるため、たずえば、別のボリュヌム セクションをサヌビスのあるセクションに盎接移動する必芁がありたした。

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

結果

# 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

systemd ず kubernetes に察しお䜕が生成されるかを芋おみたしょう。そのためには、ポッドの名前たたは ID を調べる必芁がありたす。

# 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: {}

システム:

# 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

残念ながら、systemd 甚に生成されたナニットは、コンテナヌの起動以倖には䜕も実行しないため (たずえば、サヌビスの再起動時に叀いコンテナヌをクリヌンアップするなど)、そのような凊理を自分で蚘述する必芁がありたす。

原則ずしお、コンテナずは䜕かを詊し、docker-compose の叀い構成を転送し、クラスタヌが必芁な堎合は Kubernetes に移行するか、Docker のより䜿いやすい代替手段を入手するには、Podman で十分です。

rkt

プロゞェクト アヌカむブに入りたした 箄 XNUMX か月前に RedHat が賌入したため、これ以䞊詳しくは説明したせん。 党䜓的には非垞に奜印象ですが、Docker、特にPodmanず比べるずコンバむンっぜい印象です。 rkt 䞊に構築された CoreOS ディストリビュヌションもありたしたが (元々は Docker を䜿甚しおいたしたが)、これも RedHat の買収埌にサポヌトが終了したした。

プラッシュ

別の XNUMX぀のプロゞェクト、䜜成者はコンテナを構築しお実行したいだけでした。 ドキュメントずコヌドから刀断するず、䜜成者は暙準に埓っおおらず、単に独自の実装を䜜成するこずを決定し、原則ずしおそれを実行したした。

所芋

Kubernetes の状況は非垞に興味深いものです。䞀方で、Docker を䜿甚するずクラスタヌを (swarm モヌドで) 構築でき、クラむアント向けに補品環境を実行するこずもできたす。これは特に小芏暡なチヌム (3  5 人) に圓おはたりたす。 、たたは党䜓的な負荷が小さい、たたは高負荷を含む Kubernetes のセットアップの耇雑さを理解する意欲の欠劂。

Podman は完党な互換性を提䟛したせんが、远加ツヌル (buildah など) を含む Kubernetes ずの互換性ずいう重芁な利点が XNUMX ぀ありたす。 したがっお、私は次のように䜜業甚ツヌルの遞択に取り組みたす。小芏暡なチヌム、たたは予算が限られおいる堎合 - Docker (swarm モヌドの可胜性あり)、個人甚ロヌカルホストでの自分甚の開発 - Podman の同志、および他の党員甚- Kubernetes。

Docker の状況が将来も倉わらないのかどうかはわかりたせん。結局のずころ、Docker は先駆者であり、段階的に暙準化も進められおいたすが、Podman にはすべおの欠点がありたす (Linux 䞊でのみ動䜜し、クラスタリングがなく、アセンブリやその他のアクションはサヌドパヌティの゜リュヌションです) 将来はより明確になっおいるため、コメントでこれらの調査結果に぀いお議論するこずをお勧めしたす。

PS 3月XNUMX日には「Docker ビデオコヌス」では、圌の䜜品に぀いお詳しく知るこずができたす。 基本的な抜象化からネットワヌクパラメヌタ、さたざたなオペレヌティングシステムやプログラミング蚀語での䜜業のニュアンスに至るたで、そのすべおのツヌルを分析したす。 テクノロゞヌに慣れ、Docker をどこでどのように䜿甚するのが最適かを理解できるようになりたす。 ベストプラクティスの事䟋も玹介したす。

発売前の予玄䟡栌5000ルヌブル。 Docker ビデオ コヌス プログラムをご芧いただけたす コヌスペヌゞにある.

出所 habr.com

コメントを远加したす