zaki work log

作業ログやら生活ログやらなんやら

[Oracle Linux] arm64アーキテクチャのA1.FlexのVMでDocker版NetBoxをビルド&デプロイする (Ubuntu / Oracle Linux)

Oracle Cloudで無料で使えるA1.FlexシェイプのVM(arm64アーキテクチャ)でNetBoxをDockerでデプロイしてみました。
NetBoxのコンテナイメージはamd64版しか公開されていないため、arm64アーキテクチャでコンテナ版をデプロイするには、自前でビルドする必要があります。 ただ、ビルドのためのスクリプト類は用意されてるので、簡単にビルドできます。

ビルド自体は以前試したここの手順の通りで、NetBox本体のリポジトリのtag名などを指定すれば、そのバージョンのイメージをビルドできます。

zaki-hmkc.hatenablog.com

Oracle Cloud A1.FlexのインスタンスへのDockerエンジン本体のインストールはこちら
Docker Composeのインストールはpip版Docker Plugin版どちらかでインストールする。本エントリではDocker PluginとしてインストールしたCompose v2でお試し。

Ubuntu 20.04 / Oracle Linux 8

$ git clone -b release https://github.com/netbox-community/netbox-docker.git
$ cd netbox-docker/

で、本来であれば必要に応じてdocker-compose.override.ymlを用意したりし、upすればデプロイできるのですが、

netbox-docker-netbox-1               | standard_init_linux.go:228: exec user process caused: exec format error
netbox-docker-netbox-1 exited with code 1

起動に失敗します。
これは、NetBoxのコンテナイメージがamd64向けしか公開されておらず、でも実行しようとしてるプラットフォームはarm64のため起動に失敗している状態のため、何をどう頑張っても起動できません。

f:id:zaki-hmkc:20210930230153p:plain

$ docker run --rm netboxcommunity/netbox:v3.0 
WARNING: The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested
standard_init_linux.go:228: exec user process caused: exec format error

じゃあどうすればいいかと言うと、実行したいプラットフォーム用のイメージを自分でビルドすれば(今回動かしたいNetBoxについては)OKです。
NetBoxのコンテナイメージは、(わかりにくいけど)alpineがベースイメージになっていて、このイメージはarm64用が用意されているため、このイメージをベースにビルドします。特定プラットフォーム用のビルドというとクロスコンパイルみたいなイメージがありますが、単に動かしたいarm64のプラットフォーム(のDockerエンジン)上でビルドすればOKです。

f:id:zaki-hmkc:20210930230417p:plain

NetBoxのコンテナイメージビルドは、デプロイに使用するComposeファイルを提供しているnetbox-dockerリポジトリに、ビルド用のスクリプトも同梱しているため、そのスクリプトを実行すればよいので簡単にビルドできます。

github.com

2021.09.30時点で最新のv3.0.4でお試し。
ビルドスクリプトの引数に、NetBox本体のリポジトリのターゲットバージョンのtagを指定します。

github.com

$ ./build.sh v3.0.4

ビルドはこれだけ。そこそこ時間かかる。
ビルド完了すると以下の通り。

$ docker image ls
REPOSITORY               TAG           IMAGE ID       CREATED         SIZE
netboxcommunity/netbox   latest-ldap   955e60dabcfc   4 minutes ago   442MB
netboxcommunity/netbox   v3.0-ldap     955e60dabcfc   4 minutes ago   442MB
netboxcommunity/netbox   v3.0.4-ldap   955e60dabcfc   4 minutes ago   442MB
netboxcommunity/netbox   latest        cffca943100b   4 minutes ago   436MB
netboxcommunity/netbox   v3.0          cffca943100b   4 minutes ago   436MB
netboxcommunity/netbox   v3.0.4        cffca943100b   4 minutes ago   436MB

v3.0のタグを含めてビルドできてるので、そのままdocker compose upします。
(標準で用意されているdocker-compose.ymlv3.0タグ前提の記述なので)

$ docker compose up 
[+] Running 6/6
 ⠿ Container netbox-docker-redis-cache-1          Creat...                                         0.0s
 ⠿ Container netbox-docker-postgres-1             Created                                          0.0s
 ⠿ Container netbox-docker-redis-1                Created                                          0.0s
 ⠿ Container netbox-docker-netbox-housekeeping-1  Recreated                                        0.1s
 ⠿ Container netbox-docker-netbox-worker-1        Rec...                                           0.1s
 ⠿ Container netbox-docker-netbox-1               Recreated                                        0.1s
Attaching to netbox-docker-netbox-1, netbox-docker-netbox-housekeeping-1, netbox-docker-netbox-worker-1, netbox-docker-postgres-1, netbox-docker-redis-1, netbox-docker-redis-cache-1
netbox-docker-redis-cache-1          | 1:C 30 Sep 2021 12:11:13.783 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo

[...]

netbox-docker-netbox-1               | ✅ Initialisation is done.
netbox-docker-netbox-1               | ⏳ Waiting for control socket to be created... (1/10)
netbox-docker-netbox-1               | 2021/09/30 12:12:15 [warn] 7#7 Unit is running unprivileged, then it cannot use arbitrary user and group.
netbox-docker-netbox-1               | 2021/09/30 12:12:15 [info] 7#7 unit started
netbox-docker-netbox-1               | 2021/09/30 12:12:15 [info] 20#20 discovery started
netbox-docker-netbox-1               | 2021/09/30 12:12:15 [notice] 20#20 module: python 3.9.5 "/usr/lib/unit/modules/python3.unit.so"
netbox-docker-netbox-1               | 2021/09/30 12:12:15 [info] 7#7 controller started
netbox-docker-netbox-1               | 2021/09/30 12:12:15 [notice] 7#7 process 20 exited with code 0
netbox-docker-netbox-1               | 2021/09/30 12:12:15 [info] 22#22 router started
netbox-docker-netbox-1               | 2021/09/30 12:12:15 [info] 22#22 OpenSSL 1.1.1l  24 Aug 2021, 101010cf
netbox-docker-netbox-1               | ⚙️ Applying configuration from /etc/unit/nginx-unit.json
netbox-docker-netbox-1               | 2021/09/30 12:12:16 [info] 26#26 "netbox" application started
netbox-docker-netbox-1               | 🧬 loaded config '/etc/netbox/config/configuration.py'
netbox-docker-netbox-1               | 🧬 loaded config '/etc/netbox/config/extra.py'
netbox-docker-netbox-1               | 🧬 loaded config '/etc/netbox/config/logging.py'
netbox-docker-netbox-1               | 🧬 loaded config '/etc/netbox/config/plugins.py'
netbox-docker-netbox-1               | ✅ Unit configuration loaded successfully
netbox-docker-netbox-1               | 2021/09/30 12:12:18 [notice] 7#7 process 18 exited with code 0

はい。
あとはセキュリティグループなどの設定を確認しつつwebアクセスすればこの通り。

f:id:zaki-hmkc:20210930230721p:plain

Oracle Linux 7.9の場合

Gitバージョンでトラップあるので注意。
それ以外はUbuntu 20.04 / Oracle Linux 8と同じ。

$ ./build.sh v3.0.4
▶️ ./build.sh v3.0.4
🌐 Checking out 'v3.0.4' of NetBox from the url 'https://github.com/netbox-community/netbox.git' into '.netbox'
Note: checking out '84d83fbd143f26097db9464a46657b7a65ab27cb'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b new_branch_name

fatal: git fetch-pack: expected shallow list

標準リポジトリyum installできるGitのバージョンが1系のため、必要な操作ができないエラーになります。

$ git version
git version 1.8.3.1

IUSのリポジトリからインストールできたら簡単かな?と思ったけど、あいにくこのリポジトリではarm64版のパッケージはありません。
探した結果、Oracle Linux 7.9では標準リポジトリrh-git218-git-all.noarchというパッケージが用意されています。(名前…いいのかな、これw)

$ sudo yum install rh-git218-git-all

このパッケージをインストールすると、/opt/rh/rh-git218/root/usr/bin/gitにv2系のGitがインストールされます。

$ /opt/rh/rh-git218/root/usr/bin/git version
git version 2.18.4

PATH設定してリビルド

$ export PATH=/opt/rh/rh-git218/root/usr/bin:$PATH
$ ./build.sh v3.0.4
▶️ ./build.sh v3.0.4
/opt/rh/rh-git218/root/usr/libexec/git-core/git-remote-https: error while loading shared libraries: libcurl-httpd24.so.4: cannot open shared object file: No such file or directory
❌ Remote branch 'v3.0.4' not found in 'https://github.com/netbox-community/netbox.git'; Nothing to do

をしようとすると、更にエラー。
検索すると以下がヒット。

bugzilla.redhat.com

$ sudo ln -s /opt/rh/httpd24/root/usr/lib64/libcurl-httpd24.so.4 /lib64/

この状態で更にリビルトしようとすると、同じように以下のエラー

$ ./build.sh v3.0.4
▶️ ./build.sh v3.0.4
/opt/rh/rh-git218/root/usr/libexec/git-core/git-remote-https: error while loading shared libraries: libnghttp2-httpd24.so.14: cannot open shared object file: No such file or directory
❌ Remote branch 'v3.0.4' not found in 'https://github.com/netbox-community/netbox.git'; Nothing to do

これも同様に、

$ sudo ln -s /opt/rh/httpd24/root/usr/lib64/libnghttp2-httpd24.so.14 /lib64/

する。
今度こそリビルド。

$ ./build.sh v3.0.4

しばらく待てばビルド完了するはず。

$ docker image ls
REPOSITORY               TAG           IMAGE ID       CREATED              SIZE
netboxcommunity/netbox   latest-ldap   feae491462bb   41 seconds ago       442MB
netboxcommunity/netbox   v3.0-ldap     feae491462bb   41 seconds ago       442MB
netboxcommunity/netbox   v3.0.4-ldap   feae491462bb   41 seconds ago       442MB
netboxcommunity/netbox   latest        b746cc1f2603   About a minute ago   436MB
netboxcommunity/netbox   v3.0          b746cc1f2603   About a minute ago   436MB
netboxcommunity/netbox   v3.0.4        b746cc1f2603   About a minute ago   436MB

[...]

あとは同じようにdocker-compose.override.ymlを作成し、docker compose up -dでデプロイできます。

$ docker compose up -d
[+] Running 1/3
 ⠴ redis-cache Pulling                                                                                          1.6s
   ⠿ 552d1f2373af Already exists                                                                                0.0s
   ⠋ 08b93f529d04 Waiting                                                                                       0.1s
[+] Running 1/169 Waiting                                                                                       0.1s
 ⠦ redis-cache Pulling                                                                                          1.7s

[...]

現状だとHTTPアクセスになっており経路が暗号化されないのでその点は注意。
あくまでお試しということで、セキュリティグループで自分のIPアドレスでのみアクセスできるようにするなどフィルタした方がよい。

Docker PluginとしてDocker Compose (v2) のインストールとお試し実行 (arm64 / Oracle Cloud A1.Flex)

気が付いたらCompose v2がリリース版になってました。

github.com

これまでのようにdocker-composeコマンド単体でなく、Docker Pluginとして利用する形式になっています。
あとv1系のときはx86_64のバイナリしかなかったけど、arm64やs390xのバイナリも配布されるようになってるようです。
Linuxの場合は現状ではマニュアルインストールとなっており、必要なバイナリを所定のパスにダウンロードして利用します。

バイナリはReleaseページから。

github.com

インストール手順はDockerのドキュメント参照。 ただし、2021.9.29時点でまだバージョンがv2.0.0-rc.3になっているのでここをv2.0.0に置き換えて、アーキテクチャも環境に合わせる。今回はarm64で。

docs.docker.com

Dockerがインストールされてる状態で以下実行(arm64の場合)。

$ mkdir -p ~/.docker/cli-plugins/
$ curl -SL https://github.com/docker/compose/releases/download/v2.0.0/docker-compose-linux-arm64 -o ~/.docker/cli-plugins/docker-compose
$ chmod +x ~/.docker/cli-plugins/docker-compose

これでdocker composeが実行できるようになります。(docker-composeでなく)

$ docker compose version
Docker Compose version v2.0.0

サンプル用Composeファイルは以下の通り。

$ cat docker-compose.yml 
version: '3'
services:
  httpd:
    image: httpd
    ports:
    - 8080:80
$ docker compose up -d
[+] Running 6/6
 ⠿ httpd Pulled                                                                      4.9s
   ⠿ 896f18f54b28 Pull complete                                                      2.1s
   ⠿ 678f4022827b Pull complete                                                      2.9s
   ⠿ c18c6f886b61 Pull complete                                                      3.2s
   ⠿ 8f8bb463f1da Pull complete                                                      4.4s
   ⠿ 5590d606630f Pull complete                                                      4.5s
[+] Running 2/2
 ⠿ Network compose_default    Created                                                0.2s
 ⠿ Container compose-httpd-1  Started                                                0.6s
$ docker compose ps
NAME                COMMAND              SERVICE             STATUS              PORTS
compose-httpd-1     "httpd-foreground"   httpd               running             0.0.0.0:8080->80/tcp, :::8080->80/tcp

Oracle CloudのA1.FlexコンピュートインスタンスOracle Linux 8とUbuntu20.04で確認。
どちらも同じ手順で実行確認。

つい先日arm64向けバイナリがないということでpipを使ってインストールしたけど、v2がリリースバージョンになってるしこっちでよいかな。

zaki-hmkc.hatenablog.com

[Oracle Cloud/A1.Flex] armアーキテクチャのLinuxへpipでDocker Composeインストール

Oracle CloudのA1.Flexのように、aarch64/arm64のアーキテクチャへのDocker本体のインストールは以下のとおり公式の手順で(ディストリビューションが対応してれば)インストールできる。

zaki-hmkc.hatenablog.com

ただし、Docker Composeについては公式で配布されてるバイナリはamd64しかないため、公式の手順通りにインストールしてもarm64上のホストだと実行できない (※ 9/29追記: Docker Compose v2になってarm64版も公開されるようになっており、Docker Pluginとして利用可能) 。

github.com

「Cloud Integrations」とされてるこちらのComposeだとarm64版も配布されてて試した限り動かせそうだけど、コマンド体系が微妙に違う?(詳細よくわからず)

github.com

使い慣れてるのDocker Composeをarm64のホストにインストールするには、pipでインストールするのが簡単そうだったので試してみた。

docs.docker.com

ドキュメントの「Install Compose」->「Alternative install options」->「Install using pip」を参照。 公式ではvirtualenv推奨となってるけど本エントリではとりあえずsudoでシステムワイドに入れてる。

環境はOracle Cloudの無償枠A1.FlexVMを使用。

Ubuntu 20.04

pipはデフォルトでは入ってないのでaptでインストールする。

$ sudo apt-get install python3-pip
$ sudo pip install docker-compose

sudoつけてpipで入れると/usr/local/bin/docker-composeにインストールされる。
venvで環境分けた場合に以下のエラーが出るのであれば、venv作成時に--system-site-packagesつけておけばよいかも。

  error: invalid command 'bdist_wheel'
  ----------------------------------------
  ERROR: Failed building wheel for docopt
$ docker-compose version
docker-compose version 1.29.2, build unknown
docker-py version: 5.0.2
CPython version: 3.8.10
OpenSSL version: OpenSSL 1.1.1f  31 Mar 2020

サンプル実行。Compose Fileはこんな感じ。

version: '3'
services:
  httpd:
    image: httpd
    ports:
    - 8080:80
$ docker-compose up -d
Creating network "compose_default" with the default driver
Pulling httpd (httpd:)...
latest: Pulling from library/httpd
d10c227306ce: Pull complete
11d295310975: Pull complete
0bd1854e47c1: Pull complete
f7ee7d85565b: Pull complete
6f13eaecb486: Pull complete
Digest: sha256:ead5178e79caa09343750bb03ff98e87ed57c537f2ae12685beb3a573cce8f55
Status: Downloaded newer image for httpd:latest
Creating compose_httpd_1 ... done
$ docker-compose ps
     Name             Command        State                  Ports                
---------------------------------------------------------------------------------
compose_httpd_1   httpd-foreground   Up      0.0.0.0:8080->80/tcp,:::8080->80/tcp
$ curl localhost:8080
<html><body><h1>It works!</h1></body></html>

Oracle Linux 8/7.9

Oracle Linuxの場合は8も7.9も手順は同じ。
pip3は始めから使用できる。

$ sudo pip3 install docker-compose

次のエラーが出る場合は…

Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-build-_2zf4o3l/pynacl/
Building wheels for collected packages: pynacl, pyrsistent
  Building wheel for pynacl (PEP 517) ... error
  build/temp.linux-aarch64-3.6/_sodium.c:22:12: fatal error: pyconfig.h: No such file or directory
   #  include <pyconfig.h>
              ^~~~~~~~~~~~
  compilation terminated.
  error: command 'gcc' failed with exit status 1
  ----------------------------------------
  ERROR: Failed building wheel for pynacl

この場合はdevel系のパッケージを追加して再度pipインストールする。

$ sudo dnf install python3-devel

インストールできればこの通り。サンプルはUbuntuの時と同じもの。

$ docker-compose up -d
Creating network "compose_default" with the default driver
Pulling httpd (httpd:)...
latest: Pulling from library/httpd
d10c227306ce: Pull complete
11d295310975: Pull complete
0bd1854e47c1: Pull complete
f7ee7d85565b: Pull complete
6f13eaecb486: Pull complete
Digest: sha256:ead5178e79caa09343750bb03ff98e87ed57c537f2ae12685beb3a573cce8f55
Status: Downloaded newer image for httpd:latest
Creating compose_httpd_1 ... done
$ curl localhost:8080
<html><body><h1>It works!</h1></body></html>

[Oracle Cloud] 無料枠のA1.FlexのコンピュートインスタンスにDockerインストール (Ubuntu/Oracle Linux)

少し前に比べると、最大で4CPUs・RAM24GBまで無料で使用できるA1.Flexのコンピュートインスタンス(VM)を作成しやすくなったのでお試し。
結論から言うとVMのイメージはUbuntuであれば問題なし。
Oracle Linuxの場合はデフォルトの7.9より8の方が手間は無い。ただし、Docker公式はOracle Linux用のパッケージは用意されてないのでここで紹介してる手順は一応動くよというレベルで当然無保証。

あとアーキテクチャは普段よく使用されているamd64でなくarm64になるので、使いたいイメージによっては公開されてないこともあるので注意。(Docker Hubのイメージ検索の「OS/ARCH」のところにlinux/arm/v*のあるイメージであればデプロイ可能)

Ubuntu

特に問題無し。公式の手順通りでインストールできる。

docs.docker.com

$ uname -a
Linux opc-ubu-a1 5.11.0-1016-oracle #17~20.04.1-Ubuntu SMP Thu Aug 12 06:20:07 UTC 2021 aarch64 aarch64 aarch64 GNU/Linux
$ cat /etc/lsb-release 
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=20.04
DISTRIB_CODENAME=focal
DISTRIB_DESCRIPTION="Ubuntu 20.04.3 LTS"
$ sudo apt-get update
$ sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg \
    lsb-release
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

stableリポジトリの追加は、arm64用の設定を行う。

$ echo \
  "deb [arch=arm64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

インストール

$ sudo apt-get update
$ sudo apt-get install docker-ce docker-ce-cli containerd.io
$ sudo docker version
Client: Docker Engine - Community
 Version:           20.10.8
 API version:       1.41
 Go version:        go1.16.6
 Git commit:        3967b7d
 Built:             Fri Jul 30 19:55:05 2021
 OS/Arch:           linux/arm64
 Context:           default
 Experimental:      true

Server: Docker Engine - Community
 Engine:
  Version:          20.10.8
  API version:      1.41 (minimum version 1.12)
  Go version:       go1.16.6
  Git commit:       75249d8
  Built:            Fri Jul 30 19:53:13 2021
  OS/Arch:          linux/arm64
  Experimental:     false
 containerd:
  Version:          1.4.9
  GitCommit:        e25210fe30a0a703442421b0f60afac609f950a3
 runc:
  Version:          1.0.1
  GitCommit:        v1.0.1-0-g4144b63
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

実行

$ sudo docker run --rm hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
109db8fad215: Pull complete 
Digest: sha256:61bd3cb6014296e214ff4c6407a5a7e7092dfa8eefdbbec539e133e97f63e09f
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (arm64v8)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

Oracle Linux

Oracle Linux用のパッケージは用意されてないので、お互いRHEL互換ということでCentOS用の手順でお試し(したら動いた、というもの)。
インストールおよびざっくり動かした感じではこれで大丈夫そう。(無保証)

docs.docker.com

以前(1.13?)はOracle Linux用(ver 6, 7)のインストール手順もあったっぽいけど、現在(2021.09時点)は無いみたい。

ver 8

Oracle Linux 8の場合はCentOS用の手順そのままでOK.

$ uname -a
Linux opc-ol8-a1 5.4.17-2102.204.4.4.el8uek.aarch64 #2 SMP Tue Aug 17 20:32:12 PDT 2021 aarch64 aarch64 aarch64 GNU/Linux
$ cat /etc/oracle-release 
Oracle Linux Server release 8.4
$ sudo yum install -y yum-utils
$ sudo yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo
$ sudo yum install docker-ce docker-ce-cli containerd.io

Ubuntuと異なり、インストールしただけだとサービスは有効にならないので有効化する。

$ systemctl status docker
● docker.service - Docker Application Container Engine
   Loaded: loaded (/usr/lib/systemd/system/docker.service; disabled; vendor preset: disabled)
   Active: inactive (dead)
     Docs: https://docs.docker.com
$ sudo systemctl enable --now docker
$ sudo docker version
Client: Docker Engine - Community
 Version:           20.10.8
 API version:       1.41
 Go version:        go1.16.6
 Git commit:        3967b7d
 Built:             Fri Jul 30 19:54:06 2021
 OS/Arch:           linux/arm64
 Context:           default
 Experimental:      true

Server: Docker Engine - Community
 Engine:
  Version:          20.10.8
  API version:      1.41 (minimum version 1.12)
  Go version:       go1.16.6
  Git commit:       75249d8
  Built:            Fri Jul 30 19:52:39 2021
  OS/Arch:          linux/arm64
  Experimental:     false
 containerd:
  Version:          1.4.9
  GitCommit:        e25210fe30a0a703442421b0f60afac609f950a3
 runc:
  Version:          1.0.1
  GitCommit:        v1.0.1-0-g4144b63
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

実行

$ sudo docker run --rm hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
109db8fad215: Pull complete 
Digest: sha256:61bd3cb6014296e214ff4c6407a5a7e7092dfa8eefdbbec539e133e97f63e09f
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (arm64v8)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

ver 7.9

7.9(OCIでコンピュートインスタンス作るときはこれがデフォルトになってる)の場合は、これもCentOS用の手順通りでインストールできるけど、Dockerが依存するパッケージのインストールがデフォルトだとリポジトリが無効になってて失敗するので、これを追加するための1手順が必要。

$ uname -a
Linux opc-ol7-a1 5.4.17-2102.204.4.4.el7uek.aarch64 #2 SMP Wed Aug 18 11:37:16 PDT 2021 aarch64 aarch64 aarch64 GNU/Linux
$ cat /etc/oracle-release 
Oracle Linux Server release 7.9
$ sudo yum install -y yum-utils
$ sudo yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo
$ sudo yum install docker-ce docker-ce-cli containerd.io

[...]

エラー: パッケージ: docker-ce-rootless-extras-20.10.8-3.el7.aarch64 (docker-ce-stable)
             要求: fuse-overlayfs >= 0.7
エラー: パッケージ: docker-ce-rootless-extras-20.10.8-3.el7.aarch64 (docker-ce-stable)
             要求: slirp4netns >= 0.4
 問題を回避するために --skip-broken を用いることができます。
 これらを試行できます: rpm -Va --nofiles --nodigest

VM作成直後の状態だと、fuse-overlayfsslirp4netnsについて依存関係を解決できずこのようにエラーになる。

yum.oracle.com

この2つのパッケージは、ol7_developer リポジトリに含まれるので、リポジトリを有効にすればOK.

$ sudo yum-config-manager --enable ol7_developer

これでsudo yum install docker-ce docker-ce-cli containerd.ioでインストールできるようになる。

[...]

インストール:
  containerd.io.aarch64 0:1.4.9-3.1.el7             docker-ce.aarch64 3:20.10.8-3.el7             docker-ce-cli.aarch64 1:20.10.8-3.el7            

依存性関連をインストールしました:
  container-selinux.noarch 2:2.119.2-1.911c772.el7_8   docker-ce-rootless-extras.aarch64 0:20.10.8-3.el7   fuse-overlayfs.aarch64 0:0.7.2-6.el7_8  
  fuse3-libs.aarch64 0:3.6.1-4.el7                     slirp4netns.aarch64 0:0.4.3-4.el7_8                

完了しました!

あとはver8の場合と同じ。

$ sudo systemctl enable --now docker
$ sudo docker version
Client: Docker Engine - Community
 Version:           20.10.8
 API version:       1.41
 Go version:        go1.16.6
 Git commit:        3967b7d
 Built:             Fri Jul 30 19:55:48 2021
 OS/Arch:           linux/arm64
 Context:           default
 Experimental:      true

Server: Docker Engine - Community
 Engine:
  Version:          20.10.8
  API version:      1.41 (minimum version 1.12)
  Go version:       go1.16.6
  Git commit:       75249d8
  Built:            Fri Jul 30 19:54:18 2021
  OS/Arch:          linux/arm64
  Experimental:     false
 containerd:
  Version:          1.4.9
  GitCommit:        e25210fe30a0a703442421b0f60afac609f950a3
 runc:
  Version:          1.0.1
  GitCommit:        v1.0.1-0-g4144b63
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

実行

$ sudo docker run --rm hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
109db8fad215: Pull complete 
Digest: sha256:61bd3cb6014296e214ff4c6407a5a7e7092dfa8eefdbbec539e133e97f63e09f
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (arm64v8)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

ほかにも、デフォルトのリポジトリだとGitのクライアントバージョンも1系なので、今ならもうOracle Linux使うなら7.9より8の方が良いのかな?


CPUアーキテクチャとかあまりちゃんと理解できてないので間違ったこと書いてたらすみません。

Debian11(Bullseye)でRootless Dockerインストールしてコンテナをデプロイ

Debian10では依存パッケージのバージョンが古くてインストールできなかったルートレスDocker、先々週リリースされたDebian11ではパッケージバージョンが新しくなって全て要件を満たしていたので試してみた。

docs.docker.com

Deiban10だとうまくいかないパターンは以下

zaki-hmkc.hatenablog.com

環境

root@debian11:~# cat /etc/debian_version 
11.0

ルートレスDockerのインストール自体は公式ドキュメントの通りセットアップすれば基本的に動く。
以下は最小構成でOSインストールした直後の状態(通常のDockerが未インストール)の場合。

ちなみに、sudoまだ入ってないので、rootにsuして実行してる。

準備

uidmap

root@debian11:~# apt-get install uidmap
zaki@debian11:~$ id -u
1000
zaki@debian11:~$ whoami 
zaki
zaki@debian11:~$ grep ^$(whoami): /etc/subuid
zaki:100000:65536
zaki@debian11:~$ grep ^$(whoami): /etc/subgid
zaki:100000:65536

dbus-user-session

root@debian11:~# apt-get install dbus-user-session

このあと一度ログインしなおす。

overlay2

一旦省略

slirp4netns

root@debian11:~# apt search slirp4netns 
ソート中... 完了
全文検索... 完了  
slirp4netns/stable 1.0.1-2 amd64
  User-mode networking for unprivileged network namespaces

うむ、バージョン要件を満たしている。

root@debian11:~# apt-get install slirp4netns
:
:
root@debian11:~# slirp4netns --version
slirp4netns version 1.0.1
commit: 6a7b16babc95b6a3056b33fb45b74a6f62262dd4
libslirp: 4.4.0

install

docs.docker.com

install docker

まずは普通に

root@debian11:~# apt-get update
root@debian11:~# apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg \
    lsb-release
root@debian11:~# curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
root@debian11:~# echo \
  "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian \
  $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null

インストールする。

root@debian11:~# apt-get update
root@debian11:~# apt-get install docker-ce docker-ce-cli containerd.io

この通り。

root@debian11:~# docker --version
Docker version 20.10.8, build 3967b7d

インストール完了するとサービスが有効になってるので止める。

root@debian11:~# systemctl disable --now docker.service docker.socket
Synchronizing state of docker.service with SysV service script with /lib/systemd/systemd-sysv-install.
Executing: /lib/systemd/systemd-sysv-install disable docker
Removed /etc/systemd/system/sockets.target.wants/docker.socket.
Removed /etc/systemd/system/multi-user.target.wants/docker.service.

rootless

一般ユーザーで以下実行。

zaki@debian11:~$ dockerd-rootless-setuptool.sh install
[INFO] Creating /home/zaki/.config/systemd/user/docker.service
[INFO] starting systemd service docker.service
+ systemctl --user start docker.service
+ sleep 3
+ systemctl --user --no-pager --full status docker.service
● docker.service - Docker Application Container Engine (Rootless)
     Loaded: loaded (/home/zaki/.config/systemd/user/docker.service; disabled; vendor preset: enabled)
     Active: active (running) since Sat 2021-08-28 18:03:56 JST; 3s ago
       Docs: https://docs.docker.com/go/rootless/
   Main PID: 2277 (rootlesskit)
      Tasks: 33
     Memory: 72.7M
        CPU: 255ms
     CGroup: /user.slice/user-1000.slice/user@1000.service/app.slice/docker.service
             ├─2277 rootlesskit --net=slirp4netns --mtu=65520 --slirp4netns-sandbox=auto --slirp4netns-seccomp=auto --disable-host-loopback --port-driver=builtin --copy-up=/etc --copy-up=/run --propagation=rslave /usr/bin/dockerd-rootless.sh
             ├─2287 /proc/self/exe --net=slirp4netns --mtu=65520 --slirp4netns-sandbox=auto --slirp4netns-seccomp=auto --disable-host-loopback --port-driver=builtin --copy-up=/etc --copy-up=/run --propagation=rslave /usr/bin/dockerd-rootless.sh
             ├─2305 slirp4netns --mtu 65520 -r 3 --disable-host-loopback --enable-sandbox --enable-seccomp 2287 tap0
             ├─2312 dockerd
             └─2328 containerd --config /run/user/1000/docker/containerd/containerd.toml --log-level info

 8月 28 18:03:56 debian11 dockerd-rootless.sh[2312]: time="2021-08-28T18:03:56.970908740+09:00" level=error msg="failed to mount overlay: operation not permitted" storage-driver=overlay
 8月 28 18:03:56 debian11 dockerd-rootless.sh[2312]: time="2021-08-28T18:03:56.983809483+09:00" level=warning msg="Unable to find cpu controller"
 8月 28 18:03:56 debian11 dockerd-rootless.sh[2312]: time="2021-08-28T18:03:56.983830087+09:00" level=warning msg="Unable to find io controller"
 8月 28 18:03:56 debian11 dockerd-rootless.sh[2312]: time="2021-08-28T18:03:56.983835839+09:00" level=warning msg="Unable to find cpuset controller"
 8月 28 18:03:56 debian11 dockerd-rootless.sh[2312]: time="2021-08-28T18:03:56.983989597+09:00" level=info msg="Loading containers: start."
 8月 28 18:03:57 debian11 dockerd-rootless.sh[2312]: time="2021-08-28T18:03:57.023743296+09:00" level=info msg="Default bridge (docker0) is assigned with an IP address 172.17.0.0/16. Daemon option --bip can be used to set a preferred IP address"
 8月 28 18:03:57 debian11 dockerd-rootless.sh[2312]: time="2021-08-28T18:03:57.060855981+09:00" level=info msg="Loading containers: done."
 8月 28 18:03:57 debian11 dockerd-rootless.sh[2312]: time="2021-08-28T18:03:57.068177847+09:00" level=info msg="Docker daemon" commit=75249d8 graphdriver(s)=vfs version=20.10.8
 8月 28 18:03:57 debian11 dockerd-rootless.sh[2312]: time="2021-08-28T18:03:57.068280606+09:00" level=info msg="Daemon has completed initialization"
 8月 28 18:03:57 debian11 dockerd-rootless.sh[2312]: time="2021-08-28T18:03:57.088288454+09:00" level=info msg="API listen on /run/user/1000/docker.sock"
+ DOCKER_HOST=unix:///run/user/1000/docker.sock /usr/bin/docker version
Client: Docker Engine - Community
 Version:           20.10.8
 API version:       1.41
 Go version:        go1.16.6
 Git commit:        3967b7d
 Built:             Fri Jul 30 19:54:22 2021
 OS/Arch:           linux/amd64
 Context:           default
 Experimental:      true

Server: Docker Engine - Community
 Engine:
  Version:          20.10.8
  API version:      1.41 (minimum version 1.12)
  Go version:       go1.16.6
  Git commit:       75249d8
  Built:            Fri Jul 30 19:52:31 2021
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.4.9
  GitCommit:        e25210fe30a0a703442421b0f60afac609f950a3
 runc:
  Version:          1.0.1
  GitCommit:        v1.0.1-0-g4144b63
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0
+ systemctl --user enable docker.service
Created symlink /home/zaki/.config/systemd/user/default.target.wants/docker.service → /home/zaki/.config/systemd/user/docker.service.
[INFO] Installed docker.service successfully.
[INFO] To control docker.service, run: `systemctl --user (start|stop|restart) docker.service`
[INFO] To run docker.service on system startup, run: `sudo loginctl enable-linger zaki`

[INFO] Creating CLI context "rootless"
Successfully created context "rootless"

[INFO] Make sure the following environment variables are set (or add them to ~/.bashrc):

export PATH=/usr/bin:$PATH
export DOCKER_HOST=unix:///run/user/1000/docker.sock

環境変数を追加する。PATHはすでにあるのでDOCKER_HOSTのみ。

zaki@debian11:~$ export DOCKER_HOST=unix:///run/user/1000/docker.sock
zaki@debian11:~$ docker image ls
REPOSITORY   TAG       IMAGE ID   CREATED   SIZE
zaki@debian11:~$ docker container ls
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

docker runお試し

zaki@debian11:~$ docker run --rm -d -p 8080:80 nginx
Unable to find image 'nginx:latest' locally
latest: Pulling from library/nginx
e1acddbe380c: Pull complete 
e21006f71c6f: Pull complete 
f3341cc17e58: Pull complete 
2a53fa598ee2: Pull complete 
12455f71a9b5: Pull complete 
b86f2ba62d17: Pull complete 
Digest: sha256:4d4d96ac750af48c6a551d757c1cbfc071692309b491b70b2b8976e102dd3fef
Status: Downloaded newer image for nginx:latest
76b82bf2fcc9d16e42142221bf52581ccb69a077e87b4863bff4913040d69e95
docker: Error response from daemon: OCI runtime create failed: container_linux.go:380: starting container process caused: process_linux.go:385: applying cgroup configuration for process caused: error while starting unit "docker-76b82bf2fcc9d16e42142221bf52581ccb69a077e87b4863bff4913040d69e95.scope" with properties [{Name:Description Value:"libcontainer container 76b82bf2fcc9d16e42142221bf52581ccb69a077e87b4863bff4913040d69e95"} {Name:Slice Value:"user.slice"} {Name:PIDs Value:@au [2645]} {Name:Delegate Value:true} {Name:MemoryAccounting Value:true} {Name:CPUAccounting Value:true} {Name:IOAccounting Value:true} {Name:TasksAccounting Value:true} {Name:DefaultDependencies Value:false}]: read unix @->/run/systemd/private: read: connection reset by peer: unknown.

あ、やっぱこのエラーでるな。。。

対応はdocker run errorsを確認。

zaki@debian11:~$ systemctl --user is-active dbus
inactive
zaki@debian11:~$ systemctl --user status dbus
● dbus.service - D-Bus User Message Bus
     Loaded: loaded (/usr/lib/systemd/user/dbus.service; static)
     Active: inactive (dead)
TriggeredBy: ● dbus.socket
       Docs: man:dbus-daemon(1)

dbus、インストールはされてるけど動いてないので有効化する。

zaki@debian11:~$ systemctl --user enable --now dbus
The unit files have no installation config (WantedBy=, RequiredBy=, Also=,
Alias= settings in the [Install] section, and DefaultInstance= for template
units). This means they are not meant to be enabled using systemctl.
 
Possible reasons for having this kind of units are:
• A unit may be statically enabled by being symlinked from another unit's
  .wants/ or .requires/ directory.
• A unit's purpose may be to act as a helper for some other unit which has
  a requirement dependency on it.
• A unit may be started when needed via activation (socket, path, timer,
  D-Bus, udev, scripted systemctl call, ...).
• In case of template units, the unit is meant to be enabled with some
  instance name specified.
zaki@debian11:~$ 
zaki@debian11:~$ 
zaki@debian11:~$ systemctl --user status dbus
● dbus.service - D-Bus User Message Bus
     Loaded: loaded (/usr/lib/systemd/user/dbus.service; static)
     Active: active (running) since Sat 2021-08-28 18:07:30 JST; 37s ago
TriggeredBy: ● dbus.socket
       Docs: man:dbus-daemon(1)
   Main PID: 2674 (dbus-daemon)
      Tasks: 1 (limit: 4675)
     Memory: 496.0K
        CPU: 2ms
     CGroup: /user.slice/user-1000.slice/user@1000.service/app.slice/dbus.service
             └─2674 /usr/bin/dbus-daemon --session --address=systemd: --nofork --nopidfile --systemd-activation --syslog-only

 8月 28 18:07:30 debian11 systemd[584]: Started D-Bus User Message Bus.

コンテナを再実行する。

zaki@debian11:~$ docker run --rm -d -p 8080:80 nginx
1872f49375bfd1e86839be7903c0ffb11ac97772926854b50782438c27a8a87f
zaki@debian11:~$ curl localhost:8080
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>

[snip]

動いた。


おまけ

Debian11入れて割とすぐくらいのタイミングで試してもうまくいかず、藁にもすがる思いでツイートしたら助けてもらいました!

というのも実は私が試したときはdbus関連のパッケージについて記載がドキュメントに載ってなくて、このやりとりのあとに、ドキュメント修正のPR出してしてくれたらしい…感謝です。

github.com

エラーメッセージもわかりやすくなるかも。

github.com

コミュニティの開発、すごい。。


ちなみにディストリビューションでいうと、「Distribution-specific hint」のところに

Note: We recommend that you use the Ubuntu kernel.

と書いてある笑

[Ansible] roleの雛形作成をカスタムする (ansible-galaxy / --role-skeleton)

roleの雛形の作り方と、雛形のカスタマイズ。
今回は試さなかったけどcollectionにも使えるはず。。

role雛形の作成

Ansibleのroleの雛形は、ansible-galaxyを使って以下のコマンドで作成できます。

$ ansible-galaxy init my-role
$ tree my-role/
my-role/
├── README.md
├── defaults
│   └── main.yml
├── files
├── handlers
│   └── main.yml
├── meta
│   └── main.yml
├── tasks
│   └── main.yml
├── templates
├── tests
│   ├── inventory
│   └── test.yml
└── vars
    └── main.yml

8 directories, 8 files

引数で指定した「my-role」というrole名で各ファイルが生成され、各ファイル内のrole名がセットされます。

role雛形のカスタム

role作成のansible-galaxyのオプションで--role-skeleton=/path/to/role-skeletonを指定することで、雛形のスケルトン(ややこしい)を指定できます。
ケルトンは一旦ansible-galaxy initでrole雛形を作り、出来た雛形に必要なファイルを作成・編集したり、不要ファイル削除したりすれば、それをスケルトンとして使用可能。
例えば「ディレクトリだけのfilestemplatesは要らん(必要があるときに作る)」「defaultsは使わない」「README.mdはプロジェクトのテンプレートを使う」とか。

雛形のスケルトンを作る

$ ansible-galaxy init role-skeleton
- Role role-skeleton was created successfully

そこから(例として)不要なファイルを削除。

$ rm -rf role-skeleton/files/ role-skeleton/handlers/ role-skeleton/templates/ role-skeleton/defaults/
$ tree role-skeleton/role-skeleton/
├── README.md
├── meta
│   └── main.yml
├── tasks
│   └── main.yml
├── tests
│   ├── inventory
│   └── test.yml
└── vars
    └── main.yml

4 directories, 6 files

(例として)READMEを編集。(ちなみにREADME.md.orgは残しておくとこれも雛形に含まれるので削除を忘れずに)

$ diff -u role-skeleton/README.md.org role-skeleton/README.md
--- role-skeleton/README.md.org 2021-08-27 08:39:54.140736835 +0900
+++ role-skeleton/README.md     2021-08-27 08:43:23.359197543 +0900
@@ -1,38 +1,34 @@
 Role Name
 =========
 
-A brief description of the role goes here.
+fixme
 
 Requirements
 ------------
 
(中略)

 License
 -------
 
-BSD
+MIT
 
 Author Information
 ------------------
 
-An optional section for the role authors to include contact information, or a website (HTML is not allowed).
+@zaki_hmkc

ケルトンからroleの雛形を作成

↑で作成したスケルトンを指定してrole雛形を作成します。

$ ansible-galaxy init --role-skeleton=./role-skeleton customize-role
- Role customize-role was created successfully

これでカスタムしたスケルトンで用意したファイルのみのrole雛形になります。

$ tree customize-role/
customize-role/
├── README.md
├── meta
│   └── main.yml
├── tasks
│   └── main.yml
├── tests
│   ├── inventory
│   └── test.yml
└── vars
    └── main.yml

4 directories, 6 files

カスタムしたREADME.mdもこの通り。

$ cat customize-role/README.md 
Role Name
=========

fixme

Requirements

(中略)

License
-------

MIT

Author Information
------------------

@zaki_hmkc

role名の埋め込み

ただし↑の手順だけだと、ファイル内のrole名がセットされる箇所が、スケルトンを作ったときのままになります。

$ cat customize-role/tasks/main.yml 
---
# tasks file for role-skeleton

ここにスケルトンではなく新しく作るrole雛形の名前をセットするにはJinja2テンプレートで変数を指定します。
その際、テンプレートで変数使う場合はファイル名も.j2を追加します。

tasks/main.ymlでテンプレートを参照するのであれば、tasks/main.yml.j2にして、role名に置き換えたい箇所を{{ role_name }}に置き換えます。

$ cat role-skeleton/tasks/main.yml.j2
---
# tasks file for {{ role_name }}

この内容のスケルトンを指定してrole雛形を作成すると、以下の通り。

$ ansible-galaxy init --role-skeleton=./role-skeleton customize-role2
- Role customize-role2 was created successfully
$ cat customize-role2/tasks/main.yml 
---
# tasks file for customize-role2

role名を変換できました。
現状変数指定できるのは{{ role_name }}のみ、とのこと。
また、templatesディレクトリ以下の*.j2ファイルに対しては、テンプレートとしての変数変換は行われません。(なので、スケルトンに用意したファイルはそのまま雛形として出力される)

any .j2 files found outside of a templates folder will be rendered as templates. The only useful variable at the moment is role_name

https://docs.ansible.com/ansible/latest/galaxy/dev_guide.html#using-a-custom-role-skeleton

role名変換とJinja2テンプレートの書式を同時に使いたいとき

ファイル名を.j2にすると、ファイル内のJinja2テンプレートの変数参照は全て雛形作成時に変換処理が行われます(そして{{ role_name }}以外は未定義エラーになる)。

{{ role_name }}は変換しつつ、それ以外はJinja2として解釈せずにそのまま雛形作成するには、Jinja2の{% raw %}を使ってエスケープします。

タスクのスケルトンをこのように記述しておくと、

$ cat role-skeleton/tasks/main.yml.j2
---
# tasks file for {{ role_name }}
- name: print values
  ansible.builtin.debug:
    msg: {% raw %}"{{ role_values }}"{% endraw %}

生成されるrole雛形のタスクファイルはこの通り。
{{ role_name }}はテンプレートとして変換されて、{{ role_values }}はそのまま。

$ cat customize-role3/tasks/main.yml 
---
# tasks file for customize-role3
- name: print values
  ansible.builtin.debug:
    msg: "{{ role_values }}"

↑は変数参照部分だけ'{% raw %}`で囲んでるけど、個数が多いなら上から下まで丸ごと囲んでも良いかも。

参考情報

docs.ansible.com

「Using a custom role skeleton」参照。

環境

ansible-galaxy [core 2.11.2] 
  config file = /home/zaki/.ansible.cfg
  configured module search path = ['/home/zaki/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/zaki/src/ansible-sample/venv/ansible4/lib64/python3.6/site-packages/ansible
  ansible collection location = /home/zaki/.ansible/collections:/usr/share/ansible/collections
  executable location = /home/zaki/src/ansible-sample/venv/ansible4/bin/ansible-galaxy
  python version = 3.6.8 (default, Nov 16 2020, 16:55:22) [GCC 4.8.5 20150623 (Red Hat 4.8.5-44)]
  jinja version = 3.0.1
  libyaml = True

Pythonのバージョンが(ry

[Ansible] playbookと別リポジトリ管理のroleを実行するにはroles/requirements.ymlを使う (CLI / Tower)

playbookのリポジトリとroleのリポジトリを分けた場合に、どうやって別リポジトリのroleをplaybookから実行するかについて。半年以上前に情報として聞いてはいたけれど試してなかったので実際に動かしてみた。

roleのリポジトリ

ansible-galaxy role init <role-name>で作成できるファイル群がリポジトリ直下になるようにrole作成。
この際、meta/main.ymlが必須。(無いとplaybook側で…というかansible-galaxy installコマンドでイントールできない)
リポジトリのファイル構成例としてはこんな感じ。

$ tree
.
├── README.md
├── meta
│   └── main.yml
├── tasks
│   └── main.yml
└── vars
    └── main.yml

実装例は以下。

github.com

サンプルroleの中身はこんな感じ。
(curryって変数はvars/main.ymlで定義)

---
# tasks file for sample_role
- name: sample role start
  debug:
    msg: "this is sample role"

- name: print value
  debug:
    msg: 'curry: {{ curry }}'

これをリモートリポジトリにpushしておくと、ansible-galaxy installでroleをインストールできるようになる。

playbookのリポジトリ

github.com

roleのインストール

roles/requirements.ymlに使用するroleの情報を記述する。
例としてはこんな感じ。

---
- name: hogehoge
  src: https://github.com/zaki-lknr/ansible-sample-role.git
  version: main

このrequirements.ymlを引数にansible-galaxy install -r roles/requirements.ymlを実行すると、(デフォルトでは)~/.ansible/roles/hogehoge以下へroleがインストールされる。
書式についてはInstalling multiple roles from a fileを参照。
あとscmというパラメタに、デフォルトはgitだけどhgも指定できる模様。そういやTowerもMercurialが選択肢にあったな。

(追記) role(のリポジトリ)が更新されてる場合は、-f も付与してアップデート(強制上書きインストール)が必要。
(少し前にアップデートオプションが追加されたような気がしたけど、あれってコレクションの場合(ansible-galaxy collection)のオプションだったようだ)

$ ansible-galaxy install -fr roles/requirements.yml

playbook

playbookはこの通り、hogehogeというroleを実行するように記述。

---
- hosts: localhost
  gather_facts: false

  roles:
  - hogehoge

事前に~/.ansible/roles/hogehogeへ対象roleをインストール済みであれば、このplaybookをansible-playbookで普通に実行すればhogehoge roleが呼ばれて普通に実行できる。

roleインストール先を変更したい場合

ansible.cfgなどで

[defaults]
roles_path = /var/tmp/ansible/roles

とか書いておけば指定可能。
詳しくはDEFAULT_ROLES_PATH参照。

Towerの場合

前述「playbookのリポジトリ」の内容をGitリモートリポジトリにpushしておき、Towerでは通常通りにこのリポジトリを使うプロジェクトを作成する。
プロジェクトの同期のタイミングでroles/requirements.ymlのroleが同期されるので、あとはこちらも普通に実行できる。
よくよく見ると、collections/requirements.yml もここで参照されてるんだな。

f:id:zaki-hmkc:20210819191229p:plain

roleのリポジトリで更新を行った場合はプロジェクトの再同期が必要。(と思う。自動設定は…Webhookとかで出来るかな?)
手元の環境ではジョブテンプレートの再実行だけではroleの内容は更新されなかった。
※ (追記) ↑ プロジェクトの設定で「起動時のリビジョン更新」にチェックを入れておけば、ジョブ実行毎にリポジトリの情報が更新されるので、実行時にroleも更新される。

ジョブを実行したときのログはこの通りで、指定のroleがちゃんと実行されている。

f:id:zaki-hmkc:20210819191303p:plain

これは何ができるの?

複数のリポジトリでそれぞれの目的の処理を行うplaybookを作成してて、でもいくつかのplaybookで似たような処理が出てきたので共通化したい、みたいな場合に処理を集約できる。

環境

AnsibleはCentOS7
Pythonがちょっと古い。

$ ansible --version
ansible [core 2.11.2] 
  config file = /home/zaki/.ansible.cfg
  configured module search path = ['/home/zaki/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/zaki/src/ansible-sample/venv/ansible4/lib64/python3.6/site-packages/ansible
  ansible collection location = /home/zaki/.ansible/collections:/usr/share/ansible/collections
  executable location = /home/zaki/src/ansible-sample/venv/ansible4/bin/ansible
  python version = 3.6.8 (default, Nov 16 2020, 16:55:22) [GCC 4.8.5 20150623 (Red Hat 4.8.5-44)]
  jinja version = 3.0.1
  libyaml = True

Towerは3.8.0 (on RHEL8)

zaki-hmkc.hatenablog.com

参考情報

www.ansible.com

docs.ansible.com


続報に期待です :)
(いつも貴重な情報ありがとうございます!!)