2022年12月28日水曜日

OSSのコンテナレジストリ「Harbor」インストール手順

Docker Hubのようにコンテナイメージを格納し、Dockerにてイメージをダウンロード(Pull)して利用できるようにするサービスをコンテナリポジトリと呼ぶ。

Docker Hubはインターネット上で公開されたサービスとなり、誰でも自由に使える一方、インターネット環境であることからセキュリティ面におけるリスクも大きい。

そのような状況をふまえ、自宅検証環境にプライベートのコンテナレジストリを構築することにした。本記事では、OSSのコンテナレジストリ「Harbor」をインストールする手順を記載する。

なお、今回はHarborへのアクセスをHTTPによる構成としたが、自己署名証明書を使ってHTTPSにて通信させる場合は、以下記事を参照いただきたい。

環境

Harbor自体はDockerコンテナとして動作する。Harbor及びDockerが動作するOSとしてはAlmaLinuxを使用した。

  • OS : AlmaLinux release 8.6
  • Docker : 20.10.21
  • Docker Compose : v2.12.2
  • Harbor : v2.6.2
今回の作業の簡単な概要図を以下に記載する。

Dockerインストール

1. Dockerインストール

Harbor自体もDockerコンテナとして動作するため、まずはDockerのインストールを行う。

# dnf install yum-utils -y
# yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# dnf install docker-ce docker-ce-cli containerd.io -y

プロキシ環境の場合は、インターネット接続できるようにsystemdに環境変数の設定を行う。

# sed -ie '/\[Service\]/a Environment="http_proxy=http://192.168.33.23:8080" "https_proxy=http://192.168.33.23:8080" "no_proxy=192.168.0.0/16"' /usr/lib/systemd/system/docker.service
# systemctl start docker
# systemctl enable docker

2. Docker composeのインストール

Harborはインストール時にDocker composeを利用するため、こちらもインストールする。Docker composeは以下の通りdnfコマンドでインストールすることができる。

# dnf install docker-compose-plugin -y

Docker composeのバージョンを確認しておく。

# docker compose version
Docker Compose version v2.12.2

本題とは逸れるが、Docker composeはもともとdocker-composeといったコマンド体系となっていたが、現在のDocker compose V2系では、dockerコマンドに統合されており、docker composeというハイフンなしのコマンド体系になっている。たとえば、docker-compose up -ddocker compose up -dで実行する必要があるので覚えておくとよいだろう。

Compose V2 integrates compose functions into the Docker platform, continuing to support most of the previous docker-compose features and flags. You can run Compose V2 by replacing the hyphen (-) with a space, using docker compose, instead of docker-compose.

Harborインストール

1. Harborのインストーラをダウンロード

Harborのインストーラは、オンラインインストーラとオフラインインストーラの2種類が用意されている。今回はオフラインインストーラを用いる。ダウンロードは以下URLからダウンロードすることができる。

名前に-rcN(Nは数字1桁)が付与されているものは、リリース候補版となる。今回はlatestタグの付与されているバージョン2.6.2をインストールすることにした。オフラインインストーラの容量は約760MBとなる。

2. インストーラを解凍

インストーラはtgz圧縮されているので解凍する。ファイル容量は大きいが、ファイル数自体は多くない。

# tar zxvf harbor-offline-installer-v2.6.2.tgz
harbor/harbor.v2.6.2.tar.gz
harbor/prepare
harbor/LICENSE
harbor/install.sh
harbor/common.sh
harbor/harbor.yml.tmpl

# ls -l harbor
合計 792320
-rw-r--r-- 1 root root     11347 11月  9 18:35 LICENSE
-rw-r--r-- 1 root root      3639 11月  9 18:35 common.sh
-rw-r--r-- 1 root root 811298774 11月  9 18:36 harbor.v2.6.2.tar.gz
-rw-r--r-- 1 root root     10649 11月  9 18:35 harbor.yml.tmpl
-rwxr-xr-x 1 root root      3171 11月  9 18:35 install.sh
-rwxr-xr-x 1 root root      1881 11月  9 18:35 prepare

3. インストール設定ファイル(YAML)を修正

Harborはインストールの設定ファイルとして、harbor.ymlというYAMLファイルの作成が必要となる。

解凍したインストーラ内部に、harbor.yml.tmplというテンプレートが存在するため、これをコピーしてharbor.ymlを作成する。

# cd harbor
# cp harbor.yml.tmpl harbor.yml

以下★箇所を最低限設定しておく。通常Harborへの接続としては、セキュリティの観点からHTTP通信ではなくHTTPS通信を使用すべきであるが、今回は手順簡略化のためHTTP通信による設定を行う。

その他のパラメータについては、公式ドキュメントを参照いただきたい。

harbor.yml

# Configuration file of Harbor

# The IP address or hostname to access admin UI and registry service.
# DO NOT use localhost or 127.0.0.1, because Harbor needs to be accessed by external clients.
hostname: 192.168.11.54 ←★ホスト名を設定する。DNSなどで名前解決できる場合はFQDN設定が望ましいが、今回はIPアドレスで設定する

# http related config
http:
  # port for http, default is 80. If https enabled, this port will redirect to https port
  port: 80

# https related config
#https: ←★原則はHTTPSによる通信が望ましいが、今回は手順簡略化のためHTTPを使用するためコメントアウト
  # https port for harbor, default is 443
#  port: 443 ←★原則はHTTPSによる通信が望ましいが、今回は手順簡略化のためHTTPを使用するためコメントアウト
  # The path of cert and key files for nginx
#  certificate: /your/certificate/path ★←SSLサーバ証明書を使用しないためコメントアウト
#  private_key: /your/private/key/path ★←SSLサーバ証明書を使用しないためコメントアウト

~(以下略)~

4. インストールスクリプトの実行

harbor.ymlの準備が整ったら、インストールスクリプトを実行する。[Step 0]から[Step 5]まで処理が順に実行される。最後の[Step 5]において、Docker composeによるコンテナ起動がされていることがわかる。

# ./install.sh

[Step 0]: checking if docker is installed ...

Note: docker version: 20.10.21

[Step 1]: checking docker-compose is installed ...

Note: Docker Compose version v2.12.2

[Step 2]: loading Harbor images ...
Loaded image: goharbor/harbor-jobservice:v2.6.2
Loaded image: goharbor/trivy-adapter-photon:v2.6.2
Loaded image: goharbor/chartmuseum-photon:v2.6.2
Loaded image: goharbor/redis-photon:v2.6.2
Loaded image: goharbor/nginx-photon:v2.6.2
Loaded image: goharbor/notary-signer-photon:v2.6.2
Loaded image: goharbor/harbor-core:v2.6.2
Loaded image: goharbor/harbor-db:v2.6.2
Loaded image: goharbor/harbor-registryctl:v2.6.2
Loaded image: goharbor/harbor-exporter:v2.6.2
Loaded image: goharbor/prepare:v2.6.2
Loaded image: goharbor/registry-photon:v2.6.2
Loaded image: goharbor/notary-server-photon:v2.6.2
Loaded image: goharbor/harbor-portal:v2.6.2
Loaded image: goharbor/harbor-log:v2.6.2


[Step 3]: preparing environment ...

[Step 4]: preparing harbor configs ...
prepare base dir is set to /root/harbor
WARNING:root:WARNING: HTTP protocol is insecure. Harbor will deprecate http protocol in the future. Please make sure to upgrade to https
Generated configuration file: /config/portal/nginx.conf
Generated configuration file: /config/log/logrotate.conf
Generated configuration file: /config/log/rsyslog_docker.conf
Generated configuration file: /config/nginx/nginx.conf
Generated configuration file: /config/core/env
Generated configuration file: /config/core/app.conf
Generated configuration file: /config/registry/config.yml
Generated configuration file: /config/registryctl/env
Generated configuration file: /config/registryctl/config.yml
Generated configuration file: /config/db/env
Generated configuration file: /config/jobservice/env
Generated configuration file: /config/jobservice/config.yml
Generated and saved secret to file: /data/secret/keys/secretkey
Successfully called func: create_root_cert
Generated configuration file: /compose_location/docker-compose.yml
Clean up the input dir


Note: stopping existing Harbor instance ...


[Step 5]: starting Harbor ...
[+] Running 10/10
 ? Network harbor_harbor        Created                                    0.0s
 ? Container harbor-log         Started                                    0.3s
 ? Container harbor-db          Started                                    0.9s
 ? Container registry           Started                                    1.0s
 ? Container registryctl        Started                                    0.9s
 ? Container harbor-portal      Started                                    1.0s
 ? Container redis              Started                                    1.0s
 ? Container harbor-core        Started                                    1.4s
 ? Container nginx              Started                                    2.2s
 ? Container harbor-jobservice  Started                                    2.1s
? ----Harbor has been installed and started successfully.----

もし、インストールスクリプト実行後にharbor.ymlを修正した場合は、再度インストールスクリプトを実行することで設定反映ができる。再実行の場合は、一度コンテナが削除されたのち、新しいコンテナが起動される。

# ./install.sh

[Step 0]: checking if docker is installed ...

Note: docker version: 20.10.21

[Step 1]: checking docker-compose is installed ...

Note: Docker Compose version v2.12.2

~(中略)~

Note: stopping existing Harbor instance ...
[+] Running 10/9
 ? Container nginx              Removed                                    0.1s
 ? Container harbor-jobservice  Removed                                    0.1s
 ? Container registryctl        Removed                                   10.1s
 ? Container harbor-portal      Removed                                    0.1s
 ? Container harbor-core        Removed                                    0.1s
 ? Container redis              Removed                                    0.3s
 ? Container harbor-db          Removed                                    0.3s
 ? Container registry           Removed                                    0.3s
 ? Container harbor-log         Removed                                   10.1s
 ? Network harbor_harbor        Removed                                    0.0s


[Step 5]: starting Harbor ...
[+] Running 10/10
 ? Network harbor_harbor        Created                                    0.0s
 ? Container harbor-log         Started                                    0.3s
 ? Container registryctl        Started                                    0.6s
 ? Container harbor-portal      Started                                    1.1s
 ? Container registry           Started                                    1.0s
 ? Container redis              Started                                    1.1s
 ? Container harbor-db          Started                                    1.0s
 ? Container harbor-core        Started                                    1.2s
 ? Container harbor-jobservice  Started                                    1.7s
 ? Container nginx              Started                                    1.7s
? ----Harbor has been installed and started successfully.----

5. DockerをHTTP接続に対応させる設定

Dockerは標準では、コンテナレジストリに対してHTTPSによる接続を行うため、HTTPによる接続をできるよう、/etc/docker/daemon.jsonのファイルを新規作成する。

記載しているIPアドレスは、harbor.ymlhostnameの設定と合わせればよく、IPアドレスまたはFQDNで設定することができる。

# ls -l /etc/docker/daemon.json
ls: '/etc/docker/daemon.json' にアクセスできません: そのようなファイルやディレクトリはありません
# cat << EOF > /etc/docker/daemon.json
{
  "insecure-registries": [
    "192.168.11.54"
  ]
}
EOF

設定後は、Docker及びHarborの再起動が必要となるため、以下の通り再起動を行う。

# systemctl restart docker
# docker compose down -v
# docker compose up -d

6. Web管理画面にログイン

HarborのWeb管理画面にログインする。

  • ユーザ : admin
  • 初期パスワード : Harbor12345
  • 接続先 : http://[HarborをインストールしたOSのIPアドレス]

動作確認

1. プロジェクトを作成

Harborではプロジェクトを作成し、そこにコンテナイメージを保存して管理する構成となっている。デフォルトでlibraryという名称のプロジェクトが存在するが、今回はあえて新規にmyprojectという名称のプロジェクトを作成した。

プロジェクトを作成の際の設定値は以下の通り。

設定項目 設定値 説明
Project Name myproject 任意の名前で設定する。
Access Level Public アクセス権はPublicとする。Publicの場合は、Pullする際にdocker loginコマンドによる認証が不要となる。逆にPublicにしない場合(Privateにする場合)は、Pullの際にdocker loginコマンドによる認証が必要となる。なお、Pushの際はいずれの権限においても事前の認証が必要となる。
Storage Quota -1 GiB 容量の制限(クォータ)の設定となる。今回はデフォルトの無制限(-1)とする。
Proxy Cache 無効 プロキシキャッシュの機能は無効化する。プロキシキャッシュの詳細は、公式マニュアルを参照いただきたい。

2. テスト用コンテナイメージのPull

それでは、Harborを使ってコンテナイメージのアップロード(Push)とダウンロード(Pull)ができることを確認しよう。なお、Push及びPullを行うDockerは、Harborとは別のサーバにインストールしたものとする。

テスト用のコンテナイメージはoraclelinux:8.7を用いる。このコンテナイメージをHarborへPushし、その後一度コンテナイメージを削除してから、HarborよるPullできることを確認する。

まずは、oraclelinux:8.7のコンテナイメージをDocker HubよりPullする。

# docker pull oraclelinux:8.7
8.7: Pulling from library/oraclelinux
4c770e098606: Pull complete
Digest: sha256:07a995ecaf9db1ce613648a08facc162de69f26c39712f1acc93629c2e6c4e73
Status: Downloaded newer image for oraclelinux:8.7
docker.io/library/oraclelinux:8.7

# docker images
REPOSITORY    TAG       IMAGE ID       CREATED       SIZE
oraclelinux   8.7       b0045ea7bbde   10 days ago   225MB

3. DockerをHTTP接続に対応させる設定

Dockerは標準では、コンテナレジストリに対してHTTPSによる接続を行うため、HTTPによる接続をできるよう、/etc/docker/daemon.jsonのファイルを新規作成する。

# ls -l /etc/docker/daemon.json
ls: '/etc/docker/daemon.json' にアクセスできません: そのようなファイルやディレクトリはありません
# cat << EOF > /etc/docker/daemon.json
{
  "insecure-registries": [
    "192.168.11.54"
  ]
}
EOF

設定後は、Dockerの再起動が必要となるため、以下の通り再起動を行う。

# systemctl restart docker

4. Harborへの認証

Pushする場合は、事前にdocker loginコマンドにてHarborに対して認証を成功させておく必要がある。ここで入力するユーザ名とパスワードは、Web管理画面と同じadmin / Harbor12345となる。

# docker login 192.168.11.54
Username: admin
Password: ←★"Harbor12345"を入力
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

5. コンテナイメージをPush

Pushするコンテナイメージに対して、タグの設定を行う。タグは以下の形式で設定する。

[HarborのIPアドレスまたはFQDN]/[プロジェクト名]:[タグ名]

実行結果を以下に記載する。

# docker tag oraclelinux:8.7 192.168.11.54/myproject/oraclelinux:8.7
# docker images
REPOSITORY                            TAG       IMAGE ID       CREATED       SIZE
192.168.11.54/myproject/oraclelinux   8.7       b0045ea7bbde   10 days ago   225MB
oraclelinux                           8.7       b0045ea7bbde   10 days ago   225MB

タグを付与したコンテナイメージをPushする。

# docker push 192.168.11.54/myproject/oraclelinux:8.7
The push refers to repository [192.168.11.54/myproject/oraclelinux]
d8c569c85182: Pushed
8.7: digest: sha256:89787c72978339a100b1855de3ab7749f29752fc83302456bfac6ba209008401 size: 529

特に問題が発生しなければ、HarborのWeb管理画面からも、Pushしたコンテナイメージを確認することができるはずだ。

6. コンテナイメージを削除

次に、先ほどPushしたコンテナイメージをPullしてみよう。

まずは、ローカルに存在するコンテナイメージを削除する。

# docker images
REPOSITORY                            TAG       IMAGE ID       CREATED       SIZE
192.168.11.54/myproject/oraclelinux   8.7       b0045ea7bbde   10 days ago   225MB
oraclelinux                           8.7       b0045ea7bbde   10 days ago   225MB

# docker rmi b0045ea7bbde -f
Untagged: 192.168.11.54/myproject/oraclelinux:8.7
Untagged: 192.168.11.54/myproject/oraclelinux@sha256:89787c72978339a100b1855de3ab7749f29752fc83302456bfac6ba209008401
Untagged: oraclelinux:8.7
Untagged: oraclelinux@sha256:07a995ecaf9db1ce613648a08facc162de69f26c39712f1acc93629c2e6c4e73
Deleted: sha256:b0045ea7bbde263d0543ac9efb749e588d3538bc673f98fe00a73006838a9b89
Deleted: sha256:d8c569c851824688f0f55d46d659a8eef6b8af3ed0a20f389b066f16a4a250e5

# docker images
REPOSITORY   TAG       IMAGE ID   CREATED   SIZE

7. HarborよりコンテナイメージをPull

HarborよりコンテナイメージをPullする。

# docker pull 192.168.11.54/myproject/oraclelinux:8.7
8.7: Pulling from myproject/oraclelinux
4c770e098606: Pull complete
Digest: sha256:89787c72978339a100b1855de3ab7749f29752fc83302456bfac6ba209008401
Status: Downloaded newer image for 192.168.11.54/myproject/oraclelinux:8.7
192.168.11.54/myproject/oraclelinux:8.7

# docker images
REPOSITORY                            TAG       IMAGE ID       CREATED       SIZE
192.168.11.54/myproject/oraclelinux   8.7       b0045ea7bbde   10 days ago   225MB

Pullに成功すると、Harbor上でもPullが実行された回数が更新される。

以上で、OSSのコンテナレジストリ「Harbor」をインストールする手順は完了となる。

参考

2022年12月24日土曜日

商用OSのEOSを調べてみた!2022年末版

私は年末に主要な商用OSのEnd of Support (EOS) を調査しており、本記事ではその結果を記載する

結論を先に言うと、2023年中に完全にサポート期限を迎える製品は以下となる。

  • Windows 8.1
  • Windows Server 2012 無印/R2
  • vSphere 6.5/6.7
  • AIX 7.1 TL5
  • HP-UX 11i v2

以下に各製品ごとにEOSを調べた結果を記載した。2023年にサポート期限を迎える製品については、太字で強調表示してある。

なお、本記事で「EOS」と表現する場合は、製品として完全にすべてのサポートが終了する期限を指すことにする。例えば、通常サポートが終了しても延長サポートが存在するような場合は、EOSとは表現しない。

Windows (PC用)

現時点でサポートが残っているWindows OSは、Windows 8.1、Windows 10、Windows 11の3つとなる。2023年の初めに、Windows 8.1がEOSを迎えるので注意。

Windows 8.1

Windows 8.1は固定ライフサイクルポリシーであり、2023年1月まで延長サポートが継続される。

OS名 サポート状況 サポート期限
Windows 8.1 延長サポート 2023/01/10

Windows 10

Windows 10は、モダンライフサイクルポリシーが適用される。なお、今までの単純なメインストリームサポートと延長サポートの構成を「固定ライフサイクルポリシー」と呼ぶ。

モダンライフサイクルポリシーについて簡単に説明すると、Windows 10では3月と9月の年2回、機能更新プログラムのリリースが予定されており、この機能更新プログラムのリリースから18ヶ月 (EnterpriseとEducation Editonについては、9月更新は+1年された30ヶ月) が、その機能更新プログラムを適用したWindows 10のサポート期間となる。

機能更新プログラムは2020年4月まではYYMMの形式で表現されていたが、最新の2020年10月のアップデートからは20H2という名称になっている。2021年は21H1、21H2といった名称でリリースされることになる。

また、Windows 10, version 21H2以降は、今までの半期に1回の機能更新プログラムリリースから、年1回下期のリリースのみに変更された。

以下に現時点におけるサポート中のバージョンを以下に記載する。なお、Windows 11の登場によって、Windows 10 全体としてのEOSも存在するため注意すること。

OS名 サポート期限 (Home and Pro) サポート期限 (Enterprise and Education)
Windows 10 全体 2025/10/14 2025/10/14
Windows 10, version 20H2 2022/05/10 2023/05/09
Windows 10, version 21H2 2023/06/13 2024/06/11
Windows 10, version 22H2 2024/05/14 2025/05/13

Windows 11

Windows 11もモダンライフサイクルポリシーが適用されるが、サポート期間がWindows10より6ヶ月延長され、24ヶ月 (EnterpriseとEducation Editonについては36ヶ月) となった。

OS名 サポート期限 (Home and Pro) サポート期限 (Enterprise and Education)
Windows 11 (Version 21H2) 2023/10/10 2024/10/08
Windows 11 (Version 22H2) 2024/10/08 2025/10/14

Windows Server

Windows Serverは現時点で、Windows Server 2012、2012 R2、2016、2019、2022の5つのバージョンがサポートされる状況となっている。

2023年は、Windows Server 2012の延長サポートが終了する。

OS名 サポート状況 サポート期限
Windows Server 2012 延長サポート 2023/10/10
Windows Server 2012 R2 延長サポート 2023/10/10
Windows Server 2016 延長サポート 2027/01/12
Windows Server 2019 メインストリームサポート 2024/01/09
Windows Server 2019 延長サポート 2029/01/09
Windows Server 2022 メインストリームサポート 2026/10/13
Windows Server 2022 延長サポート 2031/10/14

VMware vSphere

2022年にvSphere 8.0がリリースされた年となった。2023年は、vSphere 6.5及びvSphere 6.7のTECHNICAL GUIDANCEが終了するので注意。

OS名 サポート状況 サポート期限
vSphere 6.5 TECHNICAL GUIDANCE 2023/11/15
vSphere 6.7 TECHNICAL GUIDANCE 2023/11/15
vSphere 7.0 GENERAL SUPPORT 2025/04/02
vSphere 7.0 TECHNICAL GUIDANCE 2027/04/02
vSphere 8.0 GENERAL SUPPORT 2027/10/11
vSphere 8.0 TECHNICAL GUIDANCE 2029/10/11

Red Hat Enterprise Linux

2022年はRHEL 9がリリースされた年となった。現在、RHEL 6は延長サポートフェーズのみとなっているが、2023年にEOSとなる製品は存在しない。

OS名 サポート状況 サポート期限
Red Hat Enterprise Linux 6 Extended Life-cycle Support 2024/06/30
Red Hat Enterprise Linux 7 Maintenance Support 2024/06/30
Red Hat Enterprise Linux 7 Extended Life-cycle Support 2026/06/30
Red Hat Enterprise Linux 8 Maintenance Support 2029/05/31
Red Hat Enterprise Linux 8 Extended Life-cycle Support 2031/05/31
Red Hat Enterprise Linux 9 Maintenance Support 2032/05/31
Red Hat Enterprise Linux 9 Extended Life-cycle Support 2034/05/31

AIX

AIXはTL (Technology Level)毎にサポート期限が異なる。現在サポートが継続しているTLを記載する。AIX 7.2 TL5は昨年までは2023年11月がEOS期限と予想されていたが、TBD(時期未定)に表記が更新されていた。

OS名 サポート状況 サポート期限
AIX 7.1 TL5 Service Pack Support 2023/04/30
AIX 7.2 TL5 Service Pack Support TBD(時期未定)
AIX 7.3 TL0 Service Pack Support 2024/12/31
AIX 7.3 TL1 Service Pack Support 2025/12/31

HP-UX

HP-UXはあまり頻繁なバージョンアップはなく、2007年4月に発表されたHP-UX 11i v3が未だに最新という状況となっている。

長らく延長されてきたHP-UX 11i v2のサポート期限が更新されていないことから、とうとう2023年にサポート期限を迎えるようだ。

OS名 サポート状況 サポート期限
HP-UX 11i v2 延長サポート(開発元支援なし) 2023/12月
HP-UX 11i v3 (HPE Integrity) 標準サポート 2025/12月
HP-UX 11i v3 (HPE Integrity) 延長サポート(開発元支援なし) 2028/12月

以上。

2022年12月17日土曜日

AnsibleでCisco Business 250 (CBS250)を操作する

自宅ではAnsibleを導入してから、以下OSやソフトウェアに対して作業のコード化や自動化を行ってきた。導入手順などは以下記事を参照。

OS/ソフトウェア URL
Linux AnsibleでLinuxサーバの初期設定と単体テストを行う
Windows Server AnsibleからWindows Serverに接続するための事前作業
vSphere ESXi AnsibleでESXi上に仮想マシンを構築する

今回は、Ansibleを使って物理スイッチであるCisco Business 250 (CBS250)を操作する手順を記載する。Cisco Business 250 (CBS250)は、Ansibleに標準で導入されているcommunity.ciscosmbというモジュールで操作可能となる。

注意事項

私の環境では何度かコマンド実行すると、ときおりcommand timeout triggered, timeout value is 30 secs.のエラーでコマンド実行に失敗する事象が発生した。タイムアウト時間を延ばしてもうまくいかないが、しらばく時間を空けると成功するようになることまではわかっているが、解決には至らなかった。

環境

今回手順を確認した環境は以下の通り。

  • コントロールノード
    • OS : AlmaLinux 8.5
    • Ansible : ansible [core 2.13.1]
    • jqコマンドを使うため、あらかじめパッケージをインストールしておく
  • スイッチ
    • 機種 : Cisco Business 250 (CBS250-8T-E-2G)
    • ファームウェアバージョン : 3.2.0.84

事前準備として、あらかじめCBS250に対して以下を実施しておく。

  • SSH接続できるよう設定済みであること
  • SSH用の一般ユーザを作成済みであること
  • enableコマンド実行時のパスワードを設定済みであること

Cisco Business 250のconfigを取得するPlaybook

今回のPlaybookでは、show startup-configを実行して取得したコンフィグをファイルとして保存する。

以下にPlaybookの内容を説明する。

Playbook説明

変数 (vars)

Ansibleを使ってネットワーク機器を操作する際の変数は、以下の通り設定する。ポイントは、ansible_network_oscommunity.ciscosmb.ciscosmbと設定することだ。それ以外は、Cisco IOSなどを操作する際と大きく設定は変わらない。

変数 設定値
ansible_user 任意のSSH接続用ユーザを設定。今回はciscoで設定。
ansible_password 任意のSSH接続用ユーザのパスワードを設定。
ansible_connection network_cli
ansible_network_os community.ciscosmb.ciscosmb
ansible_become_method enable
ansible_become_password enableコマンド実行時のパスワードを設定。

タスク (tasks)

Playbookのタスクは以下の通り。

タスク モジュール 説明
Exec command (show startup-config) community.ciscosmb.command show startup-configを実行した結果を変数に格納する。
Output file cbs250 configuration ansible.builtin.copy コンフィグが保存された変数の内容をファイルに出力する。出力結果はJSON形式になる。
Convert file cbs250 configuration ansible.builtin.shell JSON形式の出力結果をRAW形式に変換する。この処理はAnsibleのshellモジュールを用いてjqコマンドを用いてファイルを整形することで実現した。
Remove temp file ansible.builtin.file 整形前のJSON形式のファイルを削除する。

Playbook

以上をふまえ、Playbook全体は以下となる。

get_cbs250_config.yml

---
- name: Get cisco business 250 configuration
  gather_facts: true
  hosts: cbs250

  vars:
    ansible_user: cisco
    ansible_password: 'P@ssw0rd'
    ansible_connection: network_cli
    ansible_network_os: community.ciscosmb.ciscosmb
    ansible_become_method: enable
    ansible_become_password: 'P@ssw0rd'

    file_cbs250_config: "{{ lookup('env', 'PWD') }}/cbs250/{{ inventory_hostname }}_conf.log"
    file_cbs250_config_tmp: "{{ lookup('env', 'PWD') }}/cbs250/{{ inventory_hostname }}_conf_tmp.log"

  tasks:
    # config取得
    - name: Exec command (show startup-config)
      community.ciscosmb.command:
        commands: show startup-config
      register: result
      become: true

    # configをファイル出力
    - name: Output file cbs250 configuration
      ansible.builtin.copy:
        content: "{{ result.stdout_lines }}"
        dest: "{{ file_cbs250_config_tmp }}"
        mode: '0644'
      delegate_to: localhost

    # JSON形式からRAW形式に変換
    - name: Convert file cbs250 configuration
      ansible.builtin.shell: |
        set -o pipefail && cat "{{ file_cbs250_config_tmp }}" | jq -r .[][] > "{{ file_cbs250_config }}"
      changed_when: false
      delegate_to: localhost

    # 一時ファイルの削除
    - name: Remove temp file
      ansible.builtin.file:
        path: "{{ file_cbs250_config_tmp }}"
        state: absent

実行結果

Playbookの実行結果は以下の通り。

# ansible-playbook -i hosts get_cbs250_config.yml 

PLAY [Get cisco business 250 configuration] *************************************************************************

TASK [Gathering Facts] **********************************************************************************************
ok: [cbs250]

TASK [Exec command (show startup-config)] ***************************************************************************
ok: [cbs250]

TASK [Output file cbs250 configuration] *****************************************************************************
changed: [cbs250 -> localhost]

TASK [Convert file cbs250 configuration] ****************************************************************************
ok: [cbs250 -> localhost]

TASK [Remove temp file] *********************************************************************************************
changed: [cbs250]

PLAY RECAP **********************************************************************************************************
cbs250                  : ok=5    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

CBS250のconfigファイルも以下の通り出力される。

cbs250/cbs250_conf.log

config-file-header
cbs250
v3.2.0.84 / RCBS3.2_950_377_134
CLI v1.0
file SSD indicator encrypted
@
ssd-control-start
ssd config
ssd file passphrase control unrestricted
no ssd file integrity control

~(以下略)~

以上で、Ansibleを使って物理スイッチであるCisco Business 250 (CBS250)を操作する手順は完了となる。

2022年12月10日土曜日

Ansibleを使ってDcokerのコンテナ環境をを操作する

今まで本ブログでは、Ansibleを使ってLinuxやWindows Serverの操作を実施してきた。Ansibleは他にも様々なモジュールが標準で含まれている。

Ansibleに含まれるモジュールは、以下コマンドで確認することができる。

# ansible-galaxy collection list
Collection                    Version
----------------------------- -------
amazon.aws                    3.5.0
ansible.netcommon             3.1.3
ansible.posix                 1.4.0
ansible.utils                 2.7.0
ansible.windows               1.12.0
arista.eos                    5.0.1

~(中略)~

community.docker              2.7.1

~(中略)~

vmware.vmware_rest            2.2.0
vultr.cloud                   1.3.0
vyos.vyos                     3.0.1
wti.remote                    1.0.4

今回は、上記に記載されているcommunity.dockerモジュールを使うことでDockerのコンテナ環境を操作することができる。今回は、Ansibleを使ってDockerのコンテナの環境を操作し、コンテナの停止、ビルド、起動を行うための手順を記載する。

環境

今回手順を確認した環境のOSは以下の通り。

  • コントロールノード
    • OS : AlmaLinux 8.5
    • Ansible : ansible [core 2.13.1]
  • DockerホストOS
    • OS : CentOS Stream release 8
    • Docker : docker-ce-20.10.14

Ansibleコントロールノード構築やLinuxサーバの事前準備の手順は、以下記事を参照いただきたい。

また、Docker上の操作対象のコンテナは以下3つとなる。各コンテナは、あらかじめDockerfileや必要な設定ファイルを準備しておく。必要な設定ファイルについては、それぞれ過去記事を参照いただきたい。

Dockerホストに対する事前準備

AnsibleでDockerを操作する場合、Dcokerホストに対して事前準備作業が必要となる。

1. pipをインストール

Dockerを利用する際はPythonパッケージのインストールが必要となるため、pipをインストールしておく。

# dnf install python3-pip

2. pipを用いてPythonパッケージをインストール

pipを用いて、以下の通りPythonパッケージをインストールする。

# python3 -m pip install docker docker-compose

もしこのモジュールをインストールしていない場合は、Playbook実行時に以下のようにPythonのモジュールが不足するといったエラーが発生する。

fatal: [dockerhost]: FAILED! => {"ansible_facts": {"discovered_interpreter_python": "/usr/libexec/platform-python"}, "can_talk_to_docker": false, "changed": false, "msg": "Failed to import the required Python library (Docker SDK for Python: docker above 5.0.0 (Python >= 3.6) or docker before 5.0.0 (Python 2.7) or docker-py (Python 2.6)) on t3027dock's Python /usr/libexec/platform-python. Please read the module documentation and install it in the appropriate location. If the required library is installed, but Ansible is using the wrong Python interpreter, please consult the documentation on ansible_python_interpreter, for example via `pip install docker` (Python >= 3.6) or `pip install docker==4.4.4` (Python 2.7) or `pip install docker-py` (Python 2.6). The error was: No module named 'docker'"}
fatal: [dockerhost]: FAILED! => {"changed": false, "msg": "Unable to load docker-compose. Try `pip install docker-compose`. Error: Traceback (most recent call last):\n  File \"/tmp/ansible_community.docker.docker_compose_payload_uyzpmc__/ansible_community.docker.docker_compose_payload.zip/ansible_collections/community/docker/plugins/modules/docker_compose.py\", line 497, in <module>\nModuleNotFoundError: No module named 'compose'\n"}

なお、Pythonパッケージについて、dockerまたはdocker-pyのどちらかをインストールすればよいらしい。ただし、両方のインストールはNGであると明確にAnsibleのマニュアルに記載されているので注意しよう。

docker-py モジュールと docker python モジュールは、同じ名前空間を使用するため、
両方インストールすると、インストールが破損します。両方のパッケージをアンインストールし、
docker-py または docker python モジュールのいずれかを再インストールしてください。
Python 2.6 のサポートが必要でない場合は、
docker モジュールをインストールすることが推奨されます。
いずれかのモジュールをアンインストールするだけでは、
もう一方のモジュールが壊れた状態になる可能性があることに注意してください。

3. Ansible実行ユーザをdockerグループに所属させる

Ansible実行時にAnsible実行ユーザがDockerにアクセスできる権限が必要となる。

# usermod -aG docker ansibleuser
# id ansibleuser
uid=2001(ansibleuser) gid=2001(ansibleuser) groups=2001(ansibleuser),990(docker)

以上でDockerホストに対する事前作業は完了となる。実際にPythonを実行してみよう。

Docker操作用Playbook

1. Playbook説明

今回のPlaybookの実行フローは以下の通り。

各タスクのモジュールと処理の説明を以下表に記載する。

タスク名 モジュール 説明
Copy Dockerfile copy 各コンテナ用のDockerfile及び必要な設定ファイルをディレクトリごとコピーする。
Copy Dockerfile template template 各コンテナ用のDockerfileについて再配置する(変数で指定したベースイメージに設定したファイルを配置する)。
Build docker image docker_image Dockerfileを用いてイメージをビルドする。
Copy docker-compose.yml template template docker-compose.ymlをコピーする。
Down container docker_compose 現在稼働しているコンテナを停止&削除(Down)する。
Up container docker_compose 新しいイメージからコンテナを作成&起動(Up)する。

実際のPlaybookは以下となる。

---
- name: Rebuild docker container
  gather_facts: false
  hosts: docker_servers

  vars:
    ansible_user: ansibleuser

    docker_config:
      image: almalinux
      tag: 8.7

    docker_container:
      - name: "{{ docker_config.image }}-postfix"
        path: container-postfix
      - name: "{{ docker_config.image }}-unbound"
        path: container-unbound
      - name: "{{ docker_config.image }}-squid"
        path: container-squid

    docker_file_path: /tmp/docker

  tasks:
    # Dockerfileコピー
    - name: Copy Dockerfile
      ansible.builtin.copy:
        src: "templates/{{ item.path }}"
        dest: "/tmp/"
        mode: 0644
      loop: "{{ docker_container }}"

    # Dockerfileテンプレートコピー
    - name: Copy Dockerfile template
      ansible.builtin.template:
        src: "templates/{{ item.path }}/Dockerfile"
        dest: "/tmp/{{ item.path }}/"
        mode: 0644
      loop: "{{ docker_container }}"

    # イメージ構築
    - name: Build docker image
      community.docker.docker_image:
        build:
          path: "/tmp/{{ item.path }}"
        source: build
        name: "{{ item.name }}"
        tag: "{{ docker_config.tag }}"
        state: present
      loop: "{{ docker_container }}"

    # docker-compose.ymlテンプレートコピー
    - name: Copy docker-compose.yml template
      ansible.builtin.template:
        src: "templates/compose/docker-compose.yml"
        dest: "/root/compose/"
        mode: 0644
      become: true

    # コンテナ停止&削除
    - name: Down container
      community.docker.docker_compose:
        project_src: /root/compose
        build: false
        # stopped: true # 停止のみ実行する場合
        state: absent
      become: true

    # コンテナ起動
    - name: Up container
      community.docker.docker_compose:
        project_src: /root/compose
        build: false
        state: present
      become: true

2. Playbook実行

# ansible-playbook -i hosts -l dockerhost docker/rebuild_docker_container.yml

PLAY [Rebuild docker container] **********************************************************************************

TASK [Copy Dockerfile] *******************************************************************************************
changed: [dockerhost] => (item={'name': 'almalinux-postfix', 'path': 'container-postfix'})
changed: [dockerhost] => (item={'name': 'almalinux-unbound', 'path': 'container-unbound'})
changed: [dockerhost] => (item={'name': 'almalinux-squid', 'path': 'container-squid'})

TASK [Copy Dockerfile template] **********************************************************************************
changed: [dockerhost] => (item={'name': 'almalinux-postfix', 'path': 'container-postfix'})
changed: [dockerhost] => (item={'name': 'almalinux-unbound', 'path': 'container-unbound'})
changed: [dockerhost] => (item={'name': 'almalinux-squid', 'path': 'container-squid'})

TASK [Build docker image] ****************************************************************************************
ok: [dockerhost] => (item={'name': 'almalinux-postfix', 'path': 'container-postfix'})
ok: [dockerhost] => (item={'name': 'almalinux-unbound', 'path': 'container-unbound'})
ok: [dockerhost] => (item={'name': 'almalinux-squid', 'path': 'container-squid'})

TASK [Copy docker-compose.yml template] **************************************************************************
changed: [dockerhost]

TASK [Down container] ********************************************************************************************
ok: [dockerhost]

TASK [Up container] **********************************************************************************************
changed: [dockerhost]

PLAY RECAP *******************************************************************************************************
dockerhost                 : ok=6    changed=4    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

3. 結果確認

Playbook実行後のDcokerのコンテナイメージとコンテナの状態を比較してみよう。

まずは実行前の状態を以下に示す。イメージはAlmaLinux 8.6のみとなっており、それぞれのコンテナのタグも8.6になっていることがわかる。

# docker images
REPOSITORY          TAG       IMAGE ID       CREATED         SIZE
almalinux-unbound   8.6       fd58943ebaca   2 months ago    243MB
almalinux-squid     8.6       f6e9116750e0   2 months ago    298MB
almalinux-postfix   8.6       0ca7abe54260   2 months ago    281MB
almalinux           8.6       90516e8d258d   6 months ago    189MB

# docker ps
CONTAINER ID   IMAGE                   COMMAND                  CREATED          STATUS          PORTS                                                                              NAMES
df0976682bfe   almalinux-squid:8.6     "/usr/sbin/squid -N …"   49 minutes ago   Up 49 minutes   0.0.0.0:8080->8080/tcp, :::8080->8080/tcp                                          almalinux-squid
553c80481ac3   almalinux-unbound:8.6   "/usr/sbin/unbound -d"   49 minutes ago   Up 49 minutes   0.0.0.0:10053->53/tcp, 0.0.0.0:10053->53/udp, :::10053->53/tcp, :::10053->53/udp   almalinux-unbound
303103b4abe8   almalinux-postfix:8.6   "/startup.sh"            49 minutes ago   Up 49 minutes   0.0.0.0:25->25/tcp, :::25->25/tcp                                                  almalinux-postfix

次に、Playbook実行後の状態を以下に示す。8.6のイメージに加えて、新たに8.7のイメージが作成されていることがわかる。また、コンテナもタグが8.7に更新されていることが確認できる。

# docker images
REPOSITORY          TAG       IMAGE ID       CREATED          SIZE
almalinux-squid     8.7       7fe03e3252a7   2 seconds ago    292MB
almalinux-unbound   8.7       bed4cd545c1f   17 seconds ago   240MB
almalinux-postfix   8.7       261591afe46c   18 minutes ago   275MB
almalinux           8.7       39f63d416992   3 days ago       190MB
almalinux-unbound   8.6       fd58943ebaca   2 months ago     243MB
almalinux-squid     8.6       f6e9116750e0   2 months ago     298MB
almalinux-postfix   8.6       0ca7abe54260   2 months ago     281MB
almalinux           8.6       90516e8d258d   6 months ago     189MB

# docker ps
CONTAINER ID   IMAGE                   COMMAND                  CREATED          STATUS          PORTS                                                                              NAMES
ec700661b92c   almalinux-unbound:8.7   "/usr/sbin/unbound -d"   25 seconds ago   Up 25 seconds   0.0.0.0:10053->53/tcp, 0.0.0.0:10053->53/udp, :::10053->53/tcp, :::10053->53/udp   almalinux-unbound
1d769e4c9ee6   almalinux-squid:8.7     "/usr/sbin/squid -N …"   25 seconds ago   Up 25 seconds   0.0.0.0:8080->8080/tcp, :::8080->8080/tcp                                          almalinux-squid
9ff38aa8b594   almalinux-postfix:8.7   "/startup.sh"            25 seconds ago   Up 25 seconds   0.0.0.0:25->25/tcp, :::25->25/tcp                                                  almalinux-postfix

以上で、AnsibleにてDockerコンテナを操作する手順は完了となる。

参考

2022年12月3日土曜日

オフライン環境のPythonの仮想環境にAnsibleコントロールノードを構築する

Ansibleはエージェントレスでさまざまな機器の設定を行ことができる非常に強力なツールである。通常、Ansibleコントロールノードを構築する際には、pipを用いてインターネット環境よりインストールする必要があり、インターネットに接続できない環境での利用が難しいという問題がある。
※このようなインターネットと物理的に接続をさせない環境をエアギャップ環境と呼ぶ。

このような環境の場合は、別のインターネットに接続できる環境であらかじめダウンロードしたファイルを持ち込み適用することが一般的である。セキュリティパッチのファイルやウィルス対策ソフトのパターンファイルなども同様の手法で適用することが多い。

AnsibleはPythonをベースに動作するソフトウェアであるため、Pythonの機能を利用することで、エアギャップ環境でのインストールは可能である。

今回は、事前にインターネットに接続できる環境にてAnsibleコントロールノードに必要となるPythonパッケージをダウンロードしておき、それをオフライン環境のLinuxサーバに配置し、Pythonの仮想環境を用いてインストールする方法を紹介する。

以下に作業の概要図を記載する。

環境

今回の動作検証はAlmaLinux 8に対して実施した。ただし、Red Hat系のディストリビューションであるCentOSやRocky Linuxなどでも同様の手順で実施できるだろう。

  • OS : AlmaLinux 8.6
  • Python : 3.8.12
  • Ansible : ansible [core 2.13.5]

AnsibleのPythonパッケージをダウンロード

1. Python 3.8をインストール

AlmaLinux 8.xなどのRed Hat 8.x系のOSでは、Pythonをインストールしても通常3.6がインストールされる。Python 3.6の場合は、Ansible 2.11までであれば動作させることはできるが以下問題がある。

  • Ansible実行時に毎回[DEPRECATION WARNING]の警告メッセージが表示される
  • Ansible 2.11は2022年11月でメンテナンス終了となる

そのため、今回はPython 3.8もインストールし、Ansible 2.13を利用できるようにする。Python 3.8はdnfを使ってインストールできる。

# dnf install python38 -y
メタデータの期限切れの最終確認: 4:28:17 時間前の 2022年10月29日 17時49分52秒 に 実施しました。
依存関係が解決しました。
================================================================================
 パッケージ        Arch   バージョン                            Repo      サイズ
================================================================================
インストール:
 python38          x86_64 3.8.12-1.module_el8.6.0+2778+cd494b30 appstream  78 k
依存関係のインストール:
 python38-libs     x86_64 3.8.12-1.module_el8.6.0+2778+cd494b30 appstream 8.3 M
 python38-pip-wheel
                   noarch 19.3.1-5.module_el8.6.0+2778+cd494b30 appstream 1.0 M
 python38-setuptools-wheel
                   noarch 41.6.0-5.module_el8.6.0+2778+cd494b30 appstream 303 k
弱い依存関係のインストール:
 python38-pip      noarch 19.3.1-5.module_el8.6.0+2778+cd494b30 appstream 1.8 M
 python38-setuptools
                   noarch 41.6.0-5.module_el8.6.0+2778+cd494b30 appstream 667 k
モジュールストリームの有効化中:
 python38                 3.8

~(中略)~

インストール済み:
  python38-3.8.12-1.module_el8.6.0+2778+cd494b30.x86_64
  python38-libs-3.8.12-1.module_el8.6.0+2778+cd494b30.x86_64
  python38-pip-19.3.1-5.module_el8.6.0+2778+cd494b30.noarch
  python38-pip-wheel-19.3.1-5.module_el8.6.0+2778+cd494b30.noarch
  python38-setuptools-41.6.0-5.module_el8.6.0+2778+cd494b30.noarch
  python38-setuptools-wheel-41.6.0-5.module_el8.6.0+2778+cd494b30.noarch

完了しました!

2. pipをバージョンアップ

ダウンロードやインストール作業で失敗することがあるため、pipを最新版にしておく。

# pip-3.8 install -U pip
WARNING: Running pip install with root privileges is generally not a good idea. Try `pip-3.8 install --user` instead.
Collecting pip
  Downloading https://files.pythonhosted.org/packages/47/ef/8b5470b5b94b36231ed9c0bde90caa71c0d4322d4a15f009b2b7f4287fe0/pip-22.3-py3-none-any.whl (2.1MB)
     |????????????????????????????????| 2.1MB 10.9MB/s
Installing collected packages: pip
Successfully installed pip-22.3

3. Ansibleコントロールノード構築用のPythonパッケージをダウンロード

ダウンロードしたファイルを保管するディレクトリを以下の通り作成する。

# mkdir ansible-pack

Pythonパッケージはpip downloadコマンドを実行することでダウンロードできる。今回は以下3点のパッケージをダウンロードする。

  • pip
  • ansible
  • pywinrm

以下に実行結果を記載する。

pip

# pip-3.8 download -d ./ansible-pack pip
WARNING: pip is being invoked by an old script wrapper. This will fail in a future version of pip.
Please see https://github.com/pypa/pip/issues/5599 for advice on fixing the underlying issue.
To avoid this problem you can invoke Python with '-m pip' instead of running pip directly.
Collecting pip
  Using cached pip-22.3-py3-none-any.whl (2.1 MB)
Saved ./ansible-pack/pip-22.3-py3-none-any.whl
Successfully downloaded pip

ansible

# pip-3.8 download -d ./ansible-pack ansible
WARNING: pip is being invoked by an old script wrapper. This will fail in a future version of pip.
Please see https://github.com/pypa/pip/issues/5599 for advice on fixing the underlying issue.
To avoid this problem you can invoke Python with '-m pip' instead of running pip directly.
Collecting ansible
  Downloading ansible-6.5.0-py3-none-any.whl (44.9 MB)
     qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq 44.9/44.9 MB 30.7 MB/s eta 0:00:00
Collecting ansible-core~=2.13.5
  Downloading ansible_core-2.13.5-py3-none-any.whl (2.1 MB)
     qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq 2.1/2.1 MB 28.6 MB/s eta 0:00:00

~(中略)~

Saved ./ansible-pack/pycparser-2.21-py2.py3-none-any.whl
Successfully downloaded ansible ansible-core jinja2 PyYAML resolvelib cryptography packaging cffi MarkupSafe pyparsing pycparser

pywinrm

# pip-3.8 download -d ./ansible-pack pywinrm
WARNING: pip is being invoked by an old script wrapper. This will fail in a future version of pip.
Please see https://github.com/pypa/pip/issues/5599 for advice on fixing the underlying issue.
To avoid this problem you can invoke Python with '-m pip' instead of running pip directly.
Collecting pywinrm
  Using cached pywinrm-0.4.3-py2.py3-none-any.whl (44 kB)

~(中略)~

Saved ./ansible-pack/urllib3-1.26.12-py2.py3-none-any.whl
Successfully downloaded pywinrm requests requests-ntlm six xmltodict certifi charset-normalizer cryptography idna ntlm-auth urllib3 cffi pycparser

ダウンロードしたファイルは合計53MBとなった。

# du -h ansible-pack/
53M     ansible-pack/

4. ダウンロードしたPythonパッケージを圧縮して持ち出し

持ち出ししやすいようtarを使ってパッケージを圧縮する。

# tar zcvf ansible-pack.tgz ansible-pack/
ansible-pack/
ansible-pack/pip-22.3-py3-none-any.whl
ansible-pack/ansible-6.5.0-py3-none-any.whl
ansible-pack/ansible_core-2.13.5-py3-none-any.whl
ansible-pack/Jinja2-3.1.2-py3-none-any.whl
ansible-pack/PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl
ansible-pack/resolvelib-0.8.1-py2.py3-none-any.whl
ansible-pack/cryptography-38.0.1-cp36-abi3-manylinux_2_28_x86_64.whl
ansible-pack/packaging-21.3-py3-none-any.whl
ansible-pack/cffi-1.15.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
ansible-pack/MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
ansible-pack/pyparsing-3.0.9-py3-none-any.whl
ansible-pack/pycparser-2.21-py2.py3-none-any.whl
ansible-pack/pywinrm-0.4.3-py2.py3-none-any.whl
ansible-pack/requests-2.28.1-py3-none-any.whl
ansible-pack/requests_ntlm-1.1.0-py2.py3-none-any.whl
ansible-pack/six-1.16.0-py2.py3-none-any.whl
ansible-pack/xmltodict-0.13.0-py2.py3-none-any.whl
ansible-pack/certifi-2022.9.24-py3-none-any.whl
ansible-pack/charset_normalizer-2.1.1-py3-none-any.whl
ansible-pack/idna-3.4-py3-none-any.whl
ansible-pack/ntlm_auth-1.5.0-py2.py3-none-any.whl
ansible-pack/urllib3-1.26.12-py2.py3-none-any.whl

圧縮したファイルを任意の手法で持ち出しを行い、オフライン環境のLinuxサーバに配置しておこう。

ダウンロードしたPythonパッケージをPythonの仮想環境にインストール

続けて、ダウンロードしたPythonパッケージをPythonの仮想環境にインストールする手順を説明する。

1. 前提パッケージ確認

Ansible 2.13を動作させるためには、最低限以下2つのパッケージインストールが必要となる。

  • Python 3.8
  • sshpass

Python 3.8は前述の通り、Ansible の動作条件として必要となる。sshpassは、AnsibleからLinuxなどの機器に対してパスワード認証方式を用いてSSH接続する際に必要となる。

# dnf install --disablerepo=dvd* python38 -y
# dnf install --disablerepo=dvd* sshpass -y

2. ダウンロードしたファイルを展開

インターネット環境からダウンロードしたファイルを展開する。

# tar zxvf ansible-pack.tgz
ansible-pack/
ansible-pack/pip-22.3-py3-none-any.whl
ansible-pack/ansible-6.5.0-py3-none-any.whl
ansible-pack/ansible_core-2.13.5-py3-none-any.whl
ansible-pack/Jinja2-3.1.2-py3-none-any.whl
ansible-pack/PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl
ansible-pack/resolvelib-0.8.1-py2.py3-none-any.whl
ansible-pack/cryptography-38.0.1-cp36-abi3-manylinux_2_28_x86_64.whl
ansible-pack/packaging-21.3-py3-none-any.whl
ansible-pack/cffi-1.15.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
ansible-pack/MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
ansible-pack/pyparsing-3.0.9-py3-none-any.whl
ansible-pack/pycparser-2.21-py2.py3-none-any.whl
ansible-pack/pywinrm-0.4.3-py2.py3-none-any.whl
ansible-pack/requests-2.28.1-py3-none-any.whl
ansible-pack/requests_ntlm-1.1.0-py2.py3-none-any.whl
ansible-pack/six-1.16.0-py2.py3-none-any.whl
ansible-pack/xmltodict-0.13.0-py2.py3-none-any.whl
ansible-pack/certifi-2022.9.24-py3-none-any.whl
ansible-pack/charset_normalizer-2.1.1-py3-none-any.whl
ansible-pack/idna-3.4-py3-none-any.whl
ansible-pack/ntlm_auth-1.5.0-py2.py3-none-any.whl
ansible-pack/urllib3-1.26.12-py2.py3-none-any.whl

3. Pythonの仮想環境を作成

Pythonの仮想環境は、python -m venv [インストールディレクトリ名]とすることですぐに作成できる。

今回はディレクトリ名を.venvとし、Python 3.8を利用する必要があるので、python3.8コマンドを使って以下通りコマンドを実行した。

# python3.8 -m venv .venv
# ls -l .venv/
合計 4
drwxr-xr-x 2 root root 210 10月 29 22:15 bin
drwxr-xr-x 2 root root   6 10月 29 22:15 include
drwxr-xr-x 3 root root  23 10月 29 22:15 lib
lrwxrwxrwx 1 root root   3 10月 29 22:15 lib64 -> lib
-rw-r--r-- 1 root root  70 10月 29 22:15 pyvenv.cfg

4. Pythonの仮想環境を有効化

Pythonの仮想環境を有効化する際には、source [インストールディレクトリ]/bin/activateを実行する。実行すると、プロンプトに(.venv)が表示される。

[root@locahost ~]# source .venv/bin/activate
(.venv) [root@locahost ~]#

以降はPythonの仮想環境での作業については、(.venv)#でプロンプトを表記する。

5. Pythonの仮想環境にPythonパッケージをインストール

Pythonの仮想環境にて、ダウンロードしておいた以下のPythonパッケージをインストールしていく。

  • pip
  • ansible
  • pywinrm

通常のPythonパッケージと同様、pip installでインストールするが、以下オプションを付与する点に注意する。

オプション 説明
--no-index インターネット環境のパッケージインデックス(PyPI; Python Package Index)の検索を行わない。
--find-links=[パッケージディレクトリ] パッケージを検索するローカルディレクトリを指定する。

pip

(.venv)# pip install --no-index --find-links=./ansible-pack/ -U pip
Looking in links: ./ansible-pack/
Processing ./ansible-pack/pip-22.3-py3-none-any.whl
Installing collected packages: pip
  Found existing installation: pip 19.3.1
    Uninstalling pip-19.3.1:
      Successfully uninstalled pip-19.3.1
Successfully installed pip-22.3

ansible

(.venv)# pip install --no-index --find-links=./ansible-pack/ ansible
Looking in links: ./ansible-pack/
Processing ./ansible-pack/ansible-6.5.0-py3-none-any.whl
Processing ./ansible-pack/ansible_core-2.13.5-py3-none-any.whl
Processing ./ansible-pack/resolvelib-0.8.1-py2.py3-none-any.whl
Processing ./ansible-pack/cryptography-38.0.1-cp36-abi3-manylinux_2_28_x86_64.whl
Processing ./ansible-pack/PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl
Processing ./ansible-pack/Jinja2-3.1.2-py3-none-any.whl
Processing ./ansible-pack/packaging-21.3-py3-none-any.whl
Processing ./ansible-pack/MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Processing ./ansible-pack/cffi-1.15.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Processing ./ansible-pack/pyparsing-3.0.9-py3-none-any.whl
Processing ./ansible-pack/pycparser-2.21-py2.py3-none-any.whl
Installing collected packages: resolvelib, PyYAML, pyparsing, pycparser, MarkupSafe, packaging, jinja2, cffi, cryptography, ansible-core, ansible
Successfully installed MarkupSafe-2.1.1 PyYAML-6.0 ansible-6.5.0 ansible-core-2.13.5 cffi-1.15.1 cryptography-38.0.1 jinja2-3.1.2 packaging-21.3 pycparser-2.21 pyparsing-3.0.9 resolvelib-0.8.1

pywinrm

(.venv)# pip install --no-index --find-links=./ansible-pack/ pywinrm
Looking in links: ./ansible-pack/
Processing ./ansible-pack/pywinrm-0.4.3-py2.py3-none-any.whl
Processing ./ansible-pack/requests_ntlm-1.1.0-py2.py3-none-any.whl
Processing ./ansible-pack/six-1.16.0-py2.py3-none-any.whl
Processing ./ansible-pack/requests-2.28.1-py3-none-any.whl
Processing ./ansible-pack/xmltodict-0.13.0-py2.py3-none-any.whl
Processing ./ansible-pack/urllib3-1.26.12-py2.py3-none-any.whl
Processing ./ansible-pack/idna-3.4-py3-none-any.whl
Processing ./ansible-pack/certifi-2022.9.24-py3-none-any.whl
Processing ./ansible-pack/charset_normalizer-2.1.1-py3-none-any.whl
Processing ./ansible-pack/ntlm_auth-1.5.0-py2.py3-none-any.whl
Requirement already satisfied: cryptography>=1.3 in ./.venv/lib/python3.8/site-packages (from requests-ntlm>=1.1.0->pywinrm) (38.0.1)
Requirement already satisfied: cffi>=1.12 in ./.venv/lib/python3.8/site-packages (from cryptography>=1.3->requests-ntlm>=1.1.0->pywinrm) (1.15.1)
Requirement already satisfied: pycparser in ./.venv/lib/python3.8/site-packages (from cffi>=1.12->cryptography>=1.3->requests-ntlm>=1.1.0->pywinrm) (2.21)
Installing collected packages: xmltodict, urllib3, six, ntlm-auth, idna, charset-normalizer, certifi, requests, requests-ntlm, pywinrm
Successfully installed certifi-2022.9.24 charset-normalizer-2.1.1 idna-3.4 ntlm-auth-1.5.0 pywinrm-0.4.3 requests-2.28.1 requests-ntlm-1.1.0 six-1.16.0 urllib3-1.26.12 xmltodict-0.13.0

6. Pythonパッケージインストール後の確認

インストール後、pip listでパッケージが表示されることを確認しておこう。

(.venv)# pip list
Package            Version
------------------ ---------
ansible            6.5.0
ansible-core       2.13.5
certifi            2022.9.24
cffi               1.15.1
charset-normalizer 2.1.1
cryptography       38.0.1
idna               3.4
Jinja2             3.1.2
MarkupSafe         2.1.1
ntlm-auth          1.5.0
packaging          21.3
pip                22.3
pycparser          2.21
pyparsing          3.0.9
pywinrm            0.4.3
PyYAML             6.0
requests           2.28.1
requests-ntlm      1.1.0
resolvelib         0.8.1
setuptools         41.6.0
six                1.16.0
urllib3            1.26.12
xmltodict          0.13.0

Ansibleも問題なく2.13.5がインストールできていることが確認できる。

(.venv)# ansible --version
ansible [core 2.13.5]
  config file = /root/ansible.cfg
  configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /root/.venv/lib64/python3.8/site-packages/ansible
  ansible collection location = /root/.ansible/collections:/usr/share/ansible/collections
  executable location = /root/.venv/bin/ansible
  python version = 3.8.12 (default, Apr 21 2022, 07:55:08) [GCC 8.5.0 20210514 (Red Hat 8.5.0-10)]
  jinja version = 3.1.2
  libyaml = True

なお、Pythonの仮想環境の場合、ansibleansible-playbookの配置場所は、インストールディレクトリは以下の/binとなる。環境変数でパスが設定されているため、ここに配置されたコマンドは特にPythonの仮想環境であることを意識することなくコマンド実行することができる。

(.venv)# which ansible
/root/.venv/bin/ansible
(.venv)# which ansible-playbook
/root/.venv/bin/ansible-playbook

Pythonの仮想環境にてAnsibleコントロールノードから処理を実行

1. ansibleコマンドでpingモジュールを実行

それでは実際にAnsibleを実行してみよう。まずはLinuxサーバに対して定番のpingモジュールを実行してみる。

Ansible実行前にインベントリファイルとしてhostsというファイル名でファイルを作成しておこう。

hosts

(.venv)# cat hosts
[linux_servers]
t1193alma ansible_host=192.168.11.193

[windows_servers]
t1194w219 ansible_host=192.168.11.194

[windows_servers:vars]
ansible_user=ansibleuser
ansible_password=[ansibleuserのパスワード]
ansible_port=5986
ansible_connection=winrm
ansible_winrm_server_cert_validation=ignore

ansibleコマンドにてpingモジュールを実行してみると、問題なく"ping": "pong"と表示された。

(.venv)# ansible -i hosts -u ansibleuser -m ping t1193alma --ask-pass
SSH password:
t1193alma | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "ping": "pong"
}

2. ansibleコマンドでwin_pingモジュールを実行

同様に、win_pingモジュールを実行してみると、こちらも問題なく"ping": "pong"と表示された。

(.venv)# ansible -i hosts -m win_ping t1194w219
t1194w219 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}

3. ansible-playbookコマンドでPlaybookを実行

最後にansible-playbookでPlaybookを実行してみよう。Playbookの内容としては、以下のようなwin_pingするだけの簡単なものを作成した。

ping_windows_server.yml

# cat ping_windows_server.yml
---
- name: Setup windows server
  gather_facts: false
  hosts: windows_servers

  tasks:
    - name: Ping windows server
      ansible.windows.win_ping:

    - name: Debug
      ansible.builtin.debug:
        msg: "{{ inventory_hostname }}"

実行結果は以下の通り。問題なく処理が実行できた。

(.venv)# ansible-playbook -i hosts -l t1194w219 ping_windows_server.yml

PLAY [Setup windows server] ****************************************************

TASK [Ping windows server] *****************************************************
ok: [t1194w219]

TASK [Debug] *******************************************************************
ok: [t1194w219] => {
    "msg": "t1194w219"
}

PLAY RECAP *********************************************************************
t1194w219                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Pythonの仮想環境のAnsibleコントロールノードをアンインストール

1. Pythonの仮想環境を無効化

Pythonの仮想環境を無効化する場合は、deactivateコマンドを用いる。実行すると、プロンプトが通常の状態に戻る。

(.venv) [root@localhost ~]# deactivate
[root@localhost ~]#

2. Pythonの仮想環境をアンインストール

Pythonの仮想環境のアンインストールは、単純に作成したディレクトリ(今回の場合であれば.venv)を削除すればよい。

# rm -rf .venv/

以上で、オフライン環境のPythonの仮想環境にAnsibleコントロールノードを構築する手順は完了となる。

Pythonの仮想環境を用いることで、既存の環境への影響を極力抑えることができ、不要となればディレクトリを削除するだけで済む。そのため、一時的にAnsibleで処理を実行したい時などに利用することができる。

参考

2022年11月26日土曜日

OpenSSLでオレオレ証明書に作成時に"ERROR:There is already a certificate"のエラーが出た際の対処手順

以前、LinuxのOpenSSLを使ってオレオレ認証局を作り、ESXiの自己署名証明書をインポートする手順を記載した。

自宅ESXiを先日6.7から7.0にバージョンアップを行ったので、その際に証明書も新しくインポートしなおすことにしたが、"ERROR:There is already a certificate"というエラーが発生して証明書の発行(CSRに対する署名)に失敗した。
Signed certificate is in newcert.pemと最終行に表示されており、一見すると証明書が正常に発行されたように見えるが、実際は証明書は発行されていないので注意。

# cd /etc/pki/tls/misc
# ./CA -sign

~(中略)~

ERROR:There is already a certificate for /C=US/ST=California/L=Palo Alto/O=VMware, Inc/OU=VMware ESX Server Default Certificate/CN=192.168.33.12/emailAddress=ssl-certificates@vmware.com

~(以下略)~

DAmmd8agxO4NsMcfl6OzWs4whWX3xv7kS1drkrT8FkqfJ0F+7X174gjOXjhuvKGX
TjIsaV61YUPx83lQrwz0
-----END CERTIFICATE-----
Signed certificate is in newcert.pem

本記事では、OpenSSLで"ERROR:There is already a certificate"のエラーが発生した際の対処手順を記載する。

環境

今回の手順を試した環境は以下の通り。

  • OS : CentOS Stream release 8
  • OpenSSL : OpenSSL 1.1.1k FIPS 25 Mar 2021

事前に以下URLの手順にて、オレオレ認証局の構築やCAスクリプトは配置済みであることを前提とする。

エラーに対する対処手順

本エラーの原因は、発行済み証明書のリストである/etc/pki/CA/index.txtに、**今回発行しようとしている証明書の情報が重複している(まだ証明書が失効していない)**ためとなる。

以下、index.txtの抜粋となるが、今回発行対象のESXiと同じCN=192.168.33.12が存在していることがわかる。

# cat /etc/pki/CA/index.txt

~(中略)~

V       310501221913Z           0B41B73EACA2CA1C2BEC1B39B2318B4AE3352509        unknown /C=US/ST=California/L=Palo Alto/O=VMware, Inc/OU=VMware ESX Server Default Certificate/CN=192.168.33.12/emailAddress=ssl-certificates@vmware.com

本来は証明書の失効の処理を行い、その後証明書を再発行することが正しい手順となるが、手っ取り早くエラーを解消するためにはindex.txtで重複する証明書情報を削除してしまえばよい。

index.txtから該当行を削除後、再度証明書を発行すると問題なく成功した。

# ./CA -sign
Using configuration from /etc/pki/tls/openssl.cnf
Enter pass phrase for /etc/pki/CA/private/cakey.pem:
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number:

~(中略)~

T2JCerMlEQhoH0qXvJBcahulVqYkmX1Vcr4yt2HYJzJ3jVm/Hoe9McAnskjTySJ9
hk9/NnmdGpi6Gmb8jIAW
-----END CERTIFICATE-----
Signed certificate is in newcert.pem

以上で、OpenSSLで"ERROR:There is already a certificate"のエラーが発生した際の対処手順は完了となる。

2022年11月19日土曜日

GitLab Runnerインストール&バージョンアップ手順

GitLabには、リポジトリのコードの更新をトリガーとしてジョブを実行する機能として、「GitLab Runner」と呼ばれるツールが提供されている。GitLab Runnerを用いることで、CI/CDパイプラインをGitLab上で実現することができる。

GitLab RunnerはRPMのパッケージが提供されており、簡単に導入ができる。本記事では、GitLab Runnerのインストール手順とバージョンアップ手順を記載する。

GitLab Runnerインストール

今回の動作検証はAlmaLinux 8に対して実施した。ただし、Red Hat系のディストリビューションであるCentOSやRocky Linuxなどでも同様の手順で実施できるだろう。

  • OS : AlmaLinux 8.5
  • GitLab : 15.4.4
  • GitLab Runner : 15.4.1

また、GitLabのインストールは、以下記事の手順にてインストールを実施済みであることを前提とする。

GitLab Runnerインストール手順

1. GitLab Runnerパッケージのバージョン確認

GitLab Runnerのパッケージは、AWS S3上に作られているリポジトリから入手する。最新版であれば以下URLからダウンロードできる。

バージョン指定する場合は、まず以下サイトからGitLab Runnerのリリース情報を確認する。

例えば、2022/11月時点のタイミングでは、15.3.2、15.4.1、15.5.0などのバージョンがリリースされていることがわかる。

図15

今回は15.4.1をインストールするため、ダウンロードURLは以下の通りとなる。

2. パッケージダウンロード

curlコマンドでパッケージダウンロードを行う。あまりダウンロード速度は出ないので気長に待つこと。

# curl -LJO "[ダウンロードURL]"

コマンドの実行結果は以下の通り。今回は、パッケージの容量は414MBで3分程度でダウンロード完了した。

# curl -LJO "https://gitlab-runner-downloads.s3.amazonaws.com/v15.4.1/rpm/gitlab-runner_amd64.rpm"
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  414M  100  414M    0     0  2328k      0  0:03:02  0:03:02 --:--:-- 4487k

3. パッケージインストール

パッケージはそのままrpmコマンドでインストールすればよいが、gitのみ必要となるため、インストールしていない場合はインストールしておこう。

# dnf install git -y

gitインストール後、rpmコマンドでインストールすればよい。

# rpm -ivh gitlab-runner_amd64.rpm
警告: gitlab-runner_amd64.rpm: ヘッダー V4 RSA/SHA512 Signature、鍵 ID 35dfa027: NOKEY
Verifying...                          ################################# [100%]
準備しています...              ################################# [100%]
更新中 / インストール中...
   1:gitlab-runner-15.4.1-1           ################################# [100%]
GitLab Runner: creating gitlab-runner...
Home directory skeleton not used
Runtime platform                                    arch=amd64 os=linux pid=5982 revision=526d939d version=15.4.1
gitlab-runner: the service is not installed
Runtime platform                                    arch=amd64 os=linux pid=5990 revision=526d939d version=15.4.1
gitlab-ci-multi-runner: the service is not installed
Runtime platform                                    arch=amd64 os=linux pid=6013 revision=526d939d version=15.4.1
Runtime platform                                    arch=amd64 os=linux pid=6061 revision=526d939d version=15.4.1
INFO: Docker installation not found, skipping clear-docker-cache

4. GitLab RunnerをGitLabに登録

GitLab Runnerインストール後は、GitLabで利用できるように登録作業を行う。

まず、GitLab上のAdmin画面で、[Overview]->[Runners]を開く。ここで、登録のために必要となる[Registration token]をコピーしておく。

次に、GitLab Runnerをインストールしたサーバにて、gitlab-runner registerコマンドにて登録を行う。登録作業は対話形式で行う。

# gitlab-runner register
Runtime platform                                    arch=amd64 os=linux pid=6409 revision=526d939d version=15.4.1
Running in system-mode.

Enter the GitLab instance URL (for example, https://gitlab.com/):
http://gitlab.com/ ←★GitLabのURLを記載
Enter the registration token:
M-4oTXXXXeTxkhXXXXkX ←★先ほど確認したGitLabのRegistration tokenを記載
Enter a description for the runner:
[localhost]: ←★GitLab上の登録名。特に指定がなければそのままEnter
Enter tags for the runner (comma-separated):
 ←★そのままEnter
Enter optional maintenance note for the runner:
 ←★そのままEnter
Registering runner... succeeded                     runner=M-4oTtcR
Enter an executor: parallels, docker+machine, docker-ssh+machine, custom, docker, docker-ssh, shell, ssh, virtualbox, kubernetes:
shell ←★今回はshellを指定
Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!

Configuration (with the authentication token) was saved in "/etc/gitlab-runner/config.toml"

5. GitLab上で登録状況を確認

再度、GitLabにて[Overview]->[Runners]を開くと、先ほど登録したGitLab RunnerがOnline状態で表示されるはずだ。

以上で、GitLab Runnerのインストール手順は完了となる。

GitLab Runnerバージョンアップ手順

GitLabはかなりの高頻度でバージョンアップがされている。GitLab Runnerも同様にバージョンアップ頻度が高いため、インストール手順と併せてバージョンアップ手順も記載する。

1. GitLab Runnerパッケージのバージョン確認&ダウンロード

こちらはインストール手順と流れは変わらないため、割愛する。

2 GitLab Runnerバージョンアップ

インストール時との違いはrpmコマンドのオプションだけとなる。-Uオプションに変更することで、パッケージのバージョンアップが実施される。

# rpm -Uvh gitlab-runner_amd64.rpm
警告: gitlab-runner_amd64.rpm: ヘッダー V4 RSA/SHA512 Signature、鍵 ID 35dfa027: NOKEY
Verifying...                          ################################# [100%]
準備しています...              ################################# [100%]
更新中 / インストール中...
   1:gitlab-runner-15.4.1-1           ################################# [ 50%]
GitLab Runner: detected user gitlab-runner
Runtime platform                                    arch=amd64 os=linux pid=924254 revision=526d939d version=15.4.1
gitlab-runner: Service is running
Runtime platform                                    arch=amd64 os=linux pid=924296 revision=526d939d version=15.4.1
gitlab-ci-multi-runner: the service is not installed
Runtime platform                                    arch=amd64 os=linux pid=924315 revision=526d939d version=15.4.1
Runtime platform                                    arch=amd64 os=linux pid=924361 revision=526d939d version=15.4.1
INFO: Docker installation not found, skipping clear-docker-cache
整理中 / 削除中...
   2:gitlab-runner-15.4.0-1           ################################# [100%]

バージョンアップ後は特に手動でのサービス再起動等は不要で、GitLabを確認すると即座に新しいバージョンで認識しているはずだ。

以上で、GitLab Runnerのバージョンアップ手順は完了となる。

参考

2022年11月12日土曜日

GitLabバージョンアップ手順

GitLabはかなりの頻度でバージョンアップが繰り返しており、月1回新しいマイナーバージョンのリリースがされている状況となる。

例えば、直近(2022/11月時点)のバージョンリリースのタイミングは以下となる。毎月20日前後で新しいバージョンがリリースされていることがわかる。

バージョン リリース日
15.5 2022/10/21
15.4 2022/9/21
15.3 2022/8/19
15.2 2022/7/21
15.1 2022/6/21

以下サイトによると、GitLabのサポート期限はリリースから1年となっているようなので、定期的なバージョンアップ計画が必要となりそうだ。

上記をふまえ、本記事ではGitLabをバージョンアップする手順を記載する。

環境

今回の動作検証はAlmaLinux 8に対して実施した。ただし、Red Hat系のディストリビューションであるCentOSやRocky Linuxなどでも同様の手順で実施できるだろう。

  • OS : AlmaLinux 8.5
  • 旧バージョン : gitlab-ee-15.3.4-ee.0.el8.x86_64
  • 新バージョン : gitlab-ee-15.4.4-ee.0.el8.x86_64

また、GitLabのインストールは、以下記事の手順にてインストールを実施済みであることを前提とする。

GitLabバージョンアップ手順

1. バージョン選定

バージョンアップするにあたり、バージョンアップ対象バージョンの選定を行う。

パッチのリリース情報は、以下URLから確認することができる。

また、バージョンアップ時のアップグレードパスは、以下マニュアルに記載されている。

マニュアルでは以下の通りアップグレードパスが記載されており、例えば、15.0から最新版にバージョンアップする場合は、一度15.4.0を経由させてバージョンアップする必要がある。

8.11.Z -> 8.12.0 -> 8.17.7 -> 9.5.10 -> 10.8.7
-> 11.11.8 -> 12.0.12 -> 12.1.17 -> 12.10.14
-> 13.0.14 -> 13.1.11 -> 13.8.8 -> 13.12.15
-> 14.0.12 -> 14.3.6 -> 14.9.5 -> 14.10.Z
-> 15.0.Z -> 15.4.0 -> latest 15.Y.Z

今回は、15.3.4から15.4.4へのバージョンアップとなるため、直接バージョンアップが可能となる。

2. リポジトリ上に存在するGitLabのバージョン確認

dnfでそのままバージョンアップすると、最新版にバージョンアップされてしまう。特に確認せず最新版にバージョンアップする場合は本手順は不要だが、今回は特定のバージョンにバージョンアップするため、事前にGitLabのリポジトリに存在するGitLabのバージョン確認を行う。

バージョン確認は、dnf search時に--showduplicatesのオプションを付与して実行する。並び順がバージョン順とならない場合があるため、sortコマンドを使って表示をさせている。

実行結果は以下の通り。ターゲットバージョンであるgitlab-ee-15.4.4-ee.0.el8.x86_64が存在することが確認できた。

# dnf search --showduplicates gitlab-ee | sort
=========================== 名前 完全一致: gitlab-ee ===========================
gitlab-ee-12.10.0-ee.0.el8.x86_64 : GitLab Enterprise Edition (including NGINX, Postgres, Redis)
gitlab-ee-12.10.1-ee.0.el8.x86_64 : GitLab Enterprise Edition (including NGINX, Postgres, Redis)
gitlab-ee-12.10.10-ee.0.el8.x86_64 : GitLab Enterprise Edition (including NGINX, Postgres, Redis)

~(中略)~

gitlab-ee-15.3.0-ee.0.el8.x86_64 : GitLab Enterprise Edition (including NGINX, Postgres, Redis)
gitlab-ee-15.3.1-ee.0.el8.x86_64 : GitLab Enterprise Edition (including NGINX, Postgres, Redis)
gitlab-ee-15.3.2-ee.0.el8.x86_64 : GitLab Enterprise Edition (including NGINX, Postgres, Redis)
gitlab-ee-15.3.3-ee.0.el8.x86_64 : GitLab Enterprise Edition (including NGINX, Postgres, Redis)
gitlab-ee-15.3.4-ee.0.el8.x86_64 : GitLab Enterprise Edition (including NGINX, Postgres, Redis)
gitlab-ee-15.3.4-ee.0.el8.x86_64 : GitLab Enterprise Edition (including NGINX, Postgres, Redis)
gitlab-ee-15.3.5-ee.0.el8.x86_64 : GitLab Enterprise Edition (including NGINX, Postgres, Redis)
gitlab-ee-15.4.0-ee.0.el8.x86_64 : GitLab Enterprise Edition (including NGINX, Postgres, Redis)
gitlab-ee-15.4.1-ee.0.el8.x86_64 : GitLab Enterprise Edition (including NGINX, Postgres, Redis)
gitlab-ee-15.4.2-ee.0.el8.x86_64 : GitLab Enterprise Edition (including NGINX, Postgres, Redis)
gitlab-ee-15.4.3-ee.0.el8.x86_64 : GitLab Enterprise Edition (including NGINX, Postgres, Redis)
gitlab-ee-15.4.4-ee.0.el8.x86_64 : GitLab Enterprise Edition (including NGINX, Postgres, Redis)
gitlab-ee-15.5.0-ee.0.el8.x86_64 : GitLab Enterprise Edition (including NGINX, Postgres, Redis)
gitlab-ee-15.5.1-ee.0.el8.x86_64 : GitLab Enterprise Edition (including NGINX, Postgres, Redis)
gitlab-ee-15.5.2-ee.0.el8.x86_64 : GitLab Enterprise Edition (including NGINX, Postgres, Redis)

3. バージョンを指定してバージョンアップ

GitLabのバージョンを指定する場合は、dnfのパッケージ名の指定時に、バージョンまで含めた名称で指定すればよい。GitLab 15.xは1.2GBほどの容量があるため、そこそこダウンロードとインストールに時間を要するので気長に待とう。

# dnf update gitlab-ee-15.4.4-ee.0.el8.x86_64
メタデータの期限切れの最終確認: 0:02:03 時間前の 2022年11月03日 14時48分39秒 に実施しました。
依存関係が解決しました。
====================================================================================================================================
 パッケージ                  アーキテクチャー         バージョン                           リポジトリー                       サイズ
====================================================================================================================================
アップグレード:
 gitlab-ee                   x86_64                   15.4.4-ee.0.el8                      gitlab_gitlab-ee                   1.2 G

トランザクションの概要
====================================================================================================================================
アップグレード  1 パッケージ

ダウンロードサイズの合計: 1.2 G

~(中略)~

ok: run: redis: (pid 1602) 456972s
ok: run: redis-exporter: (pid 832200) 0s
ok: run: sidekiq: (pid 832207) 1s

     _______ __  __          __
    / ____(_) /_/ /   ____ _/ /_
   / / __/ / __/ /   / __ `/ __ \
  / /_/ / / /_/ /___/ /_/ / /_/ /
  \____/_/\__/_____/\__,_/_.___/


Upgrade complete! If your GitLab server is misbehaving try running
  sudo gitlab-ctl restart
before anything else.
If you need to roll back to the previous version you can use the database
backup made during the upgrade (scroll up for the filename).


  検証             : gitlab-ee-15.4.4-ee.0.el8.x86_64                                                                           1/2
  検証             : gitlab-ee-15.3.4-ee.0.el8.x86_64                                                                           2/2

アップグレード済み:
  gitlab-ee-15.4.4-ee.0.el8.x86_64

完了しました!

なお、バージョンアップ対象のGitLabのバージョンによっては、本体以外にも関連するパッケージのアップグレードや追加インストールが発生する。以下は、15.1.2 -> 15.3.4へバージョンアップした際のdnfの実行結果となり、本体以外にさまざまなパッケージが追加インストールされていることがわかる。

# dnf update gitlab-ee-15.3.4-ee.0.el8.x86_64
gitlab_gitlab-ee                                648  B/s | 862  B     00:01
gitlab_gitlab-ee-source                         316  B/s | 862  B     00:02
依存関係が解決しました。
================================================================================
 パッケージ                   Arch   バージョン          リポジトリー     サイズ
================================================================================
アップグレード:
 gitlab-ee                    x86_64 15.3.4-ee.0.el8     gitlab_gitlab-ee 1.1 G
 glibc                        x86_64 2.28-189.5.el8_6    baseos           2.2 M
 glibc-all-langpacks          x86_64 2.28-189.5.el8_6    baseos            25 M
 glibc-common                 x86_64 2.28-189.5.el8_6    baseos           1.3 M
依存関係のインストール:
 dwz                          x86_64 0.12-10.el8         appstream        108 k
 efi-srpm-macros              noarch 3-3.el8             appstream         21 k
 ghc-srpm-macros              noarch 1.4.2-7.el8         appstream        9.2 k
 glibc-gconv-extra            x86_64 2.28-189.5.el8_6    baseos           1.5 M

~(中略)~

 unzip                        x86_64 6.0-46.el8          baseos           195 k
 zip                          x86_64 3.0-23.el8          baseos           270 k
弱い依存関係のインストール:
 perl-Encode-Locale           noarch 1.05-10.module_el8.5.0+2812+ed912d05
                                                         appstream         20 k

トランザクションの概要
================================================================================
インストール    117 パッケージ
アップグレード    4 パッケージ

ダウンロードサイズの合計: 1.2 G

~(以下略)~

4. バージョンアップ後の確認

バージョンアップ後にGitLabにログインして、Adminの画面からバージョン確認をしてみよう。問題なくバージョンアップされていれば作業は完了となる。

以上で、GitLabをバージョンアップする手順は完了となる。

2022年11月5日土曜日

GitLabバックアップ・リストア手順

自宅環境のGitLabでは、自分が作成したAnsibleのPlaybookやPythonスクリプトだけだなく、各種技術情報などをWikiで管理するようにしており、GitLabで保存されているデータの重要性が高くなってきた。

そのため、万が一自宅環境のディスク障害などに備え、バックアップを取得することにした。幸い、GitLabではバックアップ・リストアをするためのコマンドが標準で用意されている。

今回は、GitLabの機能を用いてバックアップ・リストアを行う手順を記載する。

環境

GitLabのOSはAlmaLinuxを用いる。ただし、Red Hat系のディストリビューションであるCentOSやRocky Linuxなどでも同様の手順で対応できると想定する。

  • OS : AlmaLinux 8.5
  • GitLab : 15.3.4

また、本記事では同一サーバに対してリストアすることを想定するが、バックアップファイルを用いて別のサーバに対してリストアすることもできるようだ。その手順については、別途検証した際に公開することにしたい。

バックアップ

1. `バックアップ取得

GitLabのバックアップは、gitlab-rake gitlab:backup:createコマンドを実行するだけで完了する。本コマンドは特にGitLabのサービス停止などは不要となる。

Backup [バックアップ名] is done.と表示されれば問題なくバックアップは完了となる。

# gitlab-rake gitlab:backup:create
2022-07-29 21:24:15 +0900 -- Dumping database ...
Dumping PostgreSQL database gitlabhq_production ... [DONE]
2022-07-29 21:24:19 +0900 -- Dumping database ... done
2022-07-29 21:24:19 +0900 -- Dumping repositories ...
{"command":"create","gl_project_path":"gitlab-instance-870ba0ef.wiki","level":"info","msg":"started create","relative_path":"@groups/d4/73/d4735e3a265e16eee03f59718b9b5d03019c07d8b6c51f90da3a666eec13ab35.wiki.git","storage_name":"default","time":"2022-07-29T12:24:19.686Z"}

~(中略)~

2022-07-29 21:24:20 +0900 -- Deleting tar staging files ... done
2022-07-29 21:24:20 +0900 -- Deleting backups/tmp ...
2022-07-29 21:24:20 +0900 -- Deleting backups/tmp ... done
2022-07-29 21:24:20 +0900 -- Warning: Your gitlab.rb and gitlab-secrets.json files contain sensitive data
and are not included in this backup. You will need these files to restore a backup.
Please back them up manually.
2022-07-29 21:24:20 +0900 -- Backup 1659097455_2022_07_29_15.1.2-ee is done.

2. バックアップファイルの確認

バックアップファイルが/var/opt/gitlab/backupsに生成されていることを確認する。バックアップファイルは[時間]_[月]_[日]_[バージョン]_gitlab_backup.tarという名前で生成される。

# ls -l /var/opt/gitlab/backups
-rw------- 1 git git 25518080 10月 29 01:30 1666974616_2022_10_29_15.3.4-ee_gitlab_backup.tar

3. 設定ファイルのバックアップ

バックアップファイルにはGitLabの設定ファイルは含まれないため、以下ファイルを任意の場所にバックアップしておく。

  • /etc/gitlab/gitlab.rb
  • /etc/gitlab/gitlab-secrets.json

容量はそこまで大きくないことから、tarで固めてディレクトリ全体をバックアップしても問題ない。

# tar zcvf gitlab_config_20221029.tgz /etc/gitlab
tar: メンバ名から先頭の `/' を取り除きます
/etc/gitlab/
/etc/gitlab/gitlab-secrets.json
/etc/gitlab/trusted-certs/
/etc/gitlab/trusted-certs/public.crt
/etc/gitlab/trusted-certs/6b8ba5bf.0
/etc/gitlab/gitlab.rb

以上でGitLabのバックアップは完了となる。

GitLabリストア手順

1. 前提条件確認

前提として、バックアップファイルは/var/opt/gitlab/backupsに配置する。また、バックアップファイルとリストア先のGitLabのバージョンは一致させることが必要となる。

今回は以下の通り、バックアップファイルとリストア先のGitLabのバージョンは15.3.4で一致していることを確認した。

# ls -l /var/opt/gitlab/backups
-rw------- 1 git git 25518080 10月 29 01:30 1666974616_2022_10_29_15.3.4-ee_gitlab_backup.tar

# rpm -qa | grep gitlab
gitlab-ee-15.3.4-ee.0.el8.x86_64

また、今回はリストアされたことを確認できるよう、tuser001/linux_configというプロジェクトを事前に削除し、リストアすることで復旧することを確認する。

2. サービス停止

GitLabを構成するサービスのうち、pumasidekiqを停止する。

# gitlab-ctl status
run: alertmanager: (pid 3127640) 1418103s; run: log: (pid 1528) 3140631s
run: gitaly: (pid 3127689) 1418101s; run: log: (pid 1504) 3140631s
run: gitlab-exporter: (pid 3127638) 1418103s; run: log: (pid 1526) 3140631s

~(中略)~

run: sidekiq: (pid 3127807) 1418099s; run: log: (pid 1496) 3140631s
# gitlab-ctl stop puma
ok: down: puma: 0s, normally up
# gitlab-ctl stop sidekiq
ok: down: sidekiq: 0s, normally up
# gitlab-ctl status
run: alertmanager: (pid 3127640) 1418465s; run: log: (pid 1528) 3140993s
run: gitaly: (pid 3127689) 1418463s; run: log: (pid 1504) 3140993s
run: gitlab-exporter: (pid 3127638) 1418465s; run: log: (pid 1526) 3140993s

~(中略)~

down: puma: 17s, normally up; run: log: (pid 1495) 3140993s
~(中略)~
down: sidekiq: 8s, normally up; run: log: (pid 1496) 3140993s

3. リストア

リストアは、gitlab-rake gitlab:backup:restoreを利用する。この際にバックアップファイル名を引数として指定するが、ファイル名の拡張子(.tar)は不要となるので注意する。途中2回ほど継続しても問題ないか確認を求められるので、yesを選択して先に進めよう。

Restore task is done.と表示されれば問題なくリストアは完了となる。

# gitlab-rake gitlab:backup:restore BACKUP=1666974616_2022_10_29_15.3.4-ee
2022-08-05 22:53:54 +0900 -- Unpacking backup ... 
2022-08-05 22:53:54 +0900 -- Unpacking backup ... done
2022-08-05 22:53:54 +0900 -- Restoring database ... 
2022-08-05 22:53:54 +0900 -- Be sure to stop Puma, Sidekiq, and any other process that
connects to the database before proceeding. For Omnibus
installs, see the following link for more information:
https://docs.gitlab.com/ee/raketasks/backup_restore.html#restore-for-omnibus-gitlab-installations

Before restoring the database, we will remove all existing
tables to avoid future upgrade problems. Be aware that if you have
custom tables in the GitLab database these tables and all data will be
removed.

Do you want to continue (yes/no)? yes ★yesを入力
Removing all tables. Press `Ctrl-C` within 5 seconds to abort
2022-08-05 13:54:12 UTC -- Cleaning the database ... 
2022-08-05 13:54:14 UTC -- done
Restoring PostgreSQL database gitlabhq_production ... ERROR:  must be owner of extension pg_trgm
ERROR:  must be owner of extension btree_gist
ERROR:  must be owner of extension btree_gist
ERROR:  must be owner of extension pg_trgm

~(中略)~

2022-08-05 22:54:23 +0900 -- Restoring terraform states ... done
2022-08-05 22:54:23 +0900 -- Restoring packages ...
2022-08-05 22:54:23 +0900 -- Restoring packages ... done
This task will now rebuild the authorized_keys file.
You will lose any data stored in the authorized_keys file.
Do you want to continue (yes/no)? yes ★yesを入力

2022-08-05 22:54:49 +0900 -- Deleting tar staging files ...
2022-08-05 22:54:49 +0900 -- Cleaning up /var/opt/gitlab/backups/backup_information.yml

~(中略)~

2022-08-05 22:54:49 +0900 -- Warning: Your gitlab.rb and gitlab-secrets.json files contain sensitive data
and are not included in this backup. You will need to restore these files manually.
2022-08-05 22:54:49 +0900 -- Restore task is done.

4. 設定ファイルを再配置

事前にバックアップしていた以下ファイルを/etc/gitlabに再配置する。

  • /etc/gitlab/gitlab.rb
  • /etc/gitlab/gitlab-secrets.json

5. リストア後の再設定とサービス起動

以下コマンドを実行し、GitLabの再設定、サービス再起動を行う。

# gitlab-ctl reconfigure
# gitlab-ctl restart

再起動後にサービスがすべて起動していることを確認しよう。すべてのサービスがrunと表示されれば問題ない。

# gitlab-ctl status
run: alertmanager: (pid 1556185) 70s; run: log: (pid 1528) 3141350s
run: gitaly: (pid 3127689) 1418820s, got TERM; run: log: (pid 1504) 3141350s
run: gitlab-exporter: (pid 1556211) 38s; run: log: (pid 1526) 3141350s

~(中略)~

run: sidekiq: (pid 1556320) 33s; run: log: (pid 1496) 3141350s

6. リストア後のGitLabの健全性チェック

最後にリストア後のGitLabの健全性チェックをgitlab-rake gitlab:checkコマンドで実施する。

各種チェックが実行されるが、すべてOKとなっていれば問題ない。

# gitlab-rake gitlab:check SANITIZE=true
Checking GitLab subtasks ...

Checking GitLab Shell ...

GitLab Shell: ... GitLab Shell version >= 14.10.0 ? ... OK (14.10.0)
Running /opt/gitlab/embedded/service/gitlab-shell/bin/check
Internal API available: OK
Redis available via internal API: OK
gitlab-shell self-check successful

~(中略)~

Checking GitLab App ... Finished

Checking GitLab subtasks ... Finished

7. 削除したデータ復旧の確認

リストア後、事前に削除したtuser001/linux_configのプロジェクトが復旧できていることが確認できた。

以上でGitLabのリストアは完了となる。

参考

人気の投稿