CodeReady Containers(CRC)をリモート接続してシングルノードのOpenShiftとして利用する

Red Hatでソリューションアーキテクトをしている田中司恩です。前回記事の続きのCodeReady Containers(以下、CRC)に関する記事となります。

CRCのインストールから実用的な利用方法については杉村さんの記事で詳細に書かれていますので、そちらを参照してください。

rheb.hatenablog.com

この記事では杉村さんの記事でも利用されている「CRCのリモート接続」について掘り下げて解説いたします。

CRCのリモート接続とは

CRC v.1.15からひっそりとサポートされている構成方法です。v.1.15からドキュメントに使用方法が記載されています。

CRCはローカル端末上での実行を前提としてますので、本来はCRCを実行している端末上でしかウェブコンソールとCLIによるOpenShiftクラスターへの接続はできません。そこで追加のセットアップを行うことでLinux版のみ、リモートサーバー上に配置したCRCへアクセスすることがサポートされるようになりました。具体的にはCRCを実行するLinux上にhaproxyでロードバランサー機能を立ち上げ、リモートからのアクセスをCRC仮想マシンへ転送する仕組みとなります。また、CRCでは「crc.testing」と「apps-crc.testing」の2つの事前に定義済みのドメイン名が使用されます。リモート接続するためには外部からこれらの名前解決が行えるようにする設定も追加で必要となります。リモート接続の設定を行うことで外部の端末からウェブコンソールやCLIを使ってOpenShiftクラスターへのアクセスが可能となります。

CRCをリモート接続で構成することによりリソースに余裕のある検証・開発用のLinux端末などをOpenShiftの実行環境として利用できるので、手元のローカル端末のリソース消費を心配する必要はありません。

CRCのデフォルト接続構成
CRCのデフォルト接続構成

CRCのリモート接続構成
CRCのリモート接続構成

!!! 注意 !!!

CRCのリモート接続はローカルネットワーク内での使用を強く推奨しています。またCRCはシングルユーザーでの利用を前提としており複数ユーザーでのサーバー用途として利用することはできません。マルチユーザーでの利用はフル機能版のOpenShiftをご利用ください。

CRCのDNSのアーキテクチャー

リモート接続の説明に先立って、CRCのDNSアーキテクチャーについて解説します。 CRCで構成されているDNSのアーキテクチャーは下記の図のようになります。

※ アーキテクチャー図はCRCの挙動から判断し、独自に書き起こしたものです。公式なものではありません。

※ 本記事ではLinux版のみ対象としています。macOS、Windows版は同様の仕組みですが詳細は異なります

CRCのDNSアーキテクチャー
CRCのDNSアーキテクチャー図

ここからはCRC VMとCRCホストの設定内容を確認していきます。

CRC VMの内部動作確認

CRC VMへssh接続して確認します

$ ssh -i ~/.crc/machines/crc/id_ecdsa core@192.168.130.11
Red Hat Enterprise Linux CoreOS 47.83.202102090044-0
  Part of OpenShift 4.7, RHCOS is a Kubernetes native operating system
  managed by the Machine Config Operator (`clusteroperator/machine-config`).

WARNING: Direct SSH access to machines is not recommended; instead,
make configuration changes via `machineconfig` objects:
  https://docs.openshift.com/container-platform/4.7/architecture/architecture-rhcos.html

[core@crc-l6qvn-master-0 ~]$

CRC VMの中ではpodmanでdnsmasq(DNSサーバー)が起動されています。

[core@crc-l6qvn-master-0 ~]$ sudo podman ps -a
CONTAINER ID  IMAGE                               COMMAND  CREATED         STATUS             PORTS               NAMES
5f7915d883be  quay.io/crcont/gvisor-tap-vsock:v4           2 weeks ago     Up 31 minutes ago                      gvisor-tap-vsock
6e00d97c9ac9  quay.io/crcont/dnsmasq:latest                31 minutes ago  Up 31 minutes ago  0.0.0.0:53->53/udp  dnsmasq

使用されているdnsmaq.confの中身を確認(podman inspectでマウントしている実態ファイルのパスを確認済み)

[core@crc-l6qvn-master-0 ~]$ sudo cat /var/srv/dnsmasq.conf
user=root
port= 53
bind-interfaces
expand-hosts
log-queries
local=/crc.testing/
domain=crc.testing
address=/apps-crc.testing/192.168.130.11
address=/api.crc.testing/192.168.130.11
address=/api-int.crc.testing/192.168.130.11
address=/crc-l6qvn-master-0.crc.testing/192.168.126.11

CRCで使用しているDNSの名前解決は、ホストからこのpodmanで起動しているdnsmasq宛に問い合わせる構成となっています。ホストではNetwork Managerのdnsmasqプラグインを使用して特定のDNSの問い合わせをCRC VMへ転送するように設定されています。

CRC実行ホストのNetwork Manager設定

CRCセットアップ後のホスト上のdnsmasqのCRC用インスタンスは下記のようになっています。

$ cat /etc/NetworkManager/dnsmasq.d/crc.conf
server=/apps-crc.testing/192.168.130.11
server=/crc.testing/192.168.130.11

なお、このcrc.confはcrc setupおよびcrc start時にチェックされ、設定を変更することができません(下記はcrc start実行時のログ)

$ crc start
〜省略〜
INFO Checking if /etc/NetworkManager/conf.d/crc-nm-dnsmasq.conf exists
INFO Checking if /etc/NetworkManager/dnsmasq.d/crc.conf exists

設定を変更した場合はCRCが起動できなくなります

$ crc start
INFO Checking if running as non-root
INFO Checking if podman remote executable is cached
INFO Checking if admin-helper executable is cached
INFO Checking minimum RAM requirements
INFO Checking if Virtualization is enabled
INFO Checking if KVM is enabled
INFO Checking if libvirt is installed
INFO Checking if user is part of libvirt group
INFO Checking if libvirt daemon is running
INFO Checking if a supported libvirt version is installed
INFO Checking if crc-driver-libvirt is installed
INFO Checking if systemd-networkd is running
INFO Checking if NetworkManager is installed
INFO Checking if NetworkManager service is running
INFO Checking if /etc/NetworkManager/conf.d/crc-nm-dnsmasq.conf exists
INFO Checking if /etc/NetworkManager/dnsmasq.d/crc.conf exists
WARN Preflight checks failed during `crc start`, please try to run `crc setup` first in case you haven't done so yet
File has unexpected content: /etc/NetworkManager/dnsmasq.d/crc.conf

CRCホストの/etc/hosts

CRCセットアップ後、CRCを実行するホストの/etc/hostsには設定が追加されます

$ sudo cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.130.11 api.crc.testing console-openshift-console.apps-crc.testing default-route-openshift-image-registry.apps-crc.testing oauth-openshift.apps-crc.testing

このようにCRCの名前解決の仕組みは複雑に構成されています。リモート接続を行う場合はこれらの仕組みを維持しつつ、外部からの接続を受け付けるようにする必要があります。

リモート接続の構成方法

ここからはリモート接続の実際の設定方法を紹介します。やることは大きく2つです。

  • CRCを立ち上げるサーバー側での設定
  • CRCへ接続するクライアント側の設定

さらに、サーバー側の設定はLoadBalancer(haproxy)とDNS(dnsmasq)の設定をそれぞれ行います。

リモート接続後の構成は下記の図の通りです。 (リモートクライアントは後述するmacOSを想定して構成図になっています)

CRCのリモート接続構成
CRCのリモート接続構成

※ 以降の解説のサーバー環境は、RHEL8.3をサーバー(GUI使用)でセットアップした環境を想定しています。

サーバー側の設定:haproxy

下記はドキュメント(5.3. Setting up CodeReady Containers on a remote server)に載っている方法です。

haproxyパッケージとその他のユーティリティ をインストールします。

$ sudo dnf install haproxy policycoreutils-python-utils jq

ファイアウォールを変更して、クラスターとの通信を許可します。

$ sudo systemctl start firewalld
$ sudo firewall-cmd --add-port=80/tcp --permanent
$ sudo firewall-cmd --add-port=6443/tcp --permanent
$ sudo firewall-cmd --add-port=443/tcp --permanent
$ sudo systemctl restart firewalld

SELinuxのためのTCPポート6443のリッスンを許可します。

$ sudo semanage port -a -t http_port_t -p tcp 6443

デフォルトのhaproxyコンフィグのバックアップを作成します。

$ sudo cp /etc/haproxy/haproxy.cfg{,.bak}

haproxyのコンフィグを作成します。コンフィグ内の$CRC_IPにはCRCのIPアドレス(デフォルト:192.168.130.11)が記載されます。

$ export CRC_IP=$(crc ip)
$ sudo tee /etc/haproxy/haproxy.cfg &>/dev/null <<EOF
global
    debug

defaults
    log global
    mode http
    timeout connect 5000
    timeout client 500000
    timeout server 500000

frontend apps
    bind 0.0.0.0:80
    option tcplog
    mode tcp
    default_backend apps

frontend apps_ssl
    bind 0.0.0.0:443
    option tcplog
    mode tcp
    default_backend apps_ssl

backend apps
    mode tcp
    balance roundrobin
    server webserver1 $CRC_IP:80 check

backend apps_ssl
    mode tcp
    balance roundrobin
    option ssl-hello-chk
    server webserver1 $CRC_IP:443 check

frontend api
    bind 0.0.0.0:6443
    option tcplog
    mode tcp
    default_backend api

backend api
    mode tcp
    balance roundrobin
    option ssl-hello-chk
    server webserver1 $CRC_IP:6443 check
EOF

haproxyのサービス登録とサービスの起動を行います

$ sudo systemctl enable haproxy
$ sudo systemctl start haproxy

サーバー側の設定:dnsmasq

ドキュメントではサーバー側の設定はhaproxyについてしかありません。実際にクライアント側からアクセスする場合はCRC用のDNSによる名前解決が必要です。CRCでは*.apps.crc.testingのワイルドカードレコードの名前解決が必要です。そのため接続元のクライアントのhostsファイルへの単純な追記などでは対応が大変です。クライアント自身にDNSサーバーを立てるまたは外部のDNSサーバーを利用する、などの方法がありますが本記事ではよりシンプルに、CRCサーバーにクライアント向けのDNSサーバーを兼用する設定方法を紹介します。

作業ステップは下記の通りです。

  1. dnsmasqのインストール
  2. firewallの設定変更
  3. dnsmasq.confの設定
  4. dnsmasqサービスの登録、起動
  5. dnsmasqの動作確認

1. dnsmasqのインストール

dnfでdnsmasqをインストールします

$ sudo dnf install dnsmasq -y

2. firewallの設定変更

DNSで使用するポートの追加、反映を行います

$ sudo firewall-cmd --add-port=53/tcp --permanent
$ sudo firewall-cmd --add-port=53/udp --permanent
$ sudo firewall-cmd --reload

3. dnsmasq.confの設定

デフォルトのdnsmasq.confをバックアップし、新規に作成します。 下記の192.168.1.25はご自身のCRCサーバーのIPアドレスに置き換えてください。

$ sudo mv /etc/dnsmasq.conf{,.bak}
$ sudo tee /etc/dnsmasq.conf &>/dev/null <<EOF
user=dnsmasq
group=dnsmasq
no-hosts
bind-interfaces
listen-address=192.168.1.25
address=/testing/192.168.1.25
EOF
  • no-hosts:CRCを実行するホストの/etc/hostsにCRC用設定が追記されるため、そのアドレスを応答するのを防ぐための設定
  • bind-interfaces:Network Managerのdnsmasqプラグインによってバインドされているアドレスを避けてdnsmasqを起動するために設定
  • listen-address:クライアントからのDNS問い合わせを待ち受けるIPアドレスを指定
  • address=/testing/ :*.testingのワイルドカードアドレスを解決するIPアドレスを指定

4. dnsmasqサービスの登録、起動

systemctlコマンドでサービスを登録、起動します

$ sudo systemctl enable dnsmasq.service
$ sudo systemctl start dnsmasq.service

dnsmasqサービスの起動後、サービスが起動していること、指定したIPアドレスでtcp/udp port:53がリッスンしていることを確認します。

$ sudo systemctl status dnsmasq.service |grep Active:
   Active: active (running) since Fri 2021-03-19 01:06:40 JST; 15min ago
$ sudo ss -tlnup | grep 192.168.1.25:53
udp     UNCONN   0        0                                192.168.1.25:53                  0.0.0.0:*          users:(("dnsmasq",pid=54226,fd=4))
tcp     LISTEN   0        32                               192.168.1.25:53                  0.0.0.0:*          users:(("dnsmasq",pid=54226,fd=5))

(2021/3/29、追記)

CRC実行ホストを再起動後、dnsmasqのネットワークバインドがうまくいかない場合があります。dnsmasqサービスの起動をネットワーク起動後に遅延させることで回避できます。

systemctl edit サービス名を実行

 $ sudo systemctl edit dnsmasq

エディター画面が開いたら下記を記載してviの手順でファイルを保存し閉じる

[Unit]
After=network-online.target

追記した内容は下記のファイルに保存されています

$ cat /etc/systemd/system/dnsmasq.service.d/override.conf
[Unit]
After=network-online.target

参考リンク

access.redhat.com

5. dnsmasqの動作確認

dnsmasqが無事起動したら、あとはクライアントからapi.crc.testingや任意のワイルドカードアドレスaaa.apps-crc.testingなどが名前解決できればOKです。

(クライアントから実行)

$ dig @192.168.1.25 api.crc.testing |grep -A 1 "ANSWER SECTION"
;; ANSWER SECTION:
api.crc.testing.    0   IN  A   192.168.1.25

$ dig @192.168.1.25 aaa.apps-crc.testing |grep -A 1 "ANSWER SECTION"
;; ANSWER SECTION:
aaa.apps-crc.testing.   0   IN  A   192.168.1.25

クライアント側の設定

クライアント側の設定として、LinuxとmacOS用の設定方法を紹介します。

Linux用設定

ドキュメントではLinuxクライアントから接続する前提での方法が記載されています。

サーバー側と同様に、dnsmasqを利用してクライアント自身にDNSサーバーを構成する方法となります。

1. dnsmasqのインストール

$ sudo dnf install dnsmasq -y

2. NetworkManagerでdnsmasqによるDNS名前解決の使用を有効にします

$ sudo tee /etc/NetworkManager/conf.d/use-dnsmasq.conf &>/dev/null <<EOF
[main]
dns=dnsmasq
EOF

3. CRC用のDNSエントリを設定に追加します。

$ sudo tee /etc/NetworkManager/dnsmasq.d/external-crc.conf &>/dev/null <<EOF
address=/apps-crc.testing/192.168.1.25
address=/api.crc.testing/192.168.1.25
EOF

4. NetworkManagerサービスをリロードします。

$ sudo systemctl reload NetworkManager

macOS用の設定

macOSではDNSサーバーを立てることなく、特定のドメイン名だけを指定したDNSサーバーを使って名前解決することができます。 /etc/resolver を使用します。設定方法は簡単で/etc/resolver配下にドメイン名のファイルを作成し、中にnameserver IPアドレスの記入を行うだけです。

$ sudo tee /etc/resolver/testing &>/dev/null <<EOF
nameserver 192.168.1.25
EOF

設定を行なった後、CRCサーバーをDNSサーバーとして指定せずにdigコマンドを実行しても正しく名前解決できません。しかしながらpingでは/etc/resolverの設定に従って名前解決が行われます。ご注意ください。

CRCにリモート接続してみる

リモートの端末からブラウザでCRCの管理コンソールにアクセスします。

接続先URL:https://console-openshift-console.apps-crc.testing/

.testingドメインで問題なくコンソールが表示できればCRCのリモート接続の完成です。あとはお好きなようにOpenShift 4の環境として利用できます。

CRCのコンソール画面
CRCのコンソール画面

まとめ

CRCをリモートサーバー上で実行し、リモートクライアントから接続して利用する方法についてご紹介しました。 リモート接続の構成に当たってはDNSの名前解決の理解が必要なため、CRCのDNSのアーキテクチャーについても合わせてご紹介しました。 CRCは簡単にセットアップできるシングルノードのOpenShift 4そのものであり、比較的簡単に自由に使えるOpenShiftの環境を手に入れる方法の1つです。CRCのリモート接続でローカル端末のリソース問題を解消して開発やテスト環境でのOpenShift 4の利用がさらに便利になると思います。 次回記事ではCRCのセットアップや利用時におけるTips、注意点などについてご紹介いたします。

(2021/3/30、追記) 次回記事をアップしました

rheb.hatenablog.com

* 各記事は著者の見解によるものでありその所属組織を代表する公式なものではありません。その内容については非公式見解を含みます。