Container Linuxの後継となる新たなコンテナ向けOS「Fedora CoreOS」

2018年2月、Red Hatがコンテナ向けのLinuxディストリビューションを開発するCoreOSを買収し、その後CoreOSが手がける「Container Linux」がFedoraと統合されることが発表された。そして2019年7月、その成果物となる「Fedora Core OS」がリリースされた。記事執筆時点ではプレビュー段階という位置付けだが、その後は本番環境での利用も推奨される。本記事ではこのFedora Core OSについて導入方法や設定・管理方法、コンテナクラスタの構築などを紹介する。

コンテナ向けOSとは

昨今では、Linuxマシンで構成されるクラスタ上でコンテナ技術を使ってアプリケーションを構築する手法が広く普及している。こういったコンテナクラスタ技術として有名なものの1つにKubernetesがある。Kubernetesはコンテナクラスタを構築・管理するためのソフトウェアであり、これを導入することで最低限のコンテナクラスタの管理は完結するが、一方でKubernetes自体を動作させるハードウェアやOSの選定や管理については別途行わなければならない。今回紹介するFedora Core OSは、こういったコンテナクラスタでの利用に特化したOS(Linuxディストリビューション)だ。

KubernetesはUbuntuやDebian、CentOS、Red Hat Enterprise Linux(RHEL)などさまざまなLinuxディストリビューション上で動作する。しかし、コンテナクラスタを構築する場合、そのクラスタ上で実行されるソフトウェアは基本的にコンテナ内で動作する。そのため、OS上には必要最小限のソフトウェアさえ準備されていれば良く、そのため汎用OSで提供されている機能のうち一部は必要としない。そういったコンテナクラスタにおいて不要な機能を省略し、コンパクトにしたものがコンテナ向けOSと言われるものだ。

こうしたコンテナ向けOSのなかでも著名なのが、CoreOS社が提供していた「Container Linux」と呼ばれるLinuxディストリビューションだ。なお、Container Linuxは以前はCoreOSという名称で提供されていたが、2016年に名称をContainer Linuxに変更している。

しかし、このContainer Linuxを開発するCoreOS社は2018年2月にRed Hat Enterprise Linuxなどの開発を手がける米Red Hat(現在は米IBMの傘下)に買収された。今回紹介するFedora Core OSは、Linuxディストリビューションの「Fedora」を開発するFedora Projectが、このCoreOS/Container Linuxの技術をベースに開発・提供するLinuxディストリビューションとなる。

FedoraとRed Hat Enterprise Linuxの関連性とFedora Core OSの歴史

Fedora ProjectはRed Hat傘下のプロジェクトであり、Red Hat Enterprise Linuxなどで使われる技術を先行して実装・検証することで知られている。また、Red HatもRed Hat Enterprise Linuxブランドでコンテナ向けのOSをリリースしている。そのためブランド名がやや複雑になっているが、これらをまとめたものが図1だ。

図1 Fedora CoreOSと関連プロダクトの関係性

Red Hatによるコンテナ向けOSへの取り組みの1つに、2014年に発表された「Project Atomic」がある。Project Atomicは「小さなフットプリント」を特徴とするLinuxディストリビューションを開発するプロジェクトで、Red HatおよびFedora Project、そしてRHEL互換のディストリビューションを開発・提供するRed Hat傘下のCentOS Projectが参画していた。

Project Atomicではコンテナ向けOSを提供するためのコア技術を開発し、その成果をRHELおよびFedora、CentOSのそれぞれが取り入れて「RHEL Atomic Host」や「Fedora Atoic Host」、「CentOS Atomic Host」という形でリリースするという形で運営されていた。たとえば、RHELでは2014年にRHEL 7をベースとした「Red Hat Enterprise Linux 7 Atomic Host」を発表している。また、2014年12月にリリースされたFedora 21ではProject Atomicの成果を取り入れた「Cloud」エディションがリリースされた。Fedoraにおいて当初「Atomic Host」はCloudエディションの一部という位置付けだったが、2016年11月にリリースされたFedora 25以降ではCloudエディションが「Atomic Host」エディションに改名されている。

このように着実に成果物をリリースしていったProject Atomicだが、大きな転機となったのはRed HatによるCoreOSの買収だろう。CoreOSのContainer LinuxはAtomic Hostと技術的な類似点があり、またカバーしようとしている分野も被っていた。そのため、Red Hatはこれらプロジェクトを統合させることに決めたようだ。その結果、最終的にProject Atomicという名称は消え、Red Hatの製品やサービスとの統合が進められた「Red Hat Enterprise Linux CoreOS」(RHEL CoreOS)と、Project Atomicの後継となる「Fedora CoreOS」が生まれることとなった。

これによって生まれたRHEL CoreOSとFedora CoreOSの関係はRHELとFedoraとの関係とほぼ同じで、Fedora CoreOSが技術を先行して実装し、そこで検証された結果を元にその技術がRHEL CoreOSに導入される、という流れになっているという。また、RHEL CoreOSではクラスタ管理に向けたの商用サービスなどが提供されるが、Fedora CoreOSではそれらは利用できない。

2019年5月にリリースされた「Fedora 30」ではこれらを踏まえ、Fedora 29以前の「Atomic Host」エディションが新たに「Fedora CoreOS」というエディションとなり、その後2019年10月にリリースされた「Fedora 31」でも同様の形態でリリースが行われている。ただし、本記事執筆時点でもFedora CoreOSはまだ「プレビュー」という段階である点には注意したい。

なお、Container Linuxについては少なくとも2019年内のサポート継続が表明されている。最終的にはFedora CoreOSがContainer Linuxの後継OSとなるようだが、現時点ではContainer Linux自体の開発もFedora CoreOSと並行して進められており、既存のContainer Linuxユーザーに対しては緩やかな移行が進められるよう配慮するという。

Fedora CoreOSの特徴

Fedora CoreOSはFedoraをベースとしているものの、コンテナクラスタの構成に特化しており、Fedoraとは多くの点で違いがある。大きな違いとしては、以下の点がある。

  • コンテナ上でアプリケーションを動かすための必要最小限のソフトウェアしか搭載しない
  • パッケージマネージャを搭載しない
  • /usrディレクトリ以下は原則として書き込み不可
  • 初回起動時に「Ignition」という設定ツールが実行され、自動的に各種設定を行える
  • OSのアップデートは自動的に実行される
  • OSアップデート時には/usr以下のディレクトリツリーが丸ごと置き換えられる

特に大きな違いは、ファイルシステムの変更に制約がある点だ。/usr以下を変更できず、パッケージマネージャによるソフトウェアのインストールにも対応しない。これによって脆弱性などの問題が発生した際にシステムへの影響を最小限に抑えることが期待できる。また、最小限のソフトウェアしか搭載しないことで、システムの起動やアップデートなどが高速になっている。

こうしたアーキテクチャは、「immutable infrastructure」と呼ばれる手法に影響を受けている。immutable infrastructureは、OS環境のセットアップ完了後の設定変更を原則として行わず、設定変更が必要になったらセットアップから再度実行するという考え方だ。immutable infrastructureでは、OS環境のセットアップを、設定ツールなどを利用して自動化し、それによってヒューマンエラーを防ぎつつ、管理の手間を削減する。昨今普及しているInfrastructure as a Service(IaaS)型のクラウドでは仮想サーバーの作成や削除が容易に行え、かつその作業も自動化できるため、immutable infrastructureとの相性が良いとされている。

Fedora CoreOSの特徴とContainer Linux(CoreOS)との相違点

Fedora CoreOSはContainer LinuxとProject Atomicを統合したものだが、基本的にはContainer Linuxがベースとなっている。ただし、一部の機能はContainer Linuxから変更されている。そのなかでも大きな違いとしては次のものがある。

  • OS自体のアップデートにはrpm-ostreeを使用する
  • ネットワーク管理にはNetworkManagerを使用する
  • Kubernetesといったオーケストレーションツールのサポートはデフォルトでは提供されない

また、かつてContainer Linuxではサーバーの初期設定のために「cloud-config」という技術が使われていたが、この技術はFedora CoreOSへの移行前に「Ignition」という機能に置き換えられており、Fedora CoreOSでも利用できない。

かつてContainer LinuxはCoreOSという名称だったため、「CoreOS」などのキーワードでWeb検索を行うと旧CoreOSやContainer Linuxに関する情報が多く見つかるが、こういった相違点からそれらはFedora CoreOSにはほとんど適用できない点には注意が必要だ。Container Linuxドキュメントに記載されている情報についても同様だ。

現時点で有用な情報源としてはFedora CoreOSの公式ドキュメントがあるが、まだ情報量が少ない。また、GitHubのCoreOSアカウント下のリポジトリでもいくつかのドキュメントが公開されているので、これらも参考になるだろう。

Fedora CoreOSのインストールと初期設定

続いては、Fedora CoreOSのインストール方法について解説していこう。Fedora CoreOSのインストール方法としては次の2通りがある。

  • インストール済ディスクイメージをインポートする
  • インストールしたいマシン上でインストーラを実行する

Amazon Web Services(AWS)やGoogle Cloud Platform(GCP)などのクラウドサービスや、OpenStackなどのクラウド基盤、QEMU、VMwareといった仮想マシン上でFedora CoreOSを利用したい場合は前者を、物理マシンや直接ディスクイメージを指定できないようなVPSなどでは後者を利用する。ディスクイメージやインストーラはFedoraのダウンロードページから入手が可能だ。また、AWS向けのAMIイメージも公開されている。イメージを利用したインストールに関してはドキュメントが用意されているので、こちらに従って作業を行えば良い。

インストーラからインストールを行う場合は、インストール先のマシンで「coreos-installer」というプログラムを実行する。Fedora CoreOSのダウンロードページの「Bare Metal & Virtualized」以下ではPXEおよびISO形式でブート可能なイメージが用意されており、これを使ってシステムを起動し、そこからcoreos-installerを起動すれば良い。

なお、ダウンロードページではISOイメージとして「Installer(ISO)」と「ISO」、PXEイメージでは「Installer(PXE)」と「PXE」の2つが用意されている(図2)。

図2 Fedora CoreOSのインストールイメージダウンロードページ

「Installer(ISO)」と「Installer(PXE)」はcoreos-installerのみが含まれる最小のシステムで、起動後に自動的にcoreos-installerが実行される。一方「ISO」と「PXE」はいわゆる「ライブ」システムで、起動後にcoreos-installerコマンドを手動で実行する必要があるという違いがあるが、どちらでもインストール作業自体は可能だ。

これらのイメージを使ってインストールしたいマシンを起動し、ブート画面(図3)でEnterキーを押すと「Installer(ISO)」版イメージの場合は自動的にcoreos-installerが実行され、「ISO」版イメージの場合はシェルが起動する。また、「ISO」版イメージの場合、シェルから「/usr/libexec/coreos-installer」コマンドを実行することでインストール作業を実行できる。

図3 Fedora CoreOSのブート画面

ただし、「Installer(ISO)」イメージでは自動的にcoreos-installerが実行されるものの、そのままではインストールに必要なパラメータの設定が行われていないためにインストールに失敗する。その場合、インストールに失敗した旨が表示された画面でEnterキーを押すと「emergency shell」を起動できる(図4)。

図4 インストーラの実行に失敗した場合、Enterキーを押すとemergency shellを起動できる

ネットワーク設定については、基本的にはDHCPでIPアドレスを自動取得することが想定されている。DHCPでIPアドレスを取得できない場合、IPコマンドで手動設定が可能だ。たとえばeth1というデバイスに対して「192.0.2.200/24」というIPアドレスを指定する場合、次のように実行すれば良い。

# ip addr add 192.0.2.200/24 dev eth1

インストールに必要なパラメータの指定

記事執筆時点で公開されているFedora CoreOSのイメージファイルでは、coreos-intallerの実行時に次の3つを指定する必要がある。

  • インストール先ストレージデバイス
  • 初期設定に使用するIgnition設定ファイルのURL
  • インストールに使用するイメージファイルのURL

まずインストール先ストレージデバイスだが、これは/devディレクトリ内のデバイスファイル名で指定する。たとえば「/dev/vda」にインストールする場合、「vda」と指定する。

「初期設定に使用するIgnition設定ファイルのURL」というのは、初期設定時に実行する処理内容が記述されたIgnition設定ファイルのURLだ。Ignitionでは設定内容を記述したファイルをHTTPでダウンロードして読み込む仕組みになっており、このURLをcoreos-installerコマンドの実行時に指定する。Ignition設定ファイルについて詳しくは後述する。

また、「インストールに使用するイメージファイル」だが、coreos-installerはネットワーク経由でルートファイルシステムを含むディスクイメージファイルをダウンロードする仕組みになっている。ここではそのダウンロードURLを指定する。Fedora CoreOSのダウンロードページ内にある「Raw(Raw.xz)」ファイルがこのイメージファイルだ。直接このダウンロードURLを指定しても良いが、別途ローカルネットワーク内のHTTPサーバー内にダウンロードし、そこから配信することをおすすめする。

これらパラメータはcoreos-installerコマンドのオプションで指定できるほか、カーネルコマンドラインパラメータや/tmpディレクトリ内の対応するファイル内にその値を格納することでも指定できる(表1)。

表1 coreos-installerで指定できるパラメータ
コマンドラインオプション 説明 カーネルパラメータでの指定 対応する設定ファイル
-d <デバイス> インストール先デバイス。たとえば/dev/vdaなら「vda」と指定する coreos.coreos.inst.install_dev=<デバイス> /tmp/selected_dev
-i <ignition設定ファイルのURL> 初期設定に使用する設定ファイルのURL coreos.inst.ignition_url=<URL> /tmp/ignition_url
-b <イメージファイルのURL> インストールに使用するイメージファイルのURL coreos.inst.image_url=<URL> /tmp/image_url

たとえば、インストール先として/dev/vdaを指定し、Ignitionの設定ファイルのURLが「http://192.0.2.100:8080/container/simple.json」、イメージファイルが「http://192.0.2.100:8080/container/fedora-coreos-31.20191127.1-metal.x86_64.raw.xz」の場合、次のようにcoreos-installerを実行すれば良い。

# /usr/libexec/coreos-installer -d vda -i http://192.0.2.100:8080/container/simple.json -b http://192.0.2.100:8080/container/fedora-coreos-31.20191127.1-metal.x86_64.raw.xz

ちなみにIgnition設定ファイルについては指定を省略できるが、その場合ログインに使用するパスワードの設定なども行われず、起動後にログインができない状態になるので実用的ではない。基本的には後述するようにIgnitionで初期設定を行うのが必須となる。

なお、記事執筆時点でFedora CoreOSのイメージに含まれているcoreos-installerは、GitHubの「coreos/coreos-installer」リポジトリlegacyブランチでメンテナンスされているもののようだ。masterブランチの物とは一部パラメータなどが異なるので注意して欲しい。

Ignitionの設定

Fedora CoreOSでは、「Ignition」というツールを利用してシステムの初期設定を行うようになっている。Ignitionは基本的にシステムの初回起動時にのみ実行され、ストレージ関連の各種設定やユーザーアカウント関連の設定、サービスのインストール、各種ファイルのダウンロードといった処理を行う。前述のとおりFedora CoreOSではimmutable infrastructureに従った管理を推奨しており、基本的にはここでサーバーの設定をすべて完結させるのが望ましい。

Ignitionの設定ファイルとfcctコマンド

IgnitionではJSON形式の設定ファイルを使用するが、JSON形式は人間に取っては必ずしも読みやすいものではない。そのため、YAML形式で設定を記述し、それを「Fedora CoreOS Config Transpiler(fcct)」というツール(コマンド)でJSON形式に変換して利用する。また、fcctではYAMLの構文チェックに加えて、不適切な設定内容を検出するエラーチェック機能機能も搭載されている。

fcctコマンドは、GitHub上にあるfcctのリリースページからダウンロードできる。記事執筆時点の最新版はv0.2.0だ。ソースコードのほかLinuxやWindows、macOS(darwin)向けのバイナリも公開されており、Linux版バイナリについてはx86_64版のほか64ビットARM(aarch64)版も用意されている。

これらバイナリは単純な実行ファイルとなっているので、たとえばLinux(x86_64)版を利用する場合、次のように適当なディレクトリにダウンロードし、名前を「fcct」に変更すれば良い。

$ wget https://github.com/coreos/fcct/releases/download/v0.2.0/fcct-x86_64-unknown-linux-gnu

$ mv fcct-x86_64-unknown-linux-gnu fcct
$ chmod +x fcct

バージョンは「--version」オプション、コマンドラインオプションは「--help」オプションを付けて実行することで確認できる。

$ ./fcct --version
Fedora CoreOS Config Transpiler v0.2.0

$ ./fcct --help
Usage of ./fcct:
  -input string
        read from input file instead of stdin
  -output string
        write to output file instead of stdout
  -pretty
        output formatted json
  -strict
        fail on any warning
  -version
        print the version and exit

fcctコマンドでは、「--input」オプションで入力ファイル(YAML形式ファイル)を、「--output」オプションで出力ファイル(JSON形式ファイル)を指定する。「--output」オプションを指定しなかった場合、標準出力へ出力が行われる。また、「--pretty」オプションを指定すると、人間が読みやすいようにインデントされたJSONデータが出力される。

設定できるパラメータ

Fedora CoreOSのIgnitionで設定できるパラメータは、Configuration Specification v1.0.0として公開されている。また、設定例も公開されている。

たとえば、「core」というユーザーを作成し、そのユーザーを使ってSSHでログインするための公開鍵を登録するには、次のような設定ファイル(ここでは「simple.yaml」というファイル名とした)を用意すれば良い。

variant: fcos
version: 1.0.0
passwd:
  users:
    - name: core
      ssh_authorized_keys:
        - ssh-rsa AAAAB... ←実際にはこの部分に使用する公開鍵を記述する

このファイルを引数として次のようにfcctコマンドを実行すると、「simple.json」というファイルが作成される。

$ ./fcct --input simple.yaml --pretty --output simple.json

ここで、出力されたsimple.jsonファイルは次のようになった。

{
  "ignition": {
    "config": {
      "replace": {
        "source": null,
        "verification": {}
      }
    },
    "security": {
      "tls": {}
    },
    "timeouts": {},
    "version": "3.0.0"
  },
  "passwd": {
    "users": [
      {
        "name": "core",
        "sshAuthorizedKeys": [
          "ssh-rsa AAAAB..."
        ]
      }
    ]
  },
  "storage": {},
  "systemd": {}

前述のとおり、このファイルはcoreos-installerの実行時に、そのマシンにHTTP経由でダウンロードされる。そのため、適当なHTTPサーバーなどを利用し、Fedora CoreOSをインストールするマシンからHTTPでアクセスできるようにしておこう。

なお、Ignitionでは現状ネットワークインターフェイスに固定IPアドレスを付与する設定項目が用意されていない点には注意したい。Fedora CoreOSのデフォルト設定ではDHCP経由でIPアドレスを取得するようになっているので、ネットワーク内にDHCPサーバーを用意しておく必要がある。

このファイルを用意したあと、インストール先マシンでcoreos-installerコマンドを実行してインストールを行うと、次のようにこのURLから設定ファイルがダウンロードされインストールされる旨が表示される(図5)。

図5 coreos-installerの実行例

インストール後に再起動を行うと、Fedora CoreOSが起動してIgnitionによる初期設定が実行され、その後システムが起動される。この設定ファイルではパスワードの設定は行っていないため、端末のコンソールから直接ログインすることはできないが、登録した公開鍵に対応する秘密鍵を使ってSSHでログインが行えるはずだ(図6)。

図6 SSH経由でのログイン例

この「core」ユーザーはデフォルトでsudoコマンドが利用できるよう設定されており、パスワード無しで、sudoコマンドでroot権限でのコマンド実行が可能になっている。ホスト名についてはランダムなものが自動的に付与される。

また、Ignitionの実行ログは次のようにjournalctlコマンドを実行することで確認できる。

$ journalctl -t ignition --all
-- Logs begin at Thu 2019-12-19 12:23:44 UTC, end at Thu 2019-12-19 13:02:08 UTC. --
12月 19 12:23:46 localhost ignition[638]: Ignition 2.0.1
12月 19 12:23:46 localhost ignition[638]: Stage: fetch
12月 19 12:23:46 localhost ignition[638]: reading system config file "/usr/lib/ignition/base.ign"
12月 19 12:23:46 localhost ignition[638]: parsing config with SHA512: ff6a5153be363997e4d5d3ea8cc4048373a457c48c4a5b134a08a>
12月 19 12:23:46 localhost ignition[638]: parsed url from cmdline: ""
12月 19 12:23:46 localhost ignition[638]: no config URL provided
12月 19 12:23:46 localhost ignition[638]: reading system config file "/usr/lib/ignition/user.ign"
12月 19 12:23:46 localhost ignition[638]: parsing config with SHA512: 366bff56d8ae5c26fab2fc17ff2b4eb950c976649e04ec2ff70d7>
12月 19 12:23:46 localhost ignition[638]: fetch: fetch complete
  
  

Fedora CoreOSのディレクトリ構成とシステムアップデート

Fedora CoreOSは一般的なLinuxとはやや異なるディレクトリ構成を採用しており、システム関連のファイルはすべて/usrディレクトリ以下に、設定ファイルは/etcディレクトリ以下に、それ以外のファイルはすべて/varディレクトリ以下に格納するという方針となっている。そして/binディレクトリや/libディレクトリ、/lib64ディレクトリ、/sbinディレクトリはそれぞれ/usrディレクトリ直下にある同名のディレクトリのシンボリックリンクとなっており、/homeディレクトリや/mntディレクトリ、/optディレクトリ、/srvディレクトリは、同様に/varディレクトリ直下の、同名ディレクトリのシンボリックリンクとなっている。/rootは/var/roothomeのシンボリックリンクだ。

また、Fedoraではyumコマンドやその後継となるdnfコマンドでパッケージのアップデートを行うことでシステムをアップデートできたが、Fedora CoreOSではこのようなパッケージマネージャが利用できない。その代わりとして、/usrディレクトリを丸ごと新しいものに置き換えることでシステムをアップデートする仕組みが導入されている。このアップデート処理は、「rpm-ostree」というツールで実行できるようになっている。

rpm-ostreeコマンドが実際にどのような動作を行うかについてはrpm-ostreeの公式ドキュメントを参照して欲しいが、基本的な管理については3つのサブコマンドだけで対応できる。1つめは、現在の状況を確認する「status」サブコマンドだ。

「rpm-ostree status」コマンドを実行すると、次のように現在ディスク内にインストールされているFedora CoreOSのバージョンが表示される。

$ rpm-ostree status
State: idle
AutomaticUpdates: disabled
Deployments:
● ostree://fedora:fedora/x86_64/coreos/testing
                   Version: 31.20191211.1 (2019-12-11T17:33:17Z)
                    Commit: f42843346587ae8cb8a022b5d7364864057fd2f6b54ca0b1dbf6f35faac63e0a
              GPGSignature: Valid signature by 7D22D5867F2A4236474BF7B850CB390B3C3359C4

  ostree://fedora:fedora/x86_64/coreos/testing
                   Version: 31.20191127.1 (2019-12-02T18:53:26Z)w
                    Commit: 3192002c490363d92b0b9bfe31a638c7411759aa4d46593af97fb0ae890da6dc
              GPGSignature: Valid signature by 7D22D5867F2A4236474BF7B850CB390B3C3359C4

ここでは「Version: 31.20191211.1 (2019-12-11T17:33:17Z)」と「Version: 31.20191211.1 (2019-12-11T17:33:17Z)」の2つが表示されており、前者のほうに「●」(もしくは「*」)という記号が付いている。「●」や「*」が付いているほうが現在アクティブになっているシステムだ。このようにFedora CoreOSではディスク内に複数のバージョンのシステムを用意しておき、アップデートによるトラブルが発生した場合などはすぐに以前のバージョンのシステムにロールバックできるようになっている。

システムのアップグレードを行うには、「upgrade」サブコマンドを使用する。このコマンドを実行すると、アップデートの存在するパッケージのダウンロードが行われる。ダウンロードおよびアップグレード処理の完了後、「systemctl reboot」コマンドを実行してシステムを再起動するとそれらが反映される。

$ sudo rpm-ostree upgrade
? Receiving objects: 99% (5151/5172) 2.2?MB/s 148.5?MB
Receiving objects: 99% (5151/5172) 2.2?MB/s 148.5?MB... done
Staging deployment... done
Upgraded:
  container-selinux 2:2.123.0-1.fc31 -> 2:2.123.0-2.fc31
  kernel 5.3.15-300.fc31 -> 5.3.16-300.fc31
  kernel-core 5.3.15-300.fc31 -> 5.3.16-300.fc31
  kernel-modules 5.3.15-300.fc31 -> 5.3.16-300.fc31
  libnghttp2 1.39.2-2.fc31 -> 1.40.0-1.module_f31+7164+9e64a937
  librepo 1.11.0-1.fc31 -> 1.11.1-1.fc31
  libsmbclient 2:4.11.2-1.fc31 -> 2:4.11.3-0.fc31
  libwbclient 2:4.11.2-1.fc31 -> 2:4.11.3-0.fc31
  samba-client-libs 2:4.11.2-1.fc31 -> 2:4.11.3-0.fc31
  samba-common 2:4.11.2-1.fc31 -> 2:4.11.3-0.fc31
  samba-common-libs 2:4.11.2-1.fc31 -> 2:4.11.3-0.fc31
  selinux-policy 3.14.4-40.fc31 -> 3.14.4-43.fc31
  selinux-policy-targeted 3.14.4-40.fc31 -> 3.14.4-43.fc31
  vim-minimal 2:8.1.2352-1.fc31 -> 2:8.1.2424-1.fc31
Removed:
  samba-libs-2:4.11.2-1.fc31.x86_64
Added:
  attr-2.4.48-7.fc31.x86_64
Run "systemctl reboot" to start a reboot

アップグレードの実行後に再度「rpm-ostree status」コマンドを実行すると、次のように以前のバージョン(Version: 31.20191217.2.0)を残しつつ、新たに「Version: 31.20191217.2.0 (2019-12-18T14:11:27Z)」がインストールされ、そちらがアクティブになっていることが分かる。

$ rpm-ostree status
State: idle
AutomaticUpdates: disabled
Deployments:
* ostree://fedora:fedora/x86_64/coreos/testing
                   Version: 31.20191217.2.0 (2019-12-18T14:11:27Z)
                    Commit: fd3a3a1549de2bb9031f0767d10d2302c178dec09203a1db146e0ad28f38c498
              GPGSignature: Valid signature by 7D22D5867F2A4236474BF7B850CB390B3C3359C4

  ostree://fedora:fedora/x86_64/coreos/testing
                   Version: 31.20191211.1 (2019-12-11T17:33:17Z)
                    Commit: f42843346587ae8cb8a022b5d7364864057fd2f6b54ca0b1dbf6f35faac63e0a
              GPGSignature: Valid signature by 7D22D5867F2A4236474BF7B850CB390B3C3359C4

アップグレード前の状態に戻すには、「rollback」サブコマンドを実行する。

$ sudo rpm-ostree rollback
Moving 'f42843346587ae8cb8a022b5d7364864057fd2f6b54ca0b1dbf6f35faac63e0a.0' to be first deployment
Bootloader updated; bootconfig swap: yes; deployment count change: 0
Downgraded:
  container-selinux 2:2.123.0-2.fc31 -> 2:2.123.0-1.fc31
  kernel 5.3.16-300.fc31 -> 5.3.15-300.fc31
  kernel-core 5.3.16-300.fc31 -> 5.3.15-300.fc31
  kernel-modules 5.3.16-300.fc31 -> 5.3.15-300.fc31
  libnghttp2 1.40.0-1.module_f31+7164+9e64a937 -> 1.39.2-2.fc31
  librepo 1.11.1-1.fc31 -> 1.11.0-1.fc31
  libsmbclient 2:4.11.3-0.fc31 -> 2:4.11.2-1.fc31
  libwbclient 2:4.11.3-0.fc31 -> 2:4.11.2-1.fc31
  samba-client-libs 2:4.11.3-0.fc31 -> 2:4.11.2-1.fc31
  samba-common 2:4.11.3-0.fc31 -> 2:4.11.2-1.fc31
  samba-common-libs 2:4.11.3-0.fc31 -> 2:4.11.2-1.fc31
  selinux-policy 3.14.4-43.fc31 -> 3.14.4-40.fc31
  selinux-policy-targeted 3.14.4-43.fc31 -> 3.14.4-40.fc31
  vim-minimal 2:8.1.2424-1.fc31 -> 2:8.1.2352-1.fc31
Removed:
  attr-2.4.48-7.fc31.x86_64
Added:
  samba-libs-2:4.11.2-1.fc31.x86_64
Run "systemctl reboot" to start a reboot

コマンドの実行後、先ほどと同様に再起動を行うと、より新しいバージョンのものを残しながら1つ前のバージョンにロールバックされる。この場合の「rpm-ostree status」コマンドの実行結果は次のようになる。

$ rpm-ostree status
State: idle
AutomaticUpdates: disabled
Deployments:
● ostree://fedora:fedora/x86_64/coreos/testing
                   Version: 31.20191211.1 (2019-12-11T17:33:17Z)
                    Commit: f42843346587ae8cb8a022b5d7364864057fd2f6b54ca0b1dbf6f35faac63e0a
              GPGSignature: Valid signature by 7D22D5867F2A4236474BF7B850CB390B3C3359C4

  ostree://fedora:fedora/x86_64/coreos/testing
                   Version: 31.20191217.2.0 (2019-12-18T14:11:27Z)
                    Commit: fd3a3a1549de2bb9031f0767d10d2302c178dec09203a1db146e0ad28f38c498
              GPGSignature: Valid signature by 7D22D5867F2A4236474BF7B850CB390B3C3359C4

systemd経由でのアプリケーションのインストールと設定

前述のとおりFedora CoreOSでは一般的なパッケージマネージャが利用できないため、パッケージマネージャ経由でのソフトウェアインストールは行えない。そのため、ソフトウェアのインストールは何らかの手段でバイナリをダウンロードして適当なディレクトリに配置して実行するか、もしくはコンテナを利用してコンテナ上で実行させることになる。

こういったコンテナの実行やソフトウェアのダウンロードおよびインストールは、Ignition経由で自動実行させることが推奨されている。また、コマンドの実行についてはIgnition経由でsystemdの設定を行うことで自動的に行えるようになっている。具体的には、まず必要なファイルをシステム内にダウンロードさせ、それを実行させるようなsystemdの設定ファイルを作成するという設定を行えば良い。

なお、Fedora CoreOSではDockerではなくRed Hatが推している「podman」というコンテナ管理ツールが標準搭載されている。podmanはコンテナ技術の標準規格を定めるOpen Container Initiative(OCI)の標準規格に基づいたコンテナ管理ツールで、Dockerとの互換性がある。そのため、dockerコマンドで実行していた処理の多くは単純にdockerコマンドをpodmanコマンドに置き換えるだけでそのまま実行が可能だ。また、記事執筆時点ではdockerコマンドも標準でインストールされており、問題なく利用が可能だ。ただし、将来的には別のコンテナエンジンに置き換えられる可能性もあるため、その点には注意したい。

設定例1:Webサーバーを起動する

まずは簡単な例として、コンテナ内でWebサーバーを実行させる設定を紹介しよう。現実的な環境であれば必要な設定ファイルなどをすべて含んだコンテナを作成するのが一般的だが、今回はテスト目的と言うことで、DockerHubで公開されているhttpdイメージをそのまま利用する。Fedora CoreOSでは前述のとおりdockerコマンドに相当するpodmanがデフォルトで利用できるので、コマンドを実行するようなsystemdのサービス設定ファイルを作成し、システム起動時にそのサービスを実行するような設定を行えば良い。

Ignitionでは、「systemd」という項目でその設定を行える。具体的には、次のような設定をIgnitionの設定ファイルに記述すれば良い。

systemd:
  units:
    - name: <サービス名>.service
      enabled: true ←trueを指定するとサービスが有効になる
      contents: |
      <この部分にサービス設定ファイルの内容を記述する
      
      

次の例は、「httpd.service」という名前でhttpdを起動する設定を含むIgnitionの設定ファイルだ。

variant: fcos
version: 1.0.0
passwd:
  users:
    - name: core
      ssh_authorized_keys:
        - ssh-rsa AAAAB... ←実際にはこの部分に使用する公開鍵を記述する
systemd:
  units:
    - name: httpd.service
      enabled: true
      contents: |
        [Unit]
        Description=httpd server
        [Service]
        Type=simple
        ExecStart=/usr/bin/podman run --rm -p 80:80 httpd:2.4
        [Install]
        WantedBy=multi-user.target

systemdのサービス設定ファイルについて詳しくはドキュメントを参考にして欲しいが、「[Service]」以下の「ExecStart」部分が実行するコマンドを指定する部分になる。また、「Type」部分はExecStartで指定したコマンドがどのような動作をするかを指定するもので、今回のようにコマンド実行後にフォアグラウンドで実行をし続けるものの場合は「simple」を指定すれば良い。このように指定した場合、「systemctl start <サービス名>」コマンド実行時にExecStartで指定したコマンドが実行され、「systemctl stop <サービス名>」コマンド実行時にそのプロセスが終了されるようになる。また、指定したコマンドが標準出力に出力した内容は「systemctl status <サービス名>」コマンドもしくは「journalctl -u <サービス名>」で確認できる。

このように記述した設定ファイルをfcctコマンドでJSON形式に変換し、coreos-installerでそれを指定してインストールを行えば、起動時にこの設定に基づいてhttpdを起動するホストができあがる。起動後に「systemctl status」コマンドで確認すると、次のようにhttpdが実行されていることを確認できるはずだ。

$ sudo systemctl status httpd
● httpd.service - httpd server
   Loaded: loaded (/etc/systemd/system/httpd.service; enabled; vendor preset: enabled)
   Active: active (running) since Fri 2019-12-20 09:42:16 UTC; 40min ago
 Main PID: 840 (podman)
    Tasks: 11 (limit: 2303)
   Memory: 97.0M
   CGroup: /system.slice/httpd.service
           mq840 /usr/bin/podman run --rm -p 80:80 httpd:2.4

12月 20 09:42:19 sv-113102244614 podman[840]: 2019-12-20 09:42:19.666891926 +0000 UTC m=+2.651944737 container attach 4549565a640e765fef2acd448988de9c1b16d83cff98e912b40a65ebf36ccdd6 (image=docker.io/library/httpd:2.4, name=dazzling_shannon)
12月 20 09:42:19 sv-113102244614 podman[840]: AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 10.88.0.3. Set the 'ServerName' directive globally to suppress this message
12月 20 09:42:19 sv-113102244614 podman[840]: AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 10.88.0.3. Set the 'ServerName' directive globally to suppress this message
12月 20 09:42:19 sv-113102244614 podman[840]: [Fri Dec 20 09:42:19.820815 2019] [mpm_event:notice] [pid 1:tid 140514339931264] AH00489: Apache/2.4.41 (Unix) configured -- resuming normal operations
12月 20 09:42:19 sv-113102244614 podman[840]: [Fri Dec 20 09:42:19.827006 2019] [core:notice] [pid 1:tid 140514339931264] AH00094: Command line: 'httpd -D FOREGROUND'

なお、Ignitionは初回起動時にのみ実行されるが、Fedora CoreOSは初回起動時かどうかを「/boot/ignition.firstboot」ファイルが存在するか、もしくはカーネルコマンドラインパラメータとして「ignition.firstboot」が定義されているかどうかで判断している(実際には、/boot/ignition.firstbootファイルの存在をブートローダであるgrubがチェックし、存在している場合カーネルコマンドラインパラメータに「ignition.firstboot」を追加するという挙動となっている)。もし「ignition.firstboot」が定義されていた場合、初回の起動だと判断してIgnitionによる初期設定が実行され、その後/boot/ignition.firstbootファイルが削除される仕組みだ。

また、coreos-installerはダウンロードしたIgnition設定ファイルを/boot/ignition/config.ignとして保存し、Ignitionによる設定の実行時にはこのファイルを参照して処理を実行する。これらを利用して、/boot/ignition/config.ignファイルを書き換えて、/boot/ignition.firstbootファイルを作成してリブートする、もしくは起動時のカーネルコマンドラインパラメータで「ignition.firstboot」を指定することで、インストール作業を実行することなしに新たに作成したIgnition設定ファイルに基づいた設定作業を実行できる。これはIgnition設定のデバッグ時などに有用だ。ただし、その場合以前にファイルシステムに加えた変更はそのまま残されるので注意したい。たとえばサービスを削除したい、といった場合は先に手動で/etc/systemd/systemディレクトリからサービス設定ファイルを削除するといった作業を実行しておく必要がある。

設定例2:Kubernetesのクラスタノード設定を自動で行う

続いての設定例は、Kubernetesのクラスタノードとして利用するための設定を行うものだ。Red Hatが提供する商用版であるRed Hat Enterprise Linux CoreOSではクラスタの構築や管理を行うツールが提供されるが、Fedora CoreOSではそういったものは提供されていないため、独自に設定を行う必要がある。今回は、以前2019年版・Kubernetesクラスタ構築入門で紹介したクラスタ構築ツール「kubeadm」で説明した手順に従ってKubernetesのクラスタノードとしての設定を行う。また、以下ではKubernetesクラスタのマスターノードがすでに構築済みであることを前提とする。マスターノードの構築についてはこの記事を参考に行って欲しい。

さて、Fedora CoreOSではKubernetesクラスタ構築に必要なkubeadmやkubeletといったKubernetes関連ツールや、コンテナ管理のためのコマンドであるcri toolsなどが含まれていない。そのため、これらは別途インストールする必要がある。これらやその設定ファイルなどはGitHubやKubernetesのダウンロードページからダウンロードできるが、これらサイトにアクセスできなくなるといった場合に備えて、あらかじめローカルネットワーク内にダウンロードしておき、そこからHTTPなどで各クラスタに配信できるように設定しておくことをおすすめする。具体的に必要なファイルとそのダウンロードURLは表2の通りだ。

表2 必要なコマンドや設定ファイルとそのダウンロードURL
ファイル名 説明 ダウンロードURL
kubeadm Kubernetesクラスタの管理ツール https://storage.googleapis.com/kubernetes-release/release/<バージョン>/bin/linux/amd64/kubeadm
kubelet Kubernetesノードの管理エージェント https://storage.googleapis.com/kubernetes-release/release/<バージョン>/bin/linux/amd64/kubelet
10-kubeadm.conf kubeadmを利用するためのkubelet向け設定ファイル https://raw.githubusercontent.com/kubernetes/kubernetes/<バージョン>/build/debs/10-kubeadm.conf
crictl コンテナ管理ツール https://github.com/kubernetes-sigs/cri-tools/releases/download/<バージョン>/crictl-<バージョン>-linux-amd64.tar.gz

なお、Kubeadmやkubeletのバージョンについては「v1.x.y」という形で指定する。記事執筆時点での最新版はv1.17.0が最新版だが、使用しているクラスタの環境に合わせたものを使用する。本記事で使用した環境ではv1.15系のKubernetesでクラスタを構築しているので、v1.15系の最新版である「v1.15.7」を使用する。この場合、kubeadmとkubelet、設定ファイルの10-kubeadm.confは次のようにしてダウンロードできる。

$ wget https://storage.googleapis.com/kubernetes-release/release/v1.15.7/bin/linux/amd64/kubeadm
$ wget https://storage.googleapis.com/kubernetes-release/release/v1.15.7/bin/linux/amd64/kubelet
$ wget https://raw.githubusercontent.com/kubernetes/kubernetes/v1.15.7/build/debs/10-kubeadm.conf

また、crictlについては使用するKubernetesのバージョンに対応するバージョンのものを選択する。基本的には、使用するKubernetesのバージョンと<メジャー>.<マイナー>部分が同じものを選択すれば良い。たとえばKubernetes v1.15.xのクラスタでは、crictlはv1.15.0を選択する。crictlはtar.gz形式で圧縮されて配布されているので、ダウンロード後にtarコマンドで展開するとcrictlコマンドが生成される。

$ wget https://github.com/kubernetes-sigs/cri-tools/releases/download/v1.15.0/crictl-v1.15.0-linux-amd64.tar.gz
$ tar xvzf crictl-v1.15.0-linux-amd64.tar.gz

これらのファイルのインストールには、Ignitionのファイルインストール機能を使用する。これは、設定ファイルで指定したURLからファイルをダウンロードしてインストールできるものだ。そのため、Fedora CoreOSをインストールするマシンからこれらのファイルにHTTPでアクセスできるようにしておく必要がある。今回は、Ignitionの設定ファイルやFedora CoreOSのイメージファイルを配信するWebサーバー上にこれらのファイルを置き、「http://192.0.2.100:8080/container/<ファイル名>」というURLからダウンロードできるように設定しておいた。

また、kubeadmを使ってKubernetesクラスタノードを構築する際は、加入するクラスタを識別するためのトークンや証明書のハッシュ文字列といった情報が必要となる。証明書のハッシュ文字列については証明書を変更しない限り変化しないが、トークンには24時間の有効期限があるため、kubeadmコマンドの実行時に別途外部からトークン文字列を取得できるように設定しておく。

トークン文字列はKuberneteのマスターノードで次のようにkubeadmコマンドを実行することで取得できる。

# kubeadm token create
7bix0y.3gece9c0oonxnlyx

今回は次のようにこの文字列を「token」というファイルに保存し、「http://192.0.2.100:8080/container/token」というURLで取得できるようにすることで、クラスタノードからトークンを取得できるようにした。

# kubeadm token create > token

また、証明書のハッシュ文字列は次のようにして確認できる。

# kubeadm token create --print-join-command
kubeadm join 192.0.2.100:6443 --token 1a0l2g.4mh3o143nznrub5j     --discovery-token-ca-cert-hash sha256:73c2...

ここで表示された「--discovery-token-ca-cert-hash」以降の文字列がkubeadmコマンド実行時に必要となるハッシュ文字列となる。

さて、これらのファイルのダウンロードや設定を行うIgnition設定ファイルは次のようになる。

variant: fcos
version: 1.0.0
passwd:
  users:
    - name: core
      ssh_authorized_keys:
        - ssh-rsa AAAAB...  ←SSHログインに使用するSSH公開鍵を指定する

# サービスの設定
systemd:
  units:
# kubeletサービスの設定
    - name: kubelet.service
      enabled: true
      contents: |
        [Unit]
        Description=kubelet: The Kubernetes Node Agent
        Documentation=http://kubernetes.io/docs/
        [Service]
        EnvironmentFile=-/etc/sysconfig/kubelet
        ExecStart=/root/bin/kubelet $KUBELET_EXTRA_ARGS
        Restart=always
        StartLimitInterval=0
        RestartSec=10
        [Install]
        WantedBy=multi-user.target
# クラスタ加入のためのスクリプトを実行させるサービスの設定
    - name: join_cluster.service
      enabled: true
      contents: |
        [Unit]
        Description=join kubernetes cluster
        Wants=network-online.target
        [Service]
        Type=oneshot
        RemainAfterExit=true
        ExecStart=/bin/bash /opt/join_cluster.sh
        [Install]
        WantedBy=multi-user.target

# インストールするファイルの設定
storage:
  files:
# kubeletをインストールする
    - path: /root/bin/kubelet
      mode: 0755
      overwrite: true
      contents:
        source: http://<設定ファイル等を配信するWebサーバー>/container/kubelet
# kubeadmをインストールする
    - path: /root/bin/kubeadm
      mode: 0755
      overwrite: true
      contents:
        source: http://<設定ファイル等を配信するWebサーバー>/container/kubeadm
# crictlをインストールする
    - path: /root/bin/crictl
      mode: 0755
      overwrite: true
      contents:
        source: http://<設定ファイル等を配信するWebサーバー>/container/crictl
# kubeadm用の設定ファイルをインストールする
    - path: /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
      mode: 0644
      overwrite: true
      contents:
        source: http://<設定ファイル等を配信するWebサーバー>/container/10-kubeadm.conf
# kubeletの設定ファイルをインストールする
# Fedora CoreOSのDockerではcgroup driverとして「systemd」を使用するように
# 設定されているので、それを明示する
    - path: /etc/sysconfig/kubelet
      mode: 0644
      overwrite: true
      contents:
        inline: KUBELET_EXTRA_ARGS="--cgroup-driver=systemd"
# クラスタ加入のためのシェルスクリプトを作成する
    - path: /opt/join_cluster.sh
      mode: 0644
      overwrite: true
      contents:
        inline: |
          # SELinuxを無効にする
          setenforce 0
          # クラスタ識別のためのトークンを取得する
          # シェルスクリプト実行時はネットワークが有効になっていない場合があるので
          # 失敗した場合は一定間隔をおいて再試行する
          TOKEN=
          RETRY=0
          while [ -z $TOKEN ]; do
            sleep $(expr $RETRY \* 10)
            TOKEN=$(curl http://<設定ファイル等を配信するWebサーバー>/container/token)
            RETRY=$(expr $RETRY + 1)
            [ $RETRY -gt 3 ] && echo "connetion error" && exit 1
          done
          HASH=<証明書のハッシュ文字列>
          # kubeadmやkubelet、crictlの実行時にパスが通っていない可能性を考慮して
          # 明示的にパスを指定してkubeadmコマンドを実行する
          PATH=/root/bin:$PATH /root/bin/kubeadm reset -f
          PATH=/root/bin:$PATH /root/bin/kubeadm join 192.0.2.100:6443 --token $TOKEN --discovery-token-ca-cert-hash $HASH

この設定ファイルでは、まず実行させるサービスの設定を行っている。まず必要となるのが、Kubernetesのクラスタノードでエージェントとして動作する「kubelet」サービスだ。ここではkubeletをデーモンとして実行させるための最小限の設定のみを行っている。細かいオプション設定は、後述するドロップイン(systemdサービスの設定を上書きするための設定)で行うためだ。

# サービスの設定
systemd:
  units:
# kubeletサービスの設定
    - name: kubelet.service
      enabled: true
      contents: |
        [Unit]
        Description=kubelet: The Kubernetes Node Agent
        Documentation=http://kubernetes.io/docs/
        [Service]
        EnvironmentFile=-/etc/sysconfig/kubelet
        ExecStart=/root/bin/kubelet $KUBELET_EXTRA_ARGS
        Restart=always
        StartLimitInterval=0
        RestartSec=10
        [Install]
        WantedBy=multi-user.target

システムの起動時にKubernetesクラスタへの加入処理を実行するスクリプトは、「join_cluster」というサービスを定義してそこで実行させるよう設定している。その設定を行っているのが次の部分だ。こういった単発の処理を行う設定については、サービスの「Type」として「oneshot」を指定すれば良い。実行するコマンド(ExecStart)としては「/bin/bash /opt/join_cluster.sh」を指定している。さらに「RemainAfterExit」をtrueに指定することで、指定した処理が正常に完了したかどうかをsystemctlコマンドで容易に確認できるようにしている。

# クラスタ加入のためのスクリプトを実行させるサービスの設定
    - name: join_cluster.service
      enabled: true
      contents: |
        [Unit]
        Description=join kubernetes cluster
        Wants=network-online.target
        [Service]
        Type=oneshot
        RemainAfterExit=true
        ExecStart=/bin/bash /opt/join_cluster.sh
        [Install]
        WantedBy=multi-user.target

Ignitionの設定ファイルでは「storage:」以下の「files:」項目でインストールするファイルを指定できる。ここではまず先に説明したkubeletおよびkubeadm、crictlのインストールを行っている。指定しているオプション設定についてはドキュメントを参照してほしいが、「mode:」はファイルのパーミッションを指定するもので、「overwrite」はファイルがすでに存在している場合でも上書きを行うことを指定するものだ。Fedora CoreOSでは/usr以下のディレクトリについては書き込みできないようになっているため、これらバイナリについては、「/root/bin」以下にインストールしている。

storage:
  files:
# kubeletをインストールする
    - path: /root/bin/kubelet
      mode: 0755
      overwrite: true
      contents:
        source: http://<設定ファイル等を配信するWebサーバー>/container/kubelet
# kubeadmをインストールする
    - path: /root/bin/kubeadm
      mode: 0755
      overwrite: true
      contents:
        source: http://<設定ファイル等を配信するWebサーバー>/container/kubeadm
# crictlをインストールする
    - path: /root/bin/crictl
      mode: 0755
      overwrite: true
      contents:
        source: http://<設定ファイル等を配信するWebサーバー>/container/crictl

kubeadm用の設定ファイル(10-kubeadm.conf)については、「/etc/systemd/system/kubelet.service.d」ディレクトリにインストールする。こうすることで、先に述べたとおりkubelet.serviceのドロップイン(ユーザー定義の設定ファイル)として認識されるようになる。

# kubeadm用の設定ファイルをインストールする
    - path: /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
      mode: 0644
      overwrite: true
      contents:
        source: http://<設定ファイル等を配信するWebサーバー>/container/10-kubeadm.conf

kubeletの設定ファイル(/etc/sysconfig/kubelet)については以下のように設定した。この設定ファイルでは「KUBELET_EXTRA_ARGS」環境変数でkubeletコマンドの追加の引数を指定できる。Fedora CoreOSのDockerではcgroup driverとして「systemd」を使用しているので、これに対応させるため今回は「--cgroup-driver=systemd」というオプションを指定している。

# kubeletの設定ファイルをインストールする
# Fedora CoreOSのDockerではcgroup driverとして「systemd」を使用するように
# 設定されているので、それを明示する
    - path: /etc/sysconfig/kubelet
      mode: 0644
      overwrite: true
      contents:
        inline: KUBELET_EXTRA_ARGS="--cgroup-driver=systemd"

最後の「/opt/join_cluster.sh」ファイルは、前述した「join_cluster」サービスが実行するシェルスクリプトだ。ここではまずcurlコマンドを使ってクラスタを識別するためのトークンを取得し、それを引数としてKubernetesクラスタへの加入処理を行うための「kubeadm join」コマンドを実行している。ただし、systemdではサービス起動処理を並行して行うため、このシェルスクリプト実行時にはネットワークが利用できない可能性がある。そのため、curlコマンドが失敗した場合にはsleepコマンドを実行して一定時間待機した後にリトライを行うような処理を行っている。

また、今回kubeadmコマンドやkubeletコマンド、crictlコマンドをインストールしている/root/binディレクトリはrootユーザー以外では検索パスに入っていない。そのため、明示的にPATH環境変数を指定してkubeadmコマンドを実行している。

# クラスタ加入のためのシェルスクリプトを作成する
    - path: /opt/join_cluster.sh
      mode: 0644
      overwrite: true
      contents:
        inline: |
          # SELinuxを無効にする
          setenforce 0
          # クラスタ識別のためのトークンを取得する
          # シェルスクリプト実行時はネットワークが有効になっていない場合があるので
          # 失敗した場合は一定間隔をおいて再試行する
          TOKEN=
          RETRY=0
          while [ -z $TOKEN ]; do
            sleep $(expr $RETRY \* 10)
            TOKEN=$(curl http://<設定ファイル等を配信するWebサーバー>/container/token)
            RETRY=$(expr $RETRY + 1)
            [ $RETRY -gt 3 ] && echo "connetion error" && exit 1
          done
          HASH=<証明書のハッシュ文字列をここで指定する>
          # kubeadmやkubelet、crictlの実行時にパスが通っていない可能性を考慮して
          # 明示的にパスを指定してkubeadmコマンドを実行する
          PATH=/root/bin:$PATH /root/bin/kubeadm reset -f
          PATH=/root/bin:$PATH /root/bin/kubeadm join <マスターノード>:6443 --token $TOKEN --discovery-token-ca-cert-hash $HASH

このような設定ファイルを使ってFedora CoreOSをインストールし、その後マシンを起動すると、自動的にそのマシンがKubernetesのクラスタノードとして認識されるようになる。たとえばマスターノードで「kubectl get node」コマンドを実行して確認すると、次のようにそのマシン(ここでは「sv-113102262049」)がノードとして認識されていることが分かる。

$ kubectl get node
NAME              STATUS   ROLES    AGE     VERSION
centos4x4         Ready    master   62d     v1.15.0
sv-113102262049   Ready    <none>   5m10s   v1.15.7

前述のようにIgnitionによる初期設定はサーバーの初回起動時に実行されるため、たとえばさくらのクラウドのようなIaaSクラウド環境ではインストール直後、初回起動前の段階のイメージファイルを複製することで、簡単にクラスタに参加するノードを構築できるようになる。

今後kubernetesクラスタで利用するOSとして主流になる可能性、ただしまだ安定版ではない点には注意が必要

昨今ではさくらのクラウドのようなIaaS(Infrastructure as a Service)型のクラウドサービスが普及しており、これらを利用することでハードウェアの管理については自前で面倒を見る必要はなくなるものの、OS環境については別途管理が必要となる。特に頭を悩ますのはアップデート関連だろう。Fedora CoreOSではアップデートが自動化されており、また個々のパッケージ管理が不要であるため管理しやすい。OS自体のフットプリントも小さく、使用するハードウェアリソースが少ないのもメリットだ。

ただ、現時点ではFedora CoreOSはプレビュー段階であり、今後仕様などが大きく変わる可能性がある。そのため、現状では運用環境での大規模な利用はあまりおすすめできない。Red Hatの発表によれば、2020年中には正式版がリリースとなるため、それまでは様子を見た方が良いだろう。