k8s 1.20のDocker非推奨問題でEKSを使用しているプロジェクトが対応すること

※ 本稿は [Tech Inside Drecom](https://tech.drecom.co.jp/?_src=qiita) に掲載された記事、「[k8s 1.20のDocker非推奨問題でEKSを使用しているプロジェクトが対応すること](https://tech.drecom.co.jp/k8s-1_20-problem-for-eks-with-docker/?_src=qiita)」の Qiita 出張版です。

---

こんにちは！
enza SREチームのmendと申します！
<a href="https://tech.drecom.co.jp/ac2020-k0sk8sk9s/?_src=qiita">前回のk0sの記事</a>に引き続いて、今回もKubernetes関連の記事になります！

enzaでは現在システムのインフラの一部を、コンテナオーケストレーションシステム：<a href="https://kubernetes.io/ja/">Kubernetes</a>(以下k8s)に依存するAWSのマネージドKubernetesサービス：<a href="https://aws.amazon.com/jp/eks/">Amazon EKS</a>で運用しております。

Kubernetesはおおよそ3ヶ月に1回のリリースサイクルとかなり活発に開発が行われており、2020年12月8日にはバージョン1.20が<a href="https://kubernetes.io/blog/2020/12/08/kubernetes-1-20-release-announcement/">リリース</a>されました。

<a href="https://kubernetes.io/docs/setup/release/notes/#v1-20-0">k8s 1.20のリリースノート</a>では、コンテナランタイムとしてのDockerが非推奨になり、2021年末リリース予定のv1.23では削除する予定であることが記載されておりました。

今回はk8sのバージョン1.20で話題になったDockerが非推奨となる問題についてのおさらいと、EKSを使用しているプロジェクトの対応方針、enzaチームでの対応方針をまとめたいと思います。

<h2>背景</h2>
2020年12月2日、Kubernetes Blogで<a href="https://kubernetes.io/blog/2020/12/02/dont-panic-kubernetes-and-docker/">Don't Panic: Kubernetes and Docker</a>が公開されました。
中にはこのような記載がされています。
<blockquote>Kubernetes is <a href="https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.20.md#deprecation">deprecating Docker</a> as a container runtime after v1.20.</blockquote>
この部分だけを見てみると「k8sでDockerが使えなくなる」=&gt; 「Dockerが使えなくなる」といった解釈をされてしまいそうですが、(実際SNSでこのような解釈をした方も結構見られました。)まず問題の要点を見ていきたいと思います。
<h2>問題の要点</h2>
<a href="https://kubernetes.io/blog/2020/12/02/dont-panic-kubernetes-and-docker/">Don't Panic: Kubernetes and Docker</a>の内容について少し解説します。

上記の記事では、<strong>k8s v1.20からDockerが非推奨になるけど焦らないで欲しい</strong>といった内容が書かれています。

重要な部分についてまとめると以下のようになっています。
<h3>Dockerで作成したイメージはそのまま使える</h3>
「Dockerが使えなくなる」という解釈が生まれていますが、「Dockerで作成したイメージはそのまま使える」が正しい認識です。
k8sではコンテナを「コンテナランタイム(※後に解説)」と呼ばれるコンテナを管理する機能があります。
v1.19まではコンテナランタイムにDockerを使用していましたが、v1.20からは<strong>コンテナランタイムにDockerを使用することは非推奨</strong>になります。
k8sのコンテナランタイムは端的に言うと<strong>コンテナを動かす場</strong>ですので<strong>Dockerで作成されたイメージは使用できないことはありません。</strong>
<h3>なぜコンテナランタイムのDockerを非推奨にするのか</h3>
k8sではコンテナランタイムに対してContainer Runtime Interface：CRIを通して通信を行っています。

そもそも今まで使用されてきたDockerはCRIに対応していませんでした。
そのためDockerをコンテナランタイムとして使用するために別途dockershimを用意しており、CRI経由のAPIをDockerで使用できるように変換することで対応しておりました。

CRIが2016年ごろに規定された背景から、今回のv1.20からCRIの規定と異なるDockerの対応を打ち切り、<strong>CRIの規定に沿った他のコンテナランタイムを使用する方針を推奨</strong>する形になったようです。
<h3>1.20に更新する際の対応</h3>
コンテナランタイムはワーカーごとに設定するものになっております。

もしDockerをコンテナランタイムとして設定したままv1.20に更新するとdockershimが非推奨であるとの警告がでるようになりますので、<strong>v1.20に更新する前にCRIに対応した別のコンテナランタイムに変更する必要があります。</strong>
<h2>コンテナランタイムとは</h2>
コンテナランタイムは簡潔にいうと<strong>コンテナを動かす場</strong>と思っていただければと思います。

コンテナランタイムはワーカーごとに設定されるもので、ワーカー内のkubeletがCRIを通してコンテナランタイムに対して通信を行い、コンテナの管理を行っております。

実際に使用しているワーカーでどのコンテナランタイムを使用しているかを確認する際には、以下のコマンドで確認できます
<pre class="wp-block-code"># dockerがコンテナランタイムに指定されている場合は以下のようになります。
$ kubectl get no k8s-node-name -o jsonpath="{.status.nodeInfo.containerRuntimeVersion}"
docker://18.9.9
</pre>
Dockerとcontainerdをコンテナランタイムとして使用する場合の動作のイメージは以下の図のようになります。

![k8s_CRI.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218415/b0a9f726-ea33-3a44-2bc9-4ef3226b35ae.png)

図を見て頂くと、Dockerを使用する場合はdockershimがCRIの通信をDocker APIに変換していることがわかると思います。
containerdのようなCRIに対応したコンテナランタイムを使用することで、構造がシンプルになり、マシンのリソースも節約できるメリットがあります。
<h2>EKSを使用している場合の対応案</h2>
EKSでk8sクラスターを構築している場合、ワーカーで指定しているコンテナランタイムを変更する対応が必要になります。

EKSではEKSに最適化されたAMIがAWS側から用意されていたり、コンテナの実行に特化したAMIであるbottlerocket OSを使用できたりと、様々なアプローチでクラスターを構成する方法があります。
今回はEKSに最適化されたAMIを使用している場合を想定し、コンテナランタイムを変更する対応の案をまとめてみました。
<h3>案1：EKS最適化されたAMIの更新を待つ</h3>
AWSから公開されている<a href="https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/eks-optimized-amis.html">EKSに最適化されたAMI</a>で、コンテナランタイムが変更されたAMIがリリースされることを待ち、リリースされたAMIからワーカーを起動する方法になります。

こちらの方法はAWS側でコンテナランタイムを変更したAMIがリリースされたものを使用するため、開発チームで対応する必要がなく、AWSによってサポートされるAMIのため簡潔に対応することができます。
<h3>案2：bottlerocketのAMIを使う</h3>
<a href="https://github.com/bottlerocket-os/bottlerocket">bottlerocket OS</a>というコンテナの実行に特化したOSを使用する案になります。

bottlerocketは既にCRIにcontainerdを使用しているため、k8s v1.20に更新するタイミングに合わせてワーカーのOSをbottlerocketに変更する案になります。

しかし直接SSHで接続できないなどのクセのある部分を確認しているので、採択には事前の検証や試用をしておいたほうが良いでしょう。
<h3>案3：カスタムAMIを作成する</h3>
3つ目の方法は最終手段的な意味合いが強いですが、コンテナランタイムにcontainerdを指定したワーカーのAMIを作成する案になります。

こちらの方法ではAMIを作成する方針のため、containerdやCRI-Oのように使用したいコンテナランタイムを選択できるなど自由度が高い一方、クラスタを維持するためにk8sの短いバージョンアップ周期に合わせてカスタムAMIのメンテナンスが必要になります。
よって基本的にオススメはできず、案1, 案2の両方が何らかの理由で採択できない場合の最終手段としての扱いです。

案1で記載したEKS最適化AMIをカスタムする対応でも良さそうと最初に思ったのですが、
<a href="https://github.com/aws/containers-roadmap">awsのcontainer-roadmap</a>を確認したところ、
2020年1月19日現在ではコンテナランタイムの移行先に使用されるcontainerdとCRI-Oがサポートされていないとの<a href="https://github.com/aws/containers-roadmap/issues?q=is%3Aissue+is%3Aopen+containerd+CRI-O">issue</a>が挙がっていました。
<h2>enzaチームの対応方針</h2>
先程の案全てを吟味した上で<strong>enzaチームでは案1のAWSで対応したAMIの使用を基本方針として進める</strong>ことにしました。
理由としては<a href="https://kubernetes.io/blog/2020/08/31/kubernetes-1-19-feature-one-year-support/">k8s 1.19からサポート期間が長くなる</a>こと、<a href="https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/kubernetes-versions.html">EKSではマイナーバージョンを約12ヶ月間サポートされる</a>ことに加えて、案1はワーカーノードのAMIを変更するだけで対応ができ、実装の負荷を他の案に比べて最小限にできるためです。

しかし案1は2021年末にリリース予定のk8s v1.23に更新する際までにAWS側で対応がされていなければ実施できないため、案1が対応されない場合は案2, 案3の優先度で進める方針です。

案2はこれまで使用したことがないOSであるため、SSHを伴う作業が必要になった場合の対応方法等の事前の調査が必要であることから実際に案2を実施するまでの期間が必要になってしまいます。

案3に至っては<a href="https://github.com/aws/containers-roadmap/issues?q=is%3Aissue+is%3Aopen+containerd+CRI-O">対象のissue</a>が解消されないと対応できないうえに将来的なメンテナンスを考慮しなくてはいけないため、今後の開発・運用に大きく関わります。
<h2>まとめ</h2>
今回はk8s 1.20のdocker非推奨問題に備え、EKSを使用しているプロジェクトが対応することをまとめてみました。

docker自体が非推奨となるわけではなく、<strong>k8s v1.20コンテナランタイムにdockerを使用することを非推奨</strong>となったのであり、k8s 1.20を迎えるenzaチームでは、k8s 1.19からサポート期間が長くなることに加えて、AMIを変更するだけで対応が可能であることから案1の方針としました。

EKSは執筆当時k8sはv1.18までリリースされている状態になっております。
現状EKSではv1.20のリリースの予定は発表されておりませんが、将来に備えて事前に調査してみました。

調査してみたところ現状EKSではv1.20のリリースの予定は発表されておりませんが、
EKSを使用するプロジェクトでは基本的に<strong>EKSに最適化されたAMI</strong>を使用することがオススメであり、
EKSに最適化されたAMIが使用できないのであれば<strong>bottlerocket OS</strong>や<strong>カスタムAMI</strong>を作成するのも一つの案です。

普段はコンテナを動作させるシステムについて意識することはありませんでしたが、
今回の調査を通して、k8sについてさらに知見を深めることができました。

今後もk8s関連の情報を発信できたらと思います。

<hr>

ドリコムでは一緒に働くメンバーを募集しています！
募集一覧は<a href="https://bit.ly/2QKNSlG" target="_blank">コチラ</a>を御覧ください！

---

※ その他の Tech Inside Drecom の記事は、[コチラ](https://tech.drecom.co.jp/?_src=qiita)からお探しいただけます！