コンテナを用いたシステムのアーキテクチャパターンはいくつか提唱されています。今回はその中で、分散システムのデザインパターンであるサイドカーパターンを取り上げます。サイドカーパターンは、マイクロサービスの課題を解決するために生まれたサービスメッシュの概念につながるパターンです。
今回は、ローカルな K8s 環境で、サイドカーパターンを用いたアプリケーションを試しに動かしてみるところまでやってみます。
サイドカーパターンとは
- 下図のように Kubernetes のポッド内で、主となるコンテナと共にそれを補助する役割を果たすコンテナを持つ構成をサイドカーパターンと呼びます。
- ポッドが起動すると、内部の複数のコンテナが同時にスタートします。
- 2 つのポッド間では、ネットワークやディスクなどの情報を共有しています。
- このパターンの利点を列挙すると、以下のようになります:
- 都度、目的にあったコンテナのイメージをビルドするのではなく、過去に開発し、実績があるコンテナを容易に再利用が可能である
- ポッド内のコンテナごとに CPU の使用時間の上限を設定することが可能
- 例えば、メインとなるコンテナに CPU を優先的に割り当てて低レインテシで応答させ、補助コンテナはメインのコンテナがヒマなときに動作させるなど。
- コンテナが障害の封じ込めの境界を提供することになるので、全体が停止するのを防止できる
- サービスメッシュの考え方にもつながる利点
- サービスメッシュについては、次回の記事で解説します
- サービスメッシュの考え方にもつながる利点
- コンテナがデプロイの単位になるため、各機能をアップグレードし、必要に応じてロールバックすることが出来る
具体的な稼働例
- 実際に、K8s を利用して、サイドカーパターンでアプリケーションをデプロイしてみます。
- 今回は、Amazon EKS の上で試すのも大げさなので、手元で動く K8s 環境にて試してみます。
- 手元で稼働する K8s 環境としては Minukube を利用するか Docker Desktop で K8s を利用する方法があります。いずれの方法でも下記の手順が成功することは確認しています。
- それぞれのツールのインストール方法は、ここでは触れません。Minikube のインストールについては参考資料をご確認ください。
- 以下、Minikube がインストールされている前提で進めていきます。
- 試してみるのは下図のようなものです:
自力で Git からの取り込みコンテナを実装する
必要なファイルを用意する
- 用意するのは以下の 3 つ:
contents-puller
#!/bin/bash # 最新WebコンテンツをGitHubからコンテナへ取込む # コンテンツ元の環境変数が無ければエラーで終了 if [ -z $CONTENTS_SOURCE_URL ]; then exit 1 fi # 初回は GitLab からコンテンツをクローンする git clone $CONTENTS_SOURCE_URL /data # 2 回目以降は、1 分ごとに変更差分を取得する cd /data while true do date sleep 60 git pull done
Dockerfile
- Git からの取り込みコンテナの定義を記述します。
- 単純に、前述のシェルスクリプトを起動するだけのコンテナです。
## Contents Cloner Image FROM alpine:latest RUN apt-get update && apt-get install -y git COPY ./contents-puller /contents-puller RUN chmod a+x /contents-puller WORKDIR / CMD ["/contents-puller"]
webserver.yml
- サイドカーポッドのマニフェストファイルです。
- デプロイメントとサービスを定義します。
- デプロイメントでは 2 つのコンテナと共有ボリュームを定義します。
- サービスでは NodePort を定義し、外部へ公開出来るようにします。
- デプロイメントとサービスを定義します。
--- apiVersion: apps/v1 kind: Deployment metadata: name: webserver spec: replicas: 1 selector: matchLabels: app: webserver template: metadata: labels: app: webserver spec: ## コンテナの定義 containers: ## 1つ目のコンテナ:Nginx - name: nginx image: nginx volumeMounts: - mountPath: /usr/share/nginx/html name: contents-vol readOnly: true ## 2つ目のコンテナ:GitLabから pull してくるコンテナ - name: cloner image: maho/c-cloner:0.1 env: - name: CONTENTS_SOURCE_URL # ここのリポジトリは適当な公開リポジトリを設定する value: https://gitlab.com/hogehoge/webcontent-test.git volumeMounts: - mountPath: /data name: contents-vol ## 共有ボリューム volumes: - name: contents-vol emptyDir: {} --- apiVersion: v1 kind: Service metadata: name: webserver labels: app: webserver spec: selector: app: webserver type: NodePort ports: - port: 80 targetPort: 80
マニフェストを適用して確認する
- 上記 3 ファイルを同じディレクトリ内に置き、マニフェストを適用します。
- 適用したら、コンテナが稼働するまでしばらく待ちます。
- 稼働したら
minikube service webserver --url
コマンドでアクセス先の URL を取得します。
$ kubectl apply -f webserver.yml $ kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES webserver-5bfdd5d57d-qjv4g 2/2 Running 0 33s 172.17.0.5 minikube <none> <none> $ kubectl get svc -o wide NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 53d <none> webserver NodePort 10.97.246.59 <none> 80:30523/TCP 48s app=webserver $ minikube service webserver --url http://192.168.64.3:30523
- 上記の場合、
http://192.168.64.3:30523
にアクセスして、リポジトリにアップしたページが表示されることを確認できます。
- また、HTML コンテンツの内容を変更して、GitLab に push してみます。 1 分程度経過した後、再度上記 URL にアクセスしてみると、きちんと変更が反映されています。
- コンテナの動作により、コンテンツが最新化されていることが分かります。
既存のコンテナ git-sync
を利用する
- 先程までの手順で、自力で実装した補助コンテナ(GitLab からコンテンツを pull してくる役割のコンテナ)ですが、同様の処理を行うコンテナが提供されています(git-sync)。
- この git-sync を利用する場合、下記のマニフェストファイル 1 つ(
git-sync.yml
)を作成するだけで、同様の処理を実現することが出来ます。
--- apiVersion: apps/v1 kind: Deployment metadata: name: git-sync spec: replicas: 1 selector: matchLabels: app: git-sync template: metadata: labels: app: git-sync spec: # コンテナの定義 containers: # 1つ目のコンテナ:nginx - name: nginx image: nginx:alpin ports: - containerPort: 80 volumeMounts: - name: git-sync-volume mountPath: /usr/share/nginx # 2つ目のコンテナ:git-sync - name: git-sync image: k8s.gcr.io/git-sync:v3.1.3 volumeMounts: - name: git-sync-volume mountPath: /sync env: - name: GIT_SYNC_REPO # ここの URL は適当なリポジトリのものに変更する value: https://gitlab.com/hogehoge/webcontent-test.git - name: GIT_SYNC_BRANCH # ブランチ名も適当なものに変更する value: master - name: GIT_SYNC_ROOT value: /sync - name: GIT_SYNC_DEST value: html volumes: - name: git-sync-volume emptyDir: {} --- apiVersion: v1 kind: Service metadata: name: git-sync labels: app: git-sync spec: selector: app: git-sync type: NodePort ports: - port: 80 targetPort: 80
- マニフェストファイルを作成したら、適用します。
$ kubectl apply -f git-sync.yml deployment.apps/git-sync created service/git-sync created tsuchinoko@Tsuchinoko-MBP-9:~/d/b/side-car $ kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES git-sync-78c65f6d77-qxls9 0/2 ContainerCreating 0 11s <none> minikube <none> <none> tsuchinoko@Tsuchinoko-MBP-9:~/d/b/side-car $ kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES git-sync-78c65f6d77-qxls9 2/2 Running 0 57s 172.17.0.5 minikube <none> <none> $ kubectl get svc -o wide NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR git-sync NodePort 10.103.190.137 <none> 80:30383/TCP 84s app=git-sync kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 54d <none> $ minikube service git-sync --url http://192.168.64.3:30383
- 先程と同様に
http://192.168.64.3:30383
にアクセスすると Git に push した HTML コンテンツが表示されていることが分かります。- また、更新を Git に push したら、約 1 分後にコンテンツが最新になっていることも確認できます。
まとめ
- 分散システムのデザインパターンの 1 つである、サイドカーパターンとは何かを確認しました。
- この手のデザインパターンには、適したコンテナが DockerHub で公開されていたりします。
- それらを上手に活用することで、開発にかかるコストを下げることが出来ます。
- サイドカーパターンで HTML コンテンツを表示する方法を実践してみました。
- このパターンを念頭に置きながら、次回はサービスメッシュを理解するための記事を書きます。
参考資料
- 高良(2019)「15Stepで習得 Dockerから入るKubernetes」リックテレコム
- サイドカーパターンの基本と説明について参考にしました。
- コンテナ・デザイン・パターンの論文要約 - Qiita
- サイドカーパターンの説明について参考にしました。
- Kubernetesで学ぶ分散システムデザインパターン - Qiita
git-sync
を用いる場合のマニフェストファイルの書き方について参考にしました。
- Minikubeのインストール - Kubernetes
- ローカルで K8s 環境を動かすことが出来る Minikube のインストール手順です。