アプリケーションを開発している際や、既存のアプリケーションをkubernetes上で稼働できるように置き換えをしていく起動順序に他のアプリケーションとの兼ね合いで、Podが再起動を繰り返す(=CrashLoopBackOff)するケースがあります。そのようなケースには、InitContainerを使って解決するのが良いので、紹介します。
よくあるケース
アプリケーションの起動シーケンスでは、下記のようなことが多いかと思います。
- DBアクセス(コネクション生成)
- メッセージブローカ初期化 + コネクション生成
- 他サービスとのコネクション生成
など、依存先のアプリケーションがすでに立ち上がっていることを前提にするケースが多いです。
postgresを例に具体的に考えてみる
下記例は、postgresをDBを生成するサービス、Statefullsets, Podのマニュフェスト例です。
apiVersion: v1
kind: Service
metadata:
name: postgres-svc
spec:
ports:
- port: 5432
selector:
app: postgres
clusterIP: None
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres-sts
spec:
serviceName: postgres-svc
replicas: 1
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:latest
ports:
- containerPort: 5432
env:
- name: POSTGRES_USER
value: dmin
- name: POSTGRES_PASSWORD
value: admin
- name: PGDATA
value: /var/lib/postgresql/data/pgdata
- name: POSTGRES_DB
value: sample
volumeMounts:
- name: postgres-pvc
mountPath: /var/lib/postgresql/data/pgdata
subPath: postgres
volumeClaimTemplates:
- metadata:
name: postgres-pvc
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 3Gi
StatefullsetsでPodを起動するケースは、起動に少し時間がかかります。下記のようなコンテナを同時に起動してまうと、“CrashLoopBackOff”を繰り返し、kubectl get pods等で確認するとRESTARTS回数が増えていきます。
apiVersion: v1
kind: Pod
metadata:
name: sample-app
spec:
containers:
- image: xxxx:latest # DBアクセスするアプリ
name: sample
kubernetesには、Init Containersという仕組みがあります。このInit Containersは、Pod内でメインとなるコンテナを起動する前に別のコンテナを起動させる機能です。この機能を使うことで、DBアクセス可能になるまでまつことが可能になります。
apiVersion: v1
kind: Pod
metadata:
name: sample-app
spec:
initContainers:
- name: check-db-ready
image: postgres:latest
command: ['sh', '-c',
'until pg_isready -h postgres-svc -p 5432;
do echo waiting for database; sleep 2; done;']
containers:
- image: xxxx:latest # DBアクセスするアプリ
name: nginx
このようにすることで、postgresが立ち上がって、通信できる状態になるまで待つことができます。initContainers自体、containersと同様、複数のPodを記載することができます。 他の利用方法としては、自動テストなどで利用するデータの投入処理なんかにも利用可能です。このようにすることで、メインのコンテナは、必要な処理だけ記載できます。
今回は、kubernetes利用時によく出るエラー”CrashLoopBackOff”の対処方法の一つとして、initContainersを紹介しました。お疲れさまでした。

