docker-composeでのdepends_onに対応した機能は、kubernetesではデフォルトではサポートされていません。本記事は、それを解決する手法についてです。
Deployment.yaml
app1がdbに依存しているという状況を考えます。何も考えずにmanifestを書くと、以下のようになるかと思います。
apiVersion: apps/v1
kind: Deployment
metadata:
name: app1
labels:
app-name: app1
namespace: ns
spec:
replicas: 1
selector:
matchLabels:
app-name: app1
template:
metadata:
labels:
app-name: app1
name: app1
spec:
containers:
- name: app1
image: SOME_API_IMAGE
restartPolicy: Always
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: db
labels:
app-name: db
namespace: ns
spec:
replicas: 1
selector:
matchLabels:
app-name: db
template:
metadata:
labels:
app-name: db
name: db
spec:
containers:
- name: db
image: mongo:4.2.21
restartPolicy: Always
しかし、これでは起動順が保証されないため、app1が正しく起動しないということが容易に起こります。そこで、app1にInitContainersの記述を追加することで、起動を遅延させます。そこでは、experimentalな機能として追加されているkubectl waitを用います。すると、以下のような形になります。
apiVersion: apps/v1
kind: Deployment
metadata:
name: app1
labels:
app-name: app1
namespace: ns
spec:
replicas: 1
selector:
matchLabels:
app-name: app1
template:
metadata:
labels:
app-name: app1
name: app1
spec:
containers:
- name: app1
image: SOME_API_IMAGE
restartPolicy: Always
initContainers:
- name: wait-for-deps
image: bitnami/kubectl:1.24
imagePullPolicy: IfNotPresent
command:
- /bin/sh
- -exc
- kubectl wait pods --for=condition=Ready -n ns -l "app-name in (${APP_NAMES})"
env:
- name: APP_NAMES
value: db
ここで、環境変数APP_NAMESはdb1, db2のように複数指定できます。
ClusterRole.yaml
この段階では以下のエラーメッセージにより、エラーが出るかと思います。
Error from server (Forbidden): pods is forbidden: User "system:serviceaccount:ns:default" cannot list resource "pods" in API group "" in the namespace "ns"
これは権限不足のエラーになるので、以下のようにRoleを設定してあげます。
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: pod-reader
labels:
death-star-project: ns
namespace: ns
rules:
- apiGroups: [""]
resources: ["services", "endpoints", "pods"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: pod-reader
labels:
death-star-project: ns
namespace: ns
subjects:
- kind: ServiceAccount
name: default
namespace: ns
roleRef:
kind: Role
name: pod-reader
apiGroup: ""
以上操作により、db→app1の順番で起動することが保証されたmanifestを作成することができます。
おわりに
自分はそこまでk8sに詳しいわけではないので、実運用ではこうしていてこの処理はいらないなど改善策があればコメント頂けると幸いです。