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に詳しいわけではないので、実運用ではこうしていてこの処理はいらないなど改善策があればコメント頂けると幸いです。