概要
GKE(Google Container Engine)をでクラスターを構築し、Container Registry(GKEで使えるDockerのPrivate registry)に独自イメージをPush。
その後Podを作成するもうまく立ち上がらず、色々修正したりしてみたけどやっぱりうまくいかず。
さらに色々調べながらやったら最終的にはちゃんと動作したのだけど、結構ハマってしまったのでここに原因と対策を書き留めておこうと思います。
ハマる
やったこと
- ローカルで
docker pull centos:7
してイメージをPull -
docker run -it --name cent1 centos /bin/bash
でターミナルを開いてコンテナ内部でNginx入れたりした -
docker commit cent1 asia.gcr.io/myproject/nginx
で構築済みのコンテナを独自イメージとして固める -
gcloud docker push asia.gcr.io/myproject/nginx
でGKEのContainer RegistryにイメージをPush - 作成しておいたクラスターにこれまた作成しておいたPod(ReplicationController)ファイルからPodを展開
- PodがなかなかREADYにならず、RESTARTを繰り返す(あれ?おかしい。。。)
ちなみにPodファイルの中身は以下のようになっています。
apiVersion: v1
kind: ReplicationController
metadata:
name: nginx-rc
spec:
replicas: 3
selector:
app: nginx-web
template:
metadata:
labels:
app: nginx-web
spec:
containers:
- name: nginx-po
image: asia.gcr.io/myproject/nginx
ports:
- containerPort: 80
原因
この手順を見てわかるように、この独自イメージはDockerfileから作ってないのです。
つまり、おそらくCMDはベースにしたcentosのイメージのまま。。。
CMD ["/usr/sbin/init"]
これがPodで起動したんですね。
ちなみにこれをバックグラウンドで起動してもコンテナはすぐ終了するので、
コンテナ作成
↓
コンテナ起動
↓
すぐ終了
↓
(GKEさんがきちんとお仕事をされて)コンテナを再生成
↓
コンテナ起動
↓
すぐ終了
↓
(GKEさんが、、、)
という挙動を繰り返したと思われます。
さらにハマる
やったこと
-
docker build -t asia.gcr.io/myproject/nginx .
で独自イメージをDockerfileからビルドしてイメージを作成(CMDもつけてNginxが起動するようにした) - 先ほどPushしたイメージはいらないのでContainer Registryから削除(GUIで消した)
-
gcloud docker push asia.gcr.io/myproject/nginx
で再度Container RegistryにイメージをPush - クラスターはそのままでPodを展開
- やはりPodはなかなかREADYにならず、RESTARTを繰り返す(あれあれ?やっぱりおかしい。。。)
原因
色々調べてみると、Kubernetes(GKEが使っている仮想コンテナを制御するサービス)のドキュメントにこんな一文がありました。
all pods can use any images cached on a node
つまり、Nodeにキャッシュされたイメージを使っていたらしいです。
これを回避する為にimagePullPolicy
というのがあるので、それを以下のようにPodファイルに定義してあげると無事解決しました。
apiVersion: v1
kind: ReplicationController
metadata:
name: nginx-rc
spec:
replicas: 3
selector:
app: nginx-web
template:
metadata:
labels:
app: nginx-web
spec:
containers:
- name: nginx-po
image: asia.gcr.io/myproject/nginx
imagePullPolicy: Always ## この行を追加
ports:
- containerPort: 80
※ Note
imagePullPolicyを設定しなくてもimageにlatestタグを定義してあげるとデフォルトがAlwaysになるみたいです。
おさらい
- Podに配置するイメージは適切なCMD(またはENTRYPOINT)を定義したDockerfileからビルドしたイメージを使いましょう。
- デフォルトではPodはNodeにキャッシュされたイメージを使うので、更新が頻繁にあるのならimagePullPolicyを設定するか、latestタグを指定した方が良いでしょう。(更新がほぼないなら当然キャッシュを使ったほうがいいのでそこは良しなに判断して下さい)
最後に
この手のトラブルはググってもあまり出てこず、ここまで解明するのに結構時間を使ってしまったのでポストしておこうかと思いました。(そもそもこんなハマり方は普通しないのかも。。。)
もし誰かのお役にたったら嬉しいです。
おわり