Kekeの日記

エンジニア、読書なんでも

PodのInitContainerとNode(GCE)のStartupScript

f:id:bobchan1915:20181007155511p:plain

本記事

本記事では、たまたま趣味で使っているKubernetesで、PodやNodeを立ち上げた時に実行したい起動スクリプトのようなものがあります。

今回はどのようにそれを実現できるかを調べていた時にInitContainerとStartupScriptを知ったので、今回はその使い方を解説したいと思います。

内容

PodのInitContainer

InitContainerとは

以下の用語を定義します。

  • InitContainer: InitContainer用のコンテナ
  • AppContainer: アプリケーション用のコンテナ

このときにInitContainerはAppContainerよりも先に実行され、主にはAppContainerのための準備に使われたりします。

また、一つ以上のInitContainerを含むことができ、ランタイム中では一つずつ実行される。

注意点

以下の注意点があります。

  • InitContainerはKuberenetesのJobのようにCompletionを目指してなるように実行されるため実装もそうしないといけない
  • AppContainerが起動されるには、すべてのInitContainerがSUCCESSしないといけない

追加方法

InitContainerを追加するにはspec.initContainersを追加し以下のようにします。

1.6以上から

apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app: myapp
spec:
  containers:
  - name: myapp-container
    image: busybox
    command: ['sh', '-c', 'echo The app is running! && sleep 3600']
  initContainers:
  - name: init-myservice
    image: busybox
    command: ['sh', '-c', 'until nslookup myservice; do echo waiting for myservice; sleep 2; done;']
  - name: init-mydb
    image: busybox
    command: ['sh', '-c', 'until nslookup mydb; do echo waiting for mydb; sleep 2; done;']

もちろん普通のPodと同様にResource Request、Security、Volumnなどを定義することができますが、Resource Requestの使い方が少し違うので詳しくは参考文献をご覧ください。

NodeのStartupScript

StartupScript

GKEではデフォルトではStartupScriptは実現できません。

なのでDaemonSetを配置することで実現できます。

DaemonSet

以下のようなDaemonSetを渡します。

kind: DaemonSet
apiVersion: extensions/v1beta1
metadata:
  name: startup-script
  labels:
    app: startup-script
spec:
  template:
    metadata:
      labels:
        app: startup-script
    spec:
      hostPID: true
      containers:
        - name: startup-script
          image: gcr.io/google-containers/startup-script:v1
          imagePullPolicy: Always
          securityContext:
            privileged: true
          env:
          - name: STARTUP_SCRIPT
            value: |
              #! /bin/bash
              set -o errexit
              set -o pipefail
              set -o nounset
              touch /tmp/foo
              echo done

ここではShell Scriptが渡されています。

NodePoolにStartupScriptを

Node PoolはKuberenetesクラスタが使用するNode群を定義されたものです。

以下のようにしてStartupScriptを渡します。

gcloud container node-pools create hoge-pool --metadata-from-file startup-script=scripts/install.sh

これによってdefault-poolに起動スクリプトがついたものをNode Poolとして設定できました。

もちろんNode Poolは変更されるような対象ではないので既存のものには起動スクリプトを定義することはできないようです。

既存のPodのスケジュールをかえたいときはkubectl drainを使うといいでしょう。以下の記事を参照ください。

www.1915keke.com

Podに書き込まれるServiceの環境変数

PodがNodeにスケジュールされた時、有効なServiceについてそれぞれ環境変数をセットする。

たとえばService名がredis-masterだとすると

REDIS_MASTER_SERVICE_HOST=10.0.0.11
REDIS_MASTER_SERVICE_PORT=6379
REDIS_MASTER_PORT=tcp://10.0.0.11:6379
REDIS_MASTER_PORT_6379_TCP=tcp://10.0.0.11:6379
REDIS_MASTER_PORT_6379_TCP_PROTO=tcp
REDIS_MASTER_PORT_6379_TCP_PORT=6379
REDIS_MASTER_PORT_6379_TCP_ADDR=10.0.0.11

の様にセットされます。

Services - Kubernetes

Podの情報をContainerに渡す方法

以下の記事で解説しているのでご覧ください。

TODO: Paste article

参考文献

Init Containers - Kubernetes

github.com

https://cloud.google.com/compute/docs/startupscript?hl=JA