nekop's blog

OpenShift / JBoss / WildFly / Infinispanの中の人 http://twitter.com/nekop

OpenShiftでStatefulSetを使ってみる

OpenShift 全部俺 Advent Calendar 2017

今までは普通のデプロイメントを利用していましたが、今回はちょっと特殊な性格を持つStatefulSetを使ってみましょう。StatefulSetのレプリカは連番のsuffixが付与され、スケール時の順序制御があったりvolumeClaimTemplatesによる個々のPodへそれぞれPVを割り当てたりできます。主にクラスタ系の分散前提のソフトウェアに利用されます。

https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/

StatefulSetはKubernetes 1.8の時点でbeta機能であり、OpenShiftでも3.5から含まれてはいますがまだフルサポートされていません。

いつものRubyプロジェクトをベースにします。

$ oc new-project test-ruby
$ oc new-app http://github.com/nekop/hello-sinatra
$ oc get all
NAME                         TYPE      FROM      LATEST
buildconfigs/hello-sinatra   Source    Git       1

NAME                     TYPE      FROM          STATUS     STARTED          DURATION
builds/hello-sinatra-1   Source    Git@cf28c79   Complete   13 minutes ago   47s

NAME                         DOCKER REPO                                                TAGS      UPDATED
imagestreams/hello-sinatra   docker-registry.default.svc:5000/test-ruby/hello-sinatra   latest    12 minutes ago

NAME                              REVISION   DESIRED   CURRENT   TRIGGERED BY
deploymentconfigs/hello-sinatra   1          1         1         config,image(hello-sinatra:latest)

NAME                       READY     STATUS      RESTARTS   AGE
po/hello-sinatra-1-build   0/1       Completed   0          13m
po/hello-sinatra-1-s2ls7   1/1       Running     0          12m

NAME                 DESIRED   CURRENT   READY     AGE
rc/hello-sinatra-1   1         1         1         12m

NAME                   CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
svc/hello-sinatra      172.30.82.101   <none>        8080/TCP   13m

ここでビルドされたイメージをデプロイするStatefulSetを作ってみましょう。まだbeta機能なのでyamlを直接記述する必要があります。

$ cat <<EOF | oc create -f -
apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
  name: hello-sinatra-ss
spec:
  replicas: 2
  serviceName: hello-sinatra-ss
  template:
    metadata:
      labels:
        app: hello-sinatra-ss
    spec:
      containers:
      - image: docker-registry.default.svc:5000/test-ruby/hello-sinatra:latest
        imagePullPolicy: Always
        name: hello-sinatra-ss
        ports:
        - containerPort: 8080
          protocol: TCP
        resources: {}
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: hello-sinatra-ss
  name: hello-sinatra-ss
spec:
  ports:
  - name: 8080-tcp
    port: 8080
    protocol: TCP
    targetPort: 8080
  selector:
    app: hello-sinatra-ss
EOF

これでStatefulSetが作成され、指定した通りレプリカが2つ起動しています。

$ oc get all
NAME                         TYPE      FROM      LATEST
buildconfigs/hello-sinatra   Source    Git       1

NAME                     TYPE      FROM          STATUS     STARTED              DURATION
builds/hello-sinatra-1   Source    Git@cf28c79   Complete   About a minute ago   47s

NAME                         DOCKER REPO                                                TAGS      UPDATED
imagestreams/hello-sinatra   docker-registry.default.svc:5000/test-ruby/hello-sinatra   latest    About a minute ago

NAME                              REVISION   DESIRED   CURRENT   TRIGGERED BY
deploymentconfigs/hello-sinatra   1          1         1         config,image(hello-sinatra:latest)

NAME                       READY     STATUS      RESTARTS   AGE
po/hello-sinatra-1-build   0/1       Completed   0          1m
po/hello-sinatra-1-s2ls7   1/1       Running     0          1m
po/hello-sinatra-ss-0      1/1       Running     0          12s
po/hello-sinatra-ss-1      1/1       Running     0          9s

NAME                 DESIRED   CURRENT   READY     AGE
rc/hello-sinatra-1   1         1         1         1m

NAME                   CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
svc/hello-sinatra      172.30.82.101   <none>        8080/TCP   1m
svc/hello-sinatra-ss   172.30.165.8    <none>        8080/TCP   12s

NAME                            DESIRED   CURRENT   AGE
statefulsets/hello-sinatra-ss   2         2         12s