MEAN StackをKubernetesで動かす(その1)
前回はMEAN StackをDocker Composeで動かしてみました。
hi1280.hatenablog.com
今回はMEAN StackをKubernetesで動かします。
Dockerに対応したので、Kubernetesでも動くようになっているはずです。試してみます。
なお、今回のKubernetesの環境はGKE(Google Kubernetes Engine)を使用します。
手軽にKubernetes環境が用意できるので、試しに使ってみるには良いと思います。
無料のトライアル期間もあります。
MEAN Stackのプログラム一式はこちら
github.com
Docker Composeの時と似たような構成でAngularとExpressとMongoDBを動かします。
実運用に耐えうることを想定して、以下の内容を含めます。
- MongoDBは可用性を高めるためにReplica Setで構成する
- 外部公開を考慮して、HTTPS対応を行う
HTTPS対応の話は次回に行います。今回はHTTPでアクセスするところまでです。
事前準備
GKEを利用するために、GCP(Google Cloud Platform)用のコマンドラインツール(gcloud)をインストールします。
Quickstarts | Cloud SDK | Google Cloud
kubectlコマンドをインストールします。
Quickstart | Kubernetes Engine Documentation | Google Cloud
gcloudコマンドでKubernetesクラスタを構築します。
$ gcloud container clusters create mean-example
MongoDBのセットアップ
MongoDBを作成する前にデータを保存するディスクを準備する必要があります。
ディスクの設定
何のディスクを利用するのかを決めるためにStorageClassを作成します。
ここでは、GCE(Google Compute Engine)のディスクを利用するように設定します。
gce-storageclass.yml
kind: StorageClass apiVersion: storage.k8s.io/v1 metadata: name: slow provisioner: kubernetes.io/gce-pd parameters: type: pd-standard
$ kubectl apply -f gce-storageclass.yml
MongoDBの作成
Replica Setで認証を行うためにkeyfileを用意します。
KubernetesのSecretに登録します。
$ TMPFILE=$(mktemp) $ /usr/bin/openssl rand -base64 741 > $TMPFILE $ kubectl create secret generic shared-bootstrap-data --from-file=internal-auth-mongodb-keyfile=$TMPFILE $ rm $TMPFILE
Replica Setにおける認証の参考情報
Internal Authentication — MongoDB Manual
MongoDB用のStatefulSetとServiceを作成します。
mongodb-service.yml
apiVersion: v1 kind: Service metadata: name: mongodb-service labels: name: mongo spec: ports: - port: 27017 targetPort: 27017 clusterIP: None selector: role: mongo --- apiVersion: apps/v1 kind: StatefulSet metadata: name: mongod spec: selector: matchLabels: role: mongo serviceName: mongodb-service replicas: 3 template: metadata: labels: role: mongo environment: test replicaset: MainRepSet spec: terminationGracePeriodSeconds: 10 volumes: - name: secrets-volume secret: secretName: shared-bootstrap-data defaultMode: 256 containers: - name: mongod-container image: mongo:3.4.16-jessie command: - "mongod" - "--bind_ip" - "0.0.0.0" - "--replSet" - "MainRepSet" - "--auth" - "--clusterAuthMode" - "keyFile" - "--keyFile" - "/etc/secrets-volume/internal-auth-mongodb-keyfile" - "--setParameter" - "authenticationMechanisms=SCRAM-SHA-1" ports: - containerPort: 27017 volumeMounts: - name: secrets-volume readOnly: true mountPath: /etc/secrets-volume - name: mongodb-persistent-storage-claim mountPath: /data/db volumeClaimTemplates: - metadata: name: mongodb-persistent-storage-claim annotations: volume.beta.kubernetes.io/storage-class: "slow" spec: accessModes: [ "ReadWriteOnce" ] resources: requests: storage: 10Gi
ServiceはHeadless Serviceで作成します。
この後にReplica Setの設定を行う際に、PodのIPアドレスを知る必要があるためです。
StatefulSetではMongoDBコンテナが起動する3つのPodを作成します。
3つのPodがReplica Setで利用されます。
mongod
コマンドで、事前に作成したSecretを利用して認証を有効にします。
volumeClaimTemplates
で先ほどのStorageClassを指定しています。
Pod毎に10Gのディスクが設定されます。
$ kubectl apply -f mongodb-service.yml
MongoDBの設定
PrimaryになるMongoDBに接続します。
$ kubectl exec -it mongod-0 -c mongod-container bash $ mongo
Replica Setを設定します。
> rs.initiate({_id: "MainRepSet", version: 1, members: [ { _id: 0, host : "mongod-0.mongodb-service:27017" }, { _id: 1, host : "mongod-1.mongodb-service:27017" }, { _id: 2, host : "mongod-2.mongodb-service:27017" } ]})
ユーザを作成します。
> db.getSiblingDB("admin").createUser({ user : "xxx", pwd : "xxx", roles: [ { role: "root", db: "admin" } ] }) > use admin > db.auth("xxx","xxx") > db.getSiblingDB("my-heroes").createUser({ user : "xxx", pwd : "xxx", roles: [{role:"readWrite", db: "my-heroes"}] })
ユーザ、パスワードは適宜設定する。
Angular+Expressの作成
Expressを作成します。
webapp-backend-service.yml
apiVersion: v1 kind: Service metadata: name: webapp-backend-service labels: name: webapp-backend spec: type: ClusterIP ports: - protocol: 'TCP' port: 3000 targetPort: 3000 selector: app: webapp-backend --- apiVersion: apps/v1 kind: Deployment metadata: name: webapp-backend spec: replicas: 1 selector: matchLabels: app: webapp-backend template: metadata: labels: app: webapp-backend spec: containers: - name: webapp-backend image: asia.gcr.io/arched-photon-204013/mean-example_backend:latest ports: - containerPort: 3000 env: - name: PORT value: '3000' - name: MONGODB_URI value: 'mongodb://xxx:xxx@mongod-0.mongodb-service:27017,mongod-1.mongodb-service:27017,mongod-2.mongodb-service:27017/my-heroes?replicaSet=MainRepSet'
コンテナレジストリにはGCR(Google Container Registry)を利用しています。
前回のExpress実行用のDockerfileから作成したイメージです。
Replica SetのMongoDBに接続するため、3つのMongoDBをホスト名で指定しています。
$ kubectl apply -f webapp-backend-service.yml
Angularを作成します。
webapp-frontend-service.yml
apiVersion: v1 kind: Service metadata: name: webapp-frontend-service labels: app: webapp-frontend spec: type: NodePort ports: - name: "http-port" protocol: "TCP" port: 80 targetPort: 80 selector: app: webapp-frontend --- apiVersion: apps/v1 kind: Deployment metadata: name: webapp-frontend spec: replicas: 1 selector: matchLabels: app: webapp-frontend template: metadata: labels: app: webapp-frontend spec: containers: - name: webapp-frontend image: asia.gcr.io/arched-photon-204013/mean-example_frontend:latest ports: - containerPort: 80 env: - name: APP_HOST value: 'webapp-backend-service' - name: APP_PORT value: '3000' command: ['/bin/sh'] args: ['-c', "envsubst '$$APP_HOST$$APP_PORT' < /etc/nginx/conf.d/default.conf.template > /etc/nginx/conf.d/default.conf && exec nginx -g 'daemon off;'"]
HTTPSに対応するためにIngressを利用することになります。Ingressを利用するためには、事前にNodePortのServiceを作成しておく必要があります。
コンテナイメージに関しては、前回のAngularアプリ実行用のDockerfileから作成したイメージです。
$ kubectl apply -f webapp-frontend-service.yml
外部からの疎通が可能なネットワークの設定
Ingressを作成します。
ingress.yml
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: webapp-service labels: app: webapp spec: backend: serviceName: webapp-frontend-service servicePort: 80
backend
では先ほど作成したNodePortのServiceを指定しています。
$ kubectl apply -f ingress.yml
Ingressを作成することで、GCLB(Google Cloud Load Balancer)が設定されます。
$ kubectl get ingress NAME HOSTS ADDRESS PORTS AGE webapp-service * xxx.xxx.xxx.xxx 80 5m
5分ほどで静的IPアドレスが割り当てられて、アクセスできるようになります。
HTTPS対応の話は次回に。
参考にした資料
Kubernetesの基礎情報 thinkit.co.jp
MongoDBのKubernetes対応 pauldone.blogspot.com