GKEへExpressを立ち上げる

概要

社内LT会でK8sのライブデプロイをするためのチートシート

構成

f:id:y-ohgi:20190327175012p:plain

手順

Expressプロジェクトを作成

Express作成用Dockerを立ち上げ

$ docker run -it -p 3000:3000 -v `pwd`:/data -w /data node:10-alpine ash

express コマンドをインストールし、プロジェクトを作成

# npm install -g express-generator
# express myapp

Expressを起動する

# cd myapp
# npm install
# npm start

ローカルにExpressのコードが展開されていることを確認

$ ls
myapp
$ ls myapp/
bin             node_modules       package.json      routes
app.js          package-lock.json  public            views

Expressのコードを編集

ホストネームを表示させるようにして、複数台コンテナを立てたときに別のコンテナにアクセスできていることを確認できるようにする

var express = require('express');
var router = express.Router();
+var os = require('os')

/* GET home page. */
router.get('/', function(req, res, next) {
-  res.render('index', { title: 'Express' });
+  res.render('index', { title: os.hostname() });
});

module.exports = router;

Dockerの作成とpush

emacsを開いてDockerfileの作成

$ cd myapp
$ emacs
FROM node:10-alpine

WORKDIR /app

COPY package.json package-lock.json /app/

RUN npm install

COPY . .

CMD ["npm", "start"]
$ docker build -t myapp .
$ docker run -p 3000:3000 myapp

http://localhost:3000 へアクセスして確認

f:id:y-ohgi:20190327113434p:plain

GCRへ作成したイメージにtagを付与し、push

$ prjid=$(gcloud config get-value project)
$ docker tag myapp asia.gcr.io/${prjid}/myapp
$ gcloud auth configure-docker
$ docker push asia.gcr.io/${prjid}/myapp

GKE Clusterの作成

gcloud beta container clusters create "standard-cluster-1" \
  --zone "asia-northeast1-a" \
  --cluster-version "latest" \
  --num-nodes "3" \
  --addons HorizontalPodAutoscaling,HttpLoadBalancing,Istio \
  --istio-config auth=MTLS_PERMISSIVE

デプロイ

GCRへ上げたイメージを使ってDeploymentを作成

$ kubectl run myapp --image=asia.gcr.io/${prjid}/myapp
$ kubectl get pods
NAME                     READY   STATUS    RESTARTS   AGE
myapp-7968fd7bb9-9lx2j   1/1     Running   0          5m45s
$ k port-forward pod/myapp-7968fd7bb9-9lx2j :3000
Forwarding from 127.0.0.1:54071 -> 3000
Forwarding from [::1]:54071 -> 3000

公開

ServiceとIngressを作成し、作成したPodを公開する マニフェストファイルを作成して、それをもとにapplyする

$ kubectl apply -f manifest.yaml
# manifest.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    run: myapp
  name: myapp
spec:
  replicas: 2
  selector:
    matchLabels:
      run: myapp
  template:
    metadata:
      labels:
        run: myapp
    spec:
      containers:
      - image: asia.gcr.io/<YOUR PROJECT ID>/myapp
        name: myapp

---
apiVersion: v1
kind: Service
metadata:
  labels:
    run: myapp
  name: myapp
spec:
  ports:
  - port: 3000
    protocol: TCP
    targetPort: 3000
  selector:
    run: myapp
  type: NodePort

---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: myapp
  labels:
    run: myapp

spec:
  backend:
    serviceName: myapp
    servicePort: 3000

確認する

$ kubectl get all
NAME                         READY   STATUS    RESTARTS   AGE
pod/myapp-7968fd7bb9-89b6b   1/1     Running   0          11m
pod/myapp-7968fd7bb9-9lx2j   1/1     Running   0          13m

NAME                 TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)          AGE
service/kubernetes   ClusterIP   10.3.240.1    <none>        443/TCP          66m
service/myapp        NodePort    10.3.255.12   <none>        3000:32646/TCP   11m

NAME                    DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/myapp   2         2         2            2           13m

NAME                               DESIRED   CURRENT   READY   AGE
replicaset.apps/myapp-7968fd7bb9   2         2         2       13m
$ kubectl get ing
NAME    HOSTS   ADDRESS         PORTS   AGE
myapp   *       35.190.83.144   80      11m

お片付け

クラスタの削除

$ gcloud beta container clusters delete standard-cluster-1 --zone "asia-northeast1-a" 

Dockerイメージの削除

$ gcloud container images list --repository asia.gcr.io/${prjid}
NAME
asia.gcr.io/<YOUR PROJECT ID>/myapp
$ gcloud container images delete asia.gcr.io/${prjid}/myapp
$ gcloud container images list --repository asia.gcr.io/${prjid}
Listed 0 items.