GKE上にwebアプリケーションを構築する方法

記事の目的
 
- GKEについての紹介
- 簡単なwebアプリケーションを構築して、GKEにデプロイする方法の紹介

# A. GKEの概要

Googleを中心に開発されているDockerコンテナの管理ソフトウェアKubernetes（k8s）のクラスタを簡単にデプロイできるサービスです。Dockerコンテナの実行にはGCE(Google Compute Engine)を利用します。

各基本概念

## クラスタ（Cluster）

クラスタは１つの小さいクラウドと考えることができます。なぜかと言うとクラスタの中でVMからネットワーク、アクセス権限など色々なリソースを設定とコントロールできるからです。

クラスタは複数Nodeで構成されて、各Node間に内部ネットワークがあります。
![devsamurai_gcp_gke_kubernetes_001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535698/05332f9d-b053-d2d5-0552-34213172c8dc.png)

## Node

Nodeは１つのVMです。マスターNodeとワーカーNodeがあります。ワーカーNode上にkubeletサービスが稼働されていて、マスターNodeからコントロール信号を受け取ります。

## Pod

Podはk8sの中でコントロールできる一番小さい単位です。通常Podは１つのアプリケーションまたは１つの稼働できる単位モジュールです。利用の目的及び稼働アプリケーションのタイプによって違うPodの種類を利用しないといけません。各種のPodの具体的は下記のリンクを参考にしてください。
https://kubernetes.io/docs/concepts/workloads/controllers/

 

まとめると、クラスタはk8s上に仮想ネットワークで複数VMが繋がれていて、小さいバージョンのクラウドが作られます。クラスタに色々なアプリケーションをデプロイでき、スケールイン・アウト設定が出来ます。アプリケーションはどのNodeで稼働されるかと考える必要はなく、全てk8sがコントロールします。

# B. webアプリケーションをGKEにデプロイする方法 

* webアプリケーション作成. 
* Dockerイメージをビルドする
* DockerイメージをGCP Container Registryにプッシュする
* Container RegistryからGKEにデプロイする

## 1. webアプリケーション作成

この記事中では、golangを利用して、labstack echoフレームワークでwebアプリケーションを作成します。


```golang:アプリケーションのフォルダ構成
simplewebapp
├── README.md
├── go.mod
├── go.sum
├── simplewebapp.Dockerfile
├── simplewebapp.deployment.yaml
└── webapp
    ├── handler
    │   └── simplewebapp_handler.go
    └── simplewebapp.go
```

```golang:simplewebapp.go
package main

import (
	"github.com/labstack/echo/v4"
	"github.com/labstack/echo/v4/middleware"

	"github.com/devsamurai/gke/simplewebapp/webapp/handler"
)

// Default Server Port
const DEFAULT_SERVER_PORT = ":80"

func main() {
	// Echo instance
	e := echo.New()

	// Middleware
	e.Use(middleware.Logger())
	e.Use(middleware.Recover())
	e.Use(middleware.CORS())

	// Route => handler
	e.GET("/", handler.SimpleWebHandler{}.Index)

	e.GET("/ping", handler.SimpleWebHandler{}.Ping)

	// Start server
	e.Logger.Fatal(e.Start(DEFAULT_SERVER_PORT))
}
```

```golang:simplewebapp_handler.go
package handler

import (
	"net/http"

	"github.com/labstack/echo/v4"
)

type SimpleWebHandler struct {
}

func (sh SimpleWebHandler) Index(c echo.Context) error {
	return c.String(http.StatusOK, "Hello, World!\n")
}

func (sh SimpleWebHandler) Ping(c echo.Context) error {
	return c.String(http.StatusOK, "Pong!\n")
}
```


```golang:ローカルで実行してみる
cd path_to_simplewebapp
go run webapp/simplewebapp.go
```
<img width="589" alt="devsamurai_gcp_gke_kubernetes_002.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535698/926c6e1a-f9a7-fa7b-3910-0d91bc405137.png">


## 2. Dockerイメージをビルドする

Dockerfileを準備する


```golang:simplewebapp.Dockerfile
FROM golang:1.12 as build_env

WORKDIR /go/src/github.com/devsamurai/gke/simplewebapp

COPY ./webapp ./webapp
COPY go.mod ./
COPY go.sum ./

ENV PATH="${PATH}:$GOPATH/bin"
ENV GO111MODULE=on

RUN export GOPROXY="https://proxy.golang.org" && export GO111MODULE=on && go test ./...
RUN export GOPROXY="https://proxy.golang.org" && export GO111MODULE=on && CGO_ENABLED=0 go build -o simplewebapp webapp/simplewebapp.go

FROM alpine:latest
WORKDIR /app
COPY --from=build_env /go/src/github.com/devsamurai/gke/simplewebapp /app

EXPOSE 80
ENTRYPOINT ["./simplewebapp"]
```


```golang:Dockerイメージをビルドする
# Dockerを事前に起動する必要は注意
cd path_to_simplewebapp

# tag nameがあるdocker imageをビルド
docker build -t ds-gke-simplewebapp:lasters -f simplewebapp.Dockerfile .

# ビルド後の確認
docker images
> REPOSITORY                         TAG                 IMAGE ID            CREATED             SIZE
> ds-gke-simplewebapp                lasters             1e2055780000        12 minutes ago      17.1MB
```

## 3. DockerイメージをGCP Container Registryにプッシュする

前提： GCPとgcloudコマンドの利用経験があることが望ましい。

```golang:ContainerRegistryに登録
# ログイン、とワーキングProjectを設定
gcloud auth login
gcloud config set project [PROJECT_ID]

# ロカルDockerはGCPにアクセスするため、GCPのcredentialを設定
gcloud auth configure-docker

# ロカルイメージをレポジトリのタグ名を付ける 
# docker tag [SOURCE_IMAGE] [HOSTNAME]/[PROJECT-ID]/[IMAGE]:[TAG]
docker images
> REPOSITORY                         TAG                 IMAGE ID            CREATED             SIZE
> ds-gke-simplewebapp                lasters             1e2055780000        25 minutes ago      17.1MB

docker tag 1e2055780000 asia.gcr.io/ds-project/ds-gke-simplewebapp:lasters

# タグ名の確認
docker images
> REPOSITORY                                    TAG                 IMAGE ID            CREATED             SIZE
> asia.gcr.io/ds-project/ds-gke-simplewebapp   lasters             1e2055780000        26 minutes ago      17.1MB

# DockerイメージをContainer Registryにプッシュする
# docker push [HOSTNAME]/[PROJECT-ID]/[IMAGE]
docker push asia.gcr.io/ds-project/ds-gke-simplewebapp
```

Container Registry上にイメージを確認
<img width="884" alt="devsamurai_gcp_gke_kubernetes_003.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535698/e244f7c5-e226-d2cb-510f-595b838a28c0.png">

## 4. Container RegistryからGKEにデプロイする

```golang:GKEのクラスタを作成する
gcloud container clusters create ds-gke-small-cluster \
	--project ds-project \
	--zone asia-northeast1-b \
	--machine-type n1-standard-1 \
	--num-nodes 1 \
	--enable-stackdriver-kubernetes
```

デプロイメント定義ファイルを準備する。

```golang:simplewebapp.deployment.yaml
apiVersion: v1
kind: Service
metadata:
  name: simple-webapp-service
spec:
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
    name: http
  selector:
    app: simple-webapp
  type: LoadBalancer
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: simple-webapp
spec:
  replicas: 2
  template:
    metadata:
      labels:
        app: simple-webapp
    spec:
      containers:
      - name: simple-webapp
        image: asia.gcr.io/ds-project/ds-gke-simplewebapp:lasters
        ports:
          - containerPort: 80
```

このデプロイメント定義ファイルは、１つのLoad Balancing作成、ポート80で公開する。webアプリケーションは後ろの２つのContainersで稼働する。



```golang:GKEにデプロイ
# k8sコントロールツールをインストール
gcloud components install kubectl
kubectl version

# GKEのクラスタにアクセスするため、credentialsを設定
gcloud container clusters get-credentials --zone asia-northeast1-b ds-gke-small-cluster

# GKEにアプリケーションを設定する
kubectl apply -f simplewebapp.deployment.yaml
```

デプロイ後、結果確認

Load Balancing
<img width="1138" alt="devsamurai_gcp_gke_kubernetes_004.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535698/c3c80a41-1e66-b88f-a2da-ad0630029731.png">

webアプリケーションを稼働するPod
<img width="926" alt="devsamurai_gcp_gke_kubernetes_005.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535698/a0d46ced-e4eb-5de7-25c0-cb4fdb8a60ed.png">



```golang:外からwebアプリケーションにアクセス確認
curl http://34.85.10.96/
> Hello, World!
```

ソースコード参照
[https://github.com/dssolutioninc/dss_gke/tree/master/simplewebapp](https://github.com/dssolutioninc/dss_gke/tree/master/simplewebapp )

 

最後まで読んで頂き、どうも有難う御座います!
DSS 橋本