GKE(Google Kubernetes Engine)クラスタにアプリをデプロイする

2023.01.27

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、yagiです。

今回は、Cloud Shell を起動して、Google Cloud の GKE(Google Kubernetes Engine)クラスタにアプリをデプロイする手順について記載します。

Cloud Shell 、とっても便利で使いやすい!

Kubernetes とは

Kubernetes は、コンテナー化されたアプリケーションを必要な場所でいつでも実行できるようにし、動作に必要なリソースとツールを見つけるのに役立ちます。Kubernetes は、コンテナ オーケストレーションにおける Google の蓄積された経験と、コミュニティからの最善のアイデアを組み合わせて設計された、本番環境に対応したオープン ソース プラットフォームです。

Kubernetes の基本

Pod と Service と Ingress(ざっくり)

Pod は、ホスト上で実行できるコンテナーのコレクションです。1つのPodに複数のコンテナを稼働することができます。Pod は Kubernetes の最小単位と定義されています。

Service は、デプロイしたPod をクラスター外部へ公開するためのリソースとなります。複数の Pod に対し、ロードバランサーなどを利用して、単一のDNS名でアクセス可能となり、正常稼働している Pod のみにアクセスできるようになります。

Service の手前に Ingress を置くと、Ingressは、クラスターの外部からクラスター内のサービスにHTTP および HTTPS ルートを公開 します。トラフィック ルーティングは、Ingress リソースで定義されたルールによって制御されます。

以下のイメージとなります。

What is Ingress?より引用

やってみる

プロジェクトセレクタでプロジェクトを選択し、Artifact Registry and Google Kubernetes Engine API を有効にします。

Cloud Shell を起動する

コンソールからCloud Shell を起動します。

しかも、鉛筆マークを押下すると、エディタ を開くことができます。これがすごく便利!

GKE クラスタを作成する

hello-cluster という名前の Autopilot クラスタを作成します。

$ gcloud container clusters create-auto hello-cluster --region=us-west1
Note: The Pod address range limits the maximum size of the cluster. Please refer to https://cloud.google.com/kubernetes-engine/docs/how-to/flexible-pod-cidr to learn how to optimize IP address allocation.
Creating cluster hello-cluster in us-west1... Cluster is being health-checked...done.     
Created [https://container.googleapis.com/v1/projects/XXXX/zones/us-west1/clusters/hello-cluster].
To inspect the contents of your cluster, go to: https://console.cloud.google.com/kubernetes/workload_/gcloud/us-west1/hello-cluster?project=XXXX
kubeconfig entry generated for hello-cluster.
NAME: hello-cluster
LOCATION: us-west1
MASTER_VERSION: 1.24.8-gke.2000
MASTER_IP: 35.233.164.192
MACHINE_TYPE: e2-medium
NODE_VERSION: 1.24.8-gke.2000
NUM_NODES: 3
STATUS: RUNNING

クラスタの認証情報を取得する

$ gcloud container clusters get-credentials hello-cluster --region us-west1
Fetching cluster endpoint and auth data.
kubeconfig entry generated for hello-cluster.

このコマンドにより、作成したクラスタを使用するように kubectl が構成されます。

アプリケーションをクラスタにデプロイする

Deployment を作成、公開します。

$ kubectl create deployment hello-server \
    --image=us-docker.pkg.dev/google-samples/containers/gke/hello-app:1.0
deployment.apps/hello-server created
$ kubectl expose deployment hello-server --type LoadBalancer --port 80 --target-port 8080
service/hello-server exposed

--type LoadBalancer で、コンテナに Compute Engine ロードバランサが作成されます。インターネット用に公開ポート 80が初期化され、アプリケーションのポート 8080 にトラフィックがルーティングされます。

アプリケーションを検査して表示する

実行中の Pod を検査します。

$ kubectl get pods
NAME                            READY   STATUS    RESTARTS   AGE
hello-server-7cc77d5467-vqv5x   1/1     Running   0          4m49s

クラスタで 1 つの hello-server Pod が実行されていることが確認できます。

Service を検査するには、kubectl get service を使用します。

$ kubectl get service hello-server
NAME           TYPE           CLUSTER-IP     EXTERNAL-IP    PORT(S)        AGE
hello-server   LoadBalancer   10.104.2.137   35.197.80.73   80:30874/TCP   6m13s

外部 IP アドレスと公開ポートを指定して、ウェブブラウザでアプリケーションを表示します。

なお、デプロイしたhello-app は、以下の 2 つのファイル(main.go と Dockerfile)で構成されるシンプルなウェブサーバー アプリケーションとなっています。

main.go

package main

import (
        "fmt"
        "log"
        "net/http"
        "os"
)

func main() {
        // register hello function to handle all requests
        mux := http.NewServeMux()
        mux.HandleFunc("/", hello)

        // use PORT environment variable, or default to 8080
        port := os.Getenv("PORT")
        if port == "" {
                port = "8080"
        }

        // start the web server on port and accept requests
        log.Printf("Server listening on port %s", port)
        log.Fatal(http.ListenAndServe(":"+port, mux))
}

// hello responds to the request with a plain-text "Hello, world" message.
func hello(w http.ResponseWriter, r *http.Request) {
        log.Printf("Serving request: %s", r.URL.Path)
        host, _ := os.Hostname()
        fmt.Fprintf(w, "Hello, world!\n")
        fmt.Fprintf(w, "Version: 1.0.0\n")
        fmt.Fprintf(w, "Hostname: %s\n", host)
}

Dockerfile

# Copyright 2022 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

FROM golang:1.19.2 as builder
WORKDIR /app
RUN go mod init hello-app
COPY *.go ./
RUN CGO_ENABLED=0 GOOS=linux go build -o /hello-app

FROM gcr.io/distroless/base-debian11
WORKDIR /
COPY --from=builder /hello-app /hello-app
ENV PORT 8080
USER nonroot:nonroot
CMD ["/hello-app"]

感想

単一のPod と Service のみのシンプルなGKEクラスタにアプリをデプロイして公開する手順を、Cloud Shellを起動して実施してみました。

次回はIngress を使用したルール制御や、複数サービスへのfanout構成なども試してみたいなと思います。

参考

kubernetes

アプリを GKE クラスタにデプロイする

Kubernetes on AWS ~アプリケーションエンジニア 本番環境へ備える