Men-deploy aplikasi dalam image container ke cluster GKE


Halaman ini menunjukkan cara melakukan hal berikut:

  1. Membuat aplikasi Halo Dunia.
  2. Memaketkan aplikasi ke dalam image container menggunakan Cloud Build.
  3. Membuat cluster di Google Kubernetes Engine (GKE).
  4. Men-deploy image container ke cluster Anda.

Contoh ini ditampilkan dalam beberapa bahasa, tetapi Anda dapat menggunakan bahasa lain selain yang ditampilkan.


Untuk mengikuti panduan langkah demi langkah tugas ini langsung di Cloud Shell Editor, klik Pandu saya:

Pandu saya


Sebelum memulai

  1. Login ke akun Google Cloud Anda. Jika Anda baru menggunakan Google Cloud, buat akun untuk mengevaluasi performa produk kami dalam skenario dunia nyata. Pelanggan baru juga mendapatkan kredit gratis senilai $300 untuk menjalankan, menguji, dan men-deploy workload.
  2. Di konsol Google Cloud, pada halaman pemilih project, pilih atau buat project Google Cloud.

    Buka pemilih project

  3. Pastikan penagihan telah diaktifkan untuk project Google Cloud Anda.

  4. Enable the Artifact Registry, Cloud Build, and Google Kubernetes Engine APIs.

    Enable the APIs

  5. Menginstal Google Cloud CLI.
  6. Untuk initialize gcloud CLI, jalankan perintah berikut:

    gcloud init
  7. Di konsol Google Cloud, pada halaman pemilih project, pilih atau buat project Google Cloud.

    Buka pemilih project

  8. Pastikan penagihan telah diaktifkan untuk project Google Cloud Anda.

  9. Enable the Artifact Registry, Cloud Build, and Google Kubernetes Engine APIs.

    Enable the APIs

  10. Menginstal Google Cloud CLI.
  11. Untuk initialize gcloud CLI, jalankan perintah berikut:

    gcloud init
  12. kubectl digunakan untuk mengelola Kubernetes, sistem orkestrasi cluster yang digunakan GKE. Anda dapat menginstal kubectl menggunakan gcloud:
    gcloud components install kubectl

Menulis aplikasi contoh

Untuk petunjuk mengenai pembuatan aplikasi Halo Dunia yang berjalan di GKE, klik bahasa Anda:

Go

  1. Buat direktori baru bernama helloworld-gke, lalu pindahlah ke direktori tersebut:

    mkdir helloworld-gke
    cd helloworld-gke
    
  2. Buat modul baru bernama example.com/helloworld:

    go mod init example.com/helloworld
    
  3. Buat file baru bernama helloworld.go dan tempelkan kode berikut ke dalamnya:

    package main
    
    import (
    	"fmt"
    	"log"
    	"net/http"
    	"os"
    )
    
    func main() {
    	http.HandleFunc("/", handler)
    
    	port := os.Getenv("PORT")
    	if port == "" {
    		port = "8080"
    	}
    
    	log.Printf("Listening on localhost:%s", port)
    	log.Fatal(http.ListenAndServe(fmt.Sprintf(":%s", port), nil))
    }
    
    func handler(w http.ResponseWriter, r *http.Request) {
    	log.Print("Hello world received a request.")
    	target := os.Getenv("TARGET")
    	if target == "" {
    		target = "World"
    	}
    	fmt.Fprintf(w, "Hello %s!\n", target)
    }
    

    Kode ini menghasilkan server web yang memantau port yang ditentukan oleh variabel lingkungan PORT.

Aplikasi Anda sudah jadi dan siap dipaketkan dalam container Docker, lalu diupload ke Artifact Registry.

Node.js

  1. Buat direktori baru bernama helloworld-gke dan pindahlah ke direktori ini:

    mkdir helloworld-gke
    cd helloworld-gke
    
  2. Buat file package.json dengan konten berikut:

    {
      "name": "gke-helloworld",
      "version": "1.0.0",
      "description": "GKE hello world sample in Node",
      "main": "index.js",
      "scripts": {
        "start": "node index.js"
      },
      "author": "",
      "license": "Apache-2.0",
      "dependencies": {
        "express": "^4.16.4"
      }
    }
    
  3. Dalam direktori yang sama, buat file index.js, lalu salin baris berikut ke dalamnya:

    const express = require('express');
    const app = express();
    
    app.get('/', (req, res) => {
      console.log('Hello world received a request.');
    
      const target = process.env.TARGET || 'World';
      res.send(`Hello ${target}!`);
    });
    
    const port = process.env.PORT || 8080;
    app.listen(port, () => {
      console.log('Hello world listening on port', port);
    });

    Kode ini menghasilkan server web yang memantau port yang ditentukan oleh variabel lingkungan PORT.

Aplikasi Anda sudah jadi dan siap dikemas dalam container Docker dan diupload ke Artifact Registry.

Python

  1. Buat direktori baru bernama helloworld-gke dan pindahlah ke direktori ini:

    mkdir helloworld-gke
    cd helloworld-gke
    
  2. Buat file bernama app.py dan tempelkan kode berikut ke dalamnya:

    import os
    
    from flask import Flask
    
    app = Flask(__name__)
    
    @app.route('/')
    def hello_world():
        target = os.environ.get('TARGET', 'World')
        return 'Hello {}!\n'.format(target)
    
    if __name__ == "__main__":
        app.run(debug=True,host='0.0.0.0',port=int(os.environ.get('PORT', 8080)))

Java

Buat aplikasi Spring Boot.

  1. Instal JDK untuk Java SE 8 atau yang lebih baru dan cURL. Java SE dan cURL hanya diperlukan untuk membuat project web baru pada langkah berikutnya. Dockerfile, yang akan dijelaskan nanti, memuat semua dependensi ke dalam container.

  2. Dari terminal Anda, buat project web kosong baru:

    curl https://start.spring.io/starter.zip \
        -d dependencies=web \
        -d javaVersion=1.8 \
        -d type=maven-project \
        -d bootVersion=2.6.6 \
        -d name=helloworld \
        -d artifactId=helloworld \
        -d baseDir=helloworld-gke \
        -o helloworld-gke.zip
    unzip helloworld-gke.zip
    cd helloworld-gke
    

    Sekarang Anda memiliki project Spring Boot baru di helloworld-gke.

  3. Dalam file src/main/java/com/example/helloworld/HelloworldApplication.java, Perbarui class HelloworldApplication dengan menambahkan @RestController untuk menangani pemetaan /.

    package com.example.helloworld;
    
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @SpringBootApplication
    public class HelloworldApplication {
    
    	@Value("${TARGET:World}")
    	String target;
    
    	@RestController
    	class HelloworldController {
    		@GetMapping("/")
    		String hello() {
    			return "Hello " + target + "!";
    		}
    	}
    
    	public static void main(String[] args) {
    		SpringApplication.run(HelloworldApplication.class, args);
    	}
    }

    Kode ini menghasilkan server web yang memantau port yang ditentukan oleh variabel lingkungan PORT.

Aplikasi Anda sudah jadi dan siap dipaketkan dalam container Docker, lalu diupload ke Artifact Registry.

C#

  1. Instal .NET SDK. .NET SDK hanya diperlukan untuk membuat project web baru pada langkah berikutnya. Dockerfile, yang akan dijelaskan nanti, memuat semua dependensi ke dalam container.

  2. Dari terminal Anda, buat project web kosong baru:

    dotnet new web -o helloworld-gke
    
  3. Ubah direktori ke helloworld-gke.

    cd helloworld-gke
    
  4. Update Program.cs untuk mendengarkan port 8080:

    var builder = WebApplication.CreateBuilder(args);
    
    // Google Cloud Run sets the PORT environment variable to tell this
    // process which port to listen to.
    var port = Environment.GetEnvironmentVariable("PORT") ?? "8080";
    var url = $"http://0.0.0.0:{port}";
    var target = Environment.GetEnvironmentVariable("TARGET") ?? "World";
    
    var app = builder.Build();
    
    app.MapGet("/", () => $"Hello {target}!");
    
    app.Run(url);

Aplikasi Anda sudah jadi dan siap dipaketkan dalam container Docker, lalu diupload ke Artifact Registry.

PHP

  1. Buat direktori baru bernama helloworld-gke dan pindahlah ke direktori ini:

    mkdir helloworld-gke
    cd helloworld-gke
    
  2. Buat file bernama index.php dan tempelkan kode berikut ke dalamnya:

    <?php
    $target = getenv('TARGET', true) ?: 'World';
    echo sprintf("Hello %s!", $target);
    ?>

Aplikasi Anda sudah jadi dan siap dipaketkan dalam container Docker, lalu diupload ke Artifact Registry.

Memasukkan aplikasi ke dalam container dengan Cloud Build

  1. Untuk memasukkan aplikasi contoh ke dalam container, buat file baru bernama Dockerfile di dalam direktori yang sama dengan file sumber, lalu salin konten berikut:

    Go

    # Use the offical Go image to create a build artifact.
    # This is based on Debian and sets the GOPATH to /go.
    # https://hub.docker.com/_/golang
    FROM golang:1.22.0 as builder
    WORKDIR /app
    
    # Initialize a new Go module.
    RUN go mod init quickstart-go
    
    # Copy local code to the container image.
    COPY *.go ./
    
    # Build the command inside the container.
    RUN CGO_ENABLED=0 GOOS=linux go build -o /quickstart-go
    
    # Use a Docker multi-stage build to create a lean production image.
    # https://docs.docker.com/develop/develop-images/multistage-build/#use-multi-stage-builds
    FROM gcr.io/distroless/base-debian11
    
    # Change the working directory.
    WORKDIR /
    
    # Copy the binary to the production image from the builder stage.
    COPY --from=builder /quickstart-go /quickstart-go
    
    # Run the web service on container startup.
    USER nonroot:nonroot
    ENTRYPOINT ["/quickstart-go"]

    Node.js

    # Use the official lightweight Node.js 16 image.
    # https://hub.docker.com/_/node
    FROM node:21-slim
    
    # Create and change to the app directory.
    WORKDIR /usr/src/app
    
    # Copy application dependency manifests to the container image.
    # A wildcard is used to ensure both package.json AND package-lock.json are copied.
    # Copying this separately prevents re-running npm install on every code change.
    COPY package*.json ./
    
    # Install production dependencies.
    RUN npm install --omit=dev
    
    # Copy local code to the container image.
    COPY . ./
    
    # Run the web service on container startup.
    CMD [ "npm", "start" ]

    Tambahkan juga file .dockerignore untuk memastikan file lokal tidak memengaruhi proses build container:

    Dockerfile
    README.md
    node_modules
    npm-debug.log
    

    Python

    # Use the official lightweight Python image.
    # https://hub.docker.com/_/python
    FROM python:3.12-slim
    
    # Copy local code to the container image.
    ENV APP_HOME /app
    WORKDIR $APP_HOME
    COPY . ./
    
    # Install production dependencies.
    RUN pip install Flask gunicorn
    
    # Run the web service on container startup. Here we use the gunicorn
    # webserver, with one worker process and 8 threads.
    # For environments with multiple CPU cores, increase the number of workers
    # to be equal to the cores available.
    CMD exec gunicorn --bind :$PORT --workers 1 --threads 8 app:app

    Tambahkan file .dockerignore untuk memastikan file lokal tidak memengaruhi proses build container:

    Dockerfile
    README.md
    *.pyc
    *.pyo
    *.pyd
    __pycache__
    

    Java

    # Use the official maven/Java 8 image to create a build artifact.
    # https://hub.docker.com/_/maven
    FROM maven:3.5-jdk-8-alpine as builder
    
    # Copy local code to the container image.
    WORKDIR /app
    COPY pom.xml ./
    COPY src ./src/
    
    # Build a release artifact.
    RUN mvn package -DskipTests
    
    # Use AdoptOpenJDK for base image.
    # It's important to use OpenJDK 8u191 or above that has container support enabled.
    # https://hub.docker.com/r/adoptopenjdk/openjdk8
    # https://docs.docker.com/develop/develop-images/multistage-build/#use-multi-stage-builds
    FROM adoptopenjdk/openjdk8:jdk8u202-b08-alpine-slim
    
    # Copy the jar to the production image from the builder stage.
    COPY --from=builder /app/target/helloworld-*.jar /helloworld.jar
    
    # Run the web service on container startup.
    CMD ["java","-Djava.security.egd=file:/dev/./urandom","-Dserver.port=${PORT}","-jar","/helloworld.jar"]

    C#

    # Use Microsoft's official lightweight .NET images.
    FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
    WORKDIR /app
    
    # Install production dependencies.
    # Copy csproj and restore as distinct layers.
    COPY *.csproj ./
    RUN dotnet restore
    
    # Copy local code to the container image.
    COPY . ./
    
    # Build a release artifact.
    RUN dotnet publish -c Release -o out
    
    # Run the web service on container startup in a lean production image.
    FROM mcr.microsoft.com/dotnet/aspnet:6.0
    WORKDIR /app
    COPY --from=build /app/out .
    
    # Start the .dll (will have the same name as your .csproj file)
    ENTRYPOINT ["dotnet", "helloworld-gke.dll"]

    Tambahkan file .dockerignore untuk memastikan file lokal tidak memengaruhi proses build container:

    Dockerfile
    README.md
    **/obj/
    **/bin/
    

    PHP

    # Use the official PHP 7.4 image.
    # https://hub.docker.com/_/php
    FROM php:8.2-apache
    
    # Copy local code to the container image.
    COPY index.php /var/www/html/
    
    # Use port 8080 in Apache configuration files.
    RUN sed -i 's/80/${PORT}/g' /etc/apache2/sites-available/000-default.conf /etc/apache2/ports.conf
    
    # Configure PHP for development.
    # Switch to the production php.ini for production operations.
    # RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
    # https://hub.docker.com/_/php#configuration
    RUN mv "$PHP_INI_DIR/php.ini-development" "$PHP_INI_DIR/php.ini"

    Tambahkan file .dockerignore untuk memastikan file lokal tidak memengaruhi proses build container:

    Dockerfile
    README.md
    vendor
    
  2. Dapatkan ID project Google Cloud Anda:

    gcloud config get-value project
    
  3. Dalam panduan memulai ini, Anda akan menyimpan container di Artifact Registry dan men-deploy container ke cluster dari registry. Jalankan perintah berikut untuk membuat repositori bernama hello-repo di lokasi yang sama dengan cluster Anda:

    gcloud artifacts repositories create hello-repo \
        --project=PROJECT_ID \
        --repository-format=docker \
        --location=us-central1 \
        --description="Docker repository"
    

    Ganti nilai berikut:

    • PROJECT_ID adalah ID project Google Cloud Anda
  4. Bangun image container Anda menggunakan Cloud Build, seperti menjalankan docker build dan docker push, tetapi build terjadi di Google Cloud:

    gcloud builds submit \
      --tag us-central1-docker.pkg.dev/PROJECT_ID/hello-repo/helloworld-gke .
    

    Image tersebut disimpan di Artifact Registry.

Membuat cluster GKE

Cluster GKE adalah serangkaian virtual machine Compute Engine terkelola yang beroperasi sebagai satu cluster GKE.

  1. Buat cluster.

    gcloud container clusters create-auto helloworld-gke \
      --location us-central1
    
  2. Pastikan Anda memiliki akses ke cluster. Perintah berikut mendaftar node di cluster container Anda yang aktif dan berjalan, serta menunjukkan bahwa Anda memiliki akses ke cluster tersebut.

    kubectl get nodes
    

    Jika Anda mengalami error, baca Panduan Pemecahan Masalah Kubernetes.

Men-deploy ke GKE

Untuk men-deploy aplikasi ke cluster GKE yang telah dibuat, Anda memerlukan dua objek Kubernetes.

  1. Deployment untuk menentukan aplikasi Anda.
  2. Service untuk menentukan cara mengakses aplikasi Anda.

Men-deploy aplikasi

Aplikasi memiliki server frontend yang menangani permintaan web. Anda menentukan resource cluster yang diperlukan untuk menjalankan frontend dalam file baru bernama deployment.yaml. Resource ini disebut Deployment. Anda menggunakan Deployment untuk membuat dan mengupdate ReplicaSet dan Pod yang terkait.

  1. Buat file deployment.yaml di direktori yang sama dengan file Anda lainnya, lalu salin konten berikut. Ganti nilai berikut di file Anda:

    • $GCLOUD_PROJECT adalah ID project Google Cloud Anda:
    • $LOCATION adalah lokasi repositori, seperti us-central1.
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: helloworld-gke
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: hello
      template:
        metadata:
          labels:
            app: hello
        spec:
          containers:
          - name: hello-app
            # Replace $LOCATION with your Artifact Registry location (e.g., us-west1).
            # Replace $GCLOUD_PROJECT with your project ID.
            image: $LOCATION-docker.pkg.dev/$GCLOUD_PROJECT/hello-repo/helloworld-gke:latest
            # This app listens on port 8080 for web traffic by default.
            ports:
            - containerPort: 8080
            env:
              - name: PORT
                value: "8080"
            resources:
              requests:
                memory: "1Gi"
                cpu: "500m"
                ephemeral-storage: "1Gi"
              limits:
                memory: "1Gi"
                cpu: "500m"
                ephemeral-storage: "1Gi"
  2. Deploy resource ke cluster:

    kubectl apply -f deployment.yaml
    
  3. Lacak status Deployment:

    kubectl get deployments
    

    Deployment selesai saat semua deployment AVAILABLE adalah READY.

    NAME              READY   UP-TO-DATE   AVAILABLE   AGE
    helloworld-gke    1/1     1            1           20s
    

    Jika Deployment mengalami kesalahan, jalankan kubectl apply -f deployment.yaml lagi untuk mengupdate perubahan pada Deployment.

  4. Setelah Deployment selesai, Anda dapat melihat Pod yang dibuat oleh Deployment:

    kubectl get pods
    

Men-deploy Layanan

Service menyediakan satu titik akses ke sekumpulan Pod. Meskipun satu Pod dapat diakses, Pod bersifat sementara dan hanya dapat diakses secara andal menggunakan alamat layanan. Di aplikasi Halo Dunia, Service "hello" menentukan load balancer untuk mengakses Pod hello-app dari satu alamat IP. Service ini ditentukan dalam file service.yaml.

  1. Buat file service.yaml dengan konten berikut di dalam direktori yang sama dengan file sumber Anda yang lain:

    # The hello service provides a load-balancing proxy over the hello-app
    # pods. By specifying the type as a 'LoadBalancer', Kubernetes Engine will
    # create an external HTTP load balancer.
    apiVersion: v1
    kind: Service
    metadata:
      name: hello
    spec:
      type: LoadBalancer
      selector:
        app: hello
      ports:
      - port: 80
        targetPort: 8080

    Pod didefinisikan secara terpisah dari service yang menggunakan Pod. Kubernetes menggunakan label untuk memilih pod yang ditangani service. Dengan label, Anda dapat memiliki service yang menangani Pod dari kumpulan replika yang berbeda dan memiliki beberapa service yang mengarah ke setiap Pod.

  2. Membuat Service Halo Dunia:

    kubectl apply -f service.yaml
    
  3. Dapatkan alamat IP eksternal service:

    kubectl get services
    

    Diperlukan waktu hingga 60 detik untuk mengalokasikan alamat IP. Alamat IP eksternal tercantum di kolom EXTERNAL-IP untuk Service hello.

    NAME         TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)        AGE
    hello        LoadBalancer   10.22.222.222   35.111.111.11   80:32341/TCP   1m
    kubernetes   ClusterIP      10.22.222.1     <none>          443/TCP        20m
    

Melihat aplikasi yang di-deploy

Anda kini telah men-deploy semua resource yang diperlukan untuk menjalankan aplikasi Hello World di GKE.

Gunakan alamat IP eksternal dari langkah sebelumnya untuk memuat aplikasi di browser web Anda, dan lihat aplikasi yang sedang berjalan:

 http://EXTERNAL_IP

Atau, Anda dapat melakukan panggilan curl ke alamat IP eksternal service:

curl EXTERNAL_IP

Outputnya menampilkan ini:

Hello World!

Pembersihan

Agar tidak menimbulkan biaya pada akun Google Cloud Anda untuk resource yang digunakan pada halaman ini, ikuti langkah-langkah berikut.

Anda dikenai biaya untuk instance Compute Engine yang berjalan di cluster Anda dan image container di Artifact Registry.

Menghapus project

Menghapus project Google Cloud akan menghentikan penagihan untuk semua resource yang digunakan dalam project tersebut.

  1. Di konsol Google Cloud, buka halaman Manage resource.

    Buka Manage resource

  2. Pada daftar project, pilih project yang ingin Anda hapus, lalu klik Delete.
  3. Pada dialog, ketik project ID, lalu klik Shut down untuk menghapus project.

Menghapus cluster dan container

Jika Anda ingin menghapus resource yang digunakan dalam tutorial ini tanpa menghapus project, hapus cluster dan image Anda.

Untuk menghapus cluster menggunakan Google Cloud CLI, jalankan perintah berikut untuk mode yang Anda gunakan:

gcloud container clusters delete helloworld-gke \
    --location us-central1

Untuk menghapus image di repositori Artifact Registry, jalankan perintah berikut:

gcloud artifacts docker images delete \
    us-central1-docker.pkg.dev/PROJECT_ID/hello-repo/helloworld-gke

Langkah selanjutnya

Untuk informasi selengkapnya tentang Kubernetes, lihat referensi berikut:

Untuk informasi selengkapnya tentang men-deploy ke GKE, lihat referensi berikut:

Untuk mengetahui informasi selengkapnya tentang membuat, mengembangkan, dan menjalankan aplikasi di GKE langsung dari IDE Anda dengan Cloud Code, lihat artikel berikut: