Golang 遇见 Kubernetes:云原生开发的完美结合

Golang 和 Kubernetes 简介

Golang 概述

Golang,也称为 Go,是由 Google 开发的一种开源编程语言。Go 由 Robert Griesemer、Rob Pike 和 Ken Thompson 设计,于 2009 年首次发布,此后在各个领域都获得了广泛的关注,尤其是在服务器端应用程序、云计算和微服务领域。

Golang 的主要特点

  1. 简洁高效:
  • Golang 的设计理念是简洁,语法简洁,注重可读性和易用性。这使得它成为初学者和经验丰富的开发人员的理想选择,能够快速学习和开发。
  1. 并发性:
  • Golang 的一大突出特点是它通过 goroutine 和 channel 内置了对并发的支持。goroutine 是由 Go 运行时管理的轻量级线程,允许开发人员同时执行多个任务,而无需承担传统线程模型带来的开销。这使得它特别适合需要高并行度的应用程序,例如 Web 服务器和实时数据处理。
  1. 性能:
  • Go 专为高性能而设计,其编译型架构可将代码直接转换为机器码。与解释型语言相比,这可以缩短执行时间。此外,Go 的垃圾回收系统非常高效,在内存管理和性能之间实现了良好的平衡。
  1. 强类型和可组合性:
  • Golang 拥有强大的静态类型系统,提供编译时类型检查,从而降低运行时错误的可能性。这有助于编写更健壮的代码并增强重构能力。此外,Go 支持组合而非继承,允许开发人员使用更简单的组件构建复杂的系统,从而增强代码的可重用性。
  1. 标准库:
  • Golang 拥有丰富的标准库,其中包含用于处理 Web 服务器、文件操作和数据格式等功能的软件包。这个丰富的库使开发人员无需依赖外部依赖即可实现功能,从而加快了开发过程。
  1. 跨平台:
  • Go 天生具备跨平台特性,使开发者能够构建可在各种操作系统(包括 Linux、Windows 和 macOS)上运行的应用程序。Go 能够通过单一代码库编译出适用于各种平台的二进制文件,这为其提供了便利。
  1. 社区和生态系统:
  • 自发布以来,Golang 就拥有一个强大而活跃的社区。Go 生态系统不断发展壮大,通过 Go Module 系统提供了众多库、框架和工具,简化了包管理和依赖项解析。
  1. 工具:
  • Go 附带一套优秀的工具,支持测试、性能分析和代码格式化,确保开发者能够轻松维护高质量的代码库。`go` 命令是一个强大的工具,可以帮助管理依赖项、编译代码和运行测试。

Golang 已成为现代软件开发的强大语言,尤其是在云原生环境和分布式系统中。 Golang 注重简洁性、性能和高效的并发性,使其成为构建可扩展且可维护应用程序的组织的首选。无论您是开发微服务、处理高性能应用程序还是执行自动化任务,Golang 都能提供丰富的特性和功能,满足您广泛的开发需求。

Kubernetes 简介

Kubernetes,通常缩写为 K8s,是一个开源容器编排平台,最初由 Google 开发。Kubernetes 于 2014 年发布,可自动部署、扩展和管理容器化应用程序。它已迅速成为管理云原生应用程序的基础工具,帮助企业优化资源利用率并提升运营工作流程的自动化程度。

Kubernetes 的用途

Kubernetes 旨在管理跨机器集群的容器化应用程序,确保这些应用程序保持可用性、可扩展性和弹性。Kubernetes 的主要用途包括:

  1. 容器编排:
  • Kubernetes 自动部署容器化应用程序,管理集群中物理机或虚拟机上的容器调度,优化资源分配,并处理容器的启动和管理。
  1. 扩展和负载均衡:
  • Kubernetes 支持根据需求对应用程序进行水平扩展。它可以根据不断变化的工作负载自动扩展活动容器实例数量,确保应用程序能够高效地处理不同的负载。此外,Kubernetes 还提供内部负载均衡功能,以便在容器实例之间分配流量。
  1. 自我修复:
  • Kubernetes 监控容器的健康状况,并在容器发生故障时自动重启或替换容器。这种自我修复功能可增强应用程序的可靠性并最大限度地减少停机时间。
  1. 服务发现和网络:
  • Kubernetes 提供内置的服务发现功能,使容器之间更容易通信。它为一组容器分配 IP 地址和单个 DNS 名称,使应用程序能够相互发现并无缝通信。
  1. 声明式配置:
  • Kubernetes 采用声明式方法进行配置和管理。用户定义应用程序的期望状态,Kubernetes 负责维护该状态。这种方法简化了部署和管理,同时允许更轻松地进行更改和回滚。
  1. 存储编排:
  • Kubernetes 可以管理容器化应用的存储资源,支持使用各种类型的持久化存储,包括云存储和本地存储。这种灵活性使应用程序即使在部署和重新部署容器时也能保持状态。

随着企业越来越多地采用云原生架构,Kubernetes 的重要性也随之提升,原因如下:

  1. 微服务架构:
  • Kubernetes 支持微服务模型,允许开发人员构建和部署由松散耦合服务组成的应用程序。这种架构增强了服务的灵活性、可扩展性和独立部署能力。
  1. 多云策略:
  • Kubernetes 为跨不同云提供商和本地环境运行应用程序提供了一个一致的平台。此功能使企业能够采用多云策略,在保持运营一致性的同时利用各种云服务。
  1. DevOps 和 CI/CD:
  • Kubernetes 与 DevOps 实践无缝集成,促进持续集成和持续部署 (CI/CD) 流水线的构建。其自动化功能可加快更新和部署速度,从而有助于缩短软件交付和开发周期。
  1. 资源管理:
  • 在基础设施成本不断上涨的时代,Kubernetes 通过确保应用程序仅在需要时运行,并根据需求动态管理资源分配,帮助优化资源使用率。
  1. 社区和生态系统:
  • Kubernetes 社区充满活力且发展迅速,其工具和扩展程序生态系统不断发展壮大,增强了其功能。Helm(用于包管理)和 Istio(用于服务网格)等热门项目充分展现了 Kubernetes 的灵活性和可扩展性。
  1. 来自主要云提供商的支持:
  • 包括 Google Cloud、AWS 和 Azure 在内的领先云提供商提供托管 Kubernetes 服务,使组织能够更轻松地部署和管理 Kubernetes 集群,而无需承担维护成本。这种支持显著降低了希望采用云原生实践的组织的准入门槛。

设置开发环境

安装 Golang 并设置 Go 工作区

安装 Golang

1.1 下载 Go

1.2 安装 Go

  • Windows:

  • 运行下载对应的.msi安装程序,并按照提示完成安装。

  • macOS:

  • 打开终端并使用 Homebrew 软件包管理器:

    bash
    brew install go

  • 或者,如果您下载的是 macOS 二进制文件,请打开下载的文件并将 Go 图标拖放到 `/usr/local` 目录中。

  • Linux:

  • 解压下载的 tarball。

tar -C /usr/local -xzf go1.17.linux-amd64.tar.gz

  • 将 go1.17.linux-amd64.tar.gz 替换为您下载的版本。

  • 将 /usr/local/go/bin添加到您的 PATH 环境变量中。您可以通过在 .bash_profile、bashrc或 .zshrc文件中添加以下行来实现:

    export PATH=$PATH:/usr/local/go/bin

  • 编辑文件后,运行:

    source ~/.bashrc

    source ~/.bash_profile

    source ~/.zshrc

1.3 验证安装

通过在终端中运行以下命令来验证 Go 是否已正确安装:

复制代码
ninjamac@192 key % go version         
go version go1.24.0 darwin/arm64

这将显示已安装的 Go 版本。

设置 Go 工作区

Go 已从传统的 GOPATH 工作区模型转变为基于模块的方法,从而简化了依赖项管理。但是,如果您愿意,仍然可以设置 GOPATH 工作区。

2.1 创建 Go 工作区

如果您使用 Go 模块,则无需创建 GOPATH 工作区,但您可以按照以下方法设置:

  1. 定义您的 GOPATH:
  • 默认情况下,GOPATH 在 Unix 系统上设置为"$HOME/go",在 Windows 系统上设置为"%USERPROFILE%\go"。您可以通过设置"GOPATH"环境变量来更改此设置。
  1. 创建工作区目录:

创建工作区目录结构。打开终端并运行:

复制代码
mkdir -p $HOME/go/{bin,pkg,src}
ninjamac@192 ~ % tree -d -L 3 go/
go/
├── bin
├── pkg
│   ├── mod
│   │   ├── al.essio.dev
│   │   ├── cache
│   │   ├── cloud.google.com
│   │   ├── github.com
│   │   ├── [email protected]
│   │   ├── go.opentelemetry.io
│   │   ├── [email protected]
│   │   ├── [email protected]
│   │   ├── go.uber.org
│   │   ├── golang.org
│   │   ├── gomodules.xyz
│   │   ├── google.golang.org
│   │   ├── gopkg.in
│   │   ├── honnef.co
│   │   ├── k8s.io
│   │   ├── mvdan.cc
│   │   └── sigs.k8s.io
│   └── sumdb
│       └── sum.golang.org
└── src
    ├── github.com
    │   └── cncamp
    ├── my-bak
    ├── my-pipeline-tutorial-project
    ├── myproject
    │   ├── cmd
    │   ├── internal
    │   ├── pkg
    │   └── test
    └── pipeline-tutorial
        ├── blog
        ├── docs
        ├── node_modules
        ├── src
        └── static

39 directories
  • bin:用于编译后的二进制文件

  • pkg:用于编译后的包对象

  • src:用于源文件

  1. 设置 GOPATH 环境变量:

将以下内容添加到您的配置文件中:

对于 Linux/macOS,请将以下行添加到您的 .bash_profile、.bashrc 或 .zshrc 中:

复制代码
export GOROOT="/opt/homebrew/Cellar/go/1.24.0/libexec"
export GOPATH="/Users/ninjamac/go"
export GOPROXY="https://goproxy.cn"

对于 Windows,请在系统设置中的环境变量中进行设置:

  • 前往系统属性 -> 环境变量 -> 用户变量,创建一个名为 `GOPATH` 的新变量,值为 C:\Users\YourUsername\go。

2.2 创建 Go 项目

  1. 导航到 src 目录:

    cd $GOPATH/src

  2. 为你的项目创建一个新目录:

    mkdir hello
    cd hello

  3. 创建你的 Go 文件:

创建一个名为 main.go的新文件:

复制代码
touch main.go
  1. 编写你的第一个 Go 程序:

使用你最喜欢的文本编辑器打开 main.go并添加以下代码:

复制代码
package main

import "fmt"

func main() {
fmt.Println("Hello, World!")
}
  1. 构建并运行你的程序:

要运行你的 Go 程序,请在项目目录中执行以下命令:

复制代码
ninjamac@192 hello % go run main.go 
Hello, World!

要构建你的项目,请使用go build,这将创建一个名为 `hello` 的可执行二进制文件,你可以使用以下命令运行它:./hello

复制代码
ninjamac@192 hello % go build
ninjamac@192 hello % ./hello
Hello, World!

恭喜!你已成功安装 Go

安装和配置Minikube

  1. macos

    brew install minikube

  2. linux

    curl -Lo minikube https://storage.googleapis.com/minikube/releases/latest/minikube-Linux-amd64
    sudo chmod +x minikube
    sudo mv minikube /usr/local/bin/

安装 Go 开发的工具和 IDE(vscode goland)

具体安装步骤请参考网站上的链接,在此不在赘述。

构建简单的 Go 应用程序

使用 Go 创建基本的 REST API

  1. 创建go-rest-api目录

    mkdir go-rest-api
    cd go-rest-api

  2. 初始化go module

    go mod init go-rest-api

  3. 编写main.go文件

    package main

    import (
    "encoding/json"
    "net/http"
    "sync"
    )

    type User struct {
    ID string json:"id"
    Name string json:"name"
    }

    var (
    users = make(map[string]User)
    mu sync.Mutex
    nextID = 1
    )

    // Get all users
    func getUsers(w http.ResponseWriter, r *http.Request) {
    mu.Lock()
    defer mu.Unlock()

    复制代码
     var userList []User
     for _, user := range users {
     	userList = append(userList, user)
     }
    
     w.Header().Set("Content-Type", "application/json")
     json.NewEncoder(w).Encode(userList)

    }

    // Create a new user
    func createUser(w http.ResponseWriter, r *http.Request) {
    mu.Lock()
    defer mu.Unlock()

    复制代码
     var newUser User
     if err := json.NewDecoder(r.Body).Decode(&newUser); err != nil {
     	http.Error(w, err.Error(), http.StatusBadRequest)
     	return
     }
    
     newUser.ID = string(nextID)
     users[newUser.ID] = newUser
     nextID++
    
     w.WriteHeader(http.StatusCreated)
     json.NewEncoder(w).Encode(newUser)

    }

    // Get a single user by ID
    func getUser(w http.ResponseWriter, r *http.Request) {
    mu.Lock()
    defer mu.Unlock()

    复制代码
     id := r.URL.Path[len("/users/"):]
    
     user, exists := users[id]
     if !exists {
     	http.Error(w, "User not found", http.StatusNotFound)
     	return
     }
    
     w.Header().Set("Content-Type", "application/json")
     json.NewEncoder(w).Encode(user)

    }

    func main() {
    http.HandleFunc("/users", getUsers)
    http.HandleFunc("/users/", getUser) // Note the trailing slash for single user
    http.HandleFunc("/users/create", createUser) // Route for creating a user

    复制代码
     http.ListenAndServe(":8080", nil)

    }

4:运行 API

要运行您的 API,请在终端中执行以下命令:

复制代码
go run main.go

您的 REST API 将启动并监听 http://localhost:8080

curl http://localhost:8080/users //查询所有的用户

复制代码
ninjamac@ip-192-168-1-101 ~ % curl http://localhost:8080/users | jq .
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   117  100   117    0     0  86156      0 --:--:-- --:--:-- --:--:--  114k
[
  {
    "id": "4",
    "name": "li si"
  },
  {
    "id": "1",
    "name": "Test User"
  },
  {
    "id": "2",
    "name": "John Doe"
  },
  {
    "id": "3",
    "name": "Zhang San"
  }
]

容器化 Go 应用程序

Docker 安装

编写dockerfile

复制代码
    # syntax=docker/dockerfile:1
    FROM golang:1.24-alpine AS builder
    
    WORKDIR /app
    
    COPY go.mod go.sum ./
    RUN go mod download
    
    COPY . .
    
    RUN go build -o main .
    
    FROM alpine:3.19
    
    WORKDIR /app
    
    COPY --from=builder /app/main .
    
    EXPOSE 8088
    
    CMD ["./main"]

构建镜像

复制代码
[ec2-user@ip-172-31-6-119 go-rest-api]$ sudo docker build -t my-gin-app .
[+] Building 36.5s (17/17) FINISHED                                                                                                                          docker:default
 => [internal] load build definition from Dockerfile                                                                                                                   0.0s
 => => transferring dockerfile: 431B                                                                                                                                   0.0s
 => [internal] load metadata for docker.io/library/alpine:3.19                                                                                                         1.3s
 => [internal] load metadata for docker.io/library/golang:1.24-alpine                                                                                                  1.3s
 => [auth] library/alpine:pull token for registry-1.docker.io                                                                                                          0.0s
 => [auth] library/golang:pull token for registry-1.docker.io                                                                                                          0.0s
 => [internal] load .dockerignore                                                                                                                                      0.0s
 => => transferring context: 2B                                                                                                                                        0.0s
 => [builder 1/6] FROM docker.io/library/golang:1.24-alpine@sha256:7772cb5322baa875edd74705556d08f0eeca7b9c4b5367754ce3f2f00041ccee                                    0.0s
 => [internal] load build context                                                                                                                                      0.0s
 => => transferring context: 2.36kB                                                                                                                                    0.0s
 => [stage-1 1/3] FROM docker.io/library/alpine:3.19@sha256:e5d0aea7f7d2954678a9a6269ca2d06e06591881161961ea59e974dff3f12377                                           0.0s
 => CACHED [builder 2/6] WORKDIR /app                                                                                                                                  0.0s
 => CACHED [builder 3/6] COPY go.mod go.sum ./                                                                                                                         0.0s
 => CACHED [builder 4/6] RUN go mod download                                                                                                                           0.0s
 => [builder 5/6] COPY . .                                                                                                                                             0.1s
 => [builder 6/6] RUN go build -o main .                                                                                                                              34.8s
 => CACHED [stage-1 2/3] WORKDIR /app                                                                                                                                  0.0s
 => [stage-1 3/3] COPY --from=builder /app/main .                                                                                                                      0.0s
 => exporting to image                                                                                                                                                 0.1s
 => => exporting layers                                                                                                                                                0.1s
 => => writing image sha256:f29bf2f7daa960b15ae094b16901b36eba8456f4702e5ea0544f3233e0707197                                                                           0.0s
 => => naming to docker.io/library/my-gin-app       

运行容器

复制代码
[ec2-user@ip-172-31-6-119 go-rest-api]$ sudo docker run -p 8088:8088 my-gin-app
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.

[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
 - using env:	export GIN_MODE=release
 - using code:	gin.SetMode(gin.ReleaseMode)

[GIN-debug] GET    /albums                   --> main.getAlbums (3 handlers)
[GIN-debug] GET    /albums/:id               --> main.getAlbumByID (3 handlers)
[GIN-debug] POST   /albums                   --> main.postAlbums (3 handlers)
[GIN-debug] [WARNING] You trusted all proxies, this is NOT safe. We recommend you to set a value.
Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.
[GIN-debug] Listening and serving HTTP on :8088
[GIN] 2025/04/27 - 02:48:51 | 200 |      51.359µs |      172.17.0.1 | GET      "/albums"
[GIN] 2025/04/27 - 02:49:39 | 200 |      21.679µs |      172.17.0.1 | GET      "/albums/1"

测试验证

复制代码
[ec2-user@ip-172-31-6-119 ~]$ curl http://localhost:8088/albums
[
    {
        "id": "1",
        "title": "Blue Train",
        "artist": "John Coltrane",
        "price": 56.99
    },
    {
        "id": "2",
        "title": "Jeru",
        "artist": "Gerry Mulligan",
        "price": 17.99
    },
    {
        "id": "3",
        "title": "Sarah Vaughan and Clifford Brown",
        "artist": "Sarah Vaughan",
        "price": 39.99
    }

将 Go 应用程序部署到 Kubernetes

将镜像上传到docker hub

复制代码
[ec2-user@ip-172-31-6-119 go-rest-api]$ sudo docker tag my-gin-app:latest rockwang415/my-gin-app:latest
[ec2-user@ip-172-31-6-119 go-rest-api]$ sudo docker push rockwang415/my-gin-app:latest
The push refers to repository [docker.io/rockwang415/my-gin-app]
69f968e9f6bc: Pushed 
36ee67fc0b34: Pushed 
0499fc56f5e2: Mounted from library/alpine 
latest: digest: sha256:b662d828445b39ac0a659ec77b629a75d1b298a6c76afdf5296cff64806fc638 size: 945

编写 Kubernetes deployment 和service yaml 文件

复制代码
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-gin-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: my-gin-app
  template:
    metadata:
      labels:
        app: my-gin-app
    spec:
      containers:
      - name: my-gin-app
        image: rockwang415/my-gin-app:latest
        ports:
        - containerPort: 8088  # Change this if your app uses a different port.

apiVersion: v1
kind: Service
metadata:
  name: my-gin-app-service
spec:
  type: NodePort
  selector:
    app: my-gin-app
  ports:
    - port: 8088           # Port that the service will expose
      targetPort: 8088     # Port on the container to forward to
      nodePort: 30080      # Port on the node to expose (optional)

使用 kubectl 应用清单并管理资源

复制代码
kubectl apply -f my-deployment-svc.yaml 

获取pod 所在的node 信息

复制代码
controlplane:~$ kubectl get pod -o wide
NAME                          READY   STATUS    RESTARTS   AGE     IP            NODE     NOMINATED NODE   READINESS GATES
my-gin-app-7cff89d685-mncx9   1/1     Running   0          5m55s   192.168.1.4   node01   <none>           <none>

//该pod 运行在node01

然后获得node01的IP 地址

复制代码
controlplane:~$ kubectl get node -o wide
NAME           STATUS   ROLES           AGE   VERSION   INTERNAL-IP   EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION     CONTAINER-RUNTIME
controlplane   Ready    control-plane   35d   v1.32.1   172.30.1.2    <none>        Ubuntu 24.04.1 LTS   6.8.0-51-generic   containerd://1.7.24
node01         Ready    <none>          35d   v1.32.1   172.30.2.2    <none>        Ubuntu 24.04.1 LTS   6.8.0-51-generic   containerd://1.7.24

controlplane:~$ curl http://172.30.2.2:30080/albums
[
    {
        "id": "1",
        "title": "Blue Train",
        "artist": "John Coltrane",
        "price": 56.99
    },
    {
        "id": "2",
        "title": "Jeru",
        "artist": "Gerry Mulligan",
        "price": 17.99
    },
    {
        "id": "3",
        "title": "Sarah Vaughan and Clifford Brown",
        "artist": "Sarah Vaughan",
        "price": 39.99
    }

结论

Go,也称为 Golang,是一种静态类型编译型语言,旨在简化和提高效率,使其成为构建强大的 Web 应用程序和微服务的绝佳选择。Kubernetes 是一个开源容器编排平台,可自动部署、扩展和管理容器化应用程序。在本项目中,可以使用 Python Flask 前端创建一个用户友好的界面,该界面可与使用 Go 开发的后端相册 API 进行交互。通过将 Go 作为后端,Flask 作为前端,并将两者部署在 Kubernetes 上,开发人员可以在云原生环境中创建可扩展、高效且易于维护的全栈应用程序。

相关推荐
Akamai中国35 分钟前
什么是云计算的边缘原生应用?
人工智能·kubernetes·云计算·边缘计算
东林牧之2 小时前
Docker搭建2FAuth服务
云原生·eureka
昌sit!2 小时前
K8S多维度问题排查
云原生·容器·kubernetes
kylin-运维2 小时前
k8s使用自建nfs做持久化无法控制磁盘使用大小问题处理
云原生·容器·kubernetes
fashia3 小时前
Java转Go日记(六十二):Raft
开发语言·后端·golang·go
movie__movie8 小时前
如何正确的配置eureka server集群
云原生·eureka
藥瓿亭10 小时前
K8S认证|CKS题库+答案| 11. AppArmor
运维·服务器·docker·云原生·容器·kubernetes·cks
955.10 小时前
k8s从入门到放弃之Ingress七层负载
云原生·容器·kubernetes
被一米六支配的恐惧11 小时前
argocd部署cli工具并添加k8s集群
docker·kubernetes·argocd
昌sit!14 小时前
K8S项目需求分析
云原生·容器·kubernetes