本文介绍了如何部署一个简单的Go项目;
源代码:
使用K8S部署最简单的Go应用
项目简介
本文构建的Go项目是一个非常简单的Web项目:
main.go
package main
import (
    "fmt"
    "net/http"
)
func index(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "<h1>Hello World</h1>")
}
func check(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "<h1>Health check</h1>")
}
func main() {
    http.HandleFunc("/", index)
    http.HandleFunc("/health_check", check)
    fmt.Println("Server starting...")
    http.ListenAndServe(":8080", nil)
}项目启动后分别访问:
- :8080/: show- <h1>Hello World</h1>
- :8080/health_check: show- <h1>Health check</h1>
会显示如下内容:

下面介绍如何在K8S中部署这个项目;
构建镜像
首先编写Dockerfile文件:
Dockerfile
FROM golang:1.17.2-alpine3.14
MAINTAINER jasonkayzk@gmail.com
RUN mkdir /app
COPY . /app
WORKDIR /app
RUN go build -o main .
CMD ["/app/main"]随后构建镜像:
docker build -t jasonkay/go-hello-app:v0.0.1 .最后,向DockerHub推送镜像;
docker push jasonkay/go-hello-app:v0.0.1当然,你也可以先在本地对镜像进行测试:
docker run -d -p 8080:8080 --rm --name go-hello-app-container jasonkay/go-hello-app:v0.0.1
部署应用至K8S中
创建文件deployment.yaml:
deploy/deployment.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: go-hello-app
  namespace: my-workspace # 声明工作空间,默认为default
spec:
  replicas: 2
  selector:
    matchLabels:
      name: go-hello-app
  template:
    metadata:
      labels:
        name: go-hello-app
    spec:
      containers:
        - name: go-hello-container
          image: jasonkay/go-hello-app:v0.0.1
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 8080 # containerPort是声明容器内部的port
---
apiVersion: v1
kind: Service
metadata:
  name: go-hello-app-service
  namespace: my-workspace # 声明工作空间,默认为default
spec:
  type: NodePort
  ports:
    - name: http
      port: 18080 # Service暴露在cluster-ip上的端口,通过<cluster-ip>:port访问服务,通过此端口集群内的服务可以相互访问
      targetPort: 8080 # Pod的外部访问端口,port和nodePort的数据通过这个端口进入到Pod内部,Pod里面的containers的端口映射到这个端口,提供服务
      nodePort: 31080 # Node节点的端口,<nodeIP>:nodePort 是提供给集群外部客户访问service的入口
  selector:
    name: go-hello-app注1:你可能需要修改上面的配置,尤其是:
- metadata.namespace;
- spec.spec.containers.image;
注2:注意在Deployment中containerPort以及Service中port、targetPort和nodePort的区别:
Deployment.containerPort:仅仅是声明容器中应用需要的Port;
Service.port:Service暴露在k8s-cluster-ip上的端口,可以通过<cluster-ip>:port访问服务,通过此端口集群内的服务可以相互访问;
Service.targetPort:Pod的外部访问端口,port和nodePort的数据通过这个端口进入到Pod内部,Pod里面的containers的端口映射到这个端口,提供服务;
Service.nodePort:Node节点的端口,<nodeIP>:nodePort是提供给集群外部客户访问service的入口!
最后,通过下面的命令向K8S的ApiServer提交配置,部署应用:
kubectl create -f deploy/deployment.yaml注意:此处使用的是kubectl create命令,也可以使用kubectl apply命令;
两者的区别:
| 序号 | kubectl apply | kubectl create | 
|---|---|---|
| 1 | 根据yaml文件中包含的字段(yaml文件可以只写需要改动的字段),直接升级集群中的现有资源对象 | 首先删除集群中现有的所有资源,然后重新根据yaml文件(必须是完整的配置信息)生成新的资源对象 | 
| 2 | yaml文件可以不完整,只写需要的字段 | yaml文件必须是完整的配置字段内容 | 
| 3 | kubectl apply只工作在yaml文件中的某些改动过的字段 | kubectl create工作在yaml文件中的所有字段 | 
| 4 | 在只改动了yaml文件中的某些声明时,而不是全部改动,你可以使用kubectl apply | 在没有改动yaml文件时,使用同一个yaml文件执行命令kubectl replace,将不会成功(fail掉),因为缺少相关改动信息 | 
部署校验
首先,我们通过命令行查看Pod状态:
kubectl get po -n my-workspace
NAME                            READY   STATUS    RESTARTS   AGE
go-hello-app-555c69b994-zt9zf   2/2     Running   0          54m
go-hello-app-555c69b994-zwdb7   2/2     Running   0          54m随后,我们通过面板查看状态:

最后,我们可以通过<k8s-node-ip:NodePort>的形式访问,即:
同样的,我们可以看到:

卸载服务
可以通过下面的命令卸载服务:
kubectl delete -f deploy/deployment.yaml小结
本文使用一个非常简单的Go项目展示了如何将项目部署在K8S中;
从上面的示例可以看到,Go项目的部署可以和K8S很紧密的结合,或许这也是为什么Go越来越流行的原因之一吧!
附录
源代码:
文章参考:
