本篇使用的goweb demo,页面很简单,功能也是很简单,写代码不是本篇的重点,重点是先体验一下整个流程:开发环境准备、写代码、提交到仓库、拉取代码构建并打包镜像、推送到镜像仓库,部署到K8S。
本篇的分享分为上篇和下篇,上篇是手动,计划在下篇再讲自动。只有手动体验过,才能更能深入的理解里面的流程、细节,后面再把这个流程改造为全程自动化就是信手拈来的事情。如果连手工部署都跑不通,还想谈自动化呢?如果是在企业里,谈自动化之前还得先把标准化流程给落实了,再来谈自动化。
golang开发环境准备
- 下载golang二进制包
wget https://golang.google.cn/dl/go1.19.3.linux-amd64.tar.gz tar -zxf go1.19.3.linux-amd64.tar.gz mv go /usr/local/
- 在/etc/profile配置环境变量
export GOROOT="/usr/local/go" export GOPATH="/data/project/gocode" export GOPROXY="https://goproxy.cn,direct" export GO111MODULE="on" export PATH=$PATH:$GOROOT/bin:$GOPATH # 使其生效 source /etc/profile
GOPROXY表示的是go的代理设置,当自动下载第三方代码的库地址时,go默认是国外下载,所以配置代理,加快速度,国内一般使用七牛云的goproxy.cn
- 进入$GOPATH创建src、pkg、bin目录
[root@workhost ~]# cd $GOPATH [root@workhost gocode]# mkdir bin pkg src
写代码
- 一个简单的项目结构
[root@workhost goweb]# tree . ├── go.mod ├── main.go ├── README.md └── static └── login.html
- 写一个简单的前端页面
static/login.html
<!DOCTYPE html> <html lang="zh-CN"> <head> <title>不背锅运维</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link href="https://cdn.staticfile.org/twitter-bootstrap/5.1.1/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.staticfile.org/twitter-bootstrap/5.1.1/js/bootstrap.bundle.min.js"></script> </head> <body class="bg-dark bg-opacity-76"> <div class="container vh-100"> <div class="row vh-100"> <div class="col-4 m-auto p-5 justify-content-center bg-white rounded"> <form action="/login" method="post"> <div class="mb-3"> <label class="form-label mb-1 text-black-50">用户名:</label> <input type="text" class="form-control" name="account"> </div> <div class="mb-4"> <label class="form-label mb-1 text-black-50">密码:</label> <input type="password" class="form-control" name="password"> </div> <div class="mb-1"> <button type="submit" class="form-control btn-primary">登录</button> </div> </form> <div class="container mt-3 justify-content-center"> <div class="container"> <p class="text-danger">{{.Msg}}</p> </div> </div> </div> </div> </div> </body> </html>
- 后端代码
main.go
package main import ( "log" "net/http" "text/template" ) type Message struct { Msg string } func home(w http.ResponseWriter, r *http.Request) { if r.Method == "GET" { w.Header().Set("Location", "/login") w.WriteHeader(http.StatusFound) } } func login(w http.ResponseWriter, r *http.Request) { t, _ := template.ParseFiles("./static/login.html") if r.Method == "GET" { t.Execute(w, nil) } else { r.ParseForm() account := r.Form["account"][0] userPwd := r.Form["password"][0] if account == "tantianran" { if userPwd == "1qaz#EDC" { msg := Message{Msg: "恭喜!验证通过O(∩_∩)O"} t.Execute(w, msg) } else { msg := Message{Msg: "密码错误..."} t.Execute(w, msg) } } else { msg := Message{Msg: "用户名错误..."} t.Execute(w, msg) } } } func main() { http.HandleFunc("/", home) http.HandleFunc("/login", login) listenAddr := ":80" log.Println("ListenAndserve", listenAddr) err := http.ListenAndServe(listenAddr, nil) if err != nil { log.Println(err) } }
- 看看页面效果
- 提交到gitab
git add . git commit -m "add code" git push
编译和打包镜像
- 编译
[root@workhost src]# git clone http://192.168.11.254:8088/tantianran/goweb.git^C [root@workhost src]# cd goweb/ [root@workhost goweb]# go build main.go
- 编写Dockerfile
这个 Dockerfile 的作用是将一个 Golang Web 应用程序打包为一个 Docker 镜像,使其可以在 Docker 容器中运行并通过 80 端口对外提供服务。
FROM golang:latest WORKDIR /app COPY static /app/static COPY main /app EXPOSE 80 CMD ["./main"]
指令解释:
- 开始构建镜像
根据 Dockerfile 构建一个 Docker 镜像并给镜像打上标签。
docker build -t 192.168.11.254:8081/webdemo/goweb:20230427v1 .
- 启动容器
docker run -d -it --name goweb -p 8090:80 192.168.11.254:8081/webdemo/goweb:20230427v1
- 访问
- 推送到私有仓库
确保镜像没问题之后,推送到Harbor
docker push 192.168.11.254:8081/webdemo/goweb:20230427v1
安装ingress-nginx
这里我打算使用ingress的方式来暴露应用,使用比较主流的ingress-nginx。
- 部署ingress-nginx
因为是内网的K8S测试集群,为了能够快速测试,以下deploy.yaml中暴露Controller的方式是使用NodePort,这种方式适用于几乎所有的集群,但通常会使用30000-32767范围内的端口。
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.7.0/deploy/static/provider/baremetal/deploy.yaml
- 部署完后查看:
tantianran@k8s-b-master:~/nginx-ingress$ kubectl get pod,svc -n ingress-nginx NAME READY STATUS RESTARTS AGE pod/ingress-nginx-admission-create-6fp24 0/1 Completed 0 9m54s pod/ingress-nginx-admission-patch-nvtjv 0/1 Completed 0 9m54s pod/ingress-nginx-controller-6b87568f97-kpms9 1/1 Running 0 9m54s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/ingress-nginx-controller NodePort 10.96.106.100 <none> 80:31179/TCP,443:30701/TCP 9m55s service/ingress-nginx-controller-admission ClusterIP 10.106.222.181 <none> 443/TCP 9m55s tantianran@k8s-b-master:~/nginx-ingress$
手工部署到K8S
- 部署Deployment、Service以及创建Ingress规则
apiVersion: apps/v1 kind: Deployment metadata: labels: app: goweb name: goweb spec: replicas: 1 selector: matchLabels: app: goweb template: metadata: labels: app: goweb spec: containers: - image: 192.168.11.254:8081/webdemo/goweb:20230427v1 name: goweb --- apiVersion: v1 kind: Service metadata: labels: app: goweb name: goweb spec: ports: - name: http-port port: 5678 protocol: TCP targetPort: 80 selector: app: goweb type: ClusterIP --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: goweb spec: ingressClassName: nginx rules: - host: "test.goweb.com" http: paths: - path: / pathType: Prefix backend: service: name: goweb port: number: 5678
- 部署完成后查看
tantianran@k8s-b-master:~/goweb$ kubectl get svc,pod,ingress NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/goweb ClusterIP 10.111.92.32 <none> 5678/TCP 2m4s service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 23h NAME READY STATUS RESTARTS AGE pod/goweb-57c44c897d-frxf6 1/1 Running 0 2m4s pod/nfs-client-provisioner-6685d955d-p9w57 1/1 Running 1 (12m ago) 12h NAME CLASS HOSTS ADDRESS PORTS AGE ingress.networking.k8s.io/goweb nginx test.goweb.com 192.168.11.101 80 2m4s tantianran@k8s-b-master:~/goweb$
- 添加域名映射
推荐大家使用SwitchHosts工具来管理hosts,方便日常测试。
- 测试访问