从做项目开始的单机应用本地调试,到项目打包放到服务器上运行,再到后来的容器虚拟化技术docker,一路走来都踩了很多坑。最近即将走进社会,在公司实习的时候,要求实习项目需要在使用Kubernetes
来使用部署。又踩了很多的坑,现在一一来记录。那些基本的知识这里不再进行赘述了,讲一下项目打包的流程及其具体命令吧。
项目打包到Kubernetes 部署发布的全过程:
- 代码编写
- 项目打包
- 镜像打包
- 推送镜像到远程仓库
- Kubernetes 创建pod 对象的yaml文件
- 使用命令创建pod
- 对相应的pod进行端口暴露
但是我因为是实习的身份,公司只给了一个测试的Kubernetes 集群,没有给远程仓库权限,只能将代码拉到测试机上,然后本地打包镜像然后再部署,其实流程是差不多的。就是打包镜像的操作是再测试机上,然后Kubernetes 拉去的镜像地址设置为本地拉取就好了。
再来说一下我的实习项目,我的实习项目是做一个配置平台,用于管理配置的,分为前端,后台,数据库还有管理主要加载配置的机器(支持优雅重启)。那么我们直接跳过代码编写的部分,我的项目值基于GVA项目的二开,GVA本身是自带docker容器化的一些信息的,支持docker-compose一键部署的(但是有一个GVA有个坑,很容易后台项目比数据库先起动完毕,然后后台会判断没有数据库,然后让你初始化数据库…所以每次我都是先把数据库启动起来先)
说正事…
我们来说一下镜像打包吧,项目本身是包含一个docker-compose.yaml文件,一键用于一键打包启动web、server、mysql、redis的,里面设置了一个网桥,用于项目内部进行通信的。但是由于我们的项目要通过Kubernetes 进行部署,所以那些配置基本上都是用不上了。我们要自己手动书写Dockerfile来进行镜像打包。一般数据库都是外置的,需要进行持久化操作的,一般不会放在Kubernetes 里面部署,所以这里主要是server和web项目的镜像打包。
以下是镜像打包的文件内容,其大概意思都是差不多的,from一个基础镜像,将代码文件拉进镜像里来,设置一个必要的环境变量,然后进行打包,运行
# dockerfile_server
FROM golang:alpine
ENV GO111MODULE=on
ENV GOPROXY=https://goproxy.cn
WORKDIR /go/src/gin-vue-admin
COPY server/ ./
RUN cat ./config.yaml
RUN go env && go build -o server .
FROM alpine:latest
LABEL MAINTAINER="SliverHorn@sliver_horn@qq.com"
WORKDIR /go/src/gin-vue-admin
COPY --from=0 /go/src/gin-vue-admin/server ./
COPY --from=0 /go/src/gin-vue-admin/config.yaml ./
COPY --from=0 /go/src/gin-vue-admin/resource ./resource
EXPOSE 8888
ENTRYPOINT ./server
# FROM node:12.16.1
WORKDIR /gva_web/
COPY web/ .
RUN npm install -g cnpm --registry=https://registry.npm.taobao.org
RUN cnpm install || npm install
RUN npm run build
FROM nginx:alpine
COPY .docker-compose/nginx/conf.d/my.conf /etc/nginx/conf.d/my.conf
COPY --from=0 /gva_web/dist /usr/share/nginx/html
RUN cat /etc/nginx/nginx.conf
RUN cat /etc/nginx/conf.d/my.conf
RUN ls -al /usr/share/nginx/html
CMD ls -al /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
特别注意:这里的前端web项目是基于nginx进行镜像打包的,而容器是判断有没有程序在运行来是否继续下去的,如果没有最后一句的nginx命令,打包操作运行完ls
-al之后,就会直接退出,这一点很重要
我这里的打包命令是
docker build -t gva-server:1.0.0 -f dockerfile_server .
docker build -t gva-web:1.0.0 -f dockerfile_web .
# docker build -t 项目名:标签名 -f dockerfile位置 .
经过上面的步骤,如果dockerfile没有编写错误的话,docker会把相关的项目打包成为一个镜像。如果配有远程仓库的话,可以将这个镜像推送到远程的仓库。然后再项目打包的时候,拉取远程仓库的镜像就行了。
然后就是Kubernetes的pod对象创建了,这里我们一般使用配置文件来创建管理pod
kubectl create deployment gva-server --image=gin-server:1.0.0 --dry-run -o yaml > gva-server.yaml
# 以上命令会生成一个用于创建和管理pod的yaml文件
# kubectl create deployment 项目名 --image=镜像地址(远程仓库地址/本地地址) --dry-run -0 yaml > 文件名.yaml
由于我这里使用的本地镜像,要在gva-server.yaml文件里面加入一个只在本地拉去的配置信息imagePullPolicy: Never
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: gva-server
name: gva-server
spec:
replicas: 1
selector:
matchLabels:
app: gva-server
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: gva-server
spec:
containers:
- image: gva-server:1.0.0
name: gva-server
resources: {}
imagePullPolicy: Never # <---只拉取本地镜像
status: {}
把对于的配置文件信息修改完毕之后,我们就可以创建pod了
# 创建pod
kubectl apply -f gva-server.yaml
# 查看pod运行情况
kubectl get pods
# 查看pod日志
kubectl logs gva-server-XXXXX # get pods 对于记录的名称
# 进入pod容器
kubectl exec -it gva-server-XXXXX /bin/bash
# 删除对应的pod
kubectl delete -f gva-server.yaml
以上步骤就创建了pod了,但是我们不能进行访问,需要对外进行暴露端口
kubectl expose deploy gva-server --port=8888 --target-port=8888 --type=NodePort
kubectl get svc #查看端口暴露情况 type:NodePort对外保留/ClusterIP对内暴露
对外暴露的端口是随机的,要通过kubectl get svc
查看,具体我也不知道这个–target-port指定的是什么
特别注意:由于Kubernetes推送的pod节点是随机的,所以前后端项目进行通信的时候指定的IP地址也是不确定的,这时候我们可以使用pod名字进行访问,他自己会识别成为对应的IP地址。
例如:http://177.7.0.13:8080
可以变成 http://gva-server:8080
以上就是我在使用kubernetes的时候所遇到的一些问题还有解决方案,但是每个pod之间还是ping不通,不知道为什么,我记得kubernetes是可以配置一个网桥的,用于pod节点进行通信,但是忘了具体怎么做了,知道的小伙伴可以分享一下,帮助一下小白本白