目前我对运维相关的东西也不熟,这里仅仅是简单地使用,部署在多个Pod中运行的Go服务主要是用于对分布式锁是否生效的测试。
集群、节点、Pod、容器、镜像仓库、镜像的关系大致如下:
电脑中已经安装好了docker和k8s:
shell
$ kubectl version --short
Flag --short has been deprecated, and will be removed in the future. The --short output will become the default.
Client Version: v1.25.9
Kustomize Version: v4.5.7
Server Version: v1.25.9
$ docker version
Client:
Cloud integration: v1.0.33
Version: 24.0.2
API version: 1.43
Go version: go1.20.4
Git commit: cb74dfc
Built: Thu May 25 21:51:16 2023
OS/Arch: darwin/amd64
Context: desktop-linux
Server: Docker Desktop 4.20.1 (110738)
Engine:
Version: 24.0.2
API version: 1.43 (minimum version 1.12)
Go version: go1.20.4
Git commit: 659604f
Built: Thu May 25 21:52:17 2023
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.6.21
GitCommit: 3dce8eb055cbb6872793272b4f20ed16117344f8
runc:
Version: 1.1.7
GitCommit: v1.1.7-0-g860f061
docker-init:
Version: 0.19.0
GitCommit: de40ad0
构建镜像
创建Dockerfile
文件,内容如下:
dockerfile
# FROM 指定基础镜像
FROM ubuntu:20.04
# 把编译好的rdl可执行文件复制到Docker内的 /app/rdl中
COPY rdl /app/rdl
# 指定/app为工作目录
WORKDIR /app
# Docker的启动程序的命令是
CMD ["/app/rdl"]
为了执行命令比较方便,创建Makefile
文件,内容如下:
mekefile
.PHONY: build
build:
# 删除之前生成的rdl可执行文件, 如果文件不存在, 会走到 || true
@rm rdl || true
# 编译出在linux环境下执行的可执行文件
@GOOS=linux GOARCH=arm go build -o rdl .
# 删除已经存在的镜像
@docker rmi -f rengmo/rdl:v0.0.1
# 构建镜像
@docker build -t rengmo/rdl:v0.0.1 .
在终端执行以下命令构建镜像:
shell
$ make build
构建成功之后打开Docker桌面应用程序能看到新构建的镜像:
K8s部署服务
创建Go服务的Deployment配置文件web/deployment.yaml
,内容如下:
yaml
# 按照apps/v1的方式处理这个配置
apiVersion: apps/v1
# 配置的类型是Deployment
kind: Deployment
# 元数据
metadata:
# 名称
name: rdl
# specification 规范说明
spec:
# 表示运行2个Pod
replicas: 2
# 选择器
selector:
# 选择包含以下标签的Pod
matchLabels:
app: rdl
# 模板表示如何创建Pod
# 比如以下内容就表示创建包含标签app:rdl, 容器rengmo/rdl:v0.0.1, 有一定资源大小限制, 容器监听的端口号是8080的Pod
template:
# Pod的元数据
metadata:
# 包含标签app: rdl
labels:
app: rdl
# 规范说明
spec:
# 包含的容器
containers:
# 容器的名称
- name: rdl
# 容器中包含的镜像
image: rengmo/rdl:v0.0.1
# 资源的配置
# resources:
# # 限制使用资源的大小
# limits:
# memory: "128Mi"
# cpu: "500m"
# 端口号
ports:
# 容器中的镜像,也就是rengmo/rdl:v0.0.1监听的端口号
- containerPort: 8080
创建Go服务的Service配置文件web/service.yaml
:
yaml
# 按照v1的方式处理这个配置
apiVersion: v1
# 配置的类型是Service
kind: Service
# 元数据
metadata:
# 配置的名称为rdl
name: rdl
# 规范说明
spec:
# 选择标签为app: rdl的Pod
selector:
app: rdl
# 端口号
ports:
# 外部访问的端口
- port: 8080
# 内部pod使用的端口
targetPort: 8080
# 使用k8s的负载均衡器提供外部可访问的IP地址
type: LoadBalancer
创建Redis的Deployment配置文件redis/deployment.yaml
:
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: rdl-redis
spec:
selector:
matchLabels:
app: rdl-redis
template:
metadata:
labels:
app: rdl-redis
spec:
containers:
- name: rdl-redis
image: redis:7.0.0
resources:
limits:
memory: "128Mi"
cpu: "500m"
ports:
- containerPort: 6379
创建Redis的Service配置文件redis/service.yaml
:
yaml
apiVersion: v1
kind: Service
metadata:
name: rdl-redis
spec:
selector:
app: rdl-redis
ports:
- port: 6380
nodePort: 31379
targetPort: 6379
type: LoadBalancer
执行以命令应用配置:
shell
$ kubectl apply -f ./deployment/redis/deployment.yaml
deployment.apps/rdl-redis created
$ kubectl apply -f ./deployment/redis/service.yaml
service/rdl-redis created
$ kubectl apply -f ./deployment/web/deployment.yaml
deployment.apps/rdl created
$ kubectl apply -f ./deployment/web/service.yaml
service/rdl created
为了方便配置文件修改之后重新应用,在Makefile文件中添加了以下内容:
makefile
# 重新应用配置
reapply: k8sd k8sa
.PHONY: reapply
# 应用配置
.PHONY: k8sa
k8sa:
@kubectl apply -f ./deployment/redis/deployment.yaml
@kubectl apply -f ./deployment/redis/service.yaml
@kubectl apply -f ./deployment/web/deployment.yaml
@kubectl apply -f ./deployment/web/service.yaml
# 删除资源
.PHONY: k8sd
k8sd:
@kubectl delete deployment rdl
@kubectl delete service rdl
@kubectl delete deployment rdl-redis
@kubectl delete service rdl-redis
执行make k8sa
应用所有对应的配置文件,执行make k8sd
删除对应的资源,在修改了配置文件之后,可以使用make reapply
指令重新应用配置文件。
应用完配置文件之后可以打开Docker桌面应用程序,可以在Container中看到服务的日志:
在终端执行以下命令查看是否能正常连接Redis服务:
shell
$ redis-cli -h 127.0.0.1 -p 6380
执行以下命令查看是否能正常请求接口:
shell
$ curl -X POST http://localhost:8080/inventory/sale
解决问题
- 执行完之后查看pod,发现有一个pod一直处于pending中:
shell
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
rdl-56b6f9f5b8-lcq95 1/1 Running 1 25m
rdl-56b6f9f5b8-r8bzb 0/1 Pending 0 25m
rdl-redis-64755679bf-pxq75 1/1 Running 2 26m
把service配置文件的资源限制部分注释了就不存在这个问题了。应该是由于分配的资源不足才会一直Pending的。