简单速通K8S
安装环境
使用VMware虚拟机部署K8S集群。我是参考这篇博客部署的遇到的问题比较少 手把手教你在虚拟机中部署Kubernetes集群(K8S)
我这里部署的是一台master主节点,和两台woker 工作节点
安装k8s dashboard,这里也略过,网上可以找到很多参考的
下面我们创建一个springboot应用来试一下K8S的 自愈能力、弹性伸缩,容器编排零停机更新应用版本
首先创建一个springboot应用。这里我们需要在pom文件引入Actuator依赖。他提供了k8s的/actuator/health健康检查接口
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
并在application.yml添加以下内容
management:
endpoints:
web:
exposure:
include: health,info # 暴露健康检查端点
endpoint:
health:
show-details: always # 显示详细健康信息
接着我们可以在springboot里面加一个controller添加一个测试方法来拉高我们的CPU以达到测试弹性扩缩容的目的,代码如下
@PostMapping("/cpu-stress")
public String cpuStressTest(
@RequestParam(defaultValue = "60", name = "targetCpuLoad") int targetCpuLoad,
@RequestParam(defaultValue = "60", name = "durationSeconds") int durationSeconds) {
if (targetCpuLoad < 1 || targetCpuLoad > 100) {
return "CPU负载参数必须在1-100之间";
}
int processors = Runtime.getRuntime().availableProcessors();
ExecutorService executor = Executors.newFixedThreadPool(processors);
AtomicBoolean running = new AtomicBoolean(true);
// 设置超时停止
Executors.newSingleThreadScheduledExecutor().schedule(() -> {
running.set(false);
executor.shutdownNow();
}, durationSeconds, TimeUnit.SECONDS);
// 创建负载线程
for (int i = 0; i < processors; i++) {
executor.submit(() -> {
long busyTime = (long) (targetCpuLoad * 10000); // 微秒
long idleTime = 1000000 - busyTime;
while (running.get()) {
long startTime = System.nanoTime();
// 繁忙循环
while ((System.nanoTime() - startTime) < busyTime * 1000 && running.get()) {
// 空循环制造CPU负载
}
try {
if (idleTime > 0) {
Thread.sleep(idleTime / 1000, (int) (idleTime % 1000));
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return;
}
}
});
}
return String.format("正在制造%d%%的CPU负载,持续%d秒", targetCpuLoad, durationSeconds);
}
接着就是部署到我们的K8S集群了
我们先把我们的springboot打包成jar包在打成镜像放到我们的k8s集群上面去。正常是可以把镜像推到远端仓库直接在k8s上拉取,但是dockerhub被墙了又懒得去注册其他私仓。这里我选择直接把镜像放到k8s集群上解析成镜像。
- 首先把springboot打成jar包。然后编写DockerFile打包成镜像
FROM openjdk:17-jdk-slim-bullseye
COPY target/K8S_demo1.jar app.jar
EXPOSE 8081
ENTRYPOINT ["java","-jar","/app.jar","--server.port=8081"]
- 执行docker build命令打包成镜像
docker build -t springboot-cpu-test:1.0 .
- 执行docker save 把镜像打成tar包传到我们k8s集群的节点上
docker save -o springboot-cpu-test.tar springboot-cpu-test:1.0
- 在k8s集群上执行 docker load 把tar包加载成镜像
docker load -i springboot-cpu-test.tar
- 编写deployment.yaml 和 service.yaml 这里说明以下k8s部署通常需要两个yaml 。deployment.yaml 负责定义和管理应用的副本(Pod)。它确保应用在集群中的可用性、伸缩性和滚动更新等。
Service 是 Kubernetes 中的一种资源,用于将请求路由到指定的 Pods。它提供了一个稳定的访问入口,可以跨多个 Pod 进行负载均衡。
deployment.yaml 内容如下
apiVersion: apps/v1
kind: Deployment
metadata:
name: springboot-cpu-test
spec:
replicas: 1
selector:
matchLabels:
app: springboot-cpu-test
template:
metadata:
labels:
app: springboot-cpu-test
spec:
containers:
- name: springboot-app
image: springboot-cpu-test:1.0
imagePullPolicy: Never
ports:
- containerPort: 8081
resources:
limits:
cpu: "1"
memory: "512Mi"
requests:
cpu: "500m"
memory: "256Mi"
livenessProbe:
httpGet:
path: /actuator/health
port: 8081
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /actuator/health
port: 8081
initialDelaySeconds: 20
periodSeconds: 5
service.yaml 内容如下
apiVersion: v1
kind: Service
metadata:
name: springboot-cpu-service
spec:
selector:
app: springboot-cpu-test
ports:
- protocol: TCP
port: 80
targetPort: 8081
type: NodePort
- 执行kubectl apply 指令部署到k8s集群上
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
-
接着我们就可以在dashboard看到我们的springboot已经部署成功
-
可以看到我们的应用已经成功部署在woker2节点,接着我们用apifox调用以下前面引入依赖的健康检查接口,可以发现已经能够调用成功了
-
接着我们尝试一下删除这个pod以及关闭其中一个工作节点,来查看k8s自愈表现,首先再删除我们的pod之后k8s帮我们再重启一个。可以看到k8s在外面删除的时候,就自动帮我们在重启了一个pod。然后我们再尝试的去关闭我们springboot应用部署的那台节点的虚拟机
可以看到在我们关闭当前springboot应用部署的节点woker1之后k8s自动帮我们迁移到健康的节点woker2
-
接着尝试一下我们的滚动更新,这是k8s让我觉得非常好用的功能。平时我们更新的时候都会导致服务中断。虽然可以通过代理集群调整权重来逐个更新。但是太过于繁琐k8s这个滚动更新可以做到。我们更新的时候在新应用更新完毕才会替换掉旧应用,更新期间服务不会中断。
我们原先的应用镜像打的是1.0版本我打了一个1.1版本的放到了服务器上。然后修改deployment.yaml中的镜像版本改为1.1。然后执行(中间忘了截图所以我又打了一个1.2的截图展示)这里可以看到我们执行完kubectl apply后1.1版本的pod不会马上关闭,仍然在运行中。它会逐步地替换旧版本的 Pod,而不需要停机。最后1.2版本运行稳定后1.1版本的pod会自动关闭掉。
kubectl apply -f deployment.yaml
- 接着我们来试一下他的自动扩缩容功能。这里我们需要编写一个hpa.yaml,hpa的职责是负责动态扩缩容的。内容如下
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
name: springboot-cpu-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: springboot-cpu-test
minReplicas: 1
maxReplicas: 5
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 30 # 当CPU大于百分之30时触发扩容
- 接着执行
kubectl apply -f hpa.yaml
接着执行
kubectl get hpa
这里我们发现无法获取到pod的CPU出现了unknown,原因是Metrics Server 未正确安装或运行,这里我们给他装一下,执行以下命令。如果无法拉取到的话。我们可以直接创建一个components.yaml去网上找到他的内容放进去,执行kubectl apply -f components.yaml。执行完后我们看到已经运行起来了。
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
安装完就可以发现,包括我们的dashboard里面也有了CPU 以及内存的监控数据
- 那么下面我们就来执行以下我们的主动拉高CPU的一个测试方法,执行完就可以看到。我们的CPU上升,并且k8s根据我们的CPU阈值扩容增加了pod,等到我们的CPU降下来之后又减少到初始pod数量