Java程序员如何快速理解Kubernetes

本文涉及的产品
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
简介: 我们希望微服务是可复制的,可替换的工作节点,这样可以轻松进行升级或降级,同时无需任何停机时间,并花费最少代价的管理。我们可以说我们希望他们成为我们的小黄人(minions)。本文我们将通过一个简单的例子来了解Kubernetes可以通过创建和编排一群“小黄人"来为我们做些什么。
我们希望微服务是可复制的,可替换的工作节点,这样可以轻松进行升级或降级,同时无需任何停机时间,并花费最少代价的管理。我们可以说我们希望他们成为我们的小黄人(minions)。本文我们将通过一个简单的例子来了解Kubernetes可以通过创建和编排一群“小黄人"来为我们做些什么。您可以与本文一起编码或从 此处 克隆项目。

先决条件

需要将使用Docker容器化微服务以便在Kubernetes中运行它们。我们将使用Minikube,而不是使用云托管的Kubernetes,以便可以在本地沙箱运行。

目的


我们的小黄人军团将是Java微服务。我们希望军团中有不同类型的工作角色,以便能够了解Kubernetes可以为我们做些什么。因此,我们的目标是让每个微服务都响应一个简单的http请求,其响应如下:
1.png

使用ASCII字来表示minion的类型。

构建Java Minion服务

我们可以通过Spring Boot Web应用程序来启动我们的微服务,程序使用具有Web启动依赖性的 Spring Initializr 初始化:
2.png

在项目中,创建一个使用@RestController注释的Controller来处理请求。使用@RequestMapping(method = GET)来提供响应主体。所以首先我们可以这样做:
@RequestMapping( method=GET)

@ResponseBody

public String minion() throws UnknownHostException {

StringBuilder stringBuilder = new StringBuilder();

stringBuilder.append("Host: ").append(InetAddress.getLocalHost().getHostName()).append("<br/>");

return stringBuilder.toString();

} 

但这并不能完全满足需求。我们可以输出ASCII字,但选择哪种minion类型?为此可以使用一个技巧。创建一个可以采用我们选择的任何minion类型的应用程序。要做到这一点,需要它包含一个ASCII艺术字库。因此,我们创建了一个名为MinionsLibrary的类,使用@Component注解,在内部我们创建了一个地图,我们使用 此博客 中的一些minions初始化:
@Component

public class MinionsLibrary {

private Map<String,String> map = new HashMap<>();

public MinionsLibrary(){

 map.put("one-eyed-minion",<COPY-PASTE MINION ASCII ART HERE>);

 map.put("two-eyed-minion",<COPY-PASTE MINION ASCII ART HERE>);

 map.put("sad-minion",<COPY-PASTE MINION ASCII ART HERE>);

 map.put("happy-minion",<COPY-PASTE MINION ASCII ART HERE>);

}

} 

或者你可以从 https://github.com/ryandawsonu ... /demo 获取。

然后告诉微服务是哪种minion类型。使用Spring应用程序的名称属性(我们稍后可以使用Docker环境变量设置)来执行此操作。它还将帮助我们稍后在响应中显示我们的应用程序版本,所以现在的Controller变为:
@RestController

public class Controller {

private final String version = "0.1";

private MinionsLibrary minionsLibrary;

@Value("${spring.application.name}")

private String appName;

public Controller(MinionsLibrary minionsLibrary){

 this.minionsLibrary=minionsLibrary;

}

@RequestMapping( method=GET)

@ResponseBody

public String minion() throws UnknownHostException {

 StringBuilder stringBuilder = new StringBuilder();

 stringBuilder.append("Host: ").append(InetAddress.getLocalHost().getHostName()).append("<br/>");

 stringBuilder.append("Minion Type: ").append(appName).append("<br/>");

 stringBuilder.append("IP: ").append(InetAddress.getLocalHost().getHostAddress()).append("<br/>");

 stringBuilder.append("Version: ").append(version).append("<br/>");

 stringBuilder.append(minionsLibrary.getMinion(appName));

 return stringBuilder.toString();

}

} 

现在选择'image'包以匹配应用程序名称,该名称将是minion类型名称(例如'单眼小黄人')。

容器化并部署

需要为我们的应用程序创建一个Docker镜像。我们想在Docker镜像中构建可执行的jar,然后在容器启动时启动Java应用程序。可以使用多阶段Docker构建来完成此任务。 Dockerfile是:
FROM maven:3.5-jdk-8 as BUILDMINION

COPY src /usr/src/myapp/src

COPY pom.xml /usr/src/myapp

RUN mvn -f /usr/src/myapp/pom.xml clean package -DskipTests

FROM openjdk:alpine

COPY --from=BUILDMINION /usr/src/myapp/target/*.jar /maven/

CMD java $JAVA_OPTS -jar maven/*.jar


从开始到'FROM openjdk:alpine'是构建JAR,然后jar包被拷贝到基于轻量的openjdk:alpine镜像的下一阶段构建。使用JAVA_OPTS参数来限制程序的内存占用(关于降低内存,可以参考 该文章 )。

然后使用命令“docker build . -t minion”构建一个镜像。

通过创建Kubernetes部署文件来部署它。我们称之为“minion-army.yml”。这将包含每个minion类型的条目。这是其中的一个minion类型:
apiVersion: apps/v1beta1

kind: Deployment

metadata:

name: one-eyed-minion

labels:

serviceType: one-eyed-minion

spec:

replicas: 2

template:

metadata:

 name: one-eyed-minion

 labels:

 serviceType: one-eyed-minion

spec:

 containers:

 - name: one-eyed-minion

 image: minion:latest

 imagePullPolicy: Never

 ports:

 - containerPort: 8080

 env:

 - name: JAVA_OPTS

 value: -Xmx64m -Xms64m

 - name: SPRING_APPLICATION_NAME

 value: "one-eyed-minion"

---

apiVersion: v1

kind: Service

metadata:

name: one-eyed-minion-entrypoint

namespace: default

spec:

selector:

serviceType: one-eyed-minion

ports:
- port: 8080

 targetPort: 8080

 nodePort: 30080

type: NodePort

请注意,“SPRING_APPLICATION_NAME”变量会自动与spring.application.name属性匹配,以便此minion服务成为单眼小黄人类型。有两个这种minion类型的实例(副本)可用,Kubernetes服务将自动将请求路由到其中一个或另一个。

该服务将通过Minikube以端口30080暴露对外提供服务 (对于真正的Kubernetes,该服务的这一点会有所不同,因为我们使用LoadBalancer而不是NodePort,并且不会限制在minikube端口范围)。服务将使用与服务匹配的Pod来处理它。我们将为每种类型提供一种服务。

minion类型的部署将创建两个Pod。每个人都是这种类型的工作节点。

我们可以为每个minion类型重复上面的配置,每次增加外部端口号以便使用不同的端口,或者我们可以使用这个GitHub存储库,它还具有其他配置,可以在不停机的情况下进行小型版本升级(如果我们使用Helm,我们可以避免重复,但我们不想添加比我们更多的工具)。

创建军团

首先启动mMinikube:
minikube start --memory 4000 --cpus 3

等待它开始,然后将您的Docker registry链接到Minikube,并为Minikube构建minion图像:
eval $(minikube docker-env)

docker build . -t minion

然后我们可以部署军团:
kubectl create -f minion-army.yml

并看到类型:
open http://$(minikube ip):30080

open http://$(minikube ip):30081

open http://$(minikube ip):30082

open http://$(minikube ip):30083

每个看起来都很像文章开头的快乐小黄人页面。

我们可以通过“kubectl get pods”来查看整个军队,或者“minikube dashboard”进到Pods页面:
3.png

创造更多的部队

我们可以在minikube dashboard的Deployments部分下创建更多特定类型的minions:
4.png

一个小黄人倒下,另一个替补他的位置

假设从浏览器点击快乐小黄人服务时得到的:
5.png

如果杀死“happy-minion-58c9c46d67-j84s9”会发生什么?可以通过仪表板的Pod部分删除:
kubectl delete pod happy-minion-58c9c46d67-j84s9

如果你在浏览器中点击刷新几次(杀死小黄人兵可能需要一点时间),你会看到该服务会使用该类型的另一个小黄人。如果浏览Pod部分,您将看到Kubernetes创建了一个新的Pod来代替您删除的那个,以保证该部署中有两个节点。

Minion升级

我们还可以为小黄人进行滚动升级。为此,我们应该在minions-army.yml文件的每个Deployment部分的'spec'部分下面(它可以直接位于同一级别的'replicas'下面):
minReadySeconds: 10

strategy:

type: RollingUpdate

rollingUpdate:

 maxUnavailable: 1

 maxSurge: 1

然后将Controller类中的版本更改为0.2,保存它然后执行:
docker build . -t minion:0.2

然后打开minion-army.yml并找到 - 用“0.2”替换所有“最新”,保存更改并执行:
kubectl apply -f minion-army.yml --record

刷新其中一个minion类型的浏览器,以查看版本更改是否与kubectl rollout status部署中看到的内容一致,其中<deployment_name>是minion类型(例如one-eyed-minion)。

小黄人回滚

要查看已部署的历史记录,请执行kubectl rollout history deployment <deployment_name>,回滚执行 kubectl rollout undo deployment <deployment_name> --to-revision = 1(可能需要一段时间)。

销毁军团

用以下方法摧毁军队:
kubectl delete -f minion-army.yml

用“minikube stop”停止minikube。

本文转自DockOne-p2p-Java程序员如何快速理解Kubernetes

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
19天前
|
Java 程序员
JAVA程序员的进阶之路:掌握URL与URLConnection,轻松玩转网络资源!
在Java编程中,网络资源的获取与处理至关重要。本文介绍了如何使用URL与URLConnection高效、准确地获取网络资源。首先,通过`java.net.URL`类定位网络资源;其次,利用`URLConnection`类实现资源的读取与写入。文章还提供了最佳实践,包括异常处理、连接池、超时设置和请求头与响应头的合理配置,帮助Java程序员提升技能,应对复杂网络编程场景。
43 9
|
3月前
|
存储 算法 Java
惊!Java程序员必看:JVM调优揭秘,堆溢出、栈溢出如何巧妙化解?
【8月更文挑战第29天】在Java领域,JVM是代码运行的基础,但需适当调优以发挥最佳性能。本文探讨了JVM中常见的堆溢出和栈溢出问题及其解决方法。堆溢出发生在堆空间不足时,可通过增加堆空间、优化代码及释放对象解决;栈溢出则因递归调用过深或线程过多引起,调整栈大小、优化算法和使用线程池可有效应对。通过合理配置和调优JVM,可确保Java应用稳定高效运行。
140 4
|
3月前
|
算法 Java 程序员
在Java的编程世界里,多态不仅仅是一种代码层面的技术,它是思想的碰撞,是程序员对现实世界复杂性的抽象映射,是对软件设计哲学的深刻领悟。
在Java的编程世界里,多态不仅仅是一种代码层面的技术,它是思想的碰撞,是程序员对现实世界复杂性的抽象映射,是对软件设计哲学的深刻领悟。
68 9
|
3月前
|
Java 程序员
Java数据类型:为什么程序员都爱它?
Java数据类型:为什么程序员都爱它?
52 1
|
3月前
|
Kubernetes jenkins 持续交付
从代码到k8s部署应有尽有系列-java源码之String详解
本文详细介绍了一个基于 `gitlab + jenkins + harbor + k8s` 的自动化部署环境搭建流程。其中,`gitlab` 用于代码托管和 CI,`jenkins` 负责 CD 发布,`harbor` 作为镜像仓库,而 `k8s` 则用于运行服务。文章具体介绍了每项工具的部署步骤,并提供了详细的配置信息和示例代码。此外,还特别指出中间件(如 MySQL、Redis 等)应部署在 K8s 之外,以确保服务稳定性和独立性。通过本文,读者可以学习如何在本地环境中搭建一套完整的自动化部署系统。
69 0
|
4天前
|
SQL 存储 Java
面向 Java 程序员的 SQLite 替代品
SQLite 是轻量级数据库,适用于小微型应用,但其对外部数据源支持较弱、无存储过程等问题影响了开发效率。esProc SPL 是一个纯 Java 开发的免费开源工具,支持标准 JDBC 接口,提供丰富的数据源访问、强大的流程控制和高效的数据处理能力,尤其适合 Java 和安卓开发。SPL 代码简洁易懂,支持热切换,可大幅提高开发效率。
|
16天前
|
SQL Java 程序员
倍增 Java 程序员的开发效率
应用计算困境:Java 作为主流开发语言,在数据处理方面存在复杂度高的问题,而 SQL 虽然简洁但受限于数据库架构。SPL(Structured Process Language)是一种纯 Java 开发的数据处理语言,结合了 Java 的架构灵活性和 SQL 的简洁性。SPL 提供简洁的语法、完善的计算能力、高效的 IDE、大数据支持、与 Java 应用无缝集成以及开放性和热切换特性,能够大幅提升开发效率和性能。
|
21天前
|
IDE Java 程序员
C++ 程序员的 Java 指南
一个 C++ 程序员自己总结的 Java 学习中应该注意的点。
20 5
|
1月前
|
Java 大数据 程序员
我的程序员之路:自学Java篇
我的程序员之路:自学Java篇
|
1月前
|
Kubernetes Cloud Native 流计算
Flink-12 Flink Java 3分钟上手 Kubernetes云原生下的Flink集群 Rancher Stateful Set yaml详细 扩容缩容部署 Docker容器编排
Flink-12 Flink Java 3分钟上手 Kubernetes云原生下的Flink集群 Rancher Stateful Set yaml详细 扩容缩容部署 Docker容器编排
73 0