本文介绍将自己编写的 Java 程序部署到 kubernetes 集群中。
我们编写一个简单的程序,访问 /hello
返回 Hello World!!!
字符串。
整个程序的结构如下:
[root@zsx proj]# tree demo/
demo/
├── demo.iml
├── pom.xml
├── src
│ ├── main
│ │ ├── java
│ │ │ └── com
│ │ │ └── example
│ │ │ └── demo
│ │ │ ├── controller
│ │ │ │ └── HelloController.java
│ │ │ └── DemoApplication.java
│ │ └── resources
│ │ └── application.properties
│ └── test
│ └── java
│ └── com
│ └── example
│ └── demo
└── target
├── classes
│ ├── application.properties
│ └── com
│ └── example
│ └── demo
│ ├── controller
│ │ └── HelloController.class
│ └── DemoApplication.class
├── demo-0.0.1-SNAPSHOT.jar
├── demo-0.0.1-SNAPSHOT.jar.original
├── Dockerfile
├── generated-sources
│ └── annotations
├── generated-test-sources
│ └── test-annotations
├── maven-archiver
│ └── pom.properties
├── maven-status
│ └── maven-compiler-plugin
│ ├── compile
│ │ └── default-compile
│ │ ├── createdFiles.lst
│ │ └── inputFiles.lst
│ └── testCompile
│ └── default-testCompile
│ ├── createdFiles.lst
│ └── inputFiles.lst
└── test-classes
31 directories, 16 files
[root@zsx proj]# cat demo/src/main/java/com/example/demo/controller/HelloController.java
package com.example.demo.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@RequestMapping("/hello")
public String hello(){
return "Hello World!!!";
}
}
[root@zsx proj]# cat demo/target/Dockerfile
from openjdk:8
COPY *.jar /app.jar
CMD ["--server.port=8080"]
EXPOSE 8080
ENTRYPOINT ["java","-jar","/app.jar"]
# 制作镜像
[root@zsx proj]# cd demo/target/
[root@zsx target]# ll
total 16948
drwxr-xr-x. 3 root root 47 Jun 23 08:00 classes
-rw-r--r--. 1 root root 17345396 Jun 23 08:00 demo-0.0.1-SNAPSHOT.jar
-rw-r--r--. 1 root root 3248 Jun 23 08:00 demo-0.0.1-SNAPSHOT.jar.original
-rw-r--r--. 1 root root 112 Jun 23 08:00 Dockerfile
drwxr-xr-x. 3 root root 25 Jun 23 08:00 generated-sources
drwxr-xr-x. 3 root root 30 Jun 23 08:00 generated-test-sources
drwxr-xr-x. 2 root root 28 Jun 23 08:00 maven-archiver
drwxr-xr-x. 3 root root 35 Jun 23 08:00 maven-status
drwxr-xr-x. 2 root root 6 Jun 23 08:00 test-classes
[root@zsx target]# docker build -t hello:v1 .
Sending build context to Docker daemon 17.37MB
Step 1/5 : from openjdk:8
---> b273004037cc
Step 2/5 : COPY *.jar /app.jar
---> Using cache
---> bf300958001d
Step 3/5 : CMD ["--server.port=8080"]
---> Using cache
---> 9ef21d4b54a5
Step 4/5 : EXPOSE 8080
---> Using cache
---> 8bd2d07448e9
Step 5/5 : ENTRYPOINT ["java","-jar","/app.jar"]
---> Using cache
---> 78775dc52045
Successfully built 78775dc52045
Successfully tagged hello:v1
# 查看镜像
[root@zsx target]# docker images | grep hello
hello v1 78775dc52045 2 minutes ago 543MB
# 发布到阿里云
# 1、登录阿里云Docker Registry
[root@zsx target]# docker login --username=15110820283 registry.cn-hangzhou.aliyuncs.com
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
# 2、打tag
[root@zsx target]# docker tag 78775dc52045 registry.cn-hangzhou.aliyuncs.com/zsxnamespace/zsxck:v1
# 3、将镜像推送到Registry
[root@zsx target]# docker push registry.cn-hangzhou.aliyuncs.com/zsxnamespace/zsxck:v1
The push refers to repository [registry.cn-hangzhou.aliyuncs.com/zsxnamespace/zsxck]
cf382d92a4c7: Pushed
6b5aaff44254: Pushed
53a0b163e995: Pushed
b626401ef603: Pushed
9b55156abf26: Pushed
293d5db30c9f: Pushed
03127cdb479b: Pushed
9c742cd6c7a5: Pushed
v1: digest: sha256:e765450f94561a97ff4f7ba73939b3033b2abde9c6a500570f41c45913374269 size: 2007
# 4、查看镜像
[root@zsx zhangshixing]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
registry.cn-hangzhou.aliyuncs.com/zsxnamespace/zsxck v1 78775dc52045 2 hours ago 543MB
# 5、如果需要退出登录执行下面的命令
[root@master ~]# docker logout
Removing login credentials for https://index.docker.io/v1/
[root@zsx target]# docker run -d -P --name hello-demo hello:v1
0204cd4e1fb6916537aabc837f911239075f3d98ada41dbc3d5ba15291ff31b0
[root@zsx target]# docker ps | grep hello
0204cd4e1fb6 hello:v1 "java -jar /app.jar …" 11 seconds ago Up 9 seconds 0.0.0.0:49153->8080/tcp, :::49153->8080/tcp hello-demo
[root@zsx target]# docker logs 0204cd4e1fb6
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.5.4)
2023-06-23 01:48:09.103 INFO 1 --- [ main] com.example.demo.DemoApplication : Starting DemoApplication v0.0.1-SNAPSHOT using Java 1.8.0_342 on 0204cd4e1fb6 with PID 1 (/app.jar started by root in /)
2023-06-23 01:48:09.117 INFO 1 --- [ main] com.example.demo.DemoApplication : No active profile set, falling back to default profiles: default
2023-06-23 01:48:12.470 INFO 1 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2023-06-23 01:48:12.512 INFO 1 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2023-06-23 01:48:12.512 INFO 1 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.52]
2023-06-23 01:48:12.717 INFO 1 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2023-06-23 01:48:12.717 INFO 1 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 3276 ms
2023-06-23 01:48:14.178 INFO 1 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2023-06-23 01:48:14.202 INFO 1 --- [ main] com.example.demo.DemoApplication : Started DemoApplication in 6.661 seconds (JVM running for 8.083)
[root@zsx target]# curl http://192.168.43.195:49153/hello
Hello World!!!
登录私有仓库需要创建 secret,存储 docker registry 的认证信息。
# 生成secret
[root@master ~]# kubectl create secret docker-registry aliyuncs-docker-secret --docker-server=registry.cn-hangzhou.aliyuncs.com --docker-username=15110820283 --docker-password=123456
secret/aliyuncs-docker-secret created
# 查看secret
[root@master ~]# kubectl get secret
NAME TYPE DATA AGE
aliyuncs-docker-secret kubernetes.io/dockerconfigjson 1 13s
default-token-w95wt kubernetes.io/service-account-token 3 24h
[root@master ~]# kubectl describe secret
Name: aliyuncs-docker-secret
Namespace: default
Labels: <none>
Annotations: <none>
Type: kubernetes.io/dockerconfigjson
Data
====
.dockerconfigjson: 135 bytes
Name: default-token-w95wt
Namespace: default
Labels: <none>
Annotations: kubernetes.io/service-account.name: default
kubernetes.io/service-account.uid: 3aec3825-99b8-44ab-8d13-043131655809
Type: kubernetes.io/service-account-token
Data
====
namespace: 7 bytes
token: eyJhbGciOiJSUzI1NiIsImtpZCI6ImhVVDlBWUFmd1lxVGRuSDJ0aEdHOFE5T09TRHV3dmw0YlctQ0wyVjZsOWMifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImRlZmF1bHQtdG9rZW4tdzk1d3QiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZGVmYXVsdCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjNhZWMzODI1LTk5YjgtNDRhYi04ZDEzLTA0MzEzMTY1NTgwOSIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZWZhdWx0OmRlZmF1bHQifQ.sbCAYjtX4jv-7R94YydQ_4mYLnKGty12h2OB8sfqM_f-a9Pur4xwh82PL29RJDCHBwJO2ujUz_dCVEsfclayc_Nzm1kJ1JrreQSuN_0dkR0dDTCwBPs9ToBhhGPjMCpYqMszwiSakRNXKXxJCxI2m5ZjxqLtI6wVRvbB7Ev4Psz3uZ7PH4_5J3z8TLx4hwXwY-Lu7p0289NNovkiOWwgQYROXuZ99_vvU6F4inr96oJKdfKjAuC0500zXfw9uaS9NPOjXSmSgWsd-iNegAW0rQzRW2JSH977J0-QFON8LkP393ZTYLCgBfJui8oLtv6eEecQIDA8Hp2GVPUqmMPDKA
ca.crt: 1066 bytes
创建好之后,后续需要挂载到 pod 上。
快速创建一个 deployment,导出 yaml 文件。
[root@master ~]# kubectl create deployment k8shello --image=registry.cn-hangzhou.aliyuncs.com/zsxnamespace/zsxck:v1 --dry-run=client -o yaml > k8shello.yaml
[root@master ~]# cat k8shello.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: k8shello
name: k8shello
spec:
replicas: 1
selector:
matchLabels:
app: k8shello
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: k8shello
spec:
containers:
- image: registry.cn-hangzhou.aliyuncs.com/zsxnamespace/zsxck:v1
name: zsxck
resources: {}
status: {}
修改 k8shello.yaml
文件:
[root@master ~]# vim k8shello.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: k8shello
name: k8shello
spec:
replicas: 2 # 修改为2个副本
selector:
matchLabels:
app: k8shello
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: k8shello
spec:
imagePullSecrets:
- name: aliyuncs-docker-secret # 挂载secret
containers:
- image: registry.cn-hangzhou.aliyuncs.com/zsxnamespace/zsxck:v1
name: zsxck
resources: {}
status: {}
[root@master ~]# kubectl apply -f k8shello.yaml
deployment.apps/k8shello created
# 等待一会以后查看创建情况
[root@master ~]# kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
k8shello 2/2 2 2 48s
[root@master ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
k8shello-5b69cdc659-6htqh 1/1 Running 0 13s 10.244.2.8 slave2 <none> <none>
k8shello-5b69cdc659-mxspp 1/1 Running 0 13s 10.244.1.10 slave1 <none> <none>
创建 k8shello-service.yaml
文件:
apiVersion: v1
kind: Service
metadata:
name: k8shello-service
spec:
selector:
app: k8shello
ports:
- protocol: TCP
port: 8080
targetPort: 8080
nodePort: 30080
type: NodePort
创建 service:
[root@master ~]# kubectl create -f k8shello-service.yaml
service/k8shello-service created
查看创建情况:
[root@master ~]# kubectl get deploy -o wide
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
k8shello 2/2 2 2 79s zsxck registry.cn-hangzhou.aliyuncs.com/zsxnamespace/zsxck:v1 app=k8shello
[root@master ~]# curl 192.168.43.201:30080/hello
Hello World!!!
[root@master ~]# curl 192.168.43.202:30080/hello
Hello World!!!
至此,将自己编写的 Java 程序部署到 kubernetes 集群中讲解完毕。