Using JKube To Do Kubernetes Deployment
This article has introduced how to use JKube
to automatically generate Docker file, build the container and deploy the container to Kubernetes/Openshift
:
And the above article uses this project as an example project:
To build the project, use this command:
➤ mvn k8s:build
And it will build a docker container:
[INFO] Scanning for projects...
[INFO]
[INFO] ----------------------< meetup:random-generator >-----------------------
[INFO] Building random-generator 0.0.1
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- kubernetes-maven-plugin:1.13.1:build (default-cli) @ random-generator ---
[INFO] k8s: Building Docker image
[INFO] k8s: Running generator spring-boot
[INFO] k8s: spring-boot: Using Docker image quay.io/jkube/jkube-java:0.0.19 as base / builder
[INFO] k8s: Pulling from jkube/jkube-java
36c12cb044ac: Pull complete
e9452697801f: Pull complete
[INFO] k8s: Digest: sha256:b7d8650e04b282b9d7b94daedf38321512f9910bce896cd40ffa15b1b92bab17
[INFO] k8s: Status: Downloaded newer image for quay.io/jkube/jkube-java:0.0.19
[INFO] k8s: Pulled quay.io/jkube/jkube-java:0.0.19 in 10 minutes and 19 seconds
[INFO] k8s: [meetup/random-generator:0.0.1] "spring-boot": Created docker-build.tar in 193 milliseconds
[INFO] k8s: [meetup/random-generator:0.0.1] "spring-boot": Built image sha256:31536
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 10:27 min
[INFO] Finished at: 2023-06-23T01:23:05+08:00
[INFO] ------------------------------------------------------------------------
From the above log output, we can see there is a docker container built, and we can see the image is in Docker local repository:
➤ docker image ls | grep random
meetup/random-generator 0.0.1 315366074b27 22 hours ago 614MB
And then running this command to generate k8s resource file:
➤ mvn k8s:resource
[INFO] Scanning for projects...
[INFO]
[INFO] ----------------------< meetup:random-generator >-----------------------
[INFO] Building random-generator 0.0.1
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- kubernetes-maven-plugin:1.13.1:resource (default-cli) @ random-generator ---
[INFO] k8s: Running generator spring-boot
[INFO] k8s: spring-boot: Using Docker image quay.io/jkube/jkube-java:0.0.19 as base / builder
[INFO] k8s: Using resource templates from /Users/weli/works/fmp-demo-project/src/main/jkube
[INFO] k8s: jkube-controller: Adding a default Deployment
[INFO] k8s: jkube-service: Adding a default service 'random-generator' with ports [8080]
[INFO] k8s: jkube-healthcheck-spring-boot: Adding readiness probe on port 8080, path='/actuator/health', scheme='HTTP', with initial delay 10 seconds
[INFO] k8s: jkube-healthcheck-spring-boot: Adding liveness probe on port 8080, path='/actuator/health', scheme='HTTP', with initial delay 180 seconds
[INFO] k8s: jkube-service-discovery: Using first mentioned service port '8080'
[INFO] k8s: jkube-revision-history: Adding revision history limit to 2
[INFO] k8s: validating /Users/weli/works/fmp-demo-project/target/classes/META-INF/jkube/kubernetes/random-generator-deployment.yml resource
[WARNING] k8s: Invalid Resource : /Users/weli/works/fmp-demo-project/target/classes/META-INF/jkube/kubernetes/random-generator-deployment.yml
[message=.spec.template.spec.containers[0].readinessProbe.httpGet.port:找到 integer,预期为 object, violation type=type]
[message=.spec.template.spec.containers[0].livenessProbe.httpGet.port:找到 integer,预期为 object, violation type=type]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3.099 s
[INFO] Finished at: 2023-06-23T01:36:30+08:00
[INFO] ------------------------------------------------------------------------
From the above log we can see the generated k8s resource file is:
/Users/weli/works/fmp-demo-project/target/classes/META-INF/jkube/kubernetes/random-generator-deployment.yml
And here is the content of above deployment file:
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
jkube.eclipse.org/git-commit: 16ff90c85f6cd0d0ec96572a60bf5d2bd9e6c0e2
jkube.eclipse.org/git-url: git@github.com:liweinan/fmp-demo-project.git
jkube.eclipse.org/scm-url: https://github.com/spring-projects/spring-boot/spring-boot-starter-parent/random-generator
jkube.eclipse.org/git-branch: master
jkube.eclipse.org/scm-tag: HEAD
labels:
app: random-generator
provider: jkube
version: 0.0.1
group: meetup
name: random-generator
spec:
replicas: 1
revisionHistoryLimit: 2
selector:
matchLabels:
app: random-generator
provider: jkube
group: meetup
template:
metadata:
annotations:
jkube.eclipse.org/git-commit: 16ff90c85f6cd0d0ec96572a60bf5d2bd9e6c0e2
jkube.eclipse.org/git-url: git@github.com:liweinan/fmp-demo-project.git
jkube.eclipse.org/scm-url: https://github.com/spring-projects/spring-boot/spring-boot-starter-parent/random-generator
jkube.eclipse.org/git-branch: master
jkube.eclipse.org/scm-tag: HEAD
labels:
app: random-generator
provider: jkube
version: 0.0.1
group: meetup
name: random-generator
spec:
containers:
- env:
- name: KUBERNETES_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: HOSTNAME
valueFrom:
fieldRef:
fieldPath: metadata.name
image: meetup/random-generator:0.0.1
imagePullPolicy: IfNotPresent
livenessProbe:
failureThreshold: 3
httpGet:
path: /actuator/health
port: 8080
scheme: HTTP
initialDelaySeconds: 180
successThreshold: 1
name: spring-boot
ports:
- containerPort: 8080
name: http
protocol: TCP
- containerPort: 9779
name: prometheus
protocol: TCP
- containerPort: 8778
name: jolokia
protocol: TCP
readinessProbe:
failureThreshold: 3
httpGet:
path: /actuator/health
port: 8080
scheme: HTTP
initialDelaySeconds: 10
successThreshold: 1
securityContext:
privileged: false
The above deployment file contains the details of the k8s deployment of the project. In addition, here is the generated k8s service file:
➤ cat ./target/classes/META-INF/jkube/kubernetes/random-generator-service.yml
---
apiVersion: v1
kind: Service
metadata:
annotations:
jkube.eclipse.org/git-commit: 4af3a83a4b6103d2d0c341aa609f98eae7f37086
prometheus.io/path: /metrics
prometheus.io/port: "9779"
jkube.eclipse.org/git-url: git@github.com:liweinan/fmp-demo-project.git
jkube.eclipse.org/scm-url: https://github.com/spring-projects/spring-boot/spring-boot-starter-parent/random-generator
prometheus.io/scrape: "true"
jkube.eclipse.org/git-branch: master
jkube.eclipse.org/scm-tag: HEAD
labels:
app: random-generator
provider: jkube
version: 0.0.1
group: meetup
name: random-generator
spec:
ports:
- name: http
port: 8080
protocol: TCP
targetPort: 8080
selector:
app: random-generator
provider: jkube
group: meetup
type: NodePort
Using the following command to do the k8s deployment:
➤ mvn k8s:deploy
And here is the deployment process output:
[INFO] Scanning for projects...
[INFO]
[INFO] ----------------------< meetup:random-generator >-----------------------
[INFO] Building random-generator 0.0.1
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] >>> kubernetes-maven-plugin:1.13.1:deploy (default-cli) > install @ random-generator >>>
[INFO]
[INFO] --- maven-resources-plugin:3.1.0:resources (default-resources) @ random-generator ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1 resource
[INFO] Copying 0 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ random-generator ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-resources-plugin:3.1.0:testResources (default-testResources) @ random-generator ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /Users/weli/works/fmp-demo-project/src/test/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:testCompile (default-testCompile) @ random-generator ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-surefire-plugin:2.22.2:test (default-test) @ random-generator ---
[INFO]
[INFO] -------------------------------------------------------
[INFO] T E S T S
[INFO] -------------------------------------------------------
[INFO] Running meetup.randomgenerator.RandomGeneratorApplicationTests
01:40:00.309 [main] DEBUG org.springframework.test.context.junit4.SpringJUnit4ClassRunner - SpringJUnit4ClassRunner constructor called with [class meetup.randomgenerator.RandomGeneratorApplicationTests]
01:40:00.312 [main] DEBUG org.springframework.test.context.BootstrapUtils - Instantiating CacheAwareContextLoaderDelegate from class [org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate]
01:40:00.317 [main] DEBUG org.springframework.test.context.BootstrapUtils - Instantiating BootstrapContext using constructor [public org.springframework.test.context.support.DefaultBootstrapContext(java.lang.Class,org.springframework.test.context.CacheAwareContextLoaderDelegate)]
01:40:00.330 [main] DEBUG org.springframework.test.context.BootstrapUtils - Instantiating TestContextBootstrapper for test class [meetup.randomgenerator.RandomGeneratorApplicationTests] from class [org.springframework.boot.test.context.SpringBootTestContextBootstrapper]
01:40:00.337 [main] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Neither @ContextConfiguration nor @ContextHierarchy found for test class [meetup.randomgenerator.RandomGeneratorApplicationTests], using SpringBootContextLoader
01:40:00.339 [main] DEBUG org.springframework.test.context.support.AbstractContextLoader - Did not detect default resource location for test class [meetup.randomgenerator.RandomGeneratorApplicationTests]: class path resource [meetup/randomgenerator/RandomGeneratorApplicationTests-context.xml] does not exist
01:40:00.339 [main] DEBUG org.springframework.test.context.support.AbstractContextLoader - Did not detect default resource location for test class [meetup.randomgenerator.RandomGeneratorApplicationTests]: class path resource [meetup/randomgenerator/RandomGeneratorApplicationTestsContext.groovy] does not exist
01:40:00.340 [main] INFO org.springframework.test.context.support.AbstractContextLoader - Could not detect default resource locations for test class [meetup.randomgenerator.RandomGeneratorApplicationTests]: no resource found for suffixes {-context.xml, Context.groovy}.
01:40:00.341 [main] INFO org.springframework.test.context.support.AnnotationConfigContextLoaderUtils - Could not detect default configuration classes for test class [meetup.randomgenerator.RandomGeneratorApplicationTests]: RandomGeneratorApplicationTests does not declare any static, non-private, non-final, nested classes annotated with @Configuration.
01:40:00.369 [main] DEBUG org.springframework.test.context.support.ActiveProfilesUtils - Could not find an 'annotation declaring class' for annotation type [org.springframework.test.context.ActiveProfiles] and class [meetup.randomgenerator.RandomGeneratorApplicationTests]
01:40:00.415 [main] DEBUG org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider - Identified candidate component class: file [/Users/weli/works/fmp-demo-project/target/classes/meetup/randomgenerator/RandomGeneratorApplication.class]
01:40:00.422 [main] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Found @SpringBootConfiguration meetup.randomgenerator.RandomGeneratorApplication for test class meetup.randomgenerator.RandomGeneratorApplicationTests
01:40:00.486 [main] DEBUG org.springframework.boot.test.context.SpringBootTestContextBootstrapper - @TestExecutionListeners is not present for class [meetup.randomgenerator.RandomGeneratorApplicationTests]: using defaults.
01:40:00.486 [main] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Loaded default TestExecutionListener class names from location [META-INF/spring.factories]: [org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener, org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener, org.springframework.boot.test.autoconfigure.restdocs.RestDocsTestExecutionListener, org.springframework.boot.test.autoconfigure.web.client.MockRestServiceServerResetTestExecutionListener, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcPrintOnlyOnFailureTestExecutionListener, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverTestExecutionListener, org.springframework.test.context.web.ServletTestExecutionListener, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener, org.springframework.test.context.support.DependencyInjectionTestExecutionListener, org.springframework.test.context.support.DirtiesContextTestExecutionListener, org.springframework.test.context.transaction.TransactionalTestExecutionListener, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener]
01:40:00.493 [main] DEBUG org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Skipping candidate TestExecutionListener [org.springframework.test.context.transaction.TransactionalTestExecutionListener] due to a missing dependency. Specify custom listener classes or make the default listener classes and their required dependencies available. Offending class: [org/springframework/transaction/interceptor/TransactionAttributeSource]
01:40:00.493 [main] DEBUG org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Skipping candidate TestExecutionListener [org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener] due to a missing dependency. Specify custom listener classes or make the default listener classes and their required dependencies available. Offending class: [org/springframework/transaction/interceptor/TransactionAttribute]
01:40:00.493 [main] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Using TestExecutionListeners: [org.springframework.test.context.web.ServletTestExecutionListener@6bedbc4d, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener@932bc4a, org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener@d29f28, org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener@2fd1433e, org.springframework.test.context.support.DirtiesContextTestExecutionListener@29d89d5d, org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener@3514a4c0, org.springframework.boot.test.autoconfigure.restdocs.RestDocsTestExecutionListener@212b5695, org.springframework.boot.test.autoconfigure.web.client.MockRestServiceServerResetTestExecutionListener@446293d, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcPrintOnlyOnFailureTestExecutionListener@69997e9d, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverTestExecutionListener@793be5ca]
01:40:00.494 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved @ProfileValueSourceConfiguration [null] for test class [meetup.randomgenerator.RandomGeneratorApplicationTests]
01:40:00.494 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved ProfileValueSource type [class org.springframework.test.annotation.SystemProfileValueSource] for class [meetup.randomgenerator.RandomGeneratorApplicationTests]
01:40:00.495 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved @ProfileValueSourceConfiguration [null] for test class [meetup.randomgenerator.RandomGeneratorApplicationTests]
01:40:00.495 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved ProfileValueSource type [class org.springframework.test.annotation.SystemProfileValueSource] for class [meetup.randomgenerator.RandomGeneratorApplicationTests]
01:40:00.495 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved @ProfileValueSourceConfiguration [null] for test class [meetup.randomgenerator.RandomGeneratorApplicationTests]
01:40:00.496 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved ProfileValueSource type [class org.springframework.test.annotation.SystemProfileValueSource] for class [meetup.randomgenerator.RandomGeneratorApplicationTests]
01:40:00.498 [main] DEBUG org.springframework.test.context.support.AbstractDirtiesContextTestExecutionListener - Before test class: context [DefaultTestContext@5fbdfdcf testClass = RandomGeneratorApplicationTests, testInstance = [null], testMethod = [null], testException = [null], mergedContextConfiguration = [WebMergedContextConfiguration@4efc180e testClass = RandomGeneratorApplicationTests, locations = '{}', classes = '{class meetup.randomgenerator.RandomGeneratorApplication}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@5d47c63f, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@4ae3c1cd, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@2c34f934, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@55a561cf], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map['org.springframework.test.context.web.ServletTestExecutionListener.activateListener' -> true]], class annotated with @DirtiesContext [false] with mode [null].
01:40:00.498 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved @ProfileValueSourceConfiguration [null] for test class [meetup.randomgenerator.RandomGeneratorApplicationTests]
01:40:00.498 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved ProfileValueSource type [class org.springframework.test.annotation.SystemProfileValueSource] for class [meetup.randomgenerator.RandomGeneratorApplicationTests]
01:40:00.515 [main] DEBUG org.springframework.test.context.support.TestPropertySourceUtils - Adding inlined properties to environment: {spring.jmx.enabled=false, org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true, server.port=-1}
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.1.8.RELEASE)
2023-06-23 01:40:00.752 INFO 77676 --- [ main] m.r.RandomGeneratorApplicationTests : Starting RandomGeneratorApplicationTests on 192.168.0.106 with PID 77676 (started by weli in /Users/weli/works/fmp-demo-project)
2023-06-23 01:40:00.754 INFO 77676 --- [ main] m.r.RandomGeneratorApplicationTests : No active profile set, falling back to default profiles: default
2023-06-23 01:40:00.803 INFO 77676 --- [ main] .e.DevToolsPropertyDefaultsPostProcessor : Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable
2023-06-23 01:40:02.522 INFO 77676 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'
2023-06-23 01:40:02.979 WARN 77676 --- [ main] .s.b.d.a.RemoteDevToolsAutoConfiguration : Listening for remote restart updates on /.~~spring-boot!~/restart
2023-06-23 01:40:03.012 INFO 77676 --- [ main] o.s.b.a.e.web.EndpointLinksResolver : Exposing 2 endpoint(s) beneath base path '/actuator'
2023-06-23 01:40:03.068 INFO 77676 --- [ main] m.r.RandomGeneratorApplicationTests : Started RandomGeneratorApplicationTests in 2.546 seconds (JVM running for 3.104)
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 3.222 s - in meetup.randomgenerator.RandomGeneratorApplicationTests
2023-06-23 01:40:03.416 INFO 77676 --- [ Thread-2] o.s.s.concurrent.ThreadPoolTaskExecutor : Shutting down ExecutorService 'applicationTaskExecutor'
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO]
[INFO] --- maven-jar-plugin:3.1.2:jar (default-jar) @ random-generator ---
[INFO] Building jar: /Users/weli/works/fmp-demo-project/target/random-generator-0.0.1.jar
[INFO]
[INFO] --- spring-boot-maven-plugin:2.1.8.RELEASE:repackage (repackage) @ random-generator ---
[INFO] Replacing main artifact with repackaged archive
[INFO]
[INFO] --- maven-install-plugin:2.5.2:install (default-install) @ random-generator ---
[INFO] Installing /Users/weli/works/fmp-demo-project/target/random-generator-0.0.1.jar to /Users/weli/.m2/repository/meetup/random-generator/0.0.1/random-generator-0.0.1.jar
[INFO] Installing /Users/weli/works/fmp-demo-project/pom.xml to /Users/weli/.m2/repository/meetup/random-generator/0.0.1/random-generator-0.0.1.pom
[INFO]
[INFO] <<< kubernetes-maven-plugin:1.13.1:deploy (default-cli) < install @ random-generator <<<
[INFO]
[INFO]
[INFO] --- kubernetes-maven-plugin:1.13.1:deploy (default-cli) @ random-generator ---
[INFO] k8s: Using Kubernetes at https://127.0.0.1:62259/ in namespace null with manifest /Users/weli/works/fmp-demo-project/target/classes/META-INF/jkube/kubernetes.yml
[INFO] k8s: Creating a Service from kubernetes.yml namespace default name random-generator
[INFO] k8s: Created Service: target/jkube/applyJson/default/service-random-generator.json
[INFO] k8s: Creating a Deployment from kubernetes.yml namespace default name random-generator
[INFO] k8s: Created Deployment: target/jkube/applyJson/default/deployment-random-generator.json
[INFO] k8s: HINT: Use the command `kubectl get pods -w` to watch your pods start up
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 8.549 s
[INFO] Finished at: 2023-06-23T01:40:07+08:00
[INFO] ------------------------------------------------------------------------
weli@192:~/w/fmp-demo-project|master⚡?
➤
I used minikube
on MacOS locally, which is backed by Docker, and the pod is deployed:
➤ kubectl get po
NAME READY STATUS RESTARTS AGE
random-generator-5c74797c5d-9wf6x 1/1 Running 0 22h
And here is the relative deployment and service of the pod:
➤ kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
random-generator 1/1 1 1 22h
weli@192:~/w/fmp-demo-project|master⚡?
➤ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 19d
random-generator NodePort 10.99.68.146 <none> 8080:31034/TCP 22h
To access the service, we can use this command to export the service to the local host:
➤ minikube service random-generator --url
http://127.0.0.1:49215
❗ Because you are using a Docker driver on darwin, the terminal needs to be open to run it.
The above minikube
command exposes the service provided by the example project, and we can access it like this:
➤ curl http://127.0.0.1:49215/random
{"id":"7d91826c-dc50-4e81-9794-a266c3454702"}⏎
Another way to expose the service is to use the port-forward
option if kubectl
command. We can see the service port is 8080
and the service type is NodePort
:
We can forward this service to the local host like this:
➤ kubectl port-forward --address 0.0.0.0 service/random-generator 33333:8080
Forwarding from 0.0.0.0:33333 -> 8080
Now the service is forwarded to port 33333
of localhost, and we can access it like this:
➤ curl http://0.0.0.0:33333/random
{"id":"7d91826c-dc50-4e81-9794-a266c3454702"}⏎
And from the port-forward
window we can see it’s handling the connection:
This is how JKube
automated the Docker build and K8s
deployment process.
If you want to modify the generated manifest, you can edit the target/META-INF/jkube/kubernetes.yml
. For example, I can edit the replicas
from 1
to 2
, and then redeploy the project into k8s:
From the above screenshot, you can see I modify the generated manifest file and redeploy the project, and we can see there are two deployments.