Java程式猿怎樣高速理解Kubernetes
我們能夠說我們希望他們成為我們的小黃人(minions)。
本文我們將通過一個簡單的樣例來了解Kubernetes能夠通過建立和編排一群“小黃人"來為我們做些什麼。您能夠與本文一起編碼或從此處[1]克隆專案。
先決條件
目的
我們希望軍團中有不同型別的工作角色,以便能夠了解Kubernetes能夠為我們做些什麼。因此,我們的目標是讓每一個微服務都響應一個簡單的http請求,其響應例如以下:
使用ASCII字來表示minion的型別。
構建Java Minion服務
在專案中。建立一個使用@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註解。在內部我們建立了一個地圖,我們使用此部落格[2]中的一些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/ryandawsonuk/minions/tree/master/src/main/java/org/minions/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型別名稱(比如'單眼小黃人')。
容器化並部署
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引數來限制程式的記憶體佔用(關於減少記憶體。能夠參考該文章[3])。
然後使用命令“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以port30080暴露對外提供服務 (對於真正的Kubernetes,該服務的這一點會有所不同,由於我們使用LoadBalancer而不是NodePort。而且不會限制在minikubeport範圍)。
服務將使用與服務匹配的Pod來處理它。
我們將為每種型別提供一種服務。
minion型別的部署將建立兩個Pod。
每一個人都是這樣的型別的工作節點。
我們能夠為每一個minion型別反覆上面的配置,每次新增外部port號以便使用不同的port。或者我們能夠使用這個GitHub儲存庫,它還具有其它配置,能夠在不停機的情況下進行小型版本號升級(假設我們使用Helm。我們能夠避免反覆。但我們不想加入比我們很多其它的工具)。
建立軍團
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頁面:
創造很多其它的部隊
一個小黃人倒下,還有一個替補他的位置
假設殺死“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
docker build . -t minion:0.2
然後開啟minion-army.yml並找到 - 用“0.2”替換全部“最新”。儲存更改並執行:
kubectl apply -f minion-army.yml --record
重新整理當中一個minion型別的瀏覽器,以檢視版本號更改是否與kubectl rollout status部署中看到的內容一致。當中是minion型別(比如one-eyed-minion)。
小黃人回滾
銷燬軍團
kubectl delete -f minion-army.yml
用“minikube stop”停止minikube。
相關連結:
https://github.com/ryandawsonuk/minions/blob/master/minion-army.yml
http://textart4u.blogspot.co.uk/2013/08/minions-emoticons-text-art-for-facebook.html
https://dzone.com/articles/how-to-decrease-jvm-memory-consumption-in-docker-u
原文連結:https://dzone.com/articles/minions-in-minikube-a-kubernetes-intro-for-java-de