前言
一開始了解到Java Api庫操作k8s集群,有兩個,分別為:
- kubernetes-client/java
- fabric8io/kubernetes-client
但個人對比使用了兩個發(fā)現(xiàn),還是fabric8io更易用,用的人多是有道理的,fabric8io和yaml文件十分貼切,所以通俗易懂。本文前提是已配置好集群,已經(jīng)熟悉了kubectl工具常用命令。
首先,需要導(dǎo)入fabric8io依賴核心庫,如下:
<dependency>
<groupId>io.fabric8</groupId>
<artifactId>kubernetes-client</artifactId>
<version>6.3.1</version>
</dependency>
注:本文采用6.3.1版本,截止2023年12月14日,官方最新版本為6.9.2版本,如果你k8s是最新版本,那么可考慮最新版本。
如果你需要看官方api操作文檔,可參考:官方使用說明
如果你初學(xué)k8s,關(guān)于k8s的基本概念和常用操作不熟,強推先讀另一個博主的文章:Kubernetes核心概念及命令使用
一、基于fabric8io操作pod
定義:pod 是包含一個或多個容器的容器組,是 Kubernetes 中創(chuàng)建和管理的最小對象。
1.1 yaml創(chuàng)建pod
如果我們在k8s集群上創(chuàng)建一個pod,常常會編寫yaml文件,例如deploy.yaml
:
apiVersion: v1
kind: Pod
metadata:
name: cm-nginx
labels:
app: cm-nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
編寫好后執(zhí)行:kubectl apply -f deploy.yaml
,就會創(chuàng)建一個pod
1.2 fabric8io創(chuàng)建pod案例
首先,需要在k8s集群master上獲取到/root/.kube/config
文件,文件內(nèi)容大致如下,證書密鑰太長,省略,這個文件記錄了連接k8s集群的信息,fabric8io操作集群就需要該文件。
注:只要你需要連接集群,就需要基于config文件,下載下來
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0t..............
server: https://192.168.20.130:6443
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: kubernetes-admin
name: kubernetes-admin@kubernetes
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: kubernetes-admin
user:
client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURJVENDQWdtZ................
client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVk.................
將config文件下載到本地,就可以對pod進行CRUD操作,本文放在resources目錄下
import io.fabric8.kubernetes.api.model.Pod;
import io.fabric8.kubernetes.api.model.PodBuilder;
import io.fabric8.kubernetes.client.Config;
import io.fabric8.kubernetes.client.DefaultKubernetesClient;
import io.fabric8.kubernetes.client.KubernetesClient;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.nio.charset.StandardCharsets;
public class PodCrudExample {
public static void main(String[] args) {
String kubeConfigPath = "D:\\IDEAProject\\k8sApi\\src\\main\\resources\\config";
KubernetesClient client;
try {
client = new DefaultKubernetesClient(Config.fromKubeconfig(FileUtils.readFileToString(new File(kubeConfigPath), StandardCharsets.UTF_8)));
// 創(chuàng)建 Pod
// createPod(client);
// 讀取 Pod
// readPod(client);
// 更新 Pod
// updatePod(client);
// 刪除 Pod
// deletePod(client);
} catch (Exception e) {
e.printStackTrace();
}
}
private static void createPod(KubernetesClient client) {
// 創(chuàng)建 Pod 對象
Pod pod = new PodBuilder()
.withNewMetadata().withName("my-pod-nginx").endMetadata()
.withNewSpec()
.addNewContainer()
.withName("nginx")
.withImage("nginx:latest")
.endContainer()
.endSpec()
.build();
// 在指定的命名空間中創(chuàng)建 Pod
client.pods().inNamespace("default").resource(pod).create();
System.out.println("Pod created successfully.");
}
private static void readPod(KubernetesClient client) {
// 讀取 Pod
Pod pod = client.pods().inNamespace("default").withName("my-pod-nginx").get();
System.out.println("Pod read successfully:");
System.out.println(pod);
}
private static void updatePod(KubernetesClient client) {
// k8s禁止直接對容器中鏡像進行更新操作,k8s更新本質(zhì)還是刪除原有的,然后根據(jù)配置創(chuàng)建新的
// 刪除舊的 Pod
client.pods().inNamespace("default").withName("my-pod-nginx").delete();
// 創(chuàng)建新的 Pod 對象
Pod pod = new PodBuilder()
.withNewMetadata().withName("my-pod-tomcat").endMetadata()
.withNewSpec()
.addNewContainer()
.withName("tomcat")
.withImage("tomcat:latest")
.endContainer()
.endSpec()
.build();
// 在指定的命名空間中創(chuàng)建新的 Pod
client.pods().inNamespace("default").resource(pod).create();
System.out.println("Pod updated successfully.");
}
private static void deletePod(KubernetesClient client) {
// 刪除 Pod,默認關(guān)閉期限30秒,即最多等待30秒
// 這涉及k8s提供的優(yōu)雅終止機制,允許容器有時間完成必要的清理工作
client.pods().inNamespace("default").withName("my-pod-tomcat").delete();
}
}
上面是創(chuàng)建一個普通的pod,無自愈、容災(zāi)等能力,一般我們會用deployment方式創(chuàng)建,deployment創(chuàng)建會在第二節(jié)【基于fabric8io創(chuàng)建Service】一并寫到,因為Service和Deployment一般是一起使用的
二、基于fabric8io創(chuàng)建Service(含Deployment)
概念:網(wǎng)絡(luò)訪問歸Service管理,它用于定義一組 Pod 并提供這些 Pod 的穩(wěn)定訪問點,主要用于服務(wù)發(fā)現(xiàn)和負載均衡。
Service 可以有不同的類型,其中最常見的兩種類型是 ClusterIP
(默認)和 NodePort
。
- 當(dāng)你創(chuàng)建一個 Service,類型為
ClusterIP
時,K8s 會為該 Service 分配一個集群地址(集群內(nèi)部使用,外部不可見) -
NodePort
類型的 Service 具有ClusterIP
的所有特性,同時還會在每個集群節(jié)點上映射一個靜態(tài)端口(NodePort),這使得外部流量可以通過任何集群節(jié)點的 NodePort 訪問 Service(外部可訪問)
2.1 yaml創(chuàng)建Service和Deployment
(1)先用Deployment創(chuàng)建兩個pod副本,deploy_dep.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: my-dep
name: my-dep
spec:
replicas: 2 # 副本數(shù)
selector:
matchLabels:
app: my-dep
template: # 創(chuàng)建pod模板
metadata:
labels:
app: my-dep
spec:
containers:
- image: nginx
name: nginx
(2)創(chuàng)建Service,deploy_svc.yaml
apiVersion: v1
kind: Service
metadata:
labels:
app: my-dep
name: my-svc
spec:
selector:
app: my-dep # 表示選擇只代理具有標(biāo)簽(鍵值對)app: my-dep的pod
ports:
- port: 8000 # 表示 Service 在集群內(nèi)部監(jiān)聽的端口
targetPort: 80 # 表示將 Service 接收到的流量轉(zhuǎn)發(fā)到 Pod 的 80 端口
type: NodePort
kubectl apply -f xxx.yaml
,先后執(zhí)行Deployment和Service
如圖,訪問時會輪巡方式,將接收到的流量轉(zhuǎn)發(fā)到對應(yīng)兩個pod的80端口(targetPort)
由于配置的是NodePort,所以在瀏覽器輸入任意節(jié)點ip:暴露的端口號,官方規(guī)定了NodePort范圍在 30000-32767
之間,這里分配的是32385,那么公網(wǎng)通過該端口可以訪問到集群,公網(wǎng)的流量都會經(jīng)過NodePort暴露的32385端口,轉(zhuǎn)發(fā)到targetPort,即80端口。
總結(jié):Service就像一個網(wǎng)關(guān),只負責(zé)網(wǎng)絡(luò)流量的分配和轉(zhuǎn)發(fā),比如將流量轉(zhuǎn)發(fā)到部署的兩個pod中,兩個pod中目前部署的都是nginx容器。
2.2 fabric8io創(chuàng)建service案例
import io.fabric8.kubernetes.api.model.*;
import io.fabric8.kubernetes.api.model.apps.*;
import io.fabric8.kubernetes.client.*;
import io.fabric8.kubernetes.client.Config;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
public class KubernetesDeployer {
public static void main(String[] args) {
String kubeConfigPath = "D:\\IDEAProject\\k8sApi\\src\\main\\resources\\config";
KubernetesClient client;
try {
client = new DefaultKubernetesClient(Config.fromKubeconfig(FileUtils.readFileToString(new File(kubeConfigPath), StandardCharsets.UTF_8))).inNamespace("default");
// 1、創(chuàng)建 Deployment(2個pod)
Map<String, String> labels = new HashMap();
labels.put("app", "my-dep-fabric8");
Deployment deployment = new DeploymentBuilder()
.withNewMetadata()
.withName("my-dep-fabric8")
.withLabels(labels)
.endMetadata()
.withNewSpec()
.withReplicas(2)
.withNewSelector()
.withMatchLabels(labels)
.endSelector()
.withNewTemplate()
.withNewMetadata()
.withLabels(labels)
.endMetadata()
.withNewSpec()
.withContainers(
new ContainerBuilder()
.withName("mynginx")
.withImage("nginx")
.build()
)
.endSpec()
.endTemplate()
.endSpec()
.build();
client.apps().deployments().inNamespace("default").resource(deployment).create();
// 2、創(chuàng)建 Service
Service service = new ServiceBuilder()
.withNewMetadata()
.withName("my-svc-fabric8")
.withLabels(labels) // 代理具有l(wèi)abels標(biāo)簽的pod
.endMetadata()
.withNewSpec()
.withSelector(labels)
.withPorts(new ServicePortBuilder()
.withPort(8000) // 集群內(nèi)部監(jiān)聽的端口
.withNewTargetPort(80) // 流量轉(zhuǎn)發(fā)的目標(biāo)端口
.build())
.withType("NodePort")
.endSpec()
.build();
client.services().inNamespace("default").resource(service).create();
System.out.println("Service Create Successfully");
} catch (Exception e) {
e.printStackTrace();
}
}
}
創(chuàng)建后,設(shè)置了NodePort,故用Ip+NodePort可以公網(wǎng)訪問,但是兩個nginx默認index.html都是Welcome to nginx,可以用echo "11112222" > index.html
改動一個nginx容器的index.html頁面。
注:用kubectl exec -it pod_name -- /bin/bash
進入容器,默認這個頁面就在/usr/shared/nginx/html/
下。
三、基于fabric8io操作Volume
概念:存儲卷(Volume)分為臨時卷和持久卷,在 Kubernetes 中,Volume
是一種抽象,用于表示容器中可以訪問的存儲。
PV(PersistentVolume)
持久卷是集群級別的資源,它是集群中的一塊持久化存儲資源,可以由多個 Pod 共享。PV 可以來自集群中的各種存儲后端,比如云存儲、網(wǎng)絡(luò)存儲、本地存儲等。PV 與實際的存儲資源相對應(yīng)。
PVC(PersistentVolumeClaim)
PersistentVolumeClaim
是對持久化存儲資源的聲明。它是一個請求,用于獲取持久 Volume
的一部分或全部存儲容量。PVC 允許開發(fā)者聲明對存儲資源的需求,而不用關(guān)心底層存儲是如何實現(xiàn)的。
關(guān)系
PersistentVolumeClaim
是對存儲資源的聲明,而 Volume
是實際的存儲資源。開發(fā)者通過 PVC 聲明存儲需求,并請求系統(tǒng)提供符合這些需求的 PersistentVolume
(PV,實際存儲卷)。
PV生命周期狀態(tài)
Available(可用)、Bound(已綁定)、Released(已釋放)、Failed(失?。?/p>
總結(jié):即一個負責(zé)申明存儲,一個是實際存儲資源
3.1 yaml配置掛載存儲卷
(1)創(chuàng)建一個 PersistentVolume
(PV),類型為 nfs
apiVersion: v1
kind: PersistentVolume
metadata:
name: my-nfs-pv
spec:
capacity:
storage: 300Mi # 允許多個 Pod 以讀寫多模式訪問,i是二進制
volumeMode: Filesystem
accessModes:
- ReadWriteMany
storageClassName: nfs
nfs:
server: 192.168.20.133 # NFS 服務(wù)器地址
path: /nfs/data/shared/ # 共享的目錄
(2)創(chuàng)建 PersistentVolumeClaim
(PVC)來請求使用這個 NFS 存儲卷
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-nfs-pvc01
labels:
app: my-pvc
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 200Mi # Kubernetes 推薦使用二進制單位i,以避免混淆,確保一致性
storageClassName: nfs
(3)創(chuàng)建Pod(可多個)
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: mynginx
image: nginx
volumeMounts:
- name: pvc-html # 這里的 name 對應(yīng) volumes 中的 name
mountPath: "/mount/data"
volumes:
- name: pvc-html # 這里的 name 是存儲卷的名稱
persistentVolumeClaim:
claimName: my-nfs-pvc
注:普通方式直接創(chuàng)建,此處未用Deployment創(chuàng)建pod
一旦 PVC 與 PV 綁定,Pod 只需聲明使用該 PVC,而不需要顯式綁定到 PV,Pod就能共享pvc對應(yīng)的pv存儲卷資源。
解釋:如上,pv共享目錄是/nfs/data/shared/
,pvc和pv綁定后,創(chuàng)建pod容器對應(yīng)的mountPath為/mount/data
,那么/nfs/data/shared/
中的內(nèi)容就會掛載到pod定義的路徑/mount/data
中,實現(xiàn)多個pod共享存儲卷pv中的內(nèi)容。
為什么兩個name要一致?(即例子pvc-html)
答:volumeMounts
定義了存儲卷掛載到容器中的路徑,其中name
字段指定了與 volumes
中相應(yīng)存儲卷的名稱。這樣 K8s 就知道將哪個卷掛載到容器的哪個路徑上。如果名字不一致,pod就不知道去找哪個存儲卷掛載到對應(yīng)路徑。
文章來源:http://www.zghlxwxcb.cn/news/detail-787649.html
3.2 基于fabric8io實現(xiàn)掛載存儲卷
package com.yx.mount_volume;
import io.fabric8.kubernetes.api.model.*;
import io.fabric8.kubernetes.client.Config;
import io.fabric8.kubernetes.client.DefaultKubernetesClient;
import io.fabric8.kubernetes.client.KubernetesClient;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
/**
* 掛載存儲卷
*/
public class MountVolumeExample {
public static void main(String[] args) {
String kubeConfigPath = "D:\\IDEAProject\\k8sApi\\src\\main\\resources\\config";
KubernetesClient client;
try {
client = new DefaultKubernetesClient(Config.fromKubeconfig(FileUtils.readFileToString(new File(kubeConfigPath), StandardCharsets.UTF_8))).inNamespace("default");
// 1、創(chuàng)建 PersistentVolume
PersistentVolume nfsPv = new PersistentVolumeBuilder()
.withNewMetadata().withName("my-pv-fabric8").endMetadata()
.withNewSpec()
.withCapacity(Collections.singletonMap("storage", new Quantity("100Mi")))
.withAccessModes("ReadWriteMany")
.withPersistentVolumeReclaimPolicy("Retain")
.withStorageClassName("nfs")
.withNfs(new NFSVolumeSourceBuilder()
.withServer("192.168.20.133")
.withPath("/nfs/data/shared/")
.build())
.endSpec()
.build();
client.persistentVolumes().resource(nfsPv).create();
// 2、創(chuàng)建 PersistentVolumeClaim
PersistentVolumeClaim nfsPvc = new PersistentVolumeClaimBuilder()
.withNewMetadata()
.withName("my-pvc-fabric8")
.endMetadata()
.withNewSpec()
.withAccessModes("ReadWriteMany")
.withResources(new ResourceRequirementsBuilder()
.addToRequests("storage", new Quantity("80Mi"))
.build())
.withStorageClassName("nfs")
.endSpec()
.build();
client.persistentVolumeClaims().resource(nfsPvc).create();
// 3、創(chuàng)建 Pod,并掛載 PersistentVolumeClaim
Pod pod = new PodBuilder()
.withNewMetadata().withName("my-pod-fabric8").endMetadata()
.withNewSpec()
.addNewContainer()
.withName("my-container")
.withImage("nginx")
.addNewVolumeMount()
.withName("pvc-fabric8")
.withMountPath("/mount/nginx/html/") // 掛載到的目錄
.endVolumeMount()
.endContainer()
.addNewVolume()
.withName("pvc-fabric8")
.withPersistentVolumeClaim(new PersistentVolumeClaimVolumeSourceBuilder()
.withClaimName("my-pvc-fabric8")
.build())
.endVolume()
.endSpec()
.build();
client.pods().inNamespace("default").resource(pod).create();
System.out.println("Pod created successfully.");
} catch (Exception e) {
e.printStackTrace();
}
}
}
以上為全部內(nèi)容!有問題可以評論區(qū)交流討論噢!文章來源地址http://www.zghlxwxcb.cn/news/detail-787649.html
到了這里,關(guān)于【Java】基于fabric8io庫操作k8s集群實戰(zhàn)(pod、deployment、service、volume)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!