python开发基础篇1——后端操作K8s API方式
文章目录
- 一、基本了解
- 1.1 操作k8s API
- 1.2 基本使用
- 二、数据表格展示K8s常见资源
- 2.1 Namespace
- 2.2 Node
- 2.3 PV
- 2.4 Deployment
- 2.5 DaemonSet
- 2.6 StatefulSet
- 2.7 Pod
- 2.8 Service
- 2.9 Ingress
- 2.10 PVC
- 2.11 ConfigMap
- 2.12 Secret
- 2.13 优化
一、基本了解
操作K8s资源api方式:
- 原生api
- 客户端库,python客户端库
K8s支持三种客户端身份认证:
- HTTPS 证书认证:基于CA证书签名的数字证书认证(kubeconfig文件,默认路径~/.kube/config)
- HTTP Token认证:通过一个Token来识别用户(ServiceAccount)
- HTTP Base认证:用户名+密码的方式认证(1.19+已经弃用)
1.1 操作k8s API
1.安装Kubernetes客户端库。
pip install kubernetes -i https://pypi.tuna.tsinghua.edu.cn/simple
2.基于HTTPS证书认证(kubeconfig)操作k8s API。
常用资源接口类实例化 | 资源 |
---|---|
core_api = client.CoreV1Api() | namespace,pod,service,pv,pvc |
apps_api = client.AppsV1Api() | deployment,statefulset,daemonset |
networking_api = client.NetworkingV1beta1Api() | ingress |
storage_api = client.StorageV1Api() | storage_class |
from kubernetes import client,config
import os
print(os.getcwd())kubeconfig = os.path.join(os.getcwd(),'kubeconfig.yaml') ##拿到k8s的~.kube/config文件内容。
config.load_kube_config(kubeconfig) ##指定kubeconfig配置文件(/root/.kube/config)
apps_api = client.AppsV1Api() # 资源接口类实例化,根据要操作的资源实例化不同的组。
# print(apps_api.list_deployment_for_all_namespaces())for dp in apps_api.list_deployment_for_all_namespaces().items:# print(dp) # 打印Deployment对象详细信息print(dp.metadata.labels)print(dp.metadata.name)
3.基于HTTP Token认证(ServiceAccount)操作K8s API。
#############################################################
##获取Token字符串:创建service account并绑定默认cluster-admin管理员集群角色。
# 创建用户
kubectl create serviceaccount dashboard-admin -n kube-system
# 用户授权
kubectl create clusterrolebinding dashboard-admin --clusterrole=cluster-admin --serviceaccount=kube-system:dashboard-admin
# 获取用户Token(1.24版本之前)
kubectl describe secrets -n kube-system $(kubectl -n kube-system get secret | awk '/dashboard-admin/{print $1}')
# 获取用户Token(1.24版本之后)
kubectl create token dashboard-admin -n kube-system
#############################################################
from kubernetes import client,config
import os
configuration = client.Configuration()
configuration.host = "https://192.168.161.120:6443" # APISERVER地址
ca_file = os.path.join(os.getcwd(),"ca.crt") # K8s集群CA证书(/etc/kubernetes/pki/ca.crt)
configuration.ssl_ca_cert= ca_file
configuration.verify_ssl = True
##启用证书验证。
token = "eyJhbGciOiJSUzI1NiIsImtpZCI6InhBd1JkOFFocE1oX0VsRnlDcmFwQUN4ajQzblNta2FnVW1ITmk1VU12ZUEifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiXSwiZXhwIjoxNjk0MDQ3ODI5LCJpYXQiOjE2OTQwNDQyMjksImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsInNlcnZpY2VhY2NvdW50Ijp7Im5hbWUiOiJkYXNoYm9hcmQtYWRtaW4iLCJ1aWQiOiI2Zjg0ZTFjMC0wYTY0LTQ4NTQtYThlMy03MDZkOWYxZThkZGMifX0sIm5iZiI6MTY5NDA0NDIyOSwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50Omt1YmUtc3lzdGVtOmRhc2hib2FyZC1hZG1pbiJ9.GXwDKDNcCPjU23R-kYbs1Sl-73hG2p7RJShB0I8BU7cpifUhBaEKJjymx5IL_CYTl5LHRdlP0uo_sqXqrUBRBYrW5vctVq8MXLFNShSAKKLmxdIxxo4fHrWHMaRv8TU_wtKkATiXAO15q3n9YD7vN443FWK3sRuWpzh6Hvlr4dljnK_37YKiOd8eS8_dDC4BkeLo38EadnO39BwvC5lommz2LkCYMawunWkOxsI_eclPqXJ3ZkSCgEZUPD4_0CNv7D_X6S_gyMkdsCVxwFuL3EjI9ENh4GV2yKBVY69wuChlXB6vHGcYtiWzhTDdibv4l-5jIWhbwR_5CgaskKtmTQ" #指定Token字符串,下面方式获取
configuration.api_key = {"authorization": "Bearer " + token} ##固定格式。
client.Configuration.set_default(configuration)
apps_api = client.AppsV1Api()for dp in apps_api.list_deployment_for_all_namespaces().items:# print(dp) # 打印Deployment对象详细信息print(dp.metadata.labels)
1.2 基本使用
1.创建一个deployment资源,名为qingjun,3个副本数,使用nginx镜像。
from kubernetes import client,config
import osconfiguration = client.Configuration()
configuration.host = "https://192.168.161.120:6443" # APISERVER地址
ca_file = os.path.join(os.getcwd(),"ca.crt") # K8s集群CA证书(/etc/kubernetes/pki/ca.crt)
configuration.ssl_ca_cert= ca_file
configuration.verify_ssl = True
# 启用证书验证
token = "eyJhbGciOiJSUzI1NiIsImtpZCI6InhBd1JkOFFocE1oX0VsRnlDcmFwQUN4ajQzblNta2FnVW1ITmk1VU12ZUEifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiXSwiZXhwIjoxNjk0MDQ3ODI5LCJpYXQiOjE2OTQwNDQyMjksImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsInNlcnZpY2VhY2NvdW50Ijp7Im5hbWUiOiJkYXNoYm9hcmQtYWRtaW4iLCJ1aWQiOiI2Zjg0ZTFjMC0wYTY0LTQ4NTQtYThlMy03MDZkOWYxZThkZGMifX0sIm5iZiI6MTY5NDA0NDIyOSwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50Omt1YmUtc3lzdGVtOmRhc2hib2FyZC1hZG1pbiJ9.GXwDKDNcCPjU23R-kYbs1Sl-73hG2p7RJShB0I8BU7cpifUhBaEKJjymx5IL_CYTl5LHRdlP0uo_sqXqrUBRBYrW5vctVq8MXLFNShSAKKLmxdIxxo4fHrWHMaRv8TU_wtKkATiXAO15q3n9YD7vN443FWK3sRuWpzh6Hvlr4dljnK_37YKiOd8eS8_dDC4BkeLo38EadnO39BwvC5lommz2LkCYMawunWkOxsI_eclPqXJ3ZkSCgEZUPD4_0CNv7D_X6S_gyMkdsCVxwFuL3EjI9ENh4GV2yKBVY69wuChlXB6vHGcYtiWzhTDdibv4l-5jIWhbwR_5CgaskKtmTQ" #指定Token字符串,下面方式获取
configuration.api_key = {"authorization": "Bearer " + token} ##固定格式。
client.Configuration.set_default(configuration)
apps_api = client.AppsV1Api()namespace = "default"
name = "qingjun"
replicas = 3
labels = {'a':'1', 'b':'2'} # 不区分数据类型,都要加引号
image = "nginx"
body = client.V1Deployment(api_version="apps/v1",kind="Deployment",metadata=client.V1ObjectMeta(name=name),spec=client.V1DeploymentSpec(replicas=replicas,selector={'matchLabels': labels},template=client.V1PodTemplateSpec(metadata=client.V1ObjectMeta(labels=labels),spec=client.V1PodSpec(containers=[client.V1Container(name="web",image=image)])),))
try:apps_api.create_namespaced_deployment(namespace=namespace, body=body) ##创建命令。
except Exception as e:status = getattr(e, "status") ##获取状态码。if status == 400: # 400 格式错误,409 资源存在,403 没权限。print(e)print("格式错误")elif status == 409:print("deployment资源存在")elif status == 403:print("没权限")
2.创建一个service资源。
core_api = client.CoreV1Api()
namespace = "default"
name = "qingjun"
selector = {'a':'1', 'b':'2'} # 不区分数据类型,都要加引号
port = 80
target_port = 80
type = "NodePort"
body = client.V1Service(api_version="v1",kind="Service",metadata=client.V1ObjectMeta(name=name),spec=client.V1ServiceSpec(selector=selector,ports=[client.V1ServicePort(port=port,target_port=target_port)],type=type)
)
try:core_api.create_namespaced_service(namespace=namespace, body=body)
except Exception as e:status = getattr(e, "status")if status == 400: # 400 格式错误,409 资源存在,403 没权限。print(e)print("格式错误")elif status == 409:print("service资源存在")elif status == 403:print("没权限")
二、数据表格展示K8s常见资源
大致思路:
- 使用Layui从接口获取JSON数据,动态渲染表格。
- Django准备接口,以JSON格式返回。
- 接口类实例化,遍历获取接口数据,取对应字段值,组成一个字典。
- 资源增删改查采用不同HTTP方法:
HTTP方法 | 数据处理 | 说明 |
---|---|---|
POST | 新增 | 新增一个资源 |
GET | 获取 | 取得一个资源 |
PUT | 更新 | 更新一个资源 |
DELETE | 删除 | 删除一个资源 |
2.1 Namespace
1.查询资源。
##items返回一个对象,类LIST([{命名空间属性},{命名空间属性}] ),每个元素是一个类字典(命名空间属性),操作类字典
for ns in core_api.list_namespace().items:name = ns.metadata.name ##名称。labels = ns.metadata.labels ##标签。create_time = ns.metadata.creation_timestamp ##创建时间。namespace = {"name": name, "labels": labels, "create_time": create_time}
2.删除资源。
core_api.delete_namespace(name=name)
3.创建资源。
body = client.V1Namespace(api_version="v1",kind="Namespace",metadata=client.V1ObjectMeta(name=ns_name)
)
core_api.create_namespace(body=body)
4.使用数据表格显示资源。
table.render({elem: '#test',url:'{% url 'namespace_api' %}',toolbar: '#toolbarDemo' //开启头部工具栏,并为其绑定左侧模板,defaultToolbar: ['filter', 'exports', 'print', { //自定义头部工具栏右侧图标。如无需自定义,去除该参数即可title: '提示',layEvent: 'LAYTABLE_TIPS',icon: 'layui-icon-tips'}],cols: [[{field: 'name', title: '名称', sort: true},{field: 'labels', title: '标签',templet: labelsFormat},{field: 'create_time', title: '创建时间'},{fixed: 'right', title:'操作', toolbar: '#barDemo', width:150}]],page: true});// 标签格式化,是一个对象function labelsFormat(d){result = "";if (d.labels == null){return "None"} else {for (let key in d.labels) {result += '<span style="border: 1px solid #d6e5ec;border-radius: 8px">' +key + ':' + d.labels[key] +'</span><br>'}return result}}
总结:其他资源功能开发与命名空间一样,拷贝后需要的修改位置:
- 服务端:新添加一个url,函数视图
- 服务端:函数视图GET方法里修改for遍历的K8s API接口、对应字段,DELETE方法里修改删除的K8s API接口
- 前端:面包屑
- 前端:table.renader修改连接的API接口,对应表头,删除接口及提示文字
- 另外,除了Namespace、Node、PV,其他适配加命名空间
2.2 Node
1.查询。
for node in core_api.list_node_with_http_info()[0].items:name = node.metadata.name ##名称。labels = node.metadata.labels ##标签。status = node.status.conditions[-1].status ##准备就绪状态。scheduler = ("是" if node.spec.unschedulable is None else "否") ##是否可调度。cpu = node.status.capacity['cpu'] ##cpui资源memory = node.status.capacity['memory'] ##内存资源kebelet_version = node.status.node_info.kubelet_version ##kubelet版本cri_version = node.status.node_info.container_runtime_version ##CRI版本create_time = node.metadata.creation_timestamp ##创建时间node = {"name": name, "labels": labels, "status":status,"scheduler":scheduler , "cpu":cpu, "memory":memory,"kebelet_version":kebelet_version, "cri_version":cri_version,"create_time": create_time}
2.数据表格。
table.render({elem: '#test',url:'{% url 'node_api' %}',toolbar: '#toolbarDemo' //开启头部工具栏,并为其绑定左侧模板,defaultToolbar: ['filter', 'exports', 'print', { //自定义头部工具栏右侧图标。如无需自定义,去除该参数即可title: '提示',layEvent: 'LAYTABLE_TIPS',icon: 'layui-icon-tips'}],cols: [[{field: 'name', title: '名称', sort: true},{field: 'labels', title: '标签',templet: labelsFormat},{field: 'status', title: '准备就绪'},{field: 'scheduler', title: '可调度'},{field: 'cpu', title: 'CPU'},{field: 'memory', title: '内存'},{field: 'kebelet_version', title: 'kubelet版本'},{field: 'cri_version', title: 'CRI版本'},{field: 'create_time', title: '创建时间'},{fixed: 'right', title:'操作', toolbar: '#barDemo', width:150}]],page: true});// 标签格式化,是一个对象function labelsFormat(d){result = "";if (d.labels == null){return "None"} else {for (let key in d.labels) {result += '<span style="border: 1px solid #d6e5ec;border-radius: 8px">' +key + ':' + d.labels[key] +'</span><br>'}return result}}
2.3 PV
- 数据存储,Pod->PVC->PV->外部存储,例如NFS、Ceph
1.查询。
字段:名称、容量、访问模式、回收策略、状态、卷申请(PVC)/命名空间、存储类、创建时间
for pv in core_api.list_persistent_volume().items:name = pv.metadata.namecapacity = pv.spec.capacity["storage"]access_modes = pv.spec.access_modesreclaim_policy = pv.spec.persistent_volume_reclaim_policystatus = pv.status.phaseif pv.spec.claim_ref is not None:pvc_ns = pv.spec.claim_ref.namespacepvc_name = pv.spec.claim_ref.namepvc = "%s / %s" % (pvc_ns, pvc_name)else:pvc = "未绑定"storage_class = pv.spec.storage_class_namecreate_time = pv.metadata.creation_timestamppv = {"name": name, "capacity": capacity, "access_modes":access_modes,"reclaim_policy":reclaim_policy , "status":status, "pvc":pvc,"storage_class":storage_class,"create_time": create_time}
2.创建。
name = request.POST.get("name", None)capacity = request.POST.get("capacity", None)access_mode = request.POST.get("access_mode", None)storage_type = request.POST.get("storage_type", None)server_ip = request.POST.get("server_ip", None)mount_path = request.POST.get("mount_path", None)body = client.V1PersistentVolume(api_version="v1",kind="PersistentVolume",metadata=client.V1ObjectMeta(name=name),spec=client.V1PersistentVolumeSpec(capacity={'storage':capacity},access_modes=[access_mode],nfs=client.V1NFSVolumeSource(server=server_ip,path="/ifs/kubernetes/%s" %mount_path)))core_api.create_persistent_volume(body=body)
3.删除。
core_api.delete_persistent_volume(name=name)
4.数据表格。
table.render({elem: '#test',url:'{% url 'pv_api' %}',toolbar: '#toolbarDemo' //开启头部工具栏,并为其绑定左侧模板,defaultToolbar: ['filter', 'exports', 'print', { //自定义头部工具栏右侧图标。如无需自定义,去除该参数即可title: '提示',layEvent: 'LAYTABLE_TIPS',icon: 'layui-icon-tips'}],cols: [[{field: 'name', title: '名称', sort: true},{field: 'capacity', title: '容量'},{field: 'access_modes', title: '访问模式'},{field: 'reclaim_policy', title: '回收策略'},{field: 'status', title: '状态'},{field: 'pvc', title: 'PVC(命名空间/名称)'},{field: 'storage_class', title: '存储类'},{field: 'create_time', title: '创建时间'},{fixed: 'right', title:'操作', toolbar: '#barDemo', width:150}]],page: true,id: 'pvtb'
});
2.4 Deployment
1.查询。
字段:名称、命名空间、预期副本数、可用副本数、Pod标签选择器、镜像/状态、创建时间
for dp in apps_api.list_namespaced_deployment(namespace).items:name = dp.metadata.namenamespace = dp.metadata.namespacereplicas = dp.spec.replicasavailable_replicas = ( 0 if dp.status.available_replicas is None else dp.status.available_replicas)labels = dp.metadata.labelsselector = dp.spec.selector.match_labelscontainers = {}for c in dp.spec.template.spec.containers:containers[c.name] = c.imagecreate_time = dp.metadata.creation_timestampdp = {"name": name, "namespace": namespace, "replicas":replicas,"available_replicas":available_replicas , "labels":labels, "selector":selector,"containers":containers, "create_time": create_time}
2.创建。
name = request.POST.get("name",None)namespace = request.POST.get("namespace",None)image = request.POST.get("image",None)replicas = int(request.POST.get("replicas",None))# 处理标签labels = {}try:for l in request.POST.get("labels",None).split(","):k = l.split("=")[0]v = l.split("=")[1]labels[k] = vexcept Exception as e:res = {"code": 1, "msg": "标签格式错误!"}return JsonResponse(res)resources = request.POST.get("resources",None)health_liveness = request.POST.get("health[liveness]",None) # {'health[liveness]': ['on'], 'health[readiness]': ['on']}health_readiness = request.POST.get("health[readiness]",None)if resources == "1c2g":resources = client.V1ResourceRequirements(limits={"cpu":"1","memory":"1Gi"},requests={"cpu":"0.9","memory":"0.9Gi"})elif resources == "2c4g":resources = client.V1ResourceRequirements(limits={"cpu": "2", "memory": "4Gi"},requests={"cpu": "1.9", "memory": "3.9Gi"})elif resources == "4c8g":resources = client.V1ResourceRequirements(limits={"cpu": "4", "memory": "8Gi"},requests={"cpu": "3.9", "memory": "7.9Gi"})else:resources = client.V1ResourceRequirements(limits={"cpu":"500m","memory":"1Gi"},requests={"cpu":"450m","memory":"900Mi"})liveness_probe = ""if health_liveness == "on":liveness_probe = client.V1Probe(http_get="/",timeout_seconds=30,initial_delay_seconds=30)readiness_probe = ""if health_readiness == "on":readiness_probe = client.V1Probe(http_get="/",timeout_seconds=30,initial_delay_seconds=30)for dp in apps_api.list_namespaced_deployment(namespace=namespace).items:if name == dp.metadata.name:res = {"code": 1, "msg": "Deployment已经存在!"}return JsonResponse(res)body = client.V1Deployment(api_version="apps/v1",kind="Deployment",metadata=client.V1ObjectMeta(name=name),spec=client.V1DeploymentSpec(replicas=replicas,selector={'matchLabels': labels},template=client.V1PodTemplateSpec(metadata=client.V1ObjectMeta(labels=labels),spec=client.V1PodSpec(containers=[client.V1Container( # https://github.com/kubernetes-client/python/blob/master/kubernetes/docs/V1Container.mdname="web",image=image,env=[{"name": "TEST", "value": "123"}, {"name": "DEV", "value": "456"}],ports=[client.V1ContainerPort(container_port=80)],# liveness_probe=liveness_probe, # readiness_probe=readiness_probe,resources=resources,)])),))apps_api.create_namespaced_deployment(namespace=namespace, body=body)
3.删除。
apps_api.delete_namespaced_deployment(namespace=namespace, name=name)
4.数据表格。
table.render({elem: '#test',url:'{% url 'deployment_api' %}?namespace=' + namespace,toolbar: '#toolbarDemo' //开启头部工具栏,并为其绑定左侧模板,defaultToolbar: ['filter', 'exports', 'print', { //自定义头部工具栏右侧图标。如无需自定义,去除该参数即可title: '提示',layEvent: 'LAYTABLE_TIPS',icon: 'layui-icon-tips'}],cols: [[{field: 'name', title: '名称', sort: true},{field: 'namespace', title: '命名空间'},{field: 'replicas', title: '预期副本数'},{field: 'available_replicas', title: '可用副本数'},{field: 'labels', title: '标签',templet: labelsFormat},{field: 'selector', title: 'Pod标签选择器',templet: selectorFormat},{field: 'containers', title: '容器', templet: containersFormat},{field: 'create_time', title: '创建时间'},{fixed: 'right', title:'操作', toolbar: '#barDemo', width:150}]],page: true,id: 'dptb'});// 标签格式化,是一个对象function labelsFormat(d){result = "";if(d.labels == null){return "None"} else {for (let key in d.labels) {result += '<span style="border: 1px solid #d6e5ec;border-radius: 8px">' +key + ':' + d.labels[key] +'</span><br>'}return result}}function selectorFormat(d){result = "";for(let key in d.selector) {result += '<span style="border: 1px solid #d6e5ec;border-radius: 8px">' +key + ':' + d.selector[key] +'</span><br>'}return result}function containersFormat(d) {result = "";for(let key in d.containers) {result += key + '=' + d.containers[key] + '<br>'}return result}
2.5 DaemonSet
1.查询。
字段:名称、命名空间、预期节点数、可用节点数、Pod标签选择器、镜像、创建时间
for ds in apps_api.list_namespaced_daemon_set(namespace).items:name = ds.metadata.namenamespace = ds.metadata.namespacedesired_number = ds.status.desired_number_scheduledavailable_number = ds.status.number_availablelabels = ds.metadata.labelsselector = ds.spec.selector.match_labelscontainers = {}for c in ds.spec.template.spec.containers:containers[c.name] = c.image create_time = ds.metadata.creation_timestampds = {"name": name, "namespace": namespace, "labels": labels, "desired_number": desired_number,"available_number": available_number,"selector": selector, "containers": containers, "create_time": create_time}
2.创建。
name = request.POST.get("name",None)namespace = request.POST.get("namespace",None)image = request.POST.get("image",None)# 处理标签labels = {}try:for l in request.POST.get("labels",None).split(","):k = l.split("=")[0]v = l.split("=")[1]labels[k] = vexcept Exception as e:res = {"code": 1, "msg": "标签格式错误!"}return JsonResponse(res)resources = request.POST.get("resources",None)health_liveness = request.POST.get("health[liveness]",None) # {'health[liveness]': ['on'], 'health[readiness]': ['on']}health_readiness = request.POST.get("health[readiness]",None)if resources == "1c2g":resources = client.V1ResourceRequirements(limits={"cpu":"1","memory":"1Gi"},requests={"cpu":"0.9","memory":"0.9Gi"})elif resources == "2c4g":resources = client.V1ResourceRequirements(limits={"cpu": "2", "memory": "4Gi"},requests={"cpu": "1.9", "memory": "3.9Gi"})elif resources == "4c8g":resources = client.V1ResourceRequirements(limits={"cpu": "4", "memory": "8Gi"},requests={"cpu": "3.9", "memory": "7.9Gi"})else:resources = client.V1ResourceRequirements(limits={"cpu":"500m","memory":"1Gi"},requests={"cpu":"450m","memory":"900Mi"})liveness_probe = ""if health_liveness == "on":liveness_probe = client.V1Probe(http_get="/",timeout_seconds=30,initial_delay_seconds=30)readiness_probe = ""if health_readiness == "on":readiness_probe = client.V1Probe(http_get="/",timeout_seconds=30,initial_delay_seconds=30)for dp in apps_api.list_namespaced_daemon_set(namespace=namespace).items:if name == dp.metadata.name:res = {"code": 1, "msg": "DaemonSet已经存在!"}return JsonResponse(res)body = client.V1DaemonSet(api_version="apps/v1",kind="DaemonSet",metadata=client.V1ObjectMeta(name=name),spec=client.V1DeploymentSpec(selector={'matchLabels': labels},template=client.V1PodTemplateSpec(metadata=client.V1ObjectMeta(labels=labels),spec=client.V1PodSpec(containers=[client.V1Container( # https://github.com/kubernetes-client/python/blob/master/kubernetes/docs/V1Container.mdname="web",image=image,env=[{"name": "TEST", "value": "123"}, {"name": "DEV", "value": "456"}],ports=[client.V1ContainerPort(container_port=80)],# liveness_probe=liveness_probe, # readiness_probe=readiness_probe,resources=resources,)])),))
3.删除。
apps_api.delete_namespaced_daemon_set(namespace=namespace, name=name)
4.数据表格。
table.render({elem: '#test',url:'{% url 'daemonset_api' %}?namespace=' + namespace,toolbar: '#toolbarDemo' //开启头部工具栏,并为其绑定左侧模板,defaultToolbar: ['filter', 'exports', 'print', { //自定义头部工具栏右侧图标。如无需自定义,去除该参数即可title: '提示',layEvent: 'LAYTABLE_TIPS',icon: 'layui-icon-tips'}],cols: [[{field: 'name', title: '名称', sort: true},{field: 'namespace', title: '命名空间',sort: true},{field: 'desired_number', title: '预期节点数',width: 100},{field: 'available_number', title: '可用节点数',width: 100},{field: 'labels', title: '标签',templet: labelsFormat},{field: 'selector', title: 'Pod 标签选择器',templet: selecotrFormat},{field: 'containers', title: '容器', templet: containersFormat},{field: 'create_time', title: '创建时间',width: 200},{fixed: 'right', title:'操作', toolbar: '#barDemo',width: 150}]],page: true,id: 'dstb'});// 标签格式化,是一个对象function labelsFormat(d){result = "";if(d.labels == null){return "None"} else {for (let key in d.labels) {result += '<span style="border: 1px solid #d6e5ec;border-radius: 8px">' +key + ':' + d.labels[key] +'</span><br>'}return result}}function selecotrFormat(d){result = "";for(let key in d.selector) {result += '<span style="border: 1px solid #d6e5ec;border-radius: 8px">' +key + ':' + d.selector[key] +'</span><br>'}return result}function containersFormat(d) {result = "";for(let key in d.containers) {result += key + '=' + d.containers[key] + '<br>'}return result}
2.6 StatefulSet
1.查询。
字段:名称、命名空间、Service名称、预期副本数、可用副本数、Pod标签选择器、镜像、创建时间
for sts in apps_api.list_namespaced_stateful_set(namespace).items:name = sts.metadata.namenamespace = sts.metadata.namespacelabels = sts.metadata.labelsselector = sts.spec.selector.match_labelsreplicas = sts.spec.replicasready_replicas = ("0" if sts.status.ready_replicas is None else sts.status.ready_replicas)#current_replicas = sts.status.current_replicasservice_name = sts.spec.service_namecontainers = {}for c in sts.spec.template.spec.containers:containers[c.name] = c.image create_time = sts.metadata.creation_timestampds = {"name": name, "namespace": namespace, "labels": labels, "replicas": replicas,"ready_replicas": ready_replicas, "service_name": service_name,"selector": selector, "containers": containers, "create_time": create_time}
2.删除。
apps_api.delete_namespaced_stateful_set(namespace=namespace, name=name)
3.数据表格。
table.render({elem: '#test',url:'{% url 'statefulset_api' %}?namespace=' + namespace,toolbar: '#toolbarDemo' //开启头部工具栏,并为其绑定左侧模板,defaultToolbar: ['filter', 'exports', 'print', { //自定义头部工具栏右侧图标。如无需自定义,去除该参数即可title: '提示',layEvent: 'LAYTABLE_TIPS',icon: 'layui-icon-tips'}],cols: [[{field: 'name', title: '名称', sort: true},{field: 'namespace', title: '命名空间',sort: true},{field: 'service_name', title: 'Service名称'},{field: 'replicas', title: '预期副本数',width: 100},{field: 'ready_replicas', title: '可用副本数',width: 100},{field: 'labels', title: '标签',templet: labelsFormat},{field: 'selector', title: 'Pod 标签选择器',templet: selecotrFormat},{field: 'containers', title: '容器', templet: containersFormat},{field: 'create_time', title: '创建时间',width: 200},{fixed: 'right', title:'操作', toolbar: '#barDemo',width: 150}]],page: true,id: 'ststb'});// 标签格式化,是一个对象function labelsFormat(d){result = "";if(d.labels == null){return "None"} else {for (let key in d.labels) {result += '<span style="border: 1px solid #d6e5ec;border-radius: 8px">' +key + ':' + d.labels[key] +'</span><br>'}return result}}function selecotrFormat(d){result = "";for(let key in d.selector) {result += '<span style="border: 1px solid #d6e5ec;border-radius: 8px">' +key + ':' + d.selector[key] +'</span><br>'}return result}function containersFormat(d) {result = "";for(let key in d.containers) {result += key + '=' + d.containers[key] + '<br>'}return result}
2.7 Pod
1.查询。
字段:名称、命名空间、IP地址、标签、容器组、状态、创建时间
for po in core_api.list_namespaced_pod(namespace).items:name = po.metadata.namenamespace = po.metadata.namespacelabels = po.metadata.labelspod_ip = po.status.pod_ipcontainers = [] # [{},{},{}]status = "None"# 只为None说明Pod没有创建(不能调度或者正在下载镜像)if po.status.container_statuses is None:status = po.status.conditions[-1].reasonelse:for c in po.status.container_statuses:c_name = c.namec_image = c.image# 获取重启次数restart_count = c.restart_count# 获取容器状态c_status = "None"if c.ready is True:c_status = "Running"elif c.ready is False:if c.state.waiting is not None:c_status = c.state.waiting.reasonelif c.state.terminated is not None:c_status = c.state.terminated.reasonelif c.state.last_state.terminated is not None:c_status = c.last_state.terminated.reasonc = {'c_name': c_name,'c_image':c_image ,'restart_count': restart_count, 'c_status': c_status}containers.append(c)create_time = po.metadata.creation_timestamppo = {"name": name, "namespace": namespace, "pod_ip": pod_ip,"labels": labels, "containers": containers, "status": status,"create_time": create_time}
2.删除。
core_api.delete_namespaced_pod(namespace=namespace, name=name)
3.数据表格。
table.render({elem: '#test',url:'{% url 'pod_api' %}?namespace=' + namespace,toolbar: '#toolbarDemo' //开启头部工具栏,并为其绑定左侧模板,defaultToolbar: ['filter', 'exports', 'print', { //自定义头部工具栏右侧图标。如无需自定义,去除该参数即可title: '提示',layEvent: 'LAYTABLE_TIPS',icon: 'layui-icon-tips'}],cols: [[{field: 'name', title: '名称', sort: true},{field: 'namespace', title: '命名空间',sort: true},{field: 'pod_ip', title: 'IP地址'},{field: 'labels', title: '标签', templet: labelsFormat},{field: 'containers', title: '容器组', templet: containersFormat},{field: 'status', title: '状态',sort: true, templet: statusFormat},{field: 'create_time', title: '创建时间'},{fixed: 'right', title:'操作', toolbar: '#barDemo',width: 250}]],page: true,id: 'potb'
});
// 标签格式化,是一个对象
function labelsFormat(d){result = "";if(d.labels == null){return "None"} else {for (let key in d.labels) {result += '<span style="border: 1px solid #d6e5ec;border-radius: 8px">' +key + ':' + d.labels[key] +'</span><br>'}return result}
}
function containersFormat(d) {result = "";if (d.containers) {for(let key in d.containers) {data = d.containers[key];result += key + ':' + data.c_name + '=' + data.c_image + '<br>' +'重启次数:' + data.restart_count + '<br>' +'状态:' + data.c_status + '<br>'}return result} else {return "None"}
}
// 如果status为None,使用容器状态显示
function statusFormat(d){result = "";if(d.status == "None"){for(let key in d.containers) {result += d.containers[key].c_status + '<br>'}return result} else {return d.status}
}
2.8 Service
1.查询。
字段:名称、命名空间、类型、集群IP、端口信息、Pod标签选择器、后端Pod、创建时间
for svc in core_api.list_namespaced_service(namespace=namespace).items:name = svc.metadata.namenamespace = svc.metadata.namespacelabels = svc.metadata.labelstype = svc.spec.typecluster_ip = svc.spec.cluster_ipports = []for p in svc.spec.ports: # 不是序列,不能直接返回port_name = p.nameport = p.porttarget_port = p.target_portprotocol = p.protocolnode_port = ""if type == "NodePort":node_port = " <br> NodePort: %s" % p.node_portport = {'port_name': port_name, 'port': port, 'protocol': protocol, 'target_port':target_port, 'node_port': node_port}ports.append(port)selector = svc.spec.selectorcreate_time = svc.metadata.creation_timestamp# 确认是否关联Podendpoint = ""for ep in core_api.list_namespaced_endpoints(namespace=namespace).items:if ep.metadata.name == name and ep.subsets is None:endpoint = "未关联"else:endpoint = "已关联"svc = {"name": name, "namespace": namespace, "type": type,"cluster_ip": cluster_ip, "ports": ports, "labels": labels,"selector": selector, "endpoint": endpoint, "create_time": create_time}
2.创建。
name = request.POST.get("name",None)namespace = request.POST.get("namespace",None)port = int(request.POST.get("port",None))target_port = int(request.POST.get("target-port",None))labels = {}try:for l in request.POST.get("labels",None).split(","):k = l.split("=")[0]v = l.split("=")[1]labels[k] = vexcept Exception as e:res = {"code": 1, "msg": "标签格式错误!"}return JsonResponse(res)type = request.POST.get("type","")body = client.V1Service(api_version="v1",kind="Service",metadata=client.V1ObjectMeta(name=name),spec=client.V1ServiceSpec(selector=labels,ports=[client.V1ServicePort(port=port,target_port=target_port,)],type=type))core_api.create_namespaced_service(namespace=namespace, body=body)
3.删除。
core_api.delete_namespaced_service(namespace=namespace, name=name)
4.数据表格。
table.render({elem: '#test',url:'{% url 'service_api' %}?namespace=' + namespace,toolbar: '#toolbarDemo' //开启头部工具栏,并为其绑定左侧模板,defaultToolbar: ['filter', 'exports', 'print', { //自定义头部工具栏右侧图标。如无需自定义,去除该参数即可title: '提示',layEvent: 'LAYTABLE_TIPS',icon: 'layui-icon-tips'}],cols: [[{field: 'name', title: '名称', sort: true, width: 150},{field: 'namespace', title: '命名空间',width: 150, sort: true},{field: 'type', title: '类型',width: 120, sort: true},{field: 'cluster_ip', title: '集群IP',width: 100},{field: 'ports', title: '端口信息',templet: portsFormat},{field: 'labels', title: '标签', templet: labelsFormat},{field: 'selector', title: 'Pod 标签选择器', templet: selecotrFormat},{field: 'endpoint', title: '后端 Pod'},{field: 'create_time', title: '创建时间'},{fixed: 'right', title:'操作', toolbar: '#barDemo',width: 150}]],page: true,id: 'svctb'
});
// 标签格式化,是一个对象
function labelsFormat(d){result = "";if(d.labels == null){return "None"} else {for (let key in d.labels) {result += '<span style="border: 1px solid #d6e5ec;border-radius: 8px">' +key + ':' + d.labels[key] +'</span><br>'}return result}
}
function selecotrFormat(d){result = "";for(let key in d.selector) {result += '<span style="border: 1px solid #d6e5ec;border-radius: 8px">' +key + ':' + d.selector[key] +'</span><br>'}return result
}
function portsFormat(d) {result = "";for(let key in d.ports) {data = d.ports[key];result += '名称: ' + data.port_name + '<br>' +'端口: ' + data.port + '<br>' +'协议: ' + data.protocol + '<br>' +'容器端口: ' + data.target_port + '<br>'}return result
}
2.9 Ingress
1.查询。
字段:名称、命名空间、HTTP、HTTPS、关联Service、创建时间
for ing in networking_api.list_namespaced_ingress(namespace=namespace).items:name = ing.metadata.namenamespace = ing.metadata.namespacelabels = ing.metadata.labelsservice = "None"http_hosts = "None"for h in ing.spec.rules:host = h.hostpath = ("/" if h.http.paths[0].path is None else h.http.paths[0].path)service_name = h.http.paths[0].backend.service_nameservice_port = h.http.paths[0].backend.service_porthttp_hosts = {'host': host, 'path': path, 'service_name': service_name, 'service_port': service_port}https_hosts = "None"if ing.spec.tls is None:https_hosts = ing.spec.tlselse:for tls in ing.spec.tls:host = tls.hosts[0]secret_name = tls.secret_namehttps_hosts = {'host': host, 'secret_name': secret_name}create_time = ing.metadata.creation_timestamping = {"name": name, "namespace": namespace,"labels": labels ,"http_hosts": http_hosts,"https_hosts": https_hosts, "service": service, "create_time": create_time
2.创建。
name = request.POST.get("name",None)namespace = request.POST.get("namespace",None)host = request.POST.get("host",None)path = request.POST.get("path","/")svc_name = request.POST.get("svc_name",None)svc_port = int(request.POST.get("svc_port",None))body = client.NetworkingV1beta1Ingress(api_version="networking.k8s.io/v1beta1",kind="Ingress",metadata=client.V1ObjectMeta(name=name, annotations={"nginx.ingress.kubernetes.io/rewrite-target": "/"}),spec=client.NetworkingV1beta1IngressSpec(rules=[client.NetworkingV1beta1IngressRule(host=host,http=client.NetworkingV1beta1HTTPIngressRuleValue(paths=[client.NetworkingV1beta1HTTPIngressPath(path=path,backend=client.NetworkingV1beta1IngressBackend(service_port=svc_port,service_name=svc_name))]))]))networking_api.create_namespaced_ingress(namespace=namespace, body=body)
3.删除。
networking_api.delete_namespaced_ingress(namespace=namespace, name=name)
4.数据表格。
table.render({elem: '#test',url:'{% url 'ingress_api' %}?namespace=' + namespace,toolbar: '#toolbarDemo' //开启头部工具栏,并为其绑定左侧模板,defaultToolbar: ['filter', 'exports', 'print', { //自定义头部工具栏右侧图标。如无需自定义,去除该参数即可title: '提示',layEvent: 'LAYTABLE_TIPS',icon: 'layui-icon-tips'}],cols: [[{field: 'name', title: '名称', sort: true, width: 300},{field: 'namespace', title: '命名空间',width: 200, sort: true},{field: 'http_hosts', title: 'HTTP',templet: httpFormat},{field: 'https_hosts', title: 'HTTPS',templet: httpsFormat},{field: 'service', title: '关联 Service', templet: serviceFormat},{field: 'create_time', title: '创建时间',width: 200},{fixed: 'right', title:'操作', toolbar: '#barDemo',width: 150}]],page: true,id: 'ingtb'
});
// 标签格式化,是一个对象
function httpFormat(d){return "域名: " + d.http_hosts.host + '<br>' + "路径: " + d.http_hosts.path + '<br>'
}
function httpsFormat(d){if(d.https_hosts != null){return "域名: " + d.https_hosts.host + '<br>' + "证书Secret名称: " + d.https_hosts.secret_name + '<br>';} else {return "None"}
}
function serviceFormat(d) {return "名称: " + d.http_hosts.service_name + '<br>' + "端口: " + d.http_hosts.service_port + '<br>';
}
2.10 PVC
1.查询。
字段:名称、命名空间、状态、卷名称、容量、访问模式、存储类、创建时间
for pvc in core_api.list_namespaced_persistent_volume_claim(namespace=namespace).items:name = pvc.metadata.namenamespace = pvc.metadata.namespacelabels = pvc.metadata.labelsstorage_class_name = pvc.spec.storage_class_nameaccess_modes = pvc.spec.access_modescapacity = (pvc.status.capacity if pvc.status.capacity is None else pvc.status.capacity["storage"])volume_name = pvc.spec.volume_namestatus = pvc.status.phasecreate_time = pvc.metadata.creation_timestamppvc = {"name": name, "namespace": namespace, "lables": labels,"storage_class_name": storage_class_name, "access_modes": access_modes, "capacity": capacity,"volume_name": volume_name, "status": status, "create_time": create_time}
2.创建。
name = request.POST.get("name", None)namespace = request.POST.get("namespace", None)storage_class = request.POST.get("storage_class", None)access_mode = request.POST.get("access_mode", None)capacity = request.POST.get("capacity", None)body = client.V1PersistentVolumeClaim(api_version="v1",kind="PersistentVolumeClaim",metadata=client.V1ObjectMeta(name=name,namespace=namespace),spec=client.V1PersistentVolumeClaimSpec(storage_class_name=storage_class, # 使用存储类创建PV,如果不用可去掉access_modes=[access_mode],resources=client.V1ResourceRequirements(requests={"storage" : capacity})))core_api.create_namespaced_persistent_volume_claim(namespace=namespace, body=body)
2.删除。
core_api.delete_namespaced_persistent_volume_claim(namespace=namespace, name=name)
3.数据表格。
layui.use('table', function(){var table = layui.table;var $ = layui.jquery;table.render({elem: '#test',url:'{% url 'pvc_api' %}?namespace=' + namespace,toolbar: '#toolbarDemo' //开启头部工具栏,并为其绑定左侧模板,defaultToolbar: ['filter', 'exports', 'print', { //自定义头部工具栏右侧图标。如无需自定义,去除该参数即可title: '提示',layEvent: 'LAYTABLE_TIPS',icon: 'layui-icon-tips'}],cols: [[{field: 'name', title: '名称', sort: true},{field: 'namespace', title: '命名空间',sort: true},{field: 'labels', title: '标签',templet: labelsFormat},{field: 'status', title: '状态',width: 130},{field: 'volume_name', title: '卷名称'},{field: 'capacity', title: '容量',width: 130},{field: 'access_modes', title: '访问模式'},{field: 'storage_class_name', title: '存储类'},{field: 'create_time', title: '创建时间',width: 200},{fixed: 'right', title:'操作', toolbar: '#barDemo',width: 150}]],page: true,id: 'pvctb'});// 标签格式化,是一个对象function labelsFormat(d){result = "";if(d.labels == null){return "None"} else {for (let key in d.labels) {result += '<span style="border: 1px solid #d6e5ec;border-radius: 8px">' +key + ':' + d.labels[key] +'</span><br>'}return result}}
2.11 ConfigMap
1.查询.
字段:名称、命名空间、数据数量、创建时间
for cm in core_api.list_namespaced_config_map(namespace=namespace).items:name = cm.metadata.namenamespace = cm.metadata.namespacedata_length = ("0" if cm.data is None else len(cm.data))create_time = cm.metadata.creation_timestampcm = {"name": name, "namespace": namespace, "data_length": data_length, "create_time": create_time}
2.删除。
core_api.delete_namespaced_config_map(name=name,namespace=namespace)
3.数据表格。
table.render({elem: '#test',url:'{% url 'configmap_api' %}?namespace=' + namespace,toolbar: '#toolbarDemo' //开启头部工具栏,并为其绑定左侧模板,defaultToolbar: ['filter', 'exports', 'print', { //自定义头部工具栏右侧图标。如无需自定义,去除该参数即可title: '提示',layEvent: 'LAYTABLE_TIPS',icon: 'layui-icon-tips'}],cols: [[{field: 'name', title: '名称', sort: true},{field: 'namespace', title: '命名空间',sort: true},{field: 'data_length', title: '数据数量'},{field: 'create_time', title: '创建时间'},{fixed: 'right', title:'操作', toolbar: '#barDemo',width: 150}]],page: true,id: 'cmtb'
});
// 标签格式化,是一个对象
function labelsFormat(d){result = "";if(d.labels == null){return "None"} else {for (let key in d.labels) {result += '<span style="border: 1px solid #d6e5ec;border-radius: 8px">' +key + ':' + d.labels[key] +'</span><br>'}return result}
}
2.12 Secret
1.查询.
字段:名称、命名空间、数据数量、创建时间
for secret in core_api.list_namespaced_secret(namespace=namespace).items:name = secret.metadata.namenamespace = secret.metadata.namespacedata_length = ("空" if secret.data is None else len(secret.data))create_time = secret.metadata.creation_timestampse = {"name": name, "namespace": namespace, "data_length": data_length, "create_time": create_time}
2.删除。
core_api.delete_namespaced_secret(namespace=namespace, name=name)
3.数据表格.
table.render({elem: '#test',url:'{% url 'secret_api' %}?namespace=' + namespace,toolbar: '#toolbarDemo' //开启头部工具栏,并为其绑定左侧模板,defaultToolbar: ['filter', 'exports', 'print', { //自定义头部工具栏右侧图标。如无需自定义,去除该参数即可title: '提示',layEvent: 'LAYTABLE_TIPS',icon: 'layui-icon-tips'}],cols: [[{field: 'name', title: '名称', sort: true},{field: 'namespace', title: '命名空间'},{field: 'data_length', title: '数据数量'},{field: 'create_time', title: '创建时间'},{fixed: 'right', title:'操作', toolbar: '#barDemo',width: 150}]],page: true,id: 'secrettb'
});
// 标签格式化,是一个对象
function labelsFormat(d){result = "";if(d.labels == null){return "None"} else {for (let key in d.labels) {result += '<span style="border: 1px solid #d6e5ec;border-radius: 8px">' +key + ':' + d.labels[key] +'</span><br>'}return result}
}
2.13 优化
1.每个k8s资源都有一个时间,默认是UTC,进行格式化中国时区
def dt_format(dt):current_datetime = dt + timedelta(hours=8)dt = date.strftime(current_datetime, '%Y-%m-%d %H:%M:%S')return dt
相关文章:

python开发基础篇1——后端操作K8s API方式
文章目录 一、基本了解1.1 操作k8s API1.2 基本使用 二、数据表格展示K8s常见资源2.1 Namespace2.2 Node2.3 PV2.4 Deployment2.5 DaemonSet2.6 StatefulSet2.7 Pod2.8 Service2.9 Ingress2.10 PVC2.11 ConfigMap2.12 Secret2.13 优化 一、基本了解 操作K8s资源api方式…...

【实践篇】Redis最强Java客户端(一)之Redisson入门介绍
Redisson入门介绍 文章目录 Redisson入门介绍1.1 Redisson简介1.1.1 起源和历史1.1.2 优势和特点1.1.3 与其他Java Redis客户端的比较 1.2 使用和配置1.2.1 依赖和SDK1.2.2 配置文件解析1.2.3 连接池配置 1.3 优雅的让Hash的某个Field过期2. 参考资料3. 源码地址4. Redis从入门…...

掌握AI助手的魔法工具:解密`Prompt`(提示)在AIGC时代的应用(下篇)
前言:在前面的两篇文章中,我们深入探讨了AI助手中的魔法工具——Prompt(提示)的基本概念以及在AIGC(Artificial Intelligence-Generated Content,人工智能生成内容)时代的应用场景。在本篇中&am…...
十)Stable Diffussion使用教程:Lora
LoRA 的全称为 Low-Rank Adaptation(低秩适应),是一种在机器学习中使用的方法,用于解决一些特殊问题,尤其是在数据中存在不均匀性的情况下表现较好。 要理解 LoRA,我们首先需要理解两个概念:低秩和适应。 低秩(Low Rank):在数学中,秩(Rank)是一个描述矩阵信息量的…...

kafka学习-消费者
目录 1、消费者、消费组 2、心跳机制 3、消费者常见参数配置 4、订阅 5、反序列化 基本概念 自定义反序列化器 6、位移提交 6.1、自动提交 6.2、手动提交 同步提交 异步提交 7、再均衡 7.1、定义与基本概念 7.2、缺陷 7.3、如何避免再均衡 7.4、如何进行组内分…...

Alibaba(商品详情)API接口
为了进行电商平台 的API开发,首先我们需要做下面几件事情。 1)开发者注册一个账号 2)然后为每个alibaba应用注册一个应用程序键(App Key) 。 3)下载alibaba API的SDK并掌握基本的API基础知识和调用 4)利…...

OLED透明屏触控:引领未来科技革命的创新力量
OLED透明屏触控技术作为一项颠覆性的创新,正在引领新一轮科技革命。它将OLED显示技术与触摸技术相结合,实现了透明度和触控功能的完美融合。 在这篇文章中,尼伽将通过引用最新的市场数据、报告和行业动态,详细介绍OLED透明屏触控…...

Ubuntu下QT操作Mysql数据库
本篇总结一下一下Ubuntu下QT操作Mysql数据库。 目录 1. 启动Mysql数据库服务器 2.查看QT支持的数据库驱动 3.连接数据库 4. 增加表和记录 5. 删除记录 6. 修改记录 7. 查询记录 8.完整代码和运行效果 常见错误总结: (1) 数据库服务没启动报错信息 (2) 有…...

sqli --【1--10】
Less-1(联合查询) 1.查看是否有回显 2.查看是否有报错 3.使用联合查询(字符注入) 3.1判断其列数 3.2 判断显示位置 3.3敏感信息查询 Less-2(联合查询) 1.查看是否有回显 2.查看是否有报错 3.使用…...

《自然语言处理(NLP)的最新进展:Transformers与GPT-4的浅析》
🌷🍁 博主猫头虎(🐅🐾)带您 Go to New World✨🍁 🦄 博客首页——🐅🐾猫头虎的博客🎐 🐳 《面试题大全专栏》 🦕 文章图文…...

Wireshark 用命令行分析数据包
1,那些情况需要使用命令行 Wireshark一次性提供了太多的信息。使用命令行工具可以限制打印出的信息,最后只显示相关数据,比如用单独一行来显示IP地址。命令行工具适用于过滤数据包捕获文件,并提供结果给另一个支持UNIX管道的工具…...

LVS DR模式负载均衡群集部署
目录 1 LVS-DR 模式的特点 1.1 数据包流向分析 1.2 DR 模式的特点 2 DR模式 LVS负载均衡群集部署 2.1 配置负载调度器 2.1.1 配置虚拟 IP 地址 2.1.2 调整 proc 响应参数 2.1.3 配置负载分配策略 2.2 部署共享存储 2.3 配置节点服务器 2.3.1 配置虚拟 IP 地址 2.3.2…...

探讨前后端分离开发的优势、实践以及如何实现更好的用户体验?
随着互联网技术的迅猛发展,前后端分离开发已经成为现代软件开发的一种重要趋势。这种开发模式将前端和后端的开发工作分开,通过清晰的接口协议进行通信,旨在优化开发流程、提升团队协作效率,并最终改善用户体验。本文将深入探讨前…...
微博一面:JVM预热,你的方案是啥?
说在前面 在40岁老架构师 尼恩的读者社区(50)中,最近有小伙伴拿到了一线互联网企业如微博、阿里、汽车之家、极兔、有赞、希音、百度、网易、滴滴的面试资格,遇到一几个很重要的面试题: JVM预热,你的方案是啥?Springb…...
open与fopen的区别
1. 来源 从来源的角度看,两者能很好的区分开,这也是两者最显而易见的区别: open是UNIX系统调用函数(包括LINUX等),返回的是文件描述符(File Descriptor),它是文件在文件…...
Unity记录一些glsl和hlsl的着色器Shader逆向代码
以下内容一般基于 GLSL 300 之后 以下某些代码行,是“伪代码“,绝大部分是renderDoc 逆向产生标准代码 本人OpenlGL零基础,也不打算重头学 目录 Clip() 剔除函数 discard; FS最终颜色输出 out 和最终颜色相加方程…...

基于Sentinel的微服务保护
前言 Sentinel是Alibaba开源的一款微服务流控组件,用于解决分布式应用场景下服务的稳定性问题。Sentinel具有丰富的应用场景,它基于流量提供一系列的服务保护措施,例如多线程秒杀情况下的系统承载,并发访问下的流量控制ÿ…...

Collectors类作用:
一、Collectors类: 1.1、Collectors介绍 Collectors类,是JDK1.8开始提供的一个的工具类,它专门用于对Stream操作流中的元素各种处理操作,Collectors类中提供了一些常用的方法,例如:toList()、toSet()、to…...

LASSO回归
LASSO回归 LASSO(Least Absolute Shrinkage and Selection Operator,最小绝对值收敛和选择算子算法)是一种回归分析技术,用于变量选择和正则化。它由Robert Tibshirani于1996年提出,作为传统最小二乘回归方法的替代品。 损失函数 1.线性回…...
机器学习中的 K-均值聚类算法及其优缺点。
K-均值聚类算法是一种常见的无监督学习算法,它可以将数据集分成 K 个簇,每个簇内部的数据点尽可能相似,而不同簇之间的数据点应尽可能不同。下面详细讲解 K-均值聚类算法的优缺点: 优点: 简单易用:K-均值…...

Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...
蓝桥杯 2024 15届国赛 A组 儿童节快乐
P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡,轻快的音乐在耳边持续回荡,小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下,六一来了。 今天是六一儿童节,小蓝老师为了让大家在节…...
Frozen-Flask :将 Flask 应用“冻结”为静态文件
Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是:将一个 Flask Web 应用生成成纯静态 HTML 文件,从而可以部署到静态网站托管服务上,如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...

tree 树组件大数据卡顿问题优化
问题背景 项目中有用到树组件用来做文件目录,但是由于这个树组件的节点越来越多,导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多,导致的浏览器卡顿,这里很明显就需要用到虚拟列表的技术&…...

优选算法第十二讲:队列 + 宽搜 优先级队列
优选算法第十二讲:队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...
Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析
Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析 一、第一轮提问(基础概念问题) 1. 请解释Spring框架的核心容器是什么?它在Spring中起到什么作用? Spring框架的核心容器是IoC容器&#…...
IP如何挑?2025年海外专线IP如何购买?
你花了时间和预算买了IP,结果IP质量不佳,项目效率低下不说,还可能带来莫名的网络问题,是不是太闹心了?尤其是在面对海外专线IP时,到底怎么才能买到适合自己的呢?所以,挑IP绝对是个技…...

[免费]微信小程序问卷调查系统(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】
大家好,我是java1234_小锋老师,看到一个不错的微信小程序问卷调查系统(SpringBoot后端Vue管理端)【论文源码SQL脚本】,分享下哈。 项目视频演示 【免费】微信小程序问卷调查系统(SpringBoot后端Vue管理端) Java毕业设计_哔哩哔哩_bilibili 项…...

代码规范和架构【立芯理论一】(2025.06.08)
1、代码规范的目标 代码简洁精炼、美观,可持续性好高效率高复用,可移植性好高内聚,低耦合没有冗余规范性,代码有规可循,可以看出自己当时的思考过程特殊排版,特殊语法,特殊指令,必须…...
怎么让Comfyui导出的图像不包含工作流信息,
为了数据安全,让Comfyui导出的图像不包含工作流信息,导出的图像就不会拖到comfyui中加载出来工作流。 ComfyUI的目录下node.py 直接移除 pnginfo(推荐) 在 save_images 方法中,删除或注释掉所有与 metadata …...