最近工作任务就是调用k8s的接口服务,然后也是解决了很多坑目前调用K8s api的方面资料少用的人少,那么就把这些积累的点记下来分享一下,也希望对大家的工作和学习有帮助。
调用k8s使用rest api形式一个是安全的地址https:127.0.0.1:6443,这个地址需要有认证权限的,可以是token方式或者是证书,这个也是我一开始使用的方式,无奈没有办法知道token什么时候过期,但是目前实验只要K8s正常启动一直没有换token也还是可以使用。
那我现在就用Kuboard获取token的方式也是能有权限操作k8s客户端接口的,如果跳过可以看1.2不授权方式,我java接口调用用的就是这种方式。
应该可以使用命令直接查询,但我这边是用的k8s的可视化Kuboard,其实kubernetes-dashboard这个官方的可视化也是可以的获取的,我拿Kuboard为例,kuboard官网获取token的命令是
kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep kuboard-user | awk '{print $1}')
然后就会获取到如下token ,直接拷走token,用https:127.0.0.1:6443地址就能进行postman测试了
当然kubernetes-dashboard也是一样要获取token,获取完的token我们这个地址也一样能使用
第二个方式是不安全的地址http://127.0.0.1:8008,就是说可以不用认证权限就可以直接访问K8s了,因为真的不知道token什么时候过期,2是k8s不稳定老是重装我就得需要换token,麻烦所以我就用这种方式了,但是网上都说这个地址可以使用但是我用一直拒绝访问我根本没法使用,原因是因为我们没有进行配置,需要对kube-apiserver进行配置地址供我们访问。
输入如下命令:
vim /etc/kubernetes/manifests/kube-apiserver.yaml
在下图的地方添加以下,写好以后保存退出,他就会重启稍微等一下我们就可以访问一下地址
- --enable-swagger-ui=true
- --insecure-bind-address=0.0.0.0
- --insecure-port=8008
我的就可以访问了
#yml
k8s:
api-http: http://192.168.7.115:8008
@Value("${k8s.api-http}")
private String httpApi;
/**
* k8s的初始化
*
* @return
*/
public ApiClient getConnection() {
ApiClient client = new ClientBuilder().
setBasePath(httpApi).setVerifyingSsl(false).build();
//setAuthentication(new AccessTokenAuthentication(token))
Configuration.setDefaultApiClient(client);
return client;
}
public Map creatNamespace(V1Namespace body) {
Map message = new HashMap<>();
// k8s初始化
ApiClient client = k8sInit.getConnection();
CoreV1Api apiInstance = new CoreV1Api();
try {
V1Namespace result = apiInstance.createNamespace(body, null, null, null);
message.put("success", "应用命名空间创建成功!");
} catch (ApiException e) {
log.error("Exception when calling CoreV1Api#createNamespace");
log.error("Status code: {}", e.getCode());
log.error("Reason: {}", e.getResponseBody());
log.error("Response headers: {}", e.getResponseHeaders());
if (e.getCode() == 409) {
message.put("error", "命名空间已重复!");
}
if (e.getCode() == 200) {
message.put("success", "应用命名空间创建成功!");
}
if (e.getCode() == 201) {
message.put("error", "命名空间已重复!");
}
if (e.getCode() == 401) {
message.put("error", "无权限操作!");
}
message.put("error", "应用命名空间创建失败!");
}
return message;
}
创建命名空间的参数值
{
"apiVersion":"v1",
"kind":"Namespace",
"metadata":{"name":"test-namespace","labels":{"name":"test-namespace"}}
}
postman返回值
看kuboard成功创建!
其实在Deployments做这个接口的时候我一直在纠结,是先要做Deployments还是先创建pod容器,后来发现Deployments或者是DaemonSet还是ReplicaSet,都是pod的管理器也就是说我们创建Deployments就会默认创建容器Pod(ps:Deployments一般部署应用级别的,DaemonSet我在做监控节点的时候用过这种级别的,另一些管理器还不理解),
那咱们来先创建应用(Deployments)的把!我这里主要是k8s自带的实体太复杂,沟通以后怕前端难弄懂,所以我给他们封装的简单的实体,由我后台对k8s实体进行赋值这样的操作。
其实我有创建pod的接口还有删除命名空间的接口,但是由于io.kubernetes-client-java删除命名空间时能删除,但是返回时源码内部报错没有办法我用了另外一种方式io.fabric8,会在下一篇博客中记录。
博客地址:https://blog.csdn.net/dfBeautifulLive/article/details/103086719
public Map createDeployments(DeploymentDTO bodyDto) {
// 为了kuboard分层操作,不用kuboard可以不做操作,当然参数bodyDto.getLabels_workLayer()传递的是空的化默认就是不分层,加不加影响不大,都可以打进k8s部署
String nameStr = bodyDto.getLabels_workLayer() + "-" + bodyDto.getMetadata_name();
Map messages = new HashMap<>();
// 赋值操作
V1Deployment body = new V1Deployment();
body.setApiVersion("apps/v1");
body.kind("Deployment");
// 赋值metadata
V1ObjectMeta objectMeta = new V1ObjectMeta();
if (bodyDto.getLabels_workLayer() != null &&
!bodyDto.getLabels_workLayer().equals("")) {
objectMeta.setName(nameStr);
}else{
objectMeta.setName(bodyDto.getMetadata_name());
}
objectMeta.setNamespace(bodyDto.getMetadata_namespace());
Map annotation = new HashMap<>();
annotation.put("k8s.eip.work/displayName", bodyDto.getRemark());
annotation.put("k8s.eip.work/ingress", "false");
annotation.put("k8s.eip.work/service", "ClusterIP");
annotation.put("k8s.eip.work/workload", nameStr);
// 默认不分层
if (bodyDto.getLabels_workLayer() != null &&
!bodyDto.getLabels_workLayer().equals("")) {
objectMeta.setAnnotations(annotation);
}
// 赋值spec
V1DeploymentSpec deploymentSpec = new V1DeploymentSpec();
deploymentSpec.setReplicas(bodyDto.getSpec_replicas());
// templete
Map Labels = new HashMap();
//Labels.put("app", "test-bs");
if (bodyDto.getLabels_workLayer() != null &&
!bodyDto.getLabels_workLayer().equals("")) {
Labels.put("k8s.eip.work/layer", bodyDto.getLabels_workLayer());
Labels.put("k8s.eip.work/name", nameStr);
} else {
Labels.put("app", bodyDto.getMetadata_name());
}
objectMeta.setLabels(Labels);
V1PodTemplateSpec templateSpec = new V1PodTemplateSpec();
templateSpec.setMetadata(objectMeta);
// spec-Template下的Spec
V1PodSpec podSpec = new V1PodSpec();
// spec-Template-spec-container
List listContainer = new ArrayList<>();
V1Container container = new V1Container();
container.setName(bodyDto.getContainers_name());
container.setImage(bodyDto.getContainers_image());
container.setImagePullPolicy(bodyDto.getContainers_imagePullPolicy());
listContainer.add(container);
podSpec.setContainers(listContainer);
templateSpec.setSpec(podSpec);
// spec-selector
Map matchLabels = new HashMap<>();
if (bodyDto.getLabels_workLayer() != null &&
!bodyDto.getLabels_workLayer().equals("")) {
matchLabels.put("k8s.eip.work/layer", bodyDto.getLabels_workLayer());
matchLabels.put("k8s.eip.work/name", bodyDto.getLabels_workLayer() + "-" + bodyDto.getMetadata_name());
} else {
matchLabels.put("app", bodyDto.getMetadata_name());
}
V1LabelSelector selector = new V1LabelSelector();
selector.setMatchLabels(matchLabels);
deploymentSpec.setTemplate(templateSpec);
deploymentSpec.setSelector(selector);
body.setMetadata(objectMeta);
body.setSpec(deploymentSpec);
//body.getSpec().getTemplate().getMetadata().setAnnotations(null);
ApiClient client = k8sInit.getConnection();
AppsV1Api apiInstance = new AppsV1Api(client);
try {
V1Deployment result = apiInstance.createNamespacedDeployment(objectMeta.getNamespace(), body, null, null, null);
messages.put("success", "工作负载创建成功!");
} catch (ApiException e) {
if (e.getCode() == 409) {
messages.put("error", "工作负载创建已重复!");
} else if (e.getCode() == 200) {
messages.put("success", "工作负载创建成功!");
} else if (e.getCode() == 201) {
messages.put("error", "工作负载创建已重复!");
} else if (e.getCode() == 401) {
messages.put("error", "无权限操作!");
} else {
messages.put("error", "工作负载创建失败!");
}
log.error("Exception when calling AppsV1Api#createNamespacedDeployment");
log.error("Status code: {}", e.getCode());
log.error("Reason: {}", e.getResponseBody());
log.error("Response headers: {}", e.getResponseHeaders());
}
return messages;
}
postman参数
{
"metadata_name":"test-bs",
"metadata_namespace":"test-namespace",
"labels_workLayer":"svc",
"spec_replicas":2,
"containers_name":"test-bsc",
"containers_image":"gsa-service-overview:v1.0.0",
"containers_imagePullPolicy":"IfNotPresent",
"remark":"测试项目"
}
返回值
查看kuboard就发现项目打进来了
接下来就是创建service来暴露或者映射端口了
public Map createService(ServiceDTO serviceDTO) {
Map message = new HashMap<>();
String nameStr = serviceDTO.getLabels_workLayer() + "-" + serviceDTO.getMetadata_name();
ApiClient client = k8sInit.getConnection();
CoreV1Api apiInstance = new CoreV1Api(client);
V1Service body = new V1Service();
body.setApiVersion("v1");
body.setKind("Service");
V1ObjectMeta objectMeta = new V1ObjectMeta();
objectMeta.setName(nameStr);
objectMeta.setNamespace(serviceDTO.getMetadata_namespace());
Map annotation = new HashMap<>();
annotation.put("k8s.eip.work/displayName", serviceDTO.getRemark());
annotation.put("k8s.eip.work/workload", nameStr);
objectMeta.setAnnotations(annotation);
Map Labels = new HashMap();
Labels.put("k8s.eip.work/layer", serviceDTO.getLabels_workLayer());
Labels.put("k8s.eip.work/name", nameStr);
objectMeta.setLabels(Labels);
V1ServiceSpec serviceSpec = new V1ServiceSpec();
List servicePorts = new ArrayList<>();
serviceSpec.setType(serviceDTO.getSpec_type());
V1ServicePort servicePort = new V1ServicePort();
//servicePort.setName(serviceDTO.getSpec_ports_name());
servicePort.setPort(serviceDTO.getSpec_ports_port());
servicePort.setNodePort(serviceDTO.getSpec_ports_nodePort());
servicePort.setProtocol(serviceDTO.getSpec_ports_protocol());
servicePort.setTargetPort(serviceDTO.getSpec_ports_targetPort());
servicePorts.add(servicePort);
// selector
Map selector = new HashMap<>();
selector.put("k8s.eip.work/layer", serviceDTO.getLabels_workLayer());
selector.put("k8s.eip.work/name", nameStr);
serviceSpec.setPorts(servicePorts);
serviceSpec.setSelector(selector);
body.setMetadata(objectMeta);
body.setSpec(serviceSpec);
try {
V1Service result = apiInstance.createNamespacedService(serviceDTO.getMetadata_namespace(), body, null, null, null);
message.put("success", "工作负载服务创建成功!");
} catch (ApiException e) {
if (e.getCode() == 409) {
message.put("error", "工作负载服务创建已重复!");
} else if (e.getCode() == 200) {
message.put("success", "工作负载服务创建成功!");
} else if (e.getCode() == 201) {
message.put("error", "工作负载服务创建已重复!");
} else if (e.getCode() == 401) {
message.put("error", "无权限操作!");
} else if (e.getCode() == 400) {
message.put("error", "后台参数错误!");
} else if (e.getCode() == 400) {
message.put("error", "没有命名空间或没有Deployment!");
} else {
message.put("error", "工作负载服务创建失败!");
}
log.error("Exception when calling AppsV1Api#createNamespacedDeployment");
log.error("Status code: {}", e.getCode());
log.error("Reason: {}", e.getResponseBody());
log.error("Response headers: {}", e.getResponseHeaders());
}
return message;
}
postman参数
{
"metadata_name":"test-bs",
"metadata_namespace":"test",
"labels_workLayer":"svc",
"spec_type":"ClusterIP",
"spec_ports_port":8995,
"spec_ports_targetPort":8995,
"spec_ports_protocol":"TCP"
}
返回值
在查看kuboard的访问方式模块,发现了我们节点端口,容器端口,服务端口等等都打进来了
以上就是自己研究调的K8s接口,希望对你有帮助!