案例描述

本案例讲述了Python调用Kubernetes API以及SDK实现Kubernetes资源的管理,并基于http.server模块,封装Kubernetes资源的API,实现将Kubernetes资源封装为Web服务。

规划节点

节点规划见表1-1。

表1-1 节点规划

IP 主机名 节点
192.168.200.21 master master

基础准备

确保已部署完成Kubernetes集群,安装了Python3的环境。

下载本案例所需用的的代码原文件:

1
kubernetes-py.tar.gz

案例实施

基于Kubernetes Restful API实现Deployment创建

在提供的OpenStack私有云平台上,使用k8s-python-dev镜像创建1台云主机,云主机类型使用4vCPU/12G内存/100G硬盘。该主机中已经默认安装了所需的开发环境,登录默认账号密码为“root/1DaoYun@2022”。

使用Kubernetes Restful API库,在/root目录下,创建api_deployment_manager.py文件,要求编写Python代码,代码实现以下任务:

(1)编写Python程序实现Deployment资源的创建。Deployment配置信息如下。如果同名Deployment存在,先删除再创建。

(2)创建完成后,查询该Deployment的详细信息,执行结果控制台输出,以yaml格式展示。

下载离线源,加载镜像:

1
2
3
[root@master ~]# ls
nginx-v1.tar
[root@master ~]# docker load < nginx-v1.tar

创建Deployment 的yaml的配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[root@master ~]# vi nginx-deployment.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:v1

api_deployment_manager.py:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import requests,json,yaml,time
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

def get_token(api_token,):
bearer_token = "bearer " + api_token
return bearer_token

class dep_manager:
def __init__(self,node_url,bearer_token):
self.node_url = node_url
self.bearer_token = bearer_token

def create_dep(self,yamlFile,namespace):
headers = {
"Content-Type": "application/json",
"Authorization": self.bearer_token
}
with open(yamlFile, encoding='utf-8') as f:
body = json.dumps(yaml.safe_load(f))

url = self.node_url + "/apis/apps/v1/namespaces/" + namespace + "/deployments"
req = json.loads(requests.post(url, headers=headers, data=body, verify=False).text)
return req

def get_dep(self,dep_name,namespace):
headers = {
"Authorization": self.bearer_token
}
url = self.node_url + "/apis/apps/v1/namespaces/" + namespace + "/deployments/" + dep_name
req = json.loads(requests.get(url, headers=headers, verify=False).text)
return req

if __name__ == "__main__":
#token换成本机的token,创建token方法如下
#kubectl create serviceaccount admin1 -n kube-system
#kubectl create clusterrolebinding admin1 --clusterrole=cluster-admin --serviceaccount=kube-system:admin1
#kubectl describe secrets -n kube-system admin1-token-
api_token = "eyJhbGciOiJSUzI1NiIsImtpZCI6ImhfMFBweXhjU1JNSjZ4cXY4eVdkRktaYVNvOVh3RGF1WFJqU1pidVBhOVEifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJhZG1pbjEtdG9rZW4tOTdtcnEiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiYWRtaW4xIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiMmMxZDM5MDEtNDlkMy00MjI3LWE1YmEtNmZmZjE1ZjFkZWJkIiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50Omt1YmUtc3lzdGVtOmFkbWluMSJ9.hoydITIrmggAN0Hqss_Vhuo6MCY5VbkUZNLuPS9jyGFSD_phb9b0f-jdTBdzHGvmtB7ULKQQuYY78y3Ba1LMMBZA78GQJPwleYhD4hRIVNDSd9LpWMPnfaqshk5EBRRTr1ZUV5y_MUw74RtQ5tL4o3CpXjpODRHOV2lAx5W1ubjyNDP1y-NAXTTfNX_q9gybuHgJGSY_ybo63Z66qxmLH7NucPgOCJsgc8XVhP0V9UoGpRPQ47A5kX6dj2LGdCSpcM240IKNSeUkdM0Nf5fyrImYtsAG9AVrJ2v1fmKCW_Gvly382WcSNySIqVmHrmvV2nbhjUQWSN3JVU8mJZOipw"
node_url = "https://172.128.11.39:6443"
bearer_token = get_token(api_token, )
dep_m = dep_manager(node_url,bearer_token)

#create
dep_create = dep_m.create_dep("nginx-deployment.yaml","default")
time.sleep(10)
print(f"创建deployment信息为:{dep_create}")

#get
get_dep = dep_m.get_dep("nginx-deployment","default")
print(f"获取到Deployment的信息为{get_dep}")

执行api_deployment_manager.py文件:

1
2
3
4
[root@master ~]# python3 api_deployment_manager.py
------------------------------------------------执行结果----------------------------------------------------------
创建deployment信息为:{'kind': 'Deployment', 'apiVersion': 'apps/v1', 'metadata': {'name': 'nginx-deployment', 'namespace': 'default', 'uid': '3b526406-895e-4c05-86a8-636c4e857f70', 'resourceVersion': '65978', 'generation': 1, 'creationTimestamp': '2022-10-11T02:17:46Z', 'labels': {'app': 'nginx'}, 'managedFields': [{'manager': 'python-requests', 'operation': 'Update', 'apiVersion': 'apps/v1', 'time': '2022-10-11T02:17:46Z', 'fieldsType': 'FieldsV1', 'fieldsV1': {'f:metadata': {'f:labels': {'.': {}, 'f:app': {}}}, 'f:spec': {'f:progressDeadlineSeconds': {}, 'f:replicas': {}, 'f:revisionHistoryLimit': {}, 'f:selector': {}, 'f:strategy': {'f:rollingUpdate': {'.': {}, 'f:maxSurge': {}, 'f:maxUnavailable': {}}, 'f:type': {}}, 'f:template': {'f:metadata': {'f:labels': {'.': {}, 'f:app': {}}}, 'f:spec': {'f:containers': {'k:{"name":"nginx"}': {'.': {}, 'f:image': {}, 'f:imagePullPolicy': {}, 'f:name': {}, 'f:ports': {'.': {}, 'k:{"containerPort":80,"protocol":"TCP"}': {'.': {}, 'f:containerPort': {}, 'f:protocol': {}}}, 'f:resources': {}, 'f:terminationMessagePath': {}, 'f:terminationMessagePolicy': {}}}, 'f:dnsPolicy': {}, 'f:restartPolicy': {}, 'f:schedulerName': {}, 'f:securityContext': {}, 'f:terminationGracePeriodSeconds': {}}}}}}]}, 'spec': {'replicas': 3, 'selector': {'matchLabels': {'app': 'nginx'}}, 'template': {'metadata': {'creationTimestamp': None, 'labels': {'app': 'nginx'}}, 'spec': {'containers': [{'name': 'nginx', 'image': 'nginx:1.15.4', 'ports': [{'containerPort': 80, 'protocol': 'TCP'}], 'resources': {}, 'terminationMessagePath': '/dev/termination-log', 'terminationMessagePolicy': 'File', 'imagePullPolicy': 'IfNotPresent'}], 'restartPolicy': 'Always', 'terminationGracePeriodSeconds': 30, 'dnsPolicy': 'ClusterFirst', 'securityContext': {}, 'schedulerName': 'default-scheduler'}}, 'strategy': {'type': 'RollingUpdate', 'rollingUpdate': {'maxUnavailable': '25%', 'maxSurge': '25%'}}, 'revisionHistoryLimit': 10, 'progressDeadlineSeconds': 600}, 'status': {}}
获取到Deployment的信息为{'kind': 'Deployment', 'apiVersion': 'apps/v1', 'metadata': {'name': 'nginx-deployment', 'namespace': 'default', 'uid': '3b526406-895e-4c05-86a8-636c4e857f70', 'resourceVersion': '66033', 'generation': 1, 'creationTimestamp': '2022-10-11T02:17:46Z', 'labels': {'app': 'nginx'}, 'annotations': {'deployment.kubernetes.io/revision': '1'}, 'managedFields': [{'manager': 'python-requests', 'operation': 'Update', 'apiVersion': 'apps/v1', 'time': '2022-10-11T02:17:46Z', 'fieldsType': 'FieldsV1', 'fieldsV1': {'f:metadata': {'f:labels': {'.': {}, 'f:app': {}}}, 'f:spec': {'f:progressDeadlineSeconds': {}, 'f:replicas': {}, 'f:revisionHistoryLimit': {}, 'f:selector': {}, 'f:strategy': {'f:rollingUpdate': {'.': {}, 'f:maxSurge': {}, 'f:maxUnavailable': {}}, 'f:type': {}}, 'f:template': {'f:metadata': {'f:labels': {'.': {}, 'f:app': {}}}, 'f:spec': {'f:containers': {'k:{"name":"nginx"}': {'.': {}, 'f:image': {}, 'f:imagePullPolicy': {}, 'f:name': {}, 'f:ports': {'.': {}, 'k:{"containerPort":80,"protocol":"TCP"}': {'.': {}, 'f:containerPort': {}, 'f:protocol': {}}}, 'f:resources': {}, 'f:terminationMessagePath': {}, 'f:terminationMessagePolicy': {}}}, 'f:dnsPolicy': {}, 'f:restartPolicy': {}, 'f:schedulerName': {}, 'f:securityContext': {}, 'f:terminationGracePeriodSeconds': {}}}}}}, {'manager': 'kube-controller-manager', 'operation': 'Update', 'apiVersion': 'apps/v1', 'time': '2022-10-11T02:17:48Z', 'fieldsType': 'FieldsV1', 'fieldsV1': {'f:metadata': {'f:annotations': {'.': {}, 'f:deployment.kubernetes.io/revision': {}}}, 'f:status': {'f:availableReplicas': {}, 'f:conditions': {'.': {}, 'k:{"type":"Available"}': {'.': {}, 'f:lastTransitionTime': {}, 'f:lastUpdateTime': {}, 'f:message': {}, 'f:reason': {}, 'f:status': {}, 'f:type': {}}, 'k:{"type":"Progressing"}': {'.': {}, 'f:lastTransitionTime': {}, 'f:lastUpdateTime': {}, 'f:message': {}, 'f:reason': {}, 'f:status': {}, 'f:type': {}}}, 'f:observedGeneration': {}, 'f:readyReplicas': {}, 'f:replicas': {}, 'f:updatedReplicas': {}}}, 'subresource': 'status'}]}, 'spec': {'replicas': 3, 'selector': {'matchLabels': {'app': 'nginx'}}, 'template': {'metadata': {'creationTimestamp': None, 'labels': {'app': 'nginx'}}, 'spec': {'containers': [{'name': 'nginx', 'image': 'nginx:1.15.4', 'ports': [{'containerPort': 80, 'protocol': 'TCP'}], 'resources': {}, 'terminationMessagePath': '/dev/termination-log', 'terminationMessagePolicy': 'File', 'imagePullPolicy': 'IfNotPresent'}], 'restartPolicy': 'Always', 'terminationGracePeriodSeconds': 30, 'dnsPolicy': 'ClusterFirst', 'securityContext': {}, 'schedulerName': 'default-scheduler'}}, 'strategy': {'type': 'RollingUpdate', 'rollingUpdate': {'maxUnavailable': '25%', 'maxSurge': '25%'}}, 'revisionHistoryLimit': 10, 'progressDeadlineSeconds': 600}, 'status': {'observedGeneration': 1, 'replicas': 3, 'updatedReplicas': 3, 'readyReplicas': 3, 'availableReplicas': 3, 'conditions': [{'type': 'Available', 'status': 'True', 'lastUpdateTime': '2022-10-11T02:17:48Z', 'lastTransitionTime': '2022-10-11T02:17:48Z', 'reason': 'MinimumReplicasAvailable', 'message': 'Deployment has minimum availability.'}, {'type': 'Progressing', 'status': 'True', 'lastUpdateTime': '2022-10-11T02:17:48Z', 'lastTransitionTime': '2022-10-11T02:17:46Z', 'reason': 'NewReplicaSetAvailable', 'message': 'ReplicaSet "nginx-deployment-746ccc65d8" has successfully progressed.'}]}}

查看pod运行情况:

1
2
3
4
5
[root@master ~]# kubectl get pods 
NAME READY STATUS RESTARTS AGE
nginx-deployment-6f494fd48c-8vlmx 1/1 Running 0 6m55s
nginx-deployment-6f494fd48c-ljtrc 1/1 Running 0 6m55s
nginx-deployment-6f494fd48c-qp5vg 1/1 Running 0 6m55s

基于Kubernetes Python SDK实现Job创建

在前面已建好的Kubernetes开发环境云平台上。使用Kubernetes Python SDK的“kubernetes”Python库,在/root目录下,创建sdk_job_manager.py文件,要求编写Python代码,代码实现以下任务:

(1)编写Python程序实现Job资源的创建。Job配置信息如下。如果同名Job存在,先删除再创建(需要将集群的config文件夹放到/root)。

(2)创建完成后,查询该Job的详细信息,执行结果控制台输出,以Json格式展示。

Job创建yaml的信息如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# vi spec-pi-job.yaml  
apiVersion: v1
kind: Pod
metadata:
name: python-dev-pod-nginx2
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:v1
ports:
- containerPort: 9081
protocol: TCP

sdk_job_manager.py:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
import requests,json,time,yaml
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

def get_token(api_token,):
bearer_token = "bearer " + api_token
return bearer_token

class pod_manager:
def __init__(self,node_url,bearer_token):
self.node_url = node_url
self.bearer_token = bearer_token

def create_pod(self,yamlFile,namespace):
headers = {
"Content-Type": "application/json",
"Authorization": self.bearer_token
}
with open(yamlFile,encoding='utf-8')as f:
body = json.dumps(yaml.safe_load(f))

url = self.node_url + "/api/v1/namespaces/" + namespace + "/pods"
req = json.loads(requests.post(url,headers=headers,data=body,verify=False).text)

return req

def get_pod(self,pod_name,namespace):
headers = {
"Authorization": self.bearer_token
}
url = self.node_url + "/api/v1/namespaces/" + namespace + "/pods/" + pod_name
req = json.loads(requests.get(url,headers=headers,verify=False).text)
return req

def delete_pod(self,pod_name,namespace):
headers = {
"Authorization": self.bearer_token
}
url = self.node_url + "/api/v1/namespaces/" + namespace + "/pods/" + pod_name
req = requests.delete(url,headers=headers,verify=False)
resp = json.loads(req.text)
if req.status_code == 200:
print(f"删除Pod成功,返回的信息为:{resp}",req.status_code)
else:
print(f"删除Pod失败,返回的信息为",req.status_code)
return
#https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#create-service-v1-core
def get_api_server_token(api_server_token, node_url):

# Bearer token
bearer_token = "bearer " + api_server_token
return bearer_token

def get_api_pod_manager():
# 将获取到的token值放到api_server_token中去
# 节点URL地址
api_server_token = "eyJhbGciOiJSUzI1NiIsImtpZCI6ImhfMFBweXhjU1JNSjZ4cXY4eVdkRktaYVNvOVh3RGF1WFJqU1pidVBhOVEifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJhZG1pbjEtdG9rZW4tOTdtcnEiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiYWRtaW4xIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiMmMxZDM5MDEtNDlkMy00MjI3LWE1YmEtNmZmZjE1ZjFkZWJkIiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50Omt1YmUtc3lzdGVtOmFkbWluMSJ9.hoydITIrmggAN0Hqss_Vhuo6MCY5VbkUZNLuPS9jyGFSD_phb9b0f-jdTBdzHGvmtB7ULKQQuYY78y3Ba1LMMBZA78GQJPwleYhD4hRIVNDSd9LpWMPnfaqshk5EBRRTr1ZUV5y_MUw74RtQ5tL4o3CpXjpODRHOV2lAx5W1ubjyNDP1y-NAXTTfNX_q9gybuHgJGSY_ybo63Z66qxmLH7NucPgOCJsgc8XVhP0V9UoGpRPQ47A5kX6dj2LGdCSpcM240IKNSeUkdM0Nf5fyrImYtsAG9AVrJ2v1fmKCW_Gvly382WcSNySIqVmHrmvV2nbhjUQWSN3JVU8mJZOipw"
cluster_server_url = "https://172.128.11.39:6443"
node_url = "https://172.128.11.39:6443"
bearer_token = get_api_server_token(api_server_token, cluster_server_url)
pod_m = pod_manager(node_url,bearer_token)
return pod_m

if __name__ == "__main__":
api_token = "eyJhbGciOiJSUzI1NiIsImtpZCI6ImhfMFBweXhjU1JNSjZ4cXY4eVdkRktaYVNvOVh3RGF1WFJqU1pidVBhOVEifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJhZG1pbjEtdG9rZW4tOTdtcnEiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiYWRtaW4xIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiMmMxZDM5MDEtNDlkMy00MjI3LWE1YmEtNmZmZjE1ZjFkZWJkIiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50Omt1YmUtc3lzdGVtOmFkbWluMSJ9.hoydITIrmggAN0Hqss_Vhuo6MCY5VbkUZNLuPS9jyGFSD_phb9b0f-jdTBdzHGvmtB7ULKQQuYY78y3Ba1LMMBZA78GQJPwleYhD4hRIVNDSd9LpWMPnfaqshk5EBRRTr1ZUV5y_MUw74RtQ5tL4o3CpXjpODRHOV2lAx5W1ubjyNDP1y-NAXTTfNX_q9gybuHgJGSY_ybo63Z66qxmLH7NucPgOCJsgc8XVhP0V9UoGpRPQ47A5kX6dj2LGdCSpcM240IKNSeUkdM0Nf5fyrImYtsAG9AVrJ2v1fmKCW_Gvly382WcSNySIqVmHrmvV2nbhjUQWSN3JVU8mJZOipw"
node_url = "https://172.128.11.39:6443"
bearer_token = get_token(api_token,)
pod_m = pod_manager(node_url,bearer_token)

# 1delete
delete_pod = pod_m.delete_pod("python-dev-pod-nginx2", "default")

#2create
create_pod = pod_m.create_pod("spec-pi-job.yaml","default")
print(f"创建的Pod信息为:{create_pod}")

#3get pod
get_pod = pod_m.get_pod("python-dev-pod-nginx2","default")
print(f"查询到的Pod信息为:{get_pod}")

#4delete
delete_pod = pod_m.delete_pod("python-dev-pod-nginx2","default")

执行sdk_job_manager.py文件:

1
[root@master ~]# python3 sdk_job_manager.py

Pod资源的Restful APIs HTTP服务封装

编写Python程序实现Pod资源管理程序,将Pod资源管理的封装成Web服务。

在/root目录下创建pod_server.py程序,实现Pod的增删查改等Web访问操作。http.server的host为localhost,端口8889;程序内部实现Kubernetes认证。

提示说明:Python标准库http.server模块,提供了HTTP Server请求封装。

需要实现的Restful API接口如下:

  • GET /pod/{name} :查询指定名称{name}的Pod;Response的Body以Json格式输出。
  • POST /pod/{yamlfilename} :创建yaml文件名称为{yamlfilename}的Pod;Response的Body以Json格式。

使用curl -X GET 127.0.0.1:8889/pod/来测试,创建Pod的yaml文件如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# vi python-dev-pod-nginx2.yaml 
apiVersion: v1
kind: Pod
metadata:
name: python-dev-pod-nginx2
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:v1
ports:
- containerPort: 9081
protocol: TCP

api_pod_manager.py:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
import requests,json,time,yaml
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

def get_token(api_token,):
bearer_token = "bearer " + api_token
return bearer_token

class pod_manager:
def __init__(self,node_url,bearer_token):
self.node_url = node_url
self.bearer_token = bearer_token

def create_pod(self,yamlFile,namespace):
headers = {
"Content-Type": "application/json",
"Authorization": self.bearer_token
}
with open(yamlFile,encoding='utf-8')as f:
body = json.dumps(yaml.safe_load(f))

url = self.node_url + "/api/v1/namespaces/" + namespace + "/pods"
req = json.loads(requests.post(url,headers=headers,data=body,verify=False).text)

return req

def get_pod(self,pod_name,namespace):
headers = {
"Authorization": self.bearer_token
}
url = self.node_url + "/api/v1/namespaces/" + namespace + "/pods/" + pod_name
req = json.loads(requests.get(url,headers=headers,verify=False).text)
return req

def delete_pod(self,pod_name,namespace):
headers = {
"Authorization": self.bearer_token
}
url = self.node_url + "/api/v1/namespaces/" + namespace + "/pods/" + pod_name
req = requests.delete(url,headers=headers,verify=False)
resp = json.loads(req.text)
if req.status_code == 200:
print(f"删除Pod成功,返回的信息为:{resp}",req.status_code)
else:
print(f"删除Pod失败,返回的信息为",req.status_code)
return
#https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#create-service-v1-core
def get_api_server_token(api_server_token, node_url):

# Bearer token
bearer_token = "bearer " + api_server_token
return bearer_token

def get_api_pod_manager():
# 将获取到的token值放到api_server_token中去
# 节点URL地址
api_server_token = "eyJhbGciOiJSUzI1NiIsImtpZCI6ImhfMFBweXhjU1JNSjZ4cXY4eVdkRktaYVNvOVh3RGF1WFJqU1pidVBhOVEifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJhZG1pbjEtdG9rZW4tOTdtcnEiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiYWRtaW4xIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiMmMxZDM5MDEtNDlkMy00MjI3LWE1YmEtNmZmZjE1ZjFkZWJkIiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50Omt1YmUtc3lzdGVtOmFkbWluMSJ9.hoydITIrmggAN0Hqss_Vhuo6MCY5VbkUZNLuPS9jyGFSD_phb9b0f-jdTBdzHGvmtB7ULKQQuYY78y3Ba1LMMBZA78GQJPwleYhD4hRIVNDSd9LpWMPnfaqshk5EBRRTr1ZUV5y_MUw74RtQ5tL4o3CpXjpODRHOV2lAx5W1ubjyNDP1y-NAXTTfNX_q9gybuHgJGSY_ybo63Z66qxmLH7NucPgOCJsgc8XVhP0V9UoGpRPQ47A5kX6dj2LGdCSpcM240IKNSeUkdM0Nf5fyrImYtsAG9AVrJ2v1fmKCW_Gvly382WcSNySIqVmHrmvV2nbhjUQWSN3JVU8mJZOipw"
cluster_server_url = "https://172.128.11.39:6443"
node_url = "https://172.128.11.39:6443"
bearer_token = get_api_server_token(api_server_token, cluster_server_url)
pod_m = pod_manager(node_url,bearer_token)
return pod_m

if __name__ == "__main__":
api_token = "eyJhbGciOiJSUzI1NiIsImtpZCI6ImhfMFBweXhjU1JNSjZ4cXY4eVdkRktaYVNvOVh3RGF1WFJqU1pidVBhOVEifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJhZG1pbjEtdG9rZW4tOTdtcnEiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiYWRtaW4xIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiMmMxZDM5MDEtNDlkMy00MjI3LWE1YmEtNmZmZjE1ZjFkZWJkIiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50Omt1YmUtc3lzdGVtOmFkbWluMSJ9.hoydITIrmggAN0Hqss_Vhuo6MCY5VbkUZNLuPS9jyGFSD_phb9b0f-jdTBdzHGvmtB7ULKQQuYY78y3Ba1LMMBZA78GQJPwleYhD4hRIVNDSd9LpWMPnfaqshk5EBRRTr1ZUV5y_MUw74RtQ5tL4o3CpXjpODRHOV2lAx5W1ubjyNDP1y-NAXTTfNX_q9gybuHgJGSY_ybo63Z66qxmLH7NucPgOCJsgc8XVhP0V9UoGpRPQ47A5kX6dj2LGdCSpcM240IKNSeUkdM0Nf5fyrImYtsAG9AVrJ2v1fmKCW_Gvly382WcSNySIqVmHrmvV2nbhjUQWSN3JVU8mJZOipw"
node_url = "https://172.128.11.39:6443"
bearer_token = get_token(api_token,)
pod_m = pod_manager(node_url,bearer_token)

# 1delete
delete_pod = pod_m.delete_pod("python-dev-pod-nginx2", "default")

#2create
create_pod = pod_m.create_pod("python-dev-pod-nginx2.yaml","default")
print(f"创建的Pod信息为:{create_pod}")

#3get pod
get_pod = pod_m.get_pod("python-dev-pod-nginx2","default")
print(f"查询到的Pod信息为:{get_pod}")

#4delete
delete_pod = pod_m.delete_pod("python-dev-pod-nginx2","default")

pod_server.py:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
import requests
import threading
from http.server import HTTPServer, BaseHTTPRequestHandler
import json
PORT = 8889
# request handler
import api_pod_manager

pod_m = api_pod_manager.get_api_pod_manager()

class MyHandler(BaseHTTPRequestHandler):
#Header setting
def _set_headers(self,content_type):
self.send_response(200) # 200 stands for request succeeded
self.send_header("Content-type", content_type) # informs requests of the Media type
self.end_headers()

def do_GET(self):
self._set_headers("application/json")

print(self.path)
#不同路径
# /pod/name
if self.path.startswith('/pod/'):
name = self.path[10:]
print(name)
result = pod_m.get_pod(name, "default")
# converts dictionary to a JSON string
json_string = json.dumps(result)
self.wfile.write(json_string.encode(encoding='utf_8'))

else:#
json_string = json.dumps({'path': 'home', 'received': 'ok'})
self.wfile.write(json_string.encode(encoding='utf_8'))

def do_POST(self):
self._set_headers("application/json")
print(self.path)
if self.path.startswith('/pod/'):
filename = self.path[10:]
print(filename)
result = pod_m.create_pod(filename, "default")
# converts dictionary to a JSON string
json_string = json.dumps(result)
self.wfile.write(json_string.encode(encoding='utf_8'))

def do_DELETE(self):
self._set_headers("application/json")
print(self.path)
if self.path.startswith('/pod/'):
name = self.path[10:]
print(name)
result = pod_m.delete_pod(name,"default")

def run(server_class=HTTPServer, handler_class=MyHandler, addr="localhost", port=PORT):
server_address = (addr, port)
httpd = server_class(server_address, handler_class)
print(f"Starting httpd server on {addr}:{port}") # f before string allows special formatting
httpd.serve_forever()


#start
if __name__ == "__main__":
print("---------start web ----------------")
run()
print("---------end web----------------")

后台执行:

1
[root@master ~]# python3 pod_server.py >/dev/null 2>&1 &

测试接口:

1
2
3
4
[root@master ~]# curl -X GET 127.0.0.1:8889/pod/
---------------------------------可以使用Postman或者Apifox来测试接口--------------------------------
curl -X GET 127.0.0.1:8889/pod/
{"kind": "PodList", "apiVersion": "v1", "metadata": {"resourceVersion": "80124"}, "items": [{"metadata": {"name": "nginx-pod", "namespace": "default", "uid": "2f464e2f-6b6e-4da0-85c2-d69da8f9db11", "resourceVersion": "80123", "creationTimestamp": "2022-10-11T05:32:17Z", "annotations": {"cni.projectcalico.org/podIP": "10.244.235.214/32", "cni.projectcalico.org/podIPs": "10.244.235.214/32", "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"v1\",\"kind\":\"Pod\",\"metadata\":{\"annotations\":{},\"name\":\"nginx-pod\",\"namespace\":\"default\"},\"spec\":{\"containers\":[{\"image\":\"nginx:1.16\",\"imagePullPolicy\":\"IfNotPresent\",\"name\":\"pod-nginx\"}]}}\n"}, "managedFields": [{"manager": "kubectl-client-side-apply", "operation": "Update", "apiVersion": "v1", "time": "2022-10-11T05:32:17Z", "fieldsType": "FieldsV1", "fieldsV1": {"f:metadata": {"f:annotations": {".": {}, "f:kubectl.kubernetes.io/last-applied-configuration": {}}}, "f:spec": {"f:containers": {"k:{\"name\":\"pod-nginx\"}": {".": {}, "f:image": {}, "f:imagePullPolicy": {}, "f:name": {}, "f:resources": {}, "f:terminationMessagePath": {}, "f:terminationMessagePolicy": {}}}, "f:dnsPolicy": {}, "f:enableServiceLinks": {}, "f:restartPolicy": {}, "f:schedulerName": {}, "f:securityContext": {}, "f:terminationGracePeriodSeconds": {}}}}, {"manager": "calico", "operation": "Update", "apiVersion": "v1", "time": "2022-10-11T05:32:18Z", "fieldsType": "FieldsV1", "fieldsV1": {"f:metadata": {"f:annotations": {"f:cni.projectcalico.org/podIP": {}, "f:cni.projectcalico.org/podIPs": {}}}}, "subresource": "status"}, {"manager": "kubelet", "operation": "Update", "apiVersion": "v1", "time": "2022-10-11T05:32:19Z", "fieldsType": "FieldsV1", "fieldsV1": {"f:status": {"f:conditions": {"k:{\"type\":\"ContainersReady\"}": {".": {}, "f:lastProbeTime": {}, "f:lastTransitionTime": {}, "f:status": {}, "f:type": {}}, "k:{\"type\":\"Initialized\"}": {".": {}, "f:lastProbeTime": {}, "f:lastTransitionTime": {}, "f:status": {}, "f:type": {}}, "k:{\"type\":\"Ready\"}": {".": {}, "f:lastProbeTime": {}, "f:lastTransitionTime": {}, "f:status": {}, "f:type": {}}}, "f:containerStatuses": {}, "f:hostIP": {}, "f:phase": {}, "f:podIP": {}, "f:podIPs": {".": {}, "k:{\"ip\":\"10.244.235.214\"}": {".": {}, "f:ip": {}}}, "f:startTime": {}}}, "subresource": "status"}]}, "spec": {"volumes": [{"name": "kube-api-access-4f2c6", "projected": {"sources": [{"serviceAccountToken": {"expirationSeconds": 3607, "path": "token"}}, {"configMap": {"name": "kube-root-ca.crt", "items": [{"key": "ca.crt", "path": "ca.crt"}]}}, {"downwardAPI": {"items": [{"path": "namespace", "fieldRef": {"apiVersion": "v1", "fieldPath": "metadata.namespace"}}]}}], "defaultMode": 420}}], "containers": [{"name": "pod-nginx", "image": "nginx:1.16", "resources": {}, "volumeMounts": [{"name": "kube-api-access-4f2c6", "readOnly": true, "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount"}], "terminationMessagePath": "/dev/termination-log", "terminationMessagePolicy": "File", "imagePullPolicy": "IfNotPresent"}], "restartPolicy": "Always", "terminationGracePeriodSeconds": 30, "dnsPolicy": "ClusterFirst", "serviceAccountName": "default", "serviceAccount": "default", "nodeName": "k8s-master", "securityContext": {}, "schedulerName": "default-scheduler", "tolerations": [{"key": "node.kubernetes.io/not-ready", "operator": "Exists", "effect": "NoExecute", "tolerationSeconds": 300}, {"key": "node.kubernetes.io/unreachable", "operator": "Exists", "effect": "NoExecute", "tolerationSeconds": 300}], "priority": 0, "enableServiceLinks": true, "preemptionPolicy": "PreemptLowerPriority"}, "status": {"phase": "Running", "conditions": [{"type": "Initialized", "status": "True", "lastProbeTime": null, "lastTransitionTime": "2022-10-11T05:32:17Z"}, {"type": "Ready", "status": "True", "lastProbeTime": null, "lastTransitionTime": "2022-10-11T05:32:19Z"}, {"type": "ContainersReady", "status": "True", "lastProbeTime": null, "lastTransitionTime": "2022-10-11T05:32:19Z"}, {"type": "PodScheduled", "status": "True", "lastProbeTime": null, "lastTransitionTime": "2022-10-11T05:32:17Z"}], "hostIP": "192.168.100.10", "podIP": "10.244.235.214", "podIPs": [{"ip": "10.244.235.214"}], "startTime": "2022-10-11T05:32:17Z", "containerStatuses": [{"name": "pod-nginx", "state": {"running": {"startedAt": "2022-10-11T05:32:18Z"}}, "lastState": {}, "ready": true, "restartCount": 0, "image": "nginx:1.16", "imageID": "docker-pullable://nginx@sha256:d20aa6d1cae56fd17cd458f4807e0de462caf2336f0b70b5eeb69fcaaf30dd9c", "containerID": "docker://4bc8b2ffa93fe12a30d119fca8ad0225db5ff93e6ab53e90abaf63d067fb06a7", "started": true}], "qosClass": "BestEffort"}}]}

Service资源Restful APIs HTTP服务封装

编写Python程序实现Service资源管理程序,将Service资源管理的封装成Web服务。

在/root目录下创建service_server.py程序,实现Service的增删查改等Web访问操作。http.server的host为localhost,端口8888;程序内部实现Kubernetes认证。

提示说明:Python标准库http.server模块,提供了HTTP Server请求封装。

需要实现的Restful API接口如下:

  • GET /services/{name}:查询指定名称{name}的Service;Response的Body以Json格式输出。
  • POST /services/{yamlfilename} :创建yaml文件名称为{yamlfilename}的Service;Response的Body以Json格式,(手工将文件服务器主目录所有*.yaml文件下载到root目录下)。
  • DELETE /services/{name}:删除指定名称的Service;Response的Body以Json格式。

使用curl -X GET 127.0.0.1:8888/services/kubernetes可以进行测试,创建service的yaml文件如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
# vi python-dev-svc3.yaml 
apiVersion: v1
kind: Service
metadata:
name: nginx-svc3
namespace: default
spec:
selector:
app: nginx
ports:
- port: 80
targetPort: 80
nodePort: 30083

api_service_manager.py:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import requests,time
import logging
import os,yaml,json
#-----------logger-----------
#get logger
logger = logging.getLogger(__name__)
# level
logger.setLevel(logging.DEBUG)
# format
format = logging.Formatter('%(asctime)s %(message)s')
# to console
stream_handler = logging.StreamHandler()
stream_handler .setFormatter(format)
logger.addHandler(stream_handler )
#-----------logger-----------

#服务接口
#https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#create-service-v1-core
def get_api_server_token(api_server_token, node_url):

# Bearer token
bearer_token = "bearer " + api_server_token
return bearer_token

class api_service_manager():
def __init__(self,node_url: str, bearer_token: str):
self.node_url = node_url
self.bearer_token = bearer_token

#创建svc
def create_svc(self, yamlFile, namespace: str):
headers = {
"Authorization": self.bearer_token,
"Content-Type": "application/json"
}
# 读取yaml文件,并转化为JSON数据
with open(yamlFile, encoding="utf8") as f:
body = json.dumps(yaml.safe_load(f))

request_url = self.node_url + "/api/v1/namespaces/" + namespace + "/services"
result = json.loads(requests.post(request_url, data=body, headers=headers, verify=False).text)
logger.debug(f"返回信息:{str(result)}")
return result

#获取svc,如果想指定获取某个svc的信息,可以加上svc_name,若不想则去掉。
def get_svc(self,svc_name:str,namespace:str):
headers = {
"Authorization": self.bearer_token,
"pretty" : "true"
}
request_url = self.node_url + "/api/v1/namespaces/" + namespace + "/services/" + svc_name
result = json.loads(requests.get(request_url, headers=headers, verify=False).text)
logger.debug(f"返回信息:{str(result)}")
return result

#更改svc,将targetPort从80更改为8080
def update_svc(self,svc_name:str,yamlFile,namespace:str):
headers = {
"Authorization": self.bearer_token,
"Content-Type": "application/strategic-merge-patch+json"
}
with open(yamlFile, encoding="utf8") as f:
body = json.dumps(yaml.safe_load(f))
# '{"spec": {"ports": [{"port": 80, "targetPort": 8089}]}}'
# body = {"spec": {"ports": [{"port": 80, "targetPort": 80}]}}

request_url = self.node_url + "/api/v1/namespaces/" + namespace + "/services/" + svc_name
resp = requests.put(request_url, data=json.dumps(body), headers=headers, verify=False)
result = json.loads(resp.text)
logger.debug(f"返回信息:{str(result)}")
return result

#删除svc
def delete_svc(self,svc_name:str,namespace:str):
headers = {
"Authorization": self.bearer_token
}
request_url = self.node_url + "/api/v1/namespaces/" + namespace + "/services/" + svc_name
result = json.loads(requests.delete(request_url, headers=headers, verify=False).text)
logger.debug(f"返回信息:{str(result)}")
return result

def get_api_service_manager():
# 使用自建token
# 将获取到的token值放到api_server_token中去
# 将获取到的token值放到api_server_token中去
api_server_token = "eyJhbGciOiJSUzI1NiIsImtpZCI6ImhfMFBweXhjU1JNSjZ4cXY4eVdkRktaYVNvOVh3RGF1WFJqU1pidVBhOVEifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJhZG1pbjEtdG9rZW4tOTdtcnEiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiYWRtaW4xIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiMmMxZDM5MDEtNDlkMy00MjI3LWE1YmEtNmZmZjE1ZjFkZWJkIiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50Omt1YmUtc3lzdGVtOmFkbWluMSJ9.hoydITIrmggAN0Hqss_Vhuo6MCY5VbkUZNLuPS9jyGFSD_phb9b0f-jdTBdzHGvmtB7ULKQQuYY78y3Ba1LMMBZA78GQJPwleYhD4hRIVNDSd9LpWMPnfaqshk5EBRRTr1ZUV5y_MUw74RtQ5tL4o3CpXjpODRHOV2lAx5W1ubjyNDP1y-NAXTTfNX_q9gybuHgJGSY_ybo63Z66qxmLH7NucPgOCJsgc8XVhP0V9UoGpRPQ47A5kX6dj2LGdCSpcM240IKNSeUkdM0Nf5fyrImYtsAG9AVrJ2v1fmKCW_Gvly382WcSNySIqVmHrmvV2nbhjUQWSN3JVU8mJZOipw"
# 节点URL地址 192.168.138.201
cluster_server_url = "https://172.128.11.39:6443"
bearer_token = get_api_server_token(api_server_token, cluster_server_url)
svc_m = api_service_manager(cluster_server_url, bearer_token)
return svc_m




if __name__ == "__main__":
#使用自建token
# 将获取到的token值放到api_server_token中去
api_server_token = "eyJhbGciOiJSUzI1NiIsImtpZCI6ImhfMFBweXhjU1JNSjZ4cXY4eVdkRktaYVNvOVh3RGF1WFJqU1pidVBhOVEifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJhZG1pbjEtdG9rZW4tOTdtcnEiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiYWRtaW4xIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiMmMxZDM5MDEtNDlkMy00MjI3LWE1YmEtNmZmZjE1ZjFkZWJkIiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50Omt1YmUtc3lzdGVtOmFkbWluMSJ9.hoydITIrmggAN0Hqss_Vhuo6MCY5VbkUZNLuPS9jyGFSD_phb9b0f-jdTBdzHGvmtB7ULKQQuYY78y3Ba1LMMBZA78GQJPwleYhD4hRIVNDSd9LpWMPnfaqshk5EBRRTr1ZUV5y_MUw74RtQ5tL4o3CpXjpODRHOV2lAx5W1ubjyNDP1y-NAXTTfNX_q9gybuHgJGSY_ybo63Z66qxmLH7NucPgOCJsgc8XVhP0V9UoGpRPQ47A5kX6dj2LGdCSpcM240IKNSeUkdM0Nf5fyrImYtsAG9AVrJ2v1fmKCW_Gvly382WcSNySIqVmHrmvV2nbhjUQWSN3JVU8mJZOipw"
# 节点URL地址 192.168.138.201
cluster_server_url = "https://172.128.11.39:6443"

bearer_token = get_api_server_token(api_server_token, cluster_server_url)
svc_m = api_service_manager(cluster_server_url,bearer_token)

namespace = "default"
svc_name = "nginx-svc3"
yaml_file = "python-dev-svc3.yaml"

#1删除svc
svc_m.delete_svc(svc_name,namespace)

#2创建svc
print("crate ----------------")
# svc_m.create_svc(yaml_file, namespace)

#3获取svc
print("get ----------------")
svc_m.get_svc(svc_name,namespace)

#4删除svc
svc_m.delete_svc(svc_name,namespace)

service_server.py:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
import requests
import threading
from http.server import HTTPServer, BaseHTTPRequestHandler
import json
PORT = 8888
# request handler
import api_service_manager

svc_m = api_service_manager.get_api_service_manager()

class MyHandler(BaseHTTPRequestHandler):
#Header setting
def _set_headers(self,content_type):
self.send_response(200) # 200 stands for request succeeded
self.send_header("Content-type", content_type) # informs requests of the Media type
self.end_headers()

def do_GET(self):
self._set_headers("application/json")

print(self.path)
#不同路径
# /services/name
if self.path.startswith('/services/'):
name = self.path[10:]
print(name)
result = svc_m.get_svc(name, "default")
# converts dictionary to a JSON string
json_string = json.dumps(result)
self.wfile.write(json_string.encode(encoding='utf_8'))


#Test 写入内容
# json_string = json.dumps({'getpath': name})
# self.wfile.write(json_string.encode(encoding='utf_8'))


else:#
json_string = json.dumps({'path': 'home', 'received': 'ok'})
self.wfile.write(json_string.encode(encoding='utf_8'))

def do_POST(self):
print("post")
self._set_headers("application/json")
print(self.path)
if self.path.startswith('/services/'):
filename = self.path[10:]
print("filename---", filename)
result = svc_m.create_svc(filename, "default")
# converts dictionary to a JSON string
print("result---", result)
json_string = json.dumps(result)
self.wfile.write(json_string.encode(encoding='utf_8'))

def do_DELETE(self):
self._set_headers("application/json")
print(self.path)
if self.path.startswith('/services/'):
name = self.path[10:]
print(name)
result = svc_m.delete_svc(name,"default")

def run(server_class=HTTPServer, handler_class=MyHandler, addr="localhost", port=PORT):
server_address = (addr, port)
httpd = server_class(server_address, handler_class)
print(f"Starting httpd server on {addr}:{port}") # f before string allows special formatting
httpd.serve_forever()


#start
if __name__ == "__main__":
print("---------start----------------")
thread = threading.Thread(target=run)
# if threading isn't used, then serve_forever() (line 43) will just stop all code run after it
thread.start()
print("---------end----------------")

后台执行:

1
[root@master ~]# python3 service_server.py >/dev/null 2>&1 &

测试接口:

1
2
3
[root@master ~]# curl -X GET 127.0.0.1:8888/services/kubernetes  
------------------------------------------------执行结果----------------------------------------------------------
{"kind": "Service", "apiVersion": "v1", "metadata": {"name": "kubernetes", "namespace": "default", "uid": "03f5c7e3-2a61-4e73-85d1-33db58e33aa5", "resourceVersion": "206", "creationTimestamp": "2022-11-18T03:52:43Z", "labels": {"component": "apiserver", "provider": "kubernetes"}, "managedFields": [{"manager": "kube-apiserver", "operation": "Update", "apiVersion": "v1", "time": "2022-11-18T03:52:43Z", "fieldsType": "FieldsV1", "fieldsV1": {"f:metadata": {"f:labels": {".": {}, "f:component": {}, "f:provider": {}}}, "f:spec": {"f:clusterIP": {}, "f:internalTrafficPolicy": {}, "f:ipFamilyPolicy": {}, "f:ports": {".": {}, "k:{\"port\":443,\"protocol\":\"TCP\"}": {".": {}, "f:name": {}, "f:port": {}, "f:protocol": {}, "f:targetPort": {}}}, "f:sessionAffinity": {}, "f:type": {}}}}]}, "spec": {"ports": [{"name": "https", "protocol": "TCP", "port": 443, "targetPort": 6443}], "clusterIP": "192.96.0.1", "clusterIPs": ["192.96.0.1"], "type": "ClusterIP", "sessionAffinity": "None", "ipFamilies": ["IPv4"], "ipFamilyPolicy": "SingleStack", "internalTrafficPolicy": "Cluster"}, "status": {"loadBalancer": {}}}