k8s的python客户端库--kubernetes

简介

Kubernetes 是什么

Kubernetes 是一个全新的基于容器技术的分布式架构解决方案,是 Google 开源的一个容器集群管理系统,Kubernetes 简称 K8S。

Kubernetes 是一个一站式的完备的分布式系统开发和支撑平台,更是一个开放平台,对现有的编程语言、编程框架、中间件没有任何侵入性。

Kubernetes 提供了完善的管理工具,这些工具涵盖了开发、部署测试、运维监控在内的各个环节。

Kubernetes 具有完备的集群管理能力,包括多层次的安全防护和准入机制、多租户应用支撑能力、透明的服务注册和服务发现机制、内建智能负载均衡器、强大的故障发现和自我修复能力、服务滚动升级和在线扩容能力、可扩展的资源自动调度机制、多粒度的资源配额管理能力。

Kubernetes 特性

  1. 自我修复
    在节点故障时,重新启动失败的容器,替换和重新部署,保证预期的副本数量;杀死健康检查失败的容器,并且在未准备好之前不会处理用户的请求,确保线上服务不中断。
  2. 弹性伸缩
    使用命令、UI或者基于CPU使用情况自动快速扩容和缩容应用程序实例,保证应用业务高峰并发时的高可用性;业务低峰时回收资源,以最小成本运行服务。
  3. 自动部署和回滚
    K8S采用滚动更新策略更新应用,一次更新一个Pod,而不是同时删除所有Pod,如果更新过程中出现问题,将回滚更改,确保升级不影响业务。
  4. 服务发现和负载均衡
    K8S为多个容器提供一个统一访问入口(内部IP地址和一个DNS名称),并且负载均衡关联的所有容器,使得用户无需考虑容器IP问题。
  5. 机密和配置管理
    管理机密数据和应用程序配置,而不需要把敏感数据暴露在镜像里,提高敏感数据安全性。并可以将一些常用的配置存储在K8S中,方便应用程序使用。
  6. 存储编排
    挂载外部存储系统,无论是来自本地存储,公有云,还是网络存储,都作为集群资源的一部分使用,极大提高存储使用灵活性。
  7. 批处理
    提供一次性任务,定时任务;满足批量数据处理和分析的场景。

k8s官网

官网:https://kubernetes.io/zh-cn/

文档:https://kubernetes.io/zh-cn/docs/home/

集群

k8s集群怎么安装可以看之前的博客,有讲怎么部署了,这里就不做赘述了

客户端

参考

客户端库:https://kubernetes.io/zh-cn/docs/reference/using-api/client-libraries/

python库:https://github.com/kubernetes-client/python/

版本要求

支持的客户端版本的兼容性列表

  • client 9.y.z: Kubernetes 1.12 or below (+-), Kubernetes 1.13 (✓), Kubernetes 1.14 or above (+-)
  • client 10.y.z: Kubernetes 1.13 or below (+-), Kubernetes 1.14 (✓), Kubernetes 1.14 or above (+-)
  • client 11.y.z: Kubernetes 1.14 or below (+-), Kubernetes 1.15 (✓), Kubernetes 1.16 or above (+-)
  • client 12.y.z: Kubernetes 1.15 or below (+-), Kubernetes 1.16 (✓), Kubernetes 1.17 or above (+-)
  • client 17.y.z: Kubernetes 1.16 or below (+-), Kubernetes 1.17 (✓), Kubernetes 1.18 or above (+-)
  • client 18.y.z: Kubernetes 1.17 or below (+-), Kubernetes 1.18 (✓), Kubernetes 1.19 or above (+-)
  • client 19.y.z: Kubernetes 1.18 or below (+-), Kubernetes 1.19 (✓), Kubernetes 1.20 or above (+-)
  • client 20.y.z: Kubernetes 1.19 or below (+-), Kubernetes 1.20 (✓), Kubernetes 1.21 or above (+-)
  • client 21.y.z: Kubernetes 1.20 or below (+-), Kubernetes 1.21 (✓), Kubernetes 1.22 or above (+-)
  • client 22.y.z: Kubernetes 1.21 or below (+-), Kubernetes 1.22 (✓), Kubernetes 1.23 or above (+-)
  • client 23.y.z: Kubernetes 1.22 or below (+-), Kubernetes 1.23 (✓), Kubernetes 1.24 or above (+-)
  • client 24.y.z: Kubernetes 1.23 or below (+-), Kubernetes 1.24 (✓), Kubernetes 1.25 or above (+-)
  • client 25.y.z: Kubernetes 1.24 or below (+-), Kubernetes 1.25 (✓), Kubernetes 1.26 or above (+-)
  • client 26.y.z: Kubernetes 1.25 or below (+-), Kubernetes 1.26 (✓), Kubernetes 1.27 or above (+-)
  • client 27.y.z: Kubernetes 1.26 or below (+-), Kubernetes 1.27 (✓), Kubernetes 1.28 or above (+-)
  • client 28.y.z: Kubernetes 1.27 or below (+-), Kubernetes 1.28 (✓), Kubernetes 1.29 or above (+-)
  • client 29.y.z: Kubernetes 1.28 or below (+-), Kubernetes 1.29 (✓), Kubernetes 1.30 or above (+-)
  • client 30.y.z: Kubernetes 1.29 or below (+-), Kubernetes 1.30 (✓), Kubernetes 1.31 or above (+-)

测试环境k8s版本

$ kubectl version
Client Version: v1.30.1
Kustomize Version: v5.0.4-0.20230601165947-6ce0bf390ce3
Server Version: v1.30.0

所以安装最新版本就可以

安装

pip install kubernetes

或者

poetry add kubernetes

连接

from kubernetes import client, config

# 加载配置文件
config.load_kube_config(config_file="examples/k8s/admin.conf")
# 如果在k8s的本机上,或者配置文件是~/.kube/config,则可以直接加载配置
# config.load_kube_config()

# 创建API对象
api_instance = client.CoreV1Api()

# 使用API对象执行操作,例如列出所有命名空间
namespace_list = api_instance.list_namespace()
for namespace in namespace_list.items:
    print(namespace.metadata.name)

使用config.load_kube_config()方法来连接k8s集群

配置文件的获取方式有两种

  • 显式通过 config_file 参数来指定
  • 不指定 config_file 参数,会先检查环境变量
    • 如果找到环境变量 KUBECONFIG ,那么就直接使用 KUBECONFIG 的值
    • 如果找不到环境变量,那就会找 ~/.kube/config

操作k8s

参考 https://github.com/kubernetes-client/python/tree/master/examples

获取POD相关信息

from prettytable import PrettyTable
from kubernetes import client, config

from common.k8s_format import get_age

# 加载配置文件
config.load_kube_config(config_file="examples/k8s/admin.conf")

# 创建API对象
api_instance = client.CoreV1Api()

# 列出所有pod
table = PrettyTable()
table.align = "l"
table.field_names = ["NAME", "NAMESPACE", "READY", "STATUS", "RESTARTS", "AGE", "IP", "NODE"]
table.title = "所有名称空间下的POD"
pod_list = api_instance.list_pod_for_all_namespaces()
for pod in pod_list.items:
    ready = 0
    restarts = 0
    for s in pod.status.container_statuses:
        if s.ready:
            ready += 1
        restarts += s.restart_count
    table.add_row([pod.metadata.name, pod.metadata.namespace,
                   f"{ready}/{len(pod.status.container_statuses)}", pod.status.phase, restarts,
                   get_age(pod.status.start_time), pod.status.pod_ip, pod.spec.node_name])
print(table)
"""
+-----------------------------------------------------------------------------------------------------------------------+
|                                                  所有名称空间下的POD                                                  |
+------------------------------------------+-------------+-------+---------+----------+--------+----------------+-------+
| NAME                                     | NAMESPACE   | READY | STATUS  | RESTARTS | AGE    | IP             | NODE  |
+------------------------------------------+-------------+-------+---------+----------+--------+----------------+-------+
| nginx-deployment-68c885dc79-6g8cr        | default     | 1/1   | Running | 0        | 2m19s  | 10.244.166.178 | node1 |
| nginx-deployment-68c885dc79-k66gf        | default     | 1/1   | Running | 0        | 2m19s  | 10.244.166.180 | node1 |
| nginx-deployment-68c885dc79-qtkvs        | default     | 1/1   | Running | 0        | 2m19s  | 10.244.166.179 | node1 |
| calico-kube-controllers-776b58cfc5-dd8s4 | kube-system | 1/1   | Running | 2        | 18d23h | 10.244.166.139 | node1 |
| calico-node-8ssd6                        | kube-system | 1/1   | Running | 2        | 18d23h | 192.168.140.76 | node1 |
| calico-node-nkckv                        | kube-system | 1/1   | Running | 2        | 18d23h | 192.168.140.75 | node  |
| coredns-7b5944fdcf-qrm6v                 | kube-system | 1/1   | Running | 2        | 18d23h | 10.244.166.142 | node1 |
| coredns-7b5944fdcf-tm2gx                 | kube-system | 1/1   | Running | 2        | 18d23h | 10.244.166.141 | node1 |
| etcd-node                                | kube-system | 1/1   | Running | 2        | 18d22h | 192.168.140.75 | node  |
| kube-apiserver-node                      | kube-system | 1/1   | Running | 2        | 18d22h | 192.168.140.75 | node  |
| kube-controller-manager-node             | kube-system | 1/1   | Running | 2        | 18d22h | 192.168.140.75 | node  |
| kube-proxy-2cndq                         | kube-system | 1/1   | Running | 2        | 18d23h | 192.168.140.75 | node  |
| kube-proxy-5mdhc                         | kube-system | 1/1   | Running | 2        | 18d23h | 192.168.140.76 | node1 |
| kube-scheduler-node                      | kube-system | 1/1   | Running | 2        | 18d22h | 192.168.140.75 | node  |
+------------------------------------------+-------------+-------+---------+----------+--------+----------------+-------+
"""


# 列出指定名称空间下的所有pod
table = PrettyTable()
table.align = "l"
table.field_names = ["NAME", "NAMESPACE", "READY", "STATUS", "RESTARTS", "AGE", "IP", "NODE"]

namespace = "default"
table.title = "{}名称空间下的POD".format(namespace)
pod_list = api_instance.list_namespaced_pod(namespace=namespace)
for pod in pod_list.items:
    ready = 0
    restarts = 0
    for s in pod.status.container_statuses:
        if s.ready:
            ready += 1
        restarts += s.restart_count
    table.add_row([pod.metadata.name, pod.metadata.namespace,
                   f"{ready}/{len(pod.status.container_statuses)}", pod.status.phase, restarts,
                   get_age(pod.status.start_time), pod.status.pod_ip, pod.spec.node_name])
print(table)
"""
+--------------------------------------------------------------------------------------------------------------+
|                                            default名称空间下的POD                                            |
+-----------------------------------+-----------+-------+---------+----------+--------+----------------+-------+
| NAME                              | NAMESPACE | READY | STATUS  | RESTARTS | AGE    | IP             | NODE  |
+-----------------------------------+-----------+-------+---------+----------+--------+----------------+-------+
| nginx-deployment-68c885dc79-6g8cr | default   | 1/1   | Running | 0        | 23m46s | 10.244.166.178 | node1 |
| nginx-deployment-68c885dc79-k66gf | default   | 1/1   | Running | 0        | 23m46s | 10.244.166.180 | node1 |
| nginx-deployment-68c885dc79-qtkvs | default   | 1/1   | Running | 0        | 23m46s | 10.244.166.179 | node1 |
+-----------------------------------+-----------+-------+---------+----------+--------+----------------+-------+
"""


# 读取指定pod的信息
table = PrettyTable()
table.align = "l"
table.field_names = ["NAME", "NAMESPACE", "READY", "STATUS", "RESTARTS", "AGE", "IP", "NODE"]

namespace = "default"
name="nginx-deployment-68c885dc79-6g8cr"
pod = api_instance.read_namespaced_pod(name, namespace)
ready = 0
restarts = 0
for s in pod.status.container_statuses:
    if s.ready:
        ready += 1
    restarts += s.restart_count
table.add_row([pod.metadata.name, pod.metadata.namespace,
               f"{ready}/{len(pod.status.container_statuses)}", pod.status.phase, restarts,
               get_age(pod.status.start_time), pod.status.pod_ip, pod.spec.node_name])
print(table)
"""
+-----------------------------------+-----------+-------+---------+----------+--------+----------------+-------+
| NAME                              | NAMESPACE | READY | STATUS  | RESTARTS | AGE    | IP             | NODE  |
+-----------------------------------+-----------+-------+---------+----------+--------+----------------+-------+
| nginx-deployment-68c885dc79-6g8cr | default   | 1/1   | Running | 0        | 25m33s | 10.244.166.178 | node1 |
+-----------------------------------+-----------+-------+---------+----------+--------+----------------+-------+
"""

获取api-resources

from kubernetes import client, config
from prettytable import PrettyTable

# 加载配置文件
config.load_kube_config(config_file="examples/k8s/admin.conf")
t = PrettyTable()
# 设置表头
t.field_names = ["name", "short_names", "api_version", "namespaced", "kind"]
# 设置左对其
t.align = "l"

# 创建v1的API对象
# 列出v1所有资源
api_instance = client.CoreV1Api()
for resource in api_instance.get_api_resources().resources:
    row = [resource.name, ",".join(resource.short_names) if resource.short_names else " ",
           api_instance.get_api_resources().group_version, resource.namespaced, resource.kind]
    t.add_row(row)

# 创建admissionregistration.k8s.io/v1的API对象
# 列出admissionregistration.k8s.io/v1所有资源
api_instance = client.AdmissionregistrationV1Api()
for resource in api_instance.get_api_resources().resources:
    row = [resource.name, ",".join(resource.short_names) if resource.short_names else " ",
           api_instance.get_api_resources().group_version, resource.namespaced, resource.kind]
    t.add_row(row)

    
# 创建apiextensions.k8s.io/v1的API对象
# 列出apiextensions.k8s.io/v1所有资源
api_instance = client.ApiextensionsV1Api()
for resource in api_instance.get_api_resources().resources:
    row = [resource.name, ",".join(resource.short_names) if resource.short_names else " ",
           api_instance.get_api_resources().group_version, resource.namespaced, resource.kind]
    t.add_row(row)
    

# 创建apiregistration.k8s.io/v1的API对象
# 列出apiregistration.k8s.io/v1所有资源
api_instance = client.ApiregistrationV1Api()
for resource in api_instance.get_api_resources().resources:
    row = [resource.name, ",".join(resource.short_names) if resource.short_names else " ",
           api_instance.get_api_resources().group_version, resource.namespaced, resource.kind]
    t.add_row(row)

    
# 创建apps/v1的API对象
# 列出apps/v1所有资源
api_instance = client.AppsV1Api()
for resource in api_instance.get_api_resources().resources:
    row = [resource.name, ",".join(resource.short_names) if resource.short_names else " ",
           api_instance.get_api_resources().group_version, resource.namespaced, resource.kind]
    t.add_row(row)

    
# 创建authentication.k8s.io/v1的API对象
# 列出authentication.k8s.io/v1所有资源
api_instance = client.AuthenticationV1Api()
for resource in api_instance.get_api_resources().resources:
    row = [resource.name, ",".join(resource.short_names) if resource.short_names else " ",
           api_instance.get_api_resources().group_version, resource.namespaced, resource.kind]
    t.add_row(row)

    
# 创建authorization.k8s.io/v1的API对象
# 列出authorization.k8s.io/v1所有资源
api_instance = client.AuthorizationV1Api()
for resource in api_instance.get_api_resources().resources:
    row = [resource.name, ",".join(resource.short_names) if resource.short_names else " ",
           api_instance.get_api_resources().group_version, resource.namespaced, resource.kind]
    t.add_row(row)

    
# 创建autoscaling/v2的API对象
# 列出autoscaling/v2所有资源
api_instance = client.AutoscalingV2Api()
for resource in api_instance.get_api_resources().resources:
    row = [resource.name, ",".join(resource.short_names) if resource.short_names else " ",
           api_instance.get_api_resources().group_version, resource.namespaced, resource.kind]
    t.add_row(row)

    
# 创建batch/v1的API对象
# 列出batch/v1所有资源
api_instance = client.BatchV1Api()
for resource in api_instance.get_api_resources().resources:
    row = [resource.name, ",".join(resource.short_names) if resource.short_names else " ",
           api_instance.get_api_resources().group_version, resource.namespaced, resource.kind]
    t.add_row(row)

    
    
# 创建certificates.k8s.io/v1的API对象
# 列出certificates.k8s.io/v1所有资源
api_instance = client.CertificatesV1Api()
for resource in api_instance.get_api_resources().resources:
    row = [resource.name, ",".join(resource.short_names) if resource.short_names else " ",
           api_instance.get_api_resources().group_version, resource.namespaced, resource.kind]
    t.add_row(row)

    
    
# 创建coordination.k8s.io/v1的API对象
# 列出coordination.k8s.io/v1所有资源
api_instance = client.CoordinationV1Api()
for resource in api_instance.get_api_resources().resources:
    row = [resource.name, ",".join(resource.short_names) if resource.short_names else " ",
           api_instance.get_api_resources().group_version, resource.namespaced, resource.kind]
    t.add_row(row)

    
    
# 创建discovery.k8s.io/v1的API对象
# 列出discovery.k8s.io/v1所有资源
api_instance = client.DiscoveryV1Api()
for resource in api_instance.get_api_resources().resources:
    row = [resource.name, ",".join(resource.short_names) if resource.short_names else " ",
           api_instance.get_api_resources().group_version, resource.namespaced, resource.kind]
    t.add_row(row)

    
    
# 创建events.k8s.io/v1的API对象
# 列出events.k8s.io/v1所有资源
api_instance = client.EventsV1Api()
for resource in api_instance.get_api_resources().resources:
    row = [resource.name, ",".join(resource.short_names) if resource.short_names else " ",
           api_instance.get_api_resources().group_version, resource.namespaced, resource.kind]
    t.add_row(row)

    
    
# 创建flowcontrol.apiserver.k8s.io/v1的API对象
# 列出flowcontrol.apiserver.k8s.io/v1所有资源
api_instance = client.FlowcontrolApiserverV1Api()
for resource in api_instance.get_api_resources().resources:
    row = [resource.name, ",".join(resource.short_names) if resource.short_names else " ",
           api_instance.get_api_resources().group_version, resource.namespaced, resource.kind]
    t.add_row(row)

    
    
# 创建networking.k8s.io/v1的API对象
# 列出networking.k8s.io/v1所有资源
api_instance = client.NetworkingV1Api()
for resource in api_instance.get_api_resources().resources:
    row = [resource.name, ",".join(resource.short_names) if resource.short_names else " ",
           api_instance.get_api_resources().group_version, resource.namespaced, resource.kind]
    t.add_row(row)

    
    
# 创建node.k8s.io/v1的API对象
# 列出node.k8s.io/v1所有资源
api_instance = client.NodeV1Api()
for resource in api_instance.get_api_resources().resources:
    row = [resource.name, ",".join(resource.short_names) if resource.short_names else " ",
           api_instance.get_api_resources().group_version, resource.namespaced, resource.kind]
    t.add_row(row)

    
    
# 创建policy/v1的API对象
# 列出policy/v1所有资源
api_instance = client.PolicyV1Api()
for resource in api_instance.get_api_resources().resources:
    row = [resource.name, ",".join(resource.short_names) if resource.short_names else " ",
           api_instance.get_api_resources().group_version, resource.namespaced, resource.kind]
    t.add_row(row)

    
    
# 创建rbac.authorization.k8s.io/v1的API对象
# 列出rbac.authorization.k8s.io/v1所有资源
api_instance = client.RbacAuthorizationV1Api()
for resource in api_instance.get_api_resources().resources:
    row = [resource.name, ",".join(resource.short_names) if resource.short_names else " ",
           api_instance.get_api_resources().group_version, resource.namespaced, resource.kind]
    t.add_row(row)

    
    
# 创建scheduling.k8s.io/v1的API对象
# 列出scheduling.k8s.io/v1所有资源
api_instance = client.SchedulingV1Api()
for resource in api_instance.get_api_resources().resources:
    row = [resource.name, ",".join(resource.short_names) if resource.short_names else " ",
           api_instance.get_api_resources().group_version, resource.namespaced, resource.kind]
    t.add_row(row)

    
# 创建storage.k8s.io/v1的API对象
# 列出storage.k8s.io/v1所有资源
api_instance = client.StorageV1Api()
for resource in api_instance.get_api_resources().resources:
    row = [resource.name, ",".join(resource.short_names) if resource.short_names else " ",
           api_instance.get_api_resources().group_version, resource.namespaced, resource.kind]
    t.add_row(row)
print(t)

"""
如命令行 kubectl api-resources 结果
+-------------------------------------+-------------+---------------------------------+------------+----------------------------------+
| name                                | short_names | api_version                     | namespaced | kind                             |
+-------------------------------------+-------------+---------------------------------+------------+----------------------------------+
| bindings                            |             | v1                              | True       | Binding                          |
| componentstatuses                   | cs          | v1                              | False      | ComponentStatus                  |
| configmaps                          | cm          | v1                              | True       | ConfigMap                        |
| endpoints                           | ep          | v1                              | True       | Endpoints                        |
| events                              | ev          | v1                              | True       | Event                            |
| limitranges                         | limits      | v1                              | True       | LimitRange                       |
| namespaces                          | ns          | v1                              | False      | Namespace                        |
| namespaces/finalize                 |             | v1                              | False      | Namespace                        |
| namespaces/status                   |             | v1                              | False      | Namespace                        |
| nodes                               | no          | v1                              | False      | Node                             |
| nodes/proxy                         |             | v1                              | False      | NodeProxyOptions                 |
| nodes/status                        |             | v1                              | False      | Node                             |
| persistentvolumeclaims              | pvc         | v1                              | True       | PersistentVolumeClaim            |
| persistentvolumeclaims/status       |             | v1                              | True       | PersistentVolumeClaim            |
| persistentvolumes                   | pv          | v1                              | False      | PersistentVolume                 |
| persistentvolumes/status            |             | v1                              | False      | PersistentVolume                 |
| pods                                | po          | v1                              | True       | Pod                              |
| pods/attach                         |             | v1                              | True       | PodAttachOptions                 |
| pods/binding                        |             | v1                              | True       | Binding                          |
| pods/ephemeralcontainers            |             | v1                              | True       | Pod                              |
| pods/eviction                       |             | v1                              | True       | Eviction                         |
| pods/exec                           |             | v1                              | True       | PodExecOptions                   |
| pods/log                            |             | v1                              | True       | Pod                              |
| pods/portforward                    |             | v1                              | True       | PodPortForwardOptions            |
| pods/proxy                          |             | v1                              | True       | PodProxyOptions                  |
| pods/status                         |             | v1                              | True       | Pod                              |
| podtemplates                        |             | v1                              | True       | PodTemplate                      |
| replicationcontrollers              | rc          | v1                              | True       | ReplicationController            |
| replicationcontrollers/scale        |             | v1                              | True       | Scale                            |
| replicationcontrollers/status       |             | v1                              | True       | ReplicationController            |
| resourcequotas                      | quota       | v1                              | True       | ResourceQuota                    |
| resourcequotas/status               |             | v1                              | True       | ResourceQuota                    |
| secrets                             |             | v1                              | True       | Secret                           |
| serviceaccounts                     | sa          | v1                              | True       | ServiceAccount                   |
| serviceaccounts/token               |             | v1                              | True       | TokenRequest                     |
| services                            | svc         | v1                              | True       | Service                          |
| services/proxy                      |             | v1                              | True       | ServiceProxyOptions              |
| services/status                     |             | v1                              | True       | Service                          |
| mutatingwebhookconfigurations       |             | admissionregistration.k8s.io/v1 | False      | MutatingWebhookConfiguration     |
| validatingadmissionpolicies         |             | admissionregistration.k8s.io/v1 | False      | ValidatingAdmissionPolicy        |
| validatingadmissionpolicies/status  |             | admissionregistration.k8s.io/v1 | False      | ValidatingAdmissionPolicy        |
| validatingadmissionpolicybindings   |             | admissionregistration.k8s.io/v1 | False      | ValidatingAdmissionPolicyBinding |
| validatingwebhookconfigurations     |             | admissionregistration.k8s.io/v1 | False      | ValidatingWebhookConfiguration   |
| customresourcedefinitions           | crd,crds    | apiextensions.k8s.io/v1         | False      | CustomResourceDefinition         |
| customresourcedefinitions/status    |             | apiextensions.k8s.io/v1         | False      | CustomResourceDefinition         |
| apiservices                         |             | apiregistration.k8s.io/v1       | False      | APIService                       |
| apiservices/status                  |             | apiregistration.k8s.io/v1       | False      | APIService                       |
| controllerrevisions                 |             | apps/v1                         | True       | ControllerRevision               |
| daemonsets                          | ds          | apps/v1                         | True       | DaemonSet                        |
| daemonsets/status                   |             | apps/v1                         | True       | DaemonSet                        |
| deployments                         | deploy      | apps/v1                         | True       | Deployment                       |
| deployments/scale                   |             | apps/v1                         | True       | Scale                            |
| deployments/status                  |             | apps/v1                         | True       | Deployment                       |
| replicasets                         | rs          | apps/v1                         | True       | ReplicaSet                       |
| replicasets/scale                   |             | apps/v1                         | True       | Scale                            |
| replicasets/status                  |             | apps/v1                         | True       | ReplicaSet                       |
| statefulsets                        | sts         | apps/v1                         | True       | StatefulSet                      |
| statefulsets/scale                  |             | apps/v1                         | True       | Scale                            |
| statefulsets/status                 |             | apps/v1                         | True       | StatefulSet                      |
| selfsubjectreviews                  |             | authentication.k8s.io/v1        | False      | SelfSubjectReview                |
| tokenreviews                        |             | authentication.k8s.io/v1        | False      | TokenReview                      |
| localsubjectaccessreviews           |             | authorization.k8s.io/v1         | True       | LocalSubjectAccessReview         |
| selfsubjectaccessreviews            |             | authorization.k8s.io/v1         | False      | SelfSubjectAccessReview          |
| selfsubjectrulesreviews             |             | authorization.k8s.io/v1         | False      | SelfSubjectRulesReview           |
| subjectaccessreviews                |             | authorization.k8s.io/v1         | False      | SubjectAccessReview              |
| horizontalpodautoscalers            | hpa         | autoscaling/v2                  | True       | HorizontalPodAutoscaler          |
| horizontalpodautoscalers/status     |             | autoscaling/v2                  | True       | HorizontalPodAutoscaler          |
| cronjobs                            | cj          | batch/v1                        | True       | CronJob                          |
| cronjobs/status                     |             | batch/v1                        | True       | CronJob                          |
| jobs                                |             | batch/v1                        | True       | Job                              |
| jobs/status                         |             | batch/v1                        | True       | Job                              |
| certificatesigningrequests          | csr         | certificates.k8s.io/v1          | False      | CertificateSigningRequest        |
| certificatesigningrequests/approval |             | certificates.k8s.io/v1          | False      | CertificateSigningRequest        |
| certificatesigningrequests/status   |             | certificates.k8s.io/v1          | False      | CertificateSigningRequest        |
| leases                              |             | coordination.k8s.io/v1          | True       | Lease                            |
| endpointslices                      |             | discovery.k8s.io/v1             | True       | EndpointSlice                    |
| events                              | ev          | events.k8s.io/v1                | True       | Event                            |
| flowschemas                         |             | flowcontrol.apiserver.k8s.io/v1 | False      | FlowSchema                       |
| flowschemas/status                  |             | flowcontrol.apiserver.k8s.io/v1 | False      | FlowSchema                       |
| prioritylevelconfigurations         |             | flowcontrol.apiserver.k8s.io/v1 | False      | PriorityLevelConfiguration       |
| prioritylevelconfigurations/status  |             | flowcontrol.apiserver.k8s.io/v1 | False      | PriorityLevelConfiguration       |
| ingressclasses                      |             | networking.k8s.io/v1            | False      | IngressClass                     |
| ingresses                           | ing         | networking.k8s.io/v1            | True       | Ingress                          |
| ingresses/status                    |             | networking.k8s.io/v1            | True       | Ingress                          |
| networkpolicies                     | netpol      | networking.k8s.io/v1            | True       | NetworkPolicy                    |
| runtimeclasses                      |             | node.k8s.io/v1                  | False      | RuntimeClass                     |
| poddisruptionbudgets                | pdb         | policy/v1                       | True       | PodDisruptionBudget              |
| poddisruptionbudgets/status         |             | policy/v1                       | True       | PodDisruptionBudget              |
| clusterrolebindings                 |             | rbac.authorization.k8s.io/v1    | False      | ClusterRoleBinding               |
| clusterroles                        |             | rbac.authorization.k8s.io/v1    | False      | ClusterRole                      |
| rolebindings                        |             | rbac.authorization.k8s.io/v1    | True       | RoleBinding                      |
| roles                               |             | rbac.authorization.k8s.io/v1    | True       | Role                             |
| priorityclasses                     | pc          | scheduling.k8s.io/v1            | False      | PriorityClass                    |
| csidrivers                          |             | storage.k8s.io/v1               | False      | CSIDriver                        |
| csinodes                            |             | storage.k8s.io/v1               | False      | CSINode                          |
| csistoragecapacities                |             | storage.k8s.io/v1               | True       | CSIStorageCapacity               |
| storageclasses                      | sc          | storage.k8s.io/v1               | False      | StorageClass                     |
| volumeattachments                   |             | storage.k8s.io/v1               | False      | VolumeAttachment                 |
| volumeattachments/status            |             | storage.k8s.io/v1               | False      | VolumeAttachment                 |
+-------------------------------------+-------------+---------------------------------+------------+----------------------------------+
"""

获取deploy相关信息

from kubernetes import client, config
from prettytable import PrettyTable
from common.k8s_format import get_age

# 加载配置文件
config.load_kube_config(config_file="examples/k8s/admin.conf")

# 创建API对象
api_instance = client.AppsV1Api()

# 获取所有Deployment
table = PrettyTable()
table.align = "l"
table.field_names = ["NAMESPACE", "NAME", "READY", "UP-TO-DATE", "AVAILABLE", "AGE", "CONTAINERS",
                     "SELECTOR"]
table.title = "所有名称空间下的Deployment"

deploy_list = api_instance.list_deployment_for_all_namespaces()
for deploy in deploy_list.items:
    containers = []
    for container in deploy.spec.template.spec.containers:
        containers.append(container.name)
    if len(containers) == 1:
        containers = containers[0]
    selector = None
    if deploy.spec.selector.match_labels:
        selector = deploy.spec.selector.match_labels
    else:
        selector = deploy.spec.selector.match_expressions
    table.add_row([deploy.metadata.namespace, deploy.metadata.name,
                   f"{deploy.status.ready_replicas}/{deploy.status.replicas}",
                   deploy.status.updated_replicas, deploy.status.available_replicas,
                   get_age(deploy.metadata.creation_timestamp),
                   containers if containers else "<none>",
                   selector if selector else "<none>"])
print(table)

"""
+----------------------------------------------------------------------------------------------------------------------------------------------------+
|                                                             所有名称空间下的Deployment                                                              |
+-------------+-------------------------+-------+------------+-----------+--------+-------------------------+----------------------------------------+
| NAMESPACE   | NAME                    | READY | UP-TO-DATE | AVAILABLE | AGE    | CONTAINERS              | SELECTOR                               |
+-------------+-------------------------+-------+------------+-----------+--------+-------------------------+----------------------------------------+
| default     | nginx-deployment        | 3/3   | 3          | 3         | 30m12s | nginx-http              | {'app': 'http-server'}                 |
| kube-system | calico-kube-controllers | 1/1   | 1          | 1         | 18d23h | calico-kube-controllers | {'k8s-app': 'calico-kube-controllers'} |
| kube-system | coredns                 | 2/2   | 2          | 2         | 19d0h  | coredns                 | {'k8s-app': 'kube-dns'}                |
+-------------+-------------------------+-------+------------+-----------+--------+-------------------------+----------------------------------------+
"""

# 获取指定命名空间下的Deployment
namespace = "default"
table = PrettyTable()
table.align = "l"
table.field_names = ["NAMESPACE", "NAME", "READY", "UP-TO-DATE", "AVAILABLE", "AGE", "CONTAINERS",
                     "SELECTOR"]
table.title = f"{namespace}名称空间下的Deployment"
deploy_list = api_instance.list_namespaced_deployment(namespace=namespace)
for deploy in deploy_list.items:
    containers = []
    for container in deploy.spec.template.spec.containers:
        containers.append(container.name)
    if len(containers) == 1:
        containers = containers[0]
    selector = None
    if deploy.spec.selector.match_labels:
        selector = deploy.spec.selector.match_labels
    else:
        selector = deploy.spec.selector.match_expressions
    table.add_row([deploy.metadata.namespace, deploy.metadata.name,
                   f"{deploy.status.ready_replicas}/{deploy.status.replicas}",
                   deploy.status.updated_replicas, deploy.status.available_replicas,
                   get_age(deploy.metadata.creation_timestamp),
                   containers if containers else "<none>",
                   selector if selector else "<none>"])
print(table)

"""
+--------------------------------------------------------------------------------------------------------------+
|                                        default名称空间下的Deployment                                         |
+-----------+------------------+-------+------------+-----------+--------+------------+------------------------+
| NAMESPACE | NAME             | READY | UP-TO-DATE | AVAILABLE | AGE    | CONTAINERS | SELECTOR               |
+-----------+------------------+-------+------------+-----------+--------+------------+------------------------+
| default   | nginx-deployment | 3/3   | 3          | 3         | 33m59s | nginx-http | {'app': 'http-server'} |
+-----------+------------------+-------+------------+-----------+--------+------------+------------------------+
"""



# 获取指定deploy的相关信息
name = "nginx-deployment"
namespace = "default"
table = PrettyTable()
table.align = "l"
table.field_names = ["NAMESPACE", "NAME", "READY", "UP-TO-DATE", "AVAILABLE", "AGE", "CONTAINERS",
                     "SELECTOR"]
deploy = api_instance.read_namespaced_deployment(name=name, namespace=namespace)
containers = []
for container in deploy.spec.template.spec.containers:
    containers.append(container.name)
if len(containers) == 1:
    containers = containers[0]
selector = None
if deploy.spec.selector.match_labels:
    selector = deploy.spec.selector.match_labels
else:
    selector = deploy.spec.selector.match_expressions
table.add_row([deploy.metadata.namespace, deploy.metadata.name,
               f"{deploy.status.ready_replicas}/{deploy.status.replicas}",
               deploy.status.updated_replicas, deploy.status.available_replicas,
               get_age(deploy.metadata.creation_timestamp),
               containers if containers else "<none>",
               selector if selector else "<none>"])
print(table)

"""
+-----------+------------------+-------+------------+-----------+--------+------------+------------------------+
| NAMESPACE | NAME             | READY | UP-TO-DATE | AVAILABLE | AGE    | CONTAINERS | SELECTOR               |
+-----------+------------------+-------+------------+-----------+--------+------------+------------------------+
| default   | nginx-deployment | 3/3   | 3          | 3         | 35m21s | nginx-http | {'app': 'http-server'} |
+-----------+------------------+-------+------------+-----------+--------+------------+------------------------+
"""

获取service的相关信息

from kubernetes import client, config
from prettytable import PrettyTable

from common.k8s_format import get_age

# 加载配置文件
config.load_kube_config(config_file="examples/k8s/admin.conf")

# 创建API对象
api_instance = client.CoreV1Api()
table = PrettyTable()
table.align = "l"
table.field_names = ["NAMESPACE", "NAME", "TYPE", "CLUSTER-IP", "EXTERNAL-IP", "PORT(S)", "AGE",
                     "SELECTOR"]
table.title = "所有名称空间下的Service"
svc_list = api_instance.list_service_for_all_namespaces()
for svc in svc_list.items:
    table.add_row([svc.metadata.namespace, svc.metadata.name, svc.spec.type,
                   ",".join(svc.spec.cluster_i_ps),
                   ",".join(svc.spec.external_i_ps) if svc.spec.external_i_ps else "<none>",
                   ",".join(map(lambda x: str(x.port) + "/" + x.protocol, svc.spec.ports)),
                   get_age(svc.metadata.creation_timestamp),
                   svc.spec.selector if svc.spec.selector else "<none>"])
print(table)
"""
+----------------------------------------------------------------------------------------------------------------------------+
|                                                  所有名称空间下的Service                                                    |
+-------------+------------+-----------+------------+-------------+------------------------+-------+-------------------------+
| NAMESPACE   | NAME       | TYPE      | CLUSTER-IP | EXTERNAL-IP | PORT(S)                | AGE   | SELECTOR                |
+-------------+------------+-----------+------------+-------------+------------------------+-------+-------------------------+
| default     | kubernetes | ClusterIP | 10.96.0.1  | <none>      | 443/TCP                | 19d0h | <none>                  |
| kube-system | kube-dns   | ClusterIP | 10.96.0.10 | <none>      | 53/UDP,53/TCP,9153/TCP | 19d0h | {'k8s-app': 'kube-dns'} |
+-------------+------------+-----------+------------+-------------+------------------------+-------+-------------------------+
"""

# 获取指定名称空间下的所有service
table = PrettyTable()
table.align = "l"
table.field_names = ["NAMESPACE", "NAME", "TYPE", "CLUSTER-IP", "EXTERNAL-IP", "PORT(S)", "AGE",
                     "SELECTOR"]
namespace = "default"
table.title = f"{namespace}名称空间下的Service"
svc_list = api_instance.list_namespaced_service(namespace=namespace)
for svc in svc_list.items:
    table.add_row([svc.metadata.namespace, svc.metadata.name, svc.spec.type,
                   ",".join(svc.spec.cluster_i_ps),
                   ",".join(svc.spec.external_i_ps) if svc.spec.external_i_ps else "<none>",
                   ",".join(map(lambda x: str(x.port) + "/" + x.protocol, svc.spec.ports)),
                   get_age(svc.metadata.creation_timestamp),
                   svc.spec.selector if svc.spec.selector else "<none>"])
print(table)

"""
+--------------------------------------------------------------------------------------------+
|                                 default名称空间下的Service                                  |
+-----------+------------+-----------+------------+-------------+---------+-------+----------+
| NAMESPACE | NAME       | TYPE      | CLUSTER-IP | EXTERNAL-IP | PORT(S) | AGE   | SELECTOR |
+-----------+------------+-----------+------------+-------------+---------+-------+----------+
| default   | kubernetes | ClusterIP | 10.96.0.1  | <none>      | 443/TCP | 19d0h | <none>   |
+-----------+------------+-----------+------------+-------------+---------+-------+----------+
"""


# 获取指定service的信息
table = PrettyTable()
table.align = "l"
table.field_names = ["NAMESPACE", "NAME", "TYPE", "CLUSTER-IP", "EXTERNAL-IP", "PORT(S)", "AGE",
                     "SELECTOR"]
namespace = "default"
name="kubernetes"
svc = api_instance.read_namespaced_service(name=name, namespace=namespace)
table.add_row([svc.metadata.namespace, svc.metadata.name, svc.spec.type,
               ",".join(svc.spec.cluster_i_ps),
               ",".join(svc.spec.external_i_ps) if svc.spec.external_i_ps else "<none>",
               ",".join(map(lambda x: str(x.port) + "/" + x.protocol, svc.spec.ports)),
               get_age(svc.metadata.creation_timestamp),
               svc.spec.selector if svc.spec.selector else "<none>"])
print(table)
"""
+-----------+------------+-----------+------------+-------------+---------+-------+----------+
| NAMESPACE | NAME       | TYPE      | CLUSTER-IP | EXTERNAL-IP | PORT(S) | AGE   | SELECTOR |
+-----------+------------+-----------+------------+-------------+---------+-------+----------+
| default   | kubernetes | ClusterIP | 10.96.0.1  | <none>      | 443/TCP | 19d0h | <none>   |
+-----------+------------+-----------+------------+-------------+---------+-------+----------+
"""

创建资源

大概分两类:

  1. 不需要指定什么类型的资源,根据给出的资源清单创建文件
  2. 创建什么资源就用什么特定的接口

通过yaml文件创建

yaml文件

# nginx.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: http-server
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: http-server
    spec:
      containers:
      - name: nginx-http
        image: nginx:latest
        imagePullPolicy: IfNotPresent
        ports:
        - protocol: TCP
          containerPort: 80

创建

from kubernetes import client, config, utils

# 加载配置文件
config.load_kube_config(config_file="examples/k8s/admin.conf")

k8s_client = client.ApiClient()
utils.create_from_yaml(k8s_client, "examples/k8s/nginx/nginx.yaml",verbose=True)

通过文件夹创建资源

from kubernetes import client, config, utils

# 加载配置文件
config.load_kube_config(config_file="examples/k8s/admin.conf")

k8s_client = client.ApiClient()
utils.create_from_directory(k8s_client, yaml_dir="examples/k8s/nginx", verbose=True)

通过字典创建资源

from kubernetes import client, config, utils

# 加载配置文件
config.load_kube_config(config_file="examples/k8s/admin.conf")

k8s_client = client.ApiClient()
data = {
    'apiVersion': 'apps/v1',
    'kind'      : 'Deployment',
    'metadata'  : { 'name': 'nginx-deployment' },
    'spec'      : {
        'replicas': 3,
        'selector': {
            'matchLabels': { 'app': 'http-server' }
        },
        'strategy': { 'type': 'Recreate' },
        'template': {
            'metadata': {
                'labels': {
                    'app': 'http-server'
                }
            },
            'spec'    : {
                'containers': [
                    {
                        'name'           : 'nginx-http',
                        'image'          : 'nginx:latest',
                        'imagePullPolicy': 'IfNotPresent',
                        'ports'          : [
                            {
                                'protocol'     : 'TCP',
                                'containerPort': 80
                            }
                        ]
                    }
                ]
            }
        }
    }
}
utils.create_from_dict(k8s_client, data=data, verbose=True)

通过专门的接口来创建资源

这里以 创建deploy举例

from kubernetes import client, config, utils
from kubernetes.client import exceptions
import yaml

# 加载配置文件
config.load_kube_config(config_file="examples/k8s/admin.conf")

api_instance = client.AppsV1Api()
with open("examples/k8s/nginx/nginx.yaml") as f:
    nginx = yaml.safe_load(f)
try:
    res = api_instance.create_namespaced_deployment(namespace="default", body=nginx)
    print(res)
except exceptions.ApiException as e:
    print("状态码:", e.status)
    print("错误信息:", e.body)

以上基本都是通过读取yaml文件或者类似的资源清单来创建的

其实也可以通过接口一步步新建一个资源,只是比较复杂而已

通过接口创建资源

from kubernetes import client, config


# 加载配置文件
config.load_kube_config(config_file="examples/k8s/admin.conf")
DEPLOYMENT_NAME = "nginx-deployment"

# 配置Pod容器
container = client.V1Container(
        name="nginx",
        image="nginx:latest",
        ports=[client.V1ContainerPort(container_port=80)],
        resources=client.V1ResourceRequirements(
                requests={ "cpu": "100m", "memory": "200Mi" },
                limits={ "cpu": "500m", "memory": "500Mi" },
        ),
)
# 创建容器模板
template = client.V1PodTemplateSpec(
        metadata=client.V1ObjectMeta(labels={ "app": "nginx" }),
        spec=client.V1PodSpec(containers=[container]),
)
# 创建spec
spec = client.V1DeploymentSpec(
        replicas=3, template=template, selector={
            "matchLabels":
                { "app": "nginx" } })
# 创建deploy对象
deployment = client.V1Deployment(
        api_version="apps/v1",
        kind="Deployment",
        metadata=client.V1ObjectMeta(name=DEPLOYMENT_NAME),
        spec=spec,
)
api = client.AppsV1Api()
# 运行部署
resp = api.create_namespaced_deployment(
        body=deployment, namespace="default"
)
# 响应
print("\n[INFO] deployment `nginx-deployment` created.\n")
print("%s\t%s\t\t\t%s\t%s" % ("NAMESPACE", "NAME", "REVISION", "IMAGE"))
print(
        "%s\t\t%s\t%s\t\t%s\n"
        % (
            resp.metadata.namespace,
            resp.metadata.name,
            resp.metadata.generation,
            resp.spec.template.spec.containers[0].image,
        )
)

对资源的CRUD

这里以deployment为例

创建

from kubernetes import client, config
import yaml
from kubernetes.client import exceptions

# 加载配置文件
config.load_kube_config(config_file="examples/k8s/admin.conf")

api_instance = client.AppsV1Api()
with open("examples/k8s/nginx/nginx.yaml") as f:
    nginx = yaml.safe_load(f)
try:
    res = api_instance.create_namespaced_deployment(body=nginx)
    print(res)
except exceptions.ApiException as e:
    print("状态码:", e.status)
    print("错误信息:", e.body)

删除

from kubernetes import client, config

# 加载配置文件
config.load_kube_config(config_file="examples/k8s/admin.conf")

name = "nginx-deployment"
namespace = "default"
api_instance = client.AppsV1Api()
res = api_instance.delete_namespaced_deployment(namespace=ns, name=deploy_name)
print(res)

查询

from kubernetes import client, config

# 加载配置文件
config.load_kube_config(config_file="examples/k8s/admin.conf")

name = "nginx-deployment"
namespace = "default"
api_instance = client.AppsV1Api()
res = api_instance.read_namespaced_deployment(namespace=ns, name=deploy_name)
print(res)

修改

from kubernetes import client, config

# 加载配置文件
config.load_kube_config(config_file="examples/k8s/admin.conf")

# 先查找
name = "nginx-deployment"
namespace = "default"
api_instance = client.AppsV1Api()
deploy = api_instance.read_namespaced_deployment(namespace=namespace, name=name)

# 再修改
deploy.spec.replicas = 1
res = api_instance.patch_namespaced_deployment(
        namespace=deploy.metadata.namespace,
        name=deploy.metadata.name,
        body=deploy
)
print(res)

重启deploy

from kubernetes import client, config
import datetime
import pytz

# 加载配置文件
config.load_kube_config(config_file="examples/k8s/admin.conf")

# 先查找
name = "nginx-deployment"
namespace = "default"
api_instance = client.AppsV1Api()
deploy = api_instance.read_namespaced_deployment(namespace=namespace, name=name)

# 再重启
# update `spec.template.metadata` section
# to add `kubectl.kubernetes.io/restartedAt` annotation
deploy.spec.template.metadata.annotations = {
    "kubectl.kubernetes.io/restartedAt": datetime.datetime.now(tz=pytz.UTC)
    .isoformat()
}
api_instance = client.AppsV1Api()
# patch the deployment
resp = api_instance.patch_namespaced_deployment(
        name=name, namespace=namespace, body=deploy
)
print("\n[INFO] deployment `nginx-deployment` restarted.\n")
print("%s\t\t\t%s\t%s" % ("NAME", "REVISION", "RESTARTED-AT"))
print(
        "%s\t%s\t\t%s\n"
        % (
            resp.metadata.name,
            resp.metadata.generation,
            resp.spec.template.metadata.annotations,
        )
)
posted @ 2024-06-18 16:03  厚礼蝎  阅读(514)  评论(0编辑  收藏  举报