kubectl 常用操作

本文先理清 kubectl 操作资源对象的三种方式及其背后的差异(命令式与声明式、replaceapply),再按使用场景汇总常用命令示例:查看集群与 API 信息、资源对象的增删查改、查看日志、进入容器执行命令以及统计资源占用。

1. kubectl 的三种操作方式

kubectl 的核心功能在于通过 API Server 操作 Kubernetes 的各种资源对象,操作方式有三种:直接命令、命令式对象配置、声明式对象配置。

直接命令

直接通过 kubectl 命令及相关的选项创建资源对象的方式,即为直接命令式操作:

1
2
3
4
5
6
7
# 创建名为nginx-deploy的Deployment控制器资源对象
[root@k8s01 ~]# kubectl run nginx-deploy --image=nginx:1.12 --replicas=2
Flag --replicas has been deprecated, has no effect and will be removed in the future.
# --replicas 已不支持直接命令式操作

# 创建名为nginx-svc的Service资源对象
[root@k8s01 ~]# kubectl expose deployment/nginx --name=nginx-svc --port=80

命令式对象配置

也可以根据资源清单创建资源对象,即命令式对象配置文件。假设存在定义了 Deployment 对象的 nginx-deploy.yaml 文件,和定义了 Service 对象的 nginx-svc.yaml 文件:

1
kubectl create -f nginx-deploy.yaml -f nginx-svc.yaml

声明式对象配置

还可以把怎么改交由 kubectl 自行确定,用户只需要声明期望的状态,即为声明式对象配置:

1
kubectl apply -f nginx-deploy.yaml -f nginx-svc.yaml

replace 与 apply 的区别

可以简单地理解为,kubectl replace 的执行过程,是使用新的 YAML 文件中的 API 对象,替换原有的 API 对象;而 kubectl apply,则是执行了一个对原有 API 对象的 PATCH 操作。

kube-apiserver 在响应命令式请求(比如 kubectl replace)的时候,一次只能处理一个写请求,否则会有产生冲突的可能。而对于声明式请求(比如 kubectl apply),一次能处理多个写操作,并且具备 Merge 能力。

声明式 API 的价值:以 Istio 的 sidecar 注入为例

上面所说的 Merge 能力并不只是省事,它是很多扩展能力的前提。

istio

Istio 是一个基于 Kubernetes 项目的微服务治理框架,它的架构非常清晰。Istio 最根本的组件,是运行在每一个应用 Pod 里的 Envoy 容器(高性能 C++ 网络代理)。Istio 项目的核心,就是由无数个运行在应用 Pod 中的 Envoy 容器组成的服务代理网格。

Istio 项目把这个代理服务以 sidecar 容器的方式,运行在了每一个被治理的应用 Pod 中。Pod 里的所有容器都共享同一个 Network Namespace,所以 Envoy 容器就能够通过配置 Pod 里的 iptables 规则,把整个 Pod 的进出流量接管下来。这样,Istio 的控制层(Control Plane)里的 Pilot 组件,就能够通过调用每个 Envoy 容器的 API,对这个 Envoy 代理进行配置,从而实现微服务治理。

假设架构图左边的 Pod 是已经在运行的应用,而右边的 Pod 则是刚刚上线的应用的新版本。这时候,Pilot 通过调节这两个 Pod 里 Envoy 容器的配置,从而将 90% 的流量分配给旧版本的应用,将 10% 的流量分配给新版本应用,并且还可以在后续的过程中随时调整。这样,一个典型的「灰度发布」的场景就完成了。比如 Istio 可以调节这个流量从 90%-10% 改到 80%-20%,再到 50%-50%,最后到 0%-100%,就完成了这个灰度发布的过程。

Istio 项目使用的,是 Kubernetes 中的一个非常重要的功能,叫作 Dynamic Admission Control(也叫做 Initializer)。

用户提交的原始 pod.yaml 里并没有 Envoy:

1
2
3
4
5
6
7
8
9
10
11
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
spec:
containers:
- name: myapp-container
image: busybox
command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 3600']

注入 envoy 容器后变成:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
spec:
containers:
- name: myapp-container
image: busybox
command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 3600']
- name: envoy
image: lyft/envoy:845747b88f102c0fd262ab234308e9e22f693a1
command: ["/usr/local/bin/envoy"]
# ...(其余字段省略)

Istio 要做的,就是编写一个用来为 Pod 自动注入 Envoy 容器的 InitializerInitializer 要做的工作,就是把这部分 Envoy 相关的字段,自动添加到用户提交的 PodAPI 对象里。可是用户提交的 Pod 里本来就有 containers 字段和 volumes 字段,所以 Kubernetes 在处理这样的更新请求时,就必须使用类似于 git merge 这样的操作,才能将这两部分内容合并在一起,而这正是声明式 API 最主要的能力。

2. 常用命令示例

获取集群相关信息

1
2
3
4
5
6
7
8
9
10
11
12
13
# 显示的是当前使用的客户端及服务端程序版本信息
[root@centos01 ~]# kubectl version --short=true
Client Version: v1.18.6
Server Version: v1.18.0

# 显示集群信息
[root@centos01 ~]# kubectl cluster-info
Kubernetes master is running at https://192.168.43.25:6443
KubeDNS is running at https://192.168.43.25:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

[root@centos01 ~]# kubectl cluster-info dump > ./k8s.log

查看 API 资源与版本

kubectl api-resources 列出当前集群支持的资源类型、简称与所属 API 组,kubectl api-versions 只列出 API 组与版本,写资源清单时用它确认 apiVersion 该怎么填。

⚠️ 注:以下为约 k8s 1.20 集群的 api-resources/api-versions 快照,其中大量 *beta* 版本已在新版中被移除或转正,常见对应关系:batch/v1beta1(CronJob)→ batch/v1(1.25 移除 beta);rbac.authorization.k8s.io/v1beta1rbac.authorization.k8s.io/v1(1.22 移除);extensions/v1beta1networking.k8s.io/v1beta1(Ingress)→ networking.k8s.io/v1(1.22 移除);policy/v1beta1policy/v1,其中 PodSecurityPolicy 已于 1.25 整体移除;autoscaling/v2beta1autoscaling/v2beta2autoscaling/v2discovery.k8s.io/v1beta1discovery.k8s.io/v1

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
124
125
126
127
[root@k8s01 ~]# kubectl api-resources
NAME SHORTNAMES APIVERSION 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
nodes no v1 false Node
persistentvolumeclaims pvc v1 true PersistentVolumeClaim
persistentvolumes pv v1 false PersistentVolume
pods po v1 true Pod
podtemplates v1 true PodTemplate
replicationcontrollers rc v1 true ReplicationController
resourcequotas quota v1 true ResourceQuota
secrets v1 true Secret
serviceaccounts sa v1 true ServiceAccount
services svc v1 true Service
mutatingwebhookconfigurations admissionregistration.k8s.io/v1 false MutatingWebhookConfiguration
validatingwebhookconfigurations admissionregistration.k8s.io/v1 false ValidatingWebhookConfiguration
customresourcedefinitions crd,crds apiextensions.k8s.io/v1 false CustomResourceDefinition
apiservices apiregistration.k8s.io/v1 false APIService
controllerrevisions apps/v1 true ControllerRevision
daemonsets ds apps/v1 true DaemonSet
deployments deploy apps/v1 true Deployment
replicasets rs apps/v1 true ReplicaSet
statefulsets sts apps/v1 true StatefulSet
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/v1 true HorizontalPodAutoscaler
cronjobs cj batch/v1beta1 true CronJob
jobs batch/v1 true Job
certificatesigningrequests csr certificates.k8s.io/v1 false CertificateSigningRequest
leases coordination.k8s.io/v1 true Lease
bgpconfigurations crd.projectcalico.org/v1 false BGPConfiguration
bgppeers crd.projectcalico.org/v1 false BGPPeer
blockaffinities crd.projectcalico.org/v1 false BlockAffinity
clusterinformations crd.projectcalico.org/v1 false ClusterInformation
felixconfigurations crd.projectcalico.org/v1 false FelixConfiguration
globalnetworkpolicies gnp crd.projectcalico.org/v1 false GlobalNetworkPolicy
globalnetworksets crd.projectcalico.org/v1 false GlobalNetworkSet
hostendpoints crd.projectcalico.org/v1 false HostEndpoint
ipamblocks crd.projectcalico.org/v1 false IPAMBlock
ipamconfigs crd.projectcalico.org/v1 false IPAMConfig
ipamhandles crd.projectcalico.org/v1 false IPAMHandle
ippools crd.projectcalico.org/v1 false IPPool
kubecontrollersconfigurations crd.projectcalico.org/v1 false KubeControllersConfiguration
networkpolicies crd.projectcalico.org/v1 true NetworkPolicy
networksets crd.projectcalico.org/v1 true NetworkSet
endpointslices discovery.k8s.io/v1beta1 true EndpointSlice
events ev events.k8s.io/v1 true Event
ingresses ing extensions/v1beta1 true Ingress
flowschemas flowcontrol.apiserver.k8s.io/v1beta1 false FlowSchema
prioritylevelconfigurations flowcontrol.apiserver.k8s.io/v1beta1 false PriorityLevelConfiguration
nodes metrics.k8s.io/v1beta1 false NodeMetrics
pods metrics.k8s.io/v1beta1 true PodMetrics
alertmanagerconfigs monitoring.coreos.com/v1alpha1 true AlertmanagerConfig
alertmanagers monitoring.coreos.com/v1 true Alertmanager
podmonitors monitoring.coreos.com/v1 true PodMonitor
probes monitoring.coreos.com/v1 true Probe
prometheuses monitoring.coreos.com/v1 true Prometheus
prometheusrules monitoring.coreos.com/v1 true PrometheusRule
servicemonitors monitoring.coreos.com/v1 true ServiceMonitor
thanosrulers monitoring.coreos.com/v1 true ThanosRuler
ingressclasses networking.k8s.io/v1 false IngressClass
ingresses ing networking.k8s.io/v1 true Ingress
networkpolicies netpol networking.k8s.io/v1 true NetworkPolicy
runtimeclasses node.k8s.io/v1 false RuntimeClass
poddisruptionbudgets pdb policy/v1beta1 true PodDisruptionBudget
podsecuritypolicies psp policy/v1beta1 false PodSecurityPolicy
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
storageclasses sc storage.k8s.io/v1 false StorageClass
volumeattachments storage.k8s.io/v1 false VolumeAttachment


[root@k8s01 ~]# kubectl api-versions
admissionregistration.k8s.io/v1
admissionregistration.k8s.io/v1beta1
apiextensions.k8s.io/v1
apiextensions.k8s.io/v1beta1
apiregistration.k8s.io/v1
apiregistration.k8s.io/v1beta1
apps/v1
authentication.k8s.io/v1
authentication.k8s.io/v1beta1
authorization.k8s.io/v1
authorization.k8s.io/v1beta1
autoscaling/v1
autoscaling/v2beta1
autoscaling/v2beta2
batch/v1
batch/v1beta1
certificates.k8s.io/v1
certificates.k8s.io/v1beta1
coordination.k8s.io/v1
coordination.k8s.io/v1beta1
crd.projectcalico.org/v1
discovery.k8s.io/v1beta1
events.k8s.io/v1
events.k8s.io/v1beta1
extensions/v1beta1
flowcontrol.apiserver.k8s.io/v1beta1
metrics.k8s.io/v1beta1
monitoring.coreos.com/v1
monitoring.coreos.com/v1alpha1
networking.k8s.io/v1
networking.k8s.io/v1beta1
node.k8s.io/v1
node.k8s.io/v1beta1
policy/v1beta1
rbac.authorization.k8s.io/v1
rbac.authorization.k8s.io/v1beta1
scheduling.k8s.io/v1
scheduling.k8s.io/v1beta1
storage.k8s.io/v1
storage.k8s.io/v1beta1
v1

创建资源对象

创建资源对象常用四个子命令,分别对应上面讲过的三种操作方式:kubectl runkubectl expose 属于直接命令,kubectl create 为命令式对象配置,kubectl apply 为声明式对象配置。

直接命令还可以顺手指定 Service 类型:

1
kubectl expose pod httpd-app --type='NodePort' --port 80

不确定要不要真的执行、或者想拿一份清单模板时,加上 --dry-run=client

1
2
3
4
5
6
7
8
9
10
11
12
[root@k8s01 storage]#  kubectl run myapp --image=nginx:1.7.9 --port=80 --dry-run=client  # 并未真正执行
pod/myapp created (dry run)

[root@k8s01 test]# kubectl create ns demo --dry-run=client -o yaml > demo-ns.yaml # 生成模板文件
[root@k8s01 test]# cat demo-ns.yaml
apiVersion: v1
kind: Namespace
metadata:
creationTimestamp: null
name: demo
spec: {}
status: {}

查看资源对象

kubectl get 可分类列出资源对象及其相关的状态信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 列出系统上所有的Namespace资源对象
[root@k8s01 ~]# kubectl get namespaces
NAME STATUS AGE
default Active 20m
kube-node-lease Active 20m
kube-public Active 20m
kube-system Active 20m


# 列出默认名称空间内的所有Pod和Service对象,并输出额外信息
[root@k8s01 ~]# kubectl get pods,services -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/nginx-deploy 1/1 Running 0 8m49s 172.18.236.129 k8s02 <none> <none>

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 30m <none>
service/nginx-svc ClusterIP 10.100.63.22 <none> 80/TCP 2m11s run=nginx-deploy

# 获取含有标签 app=nginx 的 pod name
kubectl get pod -l app=nginx -o jsonpath={.items..metadata.name}

上面拿到的 Pod IP 与 ClusterIP,在 k8s 集群上任一节点均可访问:

1
curl 172.18.236.129 && curl  10.100.63.22

日常用得最多的还是各类资源的简写查询:

1
2
3
4
5
6
7
kubectl get deployments
kubectl get svc
kubectl get rs
kubectl get pod
kubectl get node
kubectl get cm
kubectl get secret

Pod 较多时可以按时间排序,方便找出最近重建的实例:

1
2
kubectl get pod --sort-by=.status.startTime
kubectl get pod --sort-by=.metadata.creationTimestamp

打印资源对象的详细信息

每个资源对象都包含着用户期望的状态(Spec)和现有的实际状态(Status)两种状态信息,kubectl get -o {yaml|json}kubectl describe 命令都能够打印出指定资源对象的详细描述信息。

1
2
3
4
5
# 查看kube-system名称空间中拥有标签component=kube-apiserver的Pod对象的资源配置清单(期望的状态)及当前的状态信息,并输出为yaml格式
kubectl get pods -l component=kube-apiserver -o yaml -n kube-system

# 查看kube-system名称空间中拥有标签component=kube-apiserver的Pod对象的详细描述信息
kubectl describe pods -l component=kube-apiserver -n kube-system

打印容器中的日志信息

通常一个容器中仅会运行一个进程(及其子进程),此进程作为 PID 为 1 的进程接收并处理管理信息,同时将日志直接输出至终端中,而无须再像传统的多进程系统环境那样将日志保存于文件中,因此容器日志信息的获取一般要到其控制台上进行。

kubectl logs 命令可打印 Pod 对象内指定容器的日志信息,命令格式为 kubectl logs [-f] [-p] (POD|TYPE/NAME) [-c CONTAINER] [options],其中 -f 为持续跟踪输出,--tail=100 只看最后 100 行:

1
2
3
4
5
6
7
8
9
# 查看名称空间kube-system中仅有一个容器的Pod对象kube-apiserver-k8s01的日志
kubectl logs kube-apiserver-k8s01 -n kube-system

# 持续跟踪
kubectl logs -f kube-apiserver-k8s01 -n kube-system
kubectl logs --tail=100 -f kube-apiserver-k8s01 -n kube-system

# 输出最后 100 行日志到文件
kubectl logs --tail=100 -n rook-ceph rook-ceph-operator-6f7f6b96d-vqx5c > /tmp/rook-ceph-operator.log

在容器中执行命令

kubectl exec 命令用于在指定的容器内运行其他应用程序:

1
2
# 在kube-system名称空间中的Pod对象kube-apiserver-k8s01上的唯一容器中运行ps命令
kubectl exec kube-apiserver-k8s01 -n kube-system -- ps

Pod 对象中存在多个容器,则需要以 -c 选项指定容器后再运行。

删除资源对象

kubectl delete 用于删除资源对象。注意对于受控于控制器的对象来说,删除之后其控制器可能会重建出类似的对象:

1
2
3
4
5
6
7
8
9
10
11
12
# 删除默认名称空间中名为nginx-svc的Service资源对象
kubectl delete services nginx-svc

# 删除kube-system名称空间中拥有标签“app=monitor”的所有Pod对象
kubectl delete pods -l app=monitor -n kube-system

# 删除所有名称空间中拥有标签“app=monitor”和“ver=3.1.1”的所有Pod、service对象
kubectl delete pods services -l ver=3.1.1,app=monitor --all-namespaces

# kubectl delete TYPE --all -n NS
# 删除default名称空间中的所有Pod对象
kubectl delete pods --all -n default

有些资源类型(如 Pod)支持优雅删除的机制,它们有着默认的删除宽限期,不过用户可以在命令中使用 --grace-period 选项或 --now 选项来覆盖默认的宽限期。

查看资源占用情况

需要先安装 metrics-server:

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
[root@test-173 ~]# kubectl top pod -n kube-system
NAME CPU(cores) MEMORY(bytes)
calico-kube-controllers-d8d4d9587-cbsn6 7m 17Mi
calico-node-dt2bh 46m 35Mi
calico-node-fgwkj 43m 23Mi
calico-node-fj8gp 58m 22Mi
calico-node-tth8k 30m 22Mi
coredns-59c8bd8884-pcnbt 9m 16Mi
coredns-59c8bd8884-xqnnj 10m 14Mi
heapster-7d7fc6648b-kkd9q 1m 17Mi
kubernetes-dashboard-96f697bc5-w942c 0m 8Mi
metrics-server-67cb878c78-8q7jq 3m 20Mi
nginx-ingress-controller-kfht8 14m 77Mi
nginx-ingress-controller-rr7tn 9m 80Mi
nginx-ingress-controller-wfnmx 10m 77Mi
nginx-ingress-controller-whcqg 6m 84Mi
nginx-ingress-default-backend-58c5c69f7c-mhr2m 0m 3Mi
tiller-deploy-7bb9858659-w84j9 0m 19Mi


[root@test-173 ~]# kubectl top node
NAME CPU(cores) CPU% MEMORY(bytes) MEMORY%
172.20.40.107 513m 3% 5713Mi 40%
172.20.40.173 915m 2% 13955Mi 46%
172.20.40.196 571m 3% 4313Mi 30%
172.20.40.249 282m 1% 5512Mi 38%