kubectl是一个用于操作kubernetes集群的命令行接口,通过利用kubectl的各种命令可以实现各种功能,是在使用kubernetes中非常常用的工具。这里我们会通过一些简单的实例来展现其中一些高频命令的使用方法。
更为重要的是这些命令使用的场景以及能够解决什么样的问题。上篇文章我们介绍了故障排查时常用的九条命令,这篇文章我们来看一下故障对应时最常用的另外九条命令。
kubectl故障对应相关,本文将会简单介绍一下如下命令
项番 | 命令 | 说明 |
---|---|---|
No.1 | edit | 编辑服务器侧资源 |
No.2 | replace | 使用文件名或者标准输入资源 |
No.3 | patch | 部分更新资源相关信息 |
No.4 | apply | 使用文件或者标准输入更改配置信息 |
No.5 | scale | 重新设定Deployment/ReplicaSet/RC/Job的size |
No.6 | autoscale | Deployment/ReplicaSet/RC的自动扩展设定 |
No.7 | cordon | 设定node不可使用 |
No.8 | uncordon | 设定node可以使用 |
No.9 | drain | 设定node进入维护模式 |
[root@ku8-1 tmp]# kubectl version
Client Version: version.Info{Major:"1", Minor:"5", GitVersion:"v1.5.2", GitCommit:"08e099554f3c31f6e6f07b448ab3ed78d0520507", GitTreeState:"clean", BuildDate:"2017-01-12T04:57:25Z", GoVersion:"go1.7.4", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"5", GitVersion:"v1.5.2", GitCommit:"08e099554f3c31f6e6f07b448ab3ed78d0520507", GitTreeState:"clean", BuildDate:"2017-01-12T04:52:34Z", GoVersion:"go1.7.4", Compiler:"gc", Platform:"linux/amd64"}
[root@ku8-1 tmp]#
一主三从的Kubernetes集群
项番 | 类型 | Hostname | IP |
---|---|---|---|
No.1 | Master | ku8-1 | 192.168.32.131 |
No.1 | Node | ku8-2 | 192.168.32.132 |
No.1 | Node | ku8-3 | 192.168.32.133 |
No.1 | Node | ku8-4 | 192.168.32.134 |
[root@ku8-1 tmp]# kubectl get nodes
NAME STATUS AGE
192.168.32.132 Ready 12m
192.168.32.133 Ready 11m
192.168.32.134 Ready 11m
[root@ku8-1 tmp]#
使用如下官方镜像进行实验,因为主要用于示例,自行使用各种镜像均可
镜像 | 版本 | 说明 |
---|---|---|
nginx-alpine | 1.12 | nginx的1.12的alpine版本的官方镜像 |
nginx-alpine | 1.13 | nginx的1.13的alpine版本的官方镜像 |
使用Deployment方式启动nginx的pod加上service的设定,简单如下:
[root@ku8-1 tmp]# cat nginx/nginx.yaml
---
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: nginx
spec:
replicas: 1
template:
metadata:
labels:
name: nginx
spec:
containers:
- name: nginx
image: 192.168.32.131:5000/nginx:1.12-alpine
ports:
- containerPort: 80
protocol: TCP
---
kind: Service
apiVersion: v1
metadata:
name: nginx
labels:
name: nginx
spec:
type: NodePort
ports:
- protocol: TCP
nodePort: 31001
targetPort: 80
port: 80
selector:
name: nginx
[root@ku8-1 tmp]#
创建pod/deployment/service
[root@ku8-1 tmp]# kubectl create -f nginx/
deployment "nginx" created
service "nginx" created
[root@ku8-1 tmp]#
创建pod/deployment/service
[root@ku8-1 tmp]# kubectl get service
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes 172.200.0.1 443/TCP 1d
nginx 172.200.229.212 80:31001/TCP 58s
[root@ku8-1 tmp]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-2476590065-1vtsp 1/1 Running 0 1m
[root@ku8-1 tmp]# kubectl get deploy
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx 1 1 1 1 1m
[root@ku8-1 tmp]#
edit这条命令用于编辑服务器上的资源,具体是什么意思,可以通过如下使用方式来确认。
使用-o参数指定输出格式为yaml的nginx的service的设定情况确认,取得现场情况,这也是我们不知道其yaml文件而只有环境时候能做的事情。
[root@ku8-1 tmp]# kubectl get service |grep nginx
nginx 172.200.229.212 80:31001/TCP 2m
[root@ku8-1 tmp]# kubectl get service nginx -o yaml
apiVersion: v1
kind: Service
metadata:
creationTimestamp: 2017-06-30T04:50:44Z
labels:
name: nginx
name: nginx
namespace: default
resourceVersion: "77068"
selfLink: /api/v1/namespaces/default/services/nginx
uid: ad45612a-5d4f-11e7-91ef-000c2933b773
spec:
clusterIP: 172.200.229.212
ports:
- nodePort: 31001
port: 80
protocol: TCP
targetPort: 80
selector:
name: nginx
sessionAffinity: None
type: NodePort
status:
loadBalancer: {}
[root@ku8-1 tmp]#
使用edit命令对nginx的service设定进行编辑,得到如下信息
可以看到当前端口为31001,在此编辑中,我们把它修改为31002
[root@ku8-1 tmp]# kubectl edit service nginx
service "nginx" edited
[root@ku8-1 tmp]#
编辑之后确认结果发现,此服务端口已经改变
[root@ku8-1 tmp]# kubectl get service
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes 172.200.0.1 443/TCP 1d
nginx 172.200.229.212 80:31002/TCP 8m
[root@ku8-1 tmp]#
确认后发现能够立连通
[root@ku8-1 tmp]# curl http://192.168.32.132:31002/
<html>
<head>
<title>Welcome to nginx!title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
style>
head>
<body>
<h1>Welcome to nginx!h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.orga>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.coma>.p>
<p><em>Thank you for using nginx.em>p>
body>
html>
[root@ku8-1 tmp]#
而之前的端口已经不通
[root@ku8-1 tmp]# curl http://192.168.32.132:31001/
curl: (7) Failed connect to 192.168.32.132:31001; Connection refused
[root@ku8-1 tmp]#
所使用场景之一,edit编辑的是运行环境的设定而不需要停止服务。
了解到edit用来做什么之后,我们会立即知道replace就是替换,我们使用上个例子中的service的port,重新把它改回31001
确认port信息为31002
[root@ku8-1 tmp]# kubectl get service
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes 172.200.0.1 443/TCP 1d
nginx 172.200.229.212 80:31002/TCP 17m
[root@ku8-1 tmp]#
[root@ku8-1 tmp]# kubectl get service nginx -o yaml >nginx_forreplace.yaml
[root@ku8-1 tmp]# cp -p nginx_forreplace.yaml nginx_forreplace.yaml.org
[root@ku8-1 tmp]# vi nginx_forreplace.yaml
[root@ku8-1 tmp]# diff nginx_forreplace.yaml nginx_forreplace.yaml.org
15c15
< - nodePort: 31001
---
> - nodePort: 31002
[root@ku8-1 tmp]#
提示被替换了
[root@ku8-1 tmp]# kubectl replace -f nginx_forreplace.yaml
service "nginx" replaced
[root@ku8-1 tmp]#
确认之后发现port确实重新变成了31001
[root@ku8-1 tmp]# kubectl get service
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes 172.200.0.1 443/TCP 1d
nginx 172.200.229.212 80:31001/TCP 20m
[root@ku8-1 tmp]#
当部分修改一些设定的时候patch非常有用,尤其是在1.2之前的版本,port改来改去好无聊,这次换个image
当前port中使用的nginx是alpine的1.12版本
[root@ku8-1 tmp]# kubectl exec nginx-2476590065-1vtsp -it sh
/ # nginx -v
nginx version: nginx/1.12.0
/ #
[root@ku8-1 tmp]# kubectl patch pod nginx-2476590065-1vtsp -p '{"spec":{"containers":[{"name":"nginx","image":"192.168.32.131:5000/nginx:1.13-alpine"}]}}'
"nginx-2476590065-1vtsp" patched
[root@ku8-1 tmp]#
确认当前pod中的镜像已经patch成了1.13
[root@ku8-1 tmp]# kubectl exec nginx-2476590065-1vtsp -it sh
/ # nginx -v
nginx version: nginx/1.13.1
/ #
同样apply命令是用来使用文件或者标准输入来更改配置信息。
[root@ku8-1 tmp]# kubectl delete -f nginx/
deployment "nginx" deleted
service "nginx" deleted
[root@ku8-1 tmp]# kubectl create -f nginx/
deployment "nginx" created
service "nginx" created
[root@ku8-1 tmp]#
Service的Port设定为了31001
[root@ku8-1 tmp]# kubectl get service
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes 172.200.0.1 443/TCP 1d
nginx 172.200.68.154 80:31001/TCP 11s
[root@ku8-1 tmp]#
将port修改为31002
[root@ku8-1 tmp]# vi nginx/nginx.yaml
[root@ku8-1 tmp]# grep 31002 nginx/nginx.yaml
nodePort: 31002
[root@ku8-1 tmp]#
执行设定文件可以在运行状态修改port信息
[root@ku8-1 tmp]# kubectl apply -f nginx/nginx.yaml
deployment "nginx" configured
service "nginx" configured
[root@ku8-1 tmp]#
确认确实将port已经修改为31002了
[root@ku8-1 tmp]# kubectl get service
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes 172.200.0.1 443/TCP 1d
nginx 172.200.68.154 80:31002/TCP 1m
[root@ku8-1 tmp]#
scale命令用于横向扩展,是kubernetes或者swarm这类容器编辑平台的重要功能之一,让我们来看看是如何使用的
事前设定nginx的replica为一,而经过确认此pod在192.168.32.132上运行
[root@ku8-1 tmp]# kubectl delete -f nginx/
deployment "nginx" deleted
service "nginx" deleted
[root@ku8-1 tmp]# kubectl create -f nginx/
deployment "nginx" created
service "nginx" created
[root@ku8-1 tmp]#
[root@ku8-1 tmp]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE
nginx-2476590065-74tpk 1/1 Running 0 17s 172.200.26.2 192.168.32.132
[root@ku8-1 tmp]# kubectl get deployments -o wide
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx 1 1 1 1 27s
[root@ku8-1 tmp]#
使用scale命令进行横向扩展,将原本为1的副本,提高到3。
[root@ku8-1 tmp]# kubectl scale --current-replicas=1 --replicas=3 deployment/nginx
deployment "nginx" scaled
[root@ku8-1 tmp]#
通过确认发现已经进行了横向扩展,除了192.168.132.132,另外133和134两台机器也各有一个pod运行了起来,这正是scale命令的结果。
[root@ku8-1 tmp]# kubectl get deployment
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx 3 3 3 3 2m
[root@ku8-1 tmp]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE
nginx-2476590065-74tpk 1/1 Running 0 2m 172.200.26.2 192.168.32.132
nginx-2476590065-cm5d9 1/1 Running 0 16s 172.200.44.2 192.168.32.133
nginx-2476590065-hmn9j 1/1 Running 0 16s 172.200.59.2 192.168.32.134
[root@ku8-1 tmp]#
autoscale命令用于自动扩展确认,跟scale不同的是前者还是需要手动执行,而autoscale则会根据负载进行调解。而这条命令则可以对Deployment/ReplicaSet/RC进行设定,通过最小值和最大值的指定进行设定,这里只是给出执行的结果,不再进行实际的验证。
[root@ku8-1 tmp]# kubectl autoscale deployment nginx --min=2 --max=5
deployment "nginx" autoscaled
[root@ku8-1 tmp]#
当然使用还会有一些限制,比如当前3个,设定最小值为2的话会出现什么样的情况?
[root@ku8-1 tmp]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE
nginx-2476590065-74tpk 1/1 Running 0 5m 172.200.26.2 192.168.32.132
nginx-2476590065-cm5d9 1/1 Running 0 2m 172.200.44.2 192.168.32.133
nginx-2476590065-hmn9j 1/1 Running 0 2m 172.200.59.2 192.168.32.134
[root@ku8-1 tmp]#
[root@ku8-1 tmp]# kubectl autoscale deployment nginx --min=2 --max=2
Error from server (AlreadyExists): horizontalpodautoscalers.autoscaling "nginx" already exists
[root@ku8-1 tmp]#
在实际维护的时候会出现某个node坏掉,或者做一些处理,暂时不能让生成的pod在此node上运行,需要通知kubernetes让其不要创建过来,这条命令就是cordon,uncordon则是取消这个要求。例子如下:
创建了一个nginx的pod,跑在192.168.32.133上。
[root@ku8-1 tmp]# kubectl create -f nginx/
deployment "nginx" created
service "nginx" created
[root@ku8-1 tmp]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE
nginx-2476590065-dnsmw 1/1 Running 0 6s 172.200.44.2
192.168.32.133
[root@ku8-1 tmp]#
横向扩展到3个副本,发现利用roundrobin策略每个node上运行起来了一个pod,134这台机器也有一个。
[root@ku8-1 tmp]# kubectl scale --replicas=3 deployment/nginx
deployment "nginx" scaled
[root@ku8-1 tmp]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE
nginx-2476590065-550sm 1/1 Running 0 5s 172.200.26.2 192.168.32.132
nginx-2476590065-bt3bc 1/1 Running 0 5s 172.200.59.2 192.168.32.134
nginx-2476590065-dnsmw 1/1 Running 0 17s 172.200.44.2 192.168.32.133
[root@ku8-1 tmp]# kubectl get pods -o wide |grep 192.168.32.134
nginx-2476590065-bt3bc 1/1 Running 0 12s 172.200.59.2 192.168.32.134
[root@ku8-1 tmp]#
设定134,使得134不可使用,使用get node确认,其状态显示SchedulingDisabled。
[root@ku8-1 tmp]# kubectl cordon 192.168.32.134
node "192.168.32.134" cordoned
[root@ku8-1 tmp]# kubectl get nodes -o wide
NAME STATUS AGE EXTERNAL-IP
192.168.32.132 Ready 1d
192.168.32.133 Ready 1d
192.168.32.134 Ready,SchedulingDisabled 1d
[root@ku8-1 tmp]#
再次执行横向扩展命令,看是否会有pod漂到134这台机器上,结果发现只有之前的一个pod,再没有新的pod漂过去。
[root@ku8-1 tmp]# kubectl scale --replicas=6 deployment/nginx
deployment "nginx" scaled
[root@ku8-1 tmp]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE
nginx-2476590065-550sm 1/1 Running 0 32s 172.200.26.2 192.168.32.132
nginx-2476590065-7vxvx 1/1 Running 0 3s 172.200.44.3 192.168.32.133
nginx-2476590065-bt3bc 1/1 Running 0 32s 172.200.59.2 192.168.32.134
nginx-2476590065-dnsmw 1/1 Running 0 44s 172.200.44.2 192.168.32.133
nginx-2476590065-fclhj 1/1 Running 0 3s 172.200.44.4 192.168.32.133
nginx-2476590065-fl9fn 1/1 Running 0 3s 172.200.26.3 192.168.32.132
[root@ku8-1 tmp]# kubectl get pods -o wide |grep 192.168.32.134
nginx-2476590065-bt3bc 1/1 Running 0 37s 172.200.59.2 192.168.32.134
[root@ku8-1 tmp]#
使用uncordon命令解除对134机器的限制,通过get node确认状态也已经正常。
[root@ku8-1 tmp]# kubectl uncordon 192.168.32.134
node "192.168.32.134" uncordoned
[root@ku8-1 tmp]#
[root@ku8-1 tmp]# kubectl get nodes -o wide
NAME STATUS AGE EXTERNAL-IP
192.168.32.132 Ready 1d
192.168.32.133 Ready 1d
192.168.32.134 Ready 1d
[root@ku8-1 tmp]#
再次执行scale命令,发现有新的pod可以创建到134node上了。
[root@ku8-1 tmp]# kubectl scale --replicas=10 deployment/nginx
deployment "nginx" scaled
[root@ku8-1 tmp]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE
nginx-2476590065-550sm 1/1 Running 0 1m 172.200.26.2 192.168.32.132
nginx-2476590065-7vn6z 1/1 Running 0 3s 172.200.44.4 192.168.32.133
nginx-2476590065-7vxvx 1/1 Running 0 35s 172.200.44.3 192.168.32.133
nginx-2476590065-bt3bc 1/1 Running 0 1m 172.200.59.2 192.168.32.134
nginx-2476590065-dnsmw 1/1 Running 0 1m 172.200.44.2 192.168.32.133
nginx-2476590065-fl9fn 1/1 Running 0 35s 172.200.26.3 192.168.32.132
nginx-2476590065-pdx91 1/1 Running 0 3s 172.200.59.3 192.168.32.134
nginx-2476590065-swvwf 1/1 Running 0 3s 172.200.26.5 192.168.32.132
nginx-2476590065-vdq2k 1/1 Running 0 3s 172.200.26.4 192.168.32.132
nginx-2476590065-wdv52 1/1 Running 0 3s 172.200.59.4 192.168.32.134
[root@ku8-1 tmp]#
drain命令用于对某个node进行设定,是为了设定此node为维护做准备。英文的drain有排干水的意思,下水道的水之后排干后才能进行维护。那我们来看一下kubectl”排水”的时候都作了什么
将nginx的副本设定为4,确认发现134上启动了两个pod。
[root@ku8-1 tmp]# kubectl create -f nginx/
deployment "nginx" created
service "nginx" created
[root@ku8-1 tmp]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE
nginx-2476590065-d6h8f 1/1 Running 0 8s 172.200.59.2 192.168.32.134
[root@ku8-1 tmp]#
[root@ku8-1 tmp]# kubectl get nodes -o wide
NAME STATUS AGE EXTERNAL-IP
192.168.32.132 Ready 1d
192.168.32.133 Ready 1d
192.168.32.134 Ready 1d
[root@ku8-1 tmp]#
[root@ku8-1 tmp]# kubectl scale --replicas=4 deployment/nginx
deployment "nginx" scaled
[root@ku8-1 tmp]#
[root@ku8-1 tmp]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE
nginx-2476590065-9lfzh 1/1 Running 0 12s 172.200.59.3 192.168.32.134
nginx-2476590065-d6h8f 1/1 Running 0 1m 172.200.59.2 192.168.32.134
nginx-2476590065-v8xvf 1/1 Running 0 43s 172.200.26.2 192.168.32.132
nginx-2476590065-z94cq 1/1 Running 0 12s 172.200.44.2 192.168.32.133
[root@ku8-1 tmp]#
执行drain命令,发现这条命令做了两件事情:
1. 设定此node不可以使用(cordon)
2. evict了其上的两个pod
[root@ku8-1 tmp]# kubectl drain 192.168.32.134
node "192.168.32.134" cordoned
pod "nginx-2476590065-d6h8f" evicted
pod "nginx-2476590065-9lfzh" evicted
node "192.168.32.134" drained
[root@ku8-1 tmp]#
evict的意思有驱逐和回收的意思,让我们来看一下evcit这个动作的结果到底是什么。
结果是134上面已经不再有pod,而在132和133上新生成了两个pod,用以替代在134上被退场的pod,而这个替代的动作应该是replicas的机制保证的。所以drain的结果就是退场pod和设定node不可用(排水),这样的状态则可以进行维护了,执行完后重新uncordon即可。
[root@ku8-1 tmp]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE
nginx-2476590065-1ld9j 1/1 Running 0 13s 172.200.44.3 192.168.32.133
nginx-2476590065-ss48z 1/1 Running 0 13s 172.200.26.3 192.168.32.132
nginx-2476590065-v8xvf 1/1 Running 0 1m 172.200.26.2 192.168.32.132
nginx-2476590065-z94cq 1/1 Running 0 55s 172.200.44.2 192.168.32.133
[root@ku8-1 tmp]#
[root@ku8-1 tmp]# kubectl get nodes -o wide
NAME STATUS AGE EXTERNAL-IP
192.168.32.132 Ready 1d
192.168.32.133 Ready 1d
192.168.32.134 Ready,SchedulingDisabled 1d
[root@ku8-1 tmp]#
这篇文章中介绍了九个kubectl的常用命令,利用这些能够在故障对应中起到非常有效的作用。