Kubernetes 「驾驶舱」 kubectl 知多少?

如果你的 PaaS 平台是基于容器云 Kubernetes 搭建,那么 kubectl  一定是你经常使用的工具之一,每当你花费大量时间使用某个工具时,你都非常有必要去了解它的工作原理和有效使用。

什么是 kubectl

从用户的角度来说 kubectl 是 Kubernetes 的驾驶舱,用户可以通过 kubectl 控制 kubernetes 允许的所有操作。从技术的角度来说,kubectl 是 kubernetes 的客户端。Kubernetes API 是一个 HTTP REST API。此 API 是真正的 Kubernetes 用户接口。通过 API 我们可以完全控制 Kubernetes。这意味着每个 Kubernetes 操作都作为 API 端点公开,并且可以通过对此端点的 HTTP 请求来执行。因此,kubectl 的主要工作是对Kubernetes API 执行 HTTP 请求。

执行一个 kubectl get pod 背后发生了什么


kubectl 充当 Kubernetes 客户端,直接跟 API Server 交互,通过添加 -v 可以查看执行日志,如下所示:其中 -v = 9 是 trace 最高跟踪级别。通过如下日志可以看出 kubectl 实际上是对 Kubernetes APIServer的 6443 端口通过 curl 执行了 GET请求。具体查看如下日志:

[root@k8s-master ~]# kubectl get pod -A -v=9
I0410 16:48:36.823772   18735 loader.go:359] Config loaded from file /root/.kube/config
I0410 16:48:36.827223   18735 round_trippers.go:419] curl -k -v -XGET  -H "Accept: application/json;as=Table;v=v1beta1;g=meta.k8s.io, application/json" -H "User-Agent: kubectl/v1.14.3 (linux/amd64) kubernetes/5e53fd6" 'https://12.18.7.23:6443/api/v1/pods?limit=500'
I0410 16:48:36.832563   18735 round_trippers.go:438] GET https://12.18.7.23:6443/api/v1/pods?limit=500 200 OK in 5 milliseconds
I0410 16:48:36.832579   18735 round_trippers.go:444] Response Headers:
I0410 16:48:36.832585   18735 round_trippers.go:447]     Content-Type: application/json
I0410 16:48:36.832590   18735 round_trippers.go:447]     Date: Fri, 10 Apr 2020 08:48:36 GMT
I0410 16:48:36.832654   18735 request.go:942] Response Body: {"kind":"Table","apiVersion":"meta.k8s.io/v1beta1","metadata":{"selfLink":"/api/v1/pods","resourceVersion":"60404"},"columnDefinitions":[{"name":"Name","type":"string","format":"name","description":"Name must be unique within a namespace. Is required when creating resources, although some resources may allow a client to request the generation of an appropriate name automatically. Name is primarily intended for creation idempotence and configuration definition. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names","priority":0},{"name":"Ready","type":"string","format":"","description":"The aggregate readiness state of this pod for accepting traffic.","priority":0},{"name":"Status","type":"string","format":"","description":"The aggregate status of the containers in this pod.","priority":0},{"name":"Restarts","type":"integer","format":"","description":"The number of times the containers in this pod have been restarted.","priority":0},{"name":"Age","type":"string","format":"","description":"CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC.\n\nPopulated by the system. Read-only. Null for lists. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata","priority":0},{"name":"IP","type":"string","format":"","description":"IP address allocated to the pod. Routable at least within the cluster. Empty if not yet allocated.","priority":1},{"name":"Node","type":"string","format":"","description":"NodeName is a request to schedule this pod onto a specific node. If it is non-empty, the scheduler simply schedules this pod onto that node, assuming that it fits resource requirements.","priority":1},{"name":"Nominated Node","type":"string","format":"","description":"nominatedNodeName is set only when this pod preempts other pods on the node, but it cannot be scheduled right away as preemption victims receive their graceful termination periods. This field does not guarantee that the pod will be scheduled on this node. Scheduler may decide to place the pod elsewhere if other nodes become available sooner. Scheduler may also decide to give the resources on this node to a higher priority pod that is created after preemption. As a result, this field may be different than PodSpec.nodeName when the pod is scheduled.","priority":1},{"name":"Readiness Gates","type":"string","format":"","description":"If specified, all readiness gates will be evaluated for pod readiness. A pod is ready when all its containers are ready AND all conditions specified in the readiness gates have status equal to \"True\" More info: https://git.k8s.io/enhancements/keps/sig-network/0007-pod-ready%2B%2B.md","priority":1}],"rows":[{"cells":["coredns-fb8b8dccf-2hpgr","1/1","Running",3,"13h","10.244.0.7","k8s-master","\u003cnone\u003e","\u003cnone\u003e"],"object":{"kind":"PartialObjectMetadata","apiVersion":"meta.k8s.io/v1beta1","metadata":{"name":"coredns-fb8b8dccf-2hpgr","generateName":"coredns-fb8b8dccf-","namespace":"kube-system","selfLink":"/api/v1/namespaces/kube-system/pods/coredns-fb8b8dccf-2hpgr","uid":"18503b67-7a96-11ea-a7f5-509a4c36e19d","resourceVersion":"2352","creationTimestamp":"2020-04-09T19:12:45Z","labels":{"k8s-app":"kube-dns","pod-template-hash":"fb8b8dccf"},"ownerReferences":[{"apiVersion":"apps/v1","kind":"ReplicaSet","name":"coredns-fb8b8dccf","uid":"184ecff7-7a96-11ea-a7f5-509a4c36e19d","controller":true,"blockOwnerDeletion":true}]}}},{"cells":["coredns-fb8b8dccf-jg7s2","1/1","Running",3,"13h","10.244.0.6","k8s-master","\u003cnone\u003e","\u003cnone\u003e"],"object":{"kind":"PartialObjectMetadata","apiVersion":"meta.k8s.io/v1beta1","metadata":{"name":"coredns-fb8b8dccf-jg7s2","generateName":"coredns-fb8b8dccf-","namespace":"kube-system","selfLink":"/api/v1/namespaces/kube-system/pods/coredns-fb8b8dccf-jg7s2","uid":"184fbad1-7a96-11ea-a7f5-509a4c36e19d","resourceVersion":"2391","creationTimestamp":"2020-04-09T19:12:45Z","labels":{"k8s-app":"kube-dns","pod-template-hash":"fb8b8dccf"},"ownerReferences":[{"apiVersion":"apps/v1","kind":"ReplicaSet","name":"coredns-fb8b8dccf","uid":"184ecff7-7a96-11ea-a7f5-509a4c36e19d","controller":true,"blockOwnerDeletion":true}]}}},{"cells":["etcd-k8s-master","1/1","Running",2,"13h","12.18.7.23","k8s-master","\u003cnone\u003e","\u003cnone\u003e"],"object":{"kind":"PartialObjectMetadata","apiVersion":"meta.k8s.io/v1beta1","metadata":{"name":"etcd-k8s-master","namespace":"kube-system","selfLink":"/api/v1/namespaces/kube-system/pods/etcd-k8s-master","uid":"368900c8-7a96-11ea-a7f5-509a4c36e19d","resourceVersion":"2273","creationTimestamp":"2020-04-09T19:13:36Z","labels":{"component":"etcd","tier":"control-plane"},"annotations":{"kubernetes.io/config.hash":"6758e898d84f674fbf6006af1d686f72","kubernetes.io/config.mirror":"6758e898d84f674fbf6006af1d686f72","kubernetes.io/config.seen":"2020-04-10T03:12:22.675406659+08:00","kubernetes.io/config.source":"file"}}}},{"cells":["kube-apiserver-k8s-master","1/1","Running",2,"13h","12.18.7.23","k8s-master","\u003cnone\u003e","\u003cnone\u003e"],"object":{"kind":"PartialObjectMetadata","apiVersion":"meta.k8s.io/v1beta1","metadata":{"name":"kube-apiserver-k8s-master","namespace":"kube-system","selfLink":"/api/v1/namespaces/kube-system/pods/kube-apiserver-k8s-master","uid":"401276d9-7a96-11ea-a7f5-509a4c36e19d","resourceVersion":"2305","creationTimestamp":"2020-04-09T19:13:52Z","labels":{"component":"kube-apiserver","tier":"control-plane"},"annotations":{"kubernetes.io/config.hash":"ca0a720781e095859088c1b50d34ec38","kubernetes.io/config.mirror":"ca0a720781e095859088c1b50d34ec38","kubernetes.io/config.seen":"2020-04-10T03:12:22.675410299+08:00","kubernetes.io/config.source":"file"}}}},{"cells":["kube-controller-manager-k8s-master","1/1","Running",2,"13h","12.18.7.23","k8s-master","\u003cnone\u003e","\u003cnone\u003e"],"object":{"kind":"PartialObjectMetadata","apiVersion":"meta.k8s.io/v1beta1","metadata":{"name":"kube-controller-manager-k8s-master","namespace":"kube-system","selfLink":"/api/v1/namespaces/kube-system/pods/kube-controller-manager-k8s-master","uid":"2ffb0bea-7a96-11ea-a7f5-509a4c36e19d","resourceVersion":"2314","creationTimestamp":"2020-04-09T19:13:25Z","labels":{"component":"kube-controller-manager","tier":"control-plane"},"annotations":{"kubernetes.io/config.hash":"c96931c62b3df0232e2dbe44485232fe","kubernetes.io/config.mirror":"c96931c62b3df0232e2dbe44485232fe","kubernetes.io/config.seen":"2020-04-10T03:12:22.675411341+08:00","kubernetes.io/config.source":"file"}}}},{"cells":["kube-flannel-ds-amd64-jpl22","1/1","Running",2,"13h","12.18.7.23","k8s-master","\u003cnone\u003e","\u003cnone\u003e"],"object":{"kind":"PartialObjectMetadata","apiVersion":"meta.k8s.io/v1beta1","metadata":{"name":"kube-flannel-ds-amd64-jpl22","generateName":"kube-flannel-ds-amd64-","namespace":"kube-system","selfLink":"/api/v1/namespaces/kube-system/pods/kube-flannel-ds-amd64-jpl22","uid":"6df0717d-7a97-11ea-a7f5-509a4c36e19d","resourceVersion":"2320","creationTimestamp":"2020-04-09T19:22:19Z","labels":{"app":"flannel","controller-revision-hash":"587c98f784","pod-template-generation":"1","tier":"node"},"ownerReferences":[{"apiVersion":"apps/v1","kind":"DaemonSet","name":"kube-flannel-ds-amd64","uid":"6def7733-7a97-11ea-a7f5-509a4c36e19d","controller":true,"blockOwnerDeletion":true}]}}},{"cells":["kube-proxy-6dgjz","1/1","Running",2,"13h","12.18.7.23","k8s-master","\u003cnone\u003e","\u003cnone\u003e"],"object":{"kind":"PartialObjectMetadata","apiVersion":"meta.k8s.io/v1beta1","metadata":{"name":"kube-proxy-6dgjz","generateName":"kube-proxy-","namespace":"kube-system","selfLink":"/api/v1/namespaces/kube-system/pods/kube-proxy-6dgjz","uid":"18532a7a-7a96-11ea-a7f5-509a4c36e19d","resourceVersion":"2308","creationTimestamp":"2020-04-09T19:12:46Z","labels":{"controller-revision-hash":"7999c6dd97","k8s-app":"kube-proxy","pod-template-generation":"1"},"ownerReferences":[{"apiVersion":"apps/v1","kind":"DaemonSet","name":"kube-proxy","uid":"0f90946f-7a96-11ea-a7f5-509a4c36e19d","controller":true,"blockOwnerDeletion":true}]}}},{"cells":["kube-scheduler-k8s-master","1/1","Running",2,"13h","12.18.7.23","k8s-master","\u003cnone\u003e","\u003cnone\u003e"],"object":{"kind":"PartialObjectMetadata","apiVersion":"meta.k8s.io/v1beta1","metadata":{"name":"kube-scheduler-k8s-master","namespace":"kube-system","selfLink":"/api/v1/namespaces/kube-system/pods/kube-scheduler-k8s-master","uid":"3689017b-7a96-11ea-a7f5-509a4c36e19d","resourceVersion":"2317","creationTimestamp":"2020-04-09T19:13:36Z","labels":{"component":"kube-scheduler","tier":"control-plane"},"annotations":{"kubernetes.io/config.hash":"124f5bab49bf26c80b1c1be19641c3e8","kubernetes.io/config.mirror":"124f5bab49bf26c80b1c1be19641c3e8","kubernetes.io/config.seen":"2020-04-10T03:12:22.675412214+08:00","kubernetes.io/config.source":"file"}}}}]}
I0410 16:48:36.833641   18735 get.go:570] no kind is registered for the type v1beta1.Table in scheme "k8s.io/kubernetes/pkg/api/legacyscheme/scheme.go:29"
NAMESPACE     NAME                                 READY   STATUS    RESTARTS   AGE
kube-system   coredns-fb8b8dccf-2hpgr              1/1     Running   3          13h
kube-system   coredns-fb8b8dccf-jg7s2              1/1     Running   3          13h
kube-system   etcd-k8s-master                      1/1     Running   2          13h
kube-system   kube-apiserver-k8s-master            1/1     Running   2          13h
kube-system   kube-controller-manager-k8s-master   1/1     Running   2          13h
kube-system   kube-flannel-ds-amd64-jpl22          1/1     Running   2          13h
kube-system   kube-proxy-6dgjz                     1/1     Running   2          13h
kube-system   kube-scheduler-k8s-master            1/1     Running   2          13h

kubectl命令怎么知道应该把请求发送到哪个API server呢

运行命令kubectl config view, 显示内容里的 server 后面的地址就是API server 的 url。

[root@k8s-master ~]# kubectl config view
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://12.18.7.23:6443
  name: kubernetes
contexts:
- context:
    cluster: kubernetes
    user: kubernetes-admin
  name: kubernetes-admin@kubernetes
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: kubernetes-admin
  user:
    client-certificate-data: REDACTED
    client-key-data: REDACTED

Kubectl常见问题如何排除

在安装配置好 Kubernetes 后,正常情况下服务器关机重启,kubelet 也会自动启动的。一次关机重启后提示如下错误:

The connection to the server 12.18.7.23:6443 was refused - did you specify the right host or port?

通过systemctl status kubelet 命令查看 kubelet 的情况,发现 kubelet 确实没有启动,其中原因是因为由于 K8s 必须保持全程关闭交换内存,之前安装是只是使用 swapoff -a 命令暂时关闭 swap。而机器重启后,swap 还是会自动启用,从而导致 kubelet 无法启动。

可以通过如下方式进行解决开机不能自启动问题

1、执行

swapoff -a

2、执行

vi /etc/fstab


/dev/mapper/centos-swap swap swap default 0 0

这一行前面加个 # 号将其注释掉。编辑完毕后保存退出。这样机器重启后 kubelet 也可以正常自动启动了。

如果以上修改完成后,还是不能自动启动,因为 Kubernetes 底层 依赖docker服务,可以查看docker 是否正常,如果不正常可以通过

 kubectl restart docker


如果重启docker 完成以后,还是不能正常使用,这时可以 df -h 查看磁盘资源占用是否正常,如果磁盘打满也可能导致 kubectl 不能正常运行。

本质上来说 kubectl 命令不能正常运行,很可能是 kubectl 依赖的系统环境不正常导致,日志可以解决一切。如本文所示进行问题排除:Kubernetes排障指南

总结

如上所示,介绍了 kubectl 工作原理,通过 kubectl 客户端完成对 Kubernetes 控制,如果你还是不明白 kubectl 如何使用,那么直接在安装完成 Kubernetes 环境 shell 上执行 kubectl ,它会提示你如何操作,当然你也可以配置自动补全或简写功能,提升你的工作效率。

回顾往期内容


Jenkins配合Kubernetes实现服务持续集成的实践和建议

云计算交付模型知多少IaaS、PaaS、SaaS

docker到k8s pod跨节点网络通信机制演进

Kubernetes中如何使用ClusterDNS进行服务发现?

Kubernetes入门培训(内含PPT)

从Ice到Kubernetes容器技术,微服务架构经历了什么?


原创不易,随手关注或者”在看“,诚挚感谢!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值