k8s常用命令介绍
本文将介绍 k8s 中的一些最基本的命令,并辅以解释一些基本概念来方便理解,也就是说,本文是一篇偏向实用性而非学术性的文章,如果你想提前了解一下 k8s 相关的知识的话,可以通过以下链接进行学习:
结构模型
k8s 是经典的一对多模型,有一个主要的管理节点master
和许多的工作节点slaver
。当然,k8s 也可以配置多个管理节点,拥有两个以上的管理节点被称为 高可用。k8s 包括了许多的组件,每个组件都是单运行在一个docker
容器中,然后通过自己规划的虚拟网络相互访问。你可以通过kubectl get pod -n kube-system
查看所有节点上的组件容器。
在管理节点中会比工作节点运行更多的 k8s 组件,我们就是靠着这些多出来的组件来对工作节点发号施令。他们都叫什么这里就不详细提了。反正对于”基本使用“来说,这些名字并不重要。
理念
要想理解一个东西就要先明白它的内在理念。通俗点就是,k8s 做了什么?为了提供更加可靠的服务,就要增加服务器的数量,减少每个服务器的体量来平摊负载,而越来越多的虚拟机就会带来越来越高的运维成本。如何让少量的运维人员就可以管理数量众多的服务器及其上的服务呢?这就是 k8s 做的工作。
k8s 把数量众多的服务器重新抽象为一个统一的资源池,对于运维人员来说,他们面前没有服务器1、服务器2的概念,而是一个统一的资源池,增加新的服务器对运维人员来说,只是增加自资源池的可用量。不仅如此,k8s 把所有能用的东西都抽象成了资源的概念,从而提供了一套更统一,更简洁的管理方式。
命令名 | 类型 | 作用 |
---|---|---|
get | 查 | 列出某个类型的下属资源 |
describe | 查 | 查看某个资源的详细信息 |
logs | 查 | 查看某个 pod 的日志 |
create | 增 | 新建资源 |
explain | 查 | 查看某个资源的配置项 |
delete | 删 | 删除某个资源 |
edit | 改 | 修改某个资源的配置项 |
apply | 改 | 应用某个资源的配置项 |
kubectl get 列出资源
接下来进入正题,首先来了解一下 k8s 中最最最常用的命令kubectl get
,要记住,k8s 把所有的东西都抽象成了资源,而kubectl get
就是用来查看这些资源的。最常见的资源就是 pod 。
什么是 pod?
pod
(豆荚)。 pod 的概念其实和docker
中的容器非常相似。他是 k8s 中的最小工作单位。你可以把 pod 理解成一个一个的小机器人,而 k8s 抽象出来的大资源池就是他们的工厂。
pod
和docker
容器的关系?pod 将一个或多个
docker
容器封装成一个统一的整体进行管理并对外提供服务。
不仅我们自己的服务是要包装成 pod 的,就连 k8s 自己也是运行在一堆 pod 上。接下来就让我们查看一下 k8s 的 pod :
1 | kubectl get pod -n kube-system |
-n
参数指定了要查看哪个命名空间下的 pod 。 k8s 所有的 pod 都被放置在kube-system
命名空间下。
什么是命名空间?
命名空间
namespace
,是 k8s 中”组“的概念,提供同一服务的 pod 就应该被放置同一命名空间下,而不是混杂在一起。k8s 可以用命名空间来做权限控制。如果不指定的话, pod 将被放置在默认的命名空间default
下。
执行了kubectl get pod -n kube-system
命令后,你就可以看到如下内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | NAME READY STATUS RESTARTS AGE coredns-bccdc95cf-69zrw 1/1 Running 1 4d1h coredns-bccdc95cf-77bg4 1/1 Running 1 4d1h etcd-master1 1/1 Running 6 4d1h kube-apiserver-master1 1/1 Running 6 4d1h kube-controller-manager-master1 1/1 Running 2 4d1h kube-flannel-ds-amd64-2d6tb 1/1 Running 0 47h kube-flannel-ds-amd64-kp5xs 1/1 Running 0 47h kube-flannel-ds-amd64-l9728 1/1 Running 0 47h kube-flannel-ds-amd64-r87qc 1/1 Running 0 47h kube-proxy-2lz7f 1/1 Running 0 2d23h kube-proxy-hqsdn 1/1 Running 4 4d1h kube-proxy-rh92r 1/1 Running 1 4d1h kube-proxy-tv4mt 1/1 Running 0 3d2h kube-scheduler-master1 1/1 Running 2 4d1h |
其中每一行就是一个资源,这里我们看到的资源是 pod 。你看到的 pod 数量可能和我的不一致,因为这个列表里包含了 k8s 在所有节点上运行的 pod ,你加入的节点越多,那么显示的 pod 也就越多。我们来一列一列的看:
NAME
:第一列是 pod 的名字,k8s 可以为 pod 随机分配一个五位数的后缀。READY
:第二列是 pod 中已经就绪的 docker 容器的数量,上文中我们提到了,pod 封装了一个或多个 docker 容器。在这里,1/1
的含义为就绪1个容器/共计1个容器
。STATUS
:第三列是 pod 的当前状态,下面是一些常见的状态:
状态名 | 含义 |
---|---|
Running | 运行中 |
Error | 异常,无法提供服务 |
Pending | 准备中,暂时无法提供服务 |
Terminaling | 结束中,即将被移除 |
Unknown | 未知状态,多发生于节点宕机 |
PullImageBackOff | 镜像拉取失败 |
RESTART
:k8s 可以自动重启 pod,这一行就是标记了 pod 一共重启了多少次。AGE
:pod 一共存在了多长时间。
kubectl get
可以列出 k8s 中所有资源
这里只介绍了如何用kubectl
获取 pod 的列表。但是不要把get
和pod
绑定在一起,pod 只是 k8s 中的一种服务,你不仅可以get pod
,还可以get svc
(查看服务)、get rs
(查看副本控制器)、get deploy
(查看部署)等等等等,虽然说kubectl get pod
是最常用的一个,但是如果想查看某个资源而又不知道命令是什么,kbuectl get <资源名>
就对了。
如果你想看更多的信息,就可以指定-o wide
参数,如下:
1 | kubectl get pod -n kube-system -o wide |
加上这个参数之后就可以看到资源的所在ip
和所在节点node
了。
记得加上 -n
-n
可以说是kubectl get
命令使用最频繁的参数了,在正式使用中,我们永远不会把资源发布在默认命名空间。所以,永远不要忘记在get
命令后面加上-n
。
1 2 3 4 5 6 7 8 9 10 11 12 | [root@k8smaster ~]# kubectl get pod -n kube-system -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES coredns-c676cc86f-426wc 1/1 Running 1 (2m23s ago) 22h 10.244.0.4 k8smaster <none> <none> coredns-c676cc86f-7fmck 1/1 Running 1 (2m23s ago) 22h 10.244.0.5 k8smaster <none> <none> etcd-k8smaster 1/1 Running 2 (2m23s ago) 22h 192.168.59.80 k8smaster <none> <none> kube-apiserver-k8smaster 1/1 Running 2 (2m24s ago) 22h 192.168.59.80 k8smaster <none> <none> kube-controller-manager-k8smaster 1/1 Running 2 (2m23s ago) 22h 192.168.59.80 k8smaster <none> <none> kube-proxy-24tx5 1/1 Running 1 (2m23s ago) 22h 192.168.59.80 k8smaster <none> <none> kube-proxy-h5fcs 1/1 Running 1 (114s ago) 21h 192.168.59.82 k8snode2 <none> <none> kube-proxy-ktcnm 1/1 Running 1 (2m14s ago) 21h 192.168.59.81 k8snode1 <none> <none> kube-scheduler-k8smaster 1/1 Running 2 (2m23s ago) 22h 192.168.59.80 k8smaster <none> <none> |
kubectl get
命令可以列出 k8s 中的资源,而kubectl get pod
是非常常用的查看 pod 的命令。而-n
参数则可以指定 pod 所在的命名空间。
kubectl describe 查看详情
kubectl describe
命令可以用来查看某一资源的具体信息,他同样可以查看所有资源的详情,不过最常用的还是查看 pod 的详情。他也同样可以使用-n
参数指定资源所在的命名空间。
举个例子,我们可以用下面命令来查看刚才 pod 列表中的某个 pod,注意不要忘记把 pod 名称修改成自己的:
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 | [root@k8smaster ~]# kubectl describe pod kube-proxy-ktcnm -n kube-system Name: kube-proxy-ktcnm Namespace: kube-system Priority: 2000001000 Priority Class Name: system-node-critical Service Account: kube-proxy Node: k8snode1/192.168.59.81 Start Time: Tue, 22 Nov 2022 16:16:27 +0800 Labels: controller-revision-hash=7955fd779f k8s-app=kube-proxy pod-template-generation=1 Annotations: <none> Status: Running IP: 192.168.59.81 IPs: IP: 192.168.59.81 Controlled By: DaemonSet/kube-proxy Containers: kube-proxy: Container ID: containerd://484eaf0b5073f2fcfd6f3ba57ee9ec7dc46dde1a403872ba4f26767472e09f76 Image: registry.aliyuncs.com/google_containers/kube-proxy:v1.25.4 Image ID: registry.aliyuncs.com/google_containers/kube-proxy@sha256:1df694ba49eb1263a84c6cb32dd143d09b3e0b6cb0d48fddb3424cc4afe22e49 Port: <none> Host Port: <none> Command: /usr/local/bin/kube-proxy --config=/var/lib/kube-proxy/config.conf --hostname-override=$(NODE_NAME) State: Running Started: Wed, 23 Nov 2022 14:05:50 +0800 Last State: Terminated Reason: Unknown Exit Code: 255 Started: Tue, 22 Nov 2022 16:39:08 +0800 Finished: Wed, 23 Nov 2022 14:05:34 +0800 Ready: True Restart Count: 1 Environment: NODE_NAME: (v1:spec.nodeName) Mounts: /lib/modules from lib-modules (ro) /run/xtables.lock from xtables-lock (rw) /var/lib/kube-proxy from kube-proxy (rw) /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-7jfjl (ro) Conditions: Type Status Initialized True Ready True ContainersReady True PodScheduled True Volumes: kube-proxy: Type: ConfigMap (a volume populated by a ConfigMap) Name: kube-proxy Optional: false xtables-lock: Type: HostPath (bare host directory volume) Path: /run/xtables.lock HostPathType: FileOrCreate lib-modules: Type: HostPath (bare host directory volume) Path: /lib/modules HostPathType: kube-api-access-7jfjl: Type: Projected (a volume that contains injected data from multiple sources) TokenExpirationSeconds: 3607 ConfigMapName: kube-root-ca.crt ConfigMapOptional: <nil> DownwardAPI: true QoS Class: BestEffort Node-Selectors: kubernetes.io/os=linux Tolerations: op=Exists node.kubernetes.io/disk-pressure:NoSchedule op=Exists node.kubernetes.io/memory-pressure:NoSchedule op=Exists node.kubernetes.io/network-unavailable:NoSchedule op=Exists node.kubernetes.io/not-ready:NoExecute op=Exists node.kubernetes.io/pid-pressure:NoSchedule op=Exists node.kubernetes.io/unreachable:NoExecute op=Exists node.kubernetes.io/unschedulable:NoSchedule op=Exists Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 21h default-scheduler Successfully assigned kube-system/kube-proxy-ktcnm to k8snode1 Warning FailedCreatePodSandBox 21h (x18 over 21h) kubelet Failed to create pod sandbox: rpc error: code = Unknown desc = failed to get sandbox image "registry.k8s.io/pause:3.6": failed to pull image "registry.k8s.io/pause:3.6": failed to pull and unpack image "registry.k8s.io/pause:3.6": failed to resolve reference "registry.k8s.io/pause:3.6": failed to do request: Head "https://asia-east1-docker.pkg.dev/v2/k8s-artifacts-prod/images/pause/manifests/3.6": dial tcp 108.177.97.82:443: connect: connection refused Warning FailedCreatePodSandBox 21h (x10 over 21h) kubelet Failed to create pod sandbox: rpc error: code = Unknown desc = failed to get sandbox image "registry.k8s.io/pause:3.6": failed to pull image "registry.k8s.io/pause:3.6": failed to pull and unpack image "registry.k8s.io/pause:3.6": failed to resolve reference "registry.k8s.io/pause:3.6": failed to do request: Head "https://asia-east1-docker.pkg.dev/v2/k8s-artifacts-prod/images/pause/manifests/3.6": dial tcp 142.250.157.82:443: connect: connection refused Warning FailedCreatePodSandBox 21h (x2 over 21h) kubelet Failed to create pod sandbox: rpc error: code = Unknown desc = failed to get sandbox image "registry.k8s.io/pause:3.6": failed to pull image "registry.k8s.io/pause:3.6": failed to pull and unpack image "registry.k8s.io/pause:3.6": failed to resolve reference "registry.k8s.io/pause:3.6": failed to do request: Head "https://asia-east1-docker.pkg.dev/v2/k8s-artifacts-prod/images/pause/manifests/3.6": dial tcp 142.250.157.82:443: connect: connection refused Warning FailedCreatePodSandBox 21h (x8 over 21h) kubelet Failed to create pod sandbox: rpc error: code = Unknown desc = failed to get sandbox image "registry.k8s.io/pause:3.6": failed to pull image "registry.k8s.io/pause:3.6": failed to pull and unpack image "registry.k8s.io/pause:3.6": failed to resolve reference "registry.k8s.io/pause:3.6": failed to do request: Head "https://asia-east1-docker.pkg.dev/v2/k8s-artifacts-prod/images/pause/manifests/3.6": dial tcp 108.177.97.82:443: connect: connection refused Normal Pulling 21h kubelet Pulling image "registry.aliyuncs.com/google_containers/kube-proxy:v1.25.4" Normal Pulled 21h kubelet Successfully pulled image "registry.aliyuncs.com/google_containers/kube-proxy:v1.25.4" in 5.292341096s Normal Created 21h kubelet Created container kube-proxy Normal Started 21h kubelet Started container kube-proxy Normal SandboxChanged 3m43s kubelet Pod sandbox changed, it will be killed and re-created. Normal Pulled 3m38s kubelet Container image "registry.aliyuncs.com/google_containers/kube-proxy:v1.25.4" already present on machine Normal Created 3m38s kubelet Created container kube-proxy Normal Started 3m37s kubelet Started container kube-proxy [root@k8smaster ~]# |
然后你就可以看到很多的信息,咱们分开说,首先是基本属性,你可以在详细信息的开头找到它:
基本属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | ## 实例名称 Name: kube-flannel-ds-amd64-2d6tb ## 所处命名空间 Namespace: kube-system ## 所在节点 Node: worker2/192.168.56.22 ## 启动时间 Start Time: Wed, 03 Jul 2019 09:31:50 +0000 ## 标签 Labels: app=flannel controller-revision-hash=bfc6b6dd4 pod-template-generation=2 tier=node ## 注解 Annotations: <none> ## 当前状态 Status: Running ## 所在节点 IP IP: 192.168.56.22 ## 由那种资源生成 / 控制 Controlled By: DaemonSet/kube-flannel-ds-amd64 |
其中几个比较常用的,例如Node
、labels
和Controlled By
。通过Node
你可以快速定位到 pod 所处的机器,从而检查该机器是否出现问题或宕机等。通过labels
你可以检索到该 pod 的大致用途及定位。而通过Controlled By
,你可以知道该 pod 是由那种 k8s 资源创建的,然后就可以使用kubectl get <资源名>
来继续查找问题。例如上文DaemonSet/kube-flannel-ds-amd64
,就可以通过kubectl get DaemonSet -n kube-system
来获取上一节资源的信息。
内部镜像信息
在中间部分你可以找到像下面一样的Containers
段落。该段落详细的描述了 pod 中每个 docker 容器的信息,常用的比如Image
字段,当 pod 出现 ImagePullBackOff
错误的时候就可以查看该字段确认拉取的什么镜像。其他的字段名都很通俗,直接翻译即可。
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 | Containers: kube-flannel: Container ID: docker://25d2c4896847bbf53735c57a60c5b3146e2b3a0f86811074bcd28a8291213c18 Image: quay.io/coreos/flannel:v0.11.0-amd64 Image ID: docker://sha256:ff281650a721f46bbe2169292c91031c66411554739c88c861ba78475c1df894 Port: <none> Host Port: <none> Command: /opt/bin/flanneld Args: --ip-masq --kube-subnet-mgr --iface=enp0s8 State: Running Started: Wed, 03 Jul 2019 09:31:53 +0000 Ready: True Restart Count: 0 Limits: cpu: 100m memory: 50Mi Requests: cpu: 100m memory: 50Mi Environment: POD_NAME: kube-flannel-ds-amd64-2d6tb (v1:metadata.name) POD_NAMESPACE: kube-system (v1:metadata.namespace) Mounts: /etc/kube-flannel/ from flannel-cfg (rw) /run from run (rw) /var/run/secrets/kubernetes.io/serviceaccount from flannel-token-fsqdv (ro) |
事件
在describe
查看详情的时候,最常用的信息获取处就是这个Event
段落了,你可以在介绍内容的末尾找到它,如下:
1 | Events: <none> |
是的,如果你看到上面这样,没有任何Events
的话,就说明该 pod 一切正常。当 pod 的状态不是Running
时,这里一定会有或多或少的问题,长得像下面一样,然后你就可以通过其中的信息分析 pod 出现问题的详细原因了:
1 2 3 4 5 6 7 | Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Killing 29m kubelet, worker1 Stopping container kube-flannel Warning FailedCreatePodSandBox 27m (x12 over 29m) kubelet, worker1 Failed create pod sandbox: rpc error: code = Unknown desc = failed to create a sandbox for pod "kube-flannel-ds-amd64-9trbq": Error response from daemon: cgroup-parent for systemd cgroup should be a valid slice named as "xxx.slice" Normal SandboxChanged 19m (x48 over 29m) kubelet, worker1 Pod sandbox changed, it will be killed and re-created. Normal Pulling 42s kubelet, worker1 Pulling image "quay.io/coreos/flannel:v0.11.0-amd64" |
kubectl describe <资源名> <实例名>
可以查看一个资源的详细信息,最常用的还是比如kubectl describe pod <pod名> -n <命名空间>
来获取一个 pod 的基本信息。如果出现问题的话,可以在获取到的信息的末尾看到Event
段落,其中记录着导致 pod 故障的原因。
kubectl logs 查看日志
如果你想查看一个 pod 的具体日志,就可以通过kubectl logs <pod名>
来查看。注意,这个只能查看 pod 的日志。通过添加-f
参数可以持续查看日志。例如,查看kube-system
命名空间中某个flannel
pod 的日志,注意修改 pod 名称:
1 | kubectl logs -f -n kube-system kube-flannel-ds-amd64-2d6tb |
然后就可以看到如下输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | E0706 06:55:15.848891 1 reflector.go:201] github.com/coreos/flannel/subnet/kube/kube.go:310: Failed to list *v1.Node: Get https://10.96.0.1:443/api/v1/nodes?resourceVersion=0: dial tcp 10.96.0.1:443: connect: connection refused E0706 06:55:16.948058 1 reflector.go:201] github.com/coreos/flannel/subnet/kube/kube.go:310: Failed to list *v1.Node: Get https://10.96.0.1:443/api/v1/nodes?resourceVersion=0: dial tcp 10.96.0.1:443: connect: connection refused E0706 06:55:17.949165 1 reflector.go:201] github.com/coreos/flannel/subnet/kube/kube.go:310: Failed to list *v1.Node: Get https://10.96.0.1:443/api/v1/nodes?resourceVersion=0: dial tcp 10.96.0.1:443: connect: connection refused E0706 06:55:18.954108 1 reflector.go:201] github.com/coreos/flannel/subnet/kube/kube.go:310: Failed to list *v1.Node: Get https://10.96.0.1:443/api/v1/nodes?resourceVersion=0: dial tcp 10.96.0.1:443: connect: connection refused E0706 06:55:19.955267 1 reflector.go:201] github.com/coreos/flannel/subnet/kube/kube.go:310: Failed to list *v1.Node: Get https://10.96.0.1:443/api/v1/nodes?resourceVersion=0: dial tcp 10.96.0.1:443: connect: connection refused E0706 06:55:21.046592 1 reflector.go:201] github.com/coreos/flannel/subnet/kube/kube.go:310: Failed to list *v1.Node: Get https://10.96.0.1:443/api/v1/nodes?resourceVersion=0: dial tcp 10.96.0.1:443: connect: connection refused E0706 06:55:22.048285 1 reflector.go:201] github.com/coreos/flannel/subnet/kube/kube.go:310: Failed to list *v1.Node: Get https://10.96.0.1:443/api/v1/nodes?resourceVersion=0: dial tcp 10.96.0.1:443: connect: connection refused E0706 06:55:23.147040 1 reflector.go:201] github.com/coreos/flannel/subnet/kube/kube.go:310: Failed to list *v1.Node: Get https://10.96.0.1:443/api/v1/nodes?resourceVersion=0: dial tcp 10.96.0.1:443: connect: connection refused E0706 06:55:24.148350 1 reflector.go:201] github.com/coreos/flannel/subnet/kube/kube.go:310: Failed to list *v1.Node: Get https://10.96.0.1:443/api/v1/nodes?resourceVersion=0: dial tcp 10.96.0.1:443: connect: connection refused E0706 06:55:25.247352 1 reflector.go:201] github.com/coreos/flannel/subnet/kube/kube.go:310: Failed to list *v1.Node: Get https://10.96.0.1:443/api/v1/nodes?resourceVersion=0: dial tcp 10.96.0.1:443: connect: connection refused E0706 06:55:26.248831 1 reflector.go:201] github.com/coreos/flannel/subnet/kube/kube.go:310: Failed to list *v1.Node: Get https://10.96.0.1:443/api/v1/nodes?resourceVersion=0: dial tcp 10.96.0.1:443: connect: connection refused E0706 06:55:27.347224 1 reflector.go:201] github.com/coreos/flannel/subnet/kube/kube.go:310: Failed to list *v1.Node: Get https://10.96.0.1:443/api/v1/nodes?resourceVersion=0: dial tcp 10.96.0.1:443: connect: connection refused E0706 06:55:28.348182 1 reflector.go:201] github.com/coreos/flannel/subnet/kube/kube.go:310: Failed to list *v1.Node: Get https://10.96.0.1:443/api/v1/nodes?resourceVersion=0: dial tcp 10.96.0.1:443: connect: connection refused E0706 06:55:29.350578 1 reflector.go:201] github.com/coreos/flannel/subnet/kube/kube.go:310: Failed to list *v1.Node: Get https://10.96.0.1:443/api/v1/nodes?resourceVersion=0: dial tcp 10.96.0.1:443: connect: connection refused ... |
如果你发现某个 pod 的服务有问题,但是状态还是显示Running
,就可以使用kubectl logs
来查看其详细日志。
kubectl create 创建资源
k8s 中的所有东西都可以通过kubectl create
命令创建,无论你是想创建一个 pod 还是一个大型的滚动升级服务deployment
,create
命令都可以做到。使用create
生成一个资源主要有两种常用方法,从yaml
配置文件创建 和 简易创建:
从yaml
配置文件创建
如果你想让 k8s 生成一个和你想象中一模一样的资源,那你就要充分而详细的描述这个资源,k8s 就提供了这么一个方法,你可以使用yaml
格式创建一个文件,按照 k8s 指定好的结构定义一个对象,然后使用如下方法将该文件传递给 k8s。它就可以按照你的描述进行生成了:
1 | kubectl create -f <配置文件名.yaml> |
例如,使用下面的配置文件就可以创建一个最简单的 pod:
kubia-manual.yaml
1 2 3 4 5 6 7 8 9 10 11 | apiVersion: v1 kind: Pod metadata: name: kubia-manual spec: containers: - image: luksa/kubia name: kubia ports: - containerPort: 8080 protocol: TCP |
然后使用kubectl create -f kubia-manual.yaml
即可创建
1 2 | root@master1:~/k8s-yaml## k create -f kubia-manual.yaml pod/kubia-manual created |
如果你的配置文件有问题的话那么 k8s 就会报错,如下,错误一般都是拼写导致的,比如下面这个就是Pod.spec.containers[0].ports[0]
中存在一个无法识别的名称contaienrPort
:
1 2 3 4 5 | root@master1:~/k8s-yaml## k create -f kubia-manual.yaml error: error validating "kubia-manual.yaml": error validating data: [ValidationError(Pod.spec.containers[0].ports[0]): unknown field "contaienrPort" in io.k8s.api.core.v1.ContainerPort, ValidationError(Pod.spec.containers[0].ports[0]): missing required field "containerPort" in io.k8s.api.core.v1.ContainerPort]; if you choose to ignore these errors, turn validation off with --validate=false |
这时你可能会问了,这配置文件里一大堆名字我看不懂啊,不要着急,下一条命令就会解答这个疑惑,但是在此之前,我们先来看一下更简单的 简易创建 模式。
简易创建
k8s 为一些常用的资源提供了简易创建的方法,比如说service
、namespace
、deployment
等,这些方法可以使用kubectl create <资源类型> <资源名>
的方式创建。例如我想创建一个名叫hello-world
的命名空间,直接使用下面命令即可:
1 | kubectl create namespace hello-world |
这样就不用再跟大而全的配置文件打交道了,如果你想了解都有哪些资源可以快速生成的话,使用kubectl create -h
命令查看。
kubectl create
可以通过指定-f <配置文件名.yaml>
参数来从一个yaml
文件生成资源,也可用使用kubectl create <资源类型> <资源名>
来快速生成一个资源。
kubectl explain 解释配置
从上一小节中我们可以知道,k8s 可以通过配置文件来生成资源,而为了尽可能详细的描述资源的模样,k8s 提供了数量庞大的配置项,那么有没有一种方式可以快速的了解到某个配置项的作用呢?有,那就是explain
(解释)命令。
1 | kubectl explain <配置名> |
咱们来实践一下,翻到上一小节里提到的生成 pod 的配置文件。首先,我想要了解创建 pod 的哪些基本属性都是干什么的,输入kubectl explain pod
即可:
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 | root@master1:~/k8s-yaml## kubectl explain pod KIND: Pod VERSION: v1 DESCRIPTION: Pod is a collection of containers that can run on a host. This resource is created by clients and scheduled onto hosts. FIELDS: apiVersion <string> APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources kind <string> Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds metadata <Object> Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata spec <Object> Specification of the desired behavior of the pod. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status status <Object> Most recently observed status of the pod. This data may not be up to date. Populated by the system. Read-only. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status |
可以看到,给出的解释非常详细,并且每个解释的最后都附带了一条链接,便于更加深入的进行了解,好了,那我想要了解matedata
(元数据)字段都有哪些配置项怎么办呢?
1 | kubectl explain pod.matedata |
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 | root@master1:~/k8s-yaml## kubectl explain pod.metadata KIND: Pod VERSION: v1 RESOURCE: metadata <Object> DESCRIPTION: Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata ObjectMeta is metadata that all persisted resources must have, which includes all objects users must create. FIELDS: annotations <map[string]string> Annotations is an unstructured key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. They are not queryable and should be preserved when modifying objects. More info: http://kubernetes.io/docs/user-guide/annotations clusterName <string> The name of the cluster which the object belongs to. This is used to distinguish resources with same name and namespace in different clusters. This field is not set anywhere right now and apiserver is going to ignore it if set in create or update request. ... |
又是一排十分详细的解释,通过这种方式,我们可以了解到每一个资源的每一个配置项。想了解某个属性的子属性,就加个.
继续查。不要说看不懂,我觉得 谷歌翻译 这种东西已经挺常见了。
kubectl delete 删除一切
delete
命令的使用非常简单,如下:
1 | kubectl delete <资源类型> <资源名> |
比如说你想删除一个名为kubia-4n2tg
的 pod。就可以这么写:
1 | kubectl delete pod kubia-4n2tg |
如果你想删除所有的 pod,就可以这么写:
1 | kubectl delete pod --all |
如果你想删除一切!那就这么写:
1 | kubectl delete all --all |
注意!执行删除一切命令没有二次验证,所有资源均会被直接删除,在执行前先考虑下跑路成本。
kubectl edit 修改配置
如果在日常维护过程中,因为某些原因我们需要变更一些服务的设置该怎么办呢?从创建新资源小节我们可以了解到,每个资源都是通过一个yaml
配置文件生成的,哪怕是简易创建的资源,也是 k8s 从一个默认的配置文件创建而来的。
我们可以在get
命令后附加-o yaml
文件查看某个现有资源的配置项。例如,查看 pod kubia-manual
的配置项:
1 | kubectl get pod kubia-manual -o yaml |
执行之后就可以看到一个很长的配置列表,你也可以试一下自己创建的 pod 的配置项,你会发现同样很长,这就是因为 k8s 会读取你提供的信息,并将必要但是你没有提供的其他信息设为默认值填写进去。而kubectl edit
就可以编辑刚才打开的这个列表。例如,编辑在create
小节中创建的 pod kubia-manual
。
1 | kubectl edit pod kubia-manual |
之后就会弹出系统设置的默认编辑器。这时我们就可以做任意修改,例如将名称改为kubia-manual-v2
。首先定位到metadata.name
字段,然后修改他的值:
1 2 3 4 5 6 7 8 9 10 11 | apiVersion: v1 kind: Pod metadata: creationTimestamp: "2019-07-07T07:31:11Z" name: kubia-manual ## > kubia-manual-v2 namespace: default resourceVersion: "790349" selfLink: /api/v1/namespaces/default/pods/kubia-manual uid: 51eaa1e6-5749-4e79-aec9-12cf2a3e485d spec: ... |
修改完成后输入:wq
保存,随后你会发现, k8s 居然报错了
1 2 | A copy of your changes has been stored to "/tmp/kubectl-edit-vj0ts.yaml" error: At least one of apiVersion, kind and name was changed |
不要着急,这个是 k8s 做出的限制,你无法修改一个运行中资源的名称或类型。那我们就来修改一下他的其他属性好了。例如将拉取镜像的标签指定为latest
。重新edit
配置文件,找到spec。containers.image
字段,然后在最后添加:latest
后保存。随后 k8s 会弹出保存成功,如下:
1 | pod/kubia-manual edited |
这时我们再kubectl describe pod kubia-manual
查看该 pod 的详情,就可以发现对应的字段已经更新了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | Name: kubia-manual Namespace: default Priority: 0 Node: worker1/192.168.56.21 Start Time: Sun, 07 Jul 2019 07:31:11 +0000 Labels: <none> Annotations: <none> Status: Running IP: 10.244.1.14 Containers: kubia: Container ID: docker://89617ffcc9b1455c514e5129a9b2694c43a2aff9b4c0449d5efc4aea1fe41db6 ## 已经显式的应用了 latest 标签 Image: luksa/kubia:latest Image ID: docker-pullable://luksa/kubia@sha256:3f28e304dc0f63dc30f273a4202096f0fa0d08510bd2ee7e1032ce600616de24 Port: 8080/TCP |
kubectl edit <资源类型> <资源名>
可以编辑一个资源的具体配置项,更详细的文档请参考 k8s 中文网 - kubectl edit 。edit
命令在实际使用中更偏向于人工修改某个配置项来解决问题,例如修改镜像地址解决拉取不到镜像的问题。更常用的编辑命令请参见下一节kubectl apply
。
kubectl apply 应用配置
上一节我们知道了一个简单快捷的编辑配置方法kubectl edit
,但是如果我们想对资源进行大范围的修改呢?总不能打开配置项一个一个手动修改吧。这时候就可以用到我们的kubectl apply
命令了。基本用法如下:
1 | kubectl apply -f <新配置文件名.yaml> |
kubeclt apply
可以说是edit
命令的升级版,它和edit
最大的区别就是,apply
接受一个yaml
配置文件,而不是打开一个编辑器去修改。k8s 在接受到这个配置文件后,会根据metadata
中的元数据来查找目标资源,如果没有的话则直接新建,如果找到的话就依次比对配置文件之间有什么不同点,然后应用不同的配置。
这么做的好处有很多,例如你通过kubectl apply -f https://some-network-site/resourse.yaml
命令从一个网站上部署了你的资源,这样当它的管理者更新了这个配置文件后,你只需要再次执行这个命令就可以应用更新后的内容了,而且完全不用关心修改了哪些配置项。
除了修改手段不同以外,apply
命令的行为和edit
保持一致,你可以访问 k8s 中文网 - kubectl apply 来查看更多用法。