0%

kubectl命令——资源对象增删查改篇

K8S资源对象是啥?

在 Kubernetes 系统中,Kubernetes 对象 是持久化的实体。 Kubernetes 使用这些实体去表示整个集群的状态,具体包括pod、replicaset、deployment、service、configmap、secret等等。

参考文档:

资源对象管理方式

资源对象的管理有三种方式:指令式命令、指令式对象配置和声明式对象配置。
其中,指令式对象配置和声明式对象配置都要依赖资源对象的yaml/json定义文件。

指令式命令

使用指令式命令时,用户可以在集群中的活动对象上进行操作。用户将操作传给 kubectl 命令作为参数或标志。
这是开始或者在集群中运行一次性任务的推荐方法。因为这种方式直接在活跃对象上操作,所以它不提供以前配置的历史记录。
例如,创建一个nginx deployment:

1
kubectl create deployment nginx --image nginx

指令式对象配置

在指令式对象配置中,kubectl 命令指定操作(创建、更新和删除),可选标志和至少一个文件名。指定的文件必须包含 YAML 或 JSON 格式的对象的完整定义。
例如,创建配置文件中定义的对象(前提是写好了nginx.yaml):

1
kubectl create -f nginx.yaml

通过覆盖更新配置文件中定义的对象:

1
kubectl replace -f nginx.yaml

删除两个配置文件中定义的对象:

1
kubectl delete -f nginx.yaml -f redis.yaml

声明式对象配置

使用声明式对象配置时,用户对本地存储的对象配置文件进行操作,但是用户未定义要对该文件执行的操作。 kubectl 会自动检测每个文件的创建、更新和删除操作。这使得配置可以在目录上工作,根据目录中配置文件对不同的对象执行不同的操作。
例如,处理 configs 目录中的所有对象配置文件,创建并更新活跃对象。
可以首先使用 diff 子命令查看将要进行的更改,然后再进行应用:

1
2
kubectl diff -f configs/
kubectl apply -f configs/

与指令式对象配置相比的优点:

  • 对活动对象所做的更改即使未合并到配置文件中,也会被保留下来。
  • 声明性对象配置更好地支持对目录进行操作并自动检测每个文件的操作类型(创建,更新,删除)。

与指令式对象配置相比的缺点:

  • 声明式对象配置难于调试并且出现异常时结果难以理解。
  • 使用 diff 产生的部分更新会创建复杂的合并和补丁操作。

资源对象yaml/json文件详解

yaml/json文件构成

k8s资源对象的yaml文件分成四部分,apiVersion、kind、metadata和spec。

  • apiVersion和kind是关联的,参考kubectl api-resources
  • metadata必填name、namespace、labels。
  • pod.spec主要填containers的name和image;deployment.spec主要填replicas、template和selector;service.spec主要填selector、ports和type。

yaml/json编写

编写k8s资源对象的yaml/json文件,有三种方法:

  • 纯手工编写(难度最高)
  • 使用--dry-run生成yaml/json文件,然后修改
  • 从线上导出yaml/json文件,然后修改

生成文件模板

生成deployment的yaml/json文件模板(推荐):

1
2
kubectl create deployment vk-deploy --image=nginx --dry-run -o yaml > deploy-name.yaml
kubectl create deployment vk-deploy --image=nginx --dry-run -o json > deploy-name.json

更多内容,参考Kubernetes kubectl create deployment 命令详解

注意,我们并不需要在deployment中指定容器对外暴露的ports,因为该字段只是一个提示作用。

List of ports to expose from the container. Exposing a port here gives the system additional information about the network connections a container uses, but is primarily informational. Not specifying a port here DOES NOT prevent that port from being exposed. Any port which is listening on the default “0.0.0.0” address inside a container will be accessible from the network. Cannot be updated.

生成deployment的yaml文件模板(即将废弃):

1
kubectl run vk-deploy --image=nginx --dry-run -o yaml

会出现提示:
kubectl run –generator=deployment/apps.v1 is DEPRECATED and will be removed in a future version. Use kubectl run –generator=run-pod/v1 or kubectl create instead.
因为官方不推荐使用 run-pod/v1 以外的其他生成器,其他生成器不久后就会弃用。更多内容参考kubectl run

导出文件模板

从K8S集群中导出已经存在的资源对象的yaml文件(即将废弃):

1
kubectl get deploy/deployment-name -o yaml --export > deploy-name.yaml

也会出现提示:
Flag –export has been deprecated, This flag is deprecated and will be removed in future.
很尴尬,–export 也要弃用了,且用且珍惜吧。

yaml/json验证

1
kubectl create --validate -f deploy-name.yaml --dry-run=client

需要注意的是,--dry-run=client参数要带着,否则验证成功后,这个文件直接就提交给k8s了。

yaml/json帮助

编写yaml文件的过程中,如果忘记了某些结构和字段,可以使用kubectl explain命令来获取帮助。

1、查看资源包含哪些字段
以查看deployment的yaml包含哪些字段为例:

1
2
kubectl explain deployment
kubectl explain deployment --api-version=apps/v1

2、查看子字段
以查看节点亲和性字段为例:

1
2
3
4
kubectl explain deployment.spec.template.spec.affinity
kubectl explain deployment.spec.template.spec.affinity.nodeAffinity
...
kubectl explain deployment.spec.template.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms.matchExpressions

pod yaml

生成pod的yaml文件模板比较常用,这里单独做一下记录。

1
2
3
4
5
6
kubectl run vkpod --image=busybox --restart=Never --dry-run=client -oyaml

kubectl run vk-pod --image=busybox --dry-run=client -o yaml --command -- sleep 1000

kubectl run vk-pod --image=busybox -l 'name=vk-pod,env=dev' --dry-run=client -o yaml
kubectl run vk-pod --image=busybox --labels='name=vk-pod,env=dev' --dry-run=client -o yaml

更多内容,参考Kubernetes kubectl run 命令详解kubectl 的用法约定

查看资源对象

查看可用api版本

1
kubectl api-versions

查看资源缩写

1
2
kubectl describe
kubectl api-resources

建议记住常用资源的SHORTNAMES,可以提升输入效率。
此外,记住常用资源的APIGROUP,可以提高编写yaml文件时的效率。

查看所有资源对象

1
2
kubectl get all
kubectl get all -o wide

根据label筛选资源对象

1
kubectl get all -l 'env=dev'

查看指定的资源对象

以deployment资源对象为例,其他资源对象操作方法相同。

查看所有空间的所有deployment,deployment可以缩写为deploy

1
kubectl get deployment --all-namespaces

查看指定空间下的所有deployment,默认空间default

1
2
3
kubectl get deploy
kubectl get deploy -n voidking
kubectl get deploy -n voidking -o wide

查看deployment,显示label

1
kubectl get deploy --show-labels

根据label筛选deployment

1
2
3
kubectl get deploy -l 'env=dev'
kubectl get deploy --selector='env=dev'
kubectl get deploy --selector="env=dev,type=frontend"

查看指定的deployment

1
2
3
kubectl get deploy/deployment-name
kubectl get deploy/deployment-name -o wide
kubectl get deploy/deployment-name -o yaml

查看deployment详细信息

1
kubectl describe deploy/deployment-name

查看deployment实时变化

1
kubectl get deploy/deployment-name --watch

创建资源对象

以deployment资源对象为例,其他资源对象操作方法相同。

指令式命令

1
kubectl create deployment vk-deploy --image=nginx

指令式对象配置

指令式对象配置,需要依赖定义好的资源对象yaml文件。

1
kubectl create -f deploy.yaml

声明式对象配置

和指令式对象配置唯一不同的是,kubectl create 改为 kubectl apply

更新资源对象

以deployment资源对象为例,其他资源对象操作方法相同。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 编辑集群中的资源
kubectl edit deployment deployment-name

# 比较manifest与集群中当前资源的不同
kubectl diff -f deploy.yaml

# 应用最新定义
kubectl replace -f deploy.yaml
kubectl apply -f deploy.yaml

# 添加label
kubectl label deployment deployment-name new-label=awesome

# 添加annotation
kubectl annotate deployment deployment-name icon-url=http://goo.gl/XXBTWq

# 部分修改deployment
kubectl patch deployment deployment-name --type json -p='[{"op": "remove", "path": "/spec/template/spec/containers/0/livenessProbe"}]'

删除资源对象

以deployment资源对象为例,其他资源对象操作方法相同。

1
kubectl delete deployment deployment-name

扩缩容

扩缩容针对pod对象,需要操作deployment对象。

方法一:扩缩容命令。

1
kubectl scale --replicas=2 deployment deployment-name

方法二:更新yaml文件。

重启pod

k8s中,没有pod重启命令,只有pod重建命理。
而我们配置的pod重启策略,本质上也是重建pod,只不过pod名称相同,保留了event记录。

验证方法:
创建一个100秒重启的pod,启动后在其中创建一个文件。
当pod重启后,文件消失,pod在宿主机上对应的容器id也全部改变了。

重建pod

参考文档Using Kubectl to Restart a Kubernetes Pod

方法一:删除pod并重建

1
kubectl get pod <pod_name> -n <namespace> -o yaml | kubectl replace --force -f -

方法二:删除pod利用保活重建(前提是有replicaset)

1
kubectl delete pod <pod_name> -n <namespace>

方法三:通过扩缩实现重建pod

1
2
kubectl scale deployment <deployment_name> --replicas=0 -n <namespace>
kubectl scale deployment <deployment_name> --replicas=2 -n <namespace>

方法四:通过rollout实现重建pod

1
kubectl rollout restart deployment <deployment_name> -n <namespace>

方法五:通过docker停止容器实现重建pod
前提是保证pod的重启策略是Always。
登录到pod所在宿主机,通过docker命令停止pod的pause容器。

1
2
docker ps | grep xxx
docker stop yyy

pause容器被停止后,kubectl get pods xxx看到的是pod重启。
kubectl describe pod xxx会看到:
Pod xxx changed, it will be killed and re-created.
是的,实际上pod的所有容器都会被重建。

创建service/暴露服务

命令式指令

为deployment创建clusterip,暴露clusterip的80端口,对应pod的80端口

1
kubectl expose deployment deployment-name --port=80 --name svc-name

为deployment创建clusterip,暴露clusterip的6789端口,对应pod的80端口

1
2
kubectl expose deployment deployment-name --target-port=80 --port=6789
kubectl expose -f vk-deploy.yaml --target-port=80 --port=6789

创建nodeport,暴露clusterip的80端口,对应pod的80端口,暴露node的随机端口

1
kubectl expose deployment deployment-name --port=80 --type=NodePort --name svc-name

创建clusterip,暴露clusterip的80端口,对应pod的80端口

1
kubectl create service clusterip svc-name --tcp=80:80

创建nodeport,暴露clusterip的80端口,对应pod的pod端口,暴露node的30080端口

1
kubectl create service nodeport svc-name --tcp=80:80 --node-port=30080

命令式配置文件

生成service的yaml文件模板(推荐方法):

1
kubectl create service clusterip vk-svc --tcp="5678:80" --dry-run -o yaml > service.yaml

创建service

1
kubectl create -f service.yaml

更多内容,参考Kubernetes kubectl create service 命令详解Service

声明式配置文件

创建service

1
kubectl apply -f service.yaml

kubectl port-forward

对外暴露服务,我们会使用nodeport或者loadbalance类型的service。
如果是临时测试,还可以使用kubectl port-forward

kubectl port-forward 通过端口转发映射本地端口到指定的应用端口,从而访问集群中的应用程序。

1
2
3
4
5
6
7
# 本地端口映射pod端口
kubectl port-forward pod/$pod_name -n $namespace $node_port:$pod_port
kubectl port-forward pod/$pod_name -n $namespace --address 0.0.0.0 $node_port:$pod_port

# 本地端口映射service端口
kubectl port-forward service/$service_name -n $namespace $node_port:$service_port
kubectl port-forward service/$service_name -n $namespace --address 0.0.0.0 $node_port:$service_port

版本回退

1
2
3
4
5
6
# 查看发布历史
kubectl rollout history deployment deployment-name
# 查看发布状态
kubectl rollout status deployment deployment-name
# 回退到上一个版本
kubectl rollout undo deployment deployment-name

rollout表示roll out,这里翻译为发布

configmap和secret

1、创建configmap

1
2
kubectl create configmap special-config --from-literal=special.how=very --from-literal=special.type=charm
kubectl create configmap game-config-3 --from-file=<my-key-name>=<path-to-file>

2、创建secret

1
2
3
4
5
6
7
8
9
10
# 在命令中指定key和value
kubectl create secret generic db-user-pass --from-literal=username=voidking --from-literal=password='vkpassword'
kubectl get secret db-user-pass -o yaml

# 在文件中指定value
echo -n 'voidking' > ./username.txt
echo -n 'vkpassword' > ./password.txt
kubectl create secret generic db-user-pass --from-file=./username.txt --from-file=./password.txt
kubectl create secret generic db-user-pass --from-file=username=./username.txt --from-file=password=./password.txt
kubectl get secret db-user-pass -o yaml

在yaml文件中看到的username和password,都是经过base64加密的字符串。

1
2
3
4
# 加密
echo -n 'voidking' | base64
# 解密
echo 'dm9pZGtpbmc=' | base64 --decode

创建多个资源

如果要创建ns,然后在ns中创建configmap,最后创建deployment(依赖configmap),该怎么操作?
方法一:挨个apply

1
2
3
kubectl apply -f ns.yaml
kubectl apply -f cm.yaml
kubectl apply -f deploy.yaml

方法二:按顺序合并,然后apply

1
2
cat ns.yaml <(echo "---") cm.yaml <(echo "---") deploy.yaml > ns-cm-deploy.yaml
kubecl apply -f ns-cm-deploy.yaml

方法三:多次apply

1
2
kubectl apply -f .
kubectl apply -f .

方法四:添加编号

1
2
3
4
mv ns.yaml 00-ns.yaml
mv cm.yaml 01-cm.yaml
mv deploy.yaml 02-deploy.yaml
kubectl apply -f .

Kustomize

Kustomize简介

Kustomize是一个独立的工具,用来通过kustomization文件定制Kubernetes对象。
从 1.14 版本开始,kubectl 也开始支持使用 kustomization 文件来管理 Kubernetes 对象。 要查看包含 kustomization 文件的目录中的资源,执行下面的命令:

1
kubectl kustomize <kustomization_directory>

要应用这些资源,使用 –kustomize 或 -k 参数来执行 kubectl apply:

1
kubectl apply -k <kustomization_directory>

Kustomize作用

生成资源

ConfigMap 和 Secret 包含其他 Kubernetes 对象(如 Pod)所需要的配置或敏感数据。 ConfigMap 或 Secret 中数据的来源往往是集群外部,例如某个 .properties 文件或者 SSH 密钥文件。 Kustomize 提供 secretGeneratorconfigMapGenerator,可以基于文件或字面值来生成 Secret 和 ConfigMap。

设置贯穿性字段

在项目中为所有 Kubernetes 对象设置贯穿性字段是一种常见操作。 贯穿性字段的一些使用场景如下:

  • 为所有资源设置相同的名字空间
  • 为所有对象添加相同的前缀或后缀
  • 为对象添加相同的标签集合
  • 为对象添加相同的注解集合

组织和定制资源

一种常见的做法是在项目中构造资源集合并将其放到同一个文件或目录中管理。Kustomize提供基于不同文件来组织资源并向其应用补丁或者其他定制的能力。

Kustomize 支持组合不同的资源。kustomization.yaml 文件的 resources 字段定义配置中要包含的资源列表。 我们可以将 resources 列表中的路径设置为资源配置文件的路径。

补丁文件(Patches)可以用来对资源执行不同的定制。 Kustomize 通过 patchesStrategicMerge 和 patchesJson6902 支持不同的打补丁机制。 patchesStrategicMerge 的内容是一个文件路径的列表,其中每个文件都应可解析为 策略性合并补丁(Strategic Merge Patch)。 补丁文件中的名称必须与已经加载的资源的名称匹配。 建议构造规模较小的、仅做一件事情的补丁。 例如,构造一个补丁来增加 Deployment 的副本个数;构造另外一个补丁来设置内存限制。

参考文档

  • 本文作者: 好好学习的郝
  • 本文链接: https://www.voidking.com/dev-kubectl-curd/
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!源站会及时更新知识点及修正错误,阅读体验也更好。欢迎分享,欢迎收藏~