Kubernetes基础 ( 2 ) - 资源清单

一、概述

1.1 描述文件

k8s常用资源:[1]

1.2 资源清单

类似通过Dockerfile来表示容器的创建过程,k8s里的各种资源也可以通过文本的方式来创建,通常是通过Yaml方式来定义,也支持Json。不同类型资源的资源清单字段会有部分差异,本文档主要介绍资源清单的通用用法,对具体资源的资源清单在后续使用到的地方在进行介绍。

二、Yaml示例

同样,先来看示例。

前一篇中用kubectl run的方式启动成功了,但这并不是常用方式,通常还是通过资源清单的方式创建。来看看示例,第一条命令:

2.1 创建deploy

$ kubectl run itopic --image=pengbotao/itopic.go:alpine --replicas=3 --port=8001

对应编写itopic.yaml(镜像为本博客镜像,可直接替换为Nginx镜像),文件内容如下:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: itopic-deploy
  namespace: default
  labels:
    app: itopic
spec:
  replicas: 3
  selector:
    matchLabels:
      app: itopic
  template:
    metadata:
      labels:
        app: itopic
    spec:
      containers:
      - name: itopic
        image: pengbotao/itopic.go:alpine
        resources:
          limits:
            memory: "128Mi"
            cpu: "500m"
        ports:
        - containerPort: 8001

然后执行:

$ kubectl apply -f itopic.yaml

这样DeploymentReplicaSetPod就创建好了。

2.2 创建service

第二条命令,创建service

$ kubectl expose deployment itopic --type=LoadBalancer --port=38001 --target-port=8001

对应编写itopic-svc.yaml,然后执行:kubectl apply -f itopic-svc.yaml

apiVersion: v1
kind: Service
metadata:
  name: itopic-svc
  labels:
    app: itopic-svc
spec:
  type: LoadBalancer
  selector:
    app: itopic
  ports:
  - port: 38002
    targetPort: 8001

这两个步骤完成后,就可以访问http://localhost:38002了。上面就是资源清单的基本写法,接下来对资源清单的用法做一些介绍。

三、Yaml基础字段

配置清单的写法如上面示例,不同的资源对象大同小异,通过kubectl explain pod的方式可以查看对应资源的说明文档,要看子节点可以用:kubectl explain pod.spec所有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/sig-architecture/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/sig-architecture/api-conventions.md#types-kinds

   metadata	<Object>
     Standard object's metadata. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata

   spec	<Object>
     Specification of the desired behavior of the pod. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/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/sig-architecture/api-conventions.md#spec-and-status

上面是以Pod为例,也可以看看其他的资源,比如kubectl explain deployment,但主结构基本相同。通过上面看到,基础的Yaml格式如下,可以对照前面的示例进行查看,接下来主要介绍Yaml里的语法规则,主结构:

参数名 字段类型 说明
apiVersion String k8s API的版本,可配合前面的kubectl api-versions查看
kind String 定义的资源类型,比如DeploymentPod
metadata Object 元数据对象
spec Object 详细定义对象

3.1 apiVersion

用来指定调用资源接口的版本,通过$ kubectl api-versions可以获取到所有支持的版本。通过explain也可以看到版本号。

$ kubectl explain deployment
KIND:     Deployment
VERSION:  apps/v1

3.2 kind

定义的资源类型。比如: DeploymentPod,通过explain也可以看到。查询的时候有些简写可以直接使用,比如:kubectl get deploy,但kind这里不行,

$ kubectl apply -f itopic.yaml
error: unable to recognize "itopic.yaml": no matches for kind "deploy" in version "apps/v1"

确保值和kubectl explain查看出来的一致就行。

3.3 metadata

用来定义资源自身的信息,包括资源的名称、所在的名称空间,打上什么标签。

参数名 字段类型 说明
metadata Object 元数据对象
metadata.name String 元数据对象的名称
metadata.namespace String 元数据对象的名称空间,默认为default
metadata.labels Object 自定义键值对,配合Selector使用
metadata.annotations Object 自定义注解

3.4 spec

资源信息,不同的资源对象描述信息有所不同,Pod信息有:

参数名 字段类型 说明
spec Object 详细定义对象
spec.initContainers[] List 初始化容器
spec.containers[] List 定义容器列表
spec.restartPolicy String 定义Pod重启策略,可选值:Always、Onfailure、Never,默认为Always
- Always:Pod一旦终止则理解重启
- Onfailure:非正常退出才重启(Code非0)
- Never:不重启
spec.volumes[] List 存储卷

四、Yaml解读

4.1 名称空间

4.1.1 说明

一个Kubernetes集群可以有多个名称空间,逻辑上隔离,绝大部分资源对象都是名称空间级别下的。前面的操作都没有带名称空间,默认是使用的default名称空间,一个名称空间下只能有一个同名的deploy,跨名称空间就没有这个限制了。

4.1.2 获取名称空间

$ kubectl get ns
NAME                   STATUS   AGE
default                Active   4d23h
docker                 Active   4d23h
kube-node-lease        Active   4d23h
kube-public            Active   4d23h
kube-system            Active   4d23h
kubernetes-dashboard   Active   4d23h

4.1.3 创建/删除名称空间

$ kubectl create ns test

$ kubectl -n test apply -f nginx.yaml
deployment.apps/nginx-deploy created

$ kubectl -n test get pod
NAME                            READY   STATUS    RESTARTS   AGE
nginx-deploy-6c44fdc7bb-jnj75   1/1     Running   0          32s
nginx-deploy-6c44fdc7bb-m7bvh   1/1     Running   0          32s
nginx-deploy-6c44fdc7bb-mp28r   1/1     Running   0          32s

$ kubectl delete ns test

4.2 Label / Selector

Label(标签)是Kubernetes系统中一个核心概念。一个Label是一个key=value的键值对,其中keyvalue由用户自己指定。Label可以被附加到各种资源对象上,例如NodePodServiceRS等,一个资源对象可以定义任意数量的Label,同一个Label也可以被添加到任意数量的资源对象上。Label通常在资源对象定义时确定,也可以在对象创建后动态添加或者删除。[2]

打好标签之后就可以通过Label Selector(标签选择器)查询和筛选某些Label的资源对象。

4.2.1 基于等式(Equality-based)的Selector

定义一个Deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deploy
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx-tpl-label
  template:
    metadata:
      labels:
        app: nginx-tpl-label
    spec:
      containers:
      - name: nginx-pod
        image: nginx:1.19.2-alpine

来看看这个文件, 定义了一个Deploymentmetadata下定义名字为nginx-deploy,这里没有给Deployment打标签,但注意如果定义标签是Deployment的标签,供其他地方做筛选。很多资源清单里这个标签和下面两个一致,但也需要弄清楚这个标签的作用。

看来看看service如何关联Pod

apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
spec:
  selector:
    app: nginx-tpl-label
  type: LoadBalancer
  ports:
  - port: 38003
    targetPort: 80
    protocol: TCP

前面没有给deployment打标签,通过Deployment创建的RSpod会打上nginx-tpl-label标签,service的selector相当于筛选 app = nginx-tpl-labelpod,如:

$ kubectl get pod --show-labels
NAME                            READY   STATUS    RESTARTS   AGE    LABELS
itopic-6f9dd4f4cd-6n6lp         1/1     Running   0          5d1h   pod-template-hash=6f9dd4f4cd,run=itopic
itopic-6f9dd4f4cd-8tvgq         1/1     Running   0          5d1h   pod-template-hash=6f9dd4f4cd,run=itopic
itopic-6f9dd4f4cd-l65f4         1/1     Running   0          5d1h   pod-template-hash=6f9dd4f4cd,run=itopic
nginx-deploy-6c44fdc7bb-5d8bn   1/1     Running   0          21m    app=nginx-tpl-label,pod-template-hash=6c44fdc7bb
nginx-deploy-6c44fdc7bb-mjzn5   1/1     Running   0          21m    app=nginx-tpl-label,pod-template-hash=6c44fdc7bb
nginx-deploy-6c44fdc7bb-vd5gg   1/1     Running   0          21m    app=nginx-tpl-label,pod-template-hash=6c44fdc7bb


$ kubectl get pod --show-labels -l app!=nginx-tpl-label
NAME                      READY   STATUS    RESTARTS   AGE    LABELS
itopic-6f9dd4f4cd-6n6lp   1/1     Running   0          5d1h   pod-template-hash=6f9dd4f4cd,run=itopic
itopic-6f9dd4f4cd-8tvgq   1/1     Running   0          5d1h   pod-template-hash=6f9dd4f4cd,run=itopic
itopic-6f9dd4f4cd-l65f4   1/1     Running   0          5d1h   pod-template-hash=6f9dd4f4cd,run=itopic


$ kubectl get pod --show-labels -l app!=nginx-tpl-label,run=test
No resources found in default namespace.


$ kubectl get pod --show-labels -l app!=nginx-tpl-label,run=itopic
NAME                      READY   STATUS    RESTARTS   AGE    LABELS
itopic-6f9dd4f4cd-6n6lp   1/1     Running   0          5d1h   pod-template-hash=6f9dd4f4cd,run=itopic
itopic-6f9dd4f4cd-8tvgq   1/1     Running   0          5d1h   pod-template-hash=6f9dd4f4cd,run=itopic
itopic-6f9dd4f4cd-l65f4   1/1     Running   0          5d1h   pod-template-hash=6f9dd4f4cd,run=itopic

4.2.2 基于集合(Set-based)的Selector

......
spec:
  selector:
    matchLabels:
      app: myweb
    matchExpressions;
      - {key: tier, operator: In, values: [frontend]}
      - {key: environment, operator: NotIn, values: [dev]}

前一篇中说的RS支持集合式selectorRC不支持,就是说的这里。

五、日常操作

日常操作上除了可以通过资源清单的方式操作,也可以通过kubectl命令来进行操作。

5.1 创建资源

kubectl apply -f x.yamlkubectl create -f x.yaml

区别:都可以创建资源,如果存在则create报错,apply会根据新的文件进行更新。

5.2 修改资源

日常修改操作有以下三种:

5.2.1 修改资源清单文件

操作都可以通过修改资源文件并重新应用生效,前提是资源清单文件还存在。

kubectl apply -f x.yaml

5.2.2 通过kubectl edit命令修改

$ kubectl edit deploy nginx-deploy
deployment.apps/nginx-deploy edited

找不到文件时这么修改,但需要注意这里面存储的比较完整的信息,同一个字段可能有多处,修改起来别改漏了字段。

5.2.3 通过kubect命令修改

后续的章节都是直接通过命令的方式进行修改。使用上保持一致性,以免出现通过命令改了,资源清单文件没有更新,后续又使用资源清单文件做更新。建议统一通过资源清单文件进行修改。

5.3 打标签

修改资源清单中的labels字段,也可以通过kubectl操作。各种资源对象都可以操作标签,以deploy为例。

$ kubectl get deploy --show-labels
NAME            READY   UP-TO-DATE   AVAILABLE   AGE     LABELS
itopic-deploy   3/3     3            3           7h5m    app=itopic

# 增加标签
$ kubectl label deploy itopic-deploy env=test
deployment.apps/itopic-deploy labeled

$ kubectl get deploy --show-labels
NAME            READY   UP-TO-DATE   AVAILABLE   AGE     LABELS
itopic-deploy   3/3     3            3           7h7m    app=itopic,env=test

# 修改env标签
$ kubectl label deploy itopic-deploy env=qa --overwrite

# 删除env标签
$ kubectl label deploy itopic-deploy env-

5.4 删除资源

可以通过kubectl delete deploy itopic-deploy的方式删除deploy,同修改类似,也可以直接指定yaml文件的方式来删除。

$ kubectl delete -f itopic.yaml
deployment.apps "itopic-deploy" deleted

$ kubectl delete -f itopic-svc.yaml
service "itopic-svc" deleted

也可以根据标签删除

$ kubectl delete pod -l app=itopic

5.5 扩展资源

修改副本数量,调整Yaml中的replicas或者:

kubectl scale -n default deployment itopic-deploy --replicas=5

也可以设置自动扩容:

$ kubectl autoscale deployment  nginx-deploy --min=2 --max=5 --cpu-percent=80

$ kubectl get hpa
NAME           REFERENCE                 TARGETS         MINPODS   MAXPODS   REPLICAS   AGE
nginx-deploy   Deployment/nginx-deploy   <unknown>/80%   2         5         4          2m

5.6 容器调试

创建过程中可能会出现一些问题,提供一些调试方法:

5.6.1 describe

通过describe命令查看资源信息,各个资源都可以通过describe查看。可以看到状态以及Events

5.6.2 查看容器日志

$ kubectl logs itopic-6f9dd4f4cd-6n6lp -c itopic
The topic server is running at http://0.0.0.0:8001
Quit the server with Control-C

如果Pod里只有一个容器可以省略-c参数,创建资源的时候可以通过日志看容器是否成功。也可以指定-f,类似tail -f

5.6.3 service

如果创建的service对外无法提供访问,可以通过describe查看svc信息

$ kubectl describe svc itopic-svc
Name:                     itopic-svc
Namespace:                default
Labels:                   app=itopic
Annotations:              kubectl.kubernetes.io/last-applied-configuration:
                            {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"labels":{"app":"itopic-svc"},"name":"itopic-svc","namespace":"default"},...
Selector:                 app=itopic
Type:                     LoadBalancer
IP:                       10.108.2.60
LoadBalancer Ingress:     localhost
Port:                     <unset>  38002/TCP
TargetPort:               8001/TCP
NodePort:                 <unset>  31744/TCP
Endpoints:                10.1.0.93:8001,10.1.0.94:8001,10.1.0.95:8001
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

5.7 查看Yaml

不同资源的完整的yaml信息可以这么看(也可以指定格式为json):

$ kubectl get svc itopic-svc -o yaml
apiVersion: v1
kind: Service
metadata:
  creationTimestamp: "2020-08-31T09:17:17Z"
  labels:
    app: itopic
  name: itopic-svc
  namespace: default
  resourceVersion: "418216"
  selfLink: /api/v1/namespaces/default/services/itopic-svc
  uid: 7198a068-2573-4e37-b0c6-20191940890e
spec:
  clusterIP: 10.97.234.18
  externalTrafficPolicy: Cluster
  ports:
  - nodePort: 31846
    port: 38002
    protocol: TCP
    targetPort: 8001
  selector:
    app: itopic
  sessionAffinity: None
  type: LoadBalancer
status:
  loadBalancer:
    ingress:
    - hostname: localhost

六、小结

本章节主要讲解配置清单的基础使用,了解资源清单的基本写法。至于配置清单在不同资源对象下的使用则需要根据实际场景去看,但书写方式大同小异,下一篇将聊一聊k8s下最小粒度的资源Pod


-- EOF --
最后更新于: 2020-09-25 16:31
发表于: 2020-09-01 22:06
标签: Kubernetes 容器化