Kubernetes通过YAML文件创建资源对象

Yaml语法简介

Yaml语法规则

  • 大小写敏感
  • 使用缩进表示层级关系
  • 缩进时不允许使用Tab键,只允许使用空格
  • 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
  • #号表示注释,从这个字符一直到行尾,都会被解析器忽略

Yaml数据结构

1.yaml支持三种数据结构

  • 对象:键值对的集合,又称为映射(mapping) /哈希(hashes) /字典(dictionary)
  • 数组:一组次序排列的值,又称为序列(sequence) /列表(list)
  • 纯量:(scalars) 单个的,不可两分的值

2.对象表示
对象就是一组键值对,使用冒号结构表示 :

role: web
env: test

3.数组表示
数组就是一个键可以对应多个值,如下

command:
- wget 
- '-O'
- "/work-dir/index.html"
- http:kubernetes.io

4.复合结构
复合结构是对象和数组的结合表现形式,在一个对象中嵌套多个数组

containers:
- name: nginx
  image: nginx:latest
- name: php
  image: php:latest

5.纯量表示
纯量是最基本的,不可再分的值

  • 字符串 — "我是字符串"
  • 布尔值 — true and false
  • 整数 — 10
  • 浮点数 — 10.30
  • Null — null
  • 时间 — 23:59:29
  • 日期 — 1976-07-31

Yaml多行字符串

多行字符串可以使用
| 管道符号来保留换行

  • 加号表示保留文字末尾的换行
  • 减号表示删除字符串末尾的换行
data:
  nginx-conf: |-    #这里表示换行和删除字符串末尾的换行
    server {
      listen 80;
      server_name localhost;
    }

Yaml多个配置写到一个文件内

假如我们要在同一个yaml文件中做好几件不同的事情,这个时候可以使用 — 符号来区分为多个区块。
例如我们要使用yaml文件来创建 deploy控制器和service,我们可以这样写

apiVersion:v1
kind: Deployment
metadata:
...
spec:
...
---             #使用---来区分两件事情

apiVersion:v1
kind: Service
metadata:
...
spec:
...

API资源类型

  • Kubernetes系统把管理的绝大多数事物都抽象成了资源,它们分别代表着不同事物类型,例如Node、Service、Pod、Controller等等
  • 每种类型均可通过“属性赋值”进行实例化,从而构建出“对象(Object)。

如果要查看k8s所支持的资源都有哪些可以通过kubectl api-resources命令获取

资源对象管理配置方式

所谓的资源对象管理配置方式,即为我们在去创建资源时,所用的方式,上章博客使用了命令方式去创建了deployment控制器和service,使用的语法为 kubectl create 方式进行创建,这里将通过yaml格式定义后进行创建相应的资源。虽然是通过yaml格式进行定义,但是k8s中的API Server组件并不是通过yaml格式的文件进行创建对象,而是将你定义的yaml配置转换为json,然后通过json格式去创建相应的对象。那么我们该怎么去定义yaml文件呢?定义格式如下:
通常的yaml文件有五个字段,分别为apiVersionkindmetadataspecstatus

  • apiVersion:apiVersion用于标识API群组及相关的版本,使用kubectl api-versions可以获取到api server所支持的API群组和版本。
  • kind:kind用于标识对象所属的资源类型,可使用kubectl api-resources获取。
  • metadata:metadata字段为资源提供元数据信息,例如名称、隶属的名称空间和标签等。
  • spec:spec用于定义用户期望的状态,不同的资源类型,其意义各有不同,例如Pod资源最为核心的功能在于运行容器。
  • status:status则记录着活动对象的当前状态信息,它由Kubernetes系统自行维护,对用户来说为只读字段(所以我们一般不定义status状态,当资源对象运行后由k8s自动生成)

资源名称的唯一性(在同一个名称空间下的相同资源类型名称必须唯一)
上面讲了这五个字段的意思,那么该怎么定义这五个字段呢?
我们可以通过以下命令输出现有资源的yaml格式进行参考

#将名称空间nginx-ns输出为yaml格式
kubectl get namespace/nginx-ns -o yaml

#将service nginx-svc输出为yaml格式
kubectl get service/nginx-svc -n default -o yaml

#将deploy控制器nginx-deploy输出为yaml格式
kubectl get service/nginx-svc -n default -o yaml

#将pod输出为yaml格式
kubectl get pods/nginx-deploy-7d5c9644b-cfg25 -n default -o yaml

以上命令输出了我们常用资源为yaml格式可以进行参考,不过在实际操作之前,我们还需要了解以下几种概念

和解循环(Reconciliation Loop)

资源配置格式中spec是用来定义用户对资源的期望状态,status为资源的当前状态,那么k8s的控制器是如何让用户期望状态与资源当前状态保持一致的呢?就是通过和解循环机制

  1. 我们创建资源的时候使用kubectl命令,kubectl命令做为API Server的客户端,那么kubectl将向API Server提交POST请求创建对象,通过yaml格式提交被API Server转换为json格式,资源对象的配置信息保存在etcd中,其定义出的状态也称为“期望的状态(spec)”。
  2. API Server收到客户端提交的POST请求后,调用控制器将资源创建为Kubernetes集群上的具体对象(活动对象),并确保当前状态(status)与用户期望状态相同,status由控制器自行维护,而spec则由用户进行定义后提交,活动对象在运行过程中因节点故障等原因可能会在某一时刻导致status与spec不吻合,那么控制器则通过和解循环(loop)机制不断的监控着相关对象的当前状态,在对象的当前状态发生改变时运行合适的操作让其当前状态无限接近期望状态。

上面了解了和解循环后再来了解以下两个概念:标签和标签选择器

标签及标签选择器

1.Label/资源标签
在第一章博客中有简单的了解了标签的概念,以下介绍标签的使用格式及注意事项

  • 一个对象可以拥有多个标签,而一个标签也可以被添加在多个资源之伤。
  • 实践中,可以为资源附加多个不同纬度的标签以实现灵活的资源分组管理功能,例如版本标签、环境标签、分层架构标签等,拥有交叉标示同一个资源所属的不同版本、环境及架构层级等。
  • 标签中的键名称由键前缀和键名称组成,其中键前缀可选,其格式如:"KEY_PREFEIX/KEY_NAME"。
    • 键名称最多使用63个字符,可以使用字母、数字、连接号(-)、下划线(_)、点号(.)等字符,且只能以字母或数字开头。
    • 键前缀必须为DNS子域名格式,且不能超过253个字符。省略键前缀时,键将被视为用户的私有数据,不过由Kubernetes系统组件或第三方组件自动为用户资源添加的键必须使用键前缀,而“kubernetes.io/”前缀是预留给kubernetes的核心组件使用。
    • 标签中的键值必须不能多于63个字符,要么为空,要么是以字符或数字开头及结尾,且中间仅使用了字母、数字、连接号(-)、下划线(_)、点号(.)等字符的数据。

2.标签选择器
标签选择器(Selector),全称为 ”Label Selector“,标签选择器通过 Label来过滤符合条件的 Pod,例如附有标签 ”application:nginx“的所有 Pod 挑选出来归纳为一类,并为归纳出的这组标签的 Pod 创建为 Service的端点。

标签选择器用于表达标签的查询条件或选择标准,kubernetes API目前支持两种选择器:

  • 基于等值关系(equality-based)
    • 操作符有=、==、和!=三种,其中前两个意义相同,都表示“等值”关系,最后一个表示”不等“关系
  • 基于集合关系(set-based)
    • KEY in (VALUE1,VALUE2…)
    • KEY not in (VALUE1,VALUE2…)
    • KEY:所有存在此键名标签的资源
    • !KEY:所有不存在此键名标签的资源

使用标签选择器时还将遵循以下逻辑:
* 同时指定的多个选择器之间的逻辑关系为“与”操作;
* 使用空值的标签选择器意味着每个资源对象都将被选中;
* 空的标签选择器将无法选出任何资源

定义标签选择器的方式:

  • matchLabels:通过直接给定键值对指定标签选择器;
  • matchExpressions:基于表达式指定的标签选择器列表,每个选择器如:"{key:KEY_NAME,operator:OPERATOR,values:[VALUE1,VALUE2,…]}",选择器列表间为“逻辑非”关系;
    • 使用ln或NotIn操作符时,其values非必须为非空的字符串列表,而使用Exists或DostNotExist时,其values必须为空。

3.标签管理

1.显示默认名称空间下所有带标签的资源对象
kubectl get all -n default --show-labels

2.显示pods资源所带有的标签,默认使用控制器创建的pod会附加两个标签,第一个是 app= 对应控制器的标签,pod-template-hash为pod模版,hash值等于pod模版的hash指纹信息,默认我们通过yaml配置清单中创建的pod,没有使用labels参数的则没有标签
kubectl get pods -n default --show-labels
ngx-dep-5d855b5b54-gglbl            1/1     Running   1          10d     app=ngx-dep,pod-template-hash=5d855b5b54
ngx-dep-5d855b5b54-jkftx            1/1     Running   1          10d     app=ngx-dep,pod-template-hash=5d855b5b54
ngx-dep-5d855b5b54-tbbrd            1/1     Running   1          13d     app=ngx-dep,pod-template-hash=5d855b5b54

3.标签管理命令
kubectl label -h        查看标签命令用法

4.添加标签(为下面pod添加键为application,值为nginx_proxy的标签),添加多个标签空格即可,如第二条命令
kubectl label pods/nginx-deploy-7d5c9644b-xv44v -n default application=nginx_proxy
kubectl label pods/nginx-deploy-7d5c9644b-xv44v -n default env=ngx version=1.17.2

5.修改标签(添加--overwrite参数)修改多个标签空格分割
kubectl label --overwrite pods/nginx-deploy-7d5c9644b-xv44v -n default application=ngx_proxy
kubectl label --overwrite pods/nginx-deploy-7d5c9644b-xv44v -n default env=nginx version=1.17.1

6.覆盖标签
覆盖标签用法与修改标签一致,在原来的键上直接修改

7.删除标签(将键写为 key- ,即可删除相应标签)
kubectl label pods/nginx-deploy-7d5c9644b-xv44v -n default application- version-

8.显示等于指定标签的pod(显示存在app=nginx-deploy标签的pod)
kubectl get pods --show-labels -n default -l app=nginx-deploy

9.显示不等于指定标签的pod(加 ! 过滤掉 app=nginx-deploy 的 pod)
kubectl get pods --show-labels -n default -l app!=nginx-deploy

10.显示标签键为app,值为 ngx-dep 或者nginx-deploy 的pod,如果匹配ngx-dep就显示ngx-dep,如果匹配nginx-deploy就显示nginx-deploy,如果两则都匹配,则两者都显示
kubectl get pods --show-labels -n default -l "app in (ngx-dep,nginx-deploy)"

11.在上面那条命令上使用 -L app ,会把 app(键) 作为列来展示值等于 ngx-dep 和 nginx-deploy 的 pod,-L 指定的值必须为键
kubectl get pods --show-labels -n default -l "app in (ngx-dep,nginx-deploy)" -L app
NAME                           READY   STATUS    RESTARTS   AGE     APP            LABELS
nginx-deploy-7d5c9644b-cfg25   1/1     Running   0          2d23h   nginx-deploy   app=nginx-deploy,pod-template-hash=7d5c9644b
nginx-deploy-7d5c9644b-xv44v   1/1     Running   0          2d23h   nginx-deploy   app=nginx-deploy,env=nginx,pod-template-hash=7d5c9644b
ngx-dep-5d855b5b54-4vl54       1/1     Running   1          13d     ngx-dep        app=ngx-dep,pod-template-hash=5d855b5b54
ngx-dep-5d855b5b54-7md6k       1/1     Running   1          11d     ngx-dep        app=ngx-dep,pod-template-hash=5d855b5b54

12.显示键为 app ,值不是 ngx-dep 和 nginx-deploy 的 pod
kubectl get pods --show-labels -l "app notin (ngx-dep,nginx-deploy)"

13.显示键为app的所有pod,只匹配键 
kubectl get pods --show-labels -l app

14.显示键不为app的,感叹号 ! 要用单引号扩起来,表示文本意思,不然会被shell认为有特殊意义
kubectl get pods --show-labels -l '!app'

资源注解

annotations为资源注解,常规之意即为 ”注释“

  • 注解也是“键值”类型的数据,不过它不能用于标签及挑选kubernetes对象,仅用于为资源提供“元数据”信息
  • 注解中的元数据不受字符数量的限制,它可大可小,可以为结构话或非结构话形式,也支持使用在标签中禁止使用的其它字符
  • 在kubernetes的新版本中(Alpha或则Beta阶段)为某资源引入新字段时,常以注解方式提供以一面其增删等变动给用户带来的困扰。

查看注解命令

kubectl describe pods ngx-dep-5d855b5b54-4vl54 -n default | grep Annotations

YAML创建namespace

1.编写配置清单

cat nginx-namespace.yaml
apiVersion: v1                  #指定资源群组及版本(namespace不属于任何群组,只指定v1版本)
kind: Namespace                 #指定资源类型为 Namespace
metadata:                       #元数据字段
  name: nginx-namespace         #指定名称空间名称
  labels:                       #为名称空间设置标签
    env: production             #标签key=env:value=production
    use: nginx                  #标签key=use:value=nginx
  annotations:                  #为名称空间设置注解
    k8sops.cn/env: ngx_app      #注解键前缀=k8sops.cn/key=env:value=ngx-app
spec:                           #期望状态,namespace为一个空间概念,不支持指定对它的期望状态

2.创建资源
我们可以使用 kubectl create 来创建资源,也可以使用kubectl apply,文章末尾讲解两种不同之处

kubectl create -f nginx-namespace.yaml

3.查看创建的名称空间

kubectl describe namespace/nginx-namespace

YAML创建Devloyment控制器

1.编写nginx-deploy deploy配置清单

cat nginx-deploy.yaml
apiVersion: apps/v1                         #指定资源群组及版本
kind: Deployment                            #指定资源类型
metadata:                                   #元数据配置段
  name: nginx-deployments                   #deploy控制器名称
  namespace: nginx-namespace                #deploy控制器所属名称空间
  annotations:                              #注解
    deployment.k8sops.cn/type: deploy
  labels:                                   #标签
    app: nginx-deploy
spec:                                       #用户期望配置段
  replicas: 3                               #pod副本数量
  revisionHistoryLimit: 10                  #当你的pod要进行回滚时,k8s保留了上几个版本,默认为10个版本
  selector:                                 #标签选择器,必须与模版中的标签相匹配
    matchLabels:                            #指定标签
      app: nginx-deploy
  template:                                 #指定模版,指定模版来创建pod,不指定的话就不会通过deploy控制器创建pod
    metadata:                               #指定pod的元数据配置段
      name: nginx-proxy                     #pod的名称
      namespace: nginx-deployments          #pod所处的名称空间
      annotations:                          #pod注解
        pod.k8sops.cn/app: nginx            
      labels:                               #pod标签
        app: nginx-deploy
        version: 1.17.1
    spec:                                   #用户期望pod的配置段
      containers:                           #容器配置
      - image: nginx:1.17.1                 #容器使用的镜像
        imagePullPolicy: IfNotPresent       #镜像拉取,值(Always:指定了镜像就去镜像仓库pull),(IfNotPresent:默认值如果本地有指定的镜像,则使用本地,如果没有则到仓库拉取),(Never:只使用本地镜像,从不去仓库拉取,如果本地没有则创建失败)
        name: nginx-node01                  #指定容器的名称
        resources: {}                       #计算容器所需的资源

2.创建资源

kubectl apply -f nginx-deploy.yaml

3.查看创建的控制器对象

#以长格式显示标签🏷️及nginx-deployments控制器信息
kubectl get deploy -n nginx-namespace -o wide --show-labels

#显示nginx-deployments控制器的详细信息
kubectl describe deploy/nginx-deployments -n nginx-namespace

#以yaml格式输出nginx-deployments控制器配置信息
kubectl get deploy/nginx-deployments -n nginx-namespace -o yaml

4.查看通过deploy控制器创建的pod

kubectl get pods -n nginx-namespace -o wide

YAML创建Service控制器

1.编写nginx-service配置清单

cat nginx-svc.yaml
apiVersion: v1  
kind: Service                   #指定资源类型为 Service
metadata:                       #Service元数据配置段
  name: nginx-service           #Service名称
  namespace: nginx-namespace    #Service所属的名称空间
  labels:                       #Service的标签
    app: nginx-proxy
spec:                           #对Service期望状态配置段
  clusterIP: 10.106.189.79      #指定Service的ClusterIP,此地址用作代理后端pod的IP地址
  ports:                        #ServicePort包含关于服务端口的信息
  - port: 80                    #指定Service所监听的端口
    protocol: TCP               #指定监听端口的协议
    targetPort: 80              #指定要代理的目标端口
  selector:                     #标签选择器
    app: nginx-deploy           #指定后端需要代理的pod标签,service通过这个标签进行转发请求
  sessionAffinity: None         #service与后端pod的会话保持,值可以为 ClientIP 或者 None,None表示关闭
  type: ClusterIP               #指定Service端口暴漏类型

2.创建Service资源

kubectl apply -f nginx-svc.yaml

3.查看service

kubectl get service/nginx-service -n nginx-namespace -o wide --show-labels
kubectl get service/nginx-service -n nginx-namespace -o yaml
kubectl describe service/nginx-service -n nginx-namespace

下图可以看到已经通过标签选择器🏷️代理到了后端的三个Pod的80端口

4.访问service的clusterIP
通过访问service的ClusterIP将请求转发至后端Pod

陈述式及声明式配置

kubernetes中的陈述式和声明式指的是我们在创建资源的时候使用的方式,是kubectl create还是kubectl apply
1.kubectl命令可以分为三种使用格式

  • 陈述式命令(明确而具体,每一步描述清楚)(Imperative Commands)
  • 陈述式对象配置(Imperative Object Configuration) kubectl create -f
  • 声明式对象配置(Declarative Object Configuration) kubectl apply -f (apply可以完成增删改的所有操作,不过我们一般用
    apply做增改,而删我们经常用命令kubetctl delete)
    使用json或则yaml可以创建控制器、service、pod、namespace

2.kubectl create 和 kubectl apply 的区别
kubectl apply声明式好处是,如果你要改变它,那就改变一下源文件后再次 apply 即可,但是你create创建的不行

例子如下:
假如我们对文件进行了修改,我们再次创建它,
使用create创建的可以看到发现已经报错

kubectl create -f nginx-deploy.yaml
Error from server (AlreadyExists): error when creating "nginx-deploy.yaml": deployments.apps "nginx-deployments" already exists

而使用apply创建的则没有报错,下面说无更改,则没有发生任何改变

kubectl apply -f nginx-deploy.yaml
deployment.apps/nginx-deployments unchanged

k8s源生操作就应该是声明式

资源字段太多,记不住怎么办?

很多同学YAML不会写!主要原因还是用的少,里面都是由于各个资源组成,熟悉了每个资源应用,自然就会写了,但也不用等到熟悉各种资源,这里教你几个技巧,帮助快速上手。

1.用create命令生成部署模版
我们要部署一个新的资源,那么我们可以通过 kubectl create 命令先干跑一遍,然后将配置导入yaml文件。

kubectl create deployment nginx --image=nginx:latest -o yaml --dry-run=client > my-ngx-deploy.yaml

然后查看my-ngx-deploy.yaml就可以看到k8s自动生成的配置信息,然后我们再修改就行

2.用export命令将正在运行的资源导出为yaml格式
如下,将正在运行的pod通过–export导出为yaml格式

kubectl get pods/nginx-deployments-7f5488687b-6ggnp -n nginx-namespace -o yaml --export > nginx-pod.yaml

3.在线直接编辑正在运行的资源
如下,在线编辑service,如果我们需要部署新的service,可以先使用编辑命令后将关键配置复制出来

kubectl edit service/nginx-service -n nginx-namespace

4.通过explain命令进行查找
kubectl explain 命令用于编写资源清单时的最好帮手了,用法如下

#语法如下
kubectl explain RESOURCE [options]

#查看service资源所支持的资源清单配置块
kubectl explain service
KIND:     Service           #这里指明了service所属的资源类型
VERSION:  v1                #这里指明了service所属的资源群组及版本,如果没有群组,则此资源不需要群组

FIELDS:                     #以下五种资源配置段为service所支持的
   apiVersion   <string>
   kind <string>
   metadata <Object>
   spec <Object>
   status   <Object>

#查看service中的 spec 配置段下面都支持哪些选项
kubectl explain service.spec        #在service参数后面跟 .spec 即可查看spec下所支持的参数(选项用户以此类推)

除了上面的通过 kubectl explain 查看service资源外,还可以查询任何资源,如下
kubectl explain pods
kubectl explain deploy
kubectl explain namespace
kubectl explain ……

查看详细的资源对象配置
kubectl explain pods.apiVersion

在资源对象后面再加.xx可以更详细的看到使用格式
kubectl explain pod.spec.containers

如果还要再详细
kubectl explain pod.spec.containers.ports

5.查看官方文档
资源对象配置清单支持的参数文档:https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/







「点点赞赏,手留余香」

    还没有人赞赏,快来当第一个赞赏的人吧!
Kubernetes
0 条回复 A 作者 M 管理员
    所有的伟大,都源于一个勇敢的开始!
欢迎您,新朋友,感谢参与互动!欢迎您 {{author}},您在本站有{{commentsCount}}条评论