多读书多实践,勤思考善领悟

深入理解kubernetes Pod之 一.浅析YAML基本语法

本文于1902天之前发表,文中内容可能已经过时。

一、YAML概念

在运维日常工作中又很多遇到yaml,例如写ansible的playbook,利用yaml来定义创建各应用及服务。

1.1 概念

YAML(发音 /ˈjæməl/)是一个类似 XML、JSON 的数据序列化语言,YAML是专门用来写配置文件的语言,非常简洁和强大,使用比json更方便。它实质上是一种通用的数据串行化格式。其强调以数据为中心,旨在方便人类使用;并且适用于日常常见任务的现代编程语言。因而 YAML 本身的定义比较简单,号称“一种人性化的数据格式语言”。

1.2 优点

  • 便捷性:不必添加大量参数到命令行中执行命令

  • 可维护性:yaml文件可以通过控制源头,跟踪每次操作

  • 灵活性:yaml可创建比命令行更加复杂的结构

  • 简易:易使用

1.3 语法规则

  • 大小写敏感

  • 使用缩进表示层级关系

  • 缩进不允许使用Tab键,只允许空格

  • 缩进空格数目不重要,只要相同层级的元素左侧对齐

  • #表示注释

1.4 组织结构

YAML学习笔记

文档间使用“—”(三个横线)在每文档开始作为分隔符。同时,文档也可以使用“…”(三个点号)作为结束符(可选)

二、结构类型

2.1 Maps类型

Map为字典,一对key:value键值对,例如

1
2
3
---
apiVersion: v1
kind: Pod

第一行的—是分隔符,是可选的,在单一文件中,可用连续三个连字号—区分多个文件。这里我们可以看到,我们有两个键:kind 和 apiVersion,他们对应的值分别是:v1和Pod。上面的 YAML 文件转换成 JSON 格式的话,你肯定就容易明白了:

1
2
3
4
{
"apiVersion": "v1",
"kind": "pod"
}

上面的 YAML 文件,metadata 这个 KEY 对应的值就是一个Maps了,而且嵌套的 labels 这个 KEY 的值又是一个Map,你可以根据你自己的情况进行多层嵌套。

上面我们也提到了 YAML 文件的语法规则,YAML 处理器是根据行缩进来知道内容之间的嗯关联性的。比如我们上面的 YAML 文件,我用了两个空格作为缩进,空格的数量并不重要,但是你得保持一致,并且至少要求一个空格(什么意思?就是你别一会缩进两个空格,一会缩进4个空格)。我们可以看到 name 和 labels 是相同级别的缩进,所以 YAML 处理器就知道了他们属于同一个 MAP,而 app 是 labels 的值是因为 app 的缩进更大。

同样的,我们可以将上面的 YAML 文件转换成 JSON 文件:

1
2
3
4
5
6
7
8
9
10
{
"apiVersion": "v1",
"kind": "Pod",
"metadata": {
"name": "kube100-site",
"labels": {
"app": "web"
}
}
}

2.2 Lists类型

List为数组

1
2
3
4
args
- Cat
- Dog
- Fish

你可以有任何数量的项在列表中,每个项的定义以破折号(-)开头的,与父元素直接可以缩进一个空格。对应的 JSON 格式如下:

1
2
3
{
"args": [ 'Cat', 'Dog', 'Fish' ]
}

2.3 混合类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
---
apiVersion: v1
kind: Pod
metadata:
name: kube100-site
labels:
app: web
spec:
containers:
- name: front-end
image: nginx
ports:
- containerPort: 80
- name: flaskapp-demo
image: jcdemo/flaskapp
ports: 8080

如上述文件所示,定义一个containers的List对象,每个子项都由name、image、ports组成,每个ports都有一个KEY为containerPort的Map组成,转成JSON格式文件:

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
{
"apiVersion": "v1",
"kind": "Pod",
"metadata": {
"name": "kube100-site",
"labels": {
"app": "web"
},

},
"spec": {
"containers": [{
"name": "front-end",
"image": "nginx",
"ports": [{
"containerPort": "80"
}]
}, {
"name": "flaskapp-demo",
"image": "jcdemo/flaskapp",
"ports": [{
"containerPort": "5000"
}]
}]
}
}

对上面的yaml文件进行解释:

  • apiVersion:此处值是v1,这个版本号需要根据安装的Kubernetes版本和资源类型进行变化
  • kind:此处创建的是Pod,根据实际情况,此处资源类型可以是Deployment、Job、Ingress、Service等
  • metadata:包含了我们定义的 Pod 的一些 meta 信息,比如name、namespace、lebal等等信息。
  • spec:包括一些 containers,storage,volumes,或者其他Kubernetes需要知道的参数,以及诸如是否在容器失败时重新启动容器的属性。你可以在特定Kubernetes API找到完整的Kubernetes Pod的属性。

containers 可设置的属性:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
name
image
command
args
workingDir
ports
env
resources
volumeMounts
livenessProbe
readinessProbe
livecycle
terminationMessagePath
imagePullPolicy
securityContext
stdin
stdinOnce
tty

三、yaml文件实例

  • k8s

    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
    apiVersion: v1             #指定api版本,此值必须在kubectl apiversion中  
    kind: Pod #指定创建资源的角色/类型
    metadata: #资源的元数据/属性
    name: web04-pod #资源的名字,在同一个namespace中必须唯一
    labels: #设定资源的标签,详情请见http://blog.csdn.net/liyingke112/article/details/77482384
    k8s-app: apache
    version: v1
    kubernetes.io/cluster-service: "true"
    annotations: #自定义注解列表
    - name: String #自定义注解名字
    spec:#specification of the resource content 指定该资源的内容
    restartPolicy: Always #表明该容器一直运行,默认k8s的策略,在此容器退出后,会立即创建一个相同的容器
    nodeSelector: #节点选择,先给主机打标签kubectl label nodes kube-node1 zone=node1
    zone: node1
    containers:
    - name: web04-pod #容器的名字
    image: web:apache #容器使用的镜像地址
    imagePullPolicy: Never #三个选择Always、Never、IfNotPresent,每次启动时检查和更新(从registery)images的策略,
    # Always,每次都检查
    # Never,每次都不检查(不管本地是否有)
    # IfNotPresent,如果本地有就不检查,如果没有就拉取
    command: ['sh'] #启动容器的运行命令,将覆盖容器中的Entrypoint,对应Dockefile中的ENTRYPOINT
    args: ["$(str)"] #启动容器的命令参数,对应Dockerfile中CMD参数
    env: #指定容器中的环境变量
    - name: str #变量的名字
    value: "/etc/run.sh" #变量的值
    resources: #资源管理,请求请见http://blog.csdn.net/liyingke112/article/details/77452630
    requests: #容器运行时,最低资源需求,也就是说最少需要多少资源容器才能正常运行
    cpu: 0.1 #CPU资源(核数),两种方式,浮点数或者是整数+m,0.1=100m,最少值为0.001核(1m)
    memory: 32Mi #内存使用量
    limits: #资源限制
    cpu: 0.5
    memory: 32Mi
    ports:
    - containerPort: 80 #容器开发对外的端口
    name: httpd #名称
    protocol: TCP
    livenessProbe: #pod内容器健康检查的设置,详情请见http://blog.csdn.net/liyingke112/article/details/77531584
    httpGet: #通过httpget检查健康,返回200-399之间,则认为容器正常
    path: / #URI地址
    port: 80
    #host: 127.0.0.1 #主机地址
    scheme: HTTP
    initialDelaySeconds: 180 #表明第一次检测在容器启动后多长时间后开始
    timeoutSeconds: 5 #检测的超时时间
    periodSeconds: 15 #检查间隔时间
    #也可以用这种方法
    #exec: 执行命令的方法进行监测,如果其退出码不为0,则认为容器正常
    # command:
    # - cat
    # - /tmp/health
    #也可以用这种方法
    #tcpSocket: //通过tcpSocket检查健康
    # port: number
    lifecycle: #生命周期管理
    postStart: #容器运行之前运行的任务
    exec:
    command:
    - 'sh'
    - 'yum upgrade -y'
    preStop: #容器关闭之前运行的任务
    exec:
    command: ['service httpd stop']
    volumeMounts: #详情请见http://blog.csdn.net/liyingke112/article/details/76577520
    - name: volume #挂载设备的名字,与volumes[*].name 需要对应
    mountPath: /data #挂载到容器的某个路径下
    readOnly: True
    volumes: #定义一组挂载设备
    - name: volume #定义一个挂载设备的名字
    #meptyDir: {}
    hostPath:
    path: /opt #挂载设备类型为hostPath,路径为宿主机下的/opt,这里设备类型支持很多种

    对应的json格式

    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
    99
    100
    101
    {
    'kind': 'Pod',
    'spec': {
    'restartPolicy': 'Always',
    'containers': [
    {
    'livenessProbe': {
    'initialDelaySeconds': 180,
    'httpGet': {
    'path': '/',
    'scheme': 'HTTP',
    'port': 80
    },
    'timeoutSeconds': 5,
    'periodSeconds': 15
    },
    'name': 'web04-pod',
    'image': 'web:apache',
    'args': [
    '$(str)'
    ],
    'volumeMounts': [
    {
    'readOnly': True,
    'mountPath': '/data',
    'name': 'volume'
    }
    ],
    'ports': [
    {
    'protocol': 'TCP',
    'containerPort': 80,
    'name': 'httpd'
    }
    ],
    'command': [
    'sh'
    ],
    'env': [
    {
    'name': 'str',
    'value': '/etc/run.sh'
    }
    ],
    'imagePullPolicy': 'Never',
    'lifecycle': {
    'preStop': {
    'exec': {
    'command': [
    'service httpd stop'
    ]
    }
    },
    'postStart': {
    'exec': {
    'command': [
    'sh',
    'yum upgrade -y'
    ]
    }
    }
    },
    'resources': {
    'requests': {
    'cpu': 0.1,
    'memory': '32Mi'
    },
    'limits': {
    'cpu': 0.5,
    'memory': '32Mi'
    }
    }
    }
    ],
    'volumes': [
    {
    'hostPath': {
    'path': '/opt'
    },
    'name': 'volume'
    }
    ],
    'nodeSelector': {
    'zone': 'node1'
    }
    },
    'apiVersion': 'v1',
    'metadata': {
    'labels': {
    'k8s-app': 'apache',
    'version': 'v1',
    'kubernetes.io/cluster-service': 'true'
    },
    'name': 'web04-pod',
    'annotations': [
    {
    'name': 'String'
    }
    ]
    }
    }
  • ansible

1
2
3
4
5
6
7
8
9
10
--- 
- hosts: agent # 定义主机
remote_user: root # 定义执行此playbook的用户
tasks: # 任务
- name: install mysql-server #自定义名称
yum: name=mysql-server state=present # yum模块安装mysql-server
- name: start mysql-server
service: name=mysqld state=started # service模块启动mysql服务
- name: check mysql service
shell: ps -ef |grep mysqld # shell模块查看mysql进程

对应的json格式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
'tasks': [
{
'yum': 'name=mysql-server state=present',
'name': 'install mysql-server'
},
{
'name': 'start mysql-server',
'service': 'name=mysqld state=started'
},
{
'shell': 'ps -ef |grep mysqld',
'name': 'check mysql service'
}
],
'hosts': 'agent',
'remote_user': 'root'
}]
  • 利用python讲yaml格式转换为json
1
2
3
4
5
6
7
pip install pyyaml                # 安装pyyaml模块

import yaml

with open('config.yaml','r') as f:
content = yaml.load(f)
print(content)

接下文: 深入理解kubernetes Pod之 二.静态Pod