kubernets ymal¶
1 通用部分¶
apiVersion <string>
:必选,版本号,例如 v1(必选)kind <string>
:资源类型,例如 Pod(必选)metadata <Object>
:资源的元数据(必选)spec <Object>
:资源的详细定义- 示例
apiVersion: v1
kind: Namespace
metadata:
name: test
2 Pod¶
- 常用字段:
spec
containers
:容器相关定义image
:镜像imagePullPolicy
:镜像拉取策略ports
:暴露端口env
:设置容器内环境变量volumeMounts
:使用挂载的卷
restartPolicy
:Pod 重启策略hostNetwork
:是否使用主机网络,默认是 falseaffinity
:节点的亲和性,用于计算 Pod 调度 k8s 集群中某个 node 上volumes
:卷定义,可使用 nfs、hostPath 等方式
- 示例
apiVersion: v1
kind: Namespace
metadata:
name: test
---
apiVersion: v1
kind: Pod
metadata:
name: nginx
namespace: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent #镜像拉取策略[Never|Always|IfNotPresent]
ports:
- containerPort: 80 #容器内端口
hostPort: 8080 #宿主机端口
protocol: UDP #协议类型[TCP|UDP|SCTP](默认TCP)
- containerPort: 80
hostPort: 8080
protocol: TCP
env: #环境变量
- name: env1
value: val1
volumeMounts:
- name: fs1
mountPath: /fs1
readOnly: false
restartPolicy: Always #容器重启策略[Never|Always|OnFailure]
hostNetwork: false #是否使用主机网络[true|false](默认false);如果使用,hostPort不能和containerPort不同
#nodeName: node1 #指定k8s节点名称,pod只会调度到此节点上
#nodeSelector: #节点选择器,匹配k8s节点上含test=nginx的节点
# test: nginx
affinity: #节点亲和性,pod调度到满足条件的节点上
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution: #必要要满足的条件
nodeSelectorTerms:
- matchExpressions:
- key: test
operator: In #便签匹配运算符,有In, NotIn, Exists, DoesNotExist
values:
- nginx
preferredDuringSchedulingIgnoredDuringExecution: #优先满足的条件
- weight: 1 #权重,范围1-100
preference:
matchExpressions:
- key: label-1
operator: In
values:
- key-1
- weight: 50
preference:
matchExpressions:
- key: label-2
operator: In
values:
- key-2
volumes:
- name: fs1
hostPath: # hostPath方式挂载,此外还有nfs、ceph等等方式
path: /root/fs1 #主机挂载点路径
type: DirectoryOrCreate #可选参数,默认空
2.1 Pod 分配¶
2.1.1 nodeSelector 节点标签¶
2.1.1.1 给节点添加标签¶
-
列出你的集群中的节点, 包括这些节点上的标签:
kubectl get nodes --show-labels
输出类似如下:
NAME STATUS ROLES AGE VERSION LABELS worker0 Ready <none> 1d v1.13.0 ...,kubernetes.io/hostname=worker0 worker1 Ready <none> 1d v1.13.0 ...,kubernetes.io/hostname=worker1 worker2 Ready <none> 1d v1.13.0 ...,kubernetes.io/hostname=worker2
-
从你的节点中选择一个,为它添加标签:
kubectl label nodes <your-node-name> disktype=ssd
<your-node-name>
是你选择的节点的名称。 -
验证你选择的节点确实带有
disktype=ssd
标签:kubectl get nodes --show-labels
输出类似如下:
NAME STATUS ROLES AGE VERSION LABELS worker0 Ready <none> 1d v1.13.0 ...,disktype=ssd,kubernetes.io/hostname=worker0 worker1 Ready <none> 1d v1.13.0 ...,kubernetes.io/hostname=worker1 worker2 Ready <none> 1d v1.13.0 ...,kubernetes.io/hostname=worker2
在前面的输出中,你可以看到
worker0
节点有disktype=ssd
标签。
2.1.1.2 创建一个将被调度到你选择的节点的 Pod¶
此 Pod 配置文件描述了一个拥有节点选择器 disktype: ssd
的 Pod。这表明该 Pod 将被调度到有 disktype=ssd
标签的节点。
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
nodeSelector:
disktype: ssd
-
使用该配置文件创建一个 Pod,该 Pod 将被调度到你选择的节点上:
kubectl create -f https://k8s.io/examples/pods/pod-nginx.yaml
-
验证 Pod 确实运行在你选择的节点上:
kubectl get pods --output=wide
输出类似如下:
NAME READY STATUS RESTARTS AGE IP NODE nginx 1/1 Running 0 13s 10.200.0.4 worker0
2.1.2 nodeName 节点名称¶
你也可以通过设置 nodeName
将某个 Pod 调度到特定的节点。
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
nodeName: foo-node # 调度 Pod 到特定的节点
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
使用此配置文件来创建一个 Pod,该 Pod 将只能被调度到 foo-node
节点。
2.1.3 节点亲和性¶
- 官方文档 2 种策略:
requiredDuringSchedulingIgnoredDuringExecution
:pod 必须调度(不匹配则调度失败)preferredDuringSchedulingIgnoredDuringExecution
:pod 优先调度(不匹配可以调度其它节点)
apiVersion: v1
kind: Pod
metadata:
name: with-node-affinity
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: topology.kubernetes.io/zone
operator: In
values:
- antarctica-east1
- antarctica-west1
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: another-node-label-key
operator: In
values:
- another-node-label-value
containers:
- name: with-node-affinity
image: registry.k8s.io/pause:2.0
在这一示例中,所应用的规则如下:
- 节点 必须 包含一个键名为 topology.kubernetes.io/zone
的标签, 并且该标签的取值 必须 为 antarctica-east1
或 antarctica-west1
。
- 节点 最好 具有一个键名为 another-node-label-key
且取值为 another-node-label-value
的标签。
2.1.4 污点和容忍度¶
https://kubernetes.io/zh-cn/docs/concepts/scheduling-eviction/taint-and-toleration/ 节点亲和性 是 Pod 的一种属性,它使 Pod 被吸引到一类特定的节点(这可能出于一种偏好,也可能是硬性要求)。 污点(Taint) 则相反——它使节点能够排斥一类特定的 Pod。
容忍度(Toleration) 是应用于 Pod 上的。容忍度允许调度器调度带有对应污点的 Pod。 容忍度允许调度但并不保证调度:作为其功能的一部分, 调度器也会 评估其他参数。
污点和容忍度(Toleration)相互配合,可以用来避免 Pod 被分配到不合适的节点上。 每个节点上都可以应用一个或多个污点,这表示对于那些不能容忍这些污点的 Pod, 是不会被该节点接受的。
2.2 init 容器¶
Init 容器在应用容器启动前运行完成。
apiVersion: v1
kind: Pod
metadata:
name: init-demo
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
volumeMounts:
- name: workdir
mountPath: /usr/share/nginx/html
# 这些容器在 Pod 初始化期间运行
initContainers:
- name: install
image: busybox:1.28
command:
- wget
- "-O"
- "/work-dir/index.html"
- http://info.cern.ch
volumeMounts:
- name: workdir
mountPath: "/work-dir"
dnsPolicy: Default
volumes:
- name: workdir
emptyDir: {}
2.3 容器间共享进程命名空间¶
当启用进程命名空间共享时,容器中的进程对同一 Pod 中的所有其他容器都是可见的。
使用 Pod .spec
中的 shareProcessNamespace
字段可以启用进程命名空间共享。例如:
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
shareProcessNamespace: true
containers:
- name: nginx
image: nginx
- name: shell
image: busybox:1.28
securityContext:
capabilities:
add:
- SYS_PTRACE
stdin: true
tty: true
-
在集群中创建
nginx
Pod:kubectl apply -f https://k8s.io/examples/pods/share-process-namespace.yaml
-
获取容器
shell
,执行ps
:kubectl attach -it nginx -c shell
如果没有看到命令提示符,请按 enter 回车键。在容器 shell 中:
# 在 “shell” 容器中运行以下命令 ps ax
输出类似于:
PID USER TIME COMMAND 1 root 0:00 /pause 8 root 0:00 nginx: master process nginx -g daemon off; 14 101 0:00 nginx: worker process 15 root 0:00 sh 21 root 0:00 ps ax
你可以在其他容器中对进程发出信号。例如,发送 SIGHUP
到 nginx
以重启工作进程。 此操作需要 SYS_PTRACE
权能。
# 在 “shell” 容器中运行以下命令
kill -HUP 8 # 如有必要,更改 “8” 以匹配 nginx 领导进程的 PID
ps ax
输出类似于:
PID USER TIME COMMAND
1 root 0:00 /pause
8 root 0:00 nginx: master process nginx -g daemon off;
15 root 0:00 sh
22 101 0:00 nginx: worker process
23 root 0:00 ps ax
甚至可以使用 /proc/$pid/root
链接访问另一个容器的文件系统。
# 在 “shell” 容器中运行以下命令
# 如有必要,更改 “8” 为 Nginx 进程的 PID
head /proc/8/root/etc/nginx/nginx.conf
输出类似于:
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
2.4 生命周期检查¶
2.5 生命周期钩子¶
3 Pod控制器¶
https://kubernetes.io/zh-cn/docs/concepts/workloads/controllers/
3.1 Deployment¶
Deployment 是pod控制器的一种,实际上通常使用控制器来管理Pod,很少直接用Pod
- 常用字段
spec
replicas
:Pod 副本数selector
:标签选择器,用于匹配template
中定义的 Podstrategy
:更新策略(影响镜像修改,扩缩容操作)template
:Pod 模板,语法大致和 Pod ymal 语法相同
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx
name: nginx
spec:
replicas: 3 #Pod副本数量
selector:
matchLabels: #匹配下面容器定义的标签
app: nginx
strategy: #更新策略
type: RollingUpdate
rollingUpdate: #滚动更新策略,当type: RollingUpdate时才能用
maxSurge: 1 #滚动更新时,最多比期望的副本数多几个pod maxSurge和maxUnavailable不能同时为0,否则冲突,无法滚动更新。可以使用百分比(30%)和数值方式(2)
maxUnavailable: 1 #滚动更新时,最多比期望的副本数少几个pod
type: RollingUpdate #更新策略,[Recreate,RollingUpdate]。Recreate删除pod后再重建;RollingUpdate滚动更新,新老pod可以同时存在
template: #这部分基本与pod中定义相似
metadata:
labels:
app: nginx #此标签用于上面selector匹配的
spec:
containers:
- image: nginx
name: nginx
3.2 StatefulSet¶
4 Volume 卷¶
4.1 configMap¶
configMap
卷提供了向 Pod 注入配置数据的方法。 ConfigMap 对象中存储的数据可以被 configMap
类型的卷引用,然后被 Pod 中运行的容器化应用使用。
引用 configMap 对象时,你可以在卷中通过它的名称来引用。 你可以自定义 ConfigMap 中特定条目所要使用的路径。 下面的配置显示了如何将名为 log-config
的 ConfigMap 挂载到名为 configmap-pod
的 Pod 中:
apiVersion: v1
kind: Pod
metadata:
name: configmap-pod
spec:
containers:
- name: test
image: busybox:1.28
command: ['sh', '-c', 'echo "The app is running!" && tail -f /dev/null']
volumeMounts:
- name: config-vol
mountPath: /etc/config
volumes:
- name: config-vol
configMap:
name: log-config
items:
- key: log_level
path: log_level
log-config
ConfigMap 以卷的形式挂载,并且存储在 log_level
条目中的所有内容都被挂载到 Pod 的 /etc/config/log_level
路径下。 请注意,这个路径来源于卷的 mountPath
和 log_level
键对应的 path
。
说明:
- 在使用 ConfigMap 之前你首先要创建它。
- ConfigMap 总是以
readOnly
的模式挂载。 - 容器以
subPath
卷挂载方式使用 ConfigMap 时,将无法接收 ConfigMap 的更新。 - 文本数据挂载成文件时采用 UTF-8 字符编码。如果使用其他字符编码形式,可使用
binaryData
字段。
4.2 emptyDir¶
对于定义了 emptyDir
卷的 Pod,在 Pod 被指派到某节点时此卷会被创建。 就像其名称所表示的那样,emptyDir
卷最初是空的。尽管 Pod 中的容器挂载 emptyDir
卷的路径可能相同也可能不同,但这些容器都可以读写 emptyDir
卷中相同的文件。 当 Pod 因为某些原因被从节点上删除时,emptyDir
卷中的数据也会被永久删除。
说明:容器崩溃并 不会导致 Pod 被从节点上移除,因此容器崩溃期间 emptyDir
卷中的数据是安全的。
emptyDir
的一些用途:
- 缓存空间,例如基于磁盘的归并排序。
- 为耗时较长的计算任务提供检查点,以便任务能方便地从崩溃前状态恢复执行。
- 在 Web 服务器容器服务数据时,保存内容管理器容器获取的文件。
emptyDir.medium
字段用来控制 emptyDir
卷的存储位置。 默认情况下,emptyDir
卷存储在该节点所使用的介质上; 此处的介质可以是磁盘、SSD 或网络存储,这取决于你的环境。 你可以将 emptyDir.medium
字段设置为 "Memory"
, 以告诉 Kubernetes 为你挂载 tmpfs(基于 RAM 的文件系统)。 虽然 tmpfs 速度非常快,但是要注意它与磁盘不同, 并且你所写入的所有文件都会计入容器的内存消耗,受容器内存限制约束。
你可以通过为默认介质指定大小限制,来限制 emptyDir
卷的存储容量。
配置示例
apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: registry.k8s.io/test-webserver
name: test-container
volumeMounts:
- mountPath: /cache
name: cache-volume
volumes:
- name: cache-volume
emptyDir:
sizeLimit: 500Mi
4.3 hostPath¶
hostPath
卷能将主机节点文件系统上的文件或目录挂载到你的 Pod 中。
例如,hostPath
的一些用法有:
- 运行一个需要访问 Docker 内部机制的容器;可使用
hostPath
挂载/var/lib/docker
路径。 - 在容器中运行 cAdvisor 时,以
hostPath
方式挂载/sys
。 - 允许 Pod 指定给定的
hostPath
在运行 Pod 之前是否应该存在,是否应该创建以及应该以什么方式存在。
除了必需的 path
属性之外,你可以选择性地为 hostPath
卷指定 type
。支持的 type
值如下:
取值 | 行为 |
---|---|
空字符串(默认)用于向后兼容,这意味着在安装 hostPath 卷之前不会执行任何检查。 | |
DirectoryOrCreate |
如果在给定路径上什么都不存在,那么将根据需要创建空目录,权限设置为 0755,具有与 kubelet 相同的组和属主信息。 |
Directory |
在给定路径上必须存在的目录。 |
FileOrCreate |
如果在给定路径上什么都不存在,那么将在那里根据需要创建空文件,权限设置为 0644,具有与 kubelet 相同的组和所有权。 |
File |
在给定路径上必须存在的文件。 |
Socket |
在给定路径上必须存在的 UNIX 套接字。 |
CharDevice |
在给定路径上必须存在的字符设备。 |
BlockDevice |
在给定路径上必须存在的块设备。 |
- 下层主机上创建的文件或目录只能由 root 用户写入。 你需要在 特权容器 中以 root 身份运行进程,或者修改主机上的文件权限以便容器能够写入
hostPath
卷。
4.3.1 hostPath 配置示例¶
apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: registry.k8s.io/test-webserver
name: test-container
volumeMounts:
- mountPath: /test-pd
name: test-volume
volumes:
- name: test-volume
hostPath:
# 宿主机上目录位置
path: /data
# 此字段为可选
type: Directory
注意:FileOrCreate
模式不会负责创建文件的父目录。 如果欲挂载的文件的父目录不存在,Pod 启动会失败。 为了确保这种模式能够工作,可以尝试把文件和它对应的目录分开挂载,如 FileOrCreate
配置所示。
4.3.2 hostPath FileOrCreate 配置示例¶
apiVersion: v1
kind: Pod
metadata:
name: test-webserver
spec:
containers:
- name: test-webserver
image: registry.k8s.io/test-webserver:latest
volumeMounts:
- mountPath: /var/local/aaa
name: mydir
- mountPath: /var/local/aaa/1.txt
name: myfile
volumes:
- name: mydir
hostPath:
# 确保文件所在目录成功创建。
path: /var/local/aaa
type: DirectoryOrCreate
- name: myfile
hostPath:
path: /var/local/aaa/1.txt
type: FileOrCreate
4.4 nfs¶
nfs
卷能将 NFS (网络文件系统) 挂载到你的 Pod 中。
apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: registry.k8s.io/test-webserver
name: test-container
volumeMounts:
- mountPath: /my-nfs-data
name: test-volume
volumes:
- name: test-volume
nfs:
server: my-nfs-server.example.com
path: /my-nfs-volume
readOnly: true
还需要注意,不能在 Pod spec 中指定 NFS 挂载可选项。 可以选择设置服务端的挂载可选项,或者使用 /etc/nfsmount.conf。 此外,还可以通过允许设置挂载可选项的持久卷挂载 NFS 卷。
如需了解用持久卷挂载 NFS 卷的示例,请参考 NFS 示例。
4.5 subPath¶
4.5.1 使用 subPath¶
有时,在单个 Pod 中共享卷以供多方使用是很有用的。 volumeMounts.subPath
属性可用于指定所引用的卷内的子路径,而不是其根路径。
下面例子展示了如何配置某包含 LAMP 堆栈(Linux Apache MySQL PHP)的 Pod 使用同一共享卷。 此示例中的 subPath
配置不建议在生产环境中使用。 PHP 应用的代码和相关数据映射到卷的 html
文件夹,MySQL 数据库存储在卷的 mysql
文件夹中:
apiVersion: v1
kind: Pod
metadata:
name: my-lamp-site
spec:
containers:
- name: mysql
image: mysql
env:
- name: MYSQL_ROOT_PASSWORD
value: "rootpasswd"
volumeMounts:
- mountPath: /var/lib/mysql
name: site-data
subPath: mysql
- name: php
image: php:7.0-apache
volumeMounts:
- mountPath: /var/www/html
name: site-data
subPath: html
volumes:
- name: site-data
persistentVolumeClaim:
claimName: my-lamp-site-data
4.5.2 使用带有扩展环境变量的 subPath¶
特性状态: Kubernetes v1.17 [stable]
使用 subPathExpr
字段可以基于 downward API 环境变量来构造 subPath
目录名。 subPath
和 subPathExpr
属性是互斥的。
在这个示例中,Pod
使用 subPathExpr
来 hostPath
卷 /var/log/pods
中创建目录 pod1
。 hostPath
卷采用来自 downwardAPI
的 Pod 名称生成目录名。 宿主机目录 /var/log/pods/pod1
被挂载到容器的 /logs
中。
apiVersion: v1
kind: Pod
metadata:
name: pod1
spec:
containers:
- name: container1
env:
- name: POD_NAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.name
image: busybox:1.28
command: [ "sh", "-c", "while [ true ]; do echo 'Hello'; sleep 10; done | tee -a /logs/hello.txt" ]
volumeMounts:
- name: workdir1
mountPath: /logs
# 包裹变量名的是小括号,而不是大括号
subPathExpr: $(POD_NAME)
restartPolicy: Never
volumes:
- name: workdir1
hostPath:
path: /var/log/pods
4.6 CSI¶
容器存储接口 (CSI) 为容器编排系统(如 Kubernetes)定义标准接口,以将任意存储系统暴露给它们的容器工作负载。
更多详情请阅读 CSI 设计方案。
4.7 持久卷 PV¶
https://kubernetes.io/zh-cn/docs/concepts/storage/persistent-volumes/
4.8 存储类 StorageClass¶
https://kubernetes.io/zh-cn/docs/concepts/storage/storage-classes/
5 Service 网络¶
https://kubernetes.io/zh-cn/docs/concepts/services-networking/service/ Kubernetes 中 Service 是 将运行在一个或一组 Pod上的网络应用程序公开为网络服务的方法。