前言
Kubernetes 集群的声明式资源管理方法是当今云原生领域中的核心概念之一,使得容器化应用程序的部署和管理变得更加高效和可靠。本文将认识了解 Kubernetes 中声明式管理的相关理念、实际应用以及优势。
目录
一、管理方法介绍
1. 概述
2. 语法格式
2.1 管理资源对象格式
2.2 YAML 语法格式
3. yaml 文件组成部分
4. 如何快速编写 yaml
5. 资源配置清单
5.1 查看资源配置清单
5.2 解释资源配置清单
6. 修改资源配置清单并应用
6.1 离线修改
6.2 在线修改
7. 查看 api 资源版本标签
8. 删除资源配置清单
二、编写 ymal 文件
1. 部署 nginx-yaml 配置
1.1 编辑清单 yaml 文件
1.2 创建资源对象
1.3 创建 service 服务对外提供访问
1.4 创建 svc 资源对象
1.5 访问测试
1.6 port 端口类型
2. 部署 redis-yaml 配置
2.1 编辑清单、service yaml 文件
2.2 创建资源对象
2.3 连接 pod 实例
3. 部署 mysql-yaml 配置
3.1 生成模板 yaml 文件
3.2 创建资源
3.3 访问验证
一、管理方法介绍
1. 概述
通过使用 yaml 或 josn 文件对资源配置,然后再实现对资源的管理。
适合于对资源的修改操作
声明式资源管理方法依赖于资源配置清单文件对资源进行管理;资源配置清单文件有两种格式:yaml(人性化,易读),json(易于api接口解析)
对资源的管理,是通过事先定义在统一资源配置清单内,再通过陈述式命令应用到k8s集群里
2. 语法格式
2.1 管理资源对象格式
- JSON 格式:主要用于 api 接口之间消息的传递
- YAML 格式:用于配置和管理,YAML 是一种简洁的非标记性语言,内容格式人性化,较易读
2.2 YAML 语法格式
- 大小写敏感
- 使用缩进表示层级关系
- 不支持Tab键制表符缩进,只使用空格缩进
- 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可,通常开头缩进两个空格
- 符号字符后缩进一个空格,如冒号,逗号,短横杆(-)等
- “---”表示YAML格式,一个文件的开始,用于分隔文件间
- “#”表示注释
kubectl create -f xxxx.yaml
create 命令用于根据提供的配置文件创建新的 Kubernetes 资源。
- 如果资源尚不存在,Kubernetes 会根据 YAML 文件中的定义新建对象(如 Deployments、Services、Pods 等)。
- 如果资源已经存在,create 命令不会更改现有资源的状态,而是会报错,因为它旨在创建新资源而非修改现有资源。
kubectl apply -f xxxx.yaml
apply 命令也用于根据配置文件创建或更新资源。
- 与 create 不同的是,apply 会比较配置文件中定义的资源状态与集群中实际资源的状态。
- 如果资源不存在,它将创建资源;
- 如果资源已存在,它会尝试将实际资源的状态更新为配置文件中描述的状态。
- 这意味着你可以多次运行 apply 来更新资源。
kubectl delete -f xxxx.yaml
delete 命令用于根据配置文件删除 Kubernetes 资源;此命令非常直接,用于清理不再需要的资源。
- 当你提供一个之前用于创建或更新资源的 YAML 文件时,kubectl 会识别出文件中定义的所有资源,并将其从集群中删除;
- 这可以是单个资源,也可以是多个相关联的资源集合。
3. yaml 文件组成部分
在 K8s 中,控制器的定义是通过 YAML 文件完成的,该文件描述了资源的预期状态。这包括控制器的类型:如Deployment、statefulSet、Service 副本数量,使用的容器镜像,以及任何配置参数或环境变量。每一个控制器通常对应一种资源类型,如 Deployment、Service 等等。
在YAML中,我们可以指定这些资源的状态以及如何管理它们。Deployment 控制器在 YAML 文件中的定义可能包括:
- metadata:例如控制器的名称和命名空间
- spec:例如应用的副本数量,以及图像的 URL
- selector:例如确定哪些 Pods 应由该控制器管理的标签
- template:例如 Pod 的基本设计
4. 如何快速编写 yaml
① 使用 kubectl create 命令生成 yaml 文件导出
示例:
kubectl create deployment nginx svc -o yaml > nginx-svc.yaml
② 使用 kubectl get 命令导出 yaml 文件
示例:
kubectl get svc nginx-service -o yaml > my-svc.yaml
或
kubectl edit svc nginx-service #复制配置,再粘贴到新文件
③ 官网或者其他网站下载 yaml 模版,然后进行修改快速的方法
官网获取网址:Pods | Kubernetes
GITHUB获取地址:kubernetes/hack/testdata at master · kubernetes/kubernetes · GitHub
④ 查看字段帮助信息,可一层层的查看相关资源对象的帮助信息
kubectl explain deployments.spec.template.spec.containers
或
kubectl explain pods.spec.containers
⑤ 模拟运行 kubectl 陈述式创建资源的命令获取
用 --dry-run 命令生成:
kubectl run my-deploy --image=nginx --dry-run=client -o yaml > my-deploy.yaml
5. 资源配置清单
资源配置清单是指用于定义 K8s 资源对象的配置文件。这些配置文件通常以 YAML 或 JSON 格式编写,用于描述要在 K8s 集群中创建、管理或删除的各种资源,如 Pod、Service、Deployment 等。
5.1 查看资源配置清单
返回nginx-01的Deployment资源的摘要信息,并以yaml格式显示:
[root@master01 ~]# kubectl get deployment nginx-01 -n fql -o yaml获取nginx-service的Service资源,并以yaml格式输出该资源的详细信息:
[root@master01 ~]# kubectl get svc nginx-service -n fql -o yaml
5.2 解释资源配置清单
获取有关Kubernetes中Deployment资源的metadata字段的详细信息和说明:
[root@master01 ~]# kubectl explain deployment.metadata获取有关Kubernetes中Service资源的metadata字段的详细信息和说明
[root@master01 ~]# kubectl explain service.metadata在K8s中,metadata是用于描述资源对象的信息,metadata字段通常包括以下内容:
# name:资源对象的名称,用于在集群中唯一标识该对象
# namespace:资源对象所属的命名空间,用于对资源进行逻辑隔离和组织
# labels:一组键值对,用于标识和分类资源对象,以便于查询和选择
# annotations:一组键值对,用于存储额外的非标识性信息,如描述、构建信息等
6. 修改资源配置清单并应用
6.1 离线修改
[root@master01 ~]# kubectl create deployment nginx --image=nginx:1.14 --port=80 --replicas=2
[root@master01 ~]# kubectl expose deployment nginx --port=80 --target-port=80 --name=nginx-svc --type=NodePort[root@master01 ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 5d22h
nginx-svc NodePort 10.96.72.223 <none> 80:30997/TCP 4s
[root@master01 ~]# kubectl get pod,svc -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/nginx-d9d8cf5c7-6rhcs 1/1 Running 0 7m1s 10.244.1.40 node01 <none> <none>
pod/nginx-d9d8cf5c7-p44sk 1/1 Running 0 7m1s 10.244.1.39 node01 <none> <none>NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 5d22h <none>
service/nginx-svc NodePort 10.96.72.223 <none> 80:30997/TCP 26s app=nginx
修改 yaml 文件,并用 kubectl apply -f xxxx.yaml 文件使之生效;注意:当 apply 不生效时,先使用 delete 清除资源,再 apply 创建资源。
[root@master01 ~]# kubectl get svc nginx-svc -o yaml > nginx-svc.yaml
[root@master01 ~]# vim nginx-svc.yaml port: 8080 # 修改[root@master01 ~]# kubectl delete -f nginx-svc.yaml # 清除资源
service "nginx-svc" deleted
[root@master01 ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 5d22h
[root@master01 ~]# kubectl apply -f nginx-svc.yaml
service/nginx-svc created
[root@master01 ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 5d22h
nginx-svc NodePort 10.96.72.223 <none> 8080:30997/TCP 2s[root@master01 ~]# curl 10.96.72.223:8080
<title>Welcome to nginx!</title>
6.2 在线修改
直接使用 kubectl edit service nginx 在线编辑资源配置清单并保存退出即时生效(如port: 888)
PS:此修改方式不会对yaml文件内容修改
[root@master01 ~]# kubectl edit svc nginx-svc
service/nginx-svc edited
# i:编辑,wq:保存
[root@master01 ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 5d22h
nginx-svc NodePort 10.96.72.223 <none> 888:30997/TCP 10m
[root@master01 ~]# vim nginx-svc.yaml port: 8080 # 未对yaml文件内容进行修改
[root@master01 ~]# curl 10.96.72.223:888
<title>Welcome to nginx!</title>
7. 查看 api 资源版本标签
[root@master01 ~]# kubectl api-versions
apps/v1 # 如果是业务场景一般首选使用 apps/v1
apps/v1beta1 # 带有beta字样的代表的是测试版本,不用在生产环境中
8. 删除资源配置清单
① 陈述式删除
kubectl delete service nginx
# 是一个命令,用于删除名为nginx的服务。这将从Kubernetes集群中删除该服务的定义和相关资源
② 声明式删除
kubectl delete -f nginx-svc.yaml
# 根据提供的YAML文件删除资源
区别:
- 第一个命令是根据资源名称直接删除服务;
- 第二个命令是根据提供的 YAML 文件中的定义删除资源。第二个命令更加灵活,可以一次性删除多个资源,而不仅限于服务。
二、编写 ymal 文件
1. 部署 nginx-yaml 配置
1.1 编辑清单 yaml 文件
[root@master01 ~]# mkdir /data/demo -p
[root@master01 ~]# cd /data/demo/
[root@master01 demo]# vim nginx-dp.yaml
apiVersion: apps/v1 # 指定api版本标签
kind: Deployment # 定义资源的类型/角色,deployment为副本控制器,此处资源类型可以是Deployment、Job、Ingress、Service等
metadata: # 定义资源的元数据信息,比如资源的名称、namespace、标签等信息name: nginx-01 # 定义资源的名称,在同一个namespace空间中必须是唯一的labels: # 定义Deployment资源标签web: nginx-01 # 定义deployment资源需要的参数属性,诸如是否在容器失败时重新启动容器的属性
spec: replicas: 3 # 定义副本数量selector: # 定义标签选择器matchLabels: # 定义匹配标签 web: nginx-01 # 需与 .spec.template.metadata.labels 定义的标签保持一致template: # 定义业务模板,如果有多个副本,所有副本的属性会按照模板的相关配置进行匹配metadata: labels: # 定义Pod副本将使用的标签,需与 .spec.selector.matchLabels 定义的标签保持一致web: nginx-01spec:containers: # 定义容器属性- name: nginx # 定义一个容器名,一个 - name: 定义一个容器image: nginx:1.14 # 定义容器使用的镜像以及版本ports:- containerPort: 80 # 定义容器的对外的端口
1.2 创建资源对象
[root@master01 demo]# kubectl apply -f nginx-dp.yaml
deployment.apps/nginx-01 created
[root@master01 demo]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-01-8449c47886-22tm4 1/1 Running 0 8s
nginx-01-8449c47886-csqhk 1/1 Running 0 8s
nginx-01-8449c47886-zq9z8 1/1 Running 0 8s
1.3 创建 service 服务对外提供访问
[root@master01 demo]# vim nginx-svc.yaml
apiVersion: v1 # Kubernetes API 的版本,指定为 v1
kind: Service # 定义了一个 Service(服务)
metadata: # 包含了服务的元数据,比如名称、标签等name: nginx-svc # 服务的名称labels: # 服务的标签,用于标识和选择相关的资源web: nginx-01 # 服务的标签
spec: # 定义了服务的规格,包括服务类型、端口和选择器type: NodePort # 服务的类型,被设置为 NodePortports: # 服务的端口列表- port: 80 # 服务的端口targetPort: 80 # 服务转发请求的目标端口,设置为 80,与后端 Pod 的容器端口匹配selector: # 定义了用于选择后端 Pod 的标签web: nginx-01 # 选择器的标签,与 Deployment 或 Pod 的标签匹配
1.4 创建 svc 资源对象
[root@master01 demo]# kubectl apply -f nginx-svc.yaml
service/nginx-svc created
[root@master01 demo]# kubectl get pod,svc -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/nginx-01-8449c47886-22tm4 1/1 Running 0 24m 10.244.1.43 node01 <none> <none>
pod/nginx-01-8449c47886-csqhk 1/1 Running 0 24m 10.244.2.34 node02 <none> <none>
pod/nginx-01-8449c47886-zq9z8 1/1 Running 0 24m 10.244.1.44 node01 <none> <none>NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 6d <none>
service/nginx-svc NodePort 10.96.60.107 <none> 80:31646/TCP 10s web=nginx-01
1.5 访问测试
[root@master01 demo]# curl 10.96.60.107
<title>Welcome to nginx!</title>[root@master01 demo]# curl 10.96.60.107 -I
Server: nginx/1.14.2
1.6 port 端口类型
① port
port 是 k8s 集群内部访问 service 的端口,即通过 clusterIP: port 可以从 Pod 所在的 Node 上访问到 service(四层)
② nodePort
nodePort 是外部访问 k8s 集群中 service 的端口,通过 nodeIP: nodePort 可以从外部访问到某个 service
③ targetPort
targetPort 是 Pod 的端口,从 port 或 nodePort 来的流量经过 kube-proxy 反向代理负载均衡转发到后端 Pod 的 targetPort 上,最后进入容器
④ containerPort
containerPort 是 Pod 内部容器的端口,targetPort 映射到 containerPort
2. 部署 redis-yaml 配置
2.1 编辑清单、service yaml 文件
[root@master01 demo]# vim redis-db-svc.yaml
apiVersion: apps/v1
kind: Deployment
metadata:name: redis-dplabels:nosql: redis-01
spec:replicas: 1selector:matchLabels:nosql: redis-01template:metadata:labels:nosql: redis-01spec:containers:- name: redisimage: redis:latestports:- containerPort: 6379
---
apiVersion: v1
kind: Service
metadata:name: redis-svclabels:nosql: redis-01
spec:selector:nosql: redis-01ports:- nodePort: 30001port: 6379protocol: TCPtargetPort: 6379type: NodePort
2.2 创建资源对象
[root@master01 demo]# kubectl apply -f redis-db-svc.yaml[root@master01 demo]# kubectl get pod,svc
NAME READY STATUS RESTARTS AGE
pod/nginx-01-8449c47886-22tm4 1/1 Running 0 60m
pod/nginx-01-8449c47886-csqhk 1/1 Running 0 60m
pod/nginx-01-8449c47886-zq9z8 1/1 Running 0 60m
pod/redis-dp-cd9f5cff6-clhdr 1/1 Running 0 8m25sNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 6d1h
service/nginx-svc NodePort 10.96.60.107 <none> 80:31646/TCP 36m
service/redis-svc NodePort 10.96.203.220 <none> 6379:30002/TCP 77s
2.3 连接 pod 实例
3. 部署 mysql-yaml 配置
3.1 生成模板 yaml 文件
使用 yaml 格式导出生成模板,并进行修改以及删除一些不必要的参数
① 生成并修改命名空间创建 yaml 文件
[root@master01 ~]# kubectl create ns mysql-server -o yaml --dry-run=client > mysql.yaml
[root@master01 ~]# vim mysql.yaml
apiVersion: v1
kind: Namespace
metadata:name: mysql-server
---
② 生成并修改清单创建 yaml 文件
- 追加创建一个 Deployment YAML 文件模板,但不包含环境变量
- 手动编辑 mysql.yaml 文件,添加环境变量、卷挂载
[root@master01 ~]# kubectl create deployment mysql-01 --image=mysql:latest --port=3306 --replicas=1 -n mysql-server --dry-run=client -o yaml >> mysql.yaml
apiVersion: v1 # Kubernetes API 的版本
kind: Namespace # 定义了一个 Namespace
metadata: # 包含了资源的元数据,比如名称、标签等name: mysql-server # Namespace 的名称
--- # 这个分隔符表示 YAML 文件中的两个资源定义之间的分隔
apiVersion: apps/v1
kind: Deployment # 指定了资源类型为 Deploymen
metadata: # 包含了 Deployment 的元数据,比如名称、标签等labels: # Deployment 的标签,用于标识和选择相关的资源app: mysql-01 name: mysql-01 # Deployment 的名称namespace: mysql-server # Deployment 所属的 Namespace
spec: # 定义了 Deployment 的规格,包括副本数量、选择器和 Pod 模板replicas: 1 # Deployment 的副本数量selector: # 定义了用于选择 Pod 的标签matchLabels: # 这是选择器的标签,与 Pod 模板中的标签匹配app: mysql-01 template: # 定义了要创建的 Pod 的模板metadata: # 包含了 Pod 模板的元数据,比如标签等labels: # Pod 模板的标签,用于标识和选择相关的资源app: mysql-01spec: # 定义了 Pod 的规格,包括容器和端口containers:- image: mysql:latest # 容器的镜像,使用的是最新版本的 MySQL 镜像name: mysql # 容器的名称ports: # 容器的端口列表- containerPort: 3306 # 容器的端口env: # 定义环境变量列表- name: MYSQL_ROOT_PASSWORD # 环境变量的名称value: "123123" # 设置MySQL的root密码,也就是环境变量的值
# 当MySQL容器首次启动时,它会检查数据库是否已经初始化,并且如果没有提供密码相关的环境变量,它会报错并退出volumeMounts: # 定义如何挂载卷到容器中- name: mysql-data # 引用的卷的名称mountPath: /var/lib/mysql # 卷在容器中的挂载路径volumes: # 定义Pod中使用的卷列表- name: mysql-data # 卷的名称,与volumeMounts中的name相对应emptyDir: {}
# 一个空目录卷。这种类型的卷在Pod首次被调度到节点上时创建,并在Pod被删除时销毁。它不持久化数据,仅用于临时存储
---
③ 编辑 svc 资源 yaml 文件
由于集群中还未创建 mysql-01,无法使用命令生成模板:kubectl expose service mysql-01 --port=3306 --target-port=3306 --name=mysql-svc --type=NodePort --dry-run=client -o yaml >> mysql.yam
这里手动编辑 yaml 文件:
[root@master01 ~]# vim mysql.yaml
apiVersion: v1 # Kubernetes API 的版本
kind: Namespace # 定义了一个 Namespace
metadata: # 包含了资源的元数据,比如名称、标签等name: mysql-server # Namespace 的名称
--- # 这个分隔符表示 YAML 文件中的两个资源定义之间的分隔
apiVersion: apps/v1
kind: Deployment # 指定了资源类型为 Deploymen
metadata: # 包含了 Deployment 的元数据,比如名称、标签等labels: # Deployment 的标签,用于标识和选择相关的资源app: mysql-01 name: mysql-01 # Deployment 的名称namespace: mysql-server # Deployment 所属的 Namespace
spec: # 定义了 Deployment 的规格,包括副本数量、选择器和 Pod 模板replicas: 1 # Deployment 的副本数量selector: # 定义了用于选择 Pod 的标签matchLabels: # 这是选择器的标签,与 Pod 模板中的标签匹配app: mysql-01 template: # 定义了要创建的 Pod 的模板metadata: # 包含了 Pod 模板的元数据,比如标签等labels: # Pod 模板的标签,用于标识和选择相关的资源app: mysql-01spec: # 定义了 Pod 的规格,包括容器和端口containers:- image: mysql:latest # 容器的镜像,使用的是最新版本的 MySQL 镜像name: mysql # 容器的名称ports: # 容器的端口列表- containerPort: 3306 # 容器的端口env: # 定义环境变量列表- name: MYSQL_ROOT_PASSWORD # 环境变量的名称value: "123123" # 设置MySQL的root密码,也就是环境变量的值
# 当MySQL容器首次启动时,它会检查数据库是否已经初始化,并且如果没有提供密码相关的环境变量,它会报错并退出volumeMounts: # 定义如何挂载卷到容器中- name: mysql-data # 引用的卷的名称mountPath: /var/lib/mysql # 卷在容器中的挂载路径volumes: # 定义Pod中使用的卷列表- name: mysql-data # 卷的名称,与volumeMounts中的name相对应emptyDir: {}
# 一个空目录卷。这种类型的卷在Pod首次被调度到节点上时创建,并在Pod被删除时销毁。它不持久化数据,仅用于临时存储
---
apiVersion: v1
kind: Service # 定义了一个 Service(服务)
metadata: # 包含了服务的元数据,比如名称、标签等name: mysql-service # 服务的名称namespace: mysql-server # 服务所属的 Namespacelabels: # 服务的标签,用于标识和选择相关的资源app: mysql-01 # 服务的标签,与 Deployment 或 Pod 的标签匹配
spec: # 定义了服务的规格,包括服务类型、端口和选择器type: NodePort # 服务的类型,被设置为 NodePortports: # 服务的端口列表- port: 3306 # 服务的端口targetPort: 3306 # 服务转发请求的目标端口selector: # 定义了用于选择后端 Pod 的标签app: mysql-01 # 选择器的标签,与 Deployment 或 Pod 的标签匹配
3.2 创建资源
[root@master01 ~]# kubectl apply -f mysql.yaml
namespace/mysql-server created
deployment.apps/mysql-01 created
service/mysql-service created[root@master01 ~]# kubectl get pod,svc -n mysql-server -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/mysql-01-776dd57c9b-fb5hp 1/1 Running 0 48s 10.244.2.37 node02 <none> <none>NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service/mysql-service NodePort 10.96.103.121 <none> 3306:32316/TCP 68s app=mysql-01
3.3 访问验证
[root@master01 ~]# kubectl exec -it mysql-01-776dd57c9b-fb5hp -n mysql-server bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
root@mysql-01-776dd57c9b-fb5hp:/# mysql -u root -p'123123'
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+