K8S基础知识总结
一、containerd介绍
1.解释
containerd: 底层容器运行时(真正负责创建、启停容器的底层程序)。
容器运行时是实现容器生命周期管理、负责底层容器隔离与启停的底层组件统称.
containerd 是主流容器运行时实现产品之一。
属于【高级容器运行时】,放在整个容器栈底层,所以大家口头叫它"底层容器运行时".
2.containerd与docker
Docker 和 containerd 是包含与依赖关系,containerd 是 Docker 的底层核心组件,负责实际运行容器.
docker 是封装了containerd,额外增加了Dockerfile 构建、docker-compose、私有仓库、网络插件等上层工具。
3.containerd与K8S
在K8S 1.23版本以及以前是需要安装docker的。K8S的调用流程是这样:
K8S kubelet --> dockershim --> dockerd --> containerd --> runc
这里注意的是:
docker本身不是不兼容K8S标准的 CRI接口的,早期K8S是必须通过dockershim进行协议转换,中转调用docker
4.CRI(Container Runtime Interface)
CRI是K8s 官方定义的标准 gRPC 接口规范,目的是:【解耦 kubelet 和底层容器运行时】
K8S只认标准的CRI(Container Runtime Interface),K8S不绑定特定的CRI。
K8S中的kubelet(K8S代理节点)是通过CRI接口和底层进行通信的,
K8S支持两类运行时:
第一种就是containerd(原生CRI,直接通信,无中间层,现在主流)
第二种就是docker(需老旧 dockershim 转换,1.24+ K8s 彻底移除 dockershim,不再原生支持 Docker)
5.K8S现在标准架构
K8s kubelet → CRI 接口 → containerd → runc → Linux内核
1.kubelet 内置了CRI Client(gRPC 客户端),专门用来发送容器操作指令
2.containerd 启动 cri 插件,生成一个 gRPC 服务端,监听在 (/run/containerd/containerd.sock),等待接受请求。
3.kubelet 通过grpc客户端 发送标准 CRI 请求给 containerd
4.containerd 收到 CRI 请求后,转调用 OCI 工具链 runc 创建容器
注意的是:containerd.sock是containerd主进程创建的,由它内部的 cri插件绑定监听。
socket的作用是 传输数据,是电脑上一条无形的本地管道。不管是 kubelet 发消息,还是 containerd 回消息,全部走这个通道传递。
所以在安装K8S的时候所有服务器都需要统一安装containerd
yum install -y containerd.io
二、YAML文件
1.基本规范(硬性规范)
1.缩进只能用空格,禁止使用tab键,标准 2 空格缩进;缩进代表层级关系
2.区分大小写
3.# 为注释
4.短横线 + 空格 表示是数组元素
2.数据类型
2.1 字符串
字符串默认不用引号引起来. 单引号:不转义特殊字符。 双引号:识别转移字符 比如:\t \n
2.2 数字
整数、浮点数直接写
2.3 布尔型
true / false(小写)
2.4 空值
null ,~ ,不写也可以
2.5 对象
缩进表示层级,冒号分割键值
user:
name: 李四
info:
phone: 13800001111
等价于json数据的
{
"user": {
"name":"李四",
"info":
{"phone":"13800001111"}
}
}
2.6.数组
fruits: fruits:
- 苹果 - 苹果
- 香蕉 - 香蕉
- 橘子 - 橘子
等价于json数据的
{
"furits": ["苹果","香蕉","橘子"]
}
2.7 数组和对象嵌套
students:
- name: 小明
id: 001
- name: 小红
id: 002
等价于json数据的
{
"student": [
{"name": "小明", "id": 001},
{"name": "小红", "id": 002},
]
}
三、K8S YAML文件
在K8S的YAML文件中,pod service deploment 等它们的一级key几乎都一样。也是必不可少的
| 一级key名称 | 含义 |
|---|---|
| apiVersion | 资源版本 |
| kind | 定义资源的类型 |
| metadata | 定义元数据(名称、标签、命名空间等) |
| spec | 定义核心配置 |
| status | 里面的内容不需要定义,由kubernetes自动生成 |
环境介绍
| 主机名 | IP地址 | 操作系统 |
|---|---|---|
| k8s-master | 192.168.65.128 | Rocky Linux release 9.8 |
| k8s-node01 | 192.168.65.129 | Rocky Linux release 9.8 |
| k8s-node02 | 192.168.65.131 | Rocky Linux release 9.8 |
安装方式使用kubeadm方式安装。网络插件使用的是calico
[root@k8s-master ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-master Ready control-plane 57m v1.28.2
k8s-node1 Ready <none> 50m v1.28.2
k8s-node2 Ready <none> 49m v1.28.2
四、deployment YAML文件
Deployment是最常用控制器,用于无状态应用(Nginx、Java微服务),支持弹性伸缩、滚动更新、回滚
1.一级key结构
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-deploy
namespace: dev
labels:
app: web
spec:
注意:pod的apiVersion是: v1 控制器的是: apps/v1
这里的metadata里有一个labels属性,这是给控制器打标签,目的是能够通过标签来批量匹配控制器,进行批量操作。比如
# 只列出标签 app=web 的 Deployment
kubectl get deploy -l app=web
# 删除所有 app=web 的deployment
kubectl delete deploy -l app=web
如果不设置标签,只能通过name来进行精确匹配.
注意:通过标签匹配控制器,必须是在同命名空间下匹配,匹配同命名空间下的同标签的控制器,不能跨空间匹配
2.spce字段
| 字段 | 作用 |
|---|---|
| replicas | 设置副本数量,也就是启动pod的数量 |
| selector | 匹配pod,也就是管理哪些pod |
| template | pod模板, |
| strategy | 更新策略 |
| revisionHistoryLimit | 保留历史版本数(用于回滚) |
spce的下的基本参数
spec:
replicas: 定义副本的数量,副本就是pod的数量
selector:
matchlabels:
app: 这里的"值"是控制器匹配nginx pod的"标签的名字",通过匹配这个标签才能管理对应标签的pod
templates: 这个字段下就是定义pod的相关内容
metadata:
labels:
app: 这里定义pod的标签,这里的标签就是上边要匹配的标签,所有上下要一致
spec: 这个字段就是定义具体的pod中的容器的内容了
containers:
- name: 这里是给pod中的容器起一个名字
image:
ports:
- containerPort: 容器服务启动的端口
strategy: 定义pod的更新策略
type:
revisionHistoryLimit: 保留历史版本数量
2.1.spec.containers字段
------------------------------------
workingDir:容器启动后的默认工作目录
1.容器一启动,自动切到该路径
2.不写绝对路径的命令、文件读写、日志生成,都会默认以这个目录为基准
3.覆盖镜像内置的默认工作目录
-----------------------------------
command:
args:
这两个参数一般是同时出现,使用这两个命令的时候一定注意:
现在使用的是nginx的镜像,nginx的启动命令默认是内置在了镜像当中的。
在YMLA文件当中写了command参数,就会完全覆盖了镜像原始的ENTRYPOINT,镜像自带 CMD 直接作废
只写 args 不写 command:用镜像原有 ENTRYPOINT,参数会替换成 args的内容。
例子:
command: ["/bin/sh","-c"]
args:
- mkdir -p /data/testdir && nginx -g "daemon off;"
所以在使用nginx这种镜像时,使用command和args参数一定要注意
2.2 镜像的拉取策略
imagePullPolicy,用于设置镜像拉取策略,kubernetes支持配置三种拉取策略:
(1)Always:总是从远程仓库拉取镜像(一直远程下载 )
(2)IfNotPresent:本地有则使用本地镜像,本地没有则从远程仓库拉取镜像(本地有就本地 本地没远程下载)
(3)Never:只使用本地镜像,从不去远程仓库拉取,本地没有就报错 (一直使用本地)
2.3 资源限制resources
配置资源限制的目的是:避免 Pod 抢占资源,防止单 Pod 耗尽节点资源
kubernetes提供了对内存和cpu的资源进行配额的机制,这种机制主要通过resources选项实现,他有两个子选项:
limits:用于限制运行时容器的最大占用资源,当容器占用资源超过limits时会被终止,并进行重启
requests :用于设置容器需要的最小资源,如果环境资源不够,容器将无法启动。
对于资源限制的标准是:
同时配置 requests 和 limits,requests < limits。
建议配比:CPU 1:2~1:3,内存 1:1.5~1:2
注意:
cpu单位是m(毫核) 1cpu = 1000m
例子:500m(0.5核)、1000m(1核)、2000m(2核)
内存单位:Mi 是MB Gi是GB
例子: 256Mi 1Gi
2.4 环境变量env
containers:
env:
- name: 变量名1
value: 变量值1
- name: 变量名2
value: 变量值2
例子:
env:
- name: file_name
value: /usr/share/nginx/html/index.html
- name: dir_name
value: /usr/local/
进入容器查看变量
root@1726-nginx-deployment-7fbbf99964-cgldj:/data/testdir# echo $file_name
/usr/share/nginx/html/index.html
root@1726-nginx-deployment-7fbbf99964-cgldj:/data/testdir# echo $dir_name
/usr/local/
3.实例
来一份基本版的deployment的YAML文件
apiVersion: apps/v1
kind: Deployment
metadata:
name: 1726-nginx-deployment
namespace: dev
labels:
app: nginx-dep
spec:
replicas: 2
selector:
matchLabels:
app: nginx-pod
template:
metadata:
labels:
app: nginx-pod
spec:
containers:
- name: nginx
image: repos.taikangcloud.com/public-ecr-aws/docker/library/nginx:1.22
imagePullPolicy: IfNotPresent
command: ["/bin/sh","-c"]
args:
- mkdir -p /data/testdir && nginx -g "daemon off;"
workingDir: /data/testdir
ports:
- containerPort: 80
resources:
requests:
cpu: 200m
memory: 256Mi
limits:
cpu: 500m
memory: 512Mi
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
revisionHistoryLimit: 10
创建命名空间
kubectl create ns dev
部署yaml文件
[root@k8s-master yaml_file]# kubectl apply -f dep.yaml
deployment.apps/1726-nginx-depolyment created
# 这里可以看出pod并没有启动成功
[root@k8s-master yaml_files]# kubectl get pod -n dev
NAME READY STATUS RESTARTS AGE
1726-nginx-deployment-5dc5d7768b-5pv7q 1/1 Running 0 17m
1726-nginx-deployment-5dc5d7768b-wfh27 1/1 Running 0 17m
3.1 查看创建的控制器
[root@k8s-master yaml_files]# kubectl get deploy -n dev
NAME READY UP-TO-DATE AVAILABLE AGE
1726-nginx-deployment 2/2 2 2 51m
3.2 查看控制器的标签
[root@k8s-master yaml_files]# kubectl get deploy -n dev --show-labels
NAME READY UP-TO-DATE AVAILABLE AGE LABELS
1726-nginx-deployment 2/2 2 2 52m app=nginx-dep
3.3 查看pod的详细信息
# 查看pod的详细信息
[root@k8s-master yaml_file]# kubectl describe pod 1726-nginx-deployment-5dc5d7768b-5pv7q -n dev
3.4 查看所有pod的详细信息
[root@k8s-master yaml_file]# kubectl describe pod -n dev
3.5 查看pod的IP地址
[root@k8s-master yaml_files]# kubectl get pod -n dev -o wide |awk '{print $6}'
IP
10.244.36.71
10.244.169.132
3.6 进入pod
kubectl -n dev exec -it "Pod名称" -- /bin/bash
这里修改了index.html的内容。得到结论:在K8S中的任意服务上不论是apiserver 还是work node 都可以通过pod的IP 访问pod中的nginx服务
以下是分别在3台服务器上访问,都没有问题
[root@k8s-master ~]# curl 10.244.169.132
nginx02
[root@k8s-node1 ~]# curl 10.244.169.132
nginx02
[root@k8s-node2 ~]# curl 10.244.169.132
nginx02
4.pod更新策略(strategy)
strategy是 Deployment专属字段。常用的有两种类型:
4.1 RollingUpdate
rollingUpdate是滚动更新,生产环境常用。它有两个参数
maxSurge:更新时最多超出期望副本数的 Pod 数量
例子: 比如现在有3个pod 这里的值设置为2,也就说更新的时候做最多有5个pod
maxUnavailable: 更新时最多不可用的 Pod 数量
例子:比如这里的值设置为0 现在的副本数有3个,那么更新时候,一个pod的都不会被删除,
如果设置为1,最多删除1个pod 保证2个可以用
4.2 Recreate
先全部删除旧 Pod,再创建新 Pod,更新期间服务完全中断。
四 service YAML文件
通过以上知识得到结论:
1.K8S 中 Pod 会因重启、扩容、缩容、节点调度发生IP动态变化
2.无法提供固定的 IP 对外提供统一访问入口
1.service简介
Service 是 K8S 核心资源对象,作用是:为一组 Pod 提供固定、稳定的网络访问入口,实现 Pod 负载均衡、服务发现、流量转发,屏蔽后端 Pod 的动态变化
通过service的统一入口地址访问到 pod 中的服务.如下图所示
2.核心工作机制
Service 通过 标签匹配(selector) 关联后端 Pod.
3.service代理模式
| 模式 | 特性 |
|---|---|
| iptables(默认) | 基于内核 iptables 规则转发,性能高,支持负载均衡 |
| ipvs(高性能) | 支持大规模集群、多种负载均衡算法 |
4.service的类型
service通过对spec.type的定义访问类型。
1.CluseterIP(默认):
分配集群内部虚拟固定 IP,仅集群内部 Pod、节点可访问,外网无法访问
自动对后端多 Pod 实现轮询负载均衡
使用场景:微服务内网互相调用(后端服务、数据库、缓存等内部服务)
2.NodePort:
在所有集群节点上开放固定端口(NodePort),集群外部可以通过节点IP:nodeport 访问服务
访问链路为: 集群外部--> "节点IP:NodePort"--> ClusterIP-->后端pod
使用场景:测试环境、临时对外暴露服务,不适合生产大规模使用
3.LoadBalancer:
基于 NodePort 扩展,云厂商(阿里云/腾讯云/AWS)会自动分配公网固定负载均衡 IP
云环境生产环境对外暴露业务服务.裸金属集群无此能力,仅云 K8S 支持
5.YAML配置
5.1 一级字段
apiVersion: v1 这里的版本是固定的
kind: Service
metadate:
name: nginx-svc-1726 这里要注意,svc的名字是不能以数字开头的
namespave:dev
labels:
app: nginx-svc
spec:
5.2 spec字段
| 字段 | 作用 | 备注 |
|---|---|---|
| type | 定义service的类型 | |
| selector | 根据标签来匹配pod | |
| ports | 定义svc暴漏的端口 | |
| clusterIP | 如果不选,集群会自动分配 | 可选 |
6.ClusterIP YAML实例
apiVersion: v1
kind: Service
metadata:
name: nginx-svc-1726
namespace: dev
labels:
app: nginx-svc
spec:
type: ClusterIP
selector:
app: nginx-pod 这个值就是 pod的标签,svc通过这个值来匹配pod
ports:
- port: 80 SVC暴漏的端口
targetPort: 80 这是容器的端口
6.1 创建SVC(service)
[root@k8s-master ~]# kubectl apply -f svc.yaml
service/nginx-svc-1726 created
6.2 查看SVC
这里可以看到svc的类型和IP地址、端口信息
[root@k8s-master ~]# kubectl get svc -n dev
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-svc-1726 ClusterIP 10.97.82.106 <none> 80/TCP 56s
6.3 修改pod内容
为了方便看到负载效果,这里将两个pod的nginx的首页内容修改。修改过程不再写了
[root@k8s-master ~]# kubectl get pod -n dev -o wide |awk '{print $6}'
IP
10.244.169.143
10.244.36.82
分别访问两个pod的内容
[root@k8s-master ~]# curl 10.244.169.143
nginx01
[root@k8s-master ~]# curl 10.244.36.82
nginx02
6.4 访问svc
分别在K8S-master 、k8s-node1、k8s-node2上妇访问SVC地址都可以访问到pod的服务,结果如下
[root@k8s-master ~]# curl 10.97.82.106
nginx02
[root@k8s-master ~]# curl 10.97.82.106
nginx01
[root@k8s-master ~]# curl 10.97.82.106
nginx02
[root@k8s-master ~]# curl 10.97.82.106
nginx02
[root@k8s-master ~]# curl 10.97.82.106
nginx02
[root@k8s-master ~]# curl 10.97.82.106
nginx01
[root@k8s-master ~]# curl 10.97.82.106
nginx01
[root@k8s-master ~]# curl 10.97.82.106
nginx02
[root@k8s-master ~]# curl 10.97.82.106
nginx01
7.修改代理模式方法
但是这里又一个问题,这里的负载效果并不是我们想象中的01–>02–>01–>02的那样轮询效果。
原因是:service默认的代理模式是iptables模式,负载均衡策略是随机分发(数据包随机哈希)
如果想要看到严格的轮询模式就需要用到,可以修改service的代理模式。步骤如下
7.1 修改kube-proxy配置文件
在k8s-master上执行
kubectl edit configmap kube-proxy -n kube-system
找到
mode: "ipvs" 修改为ipvs模式
7.2 滚动重启 kube-proxy 生效
kubectl rollout restart daemonset kube-proxy -n kube-system
7.3 验证效果
此时就是轮询模式了
[root@k8s-master ~]# curl http://10.97.82.106
nginx02
[root@k8s-master ~]# curl http://10.97.82.106
nginx01
[root@k8s-master ~]# curl http://10.97.82.106
nginx02
[root@k8s-master ~]# curl http://10.97.82.106
nginx01
8.NodePort YAML实例
apiVersion: v1
kind: Service
metadata:
name: nginx-svc-1726
namespace: dev
labels:
app: nginx-svc
spec:
type: NodePort 这里的配置改为了nodeport模式
selector:
app: nginx-pod
ports:
- port: 80 SVC暴漏的端口
targetPort: 80 对应pod的端口
8.1 可选参数
在ports下有两个可选参数,如果不写集群会默认分配
nodePort: 30080 定义节点对外开放的端口
protocol: TCP 定义节点端口的协议,此参数值就是TCP协议
8.2 创建SVC
[root@k8s-master ~]# kubectl apply -f svc.yaml
service/nginx-svc-1726 configured
8.3 查看SVC
这里看到了svc的80对应节点的30184端口,默认协议为TCP
[root@k8s-master ~]# kubectl get svc -n dev
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-svc-1726 NodePort 10.97.82.106 <none> 80:30184/TCP 4h29m
8.4 访问结果
在任意服务器上执行都可以
[root@k8s-master ~]# curl 192.168.65.128:30184
nginx02
[root@k8s-master ~]# curl 192.168.65.128:30184
nginx01
[root@k8s-master ~]# curl 192.168.65.128:30184
nginx02
[root@k8s-master ~]# curl 192.168.65.128:30184
nginx01
[root@k8s-master ~]#
通过K8S-node1的IP访问
[root@k8s-master ~]# curl 192.168.65.129:30184
nginx02
[root@k8s-master ~]# curl 192.168.65.129:30184
nginx01
[root@k8s-master ~]# curl 192.168.65.129:30184
nginx02
[root@k8s-master ~]# curl 192.168.65.129:30184
nginx01
通过K8S-node2的IP访问
[root@k8s-master ~]# curl 192.168.65.131:30184
nginx02
[root@k8s-master ~]# curl 192.168.65.131:30184
nginx01
[root@k8s-master ~]# curl 192.168.65.131:30184
nginx02
[root@k8s-master ~]# curl 192.168.65.131:30184
nginx01
8.4 浏览器验证
通过任意一个都可以访问到pod中的服务
192.168.65.131:30184
192.168.65.129:30184
192.168.65.128:30184
但是这里有一个问题,通过浏览器中访问轮询效果不没有那么明显,那是因为浏览器的长连接问题
五、ingress
1.SVC两种类型的缺点
ClusterIP 的问题是 集群外部不能访问,只能集群内部访问
NodePort 的问题是 集群外部可以访问,但是需要占用节点服务器的端口。
基于这种现状,K8S提供了ingress对象
2.ingress 简介
2.1 ingress 资源(YAML)
用户通过YAML文件创建YAML规则,定义域名 路径 对应的service 本身不处理流量
2.2 ingress controller
它是一个实体pod,核心作用就是监听ingress规则,加载规则,实际处理,转发客户流量
2.3 ingress注意点
(1)ingress是七层代理,不支持TCP 和 UDP转发
(2)ingress本身无端口,依赖ingress controller的80和443端口对外提供服务
(3)域名解析必须指向ingress controller所在的节点IP,流量才能进入集群
3.ingress YAML配置
3.1 一级字段
注意:这里没有kind字段
apiVersion: networking.k8s.io/v1
metadata:
name: ingress名字
namespace: 命名空间
annotations: 注解字段,不是注释的字段,是通过这里开启一些功能,比如地址重写,https强制跳转等
spec:
annotations例子:
比如要开启http强转https: ingress.cloud.tencent.com/auto-rewrite: ‘true’
这个参数是通过腾讯云蓝鲸蓝鲸平台页面配置 自动生成的参数。
annotations:
ingress.cloud.tencent.com/auto-rewrite: 'true'
3.2 spec字段
| 字段 | 作用 |
|---|---|
| tls | https证书配置,实现443加密访问 |
| rules | 核心路由规则 |
| pathType | 路径配置规则 |
3.3 tls字段
spec:
tls:
- host: 域名,这里的域名必须要和rules.host中的域名完全配置。这里也支持泛域名"*.tkdental.com".但是证书必须也是通配符证书
secretName: 这里写"存储证书的Secret名称"
rules:
3.4 pathType
1. Prefix:前缀匹配
比如:/test 就会匹配 /test 以及他的子路径
2.Exact: 精确匹配
仅匹配路径完全一致的路径,区分大小写
3.ImplementationSpecific:控制器默认匹配规则,一般来讲使用默认匹配规则。
4 样例ingress YAML文件
spec:
tls:
- hosts: xxx.xxxx.com
secretName: 这里是存储证书的Secret
rules: 路由规则
- host: 域名
http:
paths:
- path: /
pathType: ImplementationSpecific 使用默认匹配规则
backend:
service:
name: 对应service的名称,就是转发到哪个service就写哪个
port:
number: svc端口,写service暴露的端口
- path: /api
pathType: ImplementationSpecific
backend:
service:
name:
port:
number:
六、secret
1.简介
secret是用于存储 “敏感数据”,比如:密码、密钥、数据库账号、TLS证书、私钥、API token等
secret 和confimap的区别就是 confimap是明文普通配置,secret是存放隐私设置。
2.注意点
1.secret仅作base64编码,不是加密,集群内可以直接解码
2.任何能get/list secret的账号都能拿到完整的敏感内容
3.type字段
type的值有4个类型
3.1 Opaque
此类型是默认类型,通用密钥,无格式限制,最常用。如果不声明type字段,默认就会使用这个类型
3.2 kubernetes.io/tls
此类型是专门存放TLS证书链与私钥,固定两个key。然后让ingress.tls引用。命令如下
kubectl create secret tls demo-tls --cert fullchain.pem --key privkey.pem
3.3 kubernetes.io/dockerconfigjson
存放私有镜像仓库登录账号密码,用于 imagePullSecrets
3.4 kubernetes.io/service-account-token
ServiceAccount 自动创建,存放访问集群 API 的 JWT token,无需手动创建。
4.data与stringData
4.1 data
如果使用data字段写入key和值,必须是base64后的值
4.2 stringData
如果使用stringdata字段写入key和值,直接填写明文即可,提交 API 时自动转为 base64 存入 data字段.
仅用于创建 / 更新资源,生效后此字段不会出现在 yaml中
5.YAML配置
apiVersion: v1
kind: Secret
metadata:
name: secret-1726
namespace: dev
stringData:
db_user: root
db_pass: '123456'
system_user: admin
system_pass: '654321'
应用配置
[root@k8s-master secret]# kubectl apply -f secret-1726.yaml
secret/secret-1726 created
查看创建的secret
[root@k8s-master secret]# kubectl get secret -n dev
NAME TYPE DATA AGE
secret-1726 Opaque 4 3m11s
查看详细信息:
这里以yaml格式数据创建的secret,这里可以看到:
1.stringData没有了,自动将值合并到到了data字段中
2.data字段对key的值进行了base64编码
3.在输出的yaml信息中可以到原始的key的值
[root@k8s-master secret]# kubectl get secret -n dev -o yaml
......
data:
db_pass: MTIzNDU2
db_user: cm9vdA==
system_pass: NjU0MzIx
system_user: YWRtaW4=
kind: Secret
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"v1","kind":"Secret","metadata":{"annotations":{},"name":"secret-1726","namespace":"dev"},"stringData":{"db_pass":"123456","db_user":"root","system_pass":"654321","system_user":"admin"}}
type: Opaque
......
6.引用secret
生产环境推荐以 volumes的形式引用secret
具体步骤为:
1.在控制器中的yaml文件中定义一个volumes(卷),卷引用secret
2.在将卷挂载到容器当中
这种形式推荐生产使用,因为这种形式的好处是secret更新时,容器内自动滚动更新secret内容,无需重启Pod
这种形式还支持items映射key文件名、指定权限、单独挂载指定key
6.1 创建测试secret
[root@k8s-master secret]# vim test-secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: test-secret
namespace: dev
stringData:
user: root
password: '123456'
[root@k8s-master secret]# kubectl apply -f test-secret.yaml
secret/test-secret created
[root@k8s-master secret]# kubectl get secret -n dev
NAME TYPE DATA AGE
test-secret Opaque 2 74s
6.2 创建测试deployment
[root@k8s-master yaml_files]# cat test-dep.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: test-deployment
namespace: dev
spec:
replicas: 2
selector:
matchLabels:
app: test-nginx-pod
template:
metadata:
labels:
app: test-nginx-pod
spec:
volumes: "在这里定义一个卷"
- name: secret-vlomues 这里定义卷的名字,容器挂载卷的时候,引用的是这里的名字
secret:
secretName: test-secret 这里是引用的上边定义的secret的名字
containers:
- name: nginx-pod
image: xxxxxxxxx.com/nginx:1.22
ports:
- containerPort: 80
volumeMounts: 这里开始挂载卷
- name: secret-vlomues 引用上边定义的的卷
mountPath: /etc/userinfo 挂载路径,如果目录不存在会自动创建目录。目录下key会变成文件名,文件内容就是key的值
readOnly: true
[root@k8s-master yaml_files]# kubectl apply -f test-dep.yaml
deployment.apps/test-deployment created
6.3 进入容器,查看secret
[root@k8s-master yaml_files]# kubectl -n dev exec -it test-deployment-5df97d6b5b-b7fbp -- /bin/bash
root@test-deployment-5df97d6b5b-b7fbp:/# ls /etc/userinfo/
password user
root@test-deployment-5df97d6b5b-b7fbp:/etc/userinfo# cat user; echo -e "\n"
root
root@test-deployment-5df97d6b5b-b7fbp:/etc/userinfo# cat password; echo -e "\n"
123456
七、configMap
1.简介
configmap(配置映射),是K8S内置的非敏感配置资源对象,用于存储应用的配置信息,专门实现 “配置与容器解耦”。
简单说就是把应用的配置文件、环境变量、启动参数抽离出来统一管理,无需重新打包镜像、无需重启 Pod 即可更新配置。
2.特性
1.明文存储数据
2.数据结构为键值对
3.不能跨命名空间引用
4.pod只读configmap配置,无法修改写入
5.不支持大容量数据,单configmap大小不建议超过1M
6.支持热更新:文件挂载方式可以自动更新,环境变量方式不可以热更新
3.configmap使用场景
应用配置文件:nginx.conf appalication.yaml log配置等
通用环境变量,启动参数、域名、端口、超时时间等
4.创建configmap的方式
4.1 命令行
简单的configmap可以使用命令创建,适用与快速测试
语法:
kubectl create configmap 名称 --from-literal=key=value
例子:
[root@k8s-master yaml_files]# kubectl create configmap test-cmp --from-literal=name="zhangsan" -n dev
configmap/test-cmp created
[root@k8s-master yaml_files]# kubectl get configmap -n dev
NAME DATA AGE
kube-root-ca.crt 1 3d7h
test-cmp 1 10s
4.2 单个文件创建
直接将本地配置文件转为 ConfigMap,key 默认是文件名,value 是文件内容。
例子:
[root@k8s-master nginx-config]# cat nginx.conf
worker_processes auto;
events {
worker_connections 10240;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server_tokens off;
server_names_hash_bucket_size 64;
server_names_hash_max_size 512;
include vhosts/*.conf;
}
nginx-config是创建的configmap名称
[root@k8s-master nginx-config]# kubectl create configmap nginx-config --from-file=./nginx.conf
configmap/nginx-config created
这里可以看到,data字段中的key-value内容
key: nginx.conf 文件名自动作为key
value: nginx.conf的内容作为key的value
[root@k8s-master nginx-config]# kubectl get configmap nginx-config -o yaml
apiVersion: v1
data:
nginx.conf: | "这里的 | 是保留缩进和换行,是多文本必填符号,不能省略"
worker_processes auto;
events {
worker_connections 10240;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server_tokens off;
server_names_hash_bucket_size 64;
server_names_hash_max_size 512;
include vhosts/*.conf;
}
kind: ConfigMap
metadata:
creationTimestamp: "2026-07-16T15:51:19Z"
name: nginx-config
namespace: default
resourceVersion: "441751"
uid: a64e9016-5fec-4eb1-82f1-b9b026450a32
4.3 从整个目录创建
批量加载目录下所有配置文件,每个文件对应一个 key。
kubectl create configmap app-config --from-file=./config/
4.4 YAML文件清单创建
这里一定要注意value内容的格式,一定是在key的子层级,否则会格式错误.在粘贴nginx配置的内容时一定要注意格式
apiVersion: v1
kind: ConfigMap
metadata:
name: test1-nginx-configmap
namespace: dev
data:
nginx.conf: |
worker_processes auto;
events {
worker_connections 10240;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server_tokens off;
server_names_hash_bucket_size 64;
server_names_hash_max_size 512;
include vhosts/*.conf;
}
创建configmap
[root@k8s-master nginx-config]# kubectl apply -f test1-configmap.yaml
configmap/test1-nginx-configmap created
5.引用configmap
引用方法和引用secret的方法一样,推荐使用volumes的方式,因为这种方式支持热更新.这里写了一个nginx配置文件的实例
这里的test1-nginx-configmap应用了上边4.4中例子
下边是定义了另外一个vhosts下载的配置文件的confimap: vhost-admin-configmap
apiVersion: v1
kind: ConfigMap
metadata:
name: vhost-admin-configmap
namespace: dev
data:
admin500.conf: |
server {
listen 80;
server_name admin500.test.com;
root /data/wwwroot/dental-city-web/admin; # 指向 admin 目录
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
}
定了控制器deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: test-deployment
namespace: dev
spec:
replicas: 2
selector:
matchLabels:
app: test-nginx-pod
template:
metadata:
labels:
app: test-nginx-pod
spec:
volumes:
- name: nginxconf-configmap-vlomues 定义第一个卷,将configMap定义成卷的形式
configMap:
name: test1-nginx-configmap 引用configMap的名字,不是configMap中key的名字
- name: admin500conf-configmap-volumes 定义第二卷,,将configMap定义成卷的形式
configMap:
name: vhost-admin-configmap 引用configMap的名字,不是configMap中key的名字
containers:
- name: nginx-pod
image: xxxxxxxx/nginx:1.22
ports:
- containerPort: 80
volumeMounts: 挂载卷
- name: nginxconf-configmap-vlomues 引用定义的第一个卷的名字
mountPath: /usr/share/nginx/nginx.conf 挂载点,挂载点必须是一个文件,文件可以不存在,如果是目录镜像启动失败
subPath: nginx.conf 这里的名字是configmap中key的名字,这个key定义的时候定义为了配置文件的名称,这样就见名知意了
- name: admin500conf-configmap-volumes 引用定义的第二个卷的名字
mountPath: /usr/share/nginx/vhosts/admin500.tkdental.conf
subPath: admin500.conf 这里的名字是configmap中key的名字,这个key定义的时候定义为了配置文件的名称,这样就见名知意了
6.subPath机制
subpath的字面意思是子路径的意思。这里的子路径是指的"卷"内的 "子文件/目录"或者 “key”。不是指的挂载目标的子路径,不要理解错误
如果 mountPath 结尾是目录,不能用 subPath 挂载单个文件到这个目录路径上
subPath 文件只能挂载到文件路径,不能挂载到目录
错误例子:
volumeMounts:
- name: nginxconf-configmap
mountPath: /usr/share/nginx/ # 目标是目录,这里就会报错
subPath: nginx.conf
注意:
subPath 坑:configMap/secret 用 subPath 时,不会自动热更新;不使用 subPath 才会自动更新
7.多个key挂载到目中
上边的subPath 是指定一个key挂载到指定文件中,这样挂载稍微有点繁琐,因为nginx下如果有多个server,就要创建多个configmap 挂载多次
我们可以创建一个configmap,其中创建多个对应server的key,然后这个configmap作为一个目录整个挂载到容器当中
7.1 创建两个configmap
nginx.conf的configmap
[root@k8s-master nginx-config]# cat nginx-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: cm-nginx-main
namespace: dev
data:
nginx.conf: |
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
access_log /var/log/nginx/access.log;
sendfile on;
keepalive_timeout 65;
# 统一加载vhost目录
include /usr/share/nginx/vhosts/*.conf;
}
7.2 创建vhosts目录对应的confimap
[root@k8s-master nginx-config]# cat nginx-vhost-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: cm-nginx-vhosts
namespace: dev
data:
a.com.conf: |
server {
listen 80;
server_name a.com;
location / { root /html; }
}
b.com.conf: |
server {
listen 80;
server_name b.com;
location / { root /html; }
}
c.com.conf: |
server {
listen 80;
server_name c.com;
}
[root
7.3 创建控制器
[root@k8s-master yaml_files]# cat test-dep.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: test-deployment
namespace: dev
spec:
replicas: 2
selector:
matchLabels:
app: test-nginx-pod
template:
metadata:
labels:
app: test-nginx-pod
spec:
volumes:
- name: nginxconf-configmap-vlomues 定义主配置文件的configmap的卷
configMap:
name: cm-nginx-main 引用configmap的名称
- name: nginxvhost-configmap-volumes 定义vhost目录对应的configmap的卷
configMap:
name: cm-nginx-vhosts 引用configmap的名称
containers:
- name: nginx-pod
image: xxxxxx/nginx:1.22
ports:
- containerPort: 80
volumeMounts:
- name: nginxconf-configmap-vlomues 调用卷的名称
mountPath: /usr/share/nginx/nginx.conf 挂载到的目标文件
subPath: nginx.conf 这是configmap中key的名称
- name: nginxvhost-configmap-volumes 调用卷的名称
mountPath: /usr/share/nginx/vhosts 直接挂载到目录下,没有使用subPath参数,使用就会报错
7.4 验证
这里看到cm-nginx-vhosts的configmap中的多个key被映射到了vhosts目录下,以多个文件的形式存在。
root@test-deployment-7f4797489d-8jmnn:/usr/share/nginx/vhosts# ls
a.com.conf b.com.conf c.com.conf
root@test-deployment-7f4797489d-8jmnn:/usr/share/nginx/vhosts# pwd
/usr/share/nginx/vhosts
8.items 选择性挂载
缺点:
items 也不支持configmap配置的热更新,以下只是演示items的用法
8.1 configmap
configmap内容如下:
[root@k8s-master nginx-config]# cat nginx-vhost-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-vhost-configmap
namespace: dev
data:
a.com.conf: |
server {
listen 80;
server_name a.com;
location / { root /html; }
}
b.com.conf: |
server {
listen 80;
server_name b.com;
location / { root /html; }
}
c.com.conf: |
server {
listen 80;
server_name c.com;
}
8.2 创建configmap
[root@k8s-master nginx-config]# kubectl apply -f nginx-vhost-configmap.yaml
configmap/nginx-vhost-configmap created
[root@k8s-master nginx-config]# kubectl get configmap -n dev
NAME DATA AGE
nginx-vhost-configmap 3 2m6s
8.3 创建对应的deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: 1726-nginx-deployment
namespace: dev
labels:
app: nginx-dep
spec:
replicas: 2
selector:
matchLabels:
app: nginx-pod
template:
metadata:
labels:
app: nginx-pod
spec:
volumes: 创建卷
- name: nginx-cfm-volumes 给卷起一个名称
configMap:
name: nginx-vhost-configmap 引用configmap
items: items选项是可以不写,像上边的例子中就是,如果不写就是挂载configmap中全部的key。
- key: a.com.conf 挂载第一个key
path: administrator.com.conf
- key: b.com.conf 挂载第二个key
path: benet.com.conf 这两处的path不是挂载路径,千万要注意,这里给key做了一个重命名,但也可以和key保持一致。这里特意不一样,来验证重命名的效果
containers:
- name: nginx
image: xxxxxxx/nginx:1.22
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
volumeMounts: 挂在卷
- name: nginx-cfm-volumes 引用要挂载的卷的名名称
mountPath: /etc/nginx/conf.d 挂载的目录,这里就没有使用subpath
8.4 验证
root@1726-nginx-deployment-59668458b6-jt2qj:/etc/nginx/conf.d# pwd
/etc/nginx/conf.d
这里可以看到成功挂载了两个key,并且给key做了重命名
root@1726-nginx-deployment-59668458b6-jt2qj:/etc/nginx/conf.d# ls
administrator.com.conf benet.com.conf
更多推荐
所有评论(0)