一、服务发现
1. Service:为 Pod 提供固定访问入口与负载均衡。
Service在Kubernetes中是一个核心抽象,简写为“svc”,用于定义Pod的逻辑集合及其访问策略。Pod不能直接提供给外网访问,需要通过Service实现k8s集群内部网络调用。Service实现了Pod的抽象和访问控制,使得应用服务更加灵活和可靠,通过Service可以方便地管理和访问集群中的Pod资源。它将Pod集合暴露出来,作为服务提供给外部访问。对外表现为一个统一的访问入口,请求会经过负载均衡机制,然后转发到后端具体的Pod容器。
2. Ingress:管理 HTTP/HTTPS 路由规则(需配合 Ingress Controller),用于将K8s内部服务安全地暴露给外部网络访问,通过反向代理和七层负载均衡技术,实现外部流量的高效分发。常用于Web应用的入口,提供稳定的访问入口和智能的流量调度能力。
Ingress 与 Service 在 Kubernetes 中虽然都用于服务暴露和流量管理,但定位和功能有本质区别,以下是核心差异的总结。
1、Service
1. 核心作用:实现 Pod 集群的内部服务发现与负载均衡,提供稳定的虚拟 IP(ClusterIP)和端口,屏蔽后端 Pod 的变动。
2. 通信场景:
- 集群内服务间通信(ClusterIP 类型)
- 通过 NodePort/LoadBalancer 向外暴露基础服务(TCP/UDP 协议)。
2、Ingress
1. 核心作用:作为 HTTP/HTTPS 流量的统一入口,提供基于域名、路径的路由规则,支持 SSL 终止、重定向等高级功能。
2. 依赖组件:必须配合 Ingress Controller(如 Nginx、Traefik)实现实际流量转发。
特性 | Service | Ingress |
工作层级 | 传输层(TCP/UDP) | 应用层(HTTP/HTTPS) |
负载均衡 | 基于 IP + 端口的轮询 | 基于域名/URL 路径的智能路由 |
外部暴露能力 | 需 NodePort/LoadBalancer 类型支持 | 天然设计为外部流量入口 |
SSL 支持 | 不支持终止 HTTPS | 支持 SSL 证书管理与终止 |
配置复杂度 | 简单(无额外依赖) | 较高(需独立部署 Ingress Controller) |
Service 是 Ingress 的基础设施:Ingress 规则最终将流量导向后端 Service,由 Service 完成最终到 Pod 的负载均衡。逻辑链:外部请求 → Ingress 按规则路由 → Service 负载均衡 → Pod。
总结:
- Service = 内部通信管家:专注解决 Pod 间的稳定访问与基础负载均衡。
- Ingress = 外部流量指挥官:提供精细化 HTTP 路由与安全控制,依赖 Controller 实现。
两者协同工作,共同构建 Kubernetes 服务网络体系。
1、Service
1、创建Service
编写一个nginx-svc.yaml文件,用于创建Service对象。
apiVersion: v1 # Service api的版本
kind: Service # 资源类型,此处是Service,即创建Service类型的对象
metadata: # Service对象的元数据信息
name: nginx-svc # Service对象的名称
labels: # 标签配置,以key: value的形式给Service对象打标签
app: nginx
spec: # Service对象的期望状态
selector: # 标签选择器,用于匹配哪些Pod会被该Service对象代理
app: nginx-deploy # 匹配到这些标签的Pod都可以通过该Service进行访问
ports: # 定义端口配置
- port: 80#Service对象的端口,集群内其他服务通过<service-name>.<namespace>:port访问
targetPort: 80 # 目标Pod的实际端口,可以是数字或Pod中定义的端口名称
name: web # 为端口起个名字,当Pod暴露多个端口时特别有用
type: NodePort # 服务类型,默认为ClusterIP
服务类型NodePort表示随机启动一个端口(30000-32767),映射到ports中的端口,该端口是直接绑定在node上的,且集群中的每个node都会绑定这个端口。
服务类型 | 描述 | 典型使用场景 |
ClusterIP | 默认类型,分配集群内IP | 内部服务通信 |
NodePort | 在ClusterIP基础上增加节点端口 | 开发测试环境 |
LoadBalancer | 集成云厂商LB服务 | 生产环境公网暴露 |
ExternalName | 返回CNAME记录 | 集成外部服务 |
Pod、Deployment 和 Service 的协作:
1. 使用Deployment 创建和管理 Pod:
- Deployment 通过 ReplicaSet 确保指定数量的 Pod 副本运行。
- 负责 Pod 的创建、更新、扩缩容和自愈。
2. Service 暴露 Pod:
- Service 通过标签选择器(Label Selector)关联到 Pod。
- 提供稳定的访问入口(ClusterIP/NodePort/LoadBalancer)。
- 实现负载均衡,将请求分发到后端 Pod。
3. 协作流程示例:
# 1. 创建 Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.23
ports:
- containerPort: 80
# 2. 创建 Service
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
type: LoadBalancer
4. 工作流程:
- 用户创建 Deployment。
- Deployment 创建 ReplicaSet,ReplicaSet 创建 Pod。
- Service 通过标签选择器发现并关联这些 Pod。
- 外部请求到达 Service,Service 负载均衡到后端 Pod。
2、代理kubernetes外部服务
集群内部的服务如何访问集群外部的服务呢?可以通过Service反向代理集群外部服务来实现集群内部服务访问集群外部服务,常用的实现方式有以下两种。
实现方式一:
1. 编写Service配置文件时,不指定selector属性(指定selector属性时会自动创建Endpoints)。
2. 自己手动编写yaml文件创建Endpoints。
编写一个nginx-svc-external.yaml文件,用于创建不带selector选择器的Service对象。
apiVersion: v1 # Service api的版本
kind: Service # 资源类型,此处是Service,即创建Service类型的对象
metadata: # Service对象的元数据信息
name: nginx-svc- external # Service对象的名称
labels: # 标签配置,以key: value的形式给Service对象打标签
app: nginx
spec: # Service对象的期望状态
ports: # 定义端口配置
- port: 80#Service对象的端口,集群内其他服务通过<service-name>.<namespace>:port访问
targetPort: 80 # 目标Pod的实际端口,可以是数字或Pod中定义的端口名称
name: web # 为端口起个名字,当Pod暴露多个端口时特别有用
type: ClusterIP # 服务类型,默认为ClusterIP
编写一个nginx-ep-external.yaml文件创建Endpoints对象。
apiVersion: v1
kind: Endpoints # 资源类型,Endpoints表示端点资源,用于存储服务的实际IP地址和端口
metadata: # Endpoints对象的元数据信息,包含对象的标签、名称和命名空间等
labels:
app: nginx # 给Endpoints对象打标签,必须与Service保持一致
name: nginx-svc-external # Endpoints对象名称,必须与Service对象名称一致
namespace: default # 命名空间,必须与Service保持一致
subsets: # 子网配置信息
- addresses:
- ip: 120.78.159.117 # 目标IP地址,服务访问的实际集群外部地址
ports: # 端口配置,必须与Service保持一致
- name: web # 端口名称,用于标识服务访问的端口
port: 80 # 端口号,服务监听的端口
protocol: TCP # 协议类型,TCP表示传输控制协议
使用kubectl apply(或create) -f nginx-ep-external.yaml命令创建Endpoints对象。
实现方式二:
上面那种反向代理集群外部服务的方式需要在创建Endpoints的配置文件中写上外部服务的IP地址,下面这种方式是在Service配置文件中写上外部服务的域名,通过域名访问外部服务。
apiVersion: v1 # Kubernetes的API版本,v1表示核心组的核心版本
kind: Service # 资源类型,这里表示定义一个Service资源
metadata:
labels:
app: wolfcode-external-domain # 标签,用于标识该Service对象
name: wolfcode-external-domain # Service对象的名称
spec:
type: ExternalName # Service的类型,ExternalName表示这是一个指向外部资源的Service
externalName: www.wolfcode.cn # 外部资源的名称,Service会将请求转发到这个域名
2、Ingress
参考:Ingress | Kubernetes (k8s中文文档)
Ingress 是对集群中服务的外部访问进行管理的 API 对象,典型的访问方式是 HTTP。Ingress 可以提供负载均衡、SSL 终结和基于名称的虚拟托管。Ingress 提供从集群外部到集群内服务的 HTTP 和 HTTPS 路由。 流量路由由 Ingress 资源所定义的规则来控制。
Ingress控制器负责完成 Ingress 的工作,具体实现上通常会使用某个负载均衡器,不过也可以配置边缘路由器或其他前端来帮助处理流量。必须拥有一个Ingress控制器(如 ingress-nginx)才能满足Ingress的要求,仅创建Ingress资源本身没有任何效果。
1、Ingress控制器
在安装Ingress控制器(ingress-nginx)之前需要先安装Helm,Helm是kubernetes中的包管理器。
安装Helm的步骤:
1. 下载helm压缩包并解压,官网下载地址:https://github.com/helm/helm/releases
wget https://get.helm.sh/helm-v3.2.3-linux-amd64.tar.gz
可以通过wget命令在线下载,或者打开官网地址手动下载之后上传到Linux服务器上。
2. 将解压后目录下的helm程序复制到/usr/local/bin/目录下,并通过helm version验证是否安装成功。
Helm安装成功之后,接下来安装ingress-nginx控制器。
1. 首先将ingress-nginx的官网URL添加到Helm仓库:
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
2. 查看仓库列表,搜索ingress-nginx,并拉取ingress-nginx,得到一个压缩包
helm repo list
helm search repo ingress-nginx
helm pull ingress-nginx/ingress-nginx
mv ingress-nginx-4.4.2.tgz /opt/k8s/helm/
cd /opt/k8s/helm
3. 解压之后修改values.yaml文件
tar -xf ingress-nginx-4.4.2.tgz
cd ingress-nginx
vim values.yaml
在values.yaml文件中修改如下内容:
(1)修改controller的仓库和镜像,并将哈希值校验注释掉
registry: registry.cn-hangzhou.aliyuncs.com
image: google_containers/nginx-ingress-controller
(2)按照下图所示修改kube-webhook
registry: registry.cn-hangzhou.aliyuncs.com
image: google_containers/kube-webhook-certgen
tag: v1.5.1
(3)给DaemonSet的nodeSelector添加ingress: "true"
(4)将hostNetwork的值修改成true,并将dnsPolicy的值修改成ClusterFirstWithHostNet。
(5)将Service的type改成ClusterIP,并将admissionWebhooks的enabled属性改成false。
4. values.yaml文件修改完成之后,为ingress单独创建一个命名空间,并为需要部署ingress的节点(不是主节点)添加标签。由于Kubernetes 污点(Taints)的原因,不能在Master节点上创建Pod,所以即使给Master节点添加标签,也没有任何效果。
kubectl create ns ingress-nginx
kubectl label node k8s-node1 ingress=true
5. 安装ingress-nginx,并指定上面刚创建的命名空间ingress-nginx(注意:最后有个点)
helm install ingress-nginx -n ingress-nginx .
6. 验证是否安装成功,查看命名空间ingress-nginx中是否有名称以ingress-nginx-controller为前缀的Pod对象被创建,如果有,则说明ingress-nginx控制器安装成功。
Kubernetes污点(Taints):污点是定义在节点上的键值型属性数据(格式为 key=value:effect),用于控制 Pod 调度策略。其核心作用是通过以下三种排斥等级(effect)实现节点对 Pod 的筛选:
- NoSchedule:禁止新 Pod 调度到该节点(已有 Pod 不受影响)。
- PreferNoSchedule:尽量避免调度,属于柔性限制。
- NoExecute:不仅禁止新调度,还会驱逐已运行但不满足容忍的 Pod。
Maste节点默认污点:Kubernetes 集群初始化时,Master 节点会自动添加 node-role.kubernetes.io/master:NoSchedule 污点,主要出于以下原因考虑:
- 安全隔离:防止业务 Pod 访问控制平面组件(如 etcd、kube-apiserver)。
- 资源保障:避免业务负载抢占Master节点的 CPU/内存资源,导致集群控制面不稳定。
- 职责分离:Master 节点应专注运行集群核心组件(如 scheduler、controller-manager)。
禁止在Master节点部署 Ingress-Nginx 的原因
1. 污点冲突
Ingress-Nginx 的 Pod 默认不带容忍 Master 污点的配置,导致调度失败。虽然可通过添加以下容忍强制部署,但会违反最佳实践:
tolerations:
- key: "node-role.kubernetes.io/master"
operator: "Exists"
effect: "NoSchedule"
2. 架构风险
- 单点故障:Master节点本身具有高可用要求,叠加 Ingress 流量会放大故障影响。
- 性能瓶颈:Ingress作为流量入口需要较高网络带宽,可能干扰控制面组件的网络通信。
- 安全暴露:Master节点通常位于内网隔离区,直接暴露 Ingress 会扩大攻击面。
3. 替代方案
- 专用节点:通过节点选择器将 Ingress 部署到指定 Worker 节点。
- DaemonSet 模式:配合节点亲和性在所有 Worker 节点均匀部署。
- 云厂商方案:如 AWS ALB Ingress Controller 直接集成云负载均衡器。
# 检查Master节点污点
kubectl describe node <master-node-name> | grep Taints
# 安全移除污点(仅测试环境)
kubectl taint nodes <master-node-name> node-role.kubernetes.io/master:NoSchedule-
2、Ingress
在上面成功安装Ingress控制器ingress-nginx之后,下面开始创建并使用ingress。
编写一个yaml文件用于创建Ingress对象。
apiVersion: networking.k8s.io/v1 # API版本,指定使用Kubernetes网络扩展API的v1版本
kind: Ingress # 资源类型,声明这是一个Ingress资源
metadata:
name: wolfcode-nginx-ingress # 资源名称,Ingress资源的唯一标识
annotations: # 注解,用于存储额外的非标识性元数据
kubernetes.io/ingress.class: "nginx" # Ingress类型注解,指定使用nginx Ingress控制器
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules: # 规则列表,定义Ingress的路由规则
- host: k8s.wolfcode.cn # 域名配置,指定该规则适用于哪个域名
http:
paths: # 路径列表,定义具体的路由路径
- pathType: Prefix # 路径类型,Prefix表示前缀匹配
backend: # 后端配置,指定请求转发到的后端服务
service:
name: nginx-svc # 服务名称,指定代理到哪个Service对象
port: # 服务端口,Service对象的端口
number: 80
path: /api # 路径前缀,匹配请求的URL路径部分,类似于nginx的路径前缀匹配
也可以使用多域名和多路径的配置:
路径类型
Ingress 中的每个路径都需要有对应的路径类型(Path Type)。未明确设置 pathType 的路径无法通过合法性检查。当前支持的路径类型有三种:
- ImplementationSpecific:对于这种路径类型,匹配方法取决于 IngressClass。 具体实现可以将其作为单独的 pathType 处理或者作与 Prefix 或 Exact 类型相同的处理。
- Exact:精确匹配 URL 路径,且区分大小写。
- Prefix:基于以 / 分隔的 URL 路径前缀匹配。匹配区分大小写, 并且对路径中各个元素逐个执行匹配操作。 路径元素指的是由 / 分隔符分隔的路径中的标签列表。 如果每个 p 都是请求路径 p 的元素前缀,则请求与路径 p 匹配。
类型 | 路径 | 请求路径 | 匹配与否? |
Prefix | / | (所有路径) | 是 |
Exact | /foo | /foo | 是 |
Exact | /foo | /bar | 否 |
Exact | /foo | /foo/ | 否 |
Exact | /foo/ | /foo | 否 |
Prefix | /foo | /foo, /foo/ | 是 |
Prefix | /foo/ | /foo, /foo/ | 是 |
Prefix | /aaa/bb | /aaa/bbb | 否 |
Prefix | /aaa/bbb | /aaa/bbb | 是 |
Prefix | /aaa/bbb/ | /aaa/bbb | 是,忽略尾部斜线 |
Prefix | /aaa/bbb | /aaa/bbb/ | 是,匹配尾部斜线 |
Prefix | /aaa/bbb | /aaa/bbb/ccc | 是,匹配子路径 |
Prefix | /aaa/bbb | /aaa/bbbxyz | 否,字符串前缀不匹配 |
Prefix | /, /aaa | /aaa/ccc | 是,匹配 /aaa 前缀 |
Prefix | /, /aaa, /aaa/bbb | /aaa/bbb | 是,匹配 /aaa/bbb 前缀 |
Prefix | /, /aaa, /aaa/bbb | /ccc | 是,匹配 / 前缀 |
Prefix | /aaa | /ccc | 否,使用默认后端 |
混合 | /foo (Prefix), /foo (Exact) | /foo | 是,优选 Exact 类型 |
修改Windows上的etc/hosts文件,添加ingress-nginx控制器的Pod对象所在节点IP与域名(k8s.wolfcode.cn)的映射关系。
在Windows浏览器上访问k8s集群中在k8s-node1节点上创建的Pod对象中的nginx服务。路径中的/api就是在创建Ingress的yaml文件中配置的path。
二、配置管理
ConfigMap:Kubernetes 中用于存储非敏感配置数据(如环境变量)的 API 对象,通过键值对(key-value)形式管理配置信息。与 Secret 不同,ConfigMap 禁止存储密码、密钥等敏感数据(敏感数据需使用 Secret)。其主要特性包括:
- 运行时更新:修改 ConfigMap 数据后,关联的 Pod 会自动同步更新(无需重启容器),适用于动态调整参数。
- 多环境适配:同一镜像通过不同 ConfigMap 配置,可快速部署到开发、测试、生产环境。
- 数据解耦:将应用程序配置(如环境变量、配置文件、命令行参数)与容器镜像分离,避免硬编码配置,提升镜像的可移植性。
- 数据类型支持:存储纯文本、JSON、YAML 等格式的数据,支持直接挂载为文件或注入为环境变量。
- 命名空间隔离:属于命名空间(Namespace)级别资源,仅限同一命名空间内的 Pod 访问。
Secret:存储敏感数据(如密码、密钥),无需将密码、token、密钥等敏感数据暴露到镜像或Pod Spec中,可以以Volume或环境变量的方式被Pod使用。Secret有三种加密方式:
- Service Account:自动创建并挂载,用于访问Kubernetes API。
- Opaque:存储base64编码的密码、密钥等。
- kubernetes.io/dockerconfigjson:用于存储私有Docker仓库的配置信息。
1、ConfigMap
在Kubernetes中,创建ConfigMap对象的方式有以下几种:
1. 基于文件夹创建:
使用--from-file参数指定文件夹路径,如kubectl create configmap my-config --from-file=path/to/bar。
2. 基于某个或某些文件创建:
使用--from-file参数指定文件路径,如kubectl create configmap my-config --from-file=/path/to/bar/application.yaml。
可以明确指定文件与ConfigMap中的键值对应关系,如kubectl create configmap my-config --from-file=key1=/path/to/bar/file1.txt --from-file=key2=/path/to/bar/file2.txt。
3. 从字面值创建:
直接使用--from-literal参数指定键值对,如kubectl create configmap my-config --from-literal=key1=config1 --from-literal=key2=config2。
4. 从文件中的键值对创建:
如果文件内容本身就是key=value键值对格式,可以直接使用--from-file参数,如kubectl create configmap my-config --from-file=path/to/bar(注意与第一种方式区分文件内容)。
5. 从环境文件创建:
使用--from-env-file参数指定包含环境变量的文件,如kubectl create configmap my-config --from-env-file=path/to/foo.env --from-env-file=path/to/bar.env。
在Pod和Deployment中使用环境变量的方式主要有以下三种方式:
1. 通过envFrom或configMapKeyRef引用ConfigMap/Secret的变量
- 单个变量引用:通过configMapKeyRef或secretKeyRef指定来源:
env:
- name: DB_TIMEOUT
valueFrom:
configMapKeyRef:
name: app-config
key: db.timeout
- 批量注入:使用envFrom导入全部变量:
envFrom:
- configMapRef:
name: app-config
2. 将ConfigMap/Secret中的变量定义为数据卷,通过volumeMounts挂载到Pod/Deployment:
spec:
containers:
- name: config-test # 容器名称,Pod 中容器的名字
image: alpine # 容器镜像,容器使用的镜像
volumeMounts: # 数据卷挂载配置
- name: db-config # 数据卷名称,引用volumes中定义的数据卷
mountPath: "/usr/local/mysql/conf" # 挂载路径,数据卷挂载到容器内的路径
volumes: # 定义数据卷
- name: db-config # 数据卷名称,定义数据卷的名称
configMap: # 数据卷类型为ConfigMap
name: test-dir-config # ConfigMap名称,表示从哪个ConfigMap中读取环境变量
items:
- key: "db.properties" # ConfigMap中的key,指定ConfigMap中的键
path: "db.properties" # 将键的值作为文件内容,文件名为path指定的名称
例如,下面这个创建Pod的yaml文件,基于方式一,从名为test-env-config的ConfigMap中获取键为JAVA_OPTS_TEST的值赋给环境变量JAVA_VM_OPTS,并获取键为APP_NAME的值赋给环境变量APP。另外,基于方式二,从名为test-dir-config的ConfigMap中获取环境变量定义为数据卷,再通过volumeMounts挂载到容器内某个路径,从而可以被容器使用。
apiVersion: v1 # Kubernetes API 版本,定义了使用的 Kubernetes API 的版本。
kind: Pod # 资源类型,指明这是一个 Pod 资源。
metadata:
name: test-configfile-po # Pod 名称,用于唯一标识这个 Pod。
spec:
containers:
- name: config-test # 容器名称,Pod 中容器的名字。
image: alpine # 容器镜像,容器使用的镜像。
command: ["/bin/sh", "-c", "sleep 3600"] # 容器启动命令,容器启动时执行的命令。
imagePullPolicy: IfNotPresent # 镜像拉取策略,如果不存在镜像则拉取。
env:
- name: JAVA_VM_OPTS # 环境变量名,设置环境变量JAVA_VM_OPTS
valueFrom:
configMapKeyRef:
name: test-env-config # ConfigMap名称,从名为test-env-config的ConfigMap中获取值
key: JAVA_OPTS_TEST #获取键为JAVA_OPTS_TEST的值赋给变量JAVA_VM_OPTS
- name: APP # 环境变量名,设置环境变量APP
valueFrom:
configMapKeyRef:
name: test-env-config # ConfigMap名称,从名为test-env-config的ConfigMap中获取值
key: APP_NAME # 从ConfigMap中获取键为APP_NAME的值赋给环境变量APP
volumeMounts: # 数据卷挂载配置
- name: db-config # 数据卷名称,引用volumes中定义的数据卷
mountPath: "/usr/local/mysql/conf" # 挂载路径,数据卷挂载到容器内的路径
readOnly: true # 是否只读(默认为false),数据卷以只读方式挂载
volumes: # 定义数据卷
- name: db-config # 数据卷名称,定义数据卷的名称
configMap: # 数据卷类型为ConfigMap
name: test-dir-config # ConfigMap名称,指定数据卷使用的ConfigMap
items: #若不配置items,会将ConfigMap中所有键的值保存到与键同名的文件中
- key: "db.properties" # ConfigMap中的key,指定ConfigMap中的键
path: "db.properties" # 将键的值作为文件内容,文件名为path指定的名称
restartPolicy: Never # 重启策略,Pod 失败后不重启
下面这个名为test-dir-config的ConfigMap中包含两个key,分别是dp.properties和redis.properties,也就是两个配置文件,这两个配置文件中分别配置了环境变量。如果只想从ConfigMap中加载一个文件中的环境变量,就通过volumes.configMap.items.key指定使用哪个配置文件,例如上面方式二中通过key: "db.properties"指定使用db.properties文件中的环境变量。如果没有配置volumes.configMap.items,就会从ConfigMap中加载所有文件的环境变量,会自动生成与key同名的文件保存每个配置文件中的环境变量,再通过容器中的volumeMounts挂载这些文件在容器中使用。
3. 在Pod/Deployment中直接定义环境变量
通过env字段显式设置键值对:
env:
- name: LOG_LEVEL
value: "INFO"
这种方式适用于静态配置场景。
subPath的作用:
假设Pod或Deployment的容器挂载路径/etc/nginx/目录下有多个子目录和文件,通过ConfigMap挂载的方式会将volumes.configMap.items.path中配置的文件完全替换掉容器内/etc/nginx/目录下的所有子目录和文件,可以通过在volumeMounts中添加subPath解决这个问题。subPath的值与volumes.configMap.items.path的值保持一致,且不能以/开头,这样只会精准替换掉容器内/etc/nginx/目录下与volumes.configMap.items.path配置的同名文件,不会对其他文件和目录产生影响。
但是,如果使用subPath,更新ConfigMap中的环境变量配置不会自动更新到Pod中。
subPath 方式为何不会更新?
1. 独立副本机制
subPath 挂载时,Kubernetes 会在 Pod 启动时将 ConfigMap/Secret 文件拷贝一份到容器的本地文件系统(通常是临时目录),后续 ConfigMap 的更新不会影响这份独立副本。
设计目的:防止多个 subPath 指向同一份数据时的冲突,并确保容器文件的独立性。
2. 与目录挂载的差异
直接挂载整个目录(非 subPath)会通过符号链接动态更新,而 subPath 是静态文件拷贝。
更新ConfigMap中的配置是否会更新到Pod中,主要取决于以下几种情况:
- 默认挂载方式(不带subPath):会更新,更新周期是更新时间加上缓存时间。
- subPath挂载方式:不会更新。如需更新,可取消subPath使用,将配置文件挂载到不存在目录,再利用软连接链接到目标位置。
- 引用变量形式:如果Pod中的变量是从ConfigMap或Secret中获取,同样不会更新。
方式 | 是否支持动态更新 | 注意事项 |
目录挂载 | ✅ 是 | 需应用监听文件变化或工具配合 |
引用变量 | ❌ 否 | 必须重启 Pod |
subPath 挂载 | ❌ 否 | 需重建 Pod |
配置的热更新方式:
更新ConfigMap中的配置之后,若要使得变更自动更新到Pod中,可以通过volumes和volumeMounts这种默认挂载方式实现。更新ConfigMap配置实现Pod的热更新有两种方式。
1. 通过kubectl edit cm <ConfigMap对象名称> 命令直接修改ConfigMap中的配置
2. 先修改创建ConfigMap对象的文件,然后通过kubectl create cm <ConfigMap对象名称> --from-file=<yaml文件或yaml文件所属目录> --dry-run -o yaml | kubectl replace -f- 命令将修改的yaml文件内容替换已创建的<ConfigMap对象名称>对应属性的值。
例如:kubectl create cm test-dir-config --from-file=./test/ --dry-run -o yaml | kubectl replace -f-
上面这条命令通过管道符(|)连接两个命令,左边的命令会将创建test-dir-config使用的文件内容输出到一个yaml文件中,右边的命令-f后面还有一个-,用于接收左边命令输出的yaml文件。
名称为test-dir-config的ConfigMap对象是通过test目录下的db.properties和redis.properties文件创建的,先修改db.properties文件中的环境变量,然后执行上述命令就可以修改test-dir-config中对应属性的值,进而修改挂载这个ConfigMap的Pod中变量的值。
2、Secret
Kubernetes中创建Secret的方式有以下几种:
1. 从字面值创建:使用kubectl create secret generic命令,直接指定用户名和密码等字面值。
密码最好用单引号包起来。
kubectl create secret generic <Secret对象名称> --from-literal=key1=value1 --from-literal=key2= value2
说明:generic 表示通用类型 Secret,--from-literal 直接注入明文值(自动 Base64 编码)。
例如:
kubectl create secret generic db-secret --from-literal=username=admin --from-literal=password= 'S3cr3tP@ss'
2. 从文件创建:同样使用kubectl create secret generic命令,但指定文件路径来创建Secret。
将文件内容作为 Secret 的值,适用于证书或配置文件:
kubectl create secret generic <Secret对象名称> --from-file=db-password=<文件>
例如:kubectl create secret generic file-secret --from-file=db-password=./password.txt
说明:文件内容会被自动编码,键名可自定义(如 db-password)。
3. 从目录创建:也是通过kubectl create secret generic命令,不过是指定目录路径。
批量导入目录下的所有文件:
kubectl create secret generic <Secret对象名称> --from-file=<目录>
例如:kubectl create secret generic dir-secret --from-file=./configs/
说明:目录内每个文件生成一个键值对,键名为文件名。
4. Docker注册表Secret:使用kubectl create secret docker-registry命令,专为Docker注册表创建。
存储私有镜像仓库认证信息,专用于拉取私有镜像,类型为 kubernetes.io/dockerconfigjson。
例如:
kubectl create secret docker-registry reg-secret \
--docker-username=user \
--docker-password=pass \
--docker-server=registry.example.com
5. TLS Secret:使用kubectl create secret tls命令,用于创建TLS类型的Secret。
存储 HTTPS 证书和私钥,类型为 kubernetes.io/tls,证书和私钥需预先准备。
例如:
kubectl create secret tls tls-secret \
--cert=./tls.crt \
--key=./tls.key
6. 通过YAML 声明式创建
通过yaml配置文件定义 Secret(以 Opaque 类型为例):
apiVersion: v1
kind: Secret
metadata:
name: yaml-secret
type: Opaque
data:
username: YWRtaW4= # admin 的 Base64 编码
password: UzNjcjN0UHBzcw== # S3cr3tP@ss 的编码
说明:需手动对值进行 Base64 编码(如 echo -n "admin" | base64)。
非 YAML 方式创建的 Secret 会自动编码,YAML 需手动编码处理。