详细介绍:从零开始的云原生之旅(七):ConfigMap 和 Secret 配置管理

news/2025/11/26 22:09:41/文章来源:https://www.cnblogs.com/gccbuaa/p/19274782

从零开始的云原生之旅(七):ConfigMap 和 Secret 配置管理

不要把配置写死在代码里!灵活配置才是王道!

文章目录


前言

在前面的文章中,我学会了部署各种工作负载:

  • Deployment:无状态应用
  • StatefulSet:有状态应用(Redis)
  • DaemonSet:节点级服务(日志采集)

但我发现一个问题:配置都写死在代码里!

// 写死的配置
const (
RedisHost = "redis-service"
RedisPort = 6379
LogLevel  = "info"
)

这样有什么问题?

  • ❌ 开发、测试、生产环境配置不同,需要重新编译
  • ❌ 修改配置需要重新构建镜像
  • ❌ 敏感信息(密码、Token)暴露在代码中

这篇文章,我会学习 K8s 的配置管理方案:

  • ConfigMap:管理配置数据
  • Secret:管理敏感数据
  • CronJob:定时任务的配置
  • ✅ 配置的动态更新
  • ✅ 最佳实践

一、为什么需要 ConfigMap 和 Secret?

1.1 我以前的配置方式

方式 1:写死在代码里

package config
const (
RedisHost = "redis-service"
RedisPort = 6379
LogLevel  = "debug"  // 开发环境:debug,生产环境:info
AppEnv    = "development"
)

问题:

  • 换环境要改代码、重新编译
  • 镜像和环境强绑定

方式 2:读取配置文件

// 读取 config.yaml
cfg, _ := os.ReadFile("config.yaml")
# config.yaml
redis:
host: redis-service
port: 6379
log_level: info

问题:

  • 配置文件怎么放到容器里?
  • 不同环境要维护不同的配置文件
  • 修改配置要重新构建镜像

方式 3:环境变量

redisHost := os.Getenv("REDIS_HOST")
redisPort := os.Getenv("REDIS_PORT")
# Deployment
env:
- name: REDIS_HOST
value: "redis-service"
- name: REDIS_PORT
value: "6379"

这个还不错,但:

  • 配置分散在多个 Deployment 中
  • 修改配置要编辑所有 YAML 文件
  • 敏感信息(密码)明文存储

1.2 遇到的问题

场景:部署 3 个微服务,都要连 Redis

# service-a/deployment.yaml
env:
- name: REDIS_HOST
value: "redis-service"  # 写死
# service-b/deployment.yaml
env:
- name: REDIS_HOST
value: "redis-service"  # 又写了一遍
# service-c/deployment.yaml
env:
- name: REDIS_HOST
value: "redis-service"  # 又又写了一遍

Redis 地址改了,要改 3 个文件!


场景:数据库密码

env:
- name: DB_PASSWORD
value: "mySecretPassword123"  # 明文!

问题:

  • 密码明文存储在 YAML 文件中
  • YAML 文件通常提交到 Git
  • 密码泄露!

1.3 K8s 的解决方案

ConfigMap:管理配置数据

# 统一的配置
apiVersion: v1
kind: ConfigMap
metadata:
name: common-config
data:
redis_host: "redis-service"
redis_port: "6379"

所有服务引用同一个 ConfigMap:

# service-a, service-b, service-c 都这样写
env:
- name: REDIS_HOST
valueFrom:
configMapKeyRef:
name: common-config
key: redis_host

好处:

  • ✅ 配置集中管理
  • ✅ 修改一次,所有服务生效
  • ✅ 配置和代码分离

Secret:管理敏感数据

# 创建 Secret
apiVersion: v1
kind: Secret
metadata:
name: db-secret
type: Opaque
data:
password: bXlTZWNyZXRQYXNzd29yZDEyMw==  # Base64 编码

使用 Secret:

env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: password  # 自动解码

好处:

  • ✅ Base64 编码(虽然不是加密)
  • ✅ RBAC 权限控制(谁能看 Secret)
  • ✅ 可以启用加密存储

二、ConfigMap:管理配置数据

2.1 什么是 ConfigMap?

ConfigMap = 键值对的集合

┌───────────────────────────┐
│       ConfigMap           │
│                           │
│  key1: value1             │
│  key2: value2             │
│  config.json: { ... }     │
│  redis.conf: ...          │
│                           │
└───────────────────────────┘

用途:

  • 应用配置(日志级别、数据库地址)
  • 配置文件(nginx.conf, redis.conf
  • 命令行参数
  • 环境变量

2.2 创建 ConfigMap

方法 1:从字面量创建

kubectl create configmap my-config \
--from-literal=log_level=info \
--from-literal=redis_host=redis-service

查看:

kubectl get configmap my-config -o yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: my-config
data:
log_level: info
redis_host: redis-service

方法 2:从文件创建

# 从单个文件
kubectl create configmap redis-config --from-file=redis.conf
# 从目录(目录下所有文件)
kubectl create configmap app-config --from-file=./config/

结果:

apiVersion: v1
kind: ConfigMap
metadata:
name: redis-config
data:
redis.conf: |
bind 0.0.0.0
port 6379
maxmemory 128mb

方法 3:从 YAML 文件创建(推荐)

# configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: api-config
labels:
app: api
version: v0.2
data:
# 简单的键值对
log_level: "info"
app_env: "production"
# Redis 配置
redis_host: "redis-service"
redis_port: "6379"
# 缓存配置
cache_ttl: "3600"
# 特性开关
enable_cache: "true"
enable_metrics: "true"
kubectl apply -f configmap.yaml

2.3 使用 ConfigMap 的 4 种方式

① 作为环境变量(单个键)
spec:
containers:
- name: api
image: my-api:v1.0
env:
- name: LOG_LEVEL  # 环境变量名
valueFrom:
configMapKeyRef:
name: api-config  # ConfigMap 名称
key: log_level    # ConfigMap 中的键

Pod 内看到的:

echo $LOG_LEVEL
# info

② 作为环境变量(所有键)
spec:
containers:
- name: api
image: my-api:v1.0
envFrom:
- configMapRef:
name: api-config  # 所有键都注入为环境变量

Pod 内看到的:

echo $log_level
# info
echo $redis_host
# redis-service
echo $cache_ttl
# 3600

注意:键名会自动转换为环境变量格式(大写、下划线)


③ 作为文件挂载(单个文件)
spec:
containers:
- name: redis
image: redis:7-alpine
volumeMounts:
- name: config
mountPath: /etc/redis/redis.conf
subPath: redis.conf  # 只挂载一个文件
volumes:
- name: config
configMap:
name: redis-config

Pod 内看到的:

cat /etc/redis/redis.conf
# bind 0.0.0.0
# port 6379
# maxmemory 128mb

④ 作为目录挂载(所有键)
spec:
containers:
- name: app
image: my-app:v1.0
volumeMounts:
- name: config
mountPath: /etc/config  # 挂载为目录
volumes:
- name: config
configMap:
name: api-config

Pod 内看到的:

ls /etc/config/
# cache_ttl
# enable_cache
# log_level
# redis_host
# redis_port
cat /etc/config/log_level
# info

每个键变成一个文件!


三、Secret:管理敏感数据

3.1 什么是 Secret?

Secret = 加密存储的键值对

┌───────────────────────────┐
│         Secret            │
│                           │
│  username: YWRtaW4=       │  ← Base64 编码
│  password: cGFzc3dvcmQ=   │
│                           │
└───────────────────────────┘

与 ConfigMap 的区别:

特性ConfigMapSecret
用途配置数据敏感数据
存储明文Base64 编码
大小限制1MB1MB
加密不支持可启用加密存储
权限控制一般更严格(RBAC)

3.2 创建 Secret

方法 1:从字面量创建

kubectl create secret generic db-secret \
--from-literal=username=admin \
--from-literal=password=mySecretPassword123

查看:

kubectl get secret db-secret -o yaml
apiVersion: v1
kind: Secret
metadata:
name: db-secret
type: Opaque
data:
username: YWRtaW4=  # Base64("admin")
password: bXlTZWNyZXRQYXNzd29yZDEyMw==  # Base64("mySecretPassword123")

方法 2:从文件创建

# SSH 私钥
kubectl create secret generic ssh-key \
--from-file=ssh-privatekey=~/.ssh/id_rsa
# TLS 证书
kubectl create secret tls tls-secret \
--cert=path/to/tls.cert \
--key=path/to/tls.key

方法 3:从 YAML 创建(手动 Base64 编码)

apiVersion: v1
kind: Secret
metadata:
name: db-secret
type: Opaque
data:
username: YWRtaW4=  # echo -n "admin" | base64
password: bXlTZWNyZXRQYXNzd29yZDEyMw==

或使用 stringData(自动编码):

apiVersion: v1
kind: Secret
metadata:
name: db-secret
type: Opaque
stringData:  # 不需要手动 Base64
username: admin
password: mySecretPassword123
kubectl apply -f secret.yaml

3.3 使用 Secret

使用方式和 ConfigMap 一样:

① 作为环境变量

env:
- name: DB_USERNAME
valueFrom:
secretKeyRef:
name: db-secret
key: username
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: password

② 作为文件挂载

volumeMounts:
- name: db-creds
mountPath: /etc/db-creds
readOnly: true  # 只读,更安全
volumes:
- name: db-creds
secret:
secretName: db-secret

Pod 内:

ls /etc/db-creds/
# username
# password
cat /etc/db-creds/password
# mySecretPassword123  ← 自动解码

3.4 Secret 的加密存储

默认情况:Secret 只是 Base64 编码,不是加密!

# 任何人都可以解码
echo "YWRtaW4=" | base64 -d
# admin

启用加密存储(推荐):

K8s 支持 Encryption at Rest(静态加密),配置后:

  • Secret 在 etcd 中加密存储
  • 只有 K8s API Server 能解密
  • 即使攻击者拿到 etcd 备份,也无法读取 Secret

配置方法(需要集群管理员权限):

# /etc/kubernetes/encryption-config.yaml
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
- secrets
providers:
- aescbc:
keys:
- name: key1
secret: <base64-encoded-32-byte-key>- identity: {}  # 回退到不加密

这是生产环境必须配置的!


四、实战案例:API 服务配置

4.1 配置需求分析

我的 API 服务需要:

这些配置需要:


4.2 创建 ConfigMap

apiVersion: v1
kind: ConfigMap
metadata:
name: api-config
labels:
app: api
version: v0.2
data:
# 应用配置
log_level: "info"
app_env: "production"
# Redis 配置
redis_host: "redis-service"
redis_port: "6379"
# 缓存配置
cache_ttl: "3600"  # 默认 1 小时
# 性能配置
max_connections: "100"
# 特性开关
enable_cache: "true"
enable_metrics: "true"
kubectl apply -f k8s/v0.2/api/configmap.yaml

4.3 注入到 Deployment

apiVersion: apps/v1
kind: Deployment
metadata:
name: api-server
spec:
replicas: 2
template:
spec:
containers:
- name: api
image: cloudnative-go-api:v0.2
# 环境变量(从 ConfigMap 注入)
env:
- name: APP_ENV
valueFrom:
configMapKeyRef:
name: api-config
key: app_env
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: api-config
key: log_level
- name: REDIS_HOST
valueFrom:
configMapKeyRef:
name: api-config
key: redis_host
- name: REDIS_PORT
valueFrom:
configMapKeyRef:
name: api-config
key: redis_port
- name: CACHE_TTL
valueFrom:
configMapKeyRef:
name: api-config
key: cache_ttl

4.4 应用代码读取配置

package config
import (
"os"
"strconv"
)
type Config struct {
AppEnv         string
LogLevel       string
RedisHost      string
RedisPort      int
CacheTTL       int
EnableCache    bool
EnableMetrics  bool
}
func LoadConfig() *Config {
return &Config{
AppEnv:        getEnv("APP_ENV", "development"),
LogLevel:      getEnv("LOG_LEVEL", "debug"),
RedisHost:     getEnv("REDIS_HOST", "localhost"),
RedisPort:     getEnvInt("REDIS_PORT", 6379),
CacheTTL:      getEnvInt("CACHE_TTL", 3600),
EnableCache:   getEnvBool("ENABLE_CACHE", true),
EnableMetrics: getEnvBool("ENABLE_METRICS", true),
}
}
func getEnv(key, defaultValue string) string {
if value := os.Getenv(key); value != "" {
return value
}
return defaultValue
}
func getEnvInt(key string, defaultValue int) int {
if value := os.Getenv(key); value != "" {
if intValue, err := strconv.Atoi(value); err == nil {
return intValue
}
}
return defaultValue
}
func getEnvBool(key string, defaultValue bool) bool {
if value := os.Getenv(key); value != "" {
return value == "true"
}
return defaultValue
}

使用:

func main() {
cfg := config.LoadConfig()
fmt.Printf("环境: %s\n", cfg.AppEnv)
fmt.Printf("日志级别: %s\n", cfg.LogLevel)
fmt.Printf("Redis: %s:%d\n", cfg.RedisHost, cfg.RedisPort)
}

五、实战案例:CronJob 配置

5.1 定时任务需求

需求:每小时清理 Redis 的过期键

配置需求:


5.2 CronJob 配置详解

apiVersion: batch/v1
kind: CronJob
metadata:
name: cleanup-job
labels:
app: cleanup-job
spec:
# Cron 调度表达式
schedule: "0 * * * *"  # 每小时的第0分钟
# 历史保留限制
successfulJobsHistoryLimit: 3  # 保留 3 个成功的
failedJobsHistoryLimit: 1      # 保留 1 个失败的
# 并发策略
concurrencyPolicy: Forbid  # 禁止并发
# 启动截止时间
startingDeadlineSeconds: 100  # 错过100秒就跳过
# Job 模板
jobTemplate:
spec:
# 完成后 1 小时删除 Pod
ttlSecondsAfterFinished: 3600
# 失败重试次数
backoffLimit: 3
# 任务超时时间(5分钟)
activeDeadlineSeconds: 300
template:
spec:
restartPolicy: OnFailure
containers:
- name: cleanup
image: cleanup-job:v0.2
env:
# Redis 地址
- name: REDIS_HOST
value: "redis-service:6379"
# Job 信息
- name: JOB_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
resources:
requests:
memory: "64Mi"
cpu: "50m"
limits:
memory: "128Mi"
cpu: "100m"

5.3 调度表达式

Cron 格式:

 ┌───────────── 分钟 (0 - 59)│ ┌───────────── 小时 (0 - 23)│ │ ┌───────────── 日 (1 - 31)│ │ │ ┌───────────── 月 (1 - 12)│ │ │ │ ┌───────────── 星期 (0 - 6) (0 = 周日)│ │ │ │ │* * * * *

常用示例:

表达式说明场景
*/5 * * * *每 5 分钟频繁清理
0 * * * *每小时常规清理
0 2 * * *每天凌晨 2 点数据库备份
0 0 * * 0每周日凌晨周报生成
0 0 1 * *每月 1 号凌晨月度统计
0 9-17 * * 1-5工作日 9-17 点每小时工作时间任务

5.4 并发策略

concurrencyPolicy 控制并发行为:

策略说明适用场景
Allow允许并发执行(默认)独立任务(日志归档)
Forbid禁止并发,跳过新任务数据库备份(避免冲突)
Replace取消旧任务,启动新任务实时报表(只要最新)

示例:数据库备份

spec:
schedule: "0 2 * * *"  # 每天 2 点
concurrencyPolicy: Forbid  # 如果上次备份还没完成,跳过

为什么?

  • 备份任务耗时长(可能超过 1 天)
  • 并发备份会导致数据库负载过高
  • 同时备份会冲突(写同一个文件)

六、配置的动态更新

6.1 ConfigMap 更新

# 方法 1:编辑 ConfigMap
kubectl edit configmap api-config
# 方法 2:替换 ConfigMap
kubectl apply -f configmap.yaml
# 方法 3:打补丁
kubectl patch configmap api-config \
-p '{"data":{"log_level":"debug"}}'

6.2 应用如何感知更新?

① 环境变量方式:不会自动更新

env:
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: api-config
key: log_level

更新 ConfigMap 后:

# 修改 ConfigMap
kubectl patch configmap api-config -p '{"data":{"log_level":"debug"}}'
# Pod 内查看
kubectl exec -it api-server-xxx -- env | grep LOG_LEVEL
# LOG_LEVEL=info  ← 还是旧值!

原因:环境变量在 Pod 启动时注入,不会动态更新!


② 文件挂载方式:会自动更新(有延迟)

volumeMounts:
- name: config
mountPath: /etc/config
volumes:
- name: config
configMap:
name: api-config

更新 ConfigMap 后:

# 修改 ConfigMap
kubectl patch configmap api-config -p '{"data":{"log_level":"debug"}}'
# 等待 1-2 分钟
sleep 120
# Pod 内查看
kubectl exec -it api-server-xxx -- cat /etc/config/log_level
# debug  ← 新值!

K8s 会自动同步,但有延迟(最多几分钟)


6.3 强制更新 Pod

如果希望立即生效:

方法 1:重启 Pod

kubectl rollout restart deployment api-server

方法 2:给 ConfigMap 添加版本号

# configmap-v2.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: api-config-v2  # 新名称
data:
log_level: "debug"
# deployment.yaml
env:
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: api-config-v2  # 引用新 ConfigMap
key: log_level
kubectl apply -f configmap-v2.yaml
kubectl apply -f deployment.yaml  # 触发滚动更新

方法 3:给 Deployment 添加 ConfigMap 的 Hash(自动触发更新)

# 计算 ConfigMap 的 Hash
CONFIG_HASH=$(kubectl get configmap api-config -o json | md5sum | cut -d' ' -f1)
# 添加到 Deployment 的 annotations
kubectl patch deployment api-server -p \
"{\"spec\":{\"template\":{\"metadata\":{\"annotations\":{\"configmap-hash\":\"$CONFIG_HASH\"}}}}}"

每次 ConfigMap 改变,Hash 变化,触发滚动更新!


七、最佳实践

7.1 配置分层

不要把所有配置放在一个 ConfigMap:

# ❌ 不推荐:所有配置混在一起
apiVersion: v1
kind: ConfigMap
metadata:
name: all-config
data:
log_level: info
redis_host: redis-service
db_password: password123  # 敏感信息!
nginx_conf: |
...

✅ 推荐:分层管理

# 通用配置
apiVersion: v1
kind: ConfigMap
metadata:
name: common-config
data:
log_level: info
app_env: production
---
# Redis 配置
apiVersion: v1
kind: ConfigMap
metadata:
name: redis-config
data:
redis_host: redis-service
redis_port: "6379"
---
# 敏感数据(Secret)
apiVersion: v1
kind: Secret
metadata:
name: db-secret
stringData:
password: password123

7.2 命名规范

推荐命名:

--
示例:api-config-prod       # API 服务的生产配置api-config-dev        # API 服务的开发配置redis-config          # Redis 配置db-secret             # 数据库密钥

7.3 版本管理

方案 1:在名称中包含版本

metadata:
name: api-config-v2

好处:

  • 可以同时存在多个版本
  • 回滚简单(切换引用)

坏处:

  • 要修改 Deployment 引用

方案 2:在 ConfigMap 中记录版本

metadata:
name: api-config
labels:
version: v2
data:
version: "v2"
log_level: info

好处:

  • 不需要修改 Deployment
  • 可以在应用中读取版本号

7.4 安全建议

① Secret 不要提交到 Git

# .gitignore
*-secret.yaml
secret*.yaml

或使用加密工具(如 Sealed Secrets)


② 使用 RBAC 限制访问

# 只允许特定 ServiceAccount 读取 Secret
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: secret-reader
rules:
- apiGroups: [""]
resources: ["secrets"]
resourceNames: ["db-secret"]
verbs: ["get"]

③ 启用 Secret 加密存储

# 生产环境必须启用!
# 配置 API Server 的 --encryption-provider-config

④ 定期轮换密钥

# 每季度更新一次数据库密码
kubectl create secret generic db-secret \
--from-literal=password=newPassword123 \
--dry-run=client -o yaml | kubectl apply -f -
# 重启 Pod 使其生效
kubectl rollout restart deployment api-server

八、常见问题排查

8.1 ConfigMap 不存在

症状:

kubectl get pods
# NAME                  READY   STATUS                 RESTARTS   AGE
# api-server-xxx        0/1     CreateContainerError   0          10s

日志:

kubectl describe pod api-server-xxx
# Events:
#   Warning  Failed  Error: configmap "api-config" not found

解决:

# 检查 ConfigMap 是否存在
kubectl get configmap api-config
# 如果不存在,创建它
kubectl apply -f configmap.yaml

8.2 配置未生效

症状:修改了 ConfigMap,应用还是读取旧值

排查:

# 1. 确认 ConfigMap 已更新
kubectl get configmap api-config -o yaml
# 2. 检查使用方式
kubectl get deployment api-server -o yaml | grep -A10 "env:"
# 3. 如果是环境变量方式,需要重启 Pod
kubectl rollout restart deployment api-server

8.3 Secret 解码失败

症状:

kubectl logs api-server-xxx
# Error: invalid character in password

原因:Base64 编码错误

# 检查 Secret
kubectl get secret db-secret -o yaml
# data:
#   password: bXlTZWNyZXRQYXNzd29yZDEyMw==
# 手动解码测试
echo "bXlTZWNyZXRQYXNzd29yZDEyMw==" | base64 -d
# mySecretPassword123

如果解码失败,重新创建 Secret:

kubectl delete secret db-secret
kubectl create secret generic db-secret \
--from-literal=password=mySecretPassword123

九、ConfigMap vs Secret vs 环境变量

方式优点缺点适用场景
ConfigMap集中管理、易于更新、支持文件明文存储配置数据(非敏感)
Secret加密存储、权限控制使用复杂密码、Token、证书
环境变量简单直接分散管理、不能动态更新简单配置、调试
文件格式自由、支持复杂配置需要挂载卷配置文件(nginx.conf)

推荐组合:

# 简单配置 → 环境变量(从 ConfigMap)
env:
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: api-config
key: log_level
# 复杂配置 → 文件挂载(从 ConfigMap)
volumeMounts:
- name: nginx-config
mountPath: /etc/nginx/nginx.conf
subPath: nginx.conf
volumes:
- name: nginx-config
configMap:
name: nginx-config
# 敏感数据 → Secret
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: password

结语

这篇文章,我学会了:

ConfigMap:管理配置数据

  • 创建 ConfigMap 的 3 种方法
  • 使用 ConfigMap 的 4 种方式
  • 配置集中管理、易于更新

Secret:管理敏感数据

  • Base64 编码(不是加密)
  • 启用加密存储(生产必须)
  • RBAC 权限控制

CronJob:定时任务配置

  • Cron 表达式
  • 并发策略(Allow/Forbid/Replace)
  • 历史记录管理

动态更新配置

  • 环境变量不会自动更新(需重启)
  • 文件挂载会自动更新(有延迟)
  • 强制更新的 3 种方法

最佳实践

  • 配置分层(不要混在一起)
  • 命名规范(service-type-env)
  • 版本管理(v1, v2)
  • 安全建议(加密、RBAC、轮换)

最大的收获:

不要把配置写死在代码里!
ConfigMap 管理配置,Secret 管理密钥!
配置和代码分离,才能灵活部署!


v0.2 完结!

在 v0.2 中,我学会了:

  1. K8s 工作负载全景:Deployment、StatefulSet、DaemonSet、CronJob
  2. StatefulSet 部署 Redis:持久化存储、Headless Service
  3. DaemonSet 日志采集器:节点级服务、访问宿主机
  4. ConfigMap 和 Secret:配置管理、敏感数据

下一步(v0.3 预告):

v0.3 将学习 高级网络和存储

  • Ingress(统一入口)
  • NetworkPolicy(网络隔离)
  • StorageClass(动态存储)
  • 监控和日志(Prometheus + Grafana)

敬请期待!


如果这篇文章对你有帮助,欢迎点赞、收藏、分享!

有问题欢迎在评论区讨论!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/977700.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Day 28 类的定义和手段

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

VMware虚拟机Ubuntu系统问题集

1. 网络图标及设置里的连接选项突然消失解决: 1> sudo gdeit /etc/NetworkManager/NetworkManager.conf 2> 将managed=false改为managed=true,保存退出 3> 删除NetworkManager配置 service NetworkManager …

SetSkeletalMesh优化问题

最近工作的时候遇到了一个CPU的异常开销优化,用Unreal Insights看了一下,SetSkeletalMesh的开销相当大。 主要是三个东西:CreatePhysics、InitAnim、CreateClothing。 尝试了一下定位问题:关闭SkeletalMeshCompone…

从文件结构、索引、信息更新、版本控制等全面对比Apache hudi和Apache paimon

从文件结构、索引、信息更新、版本控制等全面对比Apache hudi和Apache paimon2025-11-26 21:45 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-…

详细介绍:逻辑回归 Logistic 算法从入门到入土

详细介绍:逻辑回归 Logistic 算法从入门到入土pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", &…

NOIP 集训 day5 DP

DP:阶段、状态、转移; 优化:状态是否冗余? 转移是否可优化?Example 斐波那契数列:\(f_i=f_{i-1}+f_{i-2}\). \(f_0=0,f_1=1\).矩阵优化 将 \(f_n,f_{n-1}\) 打包为一个列向量,然后用矩阵快速幂快速求转移矩阵的…

考前复习1

考前复习11.快读 inline int read(){int k=0,f=1;char c=getchar_unlocked();while(c<0||c>9){if(c==-)f=-1;c=getchar_unlocked();}while(c>=0&&c<=9)k=k*10+c-0,c=getchar_unlocked();return k*…

NOIP 模板大赛(没写完)

T701832 滑动窗口 /【模板】单调队列单调队列板子题,所以显然是单调队列。 单调队列就俩操作,一个是加入队尾的时候如果破坏单调性了就把队尾一直 pop 到满足单调性,另一个是如果队首不在范围内就 pop 出去。因为每…

开发指南

Vue3 大屏可视化平台开发指南 一、自定义开发 1. 添加新图表 步骤一:创建图表组件 在 src/components/charts/ 目录下创建新组件: <!-- src/components/charts/MyChart.vue --> <template><div ref=&…

Day25CSS精灵

<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0">…

解码JSON

JSON 核心概念 JSON(JavaScript Object Notation)是 “JavaScript 对象表示法” 的简称,是一种轻量级数据交换文本格式,不依赖任何编程语言。它具有简洁清晰的层次结构,易于人类阅读编写,同时便于机器解析和生成…

项目启动

Vue3 大屏可视化平台项目启动 快速启动 开发模式 npm run dev启动后访问 http://localhost:3000 使用脚本快速启动(Windows): # 使用批处理文件 start.bat# 或使用 PowerShell start.ps1生产构建 npm run build构建…

11/26

今天满课,好累

2025-11-26

CF 构造(1300) Problem - 1867C - Codeforces(交互) #include <bits/stdc++.h> using namespace std; #define LL long long const LL mod = 998244353; const int N=2e5+10; int a[N];void solve() {int n;…

关于生育问题的初步看法

生育问题,即现代社会面对的,结婚率、生育率逐渐或断崖式下降的现象。 个人看法,生育问题已经涉及到现代社会的根基,即资本。 无论是工业时代的工业化、还是现代社会金融爆发,本质都是资本的不断升级,而资本升级能…

游戏立项games-stats,查询游戏tag的销量,以卡牌游戏举例

有这样一个网站叫,https://games-stats.com/ 这个网站可以查询steam上面的不同的游戏tag,他们的中位数销量是如何的 进去这个网站,然后按照如图的点击方式 首先 Games Count 数量是小于1000的,就不用看了,一般是一…

深入解析:Vue2.x + Webpack + ES6仿懂球帝足球项目实战

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

2025年11月砝码,无磁不锈钢砝码,定制砝码厂家推荐:行业权威盘点与品质红榜发布

引言在全球工业生产与科研实验中,砝码作为重要的计量器具,其精度和质量直接影响着测量结果的准确性。为了能为广大用户筛选出优质的砝码厂家,国际知名的计量协会开展了一场全面且严格的测评活动。本次测评综合考量了…

2025年11月不锈钢砝码,无磁不锈钢砝码,挂钩砝码厂家推荐,高精度与可靠性兼具的优质品牌

引言在全球工业生产、科研实验以及质量检测等众多领域,砝码作为重要的计量器具,其精度和质量至关重要。为了能给广大用户筛选出优质的砝码厂家,国际知名的计量协会开展了一场严谨且全面的测评活动。该协会采用了多维…

上下文无关文法序列

import torch import torch.nn as nn import torch.optim as optim import numpy as np def generate_data(num_samples): data = [] for _ in range(num_samples): n = 30 # 固定n为30 seq = [0]n + [1]n data.appen…