侧边栏壁纸
博主头像
路小飞博主等级

行动起来,活在当下

  • 累计撰写 72 篇文章
  • 累计创建 12 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

07- Kubernetes 配置管理

路小飞
2024-10-18 / 0 评论 / 0 点赞 / 17 阅读 / 15927 字

通常,一个服务的启动依赖于一些配置。例如,一个 Java 应用需要知道其连接的数据库和其他中间件的地址,以及与其他服务的接口地址。因此,需要将这些配置信息提供给应用。一般来说,这些信息可以通过环境变量注入或配置文件进行统一管理,而不应写死在代码中。这种配置分离是云原生应用设计的重要原则。

在传统架构中,配置文件可以存放在本地服务器、代码仓库或配置中心。而在 Kubernetes 中,配置抽象为 ConfigMap 和 Secret,用于管理程序的配置文件和 Pod 变量,如 Nginx 配置、应用配置、Maven 设置文件等。

ConfigMap 和 Secret 中的数据是以键-值对(key-value pair)的形式保存的,其中:

  • key:文件名或密钥
  • value:文件内容或字符值。

7.1 ConfigMap

7.1.1 ConfigMap 是什么

ConfigMap (缩写为cm)是 Kubernetes 中的一种资源对象,用于管理非机密的配置数据。它允许用户将配置数据以键值对的形式存储,并在应用程序的运行时将其传递给 Pod。ConfigMap 的设计旨在实现配置分离,使得应用程序的配置与其代码分开管理,增强灵活性和可维护性。

ConfigMap 是按照 Namespace 隔离的,不同命名空间的 ConfigMap 可以相同,但是不能跨命名空间访问。

ConfigMap 的主要特性:

  1. 键值存储:ConfigMap 可以存储多个键值对,每个键可以代表一个特定的配置项。
  2. 灵活性:用户可以将 ConfigMap 中的配置数据以环境变量、命令行参数或作为配置文件挂载到 Pod 中。
  3. 支持多种输入方式:可以通过 YAML 或 JSON 文件、命令行或直接使用 kubectl 创建 ConfigMap。
  4. 动态更新:更新 ConfigMap 后,使用该 ConfigMap 的 Pod 可以选择重新加载配置,支持动态配置更新。

ConfigMap 的使用场景:

  • 存储应用程序的配置文件(如数据库连接字符串、API 端点等)。
  • 存储环境特定的配置信息(如开发、测试和生产环境的配置)。
  • 允许开发团队灵活地管理应用程序配置,而无需更改代码。

7.1.2 创建 ConfigMap

ConfigMap 可以通过 YAML 文件、命令行的形式,将目录(包含多个文件)、单个文件或字符串的内容创建。

1. 基于目录创建

如果需要一次性从多个文件创建 ConfigMap,可以使用 kubectl create configmap 命令,从同一目录中导入文件。

假设您有一个名为 config 的目录,包含以下文件:

文件结构:

Copy Codeconfig/
  ├── app.properties
  └── db.properties

app.properties 内容:

propertiesCopy Codeapp.name=MyApp
app.version=1.0.0

db.properties 内容:

propertiesCopy Codedb.url=jdbc:mysql://localhost:3306/mydb
db.user=root
db.password=secret

创建命令:

kubectl create cm my-config --from-file=config

或者

kubectl -n namespace create cm my-config --from-file=config

查看 cm:

kubectl get cm my-configmap -oyaml

该 ConfigMap 是直接基于目录创建的,没有指定 Key 名,默认使用目录下的文件名作为 ConfigMap 数据中的 Key,文件内容作为 Value。

apiVersion: v1
kind: ConfigMap
metadata:
  creationTimestamp: "2024-10-17T00:00:00Z"
  name: my-app-config
  namespace: default
data:
  app.properties: |
    app.name=MyApp
    app.version=1.0.0
  db.properties: |
    db.url=jdbc:mysql://localhost:3306/mydb
    db.user=root
    db.password=secret

2. 基于文件创建

在实际使用中,大部分都是基于单个文件创建 ConfigMap的。以下是一个案例,展示如何基于单个文件创建 ConfigMap:

假设您有一个配置文件 app.properties,内容如下:

db.url=jdbc:mysql://localhost:3306/mydb
db.user=root
db.password=secret

创建命令:

kubectl create cm my-app-config --from-file=app.properties

您可以使用以下命令来验证 ConfigMap 是否成功创建,并查看其内容:

kubectl get configmap my-app-config -o yaml

该 ConfigMap 是直接基于文件创建的,没有指定 Key 名,默认使用目录下的文件名作为 ConfigMap 数据中的 Key,文件内容作为 Value。

apiVersion: v1
kind: ConfigMap
metadata:
  creationTimestamp: "2024-10-17T00:00:00Z"
  name: my-app-config
  namespace: default
data:
  app.properties: |
    db.url=jdbc:mysql://localhost:3306/mydb
    db.user=root
    db.password=secret
3. 基于 ENV 文件创建

以下是一个示例,展示如何基于 .env 文件创建 ConfigMap。

假设您有一个名为 app.env 的文件,其内容如下:

app.env 内容:

DB_URL=jdbc:mysql://localhost:3306/mydb
DB_USER=root
DB_PASSWORD=secret

使用以下命令基于该 .env 文件创建 ConfigMap:

kubectl create configmap my-app-config --from-env-file=app.env

使用以下命令验证 ConfigMap 是否成功创建,并查看其内容:

kubectl get configmap my-app-config -o yaml

运行上述命令后,您将看到类似以下的输出:

apiVersion: v1
kind: ConfigMap
metadata:
  creationTimestamp: "2024-10-17T00:00:00Z"
  name: my-app-config
  namespace: default
data:
  DB_URL: jdbc:mysql://localhost:3306/mydb
  DB_USER: root
  DB_PASSWORD: secret
4. 基于字符串创建

也可以直接基于字符串创建 ConfigMap,而不需要依赖文件。这在您有少量配置或者想快速测试时特别有用。

假设您要创建一个包含数据库连接信息的 ConfigMap,可以使用以下命令:

kubectl create configmap my-app-config --from-literal=DB_URL=jdbc:mysql://localhost:3306/mydb --from-literal=DB_USER=root --from-literal=DB_PASSWORD=secret

创建完成后,您可以使用以下命令验证 ConfigMap 是否成功创建,并查看其内容:

kubectl get configmap my-app-config -o yaml

运行上述命令后,您将看到类似以下的输出:

apiVersion: v1
kind: ConfigMap
metadata:
  creationTimestamp: "2024-10-17T00:00:00Z"
  name: my-app-config
  namespace: default
data:
  DB_URL: jdbc:mysql://localhost:3306/mydb
  DB_USER: root
  DB_PASSWORD: secret

7.2 Secret

7.2.1 Secret 是什么

与 ConfigMap 不同,Secret 主要用于存储敏感信息,如密码、令牌和 SSH 密钥,使用 Secret 存储这些信息更为安全和灵活

Secret 的结构和用法与 ConfigMap 类似,但在 Kubernetes 中,Secret 对象细分为多种类型,包括:

  1. Service Account:用于访问 Kubernetes API,由 Kubernetes 自动创建,并自动挂载到 Pod 的 /run/secrets/kubernetes.io/serviceaccount 目录中。

    每个 Kubernetes 命名空间都有一个默认的 Service Account,名为 default。这个默认的 Service Account 用于 Pod 的身份验证,并自动挂载到 Pod 的 /run/secrets/kubernetes.io/serviceaccount 目录中。

  2. Opaque [oʊˈpeɪk]:以 Base64 编码格式存储的 Secret,通常用于存储密码、密钥等敏感信息。默认情况下创建的都是这类。

  3. docker-registry:用于存储私有 Docker Registry 的认证信息。

  4. TLS:用于存储 TLS 证书和私钥,以支持加密通信,适用于需要 TLS 证书的场景。

7.2.2 创建 Secret

创建 Secret 的方式有多种,既可以通过命令行工具 kubectl,也可以通过 YAML 文件进行创建。

1. 使用 kubectl 命令行创建

假设我们有一个数据库用户和密码,分别存储在文件中。我们可以按以下步骤创建 Secret。

  1. 创建文件

首先,创建两个文件 db-user.txt 和 db-password.txt,分别存储数据库用户名和密码。

echo my-database-user >db-user.txt
echo my-secure-password >db-password.txt
  1. 使用 kubectl 创建 Secret

在命令行中运行以下命令,将文件内容以 Secret 形式存储:

kubectl create secret generic db-credentials \
  --from-file=username=db-user.txt \
  --from-file=password=db-password.txt

这个命令会创建一个名为 db-credentials 的 Secret,其中包含两个数据项:username 和 password。

  1. 查看 Secret

默认情况下,get 和 describe 都不会显示文件的内容。

[root@master-01 ~]# kubectl get secrets  db-credentials 
NAME             TYPE     DATA   AGE
db-credentials   Opaque   2      26s
[root@master-01 ~]# kubectl describe  secrets  db-credentials 
Name:         db-credentials
Namespace:    default
Labels:       <none>
Annotations:  <none>

Type:  Opaque

Data
====
password:  19 bytes
username:  17 bytes

2. 通过 YAML 文件创建

在使用 YAML 文件手动创建 Secret 时,每项内容必须经过 Base64 编码。以下是具体步骤和示例:

  1. 准备数据

假设我们要存储的数据库用户名和密码分别是 my-database-user 和 my-secure-password,我们需要将它们进行 Base64 编码。

echo -n 'my-database-user' | base64
# 输出: bXktZGF0YWJhc2UtdXNlcg==

echo -n 'my-secure-password' | base64
# 输出: bXktc2VjdXJlLXBhc3N3b3Jk

# 解码命令
echo "bXktc2VjdXJlLXBhc3N3b3Jk" |base64 --decode
  1. 创建 YAML 文件

接下来,创建一个名为 secret.yaml 的文件,并将编码后的内容写入文件中:

apiVersion: v1
kind: Secret
metadata:
  name: db-credentials
type: Opaque
data:
  username: bXktZGF0YWJhc2UtdXNlcg==
  password: bXktc2VjdXJlLXBhc3N3b3Jk
  1. 使用 kubectl 创建 Secret

通过以下命令应用 YAML 文件,创建 Secret:

kubectl apply -f secret.yaml
3. 创建其他类型的 Secret

在 Kubernetes 中,默认创建的 Secret 类型为 Opaque;如果需要创建其他类型的 Secret,则必须明确指定其类型。

以下是两个 Kubernetes 中创建不同类型 Secret 的案例,一个用于 TLS 证书,另一个用于 Docker 仓库认证。

  1. 创建 TLS Secret

TLS Secret 用于存储 TLS 证书和密钥,通常用于保护应用程序的 HTTPS 通信。以下是创建 TLS Secret 的示例:

kubectl create secret tls my-tls-secret \
  --cert=path/to/tls.crt \
  --key=path/to/tls.key

在这个命令中:

  • my-tls-secret 是 Secret 的名称。
  • --cert 指定了 TLS 证书文件的路径。
  • --key 指定了 TLS 私钥文件的路径。
  1. 创建 Docker Registry Secret

Docker Registry Secret 用于存储对私有 Docker 仓库的访问凭证。以下是创建 Docker Registry Secret 的示例:

kubectl create secret docker-registry my-docker-secret \
  --docker-username=myusername \
  --docker-password=mypassword \
  --docker-email=myemail@example.com \
  --docker-server=https://index.docker.io/v1/

在这个命令中:

  • my-docker-secret 是 Secret 的名称。
  • --docker-username 指定 Docker 仓库的用户名。
  • --docker-password 指定与该用户名相关的密码。
  • --docker-email 指定与账户相关的电子邮件地址。
  • --docker-server 指定 Docker 仓库的地址。

在你的 Pod 或 Deployment 的 YAML 文件中使用 imagePullSecrets 字段引用刚刚创建的 Secret。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: my-container
        image: myregistry.com/myapp:latest
      imagePullSecrets:
      - name: my-docker-secret		# secret name

7.3 使用 ConfigMap/Secret

7.3.1 以 valueFrom 定义容器环境变量

在 Kubernetes 中,可以使用 valueFrom 字段为环境变量指定值的来源,这些来源可以是 ConfigMap 或 Secret。以下是详细的说明和示例。

  1. ConfigMap: 通过 configMapKeyRef 从 ConfigMap 中获取值。
  2. Secret: 通过 secretKeyRef 从 Secret 中获取值。
1. 从 Secret 中获取环境变量

假设我们已经创建了一个名为 db-credentials 的 Secret,包含数据库用户名和密码。我们可以在 Pod 的 YAML 文件中使用 valueFrom 字段来引用这些 Secret。

apiVersion: v1
kind: Pod
metadata:
  name: my-app
spec:
  containers:
    - name: my-container
      image: my-database-image
      env:
        - name: DB_USER	# 变量名
          valueFrom:
            secretKeyRef:
              name: db-credentials  # 指定 Secret 的名称
              key: username          # 指定 Secret 中的Key
        - name: DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: db-credentials  # 指定 Secret 的名称
              key: password          # 指定 Secret 中的Key

将 Kubernetes 中的 Secret db-credentials 中的 username 这个 Key 对应的值赋给 Pod 中的环境变量 DB_USER

5. 从 ConfigMap 中获取环境变量

假设我们有一个名为 app-config 的 ConfigMap,里面存储了应用的配置参数。我们可以使用类似的方式来引用 ConfigMap 的内容。

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  APP_MODE: production
  APP_PORT: "8080"

然后在 Pod 的 YAML 文件中引用 ConfigMap:

apiVersion: v1
kind: Pod
metadata:
  name: my-app
spec:
  containers:
    - name: my-container
      image: my-app-image
      env:
        - name: APP_MODE
          valueFrom:
            configMapKeyRef:
              name: app-config  # 指定 ConfigMap 的名称
              key: APP_MODE      # 指定 ConfigMap 中的键
        - name: APP_PORT
          valueFrom:
            configMapKeyRef:
              name: app-config  # 指定 ConfigMap 的名称
              key: APP_PORT      # 指定 ConfigMap 中的键

7.3.2 以 volume 的方式使用

在 Kubernetes 中,Volume 是一种用于管理数据的机制,可以将数据持久化存储并在 Pod 的多个容器之间共享。SecretConfigMap 是两种可以以 Volume 方式挂载到 Pod 中的资源,它们分别用于存储敏感信息和非敏感配置信息。

注意:Volume 是 Pod 的一个属性,不属于容器,因此它与 containers 字段是同级的,都在 spec 下定义。

1. 使用 Secret 作为 Volume

首先,创建一个 Secret,然后在 Pod 中以 Volume 方式挂载它。

创建 Secret:

kubectl create secret  my-secret \
  --from-literal=username=myuser \
  --from-literal=password=mypassword

定义 Pod 并挂载 Secret:

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
    - name: my-container
      image: my-image
      volumeMounts:
        - name: secret-volume
          mountPath: /etc/secret
  volumes:
    - name: secret-volume
      secret:
        secretName: my-secret

在这个示例中:

  • secret-volume 是定义的 Volume 名称。
  • mountPath 是容器内挂载的路径。
  • secretName 是我们创建的 Secret 的名称。

在容器内,Secret 中的每个键会以文件的形式出现在 /etc/secret 目录中。

2. 使用 ConfigMap 作为 Volume

同样,我们可以使用 ConfigMap 来挂载配置信息。

创建 ConfigMap

kubectl create configmap my-config \
  --from-literal=app-config=configuration_value

定义 Pod 并挂载 ConfigMap

apiVersion: v1
kind: Pod
metadata:
  name: my-config-pod
spec:
  containers:
    - name: my-config-container
      image: my-image
      volumeMounts:
        - name: config-volume
          mountPath: /etc/config
  volumes:
    - name: config-volume
      configMap:
        name: my-config

在这个示例中:

  • config-volume 是定义的 Volume 名称。
  • mountPath 是容器内挂载的路径。
  • name 是我们创建的 ConfigMap 的名称。

在容器内,ConfigMap 中的每个键会以文件的形式出现在 /etc/config 目录中。

7.3.3 两种使用方式对比与总结

如果配置文件发生变化,Pod 中加载的数据是否会同步更新 ?

类型是否支持热更新
Volume支持
ENV(valueFrom)不支持

在 Kubernetes 中,配置管理的 API 对象 ConfigMapSecret 分别用于存储明文信息和机密敏感信息,这些数据被存储在 etcd 中,并可以在需要时注入到 Pod 中供其使用。

  1. ConfigMap:用于记录以 Key-Value 格式存储的字符串数据,其描述字段为 data,而非 spec
  2. Secret:与 ConfigMap 类似,也使用 data 字段保存字符串数据,但要求数据必须进行 Base64 编码,以提高安全性。
  3. 在 containers 的 env.valueFrom 字段中,可以引用 ConfigMapSecret,使其成为应用可访问的环境变量。
  4. 在 Pod 的 spec.volumes 字段中,可以引用 ConfigMapSecret,将它们作为存储卷,并在 spec.containers.volumeMounts 字段中以文件形式加载。
  5. 虽然 ConfigMapSecret 对存储数据的大小没有限制,但对于小数据,使用环境变量较为合适,而较大的数据应使用存储卷,以便根据具体场景灵活应用。

Kubernetes 的配置管理可以作为配置文件挂载,也可以配置为环境变量,程序适配其中的一种即可满足需求。然而,对于更复杂的配置需求,例如需求审核、备份和回滚等,建议使用专用的配置中心,如 Apollo、Nacos 或 Consul 等工具。

0

评论区