云计算百科
云计算领域专业知识百科平台

K8s 配置管理实战:ConfigMap 与 Secret 完整使用指南

K8s 配置管理实战:ConfigMap 与 Secret 完整使用指南

  • Kubernetes Configure
    • 环境准备
    • ConfigMap
      • ConfigMap 介绍
      • ConfigMap 创建
        • 键值对类型
        • 文件类型
        • 目录类型
      • ConfigMap 引用
        • 环境变量方式引用
        • 以 volume 方式引用
          • 引用整体
          • 引用特定key
        • k8s 中 ConfigMap
      • 综合案例:haproxy+web
    • Secret
      • Secret 介绍
      • Secret 类型
      • Secret 创建
        • generic
          • 基于键值对
          • 基于普通文件
          • 基于键值对内容的文件
          • 基于目录
          • 基于 yaml 文件
        • docker-registry
        • TLS
      • Secret 引用
        • 以环境变量方式引用
        • 以 volume 方式引用
          • 引用整体
          • 引用特定 key
        • 文件权限
    • 环境清理

Kubernetes Configure

摘要:本文详细介绍了 Kubernetes 中 ConfigMap 和 Secret 两种配置管理对象的使用方法。ConfigMap 用于存储非敏感配置数据,支持键值对、文件和目录三种创建方式,可通过环境变量或 Volume 挂载到 Pod 中。Secret 专门存储敏感信息(如密码、密钥),数据经过 Base64 编码,支持 generic、docker-registry 和 TLS 三种类型,同样支持环境变量和 Volume 挂载。文章通过多个实际案例演示了如何创建、引用和更新这些配置对象,并提供了一个综合案例展示如何结合 haproxy 和 nginx 构建负载均衡应用。

环境准备

root@master30:~# kubectl create ns configure
root@master30:~# kubectl config set-context –current –namespace configure

ConfigMap

学习参考:ConfigMap

ConfigMap 介绍

ConfigMap 是一个存储其他对象所需要使用的配置的 API 对象。 ConfigMap 使用 data 和 binaryData 字段,保存键值对数据。

  • data 字段,用来保存 UTF-8 字符串。
  • binaryData 字段,用来保存二进制数据(base64 编码的字串) 。

ConfigMap 的名字必须是一个合法的 DNS 子域名。data 或 binaryData 字段下面的每个键的名称都必须由字母、数字或者 -、_ 或 . 组成。在 data 下保存的键名不可以与在 binaryData 下出现的键名有重叠。

从 v1.19 开始,你可以添加一个 immutable 字段到 ConfigMap 定义中, 创建不可变更的 ConfigMap。

ConfigMap 使用建议

  • 使用 ConfigMap 存储配置数据,不存数据 / 文件,上限 = 1 MiB。

  • **ConfigMap 在设计上不是用来保存大量数据的。**如果你需要保存大量数据,考虑使用挂载存储卷或者使用独立的数据库或者文件服务。

ConfigMap 创建

使用帮助

kubectl create configmap NAME [–from-file=[key=]source]
[–from-literal=key1=value1] [–dry-run=server|client|none] [options]

键值对类型

root@master30:~# kubectl create configmap mysql –from-literal=password=redhat
root@master30:~# kubectl get configmaps mysql -o yaml |grep ^data -A1
data:
password: redhat

文件类型

root@master30:~# echo Hello World > index.html
root@master30:~# kubectl create configmap web1 –from-file=./index.html
root@master30:~# kubectl get configmaps web1 -o yaml |grep ^data -A2
data:
index.html: |
Hello World

目录类型

root@master30:~# echo error > error.html
root@master30:~# mkdir web2
root@master30:~# mv index.html error.html web2
root@master30:~# kubectl create configmap web2 –from-file=./web2
root@master30:~# kubectl get configmaps web2 -o yaml |grep ^data -A4
data:
error.html: |
error
index.html: |
Hello World

ConfigMap 引用

环境变量方式引用

**注意:**环境变量属于特定容器级别。

root@master30:~# vim pod-with-env-from-configmap.yaml


apiVersion: v1
kind: Pod
metadata:
name: mysql
labels:
name: mysql
spec:
containers:
image: hub.laoma.cloud/library/mysql:latest
imagePullPolicy: IfNotPresent
name: mysql
ports:
containerPort: 3306
name: mysql
env:
name: MYSQL_ROOT_PASSWORD
# 原先通过value设置环境变量值
valueFrom:
configMapKeyRef:
name: mysql
key: password

验证

root@master30:~# kubectl apply -f pod-with-env-from-configmap.yaml
root@master30:~# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
mysql 1/1 Running 0 4m33s 10.224.193.70 worker32.laoma.cloud <none>

root@master30:~# kubectl exec -it mysql — bash -c 'echo $MYSQL_ROOT_PASSWORD'
redhat

root@master30:~# apt install -y mysql-client
root@master30:~# mysql -u root -predhat -h 10.224.193.70
mysql: [Warning] Using a password on the command line interface can be insecure.
......

Type 'help;' or '\\h' for help. Type '\\c' to clear the current input statement.

mysql> quit
Bye

# 删除 pod
root@master30:~# kubectl delete pod mysql –force

以 volume 方式引用

**注意:**volumes属于pod级别,通过volumeMounts挂载。

引用整体

root@master30:~# vim pod-with-volume-from-configmap.yaml


apiVersion: v1
kind: Pod
metadata:
labels:
run: web
name: web
spec:
containers:
image: hub.laoma.cloud/library/nginx:latest
imagePullPolicy: IfNotPresent
name: web
volumeMounts:
name: webcontent
# mountPath值是一个挂载点,将configuremap中所有键值对挂载过来
mountPath: "/usr/share/nginx/html"
volumes:
name: webcontent
configMap:
name: web2

验证

root@master30:~# kubectl apply -f pod-with-volume-from-configmap.yaml
root@master30:~# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
web 1/1 Running 0 66s 10.224.193.69 worker32.laoma.cloud <none> <none>

root@master30:~# kubectl exec web — ls /usr/share/nginx/html
error.html
index.html

root@master30:~# curl http://10.224.193.69
Hello World
root@master30:~# curl http://10.224.193.69/error.html
error

引用特定key

root@master30:~# vim pod-cm-volume-single.yaml


apiVersion: v1
kind: Pod
metadata:
labels:
run: web
name: web
spec:
containers:
image: hub.laoma.cloud/library/nginx:latest
imagePullPolicy: IfNotPresent
name: web
volumeMounts:
name: webcontent
mountPath: "/usr/share/nginx/html"
volumes:
name: webcontent
configMap:
name: web2
items:
key: index.html
path: index.html

等同于

apiVersion: v1
kind: Pod
metadata:
labels:
run: web
name: web
spec:
containers:
image: hub.laoma.cloud/library/nginx:latest
imagePullPolicy: IfNotPresent
name: web
volumeMounts:
name: webcontent
mountPath: "/usr/share/nginx/html/index.html"
subPath: index.html
volumes:
name: webcontent
configMap:
name: web2

**被挂载的 ConfigMap 内容会被自动更新。**当卷中使用的 ConfigMap 被更新时,所投射的键最终也会被更新。 kubelet 组件会在每次周期性同步时检查所挂载的 ConfigMap 是否为最新。

k8s 中 ConfigMap

以 kube-proxy 为例

root@master30:~# kubectl get configmaps -n kube-system
NAME DATA AGE
calico-config 4 37h
coredns 1 37h
extension-apiserver-authentication 6 37h
kube-apiserver-legacy-service-account-token-tracking 1 37h
kube-proxy 2 37h
kube-root-ca.crt 1 37h
kubeadm-config 1 37h
kubelet-config 1 37h

root@master30:~# kubectl get configmaps kube-proxy -n kube-system -o yaml
apiVersion: v1
data:
config.conf: |
apiVersion: kubeproxy.config.k8s.io/v1alpha1
bindAddress: 0.0.0.0
bindAddressHardFail: false
clientConnection:
acceptContentTypes: ""
burst: 0
contentType: ""
kubeconfig: /var/lib/kube-proxy/kubeconfig.conf
qps: 0
clusterCIDR: 10.224.0.0/16
configSyncPeriod: 0s
conntrack:
maxPerCore: null
min: null
tcpCloseWaitTimeout: null
tcpEstablishedTimeout: null
detectLocalMode: ""
enableProfiling: false
healthzBindAddress: ""
hostnameOverride: ""
iptables:
masqueradeAll: false
masqueradeBit: null
minSyncPeriod: 0s
syncPeriod: 0s
ipvs:
excludeCIDRs: null
minSyncPeriod: 0s
scheduler: ""
strictARP: false
syncPeriod: 0s
tcpFinTimeout: 0s
tcpTimeout: 0s
udpTimeout: 0s
kind: KubeProxyConfiguration
metricsBindAddress: ""
mode: ""
nodePortAddresses: null
oomScoreAdj: null
portRange: ""
showHiddenMetricsForVersion: ""
udpIdleTimeout: 0s
winkernel:
enableDSR: false
networkName: ""
sourceVip: ""
kubeconfig.conf: |
apiVersion: v1
kind: Config
clusters:
– cluster:
certificate-authority: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
server: https://10.1.8.30:6443
name: default
contexts:
– context:
cluster: default
namespace: default
user: default
name: default
current-context: default
users:
– name: default
user:
tokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token
kind: ConfigMap
metadata:
annotations:
kubeadm.kubernetes.io/component-config.hash: sha256:77333136e4f6883a76e786187738706eb9a60efd1f8641f2489dbd1e085726d9
creationTimestamp: "2021-07-03T03:07:55Z"
labels:
app: kube-proxy
managedFields:
– apiVersion: v1
fieldsType: FieldsV1
fieldsV1:
f:data:
.: {}
f:config.conf: {}
f:kubeconfig.conf: {}
f:metadata:
f:annotations:
.: {}
f:kubeadm.kubernetes.io/component-config.hash: {}
f:labels:
.: {}
f:app: {}
manager: kubeadm
operation: Update
time: "2021-07-03T03:07:55Z"
name: kube-proxy
namespace: kube-system
resourceVersion: "193"
selfLink: /api/v1/namespaces/kube-system/configmaps/kube-proxy
uid: 2b6168fd-29c8-49c4-a465-08720e9f48db

# kube-proxy有两种工作模式ipvs和iptables
# 这里 mode 值为空,查看日志发现默认使用iptables。
root@master30:~# kubectl logs -n kube-system kube-proxy-8kp8w
I1019 02:26:00.975333 1 server_others.go:69] "Using iptables proxy"
I1019 02:26:01.037589 1 node.go:141] Successfully retrieved node IP: 10.1.8.31
I1019 02:26:01.040909 1 conntrack.go:100] "Set sysctl" entry="net/netfilter/nf_conntrack_max" value=131072
I1019 02:26:01.041412 1 conntrack.go:52] "Setting nf_conntrack_max" nfConntrackMax=131072
I1019 02:26:01.041902 1 conntrack.go:100] "Set sysctl" entry="net/netfilter/nf_conntrack_tcp_timeout_close_wait" value=3600
......

# 更改模式为ipvs
root@master30:~# kubectl edit cm -n kube-system kube-proxy
......
mode: "ipvs"
......

# 删除pod,等待控制器重新创建
root@master30:~# kubectl get pod -n kube-system |grep kube-proxy
kube-proxy-8kp8w 1/1 Running 1 37d
kube-proxy-ghgxw 1/1 Running 1 37d
kube-proxy-p6qnk 1/1 Running 1 37d

root@master30:~# kubectl delete pod -n kube-system kube-proxy-{8kp8w,ghgxw,p6qnk}
pod "kube-proxy-8kp8w" deleted
pod "kube-proxy-ghgxw" deleted
pod "kube-proxy-p6qnk" deleted

# 再次查看日志
root@master30:~# kubectl get pod -n kube-system |grep kube-proxy
kube-proxy-8swmx 1/1 Running 0 18s
kube-proxy-948cw 1/1 Running 0 29s
kube-proxy-xlh7b 1/1 Running 0 24s
root@master30:~# kubectl logs -n kube-system kube-proxy-8swmx
I1019 03:41:12.288952 1 node.go:141] Successfully retrieved node IP: 10.1.8.31
I1019 03:41:12.290902 1 conntrack.go:52] "Setting nf_conntrack_max" nfConntrackMax=131072
I1019 03:41:12.325988 1 server.go:632] "kube-proxy running in dual-stack mode" primary ipFamily="IPv4"
I1019 03:41:12.364416 1 server_others.go:218] "Using ipvs Proxier"
......

# 实验完成后,模式更改回来

综合案例:haproxy+web

需求:

  • 创建一个名称为 haproxy 的pod,使用镜像 haproxy,pod haproxy 的配置文件保存在 configmap 中,通过 volume 方式挂载到 /usr/local/etc/haproxy/haproxy.cfg。将流量转发到pod webapp-1 和 webapp-2。
  • haproxy 的配置文件模板内容如下:

    global
    daemon
    maxconn 256

    defaults
    mode http
    timeout connect 5000ms
    timeout client 50000ms
    timeout server 50000ms

    frontend http-in
    bind *:8080
    default_backend servers

    backend servers
    server app1 10.224.84.80:80 check
    server app2 10.224.149.25:80 check

  • 创建第一个pod,名称为webapp-1,使用镜像nginx。为该pod创建一个cm,名称为webapp-1,该cm保存两个值:
    • index.html=“hello webapp-1”
    • error.html=“sorry, error.”

    这个两个值通过volume方式挂载到**/usr/share/nginx/html**目录。

  • 创建第二个pod,名称为webapp-2,使用镜像nginx。为该pod创建一个cm,名称为webapp-2,该cm保存两个值:
    • index.html=“hello webapp-2”
    • error.html=“sorry, error.”

    这个两个值通过volume方式挂载到**/usr/share/nginx/html**目录。

    解答:

  • 创建第一个cm和pod
  • root@master30:~# mkdir web && cd web
    root@master30:~/web# kubectl create cm webapp-1 –from-literal=index.html="hello webapp-1" –from-literal=error.html="sorry, error."
    root@master30:~/web# vim pod-webapp-1.yaml

    apiVersion: v1
    kind: Pod
    metadata:
    labels:
    run: webapp1
    name: webapp1
    spec:
    containers:
    name: nginx
    image: hub.laoma.cloud/library/nginx:latest
    imagePullPolicy: IfNotPresent
    volumeMounts:
    name: config
    mountPath: "/usr/share/nginx/html"
    readOnly: true
    volumes:
    name: config
    configMap:
    name: webapp1

    root@master30:~/web# kubectl apply -f pod-webapp-1.yaml

  • 创建第二个cm和pod
  • root@master30:~/web# kubectl create cm webapp-2 –from-literal=index.html="hello webapp-2" –from-literal=error.html="sorry, error."
    root@master30:~/web# vim pod-webapp-2.yaml

    apiVersion: v1
    kind: Pod
    metadata:
    labels:
    run: webapp2
    name: webapp2
    spec:
    containers:
    name: nginx
    image: hub.laoma.cloud/library/nginx:latest
    imagePullPolicy: IfNotPresent
    volumeMounts:
    name: config
    mountPath: "/usr/share/nginx/html"
    readOnly: true
    volumes:
    name: config
    configMap:
    name: webapp2

    root@master30:~/web# kubectl apply -f pod-webapp-2.yaml

  • 创建haproxy配置文件。
  • # 获取pod ip地址
    root@master30:~/web# kubectl get pods -o wide
    NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
    webapp-1 1/1 Running 0 63m 10.224.84.80 worker1.laoma.fun <none> <none>
    webapp-2 1/1 Running 0 63m 10.224.149.25 worker2.laoma.fun <none> <none>

    # haproxy内容如下:
    root@master30:~/web# vim haproxy.cfg

    global
    daemon
    maxconn 256

    defaults
    mode http
    timeout connect 5000ms
    timeout client 50000ms
    timeout server 50000ms

    frontend http-in
    bind *:8080
    default_backend servers

    backend servers
    server app1 10.224.84.80:80 check
    server app2 10.224.149.25:80 check

    # 创建haproxy.cfg configmap
    root@master30:~/web# kubectl create cm haproxy.cfg –from-file=haproxy.cfg=./haproxy.cfg

    # 创建pod haproxy
    root@master30:~/web# vim haproxy.yaml


    apiVersion: v1
    kind: Pod
    metadata:
    name: haproxy
    spec:
    containers:
    name: haproxy
    image: hub.laoma.cloud/library/haproxy
    imagePullPolicy: IfNotPresent
    securityContext:
    allowPrivilegeEscalation: true
    volumeMounts:
    name: config
    mountPath: "/usr/local/etc/haproxy"
    readOnly: true
    volumes:
    name: config
    configMap:
    name: haproxy.cfg

    root@master30:~/web# kubectl apply -f haproxy.yaml

    # 验证
    root@master30:~/web# kubectl get pods haproxy -o wide
    NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
    haproxy 1/1 Running 0 33s 10.224.149.35 worker32.laoma.cloud <none> <none>

    root@master30:~# curl http://10.224.149.35:8080
    hello webapp-1
    root@master30:~# curl http://10.224.149.35:8080
    hello webapp-2

    Secret

    学习参考:Secret

    Secret 介绍

    Secret 是一种包含少量敏感信息的对象,例如密码、令牌或密钥。 这样的信息可能会被放在 Pod 规约中或者镜像中。 使用 Secret 意味着你不需要在应用程序代码中包含机密数据。

    创建 Secret 可以独立于使用它们的 Pod, 减少在创建、查看和编辑 Pod 的工作流程中暴露 Secret(及其数据)的风险。 Kubernetes 和在集群中运行的应用程序也可以对 Secret 采取额外的预防措施, 例如避免将敏感数据写入非易失性存储。

    Secret 类似于 ConfigMap 但专门用于保存机密数据。

    Secret 与ConfigMap的区别在于:Secret对数据编码,ConfigMap不对数据编码。

    Secret 类型

    • generic:定义键值对,对变量值加密,类型为Opaque。

    • docker-registry:用于访问registry仓库的凭据,类型kubernetes.io/dockerconfigjson。

    • tls:保存TLS公钥和私钥,类型为Opaque。

    Secret 创建

    generic

    # 帮助信息
    root@master30:~# kubectl create secret generic –help
    Create a secret based on a file, directory, or specified literal value.

    A single secret may package one or more key/value pairs
    ......

    基于键值对

    一般用于传递变量值。

    root@master30:~# kubectl create secret generic mysecret1 –from-literal=user=tom –from-literal=password1=redhat –from-literal=password2=redhat

    root@master30:~# kubectl get secrets
    NAME TYPE DATA AGE
    mysecret1 Opaque 3 21s

    root@master30:~# kubectl get secrets mysecret1 -o yaml
    apiVersion: v1
    data:
    password1: cmVkaGF0
    password2: cmVkaGF0
    user: dG9t
    kind: Secret
    metadata:
    ......
    name: mysecret1
    namespace: laoma
    resourceVersion: "24180"
    selfLink: /api/v1/namespaces/laoma/secrets/mysecret1
    uid: d510d58f-8737-4d2f-bd00-dd9ce6b50a9b
    type: Opaque

    root@master30:~# kubectl get secrets mysecret1 -o jsonpath={.data} | json_reformat
    {
    "password1": "cmVkaGF0",
    "password2": "cmVkaGF0",
    "user": "amFjaw=="
    }

    # json_reformat 工具由软件包 yajl-tools 提供

    root@master30:~# kubectl get secrets mysecret1 -o jsonpath={.data.user}
    amFjaw==

    root@master30:~# kubectl describe secrets mysecret1
    Name: mysecret1
    Namespace: laoma
    Labels: <none>
    Annotations: <none>

    Type: Opaque

    Data
    ====
    password1: 6 bytes
    password2: 6 bytes
    user: 3 bytes

    # secret 通过 base64 编码
    root@master30:~# echo -n tom | base64
    dG9t
    root@master30:~# echo -n redhat|base64
    cmVkaGF0
    root@master30:~# echo -n cmVkaGF0|base64 -d
    redhat

    基于普通文件

    一般用于传递配置文件。

    root@master30:~# echo -n tom > user
    root@master30:~# echo -n redhat > password1
    root@master30:~# echo -n redhat > password2
    root@master30:~# kubectl create secret generic mysecret2 –from-file=./user –from-file=./password1 –from-file=./password2
    # 文件名用作key名,文件内容用作value,也可以自定义key名
    root@master30:~# kubectl create secret generic mysecret3 –from-file=username=./user –from-file=./password1 –from-file=./password2

    root@master30:~# kubectl get secrets mysecret2 -o yaml
    apiVersion: v1
    data:
    password1: cmVkaGF0
    password2: cmVkaGF0
    user: dG9t
    kind: Secret
    metadata:
    ......
    name: mysecret2
    namespace: laoma
    resourceVersion: "25329"
    selfLink: /api/v1/namespaces/laoma/secrets/mysecret2
    uid: 047366b6-e8d2-4cf0-b68c-d1f5f9999458
    type: Opaque

    root@master30:~# kubectl get secrets mysecret3 -o yaml
    apiVersion: v1
    data:
    password1: cmVkaGF0
    password2: cmVkaGF0
    username: dG9t
    kind: Secret
    metadata:
    ......
    name: mysecret3
    namespace: laoma
    resourceVersion: "25532"
    selfLink: /api/v1/namespaces/laoma/secrets/mysecret3
    uid: e19df9a7-7ce3-4539-b6f5-92f83417ac1f
    type: Opaque

    基于键值对内容的文件

    root@master30:~# echo 'user=tom
    password1=redhat
    password2=redhat' > env.txt

    root@master30:~# kubectl create secret generic mysecret4 –from-env-file=./env.txt
    secret/mysecret4 created

    root@master30:~# kubectl get secrets mysecret4 -o yaml
    apiVersion: v1
    data:
    password1: cmVkaGF0
    password2: cmVkaGF0
    user: dG9t
    kind: Secret
    metadata:
    ......
    name: mysecret4
    namespace: laoma
    resourceVersion: "27240"
    selfLink: /api/v1/namespaces/laoma/secrets/mysecret3
    uid: 935c0392-8e54-492d-b093-99021e0dc5bb
    type: Opaque

    基于目录

    文件名用作key名,文件内容用作value。

    root@master30:~# mkdir config
    root@master30:~# mv user password1 password2 config
    root@master30:~# kubectl create secret generic mysecret5 –from-file=./config
    secret/my-secret5 created

    root@master30:~# kubectl get secrets mysecret5 -o yaml
    apiVersion: v1
    data:
    password1: cmVkaGF0
    password2: cmVkaGF0
    user: dG9t
    kind: Secret
    metadata:
    ......
    name: mysecret5
    namespace: laoma
    resourceVersion: "26687"
    selfLink: /api/v1/namespaces/laoma/secrets/mysecret4
    uid: 04eccd8b-8686-4856-82c3-0ac697d75746
    type: Opaque

    基于 yaml 文件

    apiVersion: v1
    kind: Secret
    metadata:
    name: mysecret6
    type: Opaque
    data:
    user: dG9t
    password1: cmVkaGF0
    password2: cmVkaGF0

    yaml格式中变量值使用转换后的值。

    docker-registry

    回顾docker login命令:

    docker login DOCKER_REGISTRY_SERVER -u=DOCKER_USER -p=DOCKER_PASSWORD

    docker 登录的信息默认保存在~/.dockercfg,后续docker pull和push使用该凭据文件访问registry。

    Usage:
    kubectl create secret docker-registry NAME –docker-username=user –docker-password=password –docker-email=email [–docker-server=string] [–from-literal=key1=value1] [–dry-run=server|client|none] [options]

    示例:

    root@master30:~# kubectl create secret docker-registry registry –docker-username=laoma –docker-password=redhat –docker-email=admin@laoma.cloud –docker-server=registry.laoma.cloud
    secret/docker-registry-secret created
    root@master30:~# kubectl get secrets docker-registry-secret -o yaml
    apiVersion: v1
    data:
    .dockerconfigjson: eyJhdXRocyI6eyJyZWdpc3RyeS5yZWRoYXQuZnVuIjp7InVzZXJuYW1lIjoibGFvbWEiLCJwYXNzd29yZCI6InJlZGhhdCIsImVtYWlsIjoibGFvbWFAcmVkaGF0LmZ1biIsImF1dGgiOiJiR0Z2YldFNmNtVmthR0YwIn19fQ==
    kind: Secret
    metadata:
    ......
    name: docker-registry-secret
    namespace: laoma
    resourceVersion: "29629"
    selfLink: /api/v1/namespaces/laoma/secrets/docker-registry-secret
    uid: 017f736a-11f5-42d8-a9ed-47dad254f2c2
    type: kubernetes.io/dockerconfigjson

    TLS

    创建 TLS secret 保存公钥/私钥对。 公钥证书必须是 .PEM 编码。

    Usage:
    kubectl create secret tls NAME –cert=path/to/cert/file –key=path/to/key/file [–dry-run=server|client|none] [options]

    创建私钥和证书

    #–1–生成私钥
    root@master30:~# mkdir certs && cd certs
    [root@master30 certs]# openssl genrsa -out www.key 2048

    #–2–生成请求文件csr
    [root@master30 certs]# openssl req -new -key www.key -out www.csr -subj "/C=CN/ST=JS/L=NJ/O=LM/OU=DEVOPS/CN=www.laoma.cloud/emailAddress=admin@laoma.cloud"
    # CN的值必须是网站域名

    #–3–使用自己的私钥对请求文件签名,以生成证书
    [root@master30 certs]# openssl x509 -req -days 3650 -in www.csr -signkey www.key -out www.crt

    创建 tls 类型 secret

    [root@master30 certs]# kubectl create secret tls www-tls –cert=./www.crt –key=./www.key

    Secret 引用

    Secrets可以以卷方式挂载给pods,也可以通过环境变量方式传递给pods。

    以环境变量方式引用

    示例:

    root@master30:~# vim pod-with-env-from-secret.yaml


    apiVersion: v1
    kind: Pod
    metadata:
    name: mysql
    labels:
    name: mysql
    spec:
    containers:
    image: hub.laoma.cloud/library/mysql:latest
    imagePullPolicy: IfNotPresent
    name: mysql
    ports:
    containerPort: 3306
    name: mysql
    env:
    name: MYSQL_ROOT_PASSWORD
    # 原先通过value设置环境变量值
    valueFrom:
    secretKeyRef:
    name: mysecret1
    key: password1

    验证

    root@master30:~# kubectl apply -f pod-with-env-from-secret.yaml
    root@master30:~# kubectl get pod -o wide
    NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
    mysql 1/1 Running 0 90s 10.224.51.131 worker31.laoma.cloud <none> <none>

    root@master30:~# kubectl exec -it mysql — bash -c 'echo $MYSQL_ROOT_PASSWORD'
    redhat

    root@master30:~# mysql -u root -predhat -h 10.224.51.131 –ssl-mode=DISABLED

    # 清理pod
    root@master30:~# kubectl delete pod mysql –force

    以 volume 方式引用

    root@master30:~# echo Hello world > index.html
    root@master30:~# echo error > error.html
    root@master30:~# kubectl create secret generic web –from-file=./index.html –from-file=./error.html

    引用整体

    示例:

    root@master30:~# vim pod-with-volume-from-secret.yaml

    apiVersion: v1
    kind: Pod
    metadata:
    labels:
    run: web
    name: web
    spec:
    containers:
    image: hub.laoma.cloud/library/nginx:latest
    imagePullPolicy: IfNotPresent
    name: web
    volumeMounts:
    name: webcontent
    # mountPath值是一个挂载点,将secrete中所有键值对挂载过来
    mountPath: "/usr/share/nginx/html"
    volumes:
    name: webcontent
    secret:
    secretName: web

    验证

    root@master30:~# kubectl apply -f pod-with-volume-from-secret.yaml
    root@master30:~# kubectl get pod -o wide
    NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
    web 1/1 Running 0 15s 10.224.51.136 worker31.laoma.cloud <none> <none>

    root@master30:~# curl 10.224.51.136
    Hello World
    root@master30:~# curl 10.224.51.136/error.html
    error

    # 清理pod
    root@master30:~# kubectl delete pod web –force

    引用特定 key

    示例:nginx.yaml

    root@master30:~# vim pod-secret-volume-single.yaml

    apiVersion: v1
    kind: Pod
    metadata:
    labels:
    run: web
    name: web
    spec:
    containers:
    image: hub.laoma.cloud/library/nginx:latest
    imagePullPolicy: IfNotPresent
    name: web
    volumeMounts:
    name: webcontent
    mountPath: "/usr/share/nginx/html"
    volumes:
    name: webcontent
    secret:
    secretName: web
    items:
    key: index.html
    # 通过path设置挂载的文件名,这里我们path值与key一致。
    path: index.html

    或者

    apiVersion: v1
    kind: Pod
    metadata:
    labels:
    run: web
    name: web
    spec:
    containers:
    image: hub.laoma.cloud/library/nginx:latest
    imagePullPolicy: IfNotPresent
    name: web
    volumeMounts:
    name: webcontent
    # 将webcontent中index.html挂载到/usr/share/nginx/html/index.html
    mountPath: "/usr/share/nginx/html/index.html"
    # 使用subPath参数,则表明mountPath的值是一个文件
    subPath: index.html
    volumes:
    name: webcontent
    secret:
    secretName: web

    验证

    root@master30:~# kubectl create -f pod-secret-volume-single.yaml

    root@master30:~# kubectl get pod -o wide
    NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
    web 1/1 Running 0 21s 10.224.51.137 worker31.laoma.cloud <none> <none>
    root@master30:~# curl 10.224.51.137/index.html
    Hello World

    # /usr/share/nginx/html目录中没有index.html和error.html
    root@master30:~# kubectl exec web — ls /usr/share/nginx/html
    index.html

    以卷方式引用,支持动态更新secret内容:

    root@master30:~# echo 'Hello Nginx' |base64
    SGVsbG8gbmdpbng=

    # 更改data.index内容为SGVsbG8gbmdpbng=
    root@master30:~# kubectl edit secrets web
    ......
    apiVersion: v1
    data:
    index: SGVsbG8gbmdpbng=
    ......

    # 等30秒左右查看
    root@master30:~# curl 10.224.51.137/index.html
    Hello Nginx

    文件权限

    映射过去文件默认权限是644(8进制),对应10进制是420.。

    设置映射的所有文件权限,defaultMode。

    volumes:
    name: foo
    secret:
    secretName: mysecret1
    defaultMode: 256

    10进制是256转换成8进制是400。因为json格式不支持8进制,所以使用10进制。

    root@master30:~# kubectl exec mypod1 — ls -l /etc/foo/..data/user
    -r——– 1 root root 4 Aug 9 08:58 /etc/foo/..data/user

    设置映射的单独文件权限

    volumes:
    name: foo
    secret:
    secretName: mysecret1
    items:
    key: user
    path: user
    mode: 511

    10进制是511转换成8进制是777。

    root@master30:~# kubectl exec mypod1 — ls -l /etc/foo/..data/user
    -rwxrwxrwx 1 root root 4 Aug 9 08:58 /etc/foo/..data/user

    环境清理

    root@master30:~# kubectl delete ns configure

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » K8s 配置管理实战:ConfigMap 与 Secret 完整使用指南
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!