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

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

Kubernetes Configure

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

环境准备

bash 复制代码
root@master30:~# kubectl create ns configure
root@master30:~# kubectl config set-context --current --namespace configure

ConfigMap

学习参考:ConfigMap

ConfigMap 介绍

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

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

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

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

ConfigMap 使用建议

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

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

ConfigMap 创建

使用帮助

bash 复制代码
kubectl create configmap NAME [--from-file=[key=]source]
[--from-literal=key1=value1] [--dry-run=server|client|none] [options]
键值对类型
bash 复制代码
root@master30:~# kubectl create configmap mysql --from-literal=password=redhat 
root@master30:~# kubectl get configmaps mysql -o yaml |grep ^data -A1
data:
  password: redhat
文件类型
bash 复制代码
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
目录类型
bash 复制代码
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 引用

环境变量方式引用

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

bash 复制代码
root@master30:~# vim pod-with-env-from-configmap.yaml
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

验证

bash 复制代码
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挂载。

引用整体
bash 复制代码
root@master30:~# vim pod-with-volume-from-configmap.yaml
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

验证

bash 复制代码
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
bash 复制代码
root@master30:~# vim pod-cm-volume-single.yaml
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

等同于

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/index.html"
      subPath: index.html
  volumes:
  - name: webcontent
    configMap:
      name: web2

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

k8s 中 ConfigMap

以 kube-proxy 为例

bash 复制代码
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

需求

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

haproxy 的配置文件模板内容如下:

ini 复制代码
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
  1. 创建第一个pod,名称为webapp-1 ,使用镜像nginx 。为该pod创建一个cm,名称为webapp-1,该cm保存两个值:
  • index.html="hello webapp-1"
  • error.html="sorry, error."

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

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

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

解答:

  1. 创建第一个cm和pod
bash 复制代码
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
yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: webapp-1
  name: webapp-1
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: webapp-1
bash 复制代码
root@master30:~/web# kubectl apply -f pod-webapp-1.yaml
  1. 创建第二个cm和pod
bash 复制代码
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
yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: webapp-2
  name: webapp-2
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: webapp-2
bash 复制代码
root@master30:~/web# kubectl apply -f pod-webapp-2.yaml
  1. 创建haproxy配置文件。
bash 复制代码
# 获取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
ini 复制代码
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
bash 复制代码
# 创建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
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
bash 复制代码
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
bash 复制代码
# 帮助信息
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
......
基于键值对

一般用于传递变量值。

bash 复制代码
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
基于普通文件

一般用于传递配置文件。

bash 复制代码
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
基于键值对内容的文件
bash 复制代码
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。

bash 复制代码
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 文件
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。

bash 复制代码
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]

示例:

bash 复制代码
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 编码。

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

创建私钥和证书

bash 复制代码
#--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

bash 复制代码
[root@master30 certs]# kubectl create secret tls www-tls --cert=./www.crt --key=./www.key

Secret 引用

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

以环境变量方式引用

示例:

bash 复制代码
root@master30:~# vim pod-with-env-from-secret.yaml
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

验证

bash 复制代码
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 方式引用
bash 复制代码
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
引用整体

示例:

bash 复制代码
root@master30:~# vim pod-with-volume-from-secret.yaml
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

验证

bash 复制代码
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

bash 复制代码
root@master30:~# vim pod-secret-volume-single.yaml
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

或者

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
      # 将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

验证

bash 复制代码
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内容:

bash 复制代码
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。

yaml 复制代码
  volumes:
  - name: foo
    secret:
      secretName: mysecret1
      defaultMode: 256

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

bash 复制代码
root@master30:~# kubectl exec mypod1 -- ls -l /etc/foo/..data/user
-r--------     1 root     root             4 Aug  9 08:58 /etc/foo/..data/user

设置映射的单独文件权限

yaml 复制代码
  volumes:
  - name: foo
    secret:
      secretName: mysecret1
      items:
      - key: user
        path: user
        mode: 511

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

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

环境清理

bash 复制代码
root@master30:~# kubectl delete ns configure
相关推荐
showyoui2 小时前
K8s 集群迁移踩坑:Istio 升级后 nginx 403
网络·docker·kubernetes·istio·service_mesh
云川之下3 小时前
【k8s】sriov‑device‑plugin、sriov‑network‑config‑daemon详解
云原生·容器·kubernetes
聚搜云——JuSouClouD14 小时前
深圳阿里云代理商:OpenTelemetry 统一观测日志指标链路接入实战
阿里云·云计算
张忠琳21 小时前
【NPU】Ascend Device Plugin —Part 6 K8s客户端 + 重复检测模块 超深度源码分析之二
云原生·容器·kubernetes·npu·docker device
云川之下21 小时前
【k8s】SR‑IOV‑Network‑Operator 详解
云原生·容器·kubernetes
风曦Kisaki1 天前
对象存储 MinIO 的两种生产环境适用部署方式
kubernetes
Ai拆代码的曹操1 天前
DaemonSet OnDelete 策略详解:为何 rollout restart 无效及正确迁移方案
docker·容器·kubernetes
名字还没想好☜1 天前
Kubernetes NetworkPolicy 实战:默认全通的坑与用标签做零信任隔离
运维·云原生·容器·kubernetes·networkpolicy
workflower1 天前
全球云计算产业发展态势-市场:云计算规模保持稳步增长,产业格局日趋明晰
人工智能·深度学习·机器学习·设计模式·机器人·云计算