kubernetes的配置管理secret管理

 

 

 

Secret

Secret 介绍

https://kubernetes.io/zh-cn/docs/concepts/configuration/secret/
https://kubernetes.io/zh-cn/docs/tasks/configmap-secret/

Secret 和 Configmap 相似,也可以提供配置数据,但主要用于为Pod提供敏感需要加密的信息
Secret 主要用于存储密码、证书私钥,SSH 密钥,OAuth令牌等敏感信息,这些敏感信息采用base64编码保存,相对明文存储更安全
相比于直接将敏感数据配置在Pod的定义或者镜像中,Secret提供了更加安全的机制,将需要共享的数据进行加密,防止数据泄露。
Secret的对象需要单独定义并创建,通常以数据卷的形式挂载到Pod中,Secret的数据将以文件的形式保存,容器通过读取文件可以获取需要的数据。

Secret volume是通过tmpfs(内存文件系统)实现的,所以这种类型的volume不是永久存储的。
每个Secret的数据不能超过1MB,支持通过资源限额控制每个名称空间的Secret的数量
注意: Secret 属于名称空间级别,只能被同一个名称空间的Pod引用

 

 

image

 

Secret 分成以下常见大的分类

 

类型 解析
generic 通用类型,基于base64编码用来存储密码,公钥等。常见的子类型有:
Opaque,kubernetes.io/service-account-token,kubernetes.io/basicauth,kubernetes.io/ssh-auth,bootstrap.kubernetes.io/token,kubernetes.io/rbd
tls 专门用于保存tls/ssl用到证书和配对的私钥,常见的子类型:kubernetes.io/tls
dockerregistry 专用于让kubelet启动Pod时从私有镜像仓库pull镜像时,首先认证到仓库Registry时使用常见的子类型:kubernetes.io/dockercfg,kubernetes.io/dockerconfigjson

 

Secret 创建方式
手动创建:用户自行创建的Secret 常用来存储用户私有的一些信息
自动创建:集群自动创建的Secret 用来作为集群中各个组件之间通信的身份校验使用
范例: Secret 大的类别

[root@master1 ~]#kubectl create secret -h
Create a secret using specified subcommand.
Available Commands:
 docker-registry   创建一个给 Docker registry 使用的 Secret
 generic           Create a secret from a local file, directory, or literal 
value
 tls               创建一个 TLS secret
Usage:
 kubectl create secret [flags] [options]
Use "kubectl <command> --help" for more information about a given command.
Use "kubectl options" for a list of global command-line options (applies to all 
commands).

 

 查看k8s系统自带 Secret 

[root@master1 ~]# kubectl get secret -A
NAMESPACE        NAME                     TYPE                            DATA   AGE
kube-system      bootstrap-token-4j1jpl   bootstrap.kubernetes.io/token   6      14d
metallb-system   memberlist               Opaque                          1      2d4h
metallb-system   metallb-webhook-cert     Opaque                          4      2d4h

 

范例:命令式创建 generic

#命令式创建

 kubectl create secret generic secret-mysql-root --from-literal=username=root --from-literal=password=123456

[root@master1 config]# kubectl get secrets
NAME                TYPE     DATA   AGE
secret-mysql-root   Opaque   2      19s

 

[root@master1 config]# kubectl get secrets secret-mysql-root -o yaml
apiVersion: v1
data:
  password: MTIzNDU2
  username: cm9vdA==
kind: Secret
metadata:
  creationTimestamp: "2026-05-24T13:21:07Z"
  name: secret-mysql-root
  namespace: default
  resourceVersion: "339720"
  uid: eed9dfc7-8059-419f-bbbe-eafba13aa860
type: Opaque

#解码

[root@master1 config]# echo -n cm9vdA== | base64 -d
root[root@master1 config]# echo -n MTIzNDU2 | base64 -d
123456[root@master1 config]# 

 

 #清单文件,secret 通过环境为提供MySQL环境初始化的密码信息,但很不安全

[root@master1 config]# cat storage-secret-mysql-init.yaml
apiVersion: v1
kind: Secret
metadata:
  name: secret-mysql
type: kubernetes.io/basic-auth
#type: Opaque  #也可以用Opaque类型
data:
  username: cm9vdAo=             #key名称:username:root
  password: MTIzNDU2             #key名称:password: 123456
---
apiVersion: v1
kind: Pod
metadata:
  name: pod-secret-mysql-init
spec:
  containers:
  - name: mysql
    image: registry.cn-beijing.aliyuncs.com/wangxiaochun/mysql:8.0.29-oracle
    env:
    - name: MYSQL_ROOT_PASSWORD
      valueFrom:
        secretKeyRef:            
          name: secret-mysql      #引用指定的secret
          key: password           #引用指定的secret中对应的key
          optional: false         #必须存在

 

kubectl apply -f storage-secret-mysql-init.yaml

[root@master1 config]# kubectl get pod
NAME                                        READY   STATUS    RESTARTS       AGE
controller-deployment-demo-5f884bb8-2ppvf   1/1     Running   5 (11h ago)    2d3h
controller-deployment-demo-5f884bb8-fscrl   1/1     Running   14 (11h ago)   8d
controller-deployment-demo-5f884bb8-rfsbv   1/1     Running   13 (11h ago)   8d
pod-nginx-conf-configmap                    1/1     Running   0              6h30m
pod-secret-mysql-init                       1/1     Running   0              5s

 

[root@master1 config]# kubectl exec -it pod-secret-mysql-init -- bash

           
bash-4.4# mysql -uroot -p123456
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.29 MySQL Community Server - GPL

Copyright (c) 2000, 2022, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

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

mysql> 
mysql> 

变量不支持动态更新

 

范例: 通过卷调用 secret

#清单文件

[root@master1 config]# cat storage-secret-test-pod.yaml 
apiVersion: v1
kind: Secret
metadata:
 name: secret-test
type: kubernetes.io/basic-auth
#type: Opaque  #也可以用Opaque类型
data:
 #username: admin
 username: YWRtaW4=
 #password: password
 password: cGFzc3dvcmQ=
 
#说明:
#type类型指定为 Opaque 或者 kubernetes.io/basic-auth,username和password是加密的信息
#资源定义文件时,与命令行创建secret的--from-literal=username=admin 效果是一样的,但命令行的变量无需加密
---
#调用secret的清单文件
apiVersion: v1
kind: Pod
metadata:
  name: pod-secret-volume
spec:
  volumes:
  - name: secret
    secret:
     secretName: secret-test       #指定secret的名称
  containers:
    - name: secret-test-container
      image: registry.cn-beijing.aliyuncs.com/wangxiaochun/nginx:1.20.0
      volumeMounts:                #卷引用secret
       - name: secret
         mountPath: /secret/
         readOnly: true

 

kubectl apply -f storage-secret-test-pod.yaml

 

root@master1 config]# kubectl get secrets
NAME          TYPE                       DATA   AGE
secret-test   kubernetes.io/basic-auth   2      3s

 

[root@master1 config]# kubectl get pod
NAME                                        READY   STATUS    RESTARTS       AGE
controller-deployment-demo-5f884bb8-2ppvf   1/1     Running   5 (11h ago)    2d4h
controller-deployment-demo-5f884bb8-fscrl   1/1     Running   14 (11h ago)   8d
controller-deployment-demo-5f884bb8-rfsbv   1/1     Running   13 (11h ago)   8d
pod-secret-volume                           1/1     Running   0              19s

 

[root@master1 config]# kubectl exec -it pod-secret-volume -- bash
root@pod-secret-volume:/# ls /secret
password  username
root@pod-secret-volume:/# cat /secret/password
passwordroot@pod-secret-volume:/# 
root@pod-secret-volume:/# cat /secret/username 
adminroot@pod-secret-volume:/# 

支持动态更新 软连接

root@pod-secret-volume:/# ls -l /secret/
total 0
lrwxrwxrwx 1 root root 15 May 24 19:06 password -> ..data/password
lrwxrwxrwx 1 root root 15 May 24 19:06 username -> ..data/username

 

TLS 案例
TLS 类型的 Secret 主要用于对https场景的证书和密钥文件来进行加密传输

 

#tls类型格式
kubectl create secret tls NAME --cert=/path/file --key=/path/file

#注意:
#保存cert文件内容的key名称不能指定,自动为tls.crt,卷挂载后生成的文件名也为tls.crt
#保存private key文件内容的key不能指定,自动为tls.key,卷挂载后生成的文件名也为tls.key

 

image

 下面案例实现一个基于https 的nginx的web服务

创建 TLS 证书文件

#生成私钥匙

openssl genrsa -out nginx-certs/www.org.key 2048

#生成自签名证书

openssl req -new -x509 -key nginx-certs/www.org.key -days 3650 -out nginx-certs/www.org.crt -subj /C=CN/ST=Guangzhou/L=Guangzhou/O=DevOps/CN=www.org

#注意:CN指向的域名必须是nginx配置中使用的域名信息

 

#查看文件

[root@master1 config]# ls nginx-certs/
www.org.crt  www.org.key

基于 TLS 证书文件创建对应的 Secret

kubectl create secret tls secret-nginx-ssl --cert=nginx-certs/www.org.crt --key=nginx-certs/www.org.key

#查看结果

[root@master1 config]# kubectl get secrets
NAME               TYPE                DATA   AGE
secret-nginx-ssl   kubernetes.io/tls   2      8s

#查看内容

[root@master1 config]# kubectl get secrets secret-nginx-ssl -o yaml
apiVersion: v1
data:
  tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURrVENDQW5tZ0F3SUJBZ0lVUVdFOE1aNHRmZldmeWVLUUtTc2lXTUI2dnZnd0RRWUpLb1pJaHZjTkFRRUwKQlFBd1dERUxNQWtHQTFVRUJoTUNRMDR4RWpBUUJnTlZCQWdNQ1VkMVlXNW5lbWh2ZFRFU01CQUdBMVVFQnd3SgpSM1ZoYm1kNmFHOTFNUTh3RFFZRFZRUUtEQVpFWlhaUGNITXhFREFPQmdOVkJBTU1CM2QzZHk1dmNtY3dIaGNOCk1qWXdOVEkwTVRreU1UVXdXaGNOTXpZd05USXhNVGt5TVRVd1dqQllNUXN3Q1FZRFZRUUdFd0pEVGpFU01CQUcKQTFVRUNBd0pSM1ZoYm1kNmFHOTFNUkl3RUFZRFZRUUhEQWxIZFdGdVozcG9iM1V4RHpBTkJnTlZCQW9NQmtSbApkazl3Y3pFUU1BNEdBMVVFQXd3SGQzZDNMbTl5WnpDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDCkFRb0NnZ0VCQU1TYXlDd2hEN2d1OWZOSTZQZlZrWFUxOXBNQXZsR3ovekx3UCt5UktGcjM0djd0MHcxV0tBZkYKOGFoSXJXek1ham1DUENuQ0RFTElKUFNRMmlxQ1FjNEQvUEdsUThza3NnUE5kYjF6NTlRNnR6MTVRbWxERWxubwpoZ0ZlVzAwL3A1bEsxWnRuU1A2QllPQUk4ckdlVGE1Tm9VcFZWcm5QTTMxWmVzVElPcm9SdFFmQldocThtTFkzCkdpOGliSkRybHErNHo5dVpheXl3VHNjdVdkUXM4OWRGT2gyOTU2ZFljQ3lJQlFVTkRUeTBtb1lyNHNnZkQ1T2EKdGhRWWR2dlkzY0loNWwrR0swbnpYQ2pCWS9GOElSaC9zV3RHZUpBYlU3SDF5VXN1bE9UcTU1cTR6YjFReWRkdQpUWnNVWmNjZmZLcDdOd2NXWWpXZTRLY0ZnNGp0MEVFQ0F3RUFBYU5UTUZFd0hRWURWUjBPQkJZRUZKVzV5NFpDClN1TUpIQ0w4NkxwUi9SYktPYzRVTUI4R0ExVWRJd1FZTUJhQUZKVzV5NFpDU3VNSkhDTDg2THBSL1JiS09jNFUKTUE4R0ExVWRFd0VCL3dRRk1BTUJBZjh3RFFZSktvWklodmNOQVFFTEJRQURnZ0VCQUFSMDh3ajBCVHhhcEhnVQpIV0R2UGZXdGQrYi9Edm1NTGxubHRpMWNJUVpHUno3UzFteGNsc1NiSTVQK01JRHhDbGJWeWVHYkRXeGR4ZWxVCjRaU1cyemNjMk5aM3VvRmxqeStXVzFCVTA5UlhwWGNnVjU3c3VFak16bDRpTnY2N2pTU3ljcHB1aitMTVg0TE0KRlNidzExZCs2VGFMc0RwMjNTdW9NYUFZdWU3SFhJWllHbzZ2M2xuNzRJWFI5NXhnN0tPcEMvNTJucEx0NzdicApFZHFLVXhpb0VVMEZZT1ZnZ1VNdm1iSm0zNE5IbFlLRkRwd3FQdXBVS3h6MUt0eUdYK25leEY1NEg3ekxkRjdoCmVjYVVKRTRKR0h6bFZXQlAzSVJQdzJFK1FuWEtzVHYvam9LVzlicE96c0JVMW1KZlY4RCsxY05HczBqeDF5OGYKb3htbExwTT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
  tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2Z0lCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktnd2dnU2tBZ0VBQW9JQkFRREVtc2dzSVErNEx2WHoKU09qMzFaRjFOZmFUQUw1UnMvOHk4RC9za1NoYTkrTCs3ZE1OVmlnSHhmR29TSzFzekdvNWdqd3B3Z3hDeUNUMAprTm9xZ2tIT0EvenhwVVBMSkxJRHpYVzljK2ZVT3JjOWVVSnBReEpaNklZQlhsdE5QNmVaU3RXYlowaitnV0RnCkNQS3huazJ1VGFGS1ZWYTV6ek45V1hyRXlEcTZFYlVId1ZvYXZKaTJOeG92SW15UTY1YXZ1TS9ibVdzc3NFN0gKTGxuVUxQUFhSVG9kdmVlbldIQXNpQVVGRFEwOHRKcUdLK0xJSHcrVG1yWVVHSGI3Mk4zQ0llWmZoaXRKODF3bwp3V1B4ZkNFWWY3RnJSbmlRRzFPeDljbExMcFRrNnVlYXVNMjlVTW5YYmsyYkZHWEhIM3lxZXpjSEZtSTFudUNuCkJZT0k3ZEJCQWdNQkFBRUNnZ0VBQUtPVUpQaVNpWUcxa08zYXUvdDR0bzNQV0ZqM1JXSzFZS0FCUlM2UG1BUVkKTzhYZ0dybjk5VkNDWVk2aTZhaWNhOFZ0bHFFbjB3dTlld0lCZzRQYTNPV01hK2lpbU1Wc3dyQm5RbzllNElTMApWY0hRSW5GeVhOSnhwUTErZEhqUmZhRU5vcXlxUXhGK2xCdlRWaHB5bkM5cVo4aHhPTGRncm5hYy9JaStFQjYvCkpyUzNKSEs4ZVp6Y0duOElBblBkRGFBZjhqL3dDWkpOUE5XOE41VkZIa0pkUTRzSm9lSGZwdW8yRG04R0ZsOVEKVk5VbTZ1VWtPcytTSCtOVE9ZWnJmUjNlMERjdENIMDZGVzNXSGhtdy9UVEZYM0cxK2VyMlNYVDNxRVpnUmlTQgpMMTRIN2dOMUdacURIenc0b2lId1hObC9GKzdlRmJ2VGhFbHhaaXR1MVFLQmdRRHY5cUVjUERqVmlMa1ZEdUlICkdHeWEzUUU2UG1mNWd2VGJOZ3VXOGNHWlVsalBGdTdLSEJ2SXRsY1VGQkRSRFUrMkxtUXluWmpmaTJ3b2NLekoKM1VseUlLWnlZekIwbU1keHBYd1VwaHdtOWZ6WGR5RTh0cWFTeEx5bmlTUXVZNnlJMEhDZU5xNjE5enBGYjhKZQo1RU1Qd1BzOE8yWDJSemNtc1BzelpoUmpUd0tCZ1FEUnZsdFE1eExnemlRNFlQMnZaOUtCMklNM2F0cVFUTWV6CkdpNjNyMXJpNWJJWmFRQXVkMllUNG9aUEhWdkNVY1F5U2ZwM253a0sxTDJuaHp5cTVVd1pRaG92WUJxRjBVOUkKckRzSnFWbmNOZ2VRWVdwditmc2VLMnBGaGVnV2pycjR5TklMYW9aTVNtOUE5Z1ozYi82dlJRTU5nbXZrbVMyOApPcGlERktEdmJ3S0JnUURFSHVOQVMydjhBZG1hLzJYMmZKek8yVkFXaFVpL1lhdXp1ZkV3OWZmUDBzQ295TXB6ClB4UHFNRFR0UVJVWmR2S3VLQzVXTy8za3ZuT3dmWjZMQWFQMGRnRHp2bU9zOSswUjBqbWVPc0VKaXNTU2FWZ3QKNGU0MFNEMFVCSDhndHZBZGhaWjFpS1cwTFJKZ0M5NWxaZFAxZlRrWTJrY1VTTkluZWtCa21zcVErd0tCZ1FERQorVnN5cUQrZlpaaTRaY1g0czYwTENqVjRsdDM1eEZHTER0eXUzbnloTjR2QnQwMVhWZ1JFU21sTjVVbG1QWG5lCnJJRVBWQWllNWxuUitmeHNsZmlZZys2cGJUeWJUWTJDdDFTZVp5K2YwaEhhY3RJTnBSdERJd3lqaS9VQk1qdS8KSm9Hei9POXd1RHF4TEJ1NGtUSUNrZklpL3NlcW9IeEdHRlZnVE1BeSt3S0JnRm5iWVkvdUR3YjFMZjR1cC90bApkRkgreHhhVnZIaXltRnI2UFIrc1QrVFROQTdPQSttc1prTkVxSmlPTThvUXUwSkVuWjdxKzhjbVFVbWhjbUMxCk5vcEJ1Y1FoMjFPWDhJd1A3dGpCRnRMNnBsRnhTeGtVcWEzdk9RRmpNcTZXV1VWVGZkRW9SS0lNOHVTakVvZk8KcWs0SlJFVFZoa1pBM1NhTmxVUFpEWHpyCi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K
kind: Secret
metadata:
  creationTimestamp: "2026-05-24T19:25:39Z"
  name: secret-nginx-ssl
  namespace: default
  resourceVersion: "350364"
  uid: 8c69e163-9c5c-4b1c-b631-33b0af8fbc23
type: kubernetes.io/tls

 

准备 Nginx 配置文件

mkdir nginx-ssl-conf.d

[root@master1 config]# cd nginx-ssl-conf.d/
[root@master1 nginx-ssl-conf.d]# ls
myserver.conf  myserver-gzip.cfg  myserver-status.cfg

 

[root@master1 nginx-ssl-conf.d]# cat myserver.conf
server {
    listen 80;
    server_name www.org; 
    return 301 https://$host$request_uri; 
}

server {
    listen 443 ssl;
    server_name www.org;

    ssl_certificate /etc/nginx/certs/tls.crt; 
    ssl_certificate_key /etc/nginx/certs/tls.key;

    ssl_session_timeout 5m;

    ssl_protocols TLSv1 TLSv1.1 TLSv1.2; 

    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE; 
    ssl_prefer_server_ciphers on;

    include /etc/nginx/conf.d/myserver-*.cfg;

    location / {
        root /usr/share/nginx/html;
    }
}

 

#nginx的压缩配置文件:myserver-gzip.cfg 

[root@master1 nginx-ssl-conf.d]# cat myserver-gzip.cfg
gzip on;
gzip_comp_level 5;
gzip_proxied     expired no-cache no-store private auth;
gzip_types text/plain text/css application/xml text/javascript;

#nginx的状态页配置文件myserver-status.cfg

[root@master1 nginx-ssl-conf.d]# cat myserver-status.cfg
location /status {
    stub_status on;
    access_log off;
}

创建配置文件对应的 Configmap

kubectl create configmap cm-nginx-ssl-conf --from-file=nginx-ssl-conf.d/

[root@master1 config]# kubectl get cm
NAME                DATA   AGE
cm-nginx-ssl-conf   3      53s
envoy-config        1      11d
kube-root-ca.crt    1      14d

创建引用Secret和configmap资源配置文件

#创建资源配置文件

[root@master1 config]# cat  storage-secret-nginx-ssl.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-nginx-ssl
  namespace: default
spec:
  volumes:
  - name: nginx-certs
    secret:
      secretName: secret-nginx-ssl
  - name: nginx-confs
    configMap:
      name: cm-nginx-ssl-conf
      optional: false
  containers:
  - image: registry.cn-beijing.aliyuncs.com/wangxiaochun/nginx:1.20.0
    name: nginx-ssl-server
    volumeMounts:
    - name: nginx-certs                 
      mountPath: /etc/nginx/certs/    #其保存cert文件自动命名为tls.crt,而保存private key文件的自动命名为tls.key
      readOnly: true
    - name: nginx-confs
      mountPath: /etc/nginx/conf.d/
      readOnly: true

kubectl apply -f storage-secret-nginx-ssl.yaml

 

[root@master1 config]# kubectl get pod
NAME                                        READY   STATUS    RESTARTS       AGE
controller-deployment-demo-5f884bb8-2ppvf   1/1     Running   5 (12h ago)    2d4h
controller-deployment-demo-5f884bb8-fscrl   1/1     Running   14 (12h ago)   8d
controller-deployment-demo-5f884bb8-rfsbv   1/1     Running   13 (12h ago)   8d
pod-nginx-ssl                               1/1     Running   0              4s

验证结果

#查看生成的证书文件,表示为关联时间戳目录下的两个双层软链接文件tls.crt和tls.key,保存证书的原始文件,而非base64格式

oot@master1 config]# kubectl exec -it pod-nginx-ssl -- ls -l /etc/nginx/certs/
total 0
lrwxrwxrwx 1 root root 14 May 24 19:42 tls.crt -> ..data/tls.crt
lrwxrwxrwx 1 root root 14 May 24 19:42 tls.key -> ..data/tls.key

 

#访问Pod

[root@master1 config]# kubectl get pod -o wide
NAME                                        READY   STATUS    RESTARTS       AGE     IP             NODE        NOMINATED NODE   READINESS GATES
controller-deployment-demo-5f884bb8-2ppvf   1/1     Running   5 (12h ago)    2d4h    10.244.1.192   node1.org   <none>           <none>
controller-deployment-demo-5f884bb8-fscrl   1/1     Running   14 (12h ago)   8d      10.244.1.193   node1.org   <none>           <none>
controller-deployment-demo-5f884bb8-rfsbv   1/1     Running   13 (12h ago)   8d      10.244.1.194   node1.org   <none>           <none>
pod-nginx-ssl                               1/1     Running   0              3m12s   10.244.2.195   node2.org   <none>           <none>

 

root@master1 config]# curl -I http://10.244.2.195 
HTTP/1.1 301 Moved Permanently
Server: nginx/1.20.0
Date: Sun, 24 May 2026 19:46:19 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive
Location: https://10.244.2.195/

 

[root@master1 config]# curl -Lkv http://10.244.2.195  
*   Trying 10.244.2.195:80...
* Connected to 10.244.2.195 (10.244.2.195) port 80 (#0)
> GET / HTTP/1.1
> Host: 10.244.2.195
> User-Agent: curl/7.76.1
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 301 Moved Permanently
< Server: nginx/1.20.0
< Date: Sun, 24 May 2026 19:46:48 GMT
< Content-Type: text/html
< Content-Length: 169
< Connection: keep-alive
< Location: https://10.244.2.195/
< 
* Ignoring the response-body
* Connection #0 to host 10.244.2.195 left intact
* Clear auth, redirects to port from 80 to 443Issue another request to this URL: 'https://10.244.2.195/'
*   Trying 10.244.2.195:443...
* Connected to 10.244.2.195 (10.244.2.195) port 443 (#1)
* ALPN, offering h2
* ALPN, offering http/1.1
*  CAfile: /etc/pki/tls/certs/ca-bundle.crt
* TLSv1.0 (OUT), TLS header, Certificate Status (22):
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS header, Finished (20):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS header, Finished (20):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server accepted to use http/1.1
* Server certificate:
*  subject: C=CN; ST=Guangzhou; L=Guangzhou; O=DevOps; CN=www.org
*  start date: May 24 19:21:50 2026 GMT
*  expire date: May 21 19:21:50 2036 GMT
*  issuer: C=CN; ST=Guangzhou; L=Guangzhou; O=DevOps; CN=www.org
*  SSL certificate verify result: self-signed certificate (18), continuing anyway.
* TLSv1.2 (OUT), TLS header, Unknown (23):
> GET / HTTP/1.1
> Host: 10.244.2.195
> User-Agent: curl/7.76.1
> Accept: */*
> 
* TLSv1.2 (IN), TLS header, Unknown (23):
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: nginx/1.20.0
< Date: Sun, 24 May 2026 19:46:48 GMT
< Content-Type: text/html
< Content-Length: 612
< Last-Modified: Tue, 20 Apr 2021 13:35:47 GMT
< Connection: keep-alive
< ETag: "607ed8b3-264"
< Accept-Ranges: bytes
< 
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
* Connection #1 to host 10.244.2.195 left intact

 

[root@master1 config]# curl -Lk http://10.244.2.195/status
Active connections: 2 
server accepts handled requests
 5 5 5 
Reading: 0 Writing: 1 Waiting: 1 

 

[root@master1 config]# curl -Lk http://10.244.2.195       
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

 

[root@master1 config]# curl -H"host: www.org" -k https://10.244.2.195  
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

 

[root@master1 config]# curl -H"host: www.org" -k https://10.244.2.195  -v
*   Trying 10.244.2.195:443...
* Connected to 10.244.2.195 (10.244.2.195) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
*  CAfile: /etc/pki/tls/certs/ca-bundle.crt
* TLSv1.0 (OUT), TLS header, Certificate Status (22):
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS header, Finished (20):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS header, Finished (20):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server accepted to use http/1.1
* Server certificate:
*  subject: C=CN; ST=Guangzhou; L=Guangzhou; O=DevOps; CN=www.org
*  start date: May 24 19:21:50 2026 GMT
*  expire date: May 21 19:21:50 2036 GMT
*  issuer: C=CN; ST=Guangzhou; L=Guangzhou; O=DevOps; CN=www.org
*  SSL certificate verify result: self-signed certificate (18), continuing anyway.
* TLSv1.2 (OUT), TLS header, Unknown (23):
> GET / HTTP/1.1
> Host: www.org
> User-Agent: curl/7.76.1
> Accept: */*
> 
* TLSv1.2 (IN), TLS header, Unknown (23):
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: nginx/1.20.0
< Date: Sun, 24 May 2026 19:51:37 GMT
< Content-Type: text/html
< Content-Length: 612
< Last-Modified: Tue, 20 Apr 2021 13:35:47 GMT
< Connection: keep-alive
< ETag: "607ed8b3-264"
< Accept-Ranges: bytes
< 
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
* Connection #0 to host 10.244.2.195 left intact

 

[root@master1 config]# kubectl get pod
NAME                                        READY   STATUS    RESTARTS       AGE
controller-deployment-demo-5f884bb8-2ppvf   1/1     Running   5 (12h ago)    2d4h
controller-deployment-demo-5f884bb8-fscrl   1/1     Running   14 (12h ago)   8d
controller-deployment-demo-5f884bb8-rfsbv   1/1     Running   13 (12h ago)   8d
pod-nginx-ssl                               1/1     Running   0              10m
[root@master1 config]# 
[root@master1 config]# kubectl exec -it pod-nginx-ssl -- bash
root@pod-nginx-ssl:/# ls /usr/share/nginx/html/
50x.html  index.html
root@pod-nginx-ssl:/# echo "heloword" > /usr/share/nginx/html/index.html 
root@pod-nginx-ssl:/# 

 

[root@master1 config]# curl -H"host: www.org" -k https://10.244.2.195  
heloword

 

更新证书
以上颁发的证书是有一定的有效期限的,在过期前需要提前更新证书
在线更新证书流程

  • 生成新的证书和私钥文件
  • 将生成的新的证书文件和私钥文件的全部内容分别先进行base64编码并删除空行
  • 利用编码后的内容分别替换以下命令kubectl edit secret secret-nginx-ssl 中原有的证书信息即可

证书的有效期一般为1年,到期前需要提前更新证书
范例: 证书更新

#重新颁发证书
生成新的key 用新的key申请自签名证书

[root@master1 config]# cd nginx-certs/
[root@master1 nginx-certs]# 
[root@master1 nginx-certs]# ls
www.org.crt  www.org.key

 

(umask 077; openssl genrsa -out ming.key 2048)

root@master1 nginx-certs]# ll
total 12
-rw------- 1 root root 1704 May 25 04:01 ming.key
-rw-r--r-- 1 root root 1298 May 25 03:21 www.org.crt
-rw------- 1 root root 1704 May 25 03:18 www.org.key

 

openssl req -new -x509 -key ming.key -out ming.crt -subj /C=CN/ST=Beijing/L=Beijing/O=SRE/CN=www.org -days 3650

root@master1 nginx-certs]# openssl req -new -x509 -key ming.key -out ming.crt -subj /C=CN/ST=Beijing/L=Beijing/O=SRE/CN=www.org -days 3650
[root@master1 nginx-certs]# ll
total 16
-rw-r--r-- 1 root root 1277 May 25 04:03 ming.crt
-rw------- 1 root root 1704 May 25 04:01 ming.key
-rw-r--r-- 1 root root 1298 May 25 03:21 www.org.crt
-rw------- 1 root root 1704 May 25 03:18 www.org.key

 

找个业务低峰期时间 更新证书文件

#删除旧证书配置 创建新证书配置

kubectl delete secrets secret-nginx-ssl && kubectl create secret tls secret-nginx-ssl --cert=./ming.crt --key=./ming.key

 

证书信息没有更新

#nginx不支持热加载,需要手动加载

[root@master1 nginx-certs]# curl -H"host: www.org" -k https://10.244.2.195  -v
*   Trying 10.244.2.195:443...
* Connected to 10.244.2.195 (10.244.2.195) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
*  CAfile: /etc/pki/tls/certs/ca-bundle.crt
* TLSv1.0 (OUT), TLS header, Certificate Status (22):
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS header, Finished (20):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS header, Finished (20):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server accepted to use http/1.1
* Server certificate:
*  subject: C=CN; ST=Guangzhou; L=Guangzhou; O=DevOps; CN=www.org
*  start date: May 24 19:21:50 2026 GMT
*  expire date: May 21 19:21:50 2036 GMT
*  issuer: C=CN; ST=Guangzhou; L=Guangzhou; O=DevOps; CN=www.org
*  SSL certificate verify result: self-signed certificate (18), continuing anyway.
* TLSv1.2 (OUT), TLS header, Unknown (23):
> GET / HTTP/1.1
> Host: www.org
> User-Agent: curl/7.76.1
> Accept: */*
> 
* TLSv1.2 (IN), TLS header, Unknown (23):
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: nginx/1.20.0
< Date: Sun, 24 May 2026 20:06:43 GMT
< Content-Type: text/html
< Content-Length: 9
< Last-Modified: Sun, 24 May 2026 19:55:19 GMT
< Connection: keep-alive
< ETag: "6a1357a7-9"
< Accept-Ranges: bytes
< 
heloword
* Connection #0 to host 10.244.2.195 left intact
[root@master1 nginx-certs]# 

 

进去pod重启nginx服务

root@master1 nginx-certs]# kubectl exec -it pod-nginx-ssl -- bash
root@pod-nginx-ssl:/# nginx -s reload
2026/05/24 20:08:03 [notice] 44#44: signal process started

 

更新了证书信息

[root@master1 nginx-certs]# curl -H"host: www.org" -k https://10.244.2.195  -v
*   Trying 10.244.2.195:443...
* Connected to 10.244.2.195 (10.244.2.195) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
*  CAfile: /etc/pki/tls/certs/ca-bundle.crt
* TLSv1.0 (OUT), TLS header, Certificate Status (22):
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS header, Finished (20):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS header, Finished (20):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server accepted to use http/1.1
* Server certificate:
*  subject: C=CN; ST=Beijing; L=Beijing; O=SRE; CN=www.org
*  start date: May 24 20:03:16 2026 GMT
*  expire date: May 21 20:03:16 2036 GMT
*  issuer: C=CN; ST=Beijing; L=Beijing; O=SRE; CN=www.org
*  SSL certificate verify result: self-signed certificate (18), continuing anyway.
* TLSv1.2 (OUT), TLS header, Unknown (23):
> GET / HTTP/1.1
> Host: www.org
> User-Agent: curl/7.76.1
> Accept: */*
> 
* TLSv1.2 (IN), TLS header, Unknown (23):
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: nginx/1.20.0
< Date: Sun, 24 May 2026 20:08:24 GMT
< Content-Type: text/html
< Content-Length: 9
< Last-Modified: Sun, 24 May 2026 19:55:19 GMT
< Connection: keep-alive
< ETag: "6a1357a7-9"
< Accept-Ranges: bytes
< 
heloword
* Connection #0 to host 10.244.2.195 left intact

 

 

[root@master1 nginx-certs]# kubectl get pod -o wide
NAME                                        READY   STATUS    RESTARTS       AGE    IP             NODE        NOMINATED NODE   READINESS GATES
controller-deployment-demo-5f884bb8-2ppvf   1/1     Running   5 (12h ago)    2d5h   10.244.1.192   node1.org   <none>           <none>
controller-deployment-demo-5f884bb8-fscrl   1/1     Running   14 (12h ago)   8d     10.244.1.193   node1.org   <none>           <none>
controller-deployment-demo-5f884bb8-rfsbv   1/1     Running   13 (12h ago)   8d     10.244.1.194   node1.org   <none>           <none>
pod-nginx-ssl                               1/1     Running   0              28m    10.244.2.195   node2.org   <none>           <none>

 

#集群外验证证书是否生效

echo "10.244.2.195 www.org" >> /etc/hosts

 

 

[root@master1 nginx-certs]# openssl s_client www.org:443
Connecting to 10.244.2.195
CONNECTED(00000003)
depth=0 C=CN, ST=Beijing, L=Beijing, O=SRE, CN=www.org
verify error:num=18:self-signed certificate
verify return:1
depth=0 C=CN, ST=Beijing, L=Beijing, O=SRE, CN=www.org
verify return:1
---
Certificate chain
 0 s:C=CN, ST=Beijing, L=Beijing, O=SRE, CN=www.org
   i:C=CN, ST=Beijing, L=Beijing, O=SRE, CN=www.org
   a:PKEY: RSA, 2048 (bit); sigalg: sha256WithRSAEncryption
   v:NotBefore: May 24 20:03:16 2026 GMT; NotAfter: May 21 20:03:16 2036 GMT
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIDgzCCAmugAwIBAgIUAl18QMG527hcAtjD34F1C45KS1UwDQYJKoZIhvcNAQEL
BQAwUTELMAkGA1UEBhMCQ04xEDAOBgNVBAgMB0JlaWppbmcxEDAOBgNVBAcMB0Jl
aWppbmcxDDAKBgNVBAoMA1NSRTEQMA4GA1UEAwwHd3d3Lm9yZzAeFw0yNjA1MjQy
MDAzMTZaFw0zNjA1MjEyMDAzMTZaMFExCzAJBgNVBAYTAkNOMRAwDgYDVQQIDAdC
ZWlqaW5nMRAwDgYDVQQHDAdCZWlqaW5nMQwwCgYDVQQKDANTUkUxEDAOBgNVBAMM
B3d3dy5vcmcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDIx18qEbZG
5YgNtWXUXIwCFcH478dqR4YYZyAeP6NCn3VAvRgc1qzuz8r572WRFF9x1pfXjJc0
zJBgMyrndUdfTyQ5wmMW7aQlIcrr4hE20N8San4PWJ/dWGmTLqQisaygvGn123JU
1oeBSYKh1d1MUrmVTJqYIxl6WV6FwTkneDJIb2CIl70ud7dqbyHa55tLK5wfCpZI
BILBPwl886XvLWTxFtfPfh0MIh5EX4XMb9Qx8+BQ2ej5zgtnqltwMkHk7odnwrM/
O0tqy3NguM9stz2cvfX//kjd36PjBAftN36guxKIcZSwMCzWzU15mm8HXoc+js98
RV+fBxthyH49AgMBAAGjUzBRMB0GA1UdDgQWBBSwp29J/yhh6u+J2gdI/RI3TT0L
lTAfBgNVHSMEGDAWgBSwp29J/yhh6u+J2gdI/RI3TT0LlTAPBgNVHRMBAf8EBTAD
AQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBKpAyVg3bjBnddbP3dVyR0IT7Ldef36+tu
8yJtBwRXGytbhthQlp7lIKrxEwlPA1eYOG6F60jKpfxloy/ANJstaNYa4h3t8Mhl
1OvnosYy2PXupKXv0uEK27Sh72QV75WvP5ny4eCQwx8EPYMoUc9gzDxpaaPWGtYs
A76tgFgmMDtMLigBMk0LitgU7kj1TB4FOyEf7iui2wi50R9yxN27bfG2vQyToWnB
W1FhQqEOcm9cO3ch8RDRLMTKtfREyztc/XObWdBtQVWkV/LtUW7xd8zuOuRM3P8I
wYoPywW3R1b/iFfq9TBuBmpVW7+6pqSrFjLxpYi/awqGZ8V1Dtyp
-----END CERTIFICATE-----
subject=C=CN, ST=Beijing, L=Beijing, O=SRE, CN=www.org
issuer=C=CN, ST=Beijing, L=Beijing, O=SRE, CN=www.org
---
No client certificate CA names sent
Peer signing digest: SHA256
Peer signature type: rsa_pss_rsae_sha256
Peer Temp Key: X25519, 253 bits
---
SSL handshake has read 1564 bytes and written 414 bytes
Verification error: self-signed certificate
---
New, TLSv1.2, Cipher is ECDHE-RSA-AES128-GCM-SHA256
Protocol: TLSv1.2
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-RSA-AES128-GCM-SHA256
    Session-ID: 163CB842E6D6A0C35564F4506B121C1498FA08A429A059F8DC473C6B9C003B98
    Session-ID-ctx: 
    Master-Key: 13E03915AC9C8953EEC2CBD5C46B4E404456A958F4AE680F585210D5DC2F945BEC6A7E30E5AADCA99472F5C00F0C5F9C
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    TLS session ticket lifetime hint: 300 (seconds)
    TLS session ticket:
    0000 - 73 de d1 ed e7 2f 73 bb-5c f5 0d ca 30 76 b5 76   s..../s.\...0v.v
    0010 - 97 31 7e 43 c9 8a 7f 3e-19 2e 53 8d c2 56 35 d8   .1~C...>..S..V5.
    0020 - 37 16 67 c1 45 95 c8 a4-0a 5f 6c 5b 9a 6d 1e 01   7.g.E...._l[.m..
    0030 - eb 66 04 0e 1c d0 a3 83-3e c5 08 85 c2 c3 42 68   .f......>.....Bh
    0040 - 05 ec 31 91 e6 1f 13 38-05 68 d8 a2 d9 a6 4d 85   ..1....8.h....M.
    0050 - c8 f0 bc f4 61 8e 1b 83-3b 73 bb 1e 19 07 46 4b   ....a...;s....FK
    0060 - 77 ca 93 38 da e2 92 14-e9 ad 82 90 bb 2d 3a 5d   w..8.........-:]
    0070 - 34 78 e3 81 83 66 18 1e-e4 48 7d 23 25 b1 c7 f3   4x...f...H}#%...
    0080 - 58 92 81 f2 e4 51 38 11-a7 61 6b df 25 55 65 41   X....Q8..ak.%UeA
    0090 - 7d 1c 65 54 03 17 75 30-d0 f9 2c c6 08 cd 68 85   }.eT..u0..,...h.
    00a0 - 68 ac b1 bd 5a d9 13 19-08 77 b9 8f 81 ad 18 2e   h...Z....w......
    00b0 - bf f2 55 48 3c 2e 8d 1e-b1 72 bf 1e 09 43 32 86   ..UH<....r...C2.

    Start Time: 1779653587
    Timeout   : 7200 (sec)
    Verify return code: 18 (self-signed certificate)
    Extended master secret: yes
---

 

 

Docker-registry 案例

Secret 实现 Docker 私有仓库的镜像访问说明

有时Docker的仓库是私有的,如果想下载镜像,就需要在下载镜像的主机上登录仓库并认证后才能实现
但是在Kubernetes集群使用私有仓库镜像就比较繁琐,因为运行Pod 的宿主机并不固定,如果在每个worker节点登录验证显然是不方便的

dockercfg及dockerconfigjson类型的Secret 适用于实现让kubelet从私有Image Registry中下载容器镜像

其引用定义在pod.spec.imagePullSecrets字段上的列表,即支持多个docker-registry类型的Secret,从上
至下逐个进行匹配
也支持pod.spec.serviceAcountName引用sa,再在serviceAccount.imagePullSecrets间接引用
Docker-registry的secret
创建此种secret 可以通过下面方式实现

 

方法1: 通过命令创建

kubectl create secret docker-registry KEYNAME --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --dockerpassword=DOCKER_PASSWORD --docker-email=EMAIL 

 

方式二: 通过docker认证文件创建

#先登录并认证到目标仓库server上,认证凭据自动保存在~/.docker/config.json文件中
docker login --username=DOCKER_USER DOCKER_REGISTRY_SERVER


#基于config.json文件生成secret
kubectl create secret docker-registry KEYNAME --fromfile=.dockerconfigjson=path/to/.docker/config.json
kubectl create secret generic KEYNAME --type='kubernetes.io/dockerconfigjson' --from-file=.dockerconfigjson=/root/.docker/config.json

#示例:
kubectl create secret docker-registry my-secret --fromfile=.dockerconfigjson=path/to/.docker/config.json
kubectl create secret generic dockerharbor-auth --type='kubernetes.io/dockerconfigjson' --from-file=.dockerconfigjson=/root/.docker/config.json

安装并创建Harbor的私有仓库和项

harbor服务器新建项目 放镜像

640e4f5eacd426cc44e12fa5999819b2

 

#修改所有集群节点的Docker配置支持私有仓库

[root@master1 test]# cat /etc/docker/daemon.json 
{
   "registry-mirrors": [
       "https://docker.m.daocloud.io",
       "https://docker.1panel.live",
       "https://docker.1ms.run",
       "https://docker.xuanyuan.me"
  ],
   "insecure-registries": ["harbor.ming.org"]
}
[root@master1 test]# 

systemctl restart docker

#拉取镜像

docker pull wangxiaochun/pod-test:v0.1

docker tag wangxiaochun/pod-test:v0.1 harbor.ming.org/image2/pod-test:v0.1

#登录

docker login -u admin -p 123456 harbor.ming.org 

[root@master1 test]# docker login -u admin -p 123456 harbor.ming.org
WARNING! Using --password via the CLI is insecure. Use --password-stdin.

WARNING! Your credentials are stored unencrypted in '/root/.docker/config.json'.
Configure a credential helper to remove this warning. See
https://docs.docker.com/go/credential-store/

Login Succeeded

 

#上传镜像到私有仓库

docker push harbor.ming.org/image2/pod-test:v0.1 

 

[root@master1 test]# docker push harbor.ming.org/image2/pod-test:v0.1 
The push refers to repository [harbor.ming.org/image2/pod-test]
6e830a323b2a: Pushed 
c9b1b535fdd9: Pushed 
3cbce035cd7c: Pushed 
b83463f478a5: Pushed 
34b1f286d5e2: Pushed 
74e68c74e8d9: Pushed 
v0.1: digest: sha256:54402cda2ef15f45e4aafe98a5e56d4de076e3d4100c2a1bf1b780c787372fed size: 1575

查看镜像

2f40dafd1b4fd467dcbd15d538fb2a46

 

通过 Docker 认证文件实现
注意: harbor.ming.org 服务器的域名解析要在worker节点上的DNS或/etc/hosts文件中实现,而无需在集群内的coreDNS实现

[root@master1 config]# cat /etc/hosts 
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.3.60 kubeapi.org kubeapi
192.168.3.60 master1.org master1
192.168.3.61 master2.org master2
192.168.3.62 master3.org master3
192.168.3.63 node1.org node1
192.168.3.64 node2.org node2
192.168.3.65 node3.org node3
192.168.3.66 ha1.org ha1
192.168.3.67 ha2.org ha2
192.168.3.10 www.ming.org test1.ming.org test2.ming.org harbor.ming.org

 

如果是自签名的HTTPS证书,需要先下载Habor的服务器证书到文件中

 

image

 

 导出

image

 https使用自签名证书 每个node节点都把证书写配置 做证书信任

cat harbor.ming.org.crt >> /etc/ssl/certs/ca-certificates.crt

 systemctl restart docker

 


范例: 通过docker认证文件实现Harbor私有仓库访问

 

拉取私有仓库镜像失败 认证失败 

 

[root@master1 test]# docker pull harbor.ming.org/image2/pod-test:v0.1
Error response from daemon: failed to resolve reference "harbor.ming.org/image2/pod-test:v0.1": pull access denied, repository does not exist or may require authorization: authorization failed: no basic auth credentials

 

登录Harbor仓库生成dockerconfig文件

docker login harbor.ming.org -u admin -p 123456

 

 

 

[root@master1 config]# cat storage-secret-docker-registry-harbor-dockerconfig.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment-secret-docker-registry-harbor-dockerconfig
spec:
  replicas: 3
  selector:
    matchLabels:
      app: pod-test-secret-docker-registry-harbor-dockerconfig
  template:
    metadata:
      labels:
        app: pod-test-secret-docker-registry-harbor-dockerconfig
    spec:
      containers:
      - name: pod-test-harbor-docker-registry-secret
        image: harbor.ming.org/image2/pod-test:v0.1
        ports:
          - containerPort: 80
      #imagePullSecrets:
      #  - name: secret-docker-registry-harbor-dockerconfig

kubectl apply -f storage-secret-docker-registry-harbor-dockerconfig.yaml 

[root@master1 config]# kubectl get pod -o wide
NAME                                                              READY   STATUS             RESTARTS   AGE    IP             NODE        NOMINATED NODE   READINESS GATES
deployment-secret-docker-registry-harbor-dockerconfig-5b668j2nf   0/1     ImagePullBackOff   0          2m     10.244.2.122   node2.org   <none>           <none>
deployment-secret-docker-registry-harbor-dockerconfig-5b66pwm7h   0/1     ImagePullBackOff   0          119s   10.244.2.123   node2.org   <none>           <none>
deployment-secret-docker-registry-harbor-dockerconfig-5b66qjvgw   0/1     ImagePullBackOff   0          119s   10.244.1.127   node1.org   <none>           <none>

 

 

没有密钥 认证失败 kubectl describe pod deployment-secret-docker-registry-harbor-dockerconfig-5b66qjvgw

  Warning  Failed     6s                kubelet            spec.containers{pod-test-harbor-docker-registry-secret}: Failed to pull image "harbor.ming.org/image2/pod-test:v0.1": Error response from daemon: failed to resolve reference "harbor.ming.org/image2/pod-test:v0.1": pull access denied, repository does not exist or may require authorization: authorization failed: no basic auth credentials
[root@master1 config]# 

 

命令行创建Secret

kubectl create secret docker-registry secret-docker-registry-harbor-dockerconfig --docker-server=harbor.ming.org --docker-username=admin --docker-password=123456

[root@master1 config]# kubectl get secrets 

NAME                                         TYPE                             DATA   AGE
secret-docker-registry-harbor-dockerconfig   kubernetes.io/dockerconfigjson   1      4m
[root@master1 config]# 

 

 

[root@master1 config]# 
[root@master1 config]# kubectl get  secret secret-docker-registry-harbor-dockerconfig -o yaml
apiVersion: v1
data:
  .dockerconfigjson: eyJhdXRocyI6eyJoYXJib3IubWluZy5vcmciOnsidXNlcm5hbWUiOiJhZG1pbiIsInBhc3N3b3JkIjoiMTIzNDU2IiwiYXV0aCI6IllXUnRhVzQ2TVRJek5EVTIifX19
kind: Secret
metadata:
  creationTimestamp: "2026-05-30T19:11:29Z"
  name: secret-docker-registry-harbor-dockerconfig
  namespace: default
  resourceVersion: "709630"
  uid: 39bb69b2-46b0-47cf-8ec3-008c25bce398
type: kubernetes.io/dockerconfigjson

 

 

kubectl create secret docker-registry secret-docker-registry-harbor-dockerconfig --docker-server=harbor.ming.org --docker-username=admin --docker-password=123456 --dry-run=client -o yaml > secret-docker-registry-harbor-dockerconfig.yaml

[root@master1 config]# cat secret-docker-registry-harbor-dockerconfig.yaml    
apiVersion: v1
data:
  .dockerconfigjson: eyJhdXRocyI6eyJoYXJib3IubWluZy5vcmciOnsidXNlcm5hbWUiOiJhZG1pbiIsInBhc3N3b3JkIjoiMTIzNDU2IiwiYXV0aCI6IllXUnRhVzQ2TVRJek5EVTIifX19
kind: Secret
metadata:
  name: secret-docker-registry-harbor-dockerconfig
type: kubernetes.io/dockerconfigjson

 

#查看data内容

[root@master1 config]# echo "eyJhdXRocyI6eyJoYXJib3IubWluZy5vcmciOnsidXNlcm5hbWUiOiJhZG1pbiIsInBhc3N3b3JkIjoiMTIzNDU2IiwiYXV0aCI6IllXUnRhVzQ2TVRJek5EVTIifX19"|base64 -d
{"auths":{"harbor.ming.org":{"username":"admin","password":"123456","auth":"YWRtaW46MTIzNDU2"}}}[root@master1 config]# 

 

#准备清单文件

从私有仓库拉镜像

[root@master1 config]# cat storage-secret-docker-registry-harbor-dockerconfig.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment-secret-docker-registry-harbor-dockerconfig
spec:
  replicas: 3
  selector:
    matchLabels:
      app: pod-test-secret-docker-registry-harbor-dockerconfig
  template:
    metadata:
      labels:
        app: pod-test-secret-docker-registry-harbor-dockerconfig
    spec:
      containers:
      - name: pod-test-harbor-docker-registry-secret
        image: harbor.ming.org/image2/pod-test:v0.1
        ports:
          - containerPort: 80
      imagePullSecrets:
        - name: secret-docker-registry-harbor-dockerconfig

 

kubectl apply -f storage-secret-docker-registry-harbor-dockerconfig.yaml

root@master1 config]# kubectl get pod -o wide
NAME                                                              READY   STATUS    RESTARTS   AGE   IP             NODE        NOMINATED NODE   READINESS GATES
deployment-secret-docker-registry-harbor-dockerconfig-854b9zcb7   1/1     Running   0          24s   10.244.1.128   node1.org   <none>           <none>
deployment-secret-docker-registry-harbor-dockerconfig-854bfz6rq   1/1     Running   0          27s   10.244.2.124   node2.org   <none>           <none>
deployment-secret-docker-registry-harbor-dockerconfig-854bvgpxs   1/1     Running   0          22s   10.244.2.125   node2.org   <none>           <none>
[root@master1 config]# 

#在上面pod运行的节点上仍然无法用docker拉取镜像

这个是docker认证和pod无关,pod在清单文件指定docker认证密钥就可以拉取

[root@node1 ~]# docker pull harbor.ming.org/image2/pod-test:v0.1
Error response from daemon: failed to resolve reference "harbor.ming.org/image2/pod-test:v0.1": pull access denied, repository does not exist or may require authorization: authorization failed: no basic auth credentials

解决node节点

#登录Harbor仓库生成dockerconfig文件

docker login harbor.ming.org -u admin -p 123456

[root@node1 ~]# docker login harbor.ming.org -u admin -p 123456
WARNING! Using --password via the CLI is insecure. Use --password-stdin.

WARNING! Your credentials are stored unencrypted in '/root/.docker/config.json'.
Configure a credential helper to remove this warning. See
https://docs.docker.com/go/credential-store/

Login Succeeded

 

root@node1 ~]# 
[root@node1 ~]# cat .docker/config.json 
{
        "auths": {
                "harbor.ming.org": {
                        "auth": "YWRtaW46MTIzNDU2"
                }
        }
}[root@node1 ~]# 

node节点再次拉取 可以拉取镜像

[root@node1 ~]# docker pull harbor.ming.org/image2/pod-test:v0.1
v0.1: Pulling from image2/pod-test
Digest: sha256:54402cda2ef15f45e4aafe98a5e56d4de076e3d4100c2a1bf1b780c787372fed
Status: Image is up to date for harbor.ming.org/image2/pod-test:v0.1
harbor.ming.org/image2/pod-test:v0.1

 

也可以指定 这个文件 为认证密钥 cat .docker/config.json 

[root@master1 config]# docker login harbor.ming.org -u admin -p 123456
WARNING! Using --password via the CLI is insecure. Use --password-stdin.

WARNING! Your credentials are stored unencrypted in '/root/.docker/config.json'.
Configure a credential helper to remove this warning. See
https://docs.docker.com/go/credential-store/

Login Succeeded

[root@master1 config]# cat /root/.docker/config.json 
{
        "auths": {
                "harbor.ming.org": {
                        "auth": "YWRtaW46MTIzNDU2"
                }
        }
}

 

 

#基于dockerconfig生成secret

kubectl create secret docker-registry secret-docker-registry-harbor-dockerconfig --from-file=.dockerconfigjson=/root/.docker/config.json

kubectl apply -f storage-secret-docker-registry-harbor-dockerconfig.yaml

[root@master1 config]# kubectl get pod -o wide
NAME                                                              READY   STATUS    RESTARTS   AGE   IP             NODE        NOMINATED NODE   READINESS GATES
deployment-secret-docker-registry-harbor-dockerconfig-854b4rfd7   1/1     Running   0          5s    10.244.2.126   node2.org   <none>           <none>
deployment-secret-docker-registry-harbor-dockerconfig-854bgchlm   1/1     Running   0          5s    10.244.1.129   node1.org   <none>           <none>
deployment-secret-docker-registry-harbor-dockerconfig-854blvrqn   1/1     Running   0          5s    10.244.2.127   node2.org   <none>           <none>
[root@master1 config]# 

 

posted @ 2026-05-25 04:56  minger_lcm  阅读(28)  评论(0)    收藏  举报