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引用

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

下面案例实现一个基于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服务器新建项目 放镜像

#修改所有集群节点的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
查看镜像

通过 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的服务器证书到文件中

导出

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]#
浙公网安备 33010602011771号