解决k8s拉取私有镜像401 Unauthorized 问题

拉取镜像时未指定账户和密码通常是因为需要访问的镜像仓库启用了认证,但 Kubernetes 默认配置中未提供访问凭据。要解决此问题,可以按照以下步骤配置镜像仓库的认证信息:


1. 创建 Kubernetes Secret

为镜像仓库配置访问凭据,使用 kubectl 创建一个类型为 docker-registry 的 Secret。

bash 复制代码
kubectl create secret -n kubesphere-devops-system docker-registry my-registry-secret \
  --docker-server=registry.flow.cn \
  --docker-username=<your-username> \
  --docker-password=<your-password> \
  --docker-email=<your-email>
  • 参数说明
    • --docker-server:镜像仓库的地址,例如 registry.flow.cn
    • --docker-username:登录仓库的用户名。
    • --docker-password:登录仓库的密码。
    • --docker-email:邮箱地址(可以是任意值,不强制验证)。

2. Pod 单独配置

修改 CronJobspec.template.spec 配置,添加 imagePullSecrets 字段,指定刚创建的 Secret 名称。

更新后的 CronJob 配置如下:

yaml 复制代码
kind: CronJob
apiVersion: batch/v1
metadata:
  name: devops
  namespace: kubesphere-devops-system
  labels:
    app: devops-pipelinerun-gcjobs
    app.kubernetes.io/managed-by: Helm
  annotations:
    meta.helm.sh/release-name: devops
    meta.helm.sh/release-namespace: kubesphere-devops-system
spec:
  schedule: "0/2 * * * *"
  startingDeadlineSeconds: 4000
  concurrencyPolicy: Forbid
  suspend: false
  jobTemplate:
    spec:
      template:
        metadata:
          labels:
            app: devops
            release: devops
        spec:
          containers:
            - name: pipeline-run-gc
              image: 'registry.flow.cn/kubesphereio/devops-tools:ks-v3.4.1'
              command:
                - ks
                - pip
                - gc
              imagePullPolicy: Always
          restartPolicy: Never
          terminationGracePeriodSeconds: 30
          dnsPolicy: ClusterFirst
          serviceAccountName: devops
          serviceAccount: devops
          imagePullSecrets:  # 添加这一部分
            - name: my-registry-secret
  successfulJobsHistoryLimit: 3
  failedJobsHistoryLimit: 1

验证配置

  1. 检查 Secret

    bash 复制代码
    kubectl get secret -n kubesphere-devops-system

    确保 my-registry-secret 已成功创建。

  2. 检查 CronJob 运行状态

    bash 复制代码
    kubectl get cronjob -n kubesphere-devops-system
  3. 查看 Pod 拉取镜像日志

    如果镜像拉取失败,检查 Pod 事件:

    bash 复制代码
    kubectl describe pod <pod-name> -n kubesphere-devops-system xxxx

注意事项

  • 镜像仓库地址 :确保仓库地址(docker-server)与 image 字段中配置的一致。
  • 命名空间 :Secret 和 CronJob 必须在同一命名空间下(如 kubesphere-devops-system)。
  • 权限问题:确保镜像仓库用户具备对目标镜像的拉取权限。

完成上述配置后,CronJob 应能够正确拉取镜像并运行。

3. ServiceAccount 配置: 如果多个 Pod 使用相同的 serviceAccount,可以为 ServiceAccount 配置 Secret

确认需要使用的 ServiceAccount

查看当前 Pod 使用的 ServiceAccount:

bash 复制代码
kubectl get pods <pod-name>  -n <namespace> -o jsonpath='{.spec.serviceAccountName}'

我我们假设返回的是 openebs-maya-operator

如果 kubectl get pods 命令返回的 serviceAccountName 是空的,说明 Pod 没有显式绑定任何 ServiceAccount ,它会默认使用 default ServiceAccount 。在这种情况下,你可以为 default ServiceAccount 配置 imagePullSecrets,或者直接为该 Pod 显式指定一个 ServiceAccount。


解决方案

方案 1:为默认 ServiceAccount 配置 imagePullSecrets

默认情况下,每个命名空间都包含一个 default ServiceAccount。如果 Pod 未显式指定 serviceAccountName,它会使用这个默认账户。

  1. 为命名空间中的 default ServiceAccount 添加 imagePullSecrets

    bash 复制代码
    kubectl patch serviceaccount default \
      -n <namespace>\
      -p '{"imagePullSecrets": [{"name": "my-registry-secret"}]}'
  2. 验证配置:

bash 复制代码
 kubectl describe serviceaccount default -n <namespace>

确保输出中有以下内容:

bash 复制代码
Image pull secrets: my-registry-secret

方案 2:显式为 Pod 指定 ServiceAccount

为 Pod 指定一个具有正确配置的 ServiceAccount,比如 openebs-maya-operator

  1. 编辑 Pod 的 YAML 文件,将 serviceAccountName 字段显式指定:

    yaml 复制代码
    spec:
      serviceAccountName: openebs-maya-operator
  2. 如果没有现成的 ServiceAccount,可以创建一个新的并配置 imagePullSecrets

bash 复制代码
kubectl create serviceaccount openebs-maya-operator -n <namespace>
bash 复制代码
kubectl patch serviceaccount openebs-maya-operator \
-n <namespace>\
-p '{"imagePullSecrets": [{"name": "my-registry-secret"}]}'
  1. 删除并重新创建 Pod 以应用更改:

    bash 复制代码
    kubectl delete pod <pod-name> -n <namespace>

方案 3:临时修改 Pod 配置

如果你只想快速测试,可以直接在 Pod 配置中添加 imagePullSecrets(不过这不是最佳实践)。

编辑 Pod 的 YAML 文件,添加以下内容:

yaml 复制代码
spec:
  imagePullSecrets:
    - name: my-registry-secret

重新应用修改后的 Pod 配置:

bash 复制代码
kubectl replace -f pod.yaml

验证步骤

无论采用哪种方案,确保最终拉取镜像成功:

  1. 查看 Pod 状态:

    bash 复制代码
    kubectl get pods -n <namespace>
  2. 如果仍有错误,请检查具体日志:

    bash 复制代码
    kubectl describe pod <pod-name> -n <namespace>
  3. 确认镜像仓库的认证信息正确,并确保网络连接正常。

相关推荐
运维&陈同学16 分钟前
【Beats01】企业级日志分析系统ELK之Metricbeat与Heartbeat 监控
运维·elk·elasticsearch·云原生·kibana·heartbeat·metricbeat
AKA小徐1 小时前
Debian12使用RKE2离线部署3master2node三主两从的k8s集群详细教程
kubernetes·rancher·rke2
老大白菜8 小时前
Windows 11 安装 Dify 完整指南 非docker环境
windows·docker·容器
tntlbb12 小时前
Ubuntu20.4 VPN+Docker代理配置
运维·ubuntu·docker·容器
Gabriel_liao12 小时前
Docker安装Neo4j
docker·容器·neo4j
有一个好名字13 小时前
zookeeper分布式锁模拟12306买票
分布式·zookeeper·云原生
Anna_Tong15 小时前
云原生大数据计算服务 MaxCompute 是什么?
大数据·阿里云·云原生·maxcompute·odps
豆豆豆豆变16 小时前
Docker轻量级可视化工具Portainer
docker·容器·自动化运维
花晓木16 小时前
k8s etcd 数据损坏处理方式
容器·kubernetes·etcd
运维&陈同学16 小时前
【模块一】kubernetes容器编排进阶实战之基于velero及minio实现etcd数据备份与恢复
数据库·后端·云原生·容器·kubernetes·etcd·minio·velero