解决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. 确认镜像仓库的认证信息正确,并确保网络连接正常。

相关推荐
能不能别报错9 小时前
K8s学习笔记(十六) 探针(Probe)
笔记·学习·kubernetes
能不能别报错10 小时前
K8s学习笔记(十四) DaemonSet
笔记·学习·kubernetes
火星MARK12 小时前
k8s面试题
容器·面试·kubernetes
Serverless社区13 小时前
阿里云函数计算 AgentRun 全新发布,构筑智能体时代的基础设施
阿里云·云原生·serverless·函数计算
赵渝强老师13 小时前
【赵渝强老师】Docker容器的资源管理机制
linux·docker·容器·kubernetes
能不能别报错15 小时前
K8s学习笔记(十五) pause容器与init容器
笔记·学习·kubernetes
稚辉君.MCA_P8_Java15 小时前
kafka解决了什么问题?mmap 和sendfile
java·spring boot·分布式·kafka·kubernetes
乄bluefox15 小时前
保姆级docker部署nacos集群
java·docker·容器
每天进步一点_JL15 小时前
Docker 是什么?
后端·docker·容器
一叶飘零_sweeeet16 小时前
从 0 到 1 掌控云原生部署:Java 项目的 Docker 容器化与 K8s 集群实战指南
docker·云原生·kubernetes·项目部署