解决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 单独配置

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

相关推荐
艾伦_耶格宇10 小时前
【DOCKER容器实战】-5 Docker容器镜像的构建
运维·docker·容器
分布式存储与RustFS11 小时前
RustFS 该跟 stable 还是 nightly?两条版本线的分工、风险与回退,一张表说清
运维·云原生·开源·对象存储·分布式存储·s3·性能基准
ggaofeng14 小时前
k8s中的dns
云原生·容器·kubernetes
我不会起名字3221 天前
K8s Ingress 返回 502 但后端日志正常:4 类上游断连与排查链
kubernetes·k8s·ingress·502·keepalive
姜鱼问生1 天前
每次开机手动检查 6 样东西?我写了个 2 秒自检脚本
运维·网络·nginx·docker·容器
wangqiaowq1 天前
PostgresSQL server Docker 安装部署
运维·docker·容器
程序员阿明1 天前
docker搭建视频流服务go2rtc,webRTC
docker·容器·webrtc
JavaPub-rodert1 天前
Docker 容器为什么 stop 半天停不下来?讲透 PID 1、SIGTERM、SIGKILL、僵尸进程与 tini
运维·docker·容器
我不会起名字3221 天前
Pod 一直 Pending:调度器 5 类失败原因与 kubectl describe 的正确读法
云原生·kubernetes·调度·排查
我不会起名字3221 天前
K8s 服务 DNS 解析偶发 5 秒超时:conntrack 与 ndots 的 3 个坑
kubernetes·k8s·dns·conntrack·coredns