所有分类
  • 所有分类
  • 未分类

K8S–解决访问Harbor私有仓库无权限的问题(401 Unauthorized)

简介

本文解决K8S访问Harbor私有仓库无权限的问题:401 Unauthorized。

问题复现

用Harbor部署了私有仓库,将镜像推送上去。指定私有仓库的镜像创建Pods时报错了,关键日志是:401 Unauthorized

这个日志是Pods的日志,可以在dashboard上或者通过kubectl describe pod 查看。

原因分析

需要访问权限。

解决方案

需要在 Kubenetes 配置 Secret 访问 Harbor私有仓库。

1.登录并获取密钥

1.登录

docker login 192.168.5.193:15001

结果 

2. 查看密钥

cat ~/.docker/config.json

结果

2.创建Harbor机器人账号

Harbor 上创建机器人账号,账号名称与将要创建的 Secret 名称一致。

3.创建Secret

1.生成密钥的base64

cat ~/.docker/config.json | base64 -w 0

结果

2.创建Secret

方式1:yaml 文件创建

创建 harbor-secret.yaml 文件,其中 .dockerconfigjson 的值为上边获得的base64值:

apiVersion: v1
kind: Secret
metadata:
  name: harbor-secret
  namespace: java-app
type: kubernetes.io/dockerconfigjson
data:
  .dockerconfigjson: ewoJImF1dGhzIjogewoJCSIxOTIuMTY4LjUuMTkzOjE1MDAxIjogewoJCQkiYXV0aCI6ICJZV1J0YVc0NlNHRnlZbTl5TVRJek5EVT0iCgkJfQoJfQp9Cg==

注意:这里是只有java-app命名空间的应用能用这个secret。

执行:

kubectl apply -f harbor-secret.yaml

结果

方式2:命令行创建

kubectl create secret docker-registry harbor-secret --docker-server="192.168.5.193:15001"  \
--docker-email=test@test.com  \
--docker-username='admin'  \
--docker-password='Harbor12345' \
-n java-app

4.Pod指定Secret

在Deployment的spec.template.spec里添加:

imagePullSecrets:
  - name: harbor-secret

整个k8s.yaml文件如下:

# 创建Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: demo-springboot-deployment
  namespace: java-app
  labels:
    app: demo-springboot #与Service的selector对应
spec:
  # 副本的数量
  replicas: 2
  selector:
    # 选择Pod
    matchLabels:
      app: demo-springboot
  # 选择或创建的Pod的模板
  template:
    metadata:
      # 与Deployment的selector对应
      labels:
        app: demo-springboot
    spec:
      imagePullSecrets:
        - name: harbor-secret

      containers:
        - image: 192.168.5.193:15001/custom_image/custom_docker-springboot:1.0
          name: custom-docker-springboot-1-0
          ports:
            - containerPort: 8080
              name: pod-8080
          # 容器内的路径
          volumeMounts:
            - name: log
              mountPath: /log/

      # 主机的路径
      volumes:
        - name: log #和volumeMounts中的内容要对应
          hostPath:
            path: /work/devops/k8s/app/demo-springboot/log/
            type: DirectoryOrCreate
---
# 创建Service
apiVersion: v1
kind: Service
metadata:
  name: demo-springboot-service
  namespace: java-app
  labels:
    app: demo-springboot
spec:
  ports:
    - name: demo-springboot-port
      port: 9000   # Service监听的端口
      targetPort: 8080  # pod自身暴露的端口。对应Deployment的containerPort
      # 对外的端口号
      nodePort: 30004
  # 选择Deployment
  selector:
    app: demo-springboot
  # NodePort类型可以对外暴露端口
  type: NodePort

然后再次执行:

kubectl apply -f k8s.yaml

结果:(成功启动)

5.访问测试

看一下SpringBoot的日志:(启动成功)

访问一下SpringBoot的端口:

访问:http://192.168.5.193:30004/doc.html

结果

访问接口:

6.自动关联 Secret

上边每次在创建 Pod 时都需要通过 imagePullSecrets 字段引用相应 namespace 下的 secret。

可以通过 kubectl patch 命令来将 namespace 和对应的 secret 自动关联,执行如下语句,关联后就不需要在 Pod 上指定 imagePullSecrets:

kubectl patch serviceaccount default -n java-app -p \
    '{"imagePullSecrets":[{"name":"harbor-secret"}]}'
0

评论0

请先

显示验证码
没有账号?注册  忘记密码?

社交账号快速登录