简介
本文解决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"}]}'
请先
!