k8s集群中运行docker registry镜像仓库实践
<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li><a href="#_label0">编写 Dockerfile</a></li><li><a href="#_label1">编写 k8s yaml 文件</a></li><ul class="second_class_ul"><li><a href="#_lab2_1_0">kubelet 配置静态 pod 路径</a></li><li><a href="#_lab2_1_1">启动静态 pod</a></li><li><a href="#_lab2_1_2">docker 配置增加 registry 地址</a></li><li><a href="#_lab2_1_3">验证 docker registry 仓库</a></li></ul><li><a href="#_label2">总结</a></li><ul class="second_class_ul"></ul></ul></div><ul><li>docker registry 相对于 harbor 来说,安全性会更低有点,不过对于一些内网场景(不需要和公网有互通)来说,其实 docker registry 更轻量化一些</li><li>本文仅作学习参考,至于实际的选择,还是以各自实际需求和场景为准</li></ul><p class="maodian"><a name="_label0"></a></p><h2>编写 Dockerfile</h2>
<ul><li>为了让 docker registry 支持认证登录,需要安装 htpasswd 命令</li><li>为了方便后期维护 docker registry,增加镜像删除的功能</li></ul>
<ul><li><code>config.yml</code></li></ul>
<div class="jb51code"><pre class="brush:yaml;">version: 0.1
log:
fields:
service: registry
storage:
cache:
blobdescriptor: inmemory
filesystem:
rootdirectory: /var/lib/registry
# 增加这里的 delete 和 enabled
## 启用 registry 镜像删除的功能
delete:
enabled: true
http:
addr: :5000
headers:
X-Content-Type-Options:
health:
storagedriver:
enabled: true
interval: 10s
threshold: 3
</pre></div>
<ul><li><code>Dockerfile</code></li></ul>
<div class="jb51code"><pre class="brush:plain;">FROM registry:2
RUN rm -f /etc/docker/registry/config.yml && \
apk add apache2-utils && \
apk cache clean
ADD ./config.yml /etc/docker/registry/
</pre></div>
<ul><li>构建镜像(需要构建成什么样的镜像名字,可以自己定义)</li></ul>
<div class="jb51code"><pre class="brush:plain;">docker build -t registry:2_auth .
</pre></div>
<p class="maodian"><a name="_label1"></a></p><h2>编写 k8s yaml 文件</h2>
<ul><li>以静态 pod 的方式来部署,这里就直接使用 <code>kind: Pod</code> ,而不是其他的控制集</li><li>不同 k8s 版本,<code>apiVersion</code> 版本可能会不一样,可以使用 <code>kubectl explain pod.apiVersion</code> 命令查看 <code>pod</code> 这个 <code>kind</code> 的 <code>apiVersion</code></li></ul>
<div class="jb51code"><pre class="brush:yaml;">---
apiVersion: v1
kind: Pod
metadata:
# pod 名称前缀
name: docker-registry
# 指定 namespace
namespace: kube-system
spec:
# 使用主机网络模式
hostNetwork: true
tolerations:
- key: node-role.kubernetes.io/master
effect: NoSchedule
- key: "CriticalAddonsOnly"
operator: "Exists"
- key: "node.alpha.kubernetes.io/notReady"
operator: "Exists"
initContainers:
# 这里注意修改成自己 build 的镜像名称
- image: registry:2_auth
# docker 容器的名字
name: docker-registry-init
imagePullPolicy: IfNotPresent
# 配置用户名和密码
command:
- sh
- "-c"
- "htpasswd -Bbn admin adminpasswd > /auth/htpasswd"
volumeMounts:
- mountPath: /auth
name: docker-registry-auth
containers:
# 这里注意修改成自己 build 的镜像名称
- image: registry:2_auth
# docker 容器的名字
name: registry
imagePullPolicy: IfNotPresent
# 资源限制以自己的实际需求为准
resources:
limits:
cpu: 3000m
memory: 3000Mi
env:
# registry 访问的端口,静态 pod 会暴露出来对应的端口
- name: REGISTRY_HTTP_ADDR
value: ":35000"
# registry 存储路径
- name: REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY
value: /var/lib/registry
# 以 htpasswd 的方式认证
- name: REGISTRY_AUTH
value: htpasswd
# 注册认证
- name: REGISTRY_AUTH_HTPASSWD_REALM
value: Registry
# 认证文件路径
- name: REGISTRY_AUTH_HTPASSWD_PATH
value: /auth/htpasswd
volumeMounts:
- mountPath: /var/lib/registry
name: docker-registry-storage
- mountPath: /auth
name: docker-registry-auth
volumes:
# 将 registry 存储路径持久化到本地,path 指定的路径可以自己修改
- name: docker-registry-storage
hostPath:
path: /data/k8s-data/registry-data
type: Directory
# 认证文件的持久化访问为 emptyDir,每次重启都会重新生成
- name: docker-registry-auth
emptyDir: {}
</pre></div>
<p class="maodian"><a name="_lab2_1_0"></a></p><h3>kubelet 配置静态 pod 路径</h3>
<ul><li>kubeadm 部署的,默认就配置了静态 pod 的存放路径,可以不进行下面的操作</li><li>二进制部署的,一般没有配置静态 pod 的存放路径,需要 kubelet 增加 <code>--pod-manifest-path</code> 指定路径(提前创建好路径),然后重启 kubelet</li></ul>
<div class="jb51code"><pre class="brush:plain;">--pod-manifest-path=/etc/kubernetes/manifests
</pre></div>
<p class="maodian"><a name="_lab2_1_1"></a></p><h3>启动静态 pod</h3>
<p>创建持久化路径,这里的路径要和 <code>yaml</code> 文件里面的 <code>volumes</code> 下面的 <code>docker-registry-storage</code> 指定的 <code>path</code> 一致</p>
<div class="jb51code"><pre class="brush:plain;">mkdir -p /data/k8s-data/registry-data
</pre></div>
<p>将 yaml 文件放到上面 kubelet 配置的静态 pod 路径下,然后等 pod 启动(如果想快点,可以直接重启 kubelet 组件)</p>
<p>查看 pod 是否创建成功</p>
<div class="jb51code"><pre class="brush:plain;">kubectl get pod -n kube-system | grep registry
</pre></div>
<p>静态 pod 会以 yaml 文件里面的 name 加上当前节点 ip 作为 pod 的名称</p>
<div class="jb51code"><pre class="brush:plain;">docker-registry-172.72.0.95 1/1 Running 0 33s
</pre></div>
<p class="maodian"><a name="_lab2_1_2"></a></p><h3>docker 配置增加 registry 地址</h3>
<div class="jb51code"><pre class="brush:plain;">vim /etc/docker/daemon.json
</pre></div>
<p>注意 json 语法格式</p>
<p>如果重启 docker 失败,日志有如下输出,表示 daemon.json 文件的格式有错误,注意最后是否需要加上逗号</p>
<blockquote><p>unable to configure the Docker daemon with file /etc/docker/daemon.json: invalid character '"' after object key:value pair</p></blockquote>
<div class="jb51code"><pre class="brush:plain;"># 增加下面的信息
"insecure-registries": ["ip:端口"]
</pre></div>
<p>拿我的举个例子</p>
<div class="jb51code"><pre class="brush:json;">{
"registry-mirrors": ["https://docker.mirrors.ustc.edu.cn"],
"insecure-registries": ["172.72.0.95:35000"],
"exec-opts": ["native.cgroupdriver=systemd"],
"data-root": "/approot/data/crt-data",
"log-driver": "json-file",
"log-opts": {
"max-size": "200m",
"max-file": "5"
},
"storage-driver": "overlay2",
"storage-opts": [
"overlay2.override_kernel_check=true"
]
}
</pre></div>
<p>重启 docker 服务</p>
<div class="jb51code"><pre class="brush:plain;">systemctl restart docker
</pre></div>
<p class="maodian"><a name="_lab2_1_3"></a></p><h3>验证 docker registry 仓库</h3>
<p>登录 docker registry 仓库,这里的用户名,密码以及登录的 ip 和端口都需要以自己的为准</p>
<div class="jb51code"><pre class="brush:plain;">docker login -u admin -p adminpasswd 172.72.0.95:35000
</pre></div>
<p>登录成功后,就会返回对应的 success 了</p>
<div class="jb51code"><pre class="brush:plain;">WARNING! Using --password via the CLI is insecure. Use --password-stdin.
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
</pre></div>
<p>修改镜像 tag,然后尝试上传镜像</p>
<div class="jb51code"><pre class="brush:plain;">docker tag registry:2_auth 172.72.0.95:35000/registry:2_auth
</pre></div>
<p>推送镜像到 docker registry</p>
<div class="jb51code"><pre class="brush:plain;">docker push 172.72.0.95:35000/registry:2_auth
</pre></div>
<p>返回类似如下的信息,说明推送成功了,可以去其他节点使用 <code>docker login</code> 登录(也需要 docker 配置文件加上 docker registry 的地址),然后直接 <code>docker pull <仓库地址>:<仓库端口>/registry:2_auth</code></p>
<div class="jb51code"><pre class="brush:bash;">The push refers to repository
f586723f1e87: Pushed
b14c705d6378: Pushed
6e5160500bc7: Pushed
744dbed40ffa: Pushed
f8dc4f9c98a6: Pushed
4984fbd72df1: Pushed
bb01bd7e32b5: Pushed
2_auth: digest: sha256:3b215dad8c5b7704b0b84a3ee46971314b8db9e65fb82a62204cf8497587377a size: 1781
</pre></div>
<p class="maodian"><a name="_label2"></a></p><h2>总结</h2>
<p>以上为个人经验,希望能给大家一个参考,也希望大家多多支持琼殿技术社区。</p>
頁:
[1]