0x01 前言

近期在学习docker,在安装k8s的时候因为众所周知的原因卡在kubeadm初始化的一步。在深入了解相关的知识后,我决定在本地配置一个私有仓库。

因为k8s的镜像存放在Google的服务器中,所以这篇文章需要用到代理,这部分请自行解决。

0x02 准备

首先需要准备一个docker环境,在启动docker服务之前需要做一些修改,以便让docker拉取镜像的时候可以通过代理进行网络通讯:

#新建文件夹
[[email protected] ~]# mkdir /etc/systemd/system/docker.service.d

#新建文件
[[email protected] ~]# vim /etc/systemd/system/docker.service.d/http-proxy.conf

#写入内容
[Service]
Environment="HTTP_PROXY=http://win10.t.com:1080/"
Environment="NO_PROXY=localhost,127.0.0.0/8,10.0.0.0/8,docker-t1,docker-t1.t.com,10.1.1.115"
  • HTTP_PROXY:配置http代理的服务器地址与端口
  • NO_PROXY:配置那些IP地址和域名的流量不走代理

然后需要重新载入daemon:

[[email protected] ~]# systemctl daemon-reload

在启动前先检查配置是否生效:

[[email protected] ~]# systemctl show --property Environment docker
Environment=GOTRACEBACK=crash DOCKER_HTTP_HOST_COMPAT=1 PATH=/usr/libexec/docker:/usr/bin:/usr/sbin HTTP_PROXY=http://win10.t.com:1080/ NO_PROXY=localhost,127.0.0.0/8,10.0.0.0/8

即可启动docker:

[[email protected] ~]# systemctl restart docker

0x03 启动本地仓库

在启动仓库之前需要确认磁盘空间是否充足,然后建立一个文件夹,用于存放docker镜像:

[[email protected] ~]# mkdir /docker_images_registry

然后搜索名为registry的镜像,看看哪些是可用的:

[[email protected] ~]# docker search registry

在拉取镜像的时候建议选择带有OFFICIAL标签的镜像。确认镜像后,通过以下命令搭建一个仓库:

[[email protected] ~]#  docker run -d -p 5000:5000 --name registry \
--privileged=true --restart=always \
-v /docker_images_registry:/var/lib/registry \
docker.io/registry

Unable to find image 'docker.io/registry:latest' locally
Trying to pull repository docker.io/library/registry ... 
latest: Pulling from docker.io/library/registry
81033e7c1d6a: Pull complete 
b235084c2315: Pull complete 
c692f3a6894b: Pull complete 
ba2177f3a70e: Pull complete 
a8d793620947: Pull complete 
Digest: sha256:672d519d7fd7bbc7a448d17956ebeefe225d5eb27509d8dc5ce67ecb4a0bce54
Status: Downloaded newer image for docker.io/registry:latest
0d8bae1acc136b5739a40f303c0c520a94fc0cf4d9478248d39dabe06cead618

当使用docker run运行一个容器时,如果本地没有指定的镜像,则会从远端进行拉取,以上命令的最后指定了需要用到的镜像与仓库:docker.io/registry

  • -d:使容器在后台运行;
  • -p:将端口暴露在本地;
  • –name:给这个容器命名;
  • –privileged:赋予该容器拓展的权限;
  • –restart:当容器退出时,将自动重启该容器;
  • -v:映射volume用于数据存储。

如果一切正常,通过以下命令即可查看相关容器的运行情况:

[[email protected] ~]# docker ps
CONTAINER ID        IMAGE                COMMAND                  CREATED             STATUS              PORTS                    NAMES
0d8bae1acc13        docker.io/registry   "/entrypoint.sh /e..."   15 minutes ago      Up 15 minutes       0.0.0.0:5000->5000/tcp   registry

最后通过curl检查该仓库运行是否正常:

[[email protected] ~]# curl 10.1.1.115:5000/v2/_catalog
{"repositories":[]}

因为还没有在该仓库里注册镜像,所以repositories的列表为空,但如果出现以上内容,则为正常。

0x04 客户端

在继续之前需要为docker指定仓库地址:

#打开文件
[[email protected] ~]# vim /etc/sysconfig/docker

#在文件最后加入以下内容:
OPTIONS='--insecure-registry 10.1.1.115:5000'
ADD_REGISTRY='--add-registry 10.1.1.115:5000'

在新版的docker,要求仓库使用https,如果想使用http,则需要添加–insecure-registry这个选项,然后还需要将仓库在docker里注册,这需要用到–add-registry。

修改完成后重启docker即可:

[[email protected] ~]# systemctl restart docker

0x05 拉取与注册

为了安装k8s,需要预先将相关镜像拉取到本地,然后重新打标签,最后push到刚才建好的仓库中。

为了减少重复性工作,我选择通过shell实现上述功能:

images=(
	gcr.io/google_containers/kube-controller-manager-amd64:v1.11.0
	gcr.io/google_containers/kube-proxy-amd64:v1.11.0
	gcr.io/google_containers/kube-scheduler-amd64:v1.11.0
	gcr.io/google_containers/kube-apiserver-amd64:v1.11.0
	gcr.io/google_containers/k8s-dns-dnsmasq-nanny-amd64:1.14.10
	gcr.io/google_containers/k8s-dns-kube-dns-amd64:1.14.10
	gcr.io/google_containers/k8s-dns-sidecar-amd64:1.14.10
	gcr.io/google_containers/etcd-amd64:3.2.18
	gcr.io/google_containers/kubernetes-dashboard-amd64:v1.8.3
	k8s.gcr.io/coredns:1.1.3
	quay.io/coreos/flannel:v0.10.0-amd64
	docker.io/registry:latest
	gcr.io/google_containers/pause-amd64:3.1
	k8s.gcr.io/pause:3.1
)

for imageName in ${images[@]}
do
    docker pull $imageName
    docker tag $imageName 10.1.1.115:5000/$imageName
    docker push 10.1.1.115:5000/$imageName
done

将以上代码复制到一个文本文件中:

[[email protected] ~]# vim k8s_shell.sh

然后运行命令,视乎代理服务器的速度,需要的时间会有所不同:

因为这是通过本地docker push到本地仓库的,所以在本地的docker也存有相关镜像:

[[email protected] ~]# docker image ls

0x06 测试

在测试之前先把本地docker的镜像删除,比如以下镜像:

gcr.io/google_containers/kube-scheduler-amd64                            v1.11.0             0e4a34a3b0e6        8 days ago          56.8 MB

确认ID后,通过以下命令进行删除:

[r[email protected] ~]# docker image rm -f 0e4a34a3b0e6
Untagged: 10.1.1.115:5000/gcr.io/google_containers/kube-scheduler-amd64:v1.11.0
Untagged: 10.1.1.115:5000/gcr.io/google_containers/[email protected]:6e1f4aeee486e0fd2d86db5ad4adeb92f05959590ec17dc09a3b1b618c899f5f
Untagged: gcr.io/google_containers/kube-scheduler-amd64:v1.11.0
Untagged: gcr.io/google_containers/[email protected]:6e1f4aeee486e0fd2d86db5ad4adeb92f05959590ec17dc09a3b1b618c899f5f
Deleted: sha256:0e4a34a3b0e6f3956a131a4f3e2244bc6bfc2c3ac5e6f384a2094d39bc207094
Deleted: sha256:2fac24847b508cf1cebd6ef8f77182194bc60ef82995f0c2b7c0cfac43e72b0e

然后尝试通本地仓库中拉取:

[[email protected] ~]# docker pull 10.1.1.115:5000/gcr.io/google_containers/kube-scheduler-amd64:v1.11.0
Trying to pull repository 10.1.1.115:5000/gcr.io/google_containers/kube-scheduler-amd64 ... 
sha256:6e1f4aeee486e0fd2d86db5ad4adeb92f05959590ec17dc09a3b1b618c899f5f: Pulling from 10.1.1.115:5000/gcr.io/google_containers/kube-scheduler-amd64
07a152489297: Already exists 
5d849ba966c4: Pull complete 
Digest: sha256:6e1f4aeee486e0fd2d86db5ad4adeb92f05959590ec17dc09a3b1b618c899f5f
Status: Downloaded newer image for 10.1.1.115:5000/gcr.io/google_containers/kube-scheduler-amd64:v1.11.0

如果一切正常, 那么会成功从本地仓库中拉取镜像。

如果需要查看仓库中的镜像,可以通过浏览器或者curl访问以下地址:

[[email protected] ~]# curl 10.1.1.115:5000/v2/_catalog
{
  "repositories": [
    "docker.io/registry",
    "gcr.io/google_containers/etcd-amd64",
    "gcr.io/google_containers/k8s-dns-dnsmasq-nanny-amd64",
    "gcr.io/google_containers/k8s-dns-kube-dns-amd64",
    "gcr.io/google_containers/k8s-dns-sidecar-amd64",
    "gcr.io/google_containers/kube-apiserver-amd64",
    "gcr.io/google_containers/kube-controller-manager-amd64",
    "gcr.io/google_containers/kube-scheduler-amd64",
    "gcr.io/google_containers/kubernetes-dashboard-amd64",
    "gcr.io/google_containers/pause-amd64",
    "k8s.gcr.io/coredns",
    "k8s.gcr.io/pause",
    "quay.io/coreos/flannel"
  ]
}

0x07 结语

其实这一系列的配置都不繁琐,但是代理这个要求却难倒很多人。

如果需要删除仓库中的镜像,则需要手动在数据存储的目录中删除文件,例如我需要删除etcd-amd64这个镜像,则删除以下目录即可:

[[email protected] ~]# rm -rf /docker_images_registry/docker/registry/v2/repositories/gcr.io/google_containers/etcd-amd64/

然后再检查仓库中是否还存在该镜像:

[[email protected] ~]# curl 10.1.1.115:5000/v2/_catalog
{
  "repositories": [
    "docker.io/registry",
    "gcr.io/google_containers/k8s-dns-dnsmasq-nanny-amd64",
    "gcr.io/google_containers/k8s-dns-kube-dns-amd64",
    "gcr.io/google_containers/k8s-dns-sidecar-amd64",
    "gcr.io/google_containers/kube-apiserver-amd64",
    "gcr.io/google_containers/kube-controller-manager-amd64",
    "gcr.io/google_containers/kube-scheduler-amd64",
    "gcr.io/google_containers/kubernetes-dashboard-amd64",
    "gcr.io/google_containers/pause-amd64",
    "k8s.gcr.io/coredns",
    "k8s.gcr.io/pause",
    "quay.io/coreos/flannel"
  ]
}

可以看到,已经没有gcr.io/google_containers/etcd-amd64这个镜像了。