以下流程在
minikube
中完全跑通
完成效果
- 可以在kubernetes集群中,搭建自己的
docker registry
registry
支持TLS验证,并且TLS证书支持IP验证【默认只支持域名验证】registry
不仅可以被集群中pod
访问,而且可以被集群外部访问。registry
使用的存储基于NFS,这就意味着你可以将镜像存在网络中其它主机上。
完整流程
创建PV
仓库的首要任务就是存储数据。我们需要决定将数据存储在哪里,可以使用Kubernetes的PersistentVolume
对象实现持久化。
1 | # kube-registry-pv.yaml |
这里面使用nfs作为持久化挂载,关于如何搭建NFS服务器,可以查看我的这篇文章:Linux NFS使用 。
创建PVC来绑定PV
PV持久卷创建完毕后,我们可以使用PersistentVolumeClaim
来绑定这个PV。
1 | # kube-registry-pvc.yaml |
创建docker registry
现在我们可以创建一个Docker仓库了。
1 | # kube-registry-rc.yaml |
这里面使用了hostPort: 5000
将Pod中的仓库端口映射到minikube的5000
端口中,以便集群外部也能访问这个docker registry。
并且,我们通过使用名叫registry-tls-secret
的Secret
资源,为这个registry pod提供了TLS必要的server.crt
和server.key
。这个Secrets
以及证书相关,会在下文介绍。
创建Service暴露Pod服务
我们可以将registry Pod作为一个Service
暴露出来。
1 | # kube-registry-svc.yaml |
OK,目前为止,我们已经建立了docker registry的相关资源,接下来就是准备TLS支持的相关工作。
生成服务端crt证书和key私钥
这一段走的时候不太顺利,尝试了很多方法,也解决了很多问题,大致包括:
- TLS证书需要支持IP验证。默认情况下证书只支持域名校验,否则会报
IP SANs
错误cannot validate certificate for 192.168.1.100 because it doesn't contain any IP SANs
。 - 不能使用自签名证书。首先必须要自己生成一个CA crt证书,然后用这个CA来签名服务端证书,然后把该CA证书放在docker的
custom root CA
目录下,如果采用自签名证书,或者不提供CA,则会报错x509: certificate signed by unknown authority
。
如前所述,我们将registry服务映射到了minikube的5000
端口上,假设minikube的IP地址为192.168.99.100
,根据这些信息我们来生成192.168.99.100:5000
服务端TLS证书。
当然了,如果你是土豪,可以直接到公网CA上直接买证书,就可以跳过这一段辛酸的经验
解决IP SANs
问题
为了让证书支持IP验证,我们首先需要定制一个自己的openssl模板文件,创建文件openssl.cnf
,内容如下:
1 | [ req ] |
主要是subjectAltName = IP:192.168.99.100
这句话,开启了对IP的验证功能。
生成ca.key
1 | openssl genrsa -out ca.key 2048 |
基于openssl.cnf
生成ca.crt
1 | openssl req -x509 -new -nodes -key ca.key -subj "/CN=192.168.99.100:5000" -days 5000 -config openssl.cnf -out ca.crt |
备注:当然,推荐使用域名作为CN,这样的话,就不需要openssl.cnf文件了,只需要在hosts文件中做域名到IP的映射就行,如果你有公网域名,那就更方便了,连hosts也不用改,DNS服务商已为你做好了一切。
生成server.key
1 | openssl genrsa -out server.key 2048 |
这个server.key
就是前面ReplicationController
配置文件里面提到的key文件。
基于openssl.cnf
生成server.csr
1 | openssl req -new -key server.key -subj "/CN=192.168.99.100:5000" -config openssl.cnf -out server.csr |
生成server.crt
1 | openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 5000 -extensions v3_req -extfile openssl.cnf |
这个命令同时还会生成ca.srl
文件。这个server.crt
就是前面ReplicationController
配置文件里面提到的crt文件。
到这儿,TLS所需要的证书和私钥已经全部准备完毕。
将server.key和server.crt打包到Secrets中
准备好了server.key
和server.crt
,需要提供给registry pod,这样才能提供TLS支持,这里使用kubernetes的Secrets
资源来提供配置。
1 | kubectl --namespace=kube-system create secret generic registry-tls-secret --from-file=server.crt=./server.crt --from-file=server.key=./server.key |
这个Secret
资源名称即为registry-tls-secret
,正好被之前的ReplicationController
所引用。
将所有准备工作串起来
到这里,所有的准备资源都已就绪,现在需要把它们整合起来并运行。首先看下当前的目录结构:
1 | . |
创建文件start.sh
,这样便于随时自动化启动运行:
1 | kubectl --namespace=kube-system create secret generic registry-tls-secret --from-file=server.crt=./server.crt --from-file=server.key=./server.key |
创建文件delete.sh
,便于自动化关闭服务:
1 | kubectl --namespace=kube-system delete secrets registry-tls-secret |
将一切运行起来:
1 | sh ./delete.sh /*删除所有相关资源以初始化*/ |
验证这一切跑通
我们可以在能访问192.168.99.100
的任一台机器上验证这一切,在验证之前,还有一项准备工作要做,否则docker会提示你证书无效:x509: certificate signed by unknown authority
向验证机器的docker提供CA证书:
1 | sudo mkdir -p /etc/docker/certs.d/192.168.99.100:5000 |
验证
1 | docker pull busybox |