在企业落地 K8S 的过程中,私有镜像库 (专用镜像库) 必不可少,特别是在 Docker Hub 开始对免费用户限流之后, 越发的体现了搭建私有镜像库的重要性。
私有镜像库不但可以加速镜像的拉取还可以避免因特有的"网络问题"导致镜像拉取失败尴尬。
当然部署了私有镜像库之后也需要对镜像库设置一些安全策略,大部分私有镜像库采用 IP访问策略+认证 (非公开项目) 的方式对镜像库进行安全保护。
那么对于含有认证限制的镜像库,在 K8S 中该如何优雅的集成呢? 下文就总结了在 K8S 中使用私有镜像库的几种情况和方式。
首先要确定私有镜像库的授权使用方式,在针对不同的使用方式选择对应的认证配置。
首先编写 Docker 的认证配置文件, 格式如下:
{
"auths": {
"<HOST>": {
"auth": "<BASIC_AUTHORIZATION>"
}
}
}
<HOST>
为私有镜像库的地址, 例如: hub.docker.com
<BASIC_AUTHORIZATION>
为 BASE64(<USERNAME>:<PASSWORD>)
例如: cmVhZGVyOjEyMzQ1Ng==
, 其中账号是: reader
, 密码是: 123456
使用 :
拼接后进行 base64
完整的配置文件, 例
{
"auths": {
"hub.docker.com": {
"auth": "cmVhZGVyOjEyMzQ1Ng=="
},
"harbor.domain.cn": {
"auth": "cmVhZGVyOiFAIzQ1Ng=="
}
}
}
如有多个镜像库在 auths
节中进行添加即可。
推荐放在 kubelet 根目录中, 配置文件需以 config.json
命名。
默认的 kubelet 根目录一般为 /var/lib/kubelet
(如有修改进行替换即可)
也就是需要放置在 /var/lib/kubelet/config.json
。
还可以放在以下位置:
{--root-dir:-/var/lib/kubelet}/config.json
{cwd of kubelet}/config.json
${HOME}/.docker/config.json
/.docker/config.json
{--root-dir:-/var/lib/kubelet}/.dockercfg
{cwd of kubelet}/.dockercfg
${HOME}/.dockercfg
/.dockercfg
参考文档: https://kubernetes.io/docs/concepts/containers/images/#configuring-nodes-to-authenticate-to-a-private-registry
需要在 kubelet service 环境中配置 HOME 的路径, 不然不会生效, 例如: HOME=/root
下面是使用 kubeadm
安装的环境中可用的脚本, 如果不是请自行配置
echo "HOME=${HOME}" >> /var/lib/kubelet/kubeadm-flags.env
如果 init 不是 systemd,请自行替换服务重启的命令
systemctl daemon-reload; systemctl restart kubelet
kubectl create secret docker-registry <SECRET_NAME> --docker-server=<DOCKER_REGISTRY_SERVER> --docker-username=<DOCKER_USER> --docker-password=<DOCKER_PASSWORD> -n <NAMESPACE>
其中
<SECRET_NAME>
是机密资源的名称, 在编辑 sa 资源的时需要引用
<DOCKER_REGISTRY_SERVER>
是私有镜像库的服务器地址
<DOCKER_USER>
是私有镜像库认证的账号
<DOCKER_PASSWORD>
是私有镜像库认证的密码
<NAMESPACE>
是命名空间名称
示例命令如下:
kubectl create secret docker-registry docker-reader-secret --docker-server=harbor.domain.cn --docker-username=reader --docker-password=123456 -n basic
apiVersion: v1
data:
.dockerconfigjson: eyJhdXRocyI6eyJET0NLRVJfUkVHSVNUUllfU0VSVkVSIjp7InVzZXJuYW1lIjoiRE9DS0VSX1VTRVIiLCJwYXNzd29yZCI6IkRPQ0tFUl9QQVNTV09SRCIsImF1dGgiOiJSRTlEUzBWU1gxVlRSVkk2UkU5RFMwVlNYMUJCVTFOWFQxSkUifX19
kind: Secret
metadata:
name: docker-reader-secret
namespace: default
type: kubernetes.io/dockerconfigjson
.dockerconfigjson
是base64之后的字符串, 具体内容参考 "编写 Docker 配置文件" 节中的内容
kubectl apply -f docker-reader-secret.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: service1
namespace: basic
secrets:
- name: service1-token-mp4qs
imagePullSecrets:
- name: docker-reader-secret
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
serviceAccountName: service1
K8S 中有个默认的机制,会在命名空间中创建一个名称为 default
的 ServiceAccount (sa) 资源。
并且在资源没有单独指定 serviceAccountName
时, 默认使用 default
作为serviceAccountName。
所以我们只需设置 default ServiceAccount 的 imagePullSecrets 即可对该命名空间中没有特殊指定 serviceAccountName
字段的 Pod 生效了。
参考 "创建一个 Docker 注册表机密资源" 节中的内容
apiVersion: v1
kind: Pod
metadata:
name: foo
namespace: awesomeapps
spec:
containers:
- name: foo
image: janedoe/awesomeapp:v1
imagePullSecrets:
- name: docker-reader-secret
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
imagePullSecrets:
- name: docker-reader-secret
如果大家的私有镜像库还没有采用认证,就赶紧行动起来吧! 血的教训,安全问题刻不容缓。