在企業落地 K8S 的過程當中,私有鏡像庫 (專用鏡像庫) 必不可少,特別是在 Docker Hub 開始對免費用戶限流以後, 愈加的體現了搭建私有鏡像庫的重要性。node
私有鏡像庫不但能夠加速鏡像的拉取還能夠避免因特有的"網絡問題"致使鏡像拉取失敗尷尬。nginx
固然部署了私有鏡像庫以後也須要對鏡像庫設置一些安全策略,大部分私有鏡像庫採用 IP訪問策略+認證 (非公開項目) 的方式對鏡像庫進行安全保護。docker
那麼對於含有認證限制的鏡像庫,在 K8S 中該如何優雅的集成呢?
下文就總結了在 K8S 中使用私有鏡像庫的幾種狀況和方式。json
首先要肯定私有鏡像庫的受權使用方式,在針對不一樣的使用方式選擇對應的認證配置。api
這個應該是企業使用 K8S 時最經常使用的方式,通常也只要使用這個就夠了,而且該方案几乎是使用了私有鏡像庫以後必不可少的配置,它能夠作到:
在節點環境中進行必定的配置,不須要在 K8S 中進行其它的配置便可享有具體私有庫的權限。
該方案對該節點上的全部 Pods 生效,同時還對非 Pods 鏡像生效,例如: kubelet 的 pause 鏡像,這個很是關鍵。安全
配置了該 ServiceAccount 的 Pod 都享有這個 ServiceAccount 所配置的鏡像庫認證設置。
還能夠利用 K8S 中 default ServiceAccount 機制,達到對一個具體命名空間中沒有特殊設置的全部 Pod 生效。服務器
針對具體的 Pod 進行認證配置,該 Pod 就會具備私有庫的權限。網絡
Deployment、DaemonSet、StatefulSet、CronJob、Job 等資源都使用了PodTemplate 最終都會以具體的 Pod 資源體驗,因此在 PodTemplate 中配置也算對 Pod 配置。app
首先編寫 Docker 的認證配置文件, 格式以下:dom
{ "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
須要在 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
若是你們的私有鏡像庫尚未採用認證,就趕忙行動起來吧! 血的教訓,安全問題刻不容緩。