在使用 Docker 和 Kubernetes 時,咱們常常須要訪問 gcr.io
和 quay.io
鏡像倉庫,因爲衆所周知的緣由,這些鏡像倉庫在中國都沒法訪問,惟一能訪問的是 Docker Hub,但速度也是奇慢無比。gcr.azk8s.cn
是 gcr.io
鏡像倉庫的代理站點,原來能夠經過 gcr.azk8s.cn
訪問 gcr.io 倉庫裏的鏡像,可是目前 *.azk8s.cn
已經僅限於 Azure
中國的 IP 使用,再也不對外提供服務了。國內其餘的鏡像加速方案大多都是採用定時同步的方式來緩存,不能保證及時更新,ustc 和七牛雲等鏡像加速器我都試過了,很是不靠譜,不少鏡像都沒有。node
爲了可以順利訪問 gcr.io
等鏡像倉庫,咱們須要在牆外本身搭建一個相似於 gcr.azk8s.cn
的鏡像倉庫代理站點。直接反代能夠保證獲取到的鏡像是最新最全的,比緩存靠譜多了。nginx
quay.io
和 Docker Hub
很好代理,能夠直接使用 Envoy
的 host_rewrite_literal 參數(這是新版本的參數,若是你使用舊版本的 Envoy,參數應該是 host_rewrite),當 Envoy 將請求轉發給上游集羣時,會直接將頭文件中的 host
改成指定的值。好比,若是上游集羣是 quay.io,就將頭文件改成 quay.io
。我以前寫過的 使用 Envoy 反向代理谷歌搜索 用的就是此方案。什麼?你是 Envoy 小白?莫慌,我已經爲大家準備了一本 Envoy 從入門到放棄 的電子書,快快點擊下方的連接學習去吧(記得給我一個 star 哦)~~git
gcr.io
稍微有點難辦,由於它在鏈接的時候須要二次認證,即便你經過反代服務器 pull 鏡像,它仍是會再次訪問 gcr.io
進行驗證,而後才能夠經過反代服務器 pull 鏡像。這就有點尷尬了,我特麼要是能訪問 gcr.io,還要什麼反代啊。。。話說 Docker 官方不是有一個 registry
鏡像嗎,能夠經過設置參數 remoteurl
將其做爲遠端倉庫的緩存倉庫,這樣當你經過這個私有倉庫的地址拉取鏡像時,regiistry 會先將鏡像緩存到本地存儲,而後再提供給拉取的客戶端(有可能這兩個步驟是同時的,我也不太清楚)。咱們能夠先部署一個私有 registry,而後將 remoteurl
設爲 https://gcr.io
,最後再經過 Envoy 反代,基本上就能夠了。github
方案肯定了以後,就能夠動手配置了。仍是使用我以前反覆提到的方法:經過文件動態更新配置。若是你不是很清楚我在說什麼,請參考 Envoy 基礎教程:基於文件系統動態更新配置。這裏我就直接貼配置了。docker
bootstrap
配置:json
# envoy.yaml node: id: node0 cluster: cluster0 dynamic_resources: lds_config: path: /etc/envoy/lds.yaml cds_config: path: /etc/envoy/cds.yaml admin: access_log_path: "/dev/stdout" address: socket_address: address: "0.0.0.0" port_value: 15001
LDS
的配置:bootstrap
# lds.yaml version_info: "0" resources: - "@type": type.googleapis.com/envoy.config.listener.v3.Listener name: listener_http address: socket_address: address: 0.0.0.0 port_value: 80 filter_chains: - filters: - name: envoy.filters.network.http_connection_manager typed_config: "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager stat_prefix: ingress_http codec_type: AUTO access_log: name: envoy.access_loggers.file typed_config: "@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog path: /dev/stdout route_config: name: http_route virtual_hosts: - name: default domains: - "*" routes: - match: prefix: "/" redirect: https_redirect: true port_redirect: 443 response_code: "FOUND" http_filters: - name: envoy.filters.http.router - "@type": type.googleapis.com/envoy.config.listener.v3.Listener name: listener_https address: socket_address: address: 0.0.0.0 port_value: 443 listener_filters: - name: "envoy.filters.listener.tls_inspector" typed_config: {} filter_chains: - transport_socket: name: envoy.transport_sockets.tls typed_config: "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext common_tls_context: alpn_protocols: h2,http/1.1 tls_certificates: - certificate_chain: filename: "/root/.acme.sh/xxx.com/fullchain.cer" private_key: filename: "/root/.acme.sh/xxx.com/xxx.com.key" filters: - name: envoy.filters.network.http_connection_manager typed_config: "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager stat_prefix: ingress_https codec_type: AUTO use_remote_address: true access_log: name: envoy.access_loggers.file typed_config: "@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog path: /dev/stdout route_config: name: https_route response_headers_to_add: - header: key: Strict-Transport-Security value: "max-age=15552000; includeSubdomains; preload" virtual_hosts: - name: gcr domains: - gcr.xxx.com routes: - match: prefix: "/" route: cluster: gcr timeout: 600s - name: quay domains: - quay.xxx.com routes: - match: prefix: "/" route: cluster: quay host_rewrite_literal: quay.io - name: docker domains: - docker.xxx.com routes: - match: prefix: "/" route: cluster: dockerhub host_rewrite_literal: registry-1.docker.io http_filters: - name: envoy.filters.http.router typed_config: "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
友情提醒:我這裏使用的是
v3
版本的 API,v2
版本的 API 即將被廢棄,請奔走相告。api
CDS
的配置:緩存
# cds.yaml version_info: "0" resources: - "@type": type.googleapis.com/envoy.config.cluster.v3.Cluster name: gcr connect_timeout: 1s type: strict_dns dns_lookup_family: V4_ONLY lb_policy: ROUND_ROBIN load_assignment: cluster_name: gcr endpoints: - lb_endpoints: - endpoint: address: socket_address: address: gcr.default port_value: 5000 - "@type": type.googleapis.com/envoy.config.cluster.v3.Cluster name: dockerhub connect_timeout: 15s type: logical_dns dns_lookup_family: V4_ONLY dns_resolvers: socket_address: address: 8.8.8.8 port_value: 53 lb_policy: ROUND_ROBIN load_assignment: cluster_name: dockerhub endpoints: - lb_endpoints: - endpoint: address: socket_address: address: registry-1.docker.io port_value: 443 transport_socket: name: envoy.transport_sockets.tls typed_config: "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext sni: registry-1.docker.io - "@type": type.googleapis.com/envoy.config.cluster.v3.Cluster name: quay connect_timeout: 15s type: logical_dns dns_lookup_family: V4_ONLY dns_resolvers: socket_address: address: 8.8.8.8 port_value: 53 lb_policy: ROUND_ROBIN load_assignment: cluster_name: quay endpoints: - lb_endpoints: - endpoint: address: socket_address: address: quay.io port_value: 443 transport_socket: name: envoy.transport_sockets.tls typed_config: "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext sni: quay.io
各個字段的含義我實在是懶得解釋,能夠直接去看上面提到的電子書。bash
配置好了 Envoy 以後,就能夠經過代理服務器拉取 Docker Hub
和 quay.io
的鏡像了。最後來解決 gcr.io 鏡像的難題。
首先須要部署一個私有的 registry,若是你只有一臺服務器(我想大多數人應該只會買一臺吧),可使用 docker-compose
,我這裏是使用 Kubernetes 部署的,首先須要準備一個部署清單:
# registry-proxy.yaml apiVersion: apps/v1 kind: Deployment metadata: name: gcr labels: app: gcr spec: replicas: 1 selector: matchLabels: app: gcr template: metadata: labels: app: gcr spec: nodeSelector: kubernetes.io/hostname: blog-k3s03 tolerations: - key: node-role.kubernetes.io/ingress operator: Exists effect: NoSchedule hostNetwork: false containers: - name: gcr image: findsec/registry-proxy:latest env: - name: PROXY_REMOTE_URL value: https://gcr.io ports: - containerPort: 5000 hostPort: 5000 protocol: TCP volumeMounts: - mountPath: /etc/localtime name: localtime - mountPath: /var/lib/registry name: registry volumes: - name: localtime hostPath: path: /etc/localtime - name: registry hostPath: path: /var/lib/registry --- apiVersion: v1 kind: Service metadata: name: gcr labels: app: gcr spec: sessionAffinity: ClientIP selector: app: gcr ports: - protocol: TCP name: http port: 5000 targetPort: 5000
而後將其部署到 Kubernetes 集羣中:
$ kubectl apply -f registry-proxy.yaml
如今再回過頭來看看 Envoy 的配置中關於 gcr
的部分,先來看看 LDS
:
virtual_hosts: - name: gcr domains: - gcr.xxx.com routes: - match: prefix: "/" route: cluster: gcr timeout: 600s
很簡單,不須要解釋,再來看看 CDS:
- "@type": type.googleapis.com/envoy.config.cluster.v3.Cluster name: gcr connect_timeout: 1s type: strict_dns dns_lookup_family: V4_ONLY lb_policy: ROUND_ROBIN load_assignment: cluster_name: gcr endpoints: - lb_endpoints: - endpoint: address: socket_address: address: gcr.default port_value: 5000
這裏的 address
使用的是 Kubernetes 集羣內部域名,其餘部署方式請本身斟酌。
最後,給服務器換個新內核,開啓 BBR
加速不過度吧?否則你的鏡像拉取仍然是龜速。
如今你就能夠經過代理服務器來拉取公共鏡像了。
對於 Docker Hub 來講,只須要將 docker.io
換成 docker.xxx.com
就好了,好比你想拉取 nginx:alpine
鏡像,可使用下面的命令:
🐳 → docker pull docker.xxx.com/library/nginx:alpine
對於 quay.io
來講,只須要將 quay.io
換成 quay.xxx.com
就好了,好比你想拉取 quay.io/coreos/kube-state-metrics:v1.5.0
鏡像,可使用下面的命令:
🐳 → docker pull quay.xxx.com/coreos/kube-state-metrics:v1.5.0
對於 gcr.io
來講,只須要將 gcr.io
換成 gcr.xxx.com
就好了,好比你想拉取 gcr.io/google-containers/etcd:3.2.24
鏡像,可使用下面的命令:
🐳 → docker pull gcr.xxx.com/google-containers/etcd:3.2.24
固然,Docker 是能夠設置 registry mirror
的,但只支持 Docker Hub
。能夠修改配置文件 /etc/docker/daemon.json
,添加下面的內容:
{ "registry-mirrors": [ "https://docker.xxx.com" ] }
而後重啓 Docker 服務,就能夠直接拉取 Docker Hub 的鏡像了,不須要顯示指定代理服務器的地址,Docker 服務自己會自動經過代理服務器去拉取鏡像。好比:
🐳 → docker pull nginx:alpine 🐳 → docker pull docker.io/library/nginx:alpine
Containerd 就比較簡單了,它支持任意 registry 的 mirror,只須要修改配置文件 /etc/containerd/config.toml
,添加以下的配置:
[plugins.cri.registry.mirrors] [plugins.cri.registry.mirrors."docker.io"] endpoint = ["https://docker.xxx.com"] [plugins.cri.registry.mirrors."quay.io"] endpoint = ["https://quay.xxx.com"] [plugins.cri.registry.mirrors."gcr.io"] endpoint = ["http://gcr.xxx.com"]
重啓 Containerd
服務後,就能夠直接拉取 Docker Hub
、gcr.io
和 quay.io
的鏡像了,不須要修改任何前綴,Containerd 會根據配置自動選擇相應的代理 URL 拉取鏡像。
好了,如今咱們來評估一下這一切的費用。首先你得有一個會魔法的服務器,國內的確定不用考慮了,必須選擇國外的,並且到國內的速度還過得去的,最低最低不會低於 30 人民幣/月 吧。除此以外,你還得擁有一個我的域名,這個價格很差說,總而言之,加起來確定不會低於 30 吧,多數人確定是下不去這個手的。不要緊,我有一個更便宜的方案,我已經部署好了一切,你能夠直接用個人服務,固然我也是本身買的服務器,每月也是要花錢的,若是你真的想用,只須要每個月支付 3 元,以此來保障我每月的服務器費用。固然確定不止你一我的,我可能還會賺點錢,但最多不容許超過 40 人,若是人數特別多,我可能會考慮加服務器。這個須要你本身考慮清楚,有意者掃描下方的二維碼加入交流羣:
若是二維碼已過時,能夠加我微信拉你進羣。
掃一掃下面的二維碼關注微信公衆號,在公衆號中回覆◉加羣◉便可加入咱們的雲原生交流羣,和孫宏亮、張館長、陽明等大佬一塊兒探討雲原生技術