Add wildcard mirror support.

Signed-off-by: Lantao Liu <lantaol@google.com>
This commit is contained in:
Lantao Liu 2019-08-13 01:17:48 -07:00
parent 8021850e91
commit 81ca274c6f
3 changed files with 114 additions and 28 deletions

View File

@ -13,12 +13,23 @@ To configure image registries create/modify the `/etc/containerd/config.toml` as
endpoint = ["https://HostIP1:Port1"]
[plugins.cri.registry.mirrors."test.insecure-registry.io"]
endpoint = ["http://HostIP2:Port2"]
# wildcard matching is supported but not required.
[plugins.cri.registry.mirrors."*"]
endpoint = ["http://HostIP3:Port3"]
```
The default configuration can be generated by `containerd config default > /etc/containerd/config.toml`.
The endpoint is a list that can contain multiple image registry URLs split by commas. When pulling an image
from a registry, containerd will try these endpoint URLs one by one, and use the first working one.
from a registry, containerd will try these endpoint URLs one by one, and use the first working one. Please note
that if the default registry endpoint is not already specified in the endpoint list, it will be automatically
tried at the end with scheme `https` and path `v2`, e.g. `https://gcr.io/v2` for `gcr.io`.
As an example, for the image `gcr.io/library/busybox:latest`, the endpoints are:
* `gcr.io` is configured: endpoints for `gcr.io` + default endpoint `https://gcr.io/v2`.
* `*` is configured, and `gcr.io` is not: endpoints for `*` + default
endpoint `https://gcr.io/v2`.
* None of above is configured: default endpoint `https:/gcr.io/v2`.
After modify this config, you need restart the `containerd` service.

View File

@ -293,11 +293,9 @@ func (c *criService) registryHosts(auth *runtime.AuthConfig) docker.RegistryHost
return func(host string) ([]docker.RegistryHost, error) {
var registries []docker.RegistryHost
// Try mirrors in order, and then try the default registry if not tried.
endpoints, err := addDefaultEndpoint(
c.config.Registry.Mirrors[host].Endpoints, host)
endpoints, err := c.registryEndpoints(host)
if err != nil {
return nil, errors.Wrapf(err, "add default endpoint")
return nil, errors.Wrap(err, "get registry endpoints")
}
for _, e := range endpoints {
u, err := url.Parse(e)
@ -347,9 +345,17 @@ func (c *criService) registryHosts(auth *runtime.AuthConfig) docker.RegistryHost
}
}
// addDefaultEndpoint add default registry endpoint if it does not
// exist in the passed-in endpoint list.
func addDefaultEndpoint(endpoints []string, host string) ([]string, error) {
// registryEndpoints returns endpoints for a given host.
// It adds default registry endpoint if it does not exist in the passed-in endpoint list.
// It also supports wildcard host matching with `*`.
func (c *criService) registryEndpoints(host string) ([]string, error) {
var endpoints []string
_, ok := c.config.Registry.Mirrors[host]
if ok {
endpoints = c.config.Registry.Mirrors[host].Endpoints
} else {
endpoints = c.config.Registry.Mirrors["*"].Endpoints
}
defaultHost, err := docker.DefaultHost(host)
if err != nil {
return nil, errors.Wrap(err, "get default host")

View File

@ -22,6 +22,8 @@ import (
"github.com/stretchr/testify/assert"
runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
criconfig "github.com/containerd/cri/pkg/config"
)
func TestParseAuth(t *testing.T) {
@ -103,16 +105,34 @@ func TestParseAuth(t *testing.T) {
}
}
func TestAddDefaultEndpoint(t *testing.T) {
func TestRegistryEndpoints(t *testing.T) {
for desc, test := range map[string]struct {
endpoints []string
host string
expected []string
mirrors map[string]criconfig.Mirror
host string
expected []string
}{
"default endpoint not in list": {
endpoints: []string{
"https://registry-1.io",
"https://registry-2.io",
"no mirror configured": {
mirrors: map[string]criconfig.Mirror{
"registry-1.io": {
Endpoints: []string{
"https://registry-1.io",
"https://registry-2.io",
},
},
},
host: "registry-3.io",
expected: []string{
"https://registry-3.io",
},
},
"mirror configured": {
mirrors: map[string]criconfig.Mirror{
"registry-3.io": {
Endpoints: []string{
"https://registry-1.io",
"https://registry-2.io",
},
},
},
host: "registry-3.io",
expected: []string{
@ -121,11 +141,50 @@ func TestAddDefaultEndpoint(t *testing.T) {
"https://registry-3.io",
},
},
"default endpoint in list with http": {
endpoints: []string{
"wildcard mirror configured": {
mirrors: map[string]criconfig.Mirror{
"*": {
Endpoints: []string{
"https://registry-1.io",
"https://registry-2.io",
},
},
},
host: "registry-3.io",
expected: []string{
"https://registry-1.io",
"https://registry-2.io",
"http://registry-3.io",
"https://registry-3.io",
},
},
"host should take precedence if both host and wildcard mirrors are configured": {
mirrors: map[string]criconfig.Mirror{
"*": {
Endpoints: []string{
"https://registry-1.io",
},
},
"registry-3.io": {
Endpoints: []string{
"https://registry-2.io",
},
},
},
host: "registry-3.io",
expected: []string{
"https://registry-2.io",
"https://registry-3.io",
},
},
"default endpoint in list with http": {
mirrors: map[string]criconfig.Mirror{
"registry-3.io": {
Endpoints: []string{
"https://registry-1.io",
"https://registry-2.io",
"http://registry-3.io",
},
},
},
host: "registry-3.io",
expected: []string{
@ -135,10 +194,14 @@ func TestAddDefaultEndpoint(t *testing.T) {
},
},
"default endpoint in list with https": {
endpoints: []string{
"https://registry-1.io",
"https://registry-2.io",
"https://registry-3.io",
mirrors: map[string]criconfig.Mirror{
"registry-3.io": {
Endpoints: []string{
"https://registry-1.io",
"https://registry-2.io",
"https://registry-3.io",
},
},
},
host: "registry-3.io",
expected: []string{
@ -148,10 +211,14 @@ func TestAddDefaultEndpoint(t *testing.T) {
},
},
"default endpoint in list with path": {
endpoints: []string{
"https://registry-1.io",
"https://registry-2.io",
"https://registry-3.io/path",
mirrors: map[string]criconfig.Mirror{
"registry-3.io": {
Endpoints: []string{
"https://registry-1.io",
"https://registry-2.io",
"https://registry-3.io/path",
},
},
},
host: "registry-3.io",
expected: []string{
@ -162,7 +229,9 @@ func TestAddDefaultEndpoint(t *testing.T) {
},
} {
t.Logf("TestCase %q", desc)
got, err := addDefaultEndpoint(test.endpoints, test.host)
c := newTestCRIService()
c.config.Registry.Mirrors = test.mirrors
got, err := c.registryEndpoints(test.host)
assert.NoError(t, err)
assert.Equal(t, test.expected, got)
}