Skip to content

Commit

Permalink
Add wildcard mirror support.
Browse files Browse the repository at this point in the history
Signed-off-by: Lantao Liu <lantaol@google.com>
  • Loading branch information
Random-Liu committed Aug 13, 2019
1 parent 8021850 commit 81ca274
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 27 deletions.
13 changes: 12 additions & 1 deletion docs/registry.md
Expand Up @@ -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.

Expand Down
20 changes: 13 additions & 7 deletions pkg/server/image_pull.go
Expand Up @@ -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)
Expand Down Expand Up @@ -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")
Expand Down
107 changes: 88 additions & 19 deletions pkg/server/image_pull_test.go
Expand Up @@ -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) {
Expand Down Expand Up @@ -103,16 +105,50 @@ 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{
"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{
"https://registry-1.io",
"https://registry-2.io",
"https://registry-3.io",
},
},
"wildcard mirror configured": {
mirrors: map[string]criconfig.Mirror{
"*": {
Endpoints: []string{
"https://registry-1.io",
"https://registry-2.io",
},
},
},
host: "registry-3.io",
expected: []string{
Expand All @@ -121,11 +157,34 @@ func TestAddDefaultEndpoint(t *testing.T) {
"https://registry-3.io",
},
},
"default endpoint in list with http": {
endpoints: []string{
"https://registry-1.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",
"http://registry-3.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{
Expand All @@ -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{
Expand All @@ -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{
Expand All @@ -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)
}
Expand Down

0 comments on commit 81ca274

Please sign in to comment.