Skip to content

Commit

Permalink
fix: add support for a fallback '*' mirror configuration
Browse files Browse the repository at this point in the history
Talos always supported that, but CRI config lacked support for it.

Now with recent containerd the new `_default` host is used as a
fallback, so this re-enables the support and updates the docs.

See containerd/containerd#8065

Signed-off-by: Andrey Smirnov <andrey.smirnov@talos-systems.com>
  • Loading branch information
smira committed Feb 16, 2023
1 parent dcd4eb1 commit 6e8f135
Show file tree
Hide file tree
Showing 8 changed files with 147 additions and 32 deletions.
16 changes: 16 additions & 0 deletions hack/release.toml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,22 @@ These APIs are available via new `talosctl etcd` sub-commands:
* `talosctl etcd status`
See also [etcd maintenance guide](https://talos.dev/v1.4/advanced/etcd-maintenance/).
"""

[notes.crihosts]
title = "Registry Mirror Catch-All Option"
description="""\
Talos now supports a catch-all option for registry mirrors:
```yaml
machine:
registries:
mirrors:
docker.io:
- https://registry-1.docker.io/
"*":
- https://my-registry.example.com/
```
"""

[make_deps]
Expand Down
11 changes: 10 additions & 1 deletion internal/pkg/containers/cri/containerd/hosts.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ type HostsFile struct {

// GenerateHosts generates a structure describing contents of the containerd hosts configuration.
//
//nolint:gocyclo
//nolint:gocyclo,cyclop
func GenerateHosts(cfg config.Registries, basePath string) (*HostsConfig, error) {
config := &HostsConfig{
Directories: map[string]*HostsDirectory{},
Expand Down Expand Up @@ -183,6 +183,11 @@ func GenerateHosts(cfg config.Registries, basePath string) (*HostsConfig, error)
}
}

if hostname == "*" {
// no way to generate TLS config for wildcard host
return nil, fmt.Errorf("wildcard host TLS configuration is not supported")
}

directory := &HostsDirectory{}

defaultHost, err := docker.DefaultHost(hostname)
Expand Down Expand Up @@ -221,6 +226,10 @@ func GenerateHosts(cfg config.Registries, basePath string) (*HostsConfig, error)

// hostDirectory converts ":port" to "_port_" in directory names.
func hostDirectory(host string) string {
if host == "*" {
return "_default"
}

idx := strings.LastIndex(host, ":")
if idx > 0 {
return host[:idx] + "_" + host[idx+1:] + "_"
Expand Down
81 changes: 81 additions & 0 deletions internal/pkg/containers/cri/containerd/hosts_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,9 @@ func TestGenerateHostsWithoutTLS(t *testing.T) {
"docker.io": {
MirrorEndpoints: []string{"https://registry-1.docker.io", "https://registry-2.docker.io"},
},
"*": {
MirrorEndpoints: []string{"https://my-registry"},
},
},
config: map[string]*v1alpha1.RegistryConfig{
"some.host:123": {
Expand Down Expand Up @@ -142,6 +145,84 @@ func TestGenerateHostsWithoutTLS(t *testing.T) {
},
},
},
"_default": {
Files: []*containerd.HostsFile{
{
Name: "hosts.toml",
Mode: 0o600,
Contents: []byte("\n[host]\n\n [host.\"https://my-registry\"]\n capabilities = [\"pull\", \"resolve\"]\n"),
},
},
},
},
}, result)
}

func TestGenerateHostsTLSWildcardWrong(t *testing.T) {
cfg := &mockConfig{
mirrors: map[string]*v1alpha1.RegistryMirrorConfig{},
config: map[string]*v1alpha1.RegistryConfig{
"*": {
RegistryTLS: &v1alpha1.RegistryTLSConfig{
TLSCA: []byte("allcert"),
},
},
},
}

_, err := containerd.GenerateHosts(cfg, "/etc/cri/conf.d/hosts")
assert.EqualError(t, err, "wildcard host TLS configuration is not supported")
}

func TestGenerateHostsTLSWildcard(t *testing.T) {
cfg := &mockConfig{
mirrors: map[string]*v1alpha1.RegistryMirrorConfig{
"*": {
MirrorEndpoints: []string{"https://my-registry1", "https://my-registry2"},
},
},
config: map[string]*v1alpha1.RegistryConfig{
"my-registry1": {
RegistryTLS: &v1alpha1.RegistryTLSConfig{
TLSCA: []byte("allcert"),
},
},
},
}

result, err := containerd.GenerateHosts(cfg, "/etc/cri/conf.d/hosts")
require.NoError(t, err)

assert.Equal(t, &containerd.HostsConfig{
Directories: map[string]*containerd.HostsDirectory{
"_default": {
Files: []*containerd.HostsFile{
{
Name: "my-registry1-ca.crt",
Mode: 0o600,
Contents: []byte("allcert"),
},
{
Name: "hosts.toml",
Mode: 0o600,
Contents: []byte("\n[host]\n\n [host.\"https://my-registry1\"]\n ca = \"/etc/cri/conf.d/hosts/_default/my-registry1-ca.crt\"\n capabilities = [\"pull\", \"resolve\"]\n\n [host.\"https://my-registry2\"]\n capabilities = [\"pull\", \"resolve\"]\n"), //nolint:lll
},
},
},
"my-registry1": {
Files: []*containerd.HostsFile{
{
Name: "my-registry1-ca.crt",
Mode: 0o600,
Contents: []byte("allcert"),
},
{
Name: "hosts.toml",
Mode: 0o600,
Contents: []byte("\n[host]\n\n [host.\"https://my-registry1\"]\n ca = \"/etc/cri/conf.d/hosts/my-registry1/my-registry1-ca.crt\"\n"),
},
},
},
},
}, result)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1868,9 +1868,9 @@
"registries": {
"$ref": "#/$defs/RegistriesConfig",
"title": "registries",
"description": "Used to configure the machine’s container image registry mirrors.\n\nAutomatically generates matching CRI configuration for registry mirrors.\n\nThe mirrors section allows to redirect requests for images to non-default registry,\nwhich might be local registry or caching mirror.\n\nThe config section provides a way to authenticate to the registry with TLS client\nidentity, provide registry CA, or authentication information.\nAuthentication information has same meaning with the corresponding field in .docker/config.json.\n\nSee also matching configuration for CRI containerd plugin.\n",
"markdownDescription": "Used to configure the machine's container image registry mirrors.\n\nAutomatically generates matching CRI configuration for registry mirrors.\n\nThe `mirrors` section allows to redirect requests for images to non-default registry,\nwhich might be local registry or caching mirror.\n\nThe `config` section provides a way to authenticate to the registry with TLS client\nidentity, provide registry CA, or authentication information.\nAuthentication information has same meaning with the corresponding field in [`.docker/config.json`](https://docs.docker.com/engine/api/v1.41/#section/Authentication).\n\nSee also matching configuration for [CRI containerd plugin](https://github.com/containerd/cri/blob/master/docs/registry.md).",
"x-intellij-html-description": "\u003cp\u003eUsed to configure the machine\u0026rsquo;s container image registry mirrors.\u003c/p\u003e\n\n\u003cp\u003eAutomatically generates matching CRI configuration for registry mirrors.\u003c/p\u003e\n\n\u003cp\u003eThe \u003ccode\u003emirrors\u003c/code\u003e section allows to redirect requests for images to non-default registry,\nwhich might be local registry or caching mirror.\u003c/p\u003e\n\n\u003cp\u003eThe \u003ccode\u003econfig\u003c/code\u003e section provides a way to authenticate to the registry with TLS client\nidentity, provide registry CA, or authentication information.\nAuthentication information has same meaning with the corresponding field in \u003ca href=\"https://docs.docker.com/engine/api/v1.41/#section/Authentication\" target=\"_blank\"\u003e\u003ccode\u003e.docker/config.json\u003c/code\u003e\u003c/a\u003e.\u003c/p\u003e\n\n\u003cp\u003eSee also matching configuration for \u003ca href=\"https://github.com/containerd/cri/blob/master/docs/registry.md\" target=\"_blank\"\u003eCRI containerd plugin\u003c/a\u003e.\u003c/p\u003e\n"
"description": "Used to configure the machine’s container image registry mirrors.\n\nAutomatically generates matching CRI configuration for registry mirrors.\n\nThe mirrors section allows to redirect requests for images to a non-default registry,\nwhich might be a local registry or a caching mirror.\n\nThe config section provides a way to authenticate to the registry with TLS client\nidentity, provide registry CA, or authentication information.\nAuthentication information has same meaning with the corresponding field in .docker/config.json.\n\nSee also matching configuration for CRI containerd plugin.\n",
"markdownDescription": "Used to configure the machine's container image registry mirrors.\n\nAutomatically generates matching CRI configuration for registry mirrors.\n\nThe `mirrors` section allows to redirect requests for images to a non-default registry,\nwhich might be a local registry or a caching mirror.\n\nThe `config` section provides a way to authenticate to the registry with TLS client\nidentity, provide registry CA, or authentication information.\nAuthentication information has same meaning with the corresponding field in [`.docker/config.json`](https://docs.docker.com/engine/api/v1.41/#section/Authentication).\n\nSee also matching configuration for [CRI containerd plugin](https://github.com/containerd/cri/blob/master/docs/registry.md).",
"x-intellij-html-description": "\u003cp\u003eUsed to configure the machine\u0026rsquo;s container image registry mirrors.\u003c/p\u003e\n\n\u003cp\u003eAutomatically generates matching CRI configuration for registry mirrors.\u003c/p\u003e\n\n\u003cp\u003eThe \u003ccode\u003emirrors\u003c/code\u003e section allows to redirect requests for images to a non-default registry,\nwhich might be a local registry or a caching mirror.\u003c/p\u003e\n\n\u003cp\u003eThe \u003ccode\u003econfig\u003c/code\u003e section provides a way to authenticate to the registry with TLS client\nidentity, provide registry CA, or authentication information.\nAuthentication information has same meaning with the corresponding field in \u003ca href=\"https://docs.docker.com/engine/api/v1.41/#section/Authentication\" target=\"_blank\"\u003e\u003ccode\u003e.docker/config.json\u003c/code\u003e\u003c/a\u003e.\u003c/p\u003e\n\n\u003cp\u003eSee also matching configuration for \u003ca href=\"https://github.com/containerd/cri/blob/master/docs/registry.md\" target=\"_blank\"\u003eCRI containerd plugin\u003c/a\u003e.\u003c/p\u003e\n"
},
"systemDiskEncryption": {
"$ref": "#/$defs/SystemDiskEncryptionConfig",
Expand Down Expand Up @@ -2254,9 +2254,9 @@
},
"type": "object",
"title": "mirrors",
"description": "Specifies mirror configuration for each registry.\nThis setting allows to use local pull-through caching registires,\nair-gapped installations, etc.\n\nRegistry name is the first segment of image identifier, with ‘docker.io’\nbeing default one.\n",
"markdownDescription": "Specifies mirror configuration for each registry.\nThis setting allows to use local pull-through caching registires,\nair-gapped installations, etc.\n\nRegistry name is the first segment of image identifier, with 'docker.io'\nbeing default one.",
"x-intellij-html-description": "\u003cp\u003eSpecifies mirror configuration for each registry.\nThis setting allows to use local pull-through caching registires,\nair-gapped installations, etc.\u003c/p\u003e\n\n\u003cp\u003eRegistry name is the first segment of image identifier, with \u0026lsquo;docker.io\u0026rsquo;\nbeing default one.\u003c/p\u003e\n"
"description": "Specifies mirror configuration for each registry host namespace.\nThis setting allows to configure local pull-through caching registires,\nair-gapped installations, etc.\n\nFor example, when pulling an image with the reference example.com:123/image:v1,\nthe example.com:123 key will be used to lookup the mirror configuration.\n\nOptionally the * key can be used to configure a fallback mirror.\n\nRegistry name is the first segment of image identifier, with ‘docker.io’\nbeing default one.\n",
"markdownDescription": "Specifies mirror configuration for each registry host namespace.\nThis setting allows to configure local pull-through caching registires,\nair-gapped installations, etc.\n\nFor example, when pulling an image with the reference `example.com:123/image:v1`,\nthe `example.com:123` key will be used to lookup the mirror configuration.\n\nOptionally the `*` key can be used to configure a fallback mirror.\n\nRegistry name is the first segment of image identifier, with 'docker.io'\nbeing default one.",
"x-intellij-html-description": "\u003cp\u003eSpecifies mirror configuration for each registry host namespace.\nThis setting allows to configure local pull-through caching registires,\nair-gapped installations, etc.\u003c/p\u003e\n\n\u003cp\u003eFor example, when pulling an image with the reference \u003ccode\u003eexample.com:123/image:v1\u003c/code\u003e,\nthe \u003ccode\u003eexample.com:123\u003c/code\u003e key will be used to lookup the mirror configuration.\u003c/p\u003e\n\n\u003cp\u003eOptionally the \u003ccode\u003e*\u003c/code\u003e key can be used to configure a fallback mirror.\u003c/p\u003e\n\n\u003cp\u003eRegistry name is the first segment of image identifier, with \u0026lsquo;docker.io\u0026rsquo;\nbeing default one.\u003c/p\u003e\n"
},
"config": {
"patternProperties": {
Expand All @@ -2266,9 +2266,9 @@
},
"type": "object",
"title": "config",
"description": "Specifies TLS \u0026amp; auth configuration for HTTPS image registries.\nMutual TLS can be enabled with ‘clientIdentity’ option.\n\nTLS configuration can be skipped if registry has trusted\nserver certificate.\n",
"markdownDescription": "Specifies TLS \u0026 auth configuration for HTTPS image registries.\nMutual TLS can be enabled with 'clientIdentity' option.\n\nTLS configuration can be skipped if registry has trusted\nserver certificate.",
"x-intellij-html-description": "\u003cp\u003eSpecifies TLS \u0026amp; auth configuration for HTTPS image registries.\nMutual TLS can be enabled with \u0026lsquo;clientIdentity\u0026rsquo; option.\u003c/p\u003e\n\n\u003cp\u003eTLS configuration can be skipped if registry has trusted\nserver certificate.\u003c/p\u003e\n"
"description": "Specifies TLS \u0026amp; auth configuration for HTTPS image registries.\nMutual TLS can be enabled with ‘clientIdentity’ option.\n\nThe full hostname and port (if not using a default port 443)\nshould be used as the key.\nThe fallback key * can’t be used for TLS configuration.\n\nTLS configuration can be skipped if registry has trusted\nserver certificate.\n",
"markdownDescription": "Specifies TLS \u0026 auth configuration for HTTPS image registries.\nMutual TLS can be enabled with 'clientIdentity' option.\n\nThe full hostname and port (if not using a default port 443)\nshould be used as the key.\nThe fallback key `*` can't be used for TLS configuration.\n\nTLS configuration can be skipped if registry has trusted\nserver certificate.",
"x-intellij-html-description": "\u003cp\u003eSpecifies TLS \u0026amp; auth configuration for HTTPS image registries.\nMutual TLS can be enabled with \u0026lsquo;clientIdentity\u0026rsquo; option.\u003c/p\u003e\n\n\u003cp\u003eThe full hostname and port (if not using a default port 443)\nshould be used as the key.\nThe fallback key \u003ccode\u003e*\u003c/code\u003e can\u0026rsquo;t be used for TLS configuration.\u003c/p\u003e\n\n\u003cp\u003eTLS configuration can be skipped if registry has trusted\nserver certificate.\u003c/p\u003e\n"
}
},
"additionalProperties": false,
Expand Down
17 changes: 13 additions & 4 deletions pkg/machinery/config/types/v1alpha1/v1alpha1_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -805,8 +805,8 @@ type MachineConfig struct {
//
// Automatically generates matching CRI configuration for registry mirrors.
//
// The `mirrors` section allows to redirect requests for images to non-default registry,
// which might be local registry or caching mirror.
// The `mirrors` section allows to redirect requests for images to a non-default registry,
// which might be a local registry or a caching mirror.
//
// The `config` section provides a way to authenticate to the registry with TLS client
// identity, provide registry CA, or authentication information.
Expand Down Expand Up @@ -1513,10 +1513,15 @@ type TimeConfig struct {
// RegistriesConfig represents the image pull options.
type RegistriesConfig struct {
// description: |
// Specifies mirror configuration for each registry.
// This setting allows to use local pull-through caching registires,
// Specifies mirror configuration for each registry host namespace.
// This setting allows to configure local pull-through caching registires,
// air-gapped installations, etc.
//
// For example, when pulling an image with the reference `example.com:123/image:v1`,
// the `example.com:123` key will be used to lookup the mirror configuration.
//
// Optionally the `*` key can be used to configure a fallback mirror.
//
// Registry name is the first segment of image identifier, with 'docker.io'
// being default one.
// examples:
Expand All @@ -1526,6 +1531,10 @@ type RegistriesConfig struct {
// Specifies TLS & auth configuration for HTTPS image registries.
// Mutual TLS can be enabled with 'clientIdentity' option.
//
// The full hostname and port (if not using a default port 443)
// should be used as the key.
// The fallback key `*` can't be used for TLS configuration.
//
// TLS configuration can be skipped if registry has trusted
// server certificate.
// examples:
Expand Down

0 comments on commit 6e8f135

Please sign in to comment.