feat: use readonly containers

Containers created with `talosctl cluster create` are ran with readonly
filesystem. This more accurately mimics standard Talos.

Signed-off-by: Andrew Rynhard <andrew@rynhard.io>
This commit is contained in:
Andrew Rynhard 2022-10-06 13:49:12 -07:00
parent d210338e33
commit b7b1d4fd6a
No known key found for this signature in database
GPG Key ID: A9DA1EDAB9DEF945
6 changed files with 60 additions and 21 deletions

View File

@ -120,7 +120,8 @@ RUN --mount=type=cache,target=/.cache go install github.com/planetscale/vtprotob
&& mv /go/bin/protoc-gen-go-vtproto /toolchain/go/bin/protoc-gen-go-vtproto
RUN --mount=type=cache,target=/.cache go install golang.org/x/vuln/cmd/govulncheck@latest \
&& mv /go/bin/govulncheck /toolchain/go/bin/govulncheck
RUN curl -sfL https://github.com/uber/prototool/releases/download/v1.10.0/prototool-Linux-x86_64.tar.gz | tar -xz --strip-components=2 -C /toolchain/bin prototool/bin/prototool
RUN --mount=type=cache,target=/.cache go install github.com/uber/prototool/cmd/prototool@v1.10.0 \
&& mv /go/bin/prototool /toolchain/go/bin/prototool
COPY ./hack/docgen /go/src/github.com/talos-systems/talos-hack-docgen
RUN --mount=type=cache,target=/.cache cd /go/src/github.com/talos-systems/talos-hack-docgen \
&& go build -o docgen . \

View File

@ -842,7 +842,7 @@ func MountOverlayFilesystems(seq runtime.Sequence, data interface{}) (runtime.Ta
// SetupSharedFilesystems represents the SetupSharedFilesystems task.
func SetupSharedFilesystems(seq runtime.Sequence, data interface{}) (runtime.TaskExecutionFunc, string) {
return func(ctx context.Context, logger *log.Logger, r runtime.Runtime) (err error) {
targets := []string{"/", "/var/lib/kubelet", "/etc/cni", "/run"}
targets := []string{"/", "/var", "/etc/cni", "/run"}
for _, t := range targets {
if err = unix.Mount("", t, "", unix.MS_SHARED|unix.MS_REC, ""); err != nil {
return err

View File

@ -6,6 +6,8 @@ package mount
import (
"golang.org/x/sys/unix"
"github.com/talos-systems/talos/pkg/machinery/constants"
)
// OverlayMountPoints returns the mountpoints required to boot the system.
@ -13,15 +15,7 @@ import (
func OverlayMountPoints() (mountpoints *Points, err error) {
mountpoints = NewMountPoints()
overlays := []string{
"/etc/kubernetes",
"/etc/cni",
"/usr/libexec/kubernetes",
"/usr/etc/udev",
"/opt",
}
for _, target := range overlays {
for _, target := range constants.Overlays {
mountpoint := NewMountPoint("", target, "", unix.MS_I_VERSION, "", WithFlags(Overlay))
mountpoints.Set(target, mountpoint)
}

View File

@ -780,3 +780,12 @@ const (
HostnameKey = "hostname"
MacKey = "mac"
)
// Overlays is the set of paths to create overlay mounts for.
var Overlays = []string{
"/etc/cni",
"/etc/kubernetes",
"/usr/libexec/kubernetes",
"/usr/etc/udev",
"/opt",
}

View File

@ -15,6 +15,7 @@ import (
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/filters"
"github.com/docker/docker/api/types/mount"
"github.com/docker/docker/api/types/network"
"github.com/docker/go-connections/nat"
"github.com/hashicorp/go-multierror"
@ -84,17 +85,26 @@ func (p *provisioner) createNode(ctx context.Context, clusterReq provision.Clust
"talos.cluster.name": clusterReq.Name,
"talos.type": nodeReq.Type.String(),
},
Volumes: map[string]struct{}{
"/var/lib/containerd": {},
"/var/lib/kubelet": {},
"/etc/cni": {},
"/run": {},
"/system": {},
},
}
// Create the host config.
mounts := []mount.Mount{}
for _, path := range []string{"/run", "/system", "/tmp"} {
mounts = append(mounts, mount.Mount{
Type: mount.TypeTmpfs,
Target: path,
})
}
for _, path := range append(constants.Overlays, "/var", "/system/state") {
mounts = append(mounts, mount.Mount{
Type: mount.TypeVolume,
Target: path,
})
}
hostConfig := &container.HostConfig{
Privileged: true,
SecurityOpt: []string{"seccomp:unconfined"},
@ -102,6 +112,8 @@ func (p *provisioner) createNode(ctx context.Context, clusterReq provision.Clust
NanoCPUs: nodeReq.NanoCPUs,
Memory: nodeReq.Memory,
},
ReadonlyRootfs: true,
Mounts: mounts,
}
if !clusterReq.Network.DockerDisableIPv6 {
@ -139,8 +151,6 @@ func (p *provisioner) createNode(ctx context.Context, clusterReq provision.Clust
hostConfig.PortBindings = generatedPortMap.portBindings
containerConfig.Volumes[constants.EtcdDataPath] = struct{}{}
if nodeReq.IPs == nil {
return provision.NodeInfo{}, errors.New("an IP address must be provided when creating a controlplane node")
}

View File

@ -1,7 +1,7 @@
---
title: Docker
description: "Creating Talos Kubernetes cluster using Docker."
aliases:
aliases:
- ../../../local-platforms/docker
---
@ -53,3 +53,28 @@ To cleanup, run:
```bash
talosctl cluster destroy
```
## Running Talos in Docker Manually
To run Talos in a container manually, run:
```bash
docker run --rm -it \
--name tutorial \
--hostname talos-cp \
--read-only \
--privileged \
--security-opt seccomp=unconfined \
--mount type=tmpfs,destination=/run \
--mount type=tmpfs,destination=/system \
--mount type=tmpfs,destination=/tmp \
--mount type=volume,destination=/system/state \
--mount type=volume,destination=/var \
--mount type=volume,destination=/etc/cni \
--mount type=volume,destination=/etc/kubernetes \
--mount type=volume,destination=/usr/libexec/kubernetes \
--mount type=volume,destination=/usr/etc/udev \
--mount type=volume,destination=/opt \
-e PLATFORM=container \
ghcr.io/siderolabs/talos:v1.3.0
```