Skip to content

Commit

Permalink
refactor: move apid, routerd, timed and trustd to single executable
Browse files Browse the repository at this point in the history
This removes container images for the aforementioned services, they are
now built into `machined` executable which launches one or another
service based on `argv[0]`.

Containers are started with rootfs directory which contains only a
single executable file for the service.

This creates rootfs on squashfs for each container in
`/opt/<container>`.

Service `networkd` is not touched as it's handled in #3350.

This removes all the image imports, snapshots and other things which
were associated with the existing way to run containers.

Signed-off-by: Andrey Smirnov <smirnov.andrey@gmail.com>
  • Loading branch information
smira authored and talos-bot committed Mar 23, 2021
1 parent 89a4b09 commit ac87647
Show file tree
Hide file tree
Showing 15 changed files with 115 additions and 158 deletions.
53 changes: 11 additions & 42 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ RUN chmod +x /init
FROM scratch AS init
COPY --from=init-build /init /init

# The machined target builds the machined image.
# The machined target builds the machined binary.

FROM base AS machined-build
ARG SHA
Expand All @@ -176,9 +176,10 @@ RUN chmod +x /machined
FROM scratch AS machined
COPY --from=machined-build /machined /machined

# The timed target builds the timed image.
# The timed target builds the timed binary.

FROM base AS timed-build

ARG SHA
ARG TAG
ARG PKGS
Expand All @@ -188,15 +189,7 @@ WORKDIR /src/internal/app/timed
RUN --mount=type=cache,target=/.cache/go-build go build -ldflags "-s -w -X ${VERSION_PKG}.Name=Server -X ${VERSION_PKG}.SHA=${SHA} -X ${VERSION_PKG}.Tag=${TAG} -X ${VERSION_PKG}.PkgsVersion=${PKGS} -X ${VERSION_PKG}.ExtrasVersion=${EXTRAS}" -o /timed
RUN chmod +x /timed

FROM base AS timed-image
ARG TAG
ARG USERNAME
COPY --from=timed-build /timed /scratch/timed
WORKDIR /scratch
RUN printf "FROM scratch\nCOPY ./timed /timed\nENTRYPOINT [\"/timed\"]" > Dockerfile
RUN --security=insecure img build --tag ${USERNAME}/timed:${TAG} --output type=docker,dest=/timed.tar --no-console .

# The apid target builds the api image.
# The apid target builds the apid binary.

FROM base AS apid-build
ARG SHA
Expand All @@ -208,15 +201,7 @@ WORKDIR /src/internal/app/apid
RUN --mount=type=cache,target=/.cache/go-build go build -ldflags "-s -w -X ${VERSION_PKG}.Name=Server -X ${VERSION_PKG}.SHA=${SHA} -X ${VERSION_PKG}.Tag=${TAG} -X ${VERSION_PKG}.PkgsVersion=${PKGS} -X ${VERSION_PKG}.ExtrasVersion=${EXTRAS}" -o /apid
RUN chmod +x /apid

FROM base AS apid-image
ARG TAG
ARG USERNAME
COPY --from=apid-build /apid /scratch/apid
WORKDIR /scratch
RUN printf "FROM scratch\nCOPY ./apid /apid\nENTRYPOINT [\"/apid\"]" > Dockerfile
RUN --security=insecure img build --tag ${USERNAME}/apid:${TAG} --output type=docker,dest=/apid.tar --no-console .

# The trustd target builds the trustd image.
# The trustd target builds the trustd binary.

FROM base AS trustd-build
ARG SHA
Expand All @@ -228,15 +213,7 @@ WORKDIR /src/internal/app/trustd
RUN --mount=type=cache,target=/.cache/go-build go build -ldflags "-s -w -X ${VERSION_PKG}.Name=Server -X ${VERSION_PKG}.SHA=${SHA} -X ${VERSION_PKG}.Tag=${TAG} -X ${VERSION_PKG}.PkgsVersion=${PKGS} -X ${VERSION_PKG}.ExtrasVersion=${EXTRAS}" -o /trustd
RUN chmod +x /trustd

FROM base AS trustd-image
ARG TAG
ARG USERNAME
COPY --from=trustd-build /trustd /scratch/trustd
WORKDIR /scratch
RUN printf "FROM scratch\nCOPY ./trustd /trustd\nENTRYPOINT [\"/trustd\"]" > Dockerfile
RUN --security=insecure img build --tag ${USERNAME}/trustd:${TAG} --output type=docker,dest=/trustd.tar --no-console .

# The routerd target builds the routerd image.
# The routerd target builds the routerd binary.

FROM base AS routerd-build
ARG SHA
Expand All @@ -248,15 +225,6 @@ WORKDIR /src/internal/app/routerd
RUN --mount=type=cache,target=/.cache/go-build go build -ldflags "-s -w -X ${VERSION_PKG}.Name=Server -X ${VERSION_PKG}.SHA=${SHA} -X ${VERSION_PKG}.Tag=${TAG} -X ${VERSION_PKG}.PkgsVersion=${PKGS} -X ${VERSION_PKG}.ExtrasVersion=${EXTRAS}" -o /routerd
RUN chmod +x /routerd

FROM base AS routerd-image
ARG TAG
ARG USERNAME
COPY --from=routerd-build /routerd /scratch/routerd
WORKDIR /scratch
RUN printf "FROM scratch\nCOPY ./routerd /routerd\nENTRYPOINT [\"/routerd\"]" > Dockerfile
RUN --security=insecure img build --tag ${USERNAME}/routerd:${TAG} --output type=docker,dest=/routerd.tar --no-console .


# The talosctl targets build the talosctl binaries.

FROM base AS talosctl-linux-amd64-build
Expand Down Expand Up @@ -371,10 +339,6 @@ COPY --from=pkg-util-linux /lib/libmount.* /rootfs/lib/
COPY --from=pkg-kmod /usr/lib/libkmod.* /rootfs/lib/
COPY --from=pkg-kernel /lib/modules /rootfs/lib/modules
COPY --from=machined /machined /rootfs/sbin/init
COPY --from=apid-image /apid.tar /rootfs/usr/images/
COPY --from=timed-image /timed.tar /rootfs/usr/images/
COPY --from=trustd-image /trustd.tar /rootfs/usr/images/
COPY --from=routerd-image /routerd.tar /rootfs/usr/images/
# NB: We run the cleanup step before creating extra directories, files, and
# symlinks to avoid accidentally cleaning them up.
COPY ./hack/cleanup.sh /toolchain/bin/cleanup.sh
Expand All @@ -389,6 +353,11 @@ RUN ln -s /etc/ssl /rootfs/etc/pki
RUN ln -s /etc/ssl /rootfs/usr/share/ca-certificates
RUN ln -s /etc/ssl /rootfs/usr/local/share/ca-certificates
RUN ln -s /etc/ssl /rootfs/etc/ca-certificates
RUN mkdir -pv /rootfs/opt/{apid,routerd,timed,trustd}
RUN ln /rootfs/sbin/init /rootfs/opt/apid/apid
RUN ln /rootfs/sbin/init /rootfs/opt/routerd/routerd
RUN ln /rootfs/sbin/init /rootfs/opt/timed/timed
RUN ln /rootfs/sbin/init /rootfs/opt/trustd/trustd

FROM rootfs-base AS rootfs-squashfs
RUN mksquashfs /rootfs /rootfs.sqsh -all-root -noappend -comp xz -Xdict-size 100% -no-progress
Expand Down
6 changes: 6 additions & 0 deletions hack/release.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ preface = """\
description = """\
* u-boot version was updated to fix the boot and USB issues on Raspberry Pi 4 8GiB version.
* added support for Rock Pi 4.
"""

[notes.optimize]
title = "Optmizations"
descriptions = """\
* Talos `system` services now run without container images on initramfs from the single executable; this change reduces RAM usage, initramfs size and boot time..
"""

[make_deps]
Expand Down
11 changes: 3 additions & 8 deletions internal/app/apid/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

package main
package apid

import (
"flag"
"log"
"regexp"
"runtime"
"strings"

"github.com/talos-systems/grpc-proxy/proxy"
Expand All @@ -31,19 +30,15 @@ var (
useK8sEndpoints *bool
)

func init() {
// Explicitly disable memory profiling to save around 1.4MiB of memory.
runtime.MemProfileRate = 0

// Main is the entrypoint of apid.
func Main() {
log.SetFlags(log.Lshortfile | log.Ldate | log.Lmicroseconds | log.Ltime)

endpoints = flag.String("endpoints", "", "the static list of IPs of the control plane nodes")
useK8sEndpoints = flag.Bool("use-kubernetes-endpoints", false, "use Kubernetes master node endpoints as control plane endpoints")

flag.Parse()
}

func main() {
if err := startup.RandSeed(); err != nil {
log.Fatalf("failed to seed RNG: %v", err)
}
Expand Down
24 changes: 24 additions & 0 deletions internal/app/machined/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,15 @@ import (
"golang.org/x/net/http/httpproxy"
"golang.org/x/sys/unix"

"github.com/talos-systems/talos/internal/app/apid"
"github.com/talos-systems/talos/internal/app/machined/pkg/runtime"
v1alpha1runtime "github.com/talos-systems/talos/internal/app/machined/pkg/runtime/v1alpha1"
"github.com/talos-systems/talos/internal/app/machined/pkg/runtime/v1alpha1/bootloader"
"github.com/talos-systems/talos/internal/app/machined/pkg/system"
"github.com/talos-systems/talos/internal/app/machined/pkg/system/services"
"github.com/talos-systems/talos/internal/app/routerd"
"github.com/talos-systems/talos/internal/app/timed"
"github.com/talos-systems/talos/internal/app/trustd"
"github.com/talos-systems/talos/internal/pkg/mount"
"github.com/talos-systems/talos/pkg/machinery/api/common"
"github.com/talos-systems/talos/pkg/machinery/api/machine"
Expand Down Expand Up @@ -260,6 +264,26 @@ func run() error {
}

func main() {
switch os.Args[0] {
case "/apid":
apid.Main()

return
case "/routerd":
routerd.Main()

return
case "/timed":
timed.Main()

return
case "/trustd":
trustd.Main()

return
default:
}

// Setup panic handler.
defer recovery()

Expand Down
48 changes: 36 additions & 12 deletions internal/app/machined/pkg/system/runner/containerd/containerd.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,13 @@ func (c *containerdRunner) Open(ctx context.Context) error {
return err
}

image, err := c.client.GetImage(c.ctx, c.opts.ContainerImage)
if err != nil {
return err
var image containerd.Image

if c.opts.ContainerImage != "" {
image, err = c.client.GetImage(c.ctx, c.opts.ContainerImage)
if err != nil {
return err
}
}

// See if there's previous container/snapshot to clean up
Expand Down Expand Up @@ -223,25 +227,45 @@ func (c *containerdRunner) Stop() error {
}

func (c *containerdRunner) newContainerOpts(image containerd.Image, specOpts []oci.SpecOpts) []containerd.NewContainerOpts {
containerOpts := []containerd.NewContainerOpts{
containerd.WithImage(image),
containerd.WithNewSnapshot(c.args.ID, image),
containerd.WithNewSpec(specOpts...),
containerOpts := []containerd.NewContainerOpts{}

if image != nil {
containerOpts = append(containerOpts,
containerd.WithImage(image),
containerd.WithNewSnapshot(c.args.ID, image),
)
}
containerOpts = append(containerOpts, c.opts.ContainerOpts...)

containerOpts = append(containerOpts,
containerd.WithNewSpec(specOpts...),
)

containerOpts = append(containerOpts,
c.opts.ContainerOpts...,
)

return containerOpts
}

func (c *containerdRunner) newOCISpecOpts(image oci.Image) []oci.SpecOpts {
specOpts := []oci.SpecOpts{
oci.WithImageConfig(image),
specOpts := []oci.SpecOpts{}

if image != nil {
specOpts = append(specOpts,
oci.WithImageConfig(image),
)
}

specOpts = append(specOpts,
oci.WithProcessArgs(c.args.ProcessArgs...),
oci.WithEnv(c.opts.Env),
oci.WithHostHostsFile,
oci.WithHostResolvconf,
}
specOpts = append(specOpts, c.opts.OCISpecOpts...)
)

specOpts = append(specOpts,
c.opts.OCISpecOpts...,
)

return specOpts
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -368,52 +368,6 @@ func (suite *ContainerdSuite) TestStopSigKill() {
<-done
}

func (suite *ContainerdSuite) TestImportSuccess() {
reqs := []*containerdrunner.ImportRequest{
{
Path: "/usr/images/timed.tar",
Options: []containerd.ImportOpt{
containerd.WithIndexName("testtalos/timed"),
},
},
{
Path: "/usr/images/trustd.tar",
Options: []containerd.ImportOpt{
containerd.WithIndexName("testtalos/trustd"),
},
},
}
suite.Assert().NoError(containerdrunner.NewImporter(
suite.containerdNamespace, containerdrunner.WithContainerdAddress(suite.containerdAddress)).Import(context.Background(), reqs...))

ctx := namespaces.WithNamespace(context.Background(), suite.containerdNamespace)

for _, imageName := range []string{"testtalos/timed", "testtalos/trustd"} {
image, err := suite.client.ImageService().Get(ctx, imageName)
suite.Require().NoError(err)
suite.Require().Equal(imageName, image.Name)
}
}

func (suite *ContainerdSuite) TestImportFail() {
reqs := []*containerdrunner.ImportRequest{
{
Path: "/usr/images/timed.tar",
Options: []containerd.ImportOpt{
containerd.WithIndexName("testtalos/timed2"),
},
},
{
Path: "/usr/images/nothere.tar",
Options: []containerd.ImportOpt{
containerd.WithIndexName("testtalos/nothere"),
},
},
}
suite.Assert().Error(containerdrunner.NewImporter(
suite.containerdNamespace, containerdrunner.WithContainerdAddress(suite.containerdAddress)).Import(context.Background(), reqs...))
}

func (suite *ContainerdSuite) TestContainerStdin() {
stdin := bytes.Repeat([]byte{0xde, 0xad, 0xbe, 0xef}, 2000)

Expand Down
8 changes: 3 additions & 5 deletions internal/app/machined/pkg/system/services/apid.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import (
"github.com/talos-systems/talos/internal/app/machined/pkg/system/runner"
"github.com/talos-systems/talos/internal/app/machined/pkg/system/runner/containerd"
"github.com/talos-systems/talos/internal/app/machined/pkg/system/runner/restart"
"github.com/talos-systems/talos/internal/pkg/containers/image"
"github.com/talos-systems/talos/pkg/conditions"
"github.com/talos-systems/talos/pkg/copy"
"github.com/talos-systems/talos/pkg/machinery/config/types/v1alpha1/machine"
Expand All @@ -52,7 +51,7 @@ func (o *APID) PreFunc(ctx context.Context, r runtime.Runtime) error {
o.syncKubeletPKI()
}

return image.Import(ctx, "/usr/images/apid.tar", "talos/apid")
return nil
}

// PostFunc implements the Service interface.
Expand Down Expand Up @@ -86,8 +85,6 @@ func (o *APID) DependsOn(r runtime.Runtime) []string {

// Runner implements the Service interface.
func (o *APID) Runner(r runtime.Runtime) (runner.Runner, error) {
image := "talos/apid"

// Ensure socket dir exists
if err := os.MkdirAll(filepath.Dir(constants.APISocketPath), 0o750); err != nil {
return nil, err
Expand Down Expand Up @@ -153,11 +150,12 @@ func (o *APID) Runner(r runtime.Runtime) (runner.Runner, error) {
runner.WithStdin(stdin),
runner.WithLoggingManager(r.Logging()),
runner.WithContainerdAddress(constants.SystemContainerdAddress),
runner.WithContainerImage(image),
runner.WithEnv(env),
runner.WithOCISpecOpts(
oci.WithHostNamespace(specs.NetworkNamespace),
oci.WithMounts(mounts),
oci.WithRootFSPath("/opt/apid"),
oci.WithRootFSReadonly(),
),
),
restart.WithType(restart.Forever),
Expand Down
Loading

0 comments on commit ac87647

Please sign in to comment.