Skip to content

Commit

Permalink
nodeup: Add support for Docker 18.09.1.
Browse files Browse the repository at this point in the history
Starting from Docker 18.09.0, the Docker distribution has been split in
3 packages: the Docker daemon, the Docker CLI, and for containerd.  This
adds a twist to how to upgrade Docker from the base image as the daemon
and CLI packages must be installed at the same time, otherwise dpkg/rpm
will refuse to upgrade (the new CLI is incompatible with the old package
and the daemon can't be installed without first installing the CLI and
the new containerd, so the upgrade MUST happen in a single transaction).

This code change thus adds the possibility to specify sources for the
CLI and containerd in nodeup, and the ability to apply the multi-package
upgrade atomically with dpkg/rpm.
  • Loading branch information
tsuna committed Jan 16, 2019
1 parent c6f4fb2 commit 28d2723
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 23 deletions.
1 change: 1 addition & 0 deletions WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ load(
"@io_bazel_rules_docker//repositories:repositories.bzl",
container_repositories = "repositories",
)

container_repositories()

load(
Expand Down
67 changes: 60 additions & 7 deletions nodeup/pkg/model/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,14 @@ import (
"strconv"
"strings"

"github.com/golang/glog"
"k8s.io/kops/nodeup/pkg/distros"
"k8s.io/kops/nodeup/pkg/model/resources"
"k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/flagbuilder"
"k8s.io/kops/pkg/systemd"
"k8s.io/kops/upup/pkg/fi"
"k8s.io/kops/upup/pkg/fi/nodeup/nodetasks"

"github.com/golang/glog"
)

// DockerBuilder install docker (just the packages at the moment)
Expand All @@ -43,13 +42,28 @@ type DockerBuilder struct {
var _ fi.ModelBuilder = &DockerBuilder{}

type dockerVersion struct {
Name string
Version string
Source string
Hash string
Name string

Version string // Docker package version
Source string // URL to download the package from
Hash string // sha1sum of the package file

// Starting from Docker 18.09, the Docker package has been split in 3
// separate packages: one for the daemon, one for the CLI, one for
// containerd. The following specifies where to fetch docker-cli from.
DockerCliVersion string // These 3 fields are ignored if this is empty.
DockerCliSource string
DockerCliHash string

// Where to fetch containerd from.
ContainerdVersion string // These 3 fields are ignored if this is empty.
ContainerdSource string
ContainerdHash string

DockerVersion string
Distros []distros.Distribution
// List of dependencies that can be installed using the system's package
// manager (e.g. apt-get install or yum install).
Dependencies []string
Architectures []Architecture

Expand Down Expand Up @@ -529,7 +543,6 @@ var dockerVersions = []dockerVersion{

// 18.06.1 - Debian Stretch
{

DockerVersion: "18.06.1",
Name: "docker-ce",
Distros: []distros.Distribution{distros.DistributionDebian9},
Expand All @@ -540,6 +553,24 @@ var dockerVersions = []dockerVersion{
Dependencies: []string{"bridge-utils", "libapparmor1", "libltdl7", "perl"},
},

// 18.09.1 - Debian Stretch
{
DockerVersion: "18.09.1",
Name: "docker-ce",
Distros: []distros.Distribution{distros.DistributionDebian9},
Architectures: []Architecture{ArchitectureAmd64},
Version: "18.09.1-0~debian",
Source: "https://download.docker.com/linux/debian/dists/stretch/pool/stable/amd64/docker-ce_18.09.1~3-0~debian-stretch_amd64.deb",
Hash: "94a619d060220b8c89c919aacdd5c5fd90bab68f",
DockerCliVersion: "18.09.1-0~debian",
DockerCliSource: "https://download.docker.com/linux/debian/dists/stretch/pool/stable/amd64/docker-ce-cli_18.09.1~3-0~debian-stretch_amd64.deb",
DockerCliHash: "10a8d6276741e07926763b3160d5188205410ef2",
ContainerdVersion: "1.2.2-1",
ContainerdSource: "https://download.docker.com/linux/debian/dists/stretch/pool/stable/amd64/containerd.io_1.2.2-1_amd64.deb",
ContainerdHash: "ebfcf91a065c8356bfd9397dd0c72a771e0bc91c",
Dependencies: []string{"bridge-utils", "libapparmor1", "libltdl7"},
},

// 18.06.1 - CentOS / Rhel7
{
DockerVersion: "18.06.1",
Expand Down Expand Up @@ -642,11 +673,33 @@ func (b *DockerBuilder) Build(c *fi.ModelBuilderContext) error {
c.AddTask(b.buildDockerGroup())
c.AddTask(b.buildSystemdSocket())
} else {
var dockerdDeps []*nodetasks.Package
if dv.DockerCliVersion != "" {
dep := &nodetasks.Package{
Name: dv.Name + "-cli",
Version: s(dv.DockerCliVersion),
Source: s(dv.DockerCliSource),
Hash: s(dv.DockerCliHash),
PreventStart: fi.Bool(true),
}
dockerdDeps = append(dockerdDeps, dep)
}
if dv.ContainerdVersion != "" {
dep := &nodetasks.Package{
Name: dv.Name + "-containerd",
Version: s(dv.ContainerdVersion),
Source: s(dv.ContainerdSource),
Hash: s(dv.ContainerdHash),
PreventStart: fi.Bool(true),
}
dockerdDeps = append(dockerdDeps, dep)
}
c.AddTask(&nodetasks.Package{
Name: dv.Name,
Version: s(dv.Version),
Source: s(dv.Source),
Hash: s(dv.Hash),
Deps: dockerdDeps,

// TODO: PreventStart is now unused?
PreventStart: fi.Bool(true),
Expand Down
45 changes: 29 additions & 16 deletions upup/pkg/fi/nodeup/nodetasks/package.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ type Package struct {

// Healthy is true if the package installation did not fail
Healthy *bool `json:"healthy,omitempty"`

// Additional dependencies that must be installed before this package.
// These will actually be passed together with this package to rpm/dpkg,
// which will then figure out the correct order in which to install them.
// This means that Deps don't get installed unless this package needs to
// get installed.
Deps []*Package `json:"deps,omitempty"`
}

const (
Expand Down Expand Up @@ -162,7 +169,7 @@ func (e *Package) findDpkg(c *fi.Context) (*Package, error) {
installed = true
installedVersion = version
healthy = fi.Bool(true)
case "iF":
case "iF", "iU":
installed = true
installedVersion = version
healthy = fi.Bool(false)
Expand Down Expand Up @@ -257,37 +264,43 @@ func (_ *Package) RenderLocal(t *local.LocalTarget, a, e, changes *Package) erro
defer packageManagerLock.Unlock()

if a == nil || changes.Version != nil {
glog.Infof("Installing package %q", e.Name)
glog.Infof("Installing package %q (dependencies: %v)", e.Name, e.Deps)

if e.Source != nil {
// Install a deb
local := path.Join(localPackageDir, e.Name)
// Install a deb or rpm.
err := os.MkdirAll(localPackageDir, 0755)
if err != nil {
return fmt.Errorf("error creating directories %q: %v", path.Dir(local), err)
return fmt.Errorf("error creating directories %q: %v", localPackageDir, err)
}

var hash *hashing.Hash
if fi.StringValue(e.Hash) != "" {
parsed, err := hashing.FromString(fi.StringValue(e.Hash))
// Download all the debs/rpms.
localPkgs := make([]string, 1+len(e.Deps))
for i, pkg := range append([]*Package{e}, e.Deps...) {
local := path.Join(localPackageDir, pkg.Name)
localPkgs[i] = local
var hash *hashing.Hash
if fi.StringValue(pkg.Hash) != "" {
parsed, err := hashing.FromString(fi.StringValue(pkg.Hash))
if err != nil {
return fmt.Errorf("error paring hash: %v", err)
}
hash = parsed
}
_, err = fi.DownloadURL(fi.StringValue(pkg.Source), local, hash)
if err != nil {
return fmt.Errorf("error paring hash: %v", err)
return err
}
hash = parsed
}
_, err = fi.DownloadURL(fi.StringValue(e.Source), local, hash)
if err != nil {
return err
}

var args []string
if t.HasTag(tags.TagOSFamilyDebian) {
args = []string{"dpkg", "-i", local}
args = []string{"dpkg", "-i"}
} else if t.HasTag(tags.TagOSFamilyRHEL) {
args = []string{"/usr/bin/rpm", "-i", local}
args = []string{"/usr/bin/rpm", "-i"}
} else {
return fmt.Errorf("unsupported package system")
}
args = append(args, localPkgs...)
glog.Infof("running command %s", args)
cmd := exec.Command(args[0], args[1:]...)
output, err := cmd.CombinedOutput()
Expand Down

0 comments on commit 28d2723

Please sign in to comment.