diff --git a/nodeup/pkg/model/docker.go b/nodeup/pkg/model/docker.go index d5357e519c..f7992ebeef 100644 --- a/nodeup/pkg/model/docker.go +++ b/nodeup/pkg/model/docker.go @@ -24,6 +24,7 @@ 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" @@ -31,8 +32,6 @@ import ( "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) @@ -42,6 +41,12 @@ type DockerBuilder struct { var _ fi.ModelBuilder = &DockerBuilder{} +type packageInfo struct { + Version string // Package version + Source string // URL to download the package from + Hash string // sha1sum of the package file +} + type dockerVersion struct { Name string @@ -54,8 +59,19 @@ type dockerVersion struct { // Hash is the sha1 hash of the file Hash string + // Extra packages to install during the same dpkg/yum transaction. + // This is used for: + // - On RHEL/CentOS, the SELinux policy needs to be installed. + // - 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. All 3 must be installed at the same time when + // upgrading from an older version of Docker. + ExtraPackages map[string]packageInfo + 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 @@ -104,16 +120,14 @@ var dockerVersions = []dockerVersion{ Version: "1.11.2", Source: "https://yum.dockerproject.org/repo/main/centos/7/Packages/docker-engine-1.11.2-1.el7.centos.x86_64.rpm", Hash: "432e6d7948df9e05f4190fce2f423eedbfd673d5", - Dependencies: []string{"libtool-ltdl"}, - }, - { - DockerVersion: "1.11.2", - Name: "docker-engine-selinux", - Distros: []distros.Distribution{distros.DistributionRhel7, distros.DistributionCentos7}, - Architectures: []Architecture{ArchitectureAmd64}, - Version: "1.11.2", - Source: "https://yum.dockerproject.org/repo/main/centos/7/Packages/docker-engine-selinux-1.11.2-1.el7.centos.noarch.rpm", - Hash: "f6da608fa8eeb2be8071489086ed9ff035f6daba", + ExtraPackages: map[string]packageInfo{ + "selinux": { + Version: "1.11.2", + Source: "https://yum.dockerproject.org/repo/main/centos/7/Packages/docker-engine-selinux-1.11.2-1.el7.centos.noarch.rpm", + Hash: "f6da608fa8eeb2be8071489086ed9ff035f6daba", + }, + }, + Dependencies: []string{"libtool-ltdl"}, }, // 1.12.1 - Jessie @@ -149,16 +163,14 @@ var dockerVersions = []dockerVersion{ Version: "1.12.1", Source: "https://yum.dockerproject.org/repo/main/centos/7/Packages/docker-engine-1.12.1-1.el7.centos.x86_64.rpm", Hash: "636471665665546224444052c3b48001397036be", - Dependencies: []string{"libtool-ltdl"}, - }, - { - DockerVersion: "1.12.1", - Name: "docker-engine-selinux", - Distros: []distros.Distribution{distros.DistributionRhel7, distros.DistributionCentos7}, - Architectures: []Architecture{ArchitectureAmd64}, - Version: "1.12.1", - Source: "https://yum.dockerproject.org/repo/main/centos/7/Packages/docker-engine-selinux-1.12.1-1.el7.centos.noarch.rpm", - Hash: "52ec22128e70acc2f76b3a8e87ff96785995116a", + ExtraPackages: map[string]packageInfo{ + "selinux": { + Version: "1.12.1", + Source: "https://yum.dockerproject.org/repo/main/centos/7/Packages/docker-engine-selinux-1.12.1-1.el7.centos.noarch.rpm", + Hash: "52ec22128e70acc2f76b3a8e87ff96785995116a", + }, + }, + Dependencies: []string{"libtool-ltdl"}, }, // 1.12.3 - k8s 1.5 @@ -210,16 +222,14 @@ var dockerVersions = []dockerVersion{ Version: "1.12.3", Source: "https://yum.dockerproject.org/repo/main/centos/7/Packages/docker-engine-1.12.3-1.el7.centos.x86_64.rpm", Hash: "67fbb78cfb9526aaf8142c067c10384df199d8f9", - Dependencies: []string{"libtool-ltdl", "libseccomp"}, - }, - { - DockerVersion: "1.12.3", - Name: "docker-engine-selinux", - Distros: []distros.Distribution{distros.DistributionRhel7, distros.DistributionCentos7}, - Architectures: []Architecture{ArchitectureAmd64}, - Version: "1.12.3", - Source: "https://yum.dockerproject.org/repo/main/centos/7/Packages/docker-engine-selinux-1.12.3-1.el7.centos.noarch.rpm", - Hash: "a6b0243af348140236ed96f2e902b259c590eefa", + ExtraPackages: map[string]packageInfo{ + "selinux": { + Version: "1.12.3", + Source: "https://yum.dockerproject.org/repo/main/centos/7/Packages/docker-engine-selinux-1.12.3-1.el7.centos.noarch.rpm", + Hash: "a6b0243af348140236ed96f2e902b259c590eefa", + }, + }, + Dependencies: []string{"libtool-ltdl", "libseccomp"}, }, // 1.12.6 - k8s 1.6 @@ -286,17 +296,14 @@ var dockerVersions = []dockerVersion{ Version: "1.12.6", Source: "https://yum.dockerproject.org/repo/main/centos/7/Packages/docker-engine-1.12.6-1.el7.centos.x86_64.rpm", Hash: "776dbefa9dc7733000e46049293555a9a422c50e", - Dependencies: []string{"libtool-ltdl", "libseccomp", "libcgroup"}, - }, - { - DockerVersion: "1.12.6", - Name: "docker-engine-selinux", - Distros: []distros.Distribution{distros.DistributionRhel7, distros.DistributionCentos7}, - Architectures: []Architecture{ArchitectureAmd64}, - Version: "1.12.6", - Source: "https://yum.dockerproject.org/repo/main/centos/7/Packages/docker-engine-selinux-1.12.6-1.el7.centos.noarch.rpm", - Hash: "9a6ee0d631ca911b6927450a3c396e9a5be75047", - Dependencies: []string{"policycoreutils-python"}, + ExtraPackages: map[string]packageInfo{ + "selinux": { + Version: "1.12.6", + Source: "https://yum.dockerproject.org/repo/main/centos/7/Packages/docker-engine-selinux-1.12.6-1.el7.centos.noarch.rpm", + Hash: "9a6ee0d631ca911b6927450a3c396e9a5be75047", + }, + }, + Dependencies: []string{"libtool-ltdl", "libseccomp", "libcgroup", "policycoreutils-python"}, }, // 1.13.1 - k8s 1.8 @@ -363,17 +370,14 @@ var dockerVersions = []dockerVersion{ Version: "1.13.1", Source: "https://yum.dockerproject.org/repo/main/centos/7/Packages/docker-engine-1.13.1-1.el7.centos.x86_64.rpm", Hash: "b18f7fd8057665e7d2871d29640e214173f70fe1", - Dependencies: []string{"libtool-ltdl", "libseccomp", "libcgroup"}, - }, - { - DockerVersion: "1.13.1", - Name: "docker-engine-selinux", - Distros: []distros.Distribution{distros.DistributionRhel7, distros.DistributionCentos7}, - Architectures: []Architecture{ArchitectureAmd64}, - Version: "1.13.1", - Source: "https://yum.dockerproject.org/repo/main/centos/7/Packages/docker-engine-selinux-1.13.1-1.el7.centos.noarch.rpm", - Hash: "948c518a610af631fa98aa32d9bcd43e9ddd5ebc", - Dependencies: []string{"policycoreutils-python", "selinux-policy-base", "selinux-policy-targeted"}, + ExtraPackages: map[string]packageInfo{ + "selinux": { + Version: "1.13.1", + Source: "https://yum.dockerproject.org/repo/main/centos/7/Packages/docker-engine-selinux-1.13.1-1.el7.centos.noarch.rpm", + Hash: "948c518a610af631fa98aa32d9bcd43e9ddd5ebc", + }, + }, + Dependencies: []string{"libtool-ltdl", "libseccomp", "libcgroup", "policycoreutils-python", "selinux-policy-base", "selinux-policy-targeted"}, }, // 17.03.2 - k8s 1.8 @@ -451,19 +455,16 @@ var dockerVersions = []dockerVersion{ Version: "17.03.2.ce", Source: "https://download.docker.com/linux/centos/7/x86_64/stable/Packages/docker-ce-17.03.2.ce-1.el7.centos.x86_64.rpm", Hash: "494ca888f5b1553f93b9d9a5dad4a67f76cf9eb5", - Dependencies: []string{"libtool-ltdl", "libseccomp", "libcgroup"}, + ExtraPackages: map[string]packageInfo{ + "selinux": { + Version: "17.03.2.ce", + Source: "https://download.docker.com/linux/centos/7/x86_64/stable/Packages/docker-ce-selinux-17.03.2.ce-1.el7.centos.noarch.rpm", + Hash: "4659c937b66519c88ef2a82a906bb156db29d191", + }, + }, + Dependencies: []string{"libtool-ltdl", "libseccomp", "libcgroup", "policycoreutils-python"}, MarkImmutable: []string{"/usr/bin/docker-runc"}, }, - { - DockerVersion: "17.03.2", - Name: "docker-ce-selinux", - Distros: []distros.Distribution{distros.DistributionRhel7, distros.DistributionCentos7}, - Architectures: []Architecture{ArchitectureAmd64}, - Version: "17.03.2.ce", - Source: "https://download.docker.com/linux/centos/7/x86_64/stable/Packages/docker-ce-selinux-17.03.2.ce-1.el7.centos.noarch.rpm", - Hash: "4659c937b66519c88ef2a82a906bb156db29d191", - Dependencies: []string{"policycoreutils-python"}, - }, // 17.09.0 - k8s 1.8 // 17.09.0 - Jessie @@ -531,16 +532,6 @@ var dockerVersions = []dockerVersion{ }, // 17.09.0 - Centos / Rhel7 (two packages) - { - DockerVersion: "17.09.0", - Name: "container-selinux", - Distros: []distros.Distribution{distros.DistributionRhel7, distros.DistributionCentos7}, - Architectures: []Architecture{ArchitectureAmd64}, - Version: "2.68", - Source: "http://mirror.centos.org/centos/7/extras/x86_64/Packages/container-selinux-2.68-1.el7.noarch.rpm", - Hash: "d9f87f7f4f2e8e611f556d873a17b8c0c580fec0", - Dependencies: []string{"policycoreutils-python"}, - }, { DockerVersion: "17.09.0", Name: "docker-ce", @@ -549,7 +540,14 @@ var dockerVersions = []dockerVersion{ Version: "17.09.0.ce", Source: "https://download.docker.com/linux/centos/7/x86_64/stable/Packages/docker-ce-17.09.0.ce-1.el7.centos.x86_64.rpm", Hash: "b4ce72e80ff02926de943082821bbbe73958f87a", - Dependencies: []string{"libtool-ltdl", "libseccomp", "libcgroup"}, + ExtraPackages: map[string]packageInfo{ + "selinux": { + Version: "17.09.0.ce", + Source: "http://mirror.centos.org/centos/7/extras/x86_64/Packages/container-selinux-2.68-1.el7.noarch.rpm", + Hash: "d9f87f7f4f2e8e611f556d873a17b8c0c580fec0", + }, + }, + Dependencies: []string{"libtool-ltdl", "libseccomp", "libcgroup", "policycoreutils-python"}, }, // 18.03.1 - Bionic @@ -582,7 +580,6 @@ var dockerVersions = []dockerVersion{ // 18.06.1 - Debian Stretch { - DockerVersion: "18.06.1", Name: "docker-ce", Distros: []distros.Distribution{distros.DistributionDebian9}, @@ -619,16 +616,6 @@ var dockerVersions = []dockerVersion{ }, // 18.06.1 - CentOS / Rhel7 (two packages) - { - DockerVersion: "18.06.1", - Name: "container-selinux", - Distros: []distros.Distribution{distros.DistributionRhel7, distros.DistributionCentos7}, - Architectures: []Architecture{ArchitectureAmd64}, - Version: "2.68", - Source: "http://mirror.centos.org/centos/7/extras/x86_64/Packages/container-selinux-2.68-1.el7.noarch.rpm", - Hash: "d9f87f7f4f2e8e611f556d873a17b8c0c580fec0", - Dependencies: []string{"policycoreutils-python"}, - }, { DockerVersion: "18.06.1", Name: "docker-ce", @@ -637,7 +624,38 @@ var dockerVersions = []dockerVersion{ Version: "18.06.1.ce", Source: "https://download.docker.com/linux/centos/7/x86_64/stable/Packages/docker-ce-18.06.1.ce-3.el7.x86_64.rpm", Hash: "0a1325e570c5e54111a79623c9fd0c0c714d3a11", - Dependencies: []string{"libtool-ltdl", "libseccomp", "libcgroup"}, + ExtraPackages: map[string]packageInfo{ + "selinux": { + Version: "18.06.1.ce", + Source: "http://mirror.centos.org/centos/7/extras/x86_64/Packages/container-selinux-2.68-1.el7.noarch.rpm", + Hash: "d9f87f7f4f2e8e611f556d873a17b8c0c580fec0", + }, + }, + Dependencies: []string{"libtool-ltdl", "libseccomp", "libcgroup", "policycoreutils-python"}, + }, + + // 18.09.3 - Debian Stretch + { + DockerVersion: "18.09.3", + Name: "docker-ce", + Distros: []distros.Distribution{distros.DistributionDebian9}, + Architectures: []Architecture{ArchitectureAmd64}, + Version: "18.09.3-0~debian", + Source: "https://download.docker.com/linux/debian/dists/stretch/pool/stable/amd64/docker-ce_18.09.3~3-0~debian-stretch_amd64.deb", + Hash: "009b9a2d8bfaa97c74773fe4ec25b6bb396b10d0", + ExtraPackages: map[string]packageInfo{ + "cli": { + Version: "18.09.3-0~debian", + Source: "https://download.docker.com/linux/debian/dists/stretch/pool/stable/amd64/docker-ce-cli_18.09.3~3-0~debian-stretch_amd64.deb", + Hash: "557f868ec63e5251639ebd1d8669eb0c61dd555c", + }, + "containerd": { + Version: "1.2.4-1", + Source: "https://download.docker.com/linux/debian/dists/stretch/pool/stable/amd64/containerd.io_1.2.4-1_amd64.deb", + Hash: "48c6ab0c908316af9a183de5aad64703bc516bdf", + }, + }, + Dependencies: []string{"bridge-utils", "libapparmor1", "libltdl7"}, }, // 18.06.2 - CentOS / Rhel7 (two packages) @@ -712,17 +730,14 @@ var dockerVersions = []dockerVersion{ Version: "2.68", Source: "http://mirror.centos.org/centos/7/extras/x86_64/Packages/container-selinux-2.68-1.el7.noarch.rpm", Hash: "d9f87f7f4f2e8e611f556d873a17b8c0c580fec0", - Dependencies: []string{"policycoreutils-python"}, - }, - { - DockerVersion: "18.06.3", - Name: "docker-ce", - Distros: []distros.Distribution{distros.DistributionRhel7, distros.DistributionCentos7}, - Architectures: []Architecture{ArchitectureAmd64}, - Version: "18.06.3.ce", - Source: "https://download.docker.com/linux/centos/7/x86_64/stable/Packages/docker-ce-18.06.3.ce-3.el7.x86_64.rpm", - Hash: "5369602f88406d4fb9159dc1d3fd44e76fb4cab8", - Dependencies: []string{"libtool-ltdl", "libseccomp", "libcgroup"}, + ExtraPackages: map[string]packageInfo{ + "selinux": { + Version: "18.06.3.ce", + Source: "https://download.docker.com/linux/centos/7/x86_64/stable/Packages/docker-ce-18.06.3.ce-3.el7.x86_64.rpm", + Hash: "5369602f88406d4fb9159dc1d3fd44e76fb4cab8", + }, + }, + Dependencies: []string{"libtool-ltdl", "libseccomp", "libcgroup", "policycoreutils-python"}, }, // TIP: When adding the next version, copy the previous @@ -828,11 +843,23 @@ func (b *DockerBuilder) Build(c *fi.ModelBuilderContext) error { c.AddTask(b.buildDockerGroup()) c.AddTask(b.buildSystemdSocket()) } else { + var extraPkgs []*nodetasks.Package + for name, pkg := range dv.ExtraPackages { + dep := &nodetasks.Package{ + Name: dv.Name + "-" + name, + Version: s(pkg.Version), + Source: s(pkg.Source), + Hash: s(pkg.Hash), + PreventStart: fi.Bool(true), + } + extraPkgs = append(extraPkgs, dep) + } packageTask = &nodetasks.Package{ Name: dv.Name, Version: s(dv.Version), Source: s(dv.Source), Hash: s(dv.Hash), + Deps: extraPkgs, // TODO: PreventStart is now unused? PreventStart: fi.Bool(true), diff --git a/upup/pkg/fi/nodeup/nodetasks/package.go b/upup/pkg/fi/nodeup/nodetasks/package.go index f6674411ac..dcc20382ec 100644 --- a/upup/pkg/fi/nodeup/nodetasks/package.go +++ b/upup/pkg/fi/nodeup/nodetasks/package.go @@ -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 ( @@ -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) @@ -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)) - if err != nil { - return fmt.Errorf("error paring hash: %v", err) + // 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 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()