mirror of https://github.com/kubernetes/kops.git
Merge pull request #414 from justinsb/ubuntu_initial_support
Initial (experimental) Ubuntu 16.04 support
This commit is contained in:
commit
0b4a558864
|
|
@ -33,14 +33,19 @@ func init() {
|
|||
cmd.Flags().BoolVar(&rollingupdateCluster.Force, "force", false, "Force rolling update, even if no changes")
|
||||
|
||||
cmd.Run = func(cmd *cobra.Command, args []string) {
|
||||
err := rollingupdateCluster.Run()
|
||||
err := rollingupdateCluster.Run(args)
|
||||
if err != nil {
|
||||
exitWithError(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *RollingUpdateClusterCmd) Run() error {
|
||||
func (c *RollingUpdateClusterCmd) Run(args []string) error {
|
||||
err := rootCommand.ProcessArgs(args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, cluster, err := rootCommand.Cluster()
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
# Images
|
||||
|
||||
Changing the image for an instance group
|
||||
|
||||
You can choose a different AMI for an instance group.
|
||||
|
||||
If you `kops edit ig nodes`, you should see an `image` member of the spec.
|
||||
|
||||
Various syntaxes are available:
|
||||
|
||||
* `ami-abcdef` specifies an AMI by id directly.
|
||||
* `<owner>/<name>` specifies an AMI by its owner and Name properties
|
||||
|
||||
The ami spec is precise, but AMIs vary by region. So it is often more convenient to use the `<owner>/<name>`
|
||||
specifier, if equivalent images have been copied to various regions with the same name.
|
||||
|
||||
For example, to use Ubuntu 16.04, you can specify:
|
||||
|
||||
`image: 099720109477/ubuntu/images/hvm-ssd/ubuntu-xenial-16.04-amd64-server-20160830`
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -103,6 +103,12 @@ function download-release() {
|
|||
done
|
||||
|
||||
echo "Running release install script"
|
||||
# We run in the background to work around https://github.com/docker/docker/issues/23793
|
||||
run-nodeup &
|
||||
}
|
||||
|
||||
function run-nodeup() {
|
||||
sleep 1
|
||||
( cd ${INSTALL_DIR}; ./nodeup --conf=/var/cache/kubernetes-install/kube_env.yaml --v=8 )
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -127,6 +127,12 @@ function download-release() {
|
|||
done
|
||||
|
||||
echo "Running release install script"
|
||||
# We run in the background to work around https://github.com/docker/docker/issues/23793
|
||||
run-nodeup &
|
||||
}
|
||||
|
||||
function run-nodeup() {
|
||||
sleep 1
|
||||
( cd ${INSTALL_DIR}; ./nodeup --conf=/var/cache/kubernetes-install/kube_env.yaml --v=8 )
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"version": "1.11.2-0~xenial",
|
||||
"source": "http://apt.dockerproject.org/repo/pool/main/d/docker-engine/docker-engine_1.11.2-0~xenial_amd64.deb",
|
||||
"hash": "194bfa864f0424d1bbdc7d499ccfa0445ce09b9f",
|
||||
|
||||
"preventStart": true
|
||||
}
|
||||
|
|
@ -399,7 +399,7 @@ func (c *AWSCloud) ResolveImage(name string) (*ec2.Image, error) {
|
|||
request.ImageIds = []*string{&name}
|
||||
} else {
|
||||
// Either <imagename> or <owner>/<imagename>
|
||||
tokens := strings.Split(name, "/")
|
||||
tokens := strings.SplitN(name, "/", 2)
|
||||
if len(tokens) == 1 {
|
||||
// self is a well-known value in the DescribeImages call
|
||||
request.Owners = aws.StringSlice([]string{"self"})
|
||||
|
|
|
|||
|
|
@ -11,7 +11,9 @@ import (
|
|||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"reflect"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type Package struct {
|
||||
|
|
@ -21,6 +23,9 @@ type Package struct {
|
|||
Source *string `json:"source"`
|
||||
Hash *string `json:"hash"`
|
||||
PreventStart *bool `json:"preventStart"`
|
||||
|
||||
// Healthy is true if the package installation did not fail
|
||||
Healthy *bool `json:"healthy"`
|
||||
}
|
||||
|
||||
const (
|
||||
|
|
@ -29,16 +34,37 @@ const (
|
|||
|
||||
var _ fi.HasDependencies = &Package{}
|
||||
|
||||
// GetDependencies computes dependencies for the package task
|
||||
func (p *Package) GetDependencies(tasks map[string]fi.Task) []fi.Task {
|
||||
var deps []fi.Task
|
||||
|
||||
// UpdatePackages before we install any packages
|
||||
for _, v := range tasks {
|
||||
if _, ok := v.(*UpdatePackages); ok {
|
||||
deps = append(deps, v)
|
||||
}
|
||||
}
|
||||
|
||||
// If this package is a bare deb, install it after OS managed packages
|
||||
if !p.isOSPackage() {
|
||||
for _, v := range tasks {
|
||||
if vp, ok := v.(*Package); ok {
|
||||
if vp.isOSPackage() {
|
||||
deps = append(deps, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return deps
|
||||
}
|
||||
|
||||
// isOSPackage returns true if this is an OS provided package (as opposed to a bare .deb, for example)
|
||||
func (p *Package) isOSPackage() bool {
|
||||
return fi.StringValue(p.Source) == ""
|
||||
}
|
||||
|
||||
// String returns a string representation, implementing the Stringer interface
|
||||
func (p *Package) String() string {
|
||||
return fmt.Sprintf("Package: %s", p.Name)
|
||||
}
|
||||
|
|
@ -51,6 +77,12 @@ func NewPackage(name string, contents string, meta string) (fi.Task, error) {
|
|||
return nil, fmt.Errorf("error parsing json for package %q: %v", name, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Default values: we want to install a package so that it is healthy
|
||||
if p.Healthy == nil {
|
||||
p.Healthy = fi.Bool(true)
|
||||
}
|
||||
|
||||
return p, nil
|
||||
}
|
||||
|
||||
|
|
@ -69,6 +101,7 @@ func (e *Package) Find(c *fi.Context) (*Package, error) {
|
|||
}
|
||||
|
||||
installed := false
|
||||
var healthy *bool
|
||||
installedVersion := ""
|
||||
for _, line := range strings.Split(string(output), "\n") {
|
||||
if line == "" {
|
||||
|
|
@ -86,6 +119,11 @@ func (e *Package) Find(c *fi.Context) (*Package, error) {
|
|||
case "ii":
|
||||
installed = true
|
||||
installedVersion = version
|
||||
healthy = fi.Bool(true)
|
||||
case "iF":
|
||||
installed = true
|
||||
installedVersion = version
|
||||
healthy = fi.Bool(false)
|
||||
case "rc":
|
||||
// removed
|
||||
installed = false
|
||||
|
|
@ -104,6 +142,7 @@ func (e *Package) Find(c *fi.Context) (*Package, error) {
|
|||
return &Package{
|
||||
Name: e.Name,
|
||||
Version: fi.String(installedVersion),
|
||||
Healthy: healthy,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
@ -115,8 +154,15 @@ func (s *Package) CheckChanges(a, e, changes *Package) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// packageManagerLock is a simple lock that prevents concurrent package manager operations
|
||||
// It just avoids unnecessary failures from running e.g. concurrent apt-get installs
|
||||
var packageManagerLock sync.Mutex
|
||||
|
||||
func (_ *Package) RenderLocal(t *local.LocalTarget, a, e, changes *Package) error {
|
||||
if changes.Version != nil {
|
||||
packageManagerLock.Lock()
|
||||
defer packageManagerLock.Unlock()
|
||||
|
||||
if a == nil || changes.Version != nil {
|
||||
glog.Infof("Installing package %q", e.Name)
|
||||
|
||||
if e.Source != nil {
|
||||
|
|
@ -156,6 +202,22 @@ func (_ *Package) RenderLocal(t *local.LocalTarget, a, e, changes *Package) erro
|
|||
return fmt.Errorf("error installing package %q: %v: %s", e.Name, err, string(output))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if changes.Healthy != nil {
|
||||
args := []string{"dpkg", "--configure", "-a"}
|
||||
glog.Infof("package is not healthy; runnning command %s", args)
|
||||
cmd := exec.Command(args[0], args[1:]...)
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error running `dpkg --configure -a`: %v: %s", err, string(output))
|
||||
}
|
||||
|
||||
changes.Healthy = nil
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(changes, &Package{}) {
|
||||
glog.Warningf("cannot apply package changes for %q: %v", e.Name, changes)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -12,6 +12,21 @@ import (
|
|||
// FindOSTags infers tags from the current distro
|
||||
// We will likely remove this when everything is containerized
|
||||
func FindOSTags(rootfs string) ([]string, error) {
|
||||
// Ubuntu has /etc/lsb-release (and /etc/debian_version)
|
||||
lsbRelease, err := ioutil.ReadFile(path.Join(rootfs, "etc/lsb-release"))
|
||||
if err == nil {
|
||||
for _, line := range strings.Split(string(lsbRelease), "\n") {
|
||||
line = strings.TrimSpace(line)
|
||||
if line == "DISTRIB_CODENAME=xenial" {
|
||||
return []string{"_xenial", "_debian_family", "_systemd"}, nil
|
||||
}
|
||||
}
|
||||
glog.Warningf("unhandled lsb-release info %q", string(lsbRelease))
|
||||
} else if !os.IsNotExist(err) {
|
||||
glog.Warningf("error reading /etc/lsb-release: %v", err)
|
||||
}
|
||||
|
||||
// Debian has /etc/debian_version
|
||||
debianVersionBytes, err := ioutil.ReadFile(path.Join(rootfs, "etc/debian_version"))
|
||||
if err == nil {
|
||||
debianVersion := strings.TrimSpace(string(debianVersionBytes))
|
||||
|
|
@ -21,8 +36,9 @@ func FindOSTags(rootfs string) ([]string, error) {
|
|||
return nil, fmt.Errorf("unhandled debian version %q", debianVersion)
|
||||
}
|
||||
} else if !os.IsNotExist(err) {
|
||||
glog.Infof("error reading /etc/debian_version: %v", err)
|
||||
glog.Warningf("error reading /etc/debian_version: %v", err)
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("cannot identify distro")
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue