Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Flatcar support #7084

Merged
merged 2 commits into from
Jun 20, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions docs/images.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,3 +143,25 @@ Be aware of the following limitations:
* [Amazon Linux 2 LTS](https://aws.amazon.com/amazon-linux-2/release-notes/) is the recommended minimum version, a previous version called just "Amazon Linux AMI" is not supported.

> Note: SSH username for Amazon Linux 2 based instances will be `ec2-user`

## Flatcar

Flatcar is a friendly fork of CoreOS and as such, compatible with it. If some issues occurs with it, it is likely that also CoreOS miight be affected. If you encounter any problem please report it to us.

The following steps are known:

* The latest stable Flatcar AMI can be found using:
```bash
aws ec2 describe-images --region=us-east-1 --owner=075585003325 \
--filters "Name=virtualization-type,Values=hvm" "Name=name,Values=Flatcar-stable*" \
--query 'sort_by(Images,&CreationDate)[-1].{id:ImageLocation}'
```

Also, you can obtain the "AMI ID" from Flatcar web page too. They publish their AMI's using a json file at [https://stable.release.flatcar-linux.net/amd64-usr/current/flatcar_production_ami_all.json](https://stable.release.flatcar-linux.net/amd64-usr/current/flatcar_production_ami_all.json). Using some scripting and a "json" parser (like jq) you can obtain the AMI ID from a specific region:

```bash
curl -s https://stable.release.flatcar-linux.net/amd64-usr/current/flatcar_production_ami_all.json | jq -r '.amis[] | select(.name == "us-east-1") | .hvm'
"ami-096be41989ec7e569"
```

> Note: SSH username for Flatcar based instances will be `core`
9 changes: 6 additions & 3 deletions nodeup/pkg/distros/distribution.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ var (
DistributionRhel7 Distribution = "rhel7"
DistributionCentos7 Distribution = "centos7"
DistributionCoreOS Distribution = "coreos"
DistributionFlatcar Distribution = "flatcar"
DistributionContainerOS Distribution = "containeros"
)

Expand All @@ -52,6 +53,8 @@ func (d Distribution) BuildTags() []string {
t = []string{"_rhel7"}
case DistributionCoreOS:
t = []string{"_coreos"}
case DistributionFlatcar:
t = []string{"_flatcar"}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just FYI we hopefully aren't using these tags any more. But no problem with leaving this in for now and removing once we confirm we're not using tags :-)

case DistributionContainerOS:
t = []string{"_containeros"}
default:
Expand All @@ -78,7 +81,7 @@ func (d Distribution) IsDebianFamily() bool {
return true
case DistributionCentos7, DistributionRhel7:
return false
case DistributionCoreOS, DistributionContainerOS:
case DistributionCoreOS, DistributionFlatcar, DistributionContainerOS:
return false
default:
klog.Fatalf("unknown distribution: %s", d)
Expand All @@ -92,7 +95,7 @@ func (d Distribution) IsRHELFamily() bool {
return true
case DistributionJessie, DistributionXenial, DistributionBionic, DistributionDebian9:
return false
case DistributionCoreOS, DistributionContainerOS:
case DistributionCoreOS, DistributionFlatcar, DistributionContainerOS:
return false
default:
klog.Fatalf("unknown distribution: %s", d)
Expand All @@ -106,7 +109,7 @@ func (d Distribution) IsSystemd() bool {
return true
case DistributionCentos7, DistributionRhel7:
return true
case DistributionCoreOS:
case DistributionCoreOS, DistributionFlatcar:
return true
case DistributionContainerOS:
return true
Expand Down
3 changes: 3 additions & 0 deletions nodeup/pkg/distros/identify.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,15 @@ func FindDistribution(rootfs string) (Distribution, error) {
}

// CoreOS uses /usr/lib/os-release
// Flatcar uses /usr/lib/os-release
usrLibOsRelease, err := ioutil.ReadFile(path.Join(rootfs, "usr/lib/os-release"))
if err == nil {
for _, line := range strings.Split(string(usrLibOsRelease), "\n") {
line = strings.TrimSpace(line)
if line == "ID=coreos" {
return DistributionCoreOS, nil
} else if line == "ID=flatcar" {
return DistributionFlatcar, nil
}
}
klog.Warningf("unhandled os-release info %q", string(usrLibOsRelease))
Expand Down
5 changes: 5 additions & 0 deletions nodeup/pkg/model/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ func (c *NodeupModelContext) SSLHostPaths() []string {
// Because /usr is read-only on CoreOS, we can't have any new directories; docker will try (and fail) to create them
// TODO: Just check if the directories exist?
paths = append(paths, "/usr/share/ca-certificates")
case distros.DistributionFlatcar:
paths = append(paths, "/usr/share/ca-certificates")
case distros.DistributionContainerOS:
paths = append(paths, "/usr/share/ca-certificates")
default:
Expand Down Expand Up @@ -412,6 +414,9 @@ func (c *NodeupModelContext) KubectlPath() string {
if c.Distribution == distros.DistributionCoreOS {
kubeletCommand = "/opt/bin"
}
if c.Distribution == distros.DistributionFlatcar {
kubeletCommand = "/opt/bin"
}
if c.Distribution == distros.DistributionContainerOS {
kubeletCommand = "/home/kubernetes/bin"
}
Expand Down
7 changes: 7 additions & 0 deletions nodeup/pkg/model/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -812,6 +812,13 @@ func (b *DockerBuilder) Build(c *fi.ModelBuilderContext) error {
}
return nil

case distros.DistributionFlatcar:
klog.Infof("Detected Flatcar; won't install Docker")
if err := b.buildContainerOSConfigurationDropIn(c); err != nil {
return err
}
return nil

case distros.DistributionContainerOS:
klog.Infof("Detected ContainerOS; won't install Docker")
if err := b.buildContainerOSConfigurationDropIn(c); err != nil {
Expand Down
4 changes: 4 additions & 0 deletions nodeup/pkg/model/etcd.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ func (b *EtcdBuilder) Build(c *fi.ModelBuilderContext) error {
klog.Infof("Detected CoreOS; skipping etcd user installation")
return nil

case distros.DistributionFlatcar:
klog.Infof("Detected Flatcar; skipping etcd user installation")
return nil

case distros.DistributionContainerOS:
klog.Infof("Detected ContainerOS; skipping etcd user installation")
return nil
Expand Down
31 changes: 31 additions & 0 deletions nodeup/pkg/model/kubelet.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,9 @@ func (b *KubeletBuilder) kubeletPath() string {
if b.Distribution == distros.DistributionCoreOS {
kubeletCommand = "/opt/kubernetes/bin/kubelet"
}
if b.Distribution == distros.DistributionFlatcar {
kubeletCommand = "/opt/kubernetes/bin/kubelet"
}
if b.Distribution == distros.DistributionContainerOS {
kubeletCommand = "/home/kubernetes/bin/kubelet"
}
Expand Down Expand Up @@ -261,6 +264,10 @@ func (b *KubeletBuilder) buildSystemdService() *nodetasks.Service {
// We add /opt/kubernetes/bin for our utilities (socat, conntrack)
manifest.Set("Service", "Environment", "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/kubernetes/bin")
}
if b.Distribution == distros.DistributionFlatcar {
// We add /opt/kubernetes/bin for our utilities (conntrack)
manifest.Set("Service", "Environment", "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/kubernetes/bin")
}
manifest.Set("Service", "EnvironmentFile", "/etc/sysconfig/kubelet")

// @check if we are using bootstrap tokens and file checker
Expand Down Expand Up @@ -336,6 +343,30 @@ func (b *KubeletBuilder) addStaticUtils(c *fi.ModelBuilderContext) error {
}
}

if b.Distribution == distros.DistributionFlatcar {
// Flatcar does not ship with conntrack. Install our own (statically linked) version
// TODO: Extract to common function?
for _, binary := range []string{"conntrack"} {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've checked and I've found out that Flatcar is shipped with socat so it is not necessary to install it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is really good news - the omission of socat was so surprising!

assetName := binary
assetPath := ""
asset, err := b.Assets.Find(assetName, assetPath)
if err != nil {
return fmt.Errorf("error trying to locate asset %q: %v", assetName, err)
}
if asset == nil {
return fmt.Errorf("unable to locate asset %q", assetName)
}

t := &nodetasks.File{
Path: "/opt/kubernetes/bin/" + binary,
Contents: asset,
Type: nodetasks.FileType_File,
Mode: s("0755"),
}
c.AddTask(t)
}
}

return nil
}

Expand Down
10 changes: 9 additions & 1 deletion nodeup/pkg/model/logrotate.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ func (b *LogrotateBuilder) Build(c *fi.ModelBuilderContext) error {
return nil
case distros.DistributionCoreOS:
klog.Infof("Detected CoreOS; won't install logrotate")
case distros.DistributionFlatcar:
klog.Infof("Detected Flatcar; won't install logrotate")
default:
c.AddTask(&nodetasks.Package{Name: "logrotate"})
}
Expand Down Expand Up @@ -93,7 +95,7 @@ func (b *LogrotateBuilder) Build(c *fi.ModelBuilderContext) error {
// addLogrotateService creates a logrotate systemd task to act as target for the timer, if one is needed
func (b *LogrotateBuilder) addLogrotateService(c *fi.ModelBuilderContext) error {
switch b.Distribution {
case distros.DistributionCoreOS, distros.DistributionContainerOS:
case distros.DistributionCoreOS, distros.DistributionFlatcar, distros.DistributionContainerOS:
// logrotate service already exists
return nil
}
Expand Down Expand Up @@ -128,6 +130,12 @@ func (b *LogrotateBuilder) addLogRotate(c *fi.ModelBuilderContext, name, path st
options.DateFormat = "-%Y%m%d-%s"
}

// Flatcar sets "dateext" options, and maxsize-based rotation will fail if
// the file has been previously rotated on the same calendar date.
if b.Distribution == distros.DistributionFlatcar {
options.DateFormat = "-%Y%m%d-%s"
}

lines := []string{
path + "{",
" rotate 5",
Expand Down
26 changes: 26 additions & 0 deletions nodeup/pkg/model/update_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ func (b *UpdateServiceBuilder) Build(c *fi.ModelBuilderContext) error {
c.AddTask(b.buildCoreOSSystemdService())
}

if b.Distribution == distros.DistributionFlatcar {
klog.Infof("Detected OS %s; building %s service to disable update scheduler", ServiceName, b.Distribution)
c.AddTask(b.buildFlatcarSystemdService())
}

return nil
}

Expand All @@ -80,3 +85,24 @@ func (b *UpdateServiceBuilder) buildCoreOSSystemdService() *nodetasks.Service {

return service
}

func (b *UpdateServiceBuilder) buildFlatcarSystemdService() *nodetasks.Service {
manifest := &systemd.Manifest{}
manifest.Set("Unit", "Description", "Disable OS Update Scheduler")

manifest.Set("Unit", "Before", "locksmithd.service")
manifest.Set("Service", "Type", "oneshot")
manifest.Set("Service", "ExecStart", "/usr/bin/systemctl mask --now locksmithd.service")

manifestString := manifest.Render()
klog.V(8).Infof("Built service manifest %q\n%s", ServiceName, manifestString)

service := &nodetasks.Service{
Name: ServiceName + ".service",
Definition: s(manifestString),
}

service.InitDefaults()

return service
}