mirror of https://github.com/kubernetes/kops.git
Merge pull request #1436 from justinsb/docker_service_in_code
Build docker service in code, to cope with variations
This commit is contained in:
commit
5cbcf2faf8
|
@ -31,17 +31,67 @@ var (
|
|||
)
|
||||
|
||||
func (d Distribution) BuildTags() []string {
|
||||
var t []string
|
||||
|
||||
switch d {
|
||||
case DistributionJessie:
|
||||
return []string{"_jessie", tags.TagOSFamilyDebian, tags.TagSystemd}
|
||||
t = []string{"_jessie"}
|
||||
case DistributionXenial:
|
||||
return []string{"_xenial", tags.TagOSFamilyDebian, tags.TagSystemd}
|
||||
t = []string{"_xenial"}
|
||||
case DistributionCentos7:
|
||||
return []string{"_centos7", tags.TagOSFamilyRHEL, tags.TagSystemd}
|
||||
t = []string{"_centos7"}
|
||||
case DistributionRhel7:
|
||||
return []string{"_rhel7", tags.TagOSFamilyRHEL, tags.TagSystemd}
|
||||
t = []string{"_rhel7"}
|
||||
default:
|
||||
glog.Fatalf("unknown distribution: %s", d)
|
||||
return nil
|
||||
}
|
||||
|
||||
if d.IsDebianFamily() {
|
||||
t = append(t, tags.TagOSFamilyDebian)
|
||||
}
|
||||
if d.IsRHELFamily() {
|
||||
t = append(t, tags.TagOSFamilyRHEL)
|
||||
}
|
||||
if d.IsSystemd() {
|
||||
t = append(t, tags.TagSystemd)
|
||||
}
|
||||
|
||||
return t
|
||||
}
|
||||
|
||||
func (d Distribution) IsDebianFamily() bool {
|
||||
switch d {
|
||||
case DistributionJessie, DistributionXenial:
|
||||
return true
|
||||
case DistributionCentos7, DistributionRhel7:
|
||||
return false
|
||||
default:
|
||||
glog.Fatalf("unknown distribution: %s", d)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func (d Distribution) IsRHELFamily() bool {
|
||||
switch d {
|
||||
case DistributionJessie, DistributionXenial:
|
||||
return false
|
||||
case DistributionCentos7, DistributionRhel7:
|
||||
return true
|
||||
default:
|
||||
glog.Fatalf("unknown distribution: %s", d)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func (d Distribution) IsSystemd() bool {
|
||||
switch d {
|
||||
case DistributionJessie, DistributionXenial:
|
||||
return true
|
||||
case DistributionCentos7, DistributionRhel7:
|
||||
return false
|
||||
default:
|
||||
glog.Fatalf("unknown distribution: %s", d)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@ limitations under the License.
|
|||
package model
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/blang/semver"
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/kops/nodeup/pkg/model/resources"
|
||||
"k8s.io/kops/upup/pkg/fi"
|
||||
|
@ -182,7 +184,7 @@ 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"},
|
||||
Dependencies: []string{"libtool-ltdl", "libseccomp"},
|
||||
},
|
||||
{
|
||||
DockerVersion: "1.12.3",
|
||||
|
@ -268,5 +270,104 @@ func (b *DockerBuilder) Build(c *fi.ModelBuilderContext) error {
|
|||
}
|
||||
}
|
||||
|
||||
dockerSemver, err := semver.Parse(dockerVersion)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error parsing docker version %q as semver: %v", dockerVersion, err)
|
||||
}
|
||||
|
||||
c.AddTask(b.buildSystemdService(dockerSemver))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *DockerBuilder) buildSystemdService(dockerVersion semver.Version) *nodetasks.Service {
|
||||
oldDocker := dockerVersion.Major <= 1 && dockerVersion.Minor <= 11
|
||||
usesDockerSocket := true
|
||||
hasDockerBabysitter := false
|
||||
|
||||
var dockerdCommand string
|
||||
if oldDocker {
|
||||
dockerdCommand = "/usr/bin/docker dameon"
|
||||
} else {
|
||||
dockerdCommand = "/usr/bin/dockerd"
|
||||
}
|
||||
|
||||
if b.Distribution.IsDebianFamily() {
|
||||
hasDockerBabysitter = true
|
||||
}
|
||||
|
||||
manifest := &ServiceManifest{}
|
||||
manifest.Set("Unit", "Description", "Docker Application Container Engine")
|
||||
manifest.Set("Unit", "Documentation", "https://docs.docker.com")
|
||||
|
||||
if usesDockerSocket {
|
||||
manifest.Set("Unit", "After", "network.target docker.socket")
|
||||
manifest.Set("Unit", "Requires", "docker.socket")
|
||||
} else {
|
||||
manifest.Set("Unit", "After", "network.target")
|
||||
}
|
||||
|
||||
manifest.Set("Service", "Type", "notify")
|
||||
manifest.Set("Service", "EnvironmentFile", "/etc/sysconfig/docker")
|
||||
|
||||
if usesDockerSocket {
|
||||
manifest.Set("Service", "ExecStart", dockerdCommand+" -H fd:// \"$DOCKER_OPTS\"")
|
||||
} else {
|
||||
manifest.Set("Service", "ExecStart", dockerdCommand+" \"$DOCKER_OPTS\"")
|
||||
}
|
||||
|
||||
if !oldDocker {
|
||||
// This was added by docker 1.12
|
||||
// TODO: They seem sensible - should we backport them?
|
||||
|
||||
manifest.Set("Service", "ExecReload", "/bin/kill -s HUP $MAINPID")
|
||||
// kill only the docker process, not all processes in the cgroup
|
||||
manifest.Set("Service", "KillMode", "process")
|
||||
|
||||
manifest.Set("Service", "TimeoutStartSec", "0")
|
||||
}
|
||||
|
||||
if oldDocker {
|
||||
// Only in older versions of docker (< 1.12)
|
||||
manifest.Set("Service", "MountFlags", "slave")
|
||||
}
|
||||
|
||||
// Having non-zero Limit*s causes performance problems due to accounting overhead
|
||||
// in the kernel. We recommend using cgroups to do container-local accounting.
|
||||
// TODO: Should we set this? https://github.com/kubernetes/kubernetes/issues/39682
|
||||
//service.Set("Service", "LimitNOFILE", "infinity")
|
||||
//service.Set("Service", "LimitNPROC", "infinity")
|
||||
//service.Set("Service", "LimitCORE", "infinity")
|
||||
manifest.Set("Service", "LimitNOFILE", "1048576")
|
||||
manifest.Set("Service", "LimitNPROC", "1048576")
|
||||
manifest.Set("Service", "LimitCORE", "infinity")
|
||||
|
||||
//# Uncomment TasksMax if your systemd version supports it.
|
||||
//# Only systemd 226 and above support this version.
|
||||
//#TasksMax=infinity
|
||||
|
||||
manifest.Set("Service", "Restart", "always")
|
||||
manifest.Set("Service", "RestartSec", "2s")
|
||||
manifest.Set("Service", "StartLimitInterval", "0")
|
||||
|
||||
// set delegate yes so that systemd does not reset the cgroups of docker containers
|
||||
manifest.Set("Service", "Delegate", "yes")
|
||||
|
||||
if hasDockerBabysitter {
|
||||
manifest.Set("Service", "ExecStartPre", "/opt/kubernetes/helpers/docker-prestart")
|
||||
}
|
||||
|
||||
manifest.Set("Install", "WantedBy", "multi-user.target")
|
||||
|
||||
manifestString := manifest.Render()
|
||||
glog.V(8).Infof("Built service manifest %q\n%s", "docker", manifestString)
|
||||
|
||||
service := &nodetasks.Service{
|
||||
Name: "docker",
|
||||
Definition: s(manifestString),
|
||||
}
|
||||
|
||||
service.InitDefaults()
|
||||
|
||||
return service
|
||||
}
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package model
|
||||
|
||||
import "bytes"
|
||||
|
||||
type ServiceManifest struct {
|
||||
Sections []*ServiceManifestSection
|
||||
}
|
||||
|
||||
type ServiceManifestSection struct {
|
||||
Key string
|
||||
Entries []*ServiceManifestEntry
|
||||
}
|
||||
|
||||
type ServiceManifestEntry struct {
|
||||
Key string
|
||||
Value string
|
||||
}
|
||||
|
||||
func (s *ServiceManifest) Set(sectionKey string, key string, value string) {
|
||||
section := s.getOrCreateSection(sectionKey)
|
||||
section.Set(key, value)
|
||||
}
|
||||
|
||||
func (s *ServiceManifest) getOrCreateSection(key string) *ServiceManifestSection {
|
||||
for _, section := range s.Sections {
|
||||
if section.Key == key {
|
||||
return section
|
||||
}
|
||||
}
|
||||
section := &ServiceManifestSection{
|
||||
Key: key,
|
||||
}
|
||||
s.Sections = append(s.Sections, section)
|
||||
return section
|
||||
}
|
||||
|
||||
func (s *ServiceManifest) Render() string {
|
||||
var b bytes.Buffer
|
||||
|
||||
for i, section := range s.Sections {
|
||||
if i != 0 {
|
||||
b.WriteString("\n")
|
||||
}
|
||||
b.WriteString(section.Render())
|
||||
}
|
||||
|
||||
return b.String()
|
||||
}
|
||||
|
||||
func (s *ServiceManifestSection) Set(key string, value string) {
|
||||
for _, entry := range s.Entries {
|
||||
if entry.Key == key {
|
||||
entry.Value = value
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
entry := &ServiceManifestEntry{
|
||||
Key: key,
|
||||
Value: value,
|
||||
}
|
||||
s.Entries = append(s.Entries, entry)
|
||||
}
|
||||
|
||||
func (s *ServiceManifestSection) Render() string {
|
||||
var b bytes.Buffer
|
||||
|
||||
b.WriteString("[" + s.Key + "]\n")
|
||||
for _, entry := range s.Entries {
|
||||
b.WriteString(entry.Key + "=" + entry.Value + "\n")
|
||||
}
|
||||
|
||||
return b.String()
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
[Unit]
|
||||
Description=Docker Application Container Engine
|
||||
Documentation=https://docs.docker.com
|
||||
After=network.target docker.socket
|
||||
Requires=docker.socket
|
||||
|
||||
[Service]
|
||||
Type=notify
|
||||
EnvironmentFile=/etc/sysconfig/docker
|
||||
ExecStart=/usr/bin/docker daemon -H fd:// "$DOCKER_OPTS"
|
||||
MountFlags=slave
|
||||
LimitNOFILE=1048576
|
||||
LimitNPROC=1048576
|
||||
LimitCORE=infinity
|
||||
Restart=always
|
||||
RestartSec=2s
|
||||
StartLimitInterval=0
|
||||
ExecStartPre=/opt/kubernetes/helpers/docker-prestart
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
|
@ -1,22 +0,0 @@
|
|||
[Unit]
|
||||
Description=Docker Application Container Engine
|
||||
Documentation=https://docs.docker.com
|
||||
After=network.target docker.socket
|
||||
Requires=docker.socket
|
||||
|
||||
[Service]
|
||||
Type=notify
|
||||
EnvironmentFile=/etc/sysconfig/docker
|
||||
ExecStart=/usr/bin/docker daemon -H fd:// "$DOCKER_OPTS"
|
||||
MountFlags=slave
|
||||
LimitNOFILE=1048576
|
||||
LimitNPROC=1048576
|
||||
LimitCORE=infinity
|
||||
Restart=always
|
||||
RestartSec=2s
|
||||
StartLimitInterval=0
|
||||
# set delegate yes so that systemd does not reset the cgroups of docker containers
|
||||
Delegate=yes
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
|
@ -55,6 +55,7 @@ type Service struct {
|
|||
}
|
||||
|
||||
var _ fi.HasDependencies = &Service{}
|
||||
var _ fi.HasName = &Service{}
|
||||
|
||||
func (p *Service) GetDependencies(tasks map[string]fi.Task) []fi.Task {
|
||||
var deps []fi.Task
|
||||
|
@ -91,6 +92,12 @@ func NewService(name string, contents string, meta string) (fi.Task, error) {
|
|||
}
|
||||
}
|
||||
|
||||
s.InitDefaults()
|
||||
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func (s *Service) InitDefaults() {
|
||||
// Default some values to true: Running, SmartRestart, ManageState
|
||||
if s.Running == nil {
|
||||
s.Running = fi.Bool(true)
|
||||
|
@ -106,8 +113,6 @@ func NewService(name string, contents string, meta string) (fi.Task, error) {
|
|||
if s.Enabled == nil {
|
||||
s.Enabled = s.Running
|
||||
}
|
||||
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func getSystemdStatus(name string) (map[string]string, error) {
|
||||
|
@ -374,3 +379,13 @@ func (_ *Service) RenderCloudInit(t *cloudinit.CloudInitTarget, a, e, changes *S
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
var _ fi.HasName = &Service{}
|
||||
|
||||
func (f *Service) GetName() *string {
|
||||
return &f.Name
|
||||
}
|
||||
|
||||
func (f *Service) SetName(name string) {
|
||||
glog.Fatalf("SetName not supported for Service task")
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue