2018-02-13 00:47:56 +00:00
package cluster
import (
"context"
"fmt"
2018-04-11 22:54:47 +00:00
"path"
2018-02-13 00:47:56 +00:00
"strconv"
2018-02-14 20:58:35 +00:00
"strings"
2018-02-13 00:47:56 +00:00
2018-03-29 20:58:46 +00:00
b64 "encoding/base64"
2018-04-18 03:16:57 +00:00
ref "github.com/docker/distribution/reference"
2018-04-11 22:54:47 +00:00
"github.com/docker/docker/api/types"
2018-06-06 17:11:47 +00:00
"github.com/rancher/rke/cloudprovider/aws"
2018-04-03 20:18:51 +00:00
"github.com/rancher/rke/docker"
2018-02-13 00:47:56 +00:00
"github.com/rancher/rke/hosts"
2018-04-03 19:27:04 +00:00
"github.com/rancher/rke/k8s"
2018-02-13 00:47:56 +00:00
"github.com/rancher/rke/pki"
"github.com/rancher/rke/services"
"github.com/rancher/types/apis/management.cattle.io/v3"
)
2018-02-14 20:58:35 +00:00
const (
2018-05-03 20:07:41 +00:00
EtcdPathPrefix = "/registry"
B2DOS = "Boot2Docker"
B2DPrefixPath = "/mnt/sda1/rke"
ROS = "RancherOS"
ROSPrefixPath = "/opt/rke"
2018-05-10 17:55:16 +00:00
CoreOS = "CoreOS"
CoreOSPrefixPath = "/opt/rke"
2018-05-03 20:07:41 +00:00
ContainerNameLabel = "io.rancher.rke.container.name"
2018-02-14 20:58:35 +00:00
)
2018-04-11 22:54:47 +00:00
func GeneratePlan ( ctx context . Context , rkeConfig * v3 . RancherKubernetesEngineConfig , hostsInfoMap map [ string ] types . Info ) ( v3 . RKEPlan , error ) {
2018-02-13 00:47:56 +00:00
clusterPlan := v3 . RKEPlan { }
2018-04-19 15:54:15 +00:00
myCluster , err := ParseCluster ( ctx , rkeConfig , "" , "" , nil , nil , nil )
if err != nil {
return clusterPlan , err
}
2018-02-13 00:47:56 +00:00
// rkeConfig.Nodes are already unique. But they don't have role flags. So I will use the parsed cluster.Hosts to make use of the role flags.
uniqHosts := hosts . GetUniqueHostList ( myCluster . EtcdHosts , myCluster . ControlPlaneHosts , myCluster . WorkerHosts )
for _ , host := range uniqHosts {
2018-04-25 22:02:40 +00:00
host . DockerInfo = hostsInfoMap [ host . Address ]
2018-04-11 22:54:47 +00:00
clusterPlan . Nodes = append ( clusterPlan . Nodes , BuildRKEConfigNodePlan ( ctx , myCluster , host , hostsInfoMap [ host . Address ] ) )
2018-02-13 00:47:56 +00:00
}
return clusterPlan , nil
}
2018-04-11 22:54:47 +00:00
func BuildRKEConfigNodePlan ( ctx context . Context , myCluster * Cluster , host * hosts . Host , hostDockerInfo types . Info ) v3 . RKEConfigNodePlan {
prefixPath := myCluster . getPrefixPath ( hostDockerInfo . OperatingSystem )
2018-02-24 13:08:46 +00:00
processes := map [ string ] v3 . Process { }
2018-02-13 00:47:56 +00:00
portChecks := [ ] v3 . PortCheck { }
// Everybody gets a sidecar and a kubelet..
2018-02-24 13:08:46 +00:00
processes [ services . SidekickContainerName ] = myCluster . BuildSidecarProcess ( )
2018-04-11 22:54:47 +00:00
processes [ services . KubeletContainerName ] = myCluster . BuildKubeletProcess ( host , prefixPath )
processes [ services . KubeproxyContainerName ] = myCluster . BuildKubeProxyProcess ( prefixPath )
2018-02-13 00:47:56 +00:00
portChecks = append ( portChecks , BuildPortChecksFromPortList ( host , WorkerPortList , ProtocolTCP ) ... )
// Do we need an nginxProxy for this one ?
2018-04-14 17:18:51 +00:00
if ! host . IsControl {
2018-02-24 13:08:46 +00:00
processes [ services . NginxProxyContainerName ] = myCluster . BuildProxyProcess ( )
2018-02-13 00:47:56 +00:00
}
if host . IsControl {
2018-04-11 22:54:47 +00:00
processes [ services . KubeAPIContainerName ] = myCluster . BuildKubeAPIProcess ( prefixPath )
processes [ services . KubeControllerContainerName ] = myCluster . BuildKubeControllerProcess ( prefixPath )
processes [ services . SchedulerContainerName ] = myCluster . BuildSchedulerProcess ( prefixPath )
2018-02-13 00:47:56 +00:00
portChecks = append ( portChecks , BuildPortChecksFromPortList ( host , ControlPlanePortList , ProtocolTCP ) ... )
}
if host . IsEtcd {
2018-04-14 18:38:07 +00:00
processes [ services . EtcdContainerName ] = myCluster . BuildEtcdProcess ( host , myCluster . EtcdReadyHosts , prefixPath )
2018-02-13 00:47:56 +00:00
portChecks = append ( portChecks , BuildPortChecksFromPortList ( host , EtcdPortList , ProtocolTCP ) ... )
}
2018-03-29 20:58:46 +00:00
cloudConfig := v3 . File {
Name : CloudConfigPath ,
Contents : b64 . StdEncoding . EncodeToString ( [ ] byte ( myCluster . CloudConfigFile ) ) ,
}
2018-02-13 00:47:56 +00:00
return v3 . RKEConfigNodePlan {
Address : host . Address ,
Processes : processes ,
PortChecks : portChecks ,
2018-03-29 20:58:46 +00:00
Files : [ ] v3 . File { cloudConfig } ,
2018-04-03 19:27:04 +00:00
Annotations : map [ string ] string {
k8s . ExternalAddressAnnotation : host . Address ,
k8s . InternalAddressAnnotation : host . InternalAddress ,
} ,
2018-04-04 10:02:11 +00:00
Labels : host . ToAddLabels ,
2018-02-13 00:47:56 +00:00
}
}
2018-04-11 22:54:47 +00:00
func ( c * Cluster ) BuildKubeAPIProcess ( prefixPath string ) v3 . Process {
2018-02-14 20:58:35 +00:00
// check if external etcd is used
etcdConnectionString := services . GetEtcdConnString ( c . EtcdHosts )
etcdPathPrefix := EtcdPathPrefix
etcdClientCert := pki . GetCertPath ( pki . KubeNodeCertName )
etcdClientKey := pki . GetKeyPath ( pki . KubeNodeCertName )
etcdCAClientCert := pki . GetCertPath ( pki . CACertName )
2018-05-03 19:37:44 +00:00
// check apiserver count
apiserverCount := len ( c . ControlPlaneHosts )
2018-02-14 20:58:35 +00:00
if len ( c . Services . Etcd . ExternalURLs ) > 0 {
etcdConnectionString = strings . Join ( c . Services . Etcd . ExternalURLs , "," )
etcdPathPrefix = c . Services . Etcd . Path
etcdClientCert = pki . GetCertPath ( pki . EtcdClientCertName )
etcdClientKey = pki . GetKeyPath ( pki . EtcdClientCertName )
etcdCAClientCert = pki . GetCertPath ( pki . EtcdClientCACertName )
}
2018-02-13 00:47:56 +00:00
Command := [ ] string {
"/opt/rke/entrypoint.sh" ,
"kube-apiserver" ,
}
2018-03-14 23:37:04 +00:00
CommandArgs := map [ string ] string {
"insecure-bind-address" : "127.0.0.1" ,
"bind-address" : "0.0.0.0" ,
"insecure-port" : "0" ,
"secure-port" : "6443" ,
2018-03-23 18:14:11 +00:00
"cloud-provider" : c . CloudProvider . Name ,
2018-03-30 22:43:34 +00:00
"allow-privileged" : "true" ,
2018-03-14 23:37:04 +00:00
"kubelet-preferred-address-types" : "InternalIP,ExternalIP,Hostname" ,
"service-cluster-ip-range" : c . Services . KubeAPI . ServiceClusterIPRange ,
"admission-control" : "ServiceAccount,NamespaceLifecycle,LimitRanger,PersistentVolumeLabel,DefaultStorageClass,ResourceQuota,DefaultTolerationSeconds" ,
"storage-backend" : "etcd3" ,
"client-ca-file" : pki . GetCertPath ( pki . CACertName ) ,
"tls-cert-file" : pki . GetCertPath ( pki . KubeAPICertName ) ,
"tls-private-key-file" : pki . GetKeyPath ( pki . KubeAPICertName ) ,
"kubelet-client-certificate" : pki . GetCertPath ( pki . KubeAPICertName ) ,
"kubelet-client-key" : pki . GetKeyPath ( pki . KubeAPICertName ) ,
"service-account-key-file" : pki . GetKeyPath ( pki . KubeAPICertName ) ,
2018-05-03 19:37:44 +00:00
"apiserver-count" : strconv . Itoa ( apiserverCount ) ,
2018-03-14 23:37:04 +00:00
}
2018-06-06 17:11:47 +00:00
if len ( c . CloudProvider . Name ) > 0 && c . CloudProvider . Name != aws . AWSCloudProviderName {
2018-03-28 19:46:28 +00:00
CommandArgs [ "cloud-config" ] = CloudConfigPath
}
2018-04-11 17:28:26 +00:00
// check if our version has specific options for this component
2018-04-18 03:16:57 +00:00
serviceOptions := c . GetKubernetesServicesOptions ( )
2018-04-17 23:08:21 +00:00
if serviceOptions . KubeAPI != nil {
2018-04-11 17:28:26 +00:00
for k , v := range serviceOptions . KubeAPI {
CommandArgs [ k ] = v
}
}
2018-02-14 20:58:35 +00:00
args := [ ] string {
"--etcd-cafile=" + etcdCAClientCert ,
"--etcd-certfile=" + etcdClientCert ,
"--etcd-keyfile=" + etcdClientKey ,
"--etcd-servers=" + etcdConnectionString ,
"--etcd-prefix=" + etcdPathPrefix ,
}
2018-02-13 00:47:56 +00:00
if c . Authorization . Mode == services . RBACAuthorizationMode {
2018-03-14 23:37:04 +00:00
CommandArgs [ "authorization-mode" ] = "Node,RBAC"
2018-02-13 00:47:56 +00:00
}
if c . Services . KubeAPI . PodSecurityPolicy {
2018-03-14 23:37:04 +00:00
CommandArgs [ "runtime-config" ] = "extensions/v1beta1/podsecuritypolicy=true"
CommandArgs [ "admission-control" ] = CommandArgs [ "admission-control" ] + ",PodSecurityPolicy"
2018-02-13 00:47:56 +00:00
}
VolumesFrom := [ ] string {
services . SidekickContainerName ,
}
Binds := [ ] string {
2018-04-11 22:54:47 +00:00
fmt . Sprintf ( "%s:/etc/kubernetes:z" , path . Join ( prefixPath , "/etc/kubernetes" ) ) ,
2018-02-13 00:47:56 +00:00
}
2018-03-14 23:37:04 +00:00
// Override args if they exist, add additional args
2018-02-13 00:47:56 +00:00
for arg , value := range c . Services . KubeAPI . ExtraArgs {
2018-03-14 23:37:04 +00:00
if _ , ok := c . Services . KubeAPI . ExtraArgs [ arg ] ; ok {
CommandArgs [ arg ] = value
}
}
for arg , value := range CommandArgs {
2018-02-13 00:47:56 +00:00
cmd := fmt . Sprintf ( "--%s=%s" , arg , value )
Command = append ( Command , cmd )
}
2018-03-16 03:20:42 +00:00
Binds = append ( Binds , c . Services . KubeAPI . ExtraBinds ... )
2018-02-13 00:47:56 +00:00
healthCheck := v3 . HealthCheck {
URL : services . GetHealthCheckURL ( true , services . KubeAPIPort ) ,
}
2018-04-03 20:18:51 +00:00
registryAuthConfig , _ , _ := docker . GetImageRegistryConfig ( c . Services . KubeAPI . Image , c . PrivateRegistriesMap )
2018-02-13 00:47:56 +00:00
return v3 . Process {
2018-04-03 20:18:51 +00:00
Name : services . KubeAPIContainerName ,
Command : Command ,
Args : args ,
VolumesFrom : VolumesFrom ,
Binds : Binds ,
NetworkMode : "host" ,
RestartPolicy : "always" ,
Image : c . Services . KubeAPI . Image ,
HealthCheck : healthCheck ,
ImageRegistryAuthConfig : registryAuthConfig ,
2018-05-03 20:07:41 +00:00
Labels : map [ string ] string {
ContainerNameLabel : services . KubeAPIContainerName ,
} ,
2018-02-13 00:47:56 +00:00
}
}
2018-04-11 22:54:47 +00:00
func ( c * Cluster ) BuildKubeControllerProcess ( prefixPath string ) v3 . Process {
2018-03-14 23:37:04 +00:00
Command := [ ] string {
"/opt/rke/entrypoint.sh" ,
2018-02-13 00:47:56 +00:00
"kube-controller-manager" ,
}
2018-03-14 23:37:04 +00:00
CommandArgs := map [ string ] string {
"address" : "0.0.0.0" ,
2018-03-23 18:14:11 +00:00
"cloud-provider" : c . CloudProvider . Name ,
2018-03-23 20:15:30 +00:00
"allow-untagged-cloud" : "true" ,
2018-03-23 18:14:11 +00:00
"configure-cloud-routes" : "false" ,
2018-03-14 23:37:04 +00:00
"leader-elect" : "true" ,
"kubeconfig" : pki . GetConfigPath ( pki . KubeControllerCertName ) ,
"enable-hostpath-provisioner" : "false" ,
"node-monitor-grace-period" : "40s" ,
"pod-eviction-timeout" : "5m0s" ,
"v" : "2" ,
"allocate-node-cidrs" : "true" ,
"cluster-cidr" : c . ClusterCIDR ,
"service-cluster-ip-range" : c . Services . KubeController . ServiceClusterIPRange ,
"service-account-private-key-file" : pki . GetKeyPath ( pki . KubeAPICertName ) ,
"root-ca-file" : pki . GetCertPath ( pki . CACertName ) ,
}
2018-06-06 17:11:47 +00:00
if len ( c . CloudProvider . Name ) > 0 && c . CloudProvider . Name != aws . AWSCloudProviderName {
2018-03-28 19:46:28 +00:00
CommandArgs [ "cloud-config" ] = CloudConfigPath
}
2018-04-11 17:28:26 +00:00
// check if our version has specific options for this component
2018-04-18 03:16:57 +00:00
serviceOptions := c . GetKubernetesServicesOptions ( )
2018-04-17 23:08:21 +00:00
if serviceOptions . KubeController != nil {
2018-04-11 17:28:26 +00:00
for k , v := range serviceOptions . KubeController {
CommandArgs [ k ] = v
}
}
2018-02-13 00:47:56 +00:00
args := [ ] string { }
if c . Authorization . Mode == services . RBACAuthorizationMode {
args = append ( args , "--use-service-account-credentials=true" )
}
VolumesFrom := [ ] string {
services . SidekickContainerName ,
}
Binds := [ ] string {
2018-04-11 22:54:47 +00:00
fmt . Sprintf ( "%s:/etc/kubernetes:z" , path . Join ( prefixPath , "/etc/kubernetes" ) ) ,
2018-02-13 00:47:56 +00:00
}
for arg , value := range c . Services . KubeController . ExtraArgs {
2018-03-14 23:37:04 +00:00
if _ , ok := c . Services . KubeController . ExtraArgs [ arg ] ; ok {
CommandArgs [ arg ] = value
}
}
for arg , value := range CommandArgs {
2018-02-13 00:47:56 +00:00
cmd := fmt . Sprintf ( "--%s=%s" , arg , value )
Command = append ( Command , cmd )
}
2018-03-16 03:20:42 +00:00
Binds = append ( Binds , c . Services . KubeController . ExtraBinds ... )
2018-02-13 00:47:56 +00:00
healthCheck := v3 . HealthCheck {
URL : services . GetHealthCheckURL ( false , services . KubeControllerPort ) ,
}
2018-04-03 20:18:51 +00:00
registryAuthConfig , _ , _ := docker . GetImageRegistryConfig ( c . Services . KubeController . Image , c . PrivateRegistriesMap )
2018-02-13 00:47:56 +00:00
return v3 . Process {
2018-04-03 20:18:51 +00:00
Name : services . KubeControllerContainerName ,
Command : Command ,
Args : args ,
VolumesFrom : VolumesFrom ,
Binds : Binds ,
NetworkMode : "host" ,
RestartPolicy : "always" ,
Image : c . Services . KubeController . Image ,
HealthCheck : healthCheck ,
ImageRegistryAuthConfig : registryAuthConfig ,
2018-05-03 20:07:41 +00:00
Labels : map [ string ] string {
ContainerNameLabel : services . KubeControllerContainerName ,
} ,
2018-02-13 00:47:56 +00:00
}
}
2018-04-11 22:54:47 +00:00
func ( c * Cluster ) BuildKubeletProcess ( host * hosts . Host , prefixPath string ) v3 . Process {
2018-02-13 00:47:56 +00:00
2018-03-14 23:37:04 +00:00
Command := [ ] string {
"/opt/rke/entrypoint.sh" ,
2018-02-13 00:47:56 +00:00
"kubelet" ,
2018-03-14 23:37:04 +00:00
}
CommandArgs := map [ string ] string {
"v" : "2" ,
"address" : "0.0.0.0" ,
"cadvisor-port" : "0" ,
"read-only-port" : "0" ,
"cluster-domain" : c . ClusterDomain ,
"pod-infra-container-image" : c . Services . Kubelet . InfraContainerImage ,
"cgroups-per-qos" : "True" ,
"enforce-node-allocatable" : "" ,
"hostname-override" : host . HostnameOverride ,
"cluster-dns" : c . ClusterDNSServer ,
"network-plugin" : "cni" ,
"cni-conf-dir" : "/etc/cni/net.d" ,
"cni-bin-dir" : "/opt/cni/bin" ,
"resolv-conf" : "/etc/resolv.conf" ,
"allow-privileged" : "true" ,
2018-03-23 18:14:11 +00:00
"cloud-provider" : c . CloudProvider . Name ,
2018-03-14 23:37:04 +00:00
"kubeconfig" : pki . GetConfigPath ( pki . KubeNodeCertName ) ,
"client-ca-file" : pki . GetCertPath ( pki . CACertName ) ,
"anonymous-auth" : "false" ,
"volume-plugin-dir" : "/var/lib/kubelet/volumeplugins" ,
"fail-swap-on" : strconv . FormatBool ( c . Services . Kubelet . FailSwapOn ) ,
2018-04-11 22:54:47 +00:00
"root-dir" : path . Join ( prefixPath , "/var/lib/kubelet" ) ,
2018-02-13 00:47:56 +00:00
}
2018-03-26 22:53:28 +00:00
if host . Address != host . InternalAddress {
CommandArgs [ "node-ip" ] = host . InternalAddress
}
2018-06-06 17:11:47 +00:00
if len ( c . CloudProvider . Name ) > 0 && c . CloudProvider . Name != aws . AWSCloudProviderName {
2018-03-28 19:46:28 +00:00
CommandArgs [ "cloud-config" ] = CloudConfigPath
}
2018-04-11 17:28:26 +00:00
// check if our version has specific options for this component
2018-04-18 03:16:57 +00:00
serviceOptions := c . GetKubernetesServicesOptions ( )
2018-04-17 23:08:21 +00:00
if serviceOptions . Kubelet != nil {
2018-04-11 17:28:26 +00:00
for k , v := range serviceOptions . Kubelet {
CommandArgs [ k ] = v
}
}
2018-02-13 00:47:56 +00:00
VolumesFrom := [ ] string {
services . SidekickContainerName ,
}
Binds := [ ] string {
2018-04-11 22:54:47 +00:00
fmt . Sprintf ( "%s:/etc/kubernetes:z" , path . Join ( prefixPath , "/etc/kubernetes" ) ) ,
2018-04-24 20:43:50 +00:00
"/etc/cni:/etc/cni:rw,z" ,
"/opt/cni:/opt/cni:rw,z" ,
2018-04-11 22:54:47 +00:00
fmt . Sprintf ( "%s:/var/lib/cni:z" , path . Join ( prefixPath , "/var/lib/cni" ) ) ,
2018-04-26 03:10:53 +00:00
"/var/lib/calico:/var/lib/calico:z" ,
2018-02-13 00:47:56 +00:00
"/etc/resolv.conf:/etc/resolv.conf" ,
2018-03-05 08:42:49 +00:00
"/sys:/sys:rprivate" ,
2018-04-10 16:49:38 +00:00
host . DockerInfo . DockerRootDir + ":" + host . DockerInfo . DockerRootDir + ":rw,rslave,z" ,
2018-04-11 22:54:47 +00:00
fmt . Sprintf ( "%s:%s:shared,z" , path . Join ( prefixPath , "/var/lib/kubelet" ) , path . Join ( prefixPath , "/var/lib/kubelet" ) ) ,
2018-04-18 20:53:14 +00:00
"/var/lib/rancher:/var/lib/rancher:shared,z" ,
2018-03-05 08:42:49 +00:00
"/var/run:/var/run:rw,rprivate" ,
"/run:/run:rprivate" ,
2018-04-11 22:54:47 +00:00
fmt . Sprintf ( "%s:/etc/ceph" , path . Join ( prefixPath , "/etc/ceph" ) ) ,
2018-03-30 18:00:19 +00:00
"/dev:/host/dev:rprivate" ,
2018-04-11 22:54:47 +00:00
fmt . Sprintf ( "%s:/var/log/containers:z" , path . Join ( prefixPath , "/var/log/containers" ) ) ,
fmt . Sprintf ( "%s:/var/log/pods:z" , path . Join ( prefixPath , "/var/log/pods" ) ) ,
2018-04-24 08:43:06 +00:00
"/usr:/host/usr:ro" ,
"/etc:/host/etc:ro" ,
2018-02-13 00:47:56 +00:00
}
for arg , value := range c . Services . Kubelet . ExtraArgs {
2018-03-14 23:37:04 +00:00
if _ , ok := c . Services . Kubelet . ExtraArgs [ arg ] ; ok {
CommandArgs [ arg ] = value
}
}
for arg , value := range CommandArgs {
2018-02-13 00:47:56 +00:00
cmd := fmt . Sprintf ( "--%s=%s" , arg , value )
Command = append ( Command , cmd )
}
2018-03-16 03:20:42 +00:00
Binds = append ( Binds , c . Services . Kubelet . ExtraBinds ... )
2018-02-13 00:47:56 +00:00
healthCheck := v3 . HealthCheck {
URL : services . GetHealthCheckURL ( true , services . KubeletPort ) ,
}
2018-04-03 20:18:51 +00:00
registryAuthConfig , _ , _ := docker . GetImageRegistryConfig ( c . Services . Kubelet . Image , c . PrivateRegistriesMap )
2018-02-13 00:47:56 +00:00
return v3 . Process {
2018-04-03 20:18:51 +00:00
Name : services . KubeletContainerName ,
Command : Command ,
VolumesFrom : VolumesFrom ,
Binds : Binds ,
NetworkMode : "host" ,
RestartPolicy : "always" ,
Image : c . Services . Kubelet . Image ,
PidMode : "host" ,
Privileged : true ,
HealthCheck : healthCheck ,
ImageRegistryAuthConfig : registryAuthConfig ,
2018-05-03 20:07:41 +00:00
Labels : map [ string ] string {
ContainerNameLabel : services . KubeletContainerName ,
} ,
2018-02-13 00:47:56 +00:00
}
}
2018-04-11 22:54:47 +00:00
func ( c * Cluster ) BuildKubeProxyProcess ( prefixPath string ) v3 . Process {
2018-03-14 23:37:04 +00:00
Command := [ ] string {
"/opt/rke/entrypoint.sh" ,
2018-02-13 00:47:56 +00:00
"kube-proxy" ,
}
2018-03-14 23:37:04 +00:00
CommandArgs := map [ string ] string {
"v" : "2" ,
"healthz-bind-address" : "0.0.0.0" ,
"kubeconfig" : pki . GetConfigPath ( pki . KubeProxyCertName ) ,
}
2018-04-11 17:28:26 +00:00
// check if our version has specific options for this component
2018-04-18 03:16:57 +00:00
serviceOptions := c . GetKubernetesServicesOptions ( )
2018-04-17 23:08:21 +00:00
if serviceOptions . Kubeproxy != nil {
2018-04-11 17:28:26 +00:00
for k , v := range serviceOptions . Kubeproxy {
CommandArgs [ k ] = v
}
}
2018-02-13 00:47:56 +00:00
VolumesFrom := [ ] string {
services . SidekickContainerName ,
}
Binds := [ ] string {
2018-04-11 22:54:47 +00:00
fmt . Sprintf ( "%s:/etc/kubernetes:z" , path . Join ( prefixPath , "/etc/kubernetes" ) ) ,
2018-02-13 00:47:56 +00:00
}
for arg , value := range c . Services . Kubeproxy . ExtraArgs {
2018-03-14 23:37:04 +00:00
if _ , ok := c . Services . Kubeproxy . ExtraArgs [ arg ] ; ok {
CommandArgs [ arg ] = value
}
}
for arg , value := range CommandArgs {
2018-02-13 00:47:56 +00:00
cmd := fmt . Sprintf ( "--%s=%s" , arg , value )
Command = append ( Command , cmd )
}
2018-03-16 03:20:42 +00:00
Binds = append ( Binds , c . Services . Kubeproxy . ExtraBinds ... )
2018-02-13 00:47:56 +00:00
healthCheck := v3 . HealthCheck {
URL : services . GetHealthCheckURL ( false , services . KubeproxyPort ) ,
}
2018-04-03 20:18:51 +00:00
registryAuthConfig , _ , _ := docker . GetImageRegistryConfig ( c . Services . Kubeproxy . Image , c . PrivateRegistriesMap )
2018-02-13 00:47:56 +00:00
return v3 . Process {
2018-02-24 13:08:46 +00:00
Name : services . KubeproxyContainerName ,
2018-02-13 00:47:56 +00:00
Command : Command ,
VolumesFrom : VolumesFrom ,
Binds : Binds ,
NetworkMode : "host" ,
RestartPolicy : "always" ,
PidMode : "host" ,
Privileged : true ,
HealthCheck : healthCheck ,
Image : c . Services . Kubeproxy . Image ,
2018-04-03 20:18:51 +00:00
ImageRegistryAuthConfig : registryAuthConfig ,
2018-05-03 20:07:41 +00:00
Labels : map [ string ] string {
ContainerNameLabel : services . KubeproxyContainerName ,
} ,
2018-02-13 00:47:56 +00:00
}
}
func ( c * Cluster ) BuildProxyProcess ( ) v3 . Process {
nginxProxyEnv := ""
for i , host := range c . ControlPlaneHosts {
nginxProxyEnv += fmt . Sprintf ( "%s" , host . InternalAddress )
if i < ( len ( c . ControlPlaneHosts ) - 1 ) {
nginxProxyEnv += ","
}
}
Env := [ ] string { fmt . Sprintf ( "%s=%s" , services . NginxProxyEnvName , nginxProxyEnv ) }
2018-04-03 20:18:51 +00:00
registryAuthConfig , _ , _ := docker . GetImageRegistryConfig ( c . SystemImages . NginxProxy , c . PrivateRegistriesMap )
2018-02-13 00:47:56 +00:00
return v3 . Process {
2018-04-22 20:55:34 +00:00
Name : services . NginxProxyContainerName ,
Env : Env ,
// we do this to force container update when CP hosts change.
Args : Env ,
Command : [ ] string { "nginx-proxy" } ,
2018-02-13 00:47:56 +00:00
NetworkMode : "host" ,
RestartPolicy : "always" ,
HealthCheck : v3 . HealthCheck { } ,
Image : c . SystemImages . NginxProxy ,
2018-04-03 20:18:51 +00:00
ImageRegistryAuthConfig : registryAuthConfig ,
2018-05-03 20:07:41 +00:00
Labels : map [ string ] string {
ContainerNameLabel : services . NginxProxyContainerName ,
} ,
2018-02-13 00:47:56 +00:00
}
}
2018-04-11 22:54:47 +00:00
func ( c * Cluster ) BuildSchedulerProcess ( prefixPath string ) v3 . Process {
2018-03-14 23:37:04 +00:00
Command := [ ] string {
"/opt/rke/entrypoint.sh" ,
2018-02-13 00:47:56 +00:00
"kube-scheduler" ,
}
2018-03-14 23:37:04 +00:00
CommandArgs := map [ string ] string {
"leader-elect" : "true" ,
"v" : "2" ,
"address" : "0.0.0.0" ,
"kubeconfig" : pki . GetConfigPath ( pki . KubeSchedulerCertName ) ,
}
2018-04-11 17:28:26 +00:00
// check if our version has specific options for this component
2018-04-18 03:16:57 +00:00
serviceOptions := c . GetKubernetesServicesOptions ( )
2018-04-17 23:08:21 +00:00
if serviceOptions . Scheduler != nil {
2018-04-11 17:28:26 +00:00
for k , v := range serviceOptions . Scheduler {
CommandArgs [ k ] = v
}
}
2018-02-13 00:47:56 +00:00
VolumesFrom := [ ] string {
services . SidekickContainerName ,
}
Binds := [ ] string {
2018-04-11 22:54:47 +00:00
fmt . Sprintf ( "%s:/etc/kubernetes:z" , path . Join ( prefixPath , "/etc/kubernetes" ) ) ,
2018-02-13 00:47:56 +00:00
}
for arg , value := range c . Services . Scheduler . ExtraArgs {
2018-03-14 23:37:04 +00:00
if _ , ok := c . Services . Scheduler . ExtraArgs [ arg ] ; ok {
CommandArgs [ arg ] = value
}
}
for arg , value := range CommandArgs {
2018-02-13 00:47:56 +00:00
cmd := fmt . Sprintf ( "--%s=%s" , arg , value )
Command = append ( Command , cmd )
}
2018-03-16 03:20:42 +00:00
Binds = append ( Binds , c . Services . Scheduler . ExtraBinds ... )
2018-02-13 00:47:56 +00:00
healthCheck := v3 . HealthCheck {
URL : services . GetHealthCheckURL ( false , services . SchedulerPort ) ,
}
2018-04-03 20:18:51 +00:00
registryAuthConfig , _ , _ := docker . GetImageRegistryConfig ( c . Services . Scheduler . Image , c . PrivateRegistriesMap )
2018-02-13 00:47:56 +00:00
return v3 . Process {
2018-04-03 20:18:51 +00:00
Name : services . SchedulerContainerName ,
Command : Command ,
Binds : Binds ,
VolumesFrom : VolumesFrom ,
NetworkMode : "host" ,
RestartPolicy : "always" ,
Image : c . Services . Scheduler . Image ,
HealthCheck : healthCheck ,
ImageRegistryAuthConfig : registryAuthConfig ,
2018-05-03 20:07:41 +00:00
Labels : map [ string ] string {
ContainerNameLabel : services . SchedulerContainerName ,
} ,
2018-02-13 00:47:56 +00:00
}
}
func ( c * Cluster ) BuildSidecarProcess ( ) v3 . Process {
2018-04-03 20:18:51 +00:00
registryAuthConfig , _ , _ := docker . GetImageRegistryConfig ( c . SystemImages . KubernetesServicesSidecar , c . PrivateRegistriesMap )
2018-02-13 00:47:56 +00:00
return v3 . Process {
2018-04-03 20:18:51 +00:00
Name : services . SidekickContainerName ,
NetworkMode : "none" ,
Image : c . SystemImages . KubernetesServicesSidecar ,
HealthCheck : v3 . HealthCheck { } ,
ImageRegistryAuthConfig : registryAuthConfig ,
2018-05-03 20:07:41 +00:00
Labels : map [ string ] string {
ContainerNameLabel : services . SidekickContainerName ,
} ,
2018-02-13 00:47:56 +00:00
}
}
2018-04-11 22:54:47 +00:00
func ( c * Cluster ) BuildEtcdProcess ( host * hosts . Host , etcdHosts [ ] * hosts . Host , prefixPath string ) v3 . Process {
2018-02-13 00:47:56 +00:00
nodeName := pki . GetEtcdCrtName ( host . InternalAddress )
initCluster := ""
if len ( etcdHosts ) == 0 {
initCluster = services . GetEtcdInitialCluster ( c . EtcdHosts )
} else {
initCluster = services . GetEtcdInitialCluster ( etcdHosts )
}
clusterState := "new"
if host . ExistingEtcdCluster {
clusterState = "existing"
}
2018-03-14 23:37:04 +00:00
args := [ ] string {
"/usr/local/bin/etcd" ,
2018-02-13 00:47:56 +00:00
"--peer-client-cert-auth" ,
"--client-cert-auth" ,
2018-03-14 23:37:04 +00:00
}
2018-04-20 04:07:44 +00:00
// If InternalAddress is not explicitly set, it's set to the same value as Address. This is all good until we deploy on a host with a DNATed public address like AWS, in that case we can't bind to that address so we fall back to 0.0.0.0
listenAddress := host . InternalAddress
if host . Address == host . InternalAddress {
listenAddress = "0.0.0.0"
}
2018-03-14 23:37:04 +00:00
CommandArgs := map [ string ] string {
"name" : "etcd-" + host . HostnameOverride ,
2018-05-15 21:06:05 +00:00
"data-dir" : services . EtcdDataDir ,
2018-03-14 23:37:04 +00:00
"advertise-client-urls" : "https://" + host . InternalAddress + ":2379,https://" + host . InternalAddress + ":4001" ,
2018-04-20 04:07:44 +00:00
"listen-client-urls" : "https://" + listenAddress + ":2379" ,
2018-03-14 23:37:04 +00:00
"initial-advertise-peer-urls" : "https://" + host . InternalAddress + ":2380" ,
2018-04-20 04:07:44 +00:00
"listen-peer-urls" : "https://" + listenAddress + ":2380" ,
2018-03-14 23:37:04 +00:00
"initial-cluster-token" : "etcd-cluster-1" ,
"initial-cluster" : initCluster ,
"initial-cluster-state" : clusterState ,
"trusted-ca-file" : pki . GetCertPath ( pki . CACertName ) ,
"peer-trusted-ca-file" : pki . GetCertPath ( pki . CACertName ) ,
"cert-file" : pki . GetCertPath ( nodeName ) ,
"key-file" : pki . GetKeyPath ( nodeName ) ,
"peer-cert-file" : pki . GetCertPath ( nodeName ) ,
"peer-key-file" : pki . GetKeyPath ( nodeName ) ,
2018-02-13 00:47:56 +00:00
}
Binds := [ ] string {
2018-05-15 21:06:05 +00:00
fmt . Sprintf ( "%s:%s:z" , path . Join ( prefixPath , "/var/lib/etcd" ) , services . EtcdDataDir ) ,
2018-04-11 22:54:47 +00:00
fmt . Sprintf ( "%s:/etc/kubernetes:z" , path . Join ( prefixPath , "/etc/kubernetes" ) ) ,
2018-02-13 00:47:56 +00:00
}
2018-03-16 03:20:42 +00:00
2018-02-13 00:47:56 +00:00
for arg , value := range c . Services . Etcd . ExtraArgs {
2018-03-14 23:37:04 +00:00
if _ , ok := c . Services . Etcd . ExtraArgs [ arg ] ; ok {
CommandArgs [ arg ] = value
}
}
for arg , value := range CommandArgs {
2018-02-13 00:47:56 +00:00
cmd := fmt . Sprintf ( "--%s=%s" , arg , value )
args = append ( args , cmd )
}
2018-03-16 03:20:42 +00:00
Binds = append ( Binds , c . Services . Etcd . ExtraBinds ... )
2018-02-13 00:47:56 +00:00
healthCheck := v3 . HealthCheck {
2018-04-20 20:17:45 +00:00
URL : fmt . Sprintf ( "https://%s:2379/health" , host . InternalAddress ) ,
2018-02-13 00:47:56 +00:00
}
2018-04-03 20:18:51 +00:00
registryAuthConfig , _ , _ := docker . GetImageRegistryConfig ( c . Services . Etcd . Image , c . PrivateRegistriesMap )
2018-05-02 11:47:53 +00:00
Env := [ ] string { }
Env = append ( Env , "ETCDCTL_API=3" )
Env = append ( Env , fmt . Sprintf ( "ETCDCTL_ENDPOINT=https://%s:2379" , listenAddress ) )
Env = append ( Env , fmt . Sprintf ( "ETCDCTL_CACERT=%s" , pki . GetCertPath ( pki . CACertName ) ) )
Env = append ( Env , fmt . Sprintf ( "ETCDCTL_CERT=%s" , pki . GetCertPath ( nodeName ) ) )
Env = append ( Env , fmt . Sprintf ( "ETCDCTL_KEY=%s" , pki . GetKeyPath ( nodeName ) ) )
2018-02-13 00:47:56 +00:00
return v3 . Process {
2018-04-03 20:18:51 +00:00
Name : services . EtcdContainerName ,
Args : args ,
Binds : Binds ,
2018-05-02 11:47:53 +00:00
Env : Env ,
2018-04-03 20:18:51 +00:00
NetworkMode : "host" ,
RestartPolicy : "always" ,
Image : c . Services . Etcd . Image ,
HealthCheck : healthCheck ,
ImageRegistryAuthConfig : registryAuthConfig ,
2018-05-03 20:07:41 +00:00
Labels : map [ string ] string {
ContainerNameLabel : services . EtcdContainerName ,
} ,
2018-02-13 00:47:56 +00:00
}
}
func BuildPortChecksFromPortList ( host * hosts . Host , portList [ ] string , proto string ) [ ] v3 . PortCheck {
portChecks := [ ] v3 . PortCheck { }
for _ , port := range portList {
intPort , _ := strconv . Atoi ( port )
portChecks = append ( portChecks , v3 . PortCheck {
Address : host . Address ,
Port : intPort ,
Protocol : proto ,
} )
}
return portChecks
}
2018-04-11 22:54:47 +00:00
func ( c * Cluster ) getPrefixPath ( osType string ) string {
var prefixPath string
2018-05-10 17:55:16 +00:00
switch {
2018-05-15 00:54:31 +00:00
case c . PrefixPath != "/" :
prefixPath = c . PrefixPath
2018-05-10 17:55:16 +00:00
case strings . Contains ( osType , B2DOS ) :
2018-04-11 22:54:47 +00:00
prefixPath = B2DPrefixPath
2018-05-10 17:55:16 +00:00
case strings . Contains ( osType , ROS ) :
2018-04-11 22:54:47 +00:00
prefixPath = ROSPrefixPath
2018-05-10 17:55:16 +00:00
case strings . Contains ( osType , CoreOS ) :
prefixPath = CoreOSPrefixPath
default :
2018-04-11 22:54:47 +00:00
prefixPath = c . PrefixPath
}
return prefixPath
}
2018-04-17 23:08:21 +00:00
2018-04-18 03:16:57 +00:00
func ( c * Cluster ) GetKubernetesServicesOptions ( ) v3 . KubernetesServicesOptions {
clusterMajorVersion := getTagMajorVersion ( c . Version )
NamedkK8sImage , _ := ref . ParseNormalizedNamed ( c . SystemImages . Kubernetes )
2018-04-18 06:52:55 +00:00
2018-04-18 03:16:57 +00:00
k8sImageTag := NamedkK8sImage . ( ref . Tagged ) . Tag ( )
k8sImageMajorVersion := getTagMajorVersion ( k8sImageTag )
2018-04-18 06:52:55 +00:00
if clusterMajorVersion != k8sImageMajorVersion && k8sImageMajorVersion != "" {
2018-04-18 03:16:57 +00:00
clusterMajorVersion = k8sImageMajorVersion
}
serviceOptions , ok := v3 . K8sVersionServiceOptions [ clusterMajorVersion ]
2018-04-17 23:08:21 +00:00
if ok {
return serviceOptions
}
return v3 . KubernetesServicesOptions { }
}
2018-04-18 03:16:57 +00:00
func getTagMajorVersion ( tag string ) string {
splitTag := strings . Split ( tag , "." )
2018-04-18 06:52:55 +00:00
if len ( splitTag ) < 2 {
return ""
}
2018-04-18 03:16:57 +00:00
return strings . Join ( splitTag [ : 2 ] , "." )
}