1
16
17 package controlplane
18
19 import (
20 "fmt"
21 "os"
22 "path/filepath"
23 "strings"
24
25 v1 "k8s.io/api/core/v1"
26 "k8s.io/apimachinery/pkg/util/sets"
27
28 kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
29 kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
30 staticpodutil "k8s.io/kubernetes/cmd/kubeadm/app/util/staticpod"
31 )
32
33 const (
34 caCertsVolumeName = "ca-certs"
35 caCertsVolumePath = "/etc/ssl/certs"
36 flexvolumeDirVolumeName = "flexvolume-dir"
37 defaultFlexvolumeDirVolumePath = "/usr/libexec/kubernetes/kubelet-plugins/volume/exec"
38 )
39
40
41
42
43 var caCertsExtraVolumePaths = []string{"/etc/pki", "/usr/share/ca-certificates", "/usr/local/share/ca-certificates", "/etc/ca-certificates"}
44
45
46 func getHostPathVolumesForTheControlPlane(cfg *kubeadmapi.ClusterConfiguration) controlPlaneHostPathMounts {
47 hostPathDirectoryOrCreate := v1.HostPathDirectoryOrCreate
48 hostPathFileOrCreate := v1.HostPathFileOrCreate
49 mounts := newControlPlaneHostPathMounts()
50
51
52
53
54 mounts.NewHostPathMount(kubeadmconstants.KubeAPIServer, kubeadmconstants.KubeCertificatesVolumeName, cfg.CertificatesDir, cfg.CertificatesDir, true, &hostPathDirectoryOrCreate)
55
56 mounts.NewHostPathMount(kubeadmconstants.KubeAPIServer, caCertsVolumeName, caCertsVolumePath, caCertsVolumePath, true, &hostPathDirectoryOrCreate)
57
58
59 if cfg.Etcd.External != nil {
60 etcdVols, etcdVolMounts := getEtcdCertVolumes(cfg.Etcd.External, cfg.CertificatesDir)
61 mounts.AddHostPathMounts(kubeadmconstants.KubeAPIServer, etcdVols, etcdVolMounts)
62 }
63
64
65
66
67 mounts.NewHostPathMount(kubeadmconstants.KubeControllerManager, kubeadmconstants.KubeCertificatesVolumeName, cfg.CertificatesDir, cfg.CertificatesDir, true, &hostPathDirectoryOrCreate)
68
69 mounts.NewHostPathMount(kubeadmconstants.KubeControllerManager, caCertsVolumeName, caCertsVolumePath, caCertsVolumePath, true, &hostPathDirectoryOrCreate)
70
71 controllerManagerKubeConfigFile := filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.ControllerManagerKubeConfigFileName)
72 mounts.NewHostPathMount(kubeadmconstants.KubeControllerManager, kubeadmconstants.KubeConfigVolumeName, controllerManagerKubeConfigFile, controllerManagerKubeConfigFile, true, &hostPathFileOrCreate)
73
74
75 flexvolumeDirVolumePath, idx := kubeadmapi.GetArgValue(cfg.ControllerManager.ExtraArgs, "flex-volume-plugin-dir", -1)
76 if idx == -1 {
77 flexvolumeDirVolumePath = defaultFlexvolumeDirVolumePath
78 }
79 mounts.NewHostPathMount(kubeadmconstants.KubeControllerManager, flexvolumeDirVolumeName, flexvolumeDirVolumePath, flexvolumeDirVolumePath, false, &hostPathDirectoryOrCreate)
80
81
82
83 schedulerKubeConfigFile := filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.SchedulerKubeConfigFileName)
84 mounts.NewHostPathMount(kubeadmconstants.KubeScheduler, kubeadmconstants.KubeConfigVolumeName, schedulerKubeConfigFile, schedulerKubeConfigFile, true, &hostPathFileOrCreate)
85
86
87
88 for _, caCertsExtraVolumePath := range caCertsExtraVolumePaths {
89 if isExtraVolumeMountNeeded(caCertsExtraVolumePath) {
90 caCertsExtraVolumeName := strings.Replace(caCertsExtraVolumePath, "/", "-", -1)[1:]
91 mounts.NewHostPathMount(kubeadmconstants.KubeAPIServer, caCertsExtraVolumeName, caCertsExtraVolumePath, caCertsExtraVolumePath, true, &hostPathDirectoryOrCreate)
92 mounts.NewHostPathMount(kubeadmconstants.KubeControllerManager, caCertsExtraVolumeName, caCertsExtraVolumePath, caCertsExtraVolumePath, true, &hostPathDirectoryOrCreate)
93 }
94 }
95
96
97
98 mounts.AddExtraHostPathMounts(kubeadmconstants.KubeAPIServer, cfg.APIServer.ExtraVolumes)
99 mounts.AddExtraHostPathMounts(kubeadmconstants.KubeControllerManager, cfg.ControllerManager.ExtraVolumes)
100 mounts.AddExtraHostPathMounts(kubeadmconstants.KubeScheduler, cfg.Scheduler.ExtraVolumes)
101
102 return mounts
103 }
104
105
106 type controlPlaneHostPathMounts struct {
107
108
109
110
111
112 volumes map[string]map[string]v1.Volume
113
114
115
116
117
118 volumeMounts map[string]map[string]v1.VolumeMount
119 }
120
121 func newControlPlaneHostPathMounts() controlPlaneHostPathMounts {
122 return controlPlaneHostPathMounts{
123 volumes: map[string]map[string]v1.Volume{},
124 volumeMounts: map[string]map[string]v1.VolumeMount{},
125 }
126 }
127
128 func (c *controlPlaneHostPathMounts) NewHostPathMount(component, mountName, hostPath, containerPath string, readOnly bool, hostPathType *v1.HostPathType) {
129 vol := staticpodutil.NewVolume(mountName, hostPath, hostPathType)
130 c.addComponentVolume(component, vol)
131 volMount := staticpodutil.NewVolumeMount(mountName, containerPath, readOnly)
132 c.addComponentVolumeMount(component, volMount)
133 }
134
135 func (c *controlPlaneHostPathMounts) AddHostPathMounts(component string, vols []v1.Volume, volMounts []v1.VolumeMount) {
136 for _, v := range vols {
137 c.addComponentVolume(component, v)
138 }
139 for _, v := range volMounts {
140 c.addComponentVolumeMount(component, v)
141 }
142 }
143
144
145
146 func (c *controlPlaneHostPathMounts) AddExtraHostPathMounts(component string, extraVols []kubeadmapi.HostPathMount) {
147 for _, extraVol := range extraVols {
148 hostPathType := extraVol.PathType
149 c.NewHostPathMount(component, extraVol.Name, extraVol.HostPath, extraVol.MountPath, extraVol.ReadOnly, &hostPathType)
150 }
151 }
152
153 func (c *controlPlaneHostPathMounts) GetVolumes(component string) map[string]v1.Volume {
154 return c.volumes[component]
155 }
156
157 func (c *controlPlaneHostPathMounts) GetVolumeMounts(component string) map[string]v1.VolumeMount {
158 return c.volumeMounts[component]
159 }
160
161 func (c *controlPlaneHostPathMounts) addComponentVolume(component string, vol v1.Volume) {
162 if _, ok := c.volumes[component]; !ok {
163 c.volumes[component] = map[string]v1.Volume{}
164 }
165 c.volumes[component][vol.Name] = vol
166 }
167
168 func (c *controlPlaneHostPathMounts) addComponentVolumeMount(component string, volMount v1.VolumeMount) {
169 if _, ok := c.volumeMounts[component]; !ok {
170 c.volumeMounts[component] = map[string]v1.VolumeMount{}
171 }
172 c.volumeMounts[component][volMount.Name] = volMount
173 }
174
175
176 func getEtcdCertVolumes(etcdCfg *kubeadmapi.ExternalEtcd, k8sCertificatesDir string) ([]v1.Volume, []v1.VolumeMount) {
177 certPaths := []string{etcdCfg.CAFile, etcdCfg.CertFile, etcdCfg.KeyFile}
178 certDirs := sets.New[string]()
179 for _, certPath := range certPaths {
180 certDir := filepath.ToSlash(filepath.Dir(certPath))
181
182
183
184 extraVolumePath := false
185 for _, caCertsExtraVolumePath := range caCertsExtraVolumePaths {
186 if strings.HasPrefix(certDir, caCertsExtraVolumePath) {
187 extraVolumePath = true
188 break
189 }
190 }
191 if certDir == "." || extraVolumePath || strings.HasPrefix(certDir, caCertsVolumePath) || strings.HasPrefix(certDir, k8sCertificatesDir) {
192 continue
193 }
194
195 alreadyExists := false
196 for _, existingCertDir := range sets.List(certDirs) {
197
198 if strings.HasPrefix(existingCertDir, certDir) {
199 certDirs.Delete(existingCertDir)
200 } else if strings.HasPrefix(certDir, existingCertDir) {
201
202 alreadyExists = true
203 }
204 }
205 if alreadyExists {
206 continue
207 }
208 certDirs.Insert(certDir)
209 }
210
211 volumes := []v1.Volume{}
212 volumeMounts := []v1.VolumeMount{}
213 pathType := v1.HostPathDirectoryOrCreate
214 for i, certDir := range sets.List(certDirs) {
215 name := fmt.Sprintf("etcd-certs-%d", i)
216 volumes = append(volumes, staticpodutil.NewVolume(name, certDir, &pathType))
217 volumeMounts = append(volumeMounts, staticpodutil.NewVolumeMount(name, certDir, true))
218 }
219 return volumes, volumeMounts
220 }
221
222
223
224
225 func isExtraVolumeMountNeeded(caCertsExtraVolumePath string) bool {
226 if _, err := os.Stat(caCertsExtraVolumePath); err == nil {
227 return true
228 }
229 return false
230 }
231
View as plain text