Skip to content

Commit 4043692

Browse files
committed
Run octavia amphora services in unprivileged/non-root containers
Moved the parts that requires privileged/root access to the init container, the services are now running with the octavia user. JIRA: OSPRH-10287
1 parent fff6549 commit 4043692

File tree

4 files changed

+70
-45
lines changed

4 files changed

+70
-45
lines changed

pkg/amphoracontrollers/daemonset.go

Lines changed: 44 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ import (
2727
appsv1 "k8s.io/api/apps/v1"
2828
corev1 "k8s.io/api/core/v1"
2929
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
30+
"k8s.io/utils/ptr"
31+
)
32+
33+
const (
34+
// InitContainerCommand -
35+
InitContainerCommand = "/usr/local/bin/container-scripts/init.sh %s"
3036
)
3137

3238
// DaemonSet func
@@ -36,8 +42,6 @@ func DaemonSet(
3642
labels map[string]string,
3743
annotations map[string]string,
3844
) *appsv1.DaemonSet {
39-
runAsUser := int64(0)
40-
privileged := true
4145
serviceName := fmt.Sprintf("octavia-%s", instance.Spec.Role)
4246

4347
// The API pod has an extra volume so the API and the provider agent can
@@ -47,7 +51,7 @@ func DaemonSet(
4751
certsSecretName := fmt.Sprintf("%s-certs-secret", parentOctaviaName)
4852
volumes = append(volumes, GetCertVolume(certsSecretName)...)
4953

50-
volumeMounts := GetVolumeMounts(serviceName)
54+
volumeMounts := octavia.GetVolumeMounts(serviceName)
5155
volumeMounts = append(volumeMounts, GetCertVolumeMount()...)
5256

5357
livenessProbe := &corev1.Probe{
@@ -100,6 +104,11 @@ func DaemonSet(
100104
volumeMounts = append(volumeMounts, instance.Spec.TLS.CreateVolumeMounts(nil)...)
101105
}
102106

107+
args := []string{
108+
"-c",
109+
fmt.Sprintf(InitContainerCommand, instance.Name),
110+
}
111+
103112
// Because we don't use jobboard, we need to ensure that the octavia
104113
// controllers are gracefully shutdown, so after they receive the signal,
105114
// they need to complete the jobs that are being executed (creating a LB,
@@ -112,6 +121,12 @@ func DaemonSet(
112121
// re-enabled
113122
terminationGracePeriodSeconds := int64(600)
114123

124+
capabilities := []corev1.Capability{"NET_ADMIN", "SYS_ADMIN", "SYS_NICE"}
125+
if instance.Spec.Role == octaviav1.HealthManager {
126+
// NET_RAW is required for IP advertisements
127+
capabilities = append(capabilities, corev1.Capability("NET_RAW"))
128+
}
129+
115130
daemonset := &appsv1.DaemonSet{
116131
ObjectMeta: metav1.ObjectMeta{
117132
Name: serviceName,
@@ -127,25 +142,40 @@ func DaemonSet(
127142
Labels: labels,
128143
},
129144
Spec: corev1.PodSpec{
145+
SecurityContext: &corev1.PodSecurityContext{
146+
FSGroup: ptr.To(octavia.OctaviaUID),
147+
},
130148
TerminationGracePeriodSeconds: &terminationGracePeriodSeconds,
131149
ServiceAccountName: instance.Spec.ServiceAccount,
132150
Containers: []corev1.Container{
133151
{
134-
Name: serviceName,
135-
Image: instance.Spec.ContainerImage,
136-
Env: env.MergeEnvs([]corev1.EnvVar{}, envVars),
137-
VolumeMounts: volumeMounts,
138-
Resources: instance.Spec.Resources,
139-
ReadinessProbe: readinessProbe,
140-
LivenessProbe: livenessProbe,
152+
Name: serviceName,
153+
Image: instance.Spec.ContainerImage,
154+
SecurityContext: octavia.GetOctaviaSecurityContext(),
155+
Env: env.MergeEnvs([]corev1.EnvVar{}, envVars),
156+
VolumeMounts: volumeMounts,
157+
Resources: instance.Spec.Resources,
158+
ReadinessProbe: readinessProbe,
159+
LivenessProbe: livenessProbe,
160+
},
161+
},
162+
InitContainers: []corev1.Container{
163+
{
164+
Name: "init",
165+
Image: instance.Spec.ContainerImage,
141166
SecurityContext: &corev1.SecurityContext{
142167
Capabilities: &corev1.Capabilities{
143-
Add: []corev1.Capability{"NET_ADMIN", "SYS_ADMIN", "SYS_NICE"},
168+
Add: capabilities,
144169
Drop: []corev1.Capability{},
145170
},
146-
RunAsUser: &runAsUser,
147-
Privileged: &privileged,
171+
RunAsUser: ptr.To(int64(0)),
148172
},
173+
Command: []string{
174+
"/bin/bash",
175+
},
176+
Env: env.MergeEnvs([]corev1.EnvVar{}, envVars),
177+
Args: args,
178+
VolumeMounts: GetInitVolumeMounts(),
149179
},
150180
},
151181
Volumes: volumes,
@@ -163,15 +193,9 @@ func DaemonSet(
163193
},
164194
corev1.LabelHostname,
165195
)
166-
if instance.Spec.NodeSelector != nil && len(instance.Spec.NodeSelector) > 0 {
196+
if len(instance.Spec.NodeSelector) > 0 {
167197
daemonset.Spec.Template.Spec.NodeSelector = instance.Spec.NodeSelector
168198
}
169199

170-
initContainerDetails := octavia.APIDetails{
171-
ContainerImage: instance.Spec.ContainerImage,
172-
VolumeMounts: octavia.GetInitVolumeMounts(),
173-
}
174-
daemonset.Spec.Template.Spec.InitContainers = octavia.InitContainer(initContainerDetails)
175-
176200
return daemonset
177201
}

pkg/amphoracontrollers/volumes.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,9 @@ func GetVolumes(name string) []corev1.Volume {
4848
)
4949
}
5050

51-
func GetVolumeMounts(serviceName string) []corev1.VolumeMount {
51+
func GetInitVolumeMounts() []corev1.VolumeMount {
5252
return append(
53-
octavia.GetVolumeMounts(serviceName),
53+
octavia.GetInitVolumeMounts(),
5454
corev1.VolumeMount{
5555
Name: "hm-ports",
5656
MountPath: "/var/lib/hmports",

templates/octaviaamphoracontroller/bin/init.sh

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,27 @@ cp -a ${SVC_CFG} ${SVC_CFG_MERGED}
3232
for dir in /var/lib/config-data/default; do
3333
merge_config_dir ${dir}
3434
done
35+
36+
# Network configuration
37+
if [ "$MGMT_CIDR" != "" ]; then
38+
/usr/local/bin/container-scripts/octavia_mgmt_subnet_route.py octavia "$MGMT_CIDR" "$MGMT_GATEWAY"
39+
fi
40+
41+
idx=0
42+
while true; do
43+
var_name="MGMT_CIDR${idx}"
44+
cidr="${!var_name}"
45+
if [ "$cidr" = "" ]; then
46+
break
47+
fi
48+
/usr/local/bin/container-scripts/octavia_mgmt_subnet_route.py octavia "$cidr" "$MGMT_GATEWAY"
49+
idx=$((idx+1))
50+
done
51+
52+
if [ "$1" = "octavia-healthmanager" ]; then
53+
/usr/local/bin/container-scripts/setipalias.py octavia hm
54+
/usr/local/bin/container-scripts/octavia_hm_advertisement.py octavia
55+
fi
56+
57+
# Ignore possible errors
58+
/usr/local/bin/container-scripts/octavia_status.py || true

templates/octaviaamphoracontroller/bin/octavia_controller_start.sh

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -15,27 +15,4 @@
1515
# under the License.
1616
set -ex
1717

18-
if [ "$MGMT_CIDR" != "" ]; then
19-
/usr/local/bin/container-scripts/octavia_mgmt_subnet_route.py octavia "$MGMT_CIDR" "$MGMT_GATEWAY"
20-
fi
21-
22-
idx=0
23-
while true; do
24-
var_name="MGMT_CIDR${idx}"
25-
cidr="${!var_name}"
26-
if [ "$cidr" = "" ]; then
27-
break
28-
fi
29-
/usr/local/bin/container-scripts/octavia_mgmt_subnet_route.py octavia "$cidr" "$MGMT_GATEWAY"
30-
idx=$((idx+1))
31-
done
32-
33-
if [ "$1" = "octavia-health-manager" ]; then
34-
/usr/local/bin/container-scripts/setipalias.py octavia hm
35-
/usr/local/bin/container-scripts/octavia_hm_advertisement.py octavia
36-
fi
37-
38-
# Ignore possible errors
39-
/usr/local/bin/container-scripts/octavia_status.py || true
40-
4118
exec /usr/bin/$1 --config-file /usr/share/octavia/octavia-dist.conf --config-file /etc/octavia/octavia.conf --config-dir /etc/octavia/octavia.conf.d/

0 commit comments

Comments
 (0)