Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
gitpod-io
GitHub Repository: gitpod-io/gitpod
Path: blob/main/install/installer/pkg/components/proxy/deployment.go
2501 views
1
// Copyright (c) 2021 Gitpod GmbH. All rights reserved.
2
// Licensed under the GNU Affero General Public License (AGPL).
3
// See License.AGPL.txt in the project root for license information.
4
5
package proxy
6
7
import (
8
"fmt"
9
"strings"
10
11
"github.com/gitpod-io/gitpod/common-go/baseserver"
12
"github.com/gitpod-io/gitpod/installer/pkg/cluster"
13
"github.com/gitpod-io/gitpod/installer/pkg/config/v1/experimental"
14
15
"github.com/gitpod-io/gitpod/installer/pkg/common"
16
17
appsv1 "k8s.io/api/apps/v1"
18
corev1 "k8s.io/api/core/v1"
19
"k8s.io/apimachinery/pkg/api/resource"
20
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
21
"k8s.io/apimachinery/pkg/runtime"
22
"k8s.io/apimachinery/pkg/util/intstr"
23
"k8s.io/utils/pointer"
24
)
25
26
func deployment(ctx *common.RenderContext) ([]runtime.Object, error) {
27
labels := common.CustomizeLabel(ctx, Component, common.TypeMetaDeployment)
28
29
var hashObj []runtime.Object
30
if objs, err := configmap(ctx); err != nil {
31
return nil, err
32
} else {
33
hashObj = append(hashObj, objs...)
34
}
35
36
prometheusPort := corev1.ContainerPort{
37
ContainerPort: baseserver.BuiltinMetricsPort,
38
Name: baseserver.BuiltinMetricsPortName,
39
}
40
41
volumes := []corev1.Volume{{
42
Name: "vhosts",
43
VolumeSource: corev1.VolumeSource{
44
ConfigMap: &corev1.ConfigMapVolumeSource{
45
LocalObjectReference: corev1.LocalObjectReference{Name: fmt.Sprintf("%s-config", Component)},
46
},
47
},
48
}, {
49
Name: "config-certificates",
50
VolumeSource: corev1.VolumeSource{
51
Secret: &corev1.SecretVolumeSource{
52
SecretName: ctx.Config.Certificate.Name,
53
},
54
},
55
},
56
common.CAVolume(),
57
}
58
59
volumeMounts := []corev1.VolumeMount{{
60
Name: "vhosts",
61
MountPath: "/etc/caddy/vhosts",
62
}, {
63
Name: "config-certificates",
64
MountPath: "/etc/caddy/certificates",
65
},
66
common.CAVolumeMount()}
67
68
if pointer.BoolDeref(ctx.Config.ContainerRegistry.InCluster, false) {
69
volumes = append(volumes, corev1.Volume{
70
Name: RegistryAuthSecret,
71
VolumeSource: corev1.VolumeSource{
72
Secret: &corev1.SecretVolumeSource{
73
SecretName: RegistryAuthSecret,
74
},
75
},
76
}, corev1.Volume{
77
Name: RegistryTLSCertSecret,
78
VolumeSource: corev1.VolumeSource{
79
Secret: &corev1.SecretVolumeSource{
80
SecretName: RegistryTLSCertSecret,
81
},
82
},
83
})
84
volumeMounts = append(volumeMounts, corev1.VolumeMount{
85
Name: RegistryAuthSecret,
86
MountPath: "/etc/caddy/registry-auth",
87
}, corev1.VolumeMount{
88
Name: RegistryTLSCertSecret,
89
MountPath: "/etc/caddy/registry-certs",
90
})
91
92
if objs, err := common.DockerRegistryHash(ctx); err != nil {
93
return nil, err
94
} else {
95
hashObj = append(hashObj, objs...)
96
}
97
}
98
99
configHash, err := common.ObjectHash(hashObj, nil)
100
if err != nil {
101
return nil, err
102
}
103
104
var frontendDevEnabled bool
105
var trustedSegmentKey string
106
var untrustedSegmentKey string
107
var segmentEndpoint string
108
_ = ctx.WithExperimental(func(cfg *experimental.Config) error {
109
if cfg.WebApp != nil && cfg.WebApp.ProxyConfig != nil {
110
frontendDevEnabled = cfg.WebApp.ProxyConfig.FrontendDevEnabled
111
if cfg.WebApp.ProxyConfig.AnalyticsPlugin != nil {
112
trustedSegmentKey = cfg.WebApp.ProxyConfig.AnalyticsPlugin.TrustedSegmentKey
113
untrustedSegmentKey = cfg.WebApp.ProxyConfig.AnalyticsPlugin.UntrustedSegmentKey
114
segmentEndpoint = cfg.WebApp.ProxyConfig.AnalyticsPlugin.SegmentEndpoint
115
}
116
}
117
if cfg.WebApp != nil && cfg.WebApp.ProxyConfig != nil && cfg.WebApp.ProxyConfig.Configcat != nil && cfg.WebApp.ProxyConfig.Configcat.FromConfigMap != "" {
118
volumes = append(volumes, corev1.Volume{
119
Name: "configcat",
120
VolumeSource: corev1.VolumeSource{
121
ConfigMap: &corev1.ConfigMapVolumeSource{
122
LocalObjectReference: corev1.LocalObjectReference{Name: cfg.WebApp.ProxyConfig.Configcat.FromConfigMap},
123
Optional: pointer.Bool(true),
124
},
125
},
126
})
127
volumeMounts = append(volumeMounts, corev1.VolumeMount{
128
Name: "configcat",
129
MountPath: "/data/configcat",
130
})
131
}
132
return nil
133
})
134
135
const kubeRbacProxyContainerName = "kube-rbac-proxy"
136
return []runtime.Object{
137
&appsv1.Deployment{
138
TypeMeta: common.TypeMetaDeployment,
139
ObjectMeta: metav1.ObjectMeta{
140
Name: Component,
141
Namespace: ctx.Namespace,
142
Labels: labels,
143
Annotations: common.CustomizeAnnotation(ctx, Component, common.TypeMetaDeployment),
144
},
145
Spec: appsv1.DeploymentSpec{
146
Selector: &metav1.LabelSelector{MatchLabels: common.DefaultLabels(Component)},
147
Replicas: common.Replicas(ctx, Component),
148
Strategy: common.DeploymentStrategy,
149
Template: corev1.PodTemplateSpec{
150
ObjectMeta: metav1.ObjectMeta{
151
Name: Component,
152
Namespace: ctx.Namespace,
153
Labels: labels,
154
Annotations: common.CustomizeAnnotation(ctx, Component, common.TypeMetaDeployment, func() map[string]string {
155
return map[string]string{
156
common.AnnotationConfigChecksum: configHash,
157
}
158
}),
159
},
160
Spec: corev1.PodSpec{
161
Affinity: cluster.WithNodeAffinityHostnameAntiAffinity(Component, cluster.AffinityLabelMeta),
162
TopologySpreadConstraints: cluster.WithHostnameTopologySpread(Component),
163
PriorityClassName: common.SystemNodeCritical,
164
ServiceAccountName: Component,
165
EnableServiceLinks: pointer.Bool(false),
166
DNSPolicy: corev1.DNSClusterFirst,
167
RestartPolicy: corev1.RestartPolicyAlways,
168
TerminationGracePeriodSeconds: pointer.Int64(30),
169
SecurityContext: &corev1.PodSecurityContext{
170
171
RunAsNonRoot: pointer.Bool(false),
172
},
173
Volumes: volumes,
174
InitContainers: []corev1.Container{{
175
Name: "sysctl",
176
Image: ctx.ImageName(common.ThirdPartyContainerRepo(ctx.Config.Repository, common.DockerRegistryURL), InitContainerImage, InitContainerTag),
177
ImagePullPolicy: corev1.PullIfNotPresent,
178
SecurityContext: &corev1.SecurityContext{
179
Privileged: pointer.Bool(true),
180
},
181
Command: []string{
182
"sh",
183
"-c",
184
"sysctl -w net.core.somaxconn=32768; sysctl -w net.ipv4.ip_local_port_range='1024 65000'",
185
},
186
}},
187
Containers: []corev1.Container{{
188
Name: kubeRbacProxyContainerName,
189
Image: ctx.ImageName(common.ThirdPartyContainerRepo(ctx.Config.Repository, KubeRBACProxyRepo), KubeRBACProxyImage, KubeRBACProxyTag),
190
ImagePullPolicy: corev1.PullIfNotPresent,
191
Args: []string{
192
"--logtostderr",
193
fmt.Sprintf("--insecure-listen-address=[$(IP)]:%d", baseserver.BuiltinMetricsPort),
194
"--upstream=http://127.0.0.1:9545/",
195
},
196
Env: []corev1.EnvVar{{
197
Name: "IP",
198
ValueFrom: &corev1.EnvVarSource{
199
FieldRef: &corev1.ObjectFieldSelector{
200
APIVersion: "v1",
201
FieldPath: "status.podIP",
202
},
203
},
204
}},
205
Ports: []corev1.ContainerPort{{
206
ContainerPort: baseserver.BuiltinMetricsPort,
207
Name: baseserver.BuiltinMetricsPortName,
208
Protocol: *common.TCPProtocol,
209
}},
210
Resources: common.ResourceRequirements(ctx, Component, kubeRbacProxyContainerName, corev1.ResourceRequirements{
211
Requests: corev1.ResourceList{
212
"cpu": resource.MustParse("1m"),
213
"memory": resource.MustParse("30Mi"),
214
},
215
}),
216
SecurityContext: &corev1.SecurityContext{
217
RunAsGroup: pointer.Int64(65532),
218
RunAsNonRoot: pointer.Bool(true),
219
RunAsUser: pointer.Int64(65532),
220
},
221
}, {
222
Name: Component,
223
Image: ctx.ImageName(ctx.Config.Repository, Component, ctx.VersionManifest.Components.Proxy.Version),
224
ImagePullPolicy: corev1.PullIfNotPresent,
225
Resources: common.ResourceRequirements(ctx, Component, Component, corev1.ResourceRequirements{
226
Requests: corev1.ResourceList{
227
"cpu": resource.MustParse("100m"),
228
"memory": resource.MustParse("200Mi"),
229
},
230
}),
231
Ports: []corev1.ContainerPort{{
232
ContainerPort: ContainerHTTPPort,
233
Name: "http",
234
}, {
235
ContainerPort: ContainerHTTPSPort,
236
Name: "https",
237
}, {
238
ContainerPort: ContainerSSHPort,
239
Name: ContainerSSHName,
240
Protocol: *common.TCPProtocol,
241
}, prometheusPort, {
242
ContainerPort: ContainerAnalyticsPort,
243
Name: ContainerAnalyticsName,
244
}, {
245
ContainerPort: ContainerConfigcatPort,
246
Name: ContainerConfigcatName,
247
}},
248
SecurityContext: &corev1.SecurityContext{
249
Privileged: pointer.Bool(false),
250
AllowPrivilegeEscalation: pointer.Bool(false),
251
},
252
ReadinessProbe: &corev1.Probe{
253
ProbeHandler: corev1.ProbeHandler{
254
HTTPGet: &corev1.HTTPGetAction{
255
Path: "/ready",
256
Port: intstr.IntOrString{IntVal: ReadinessPort},
257
},
258
},
259
InitialDelaySeconds: 5,
260
PeriodSeconds: 5,
261
TimeoutSeconds: 1,
262
SuccessThreshold: 1,
263
FailureThreshold: 3,
264
},
265
VolumeMounts: volumeMounts,
266
Env: common.CustomizeEnvvar(ctx, Component, common.MergeEnv(
267
common.DefaultEnv(&ctx.Config),
268
common.ConfigcatProxyEnv(ctx),
269
[]corev1.EnvVar{{
270
Name: "PROXY_DOMAIN",
271
Value: ctx.Config.Domain,
272
}, {
273
Name: "FRONTEND_DEV_ENABLED",
274
Value: fmt.Sprintf("%t", frontendDevEnabled),
275
}, {
276
Name: "WORKSPACE_HANDLER_FILE",
277
Value: strings.ToLower(string(ctx.Config.Kind)),
278
}, {
279
Name: "ANALYTICS_PLUGIN_TRUSTED_SEGMENT_KEY",
280
Value: trustedSegmentKey,
281
}, {
282
Name: "ANALYTICS_PLUGIN_UNTRUSTED_SEGMENT_KEY",
283
Value: untrustedSegmentKey,
284
}, {
285
Name: "ANALYTICS_PLUGIN_SEGMENT_ENDPOINT",
286
Value: segmentEndpoint,
287
}},
288
)),
289
},
290
},
291
Tolerations: common.WithTolerationWorkspaceComponentNotReady(ctx),
292
},
293
},
294
},
295
},
296
}, nil
297
}
298
299