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