in src/routingmanager/RoutingStateEstablisher.cs [400:529]
private V1Deployment GenerateEnvoyDeployment(KeyValuePair<V1Service, RoutingStateEstablisherInput> input)
{
_log.Verbose("Generating envoy deployment for service '{0}'", input.Key.Metadata.Name);
var containerPorts = new List<V1ContainerPort>();
// TODO: This is nasty and needs a better fix
// As of today we already now that at this point the targetPorts are already all integers because Pragya did so in ReplaceNamedTargetPortsInTriggerServicesAsync
// This should also be taken care of when we'll migrate to non BETA types:https://devdiv.visualstudio.com/DevDiv/_boards/board/t/Mindaro/Stories/?workitem=1269558
// With the new non BETA types we don't need intOrString anymore.
input.Key.Spec.Ports.ExecuteForEach(svcPort => containerPorts.Add(new V1ContainerPort(Int32.Parse(svcPort.TargetPort.Value))));
var envoyDeploymentName = GetEnvoyDeploymentName(input.Key.Metadata.Name);
var envoyDeployment = new V1Deployment
{
Metadata = new V1ObjectMeta
{
Name = envoyDeploymentName,
NamespaceProperty = input.Key.Metadata.NamespaceProperty,
Labels = new Dictionary<string, string>
{
{ Routing.GeneratedLabel, "true" },
{ Constants.EntityLabel, envoyDeploymentName },
{ Constants.TriggerEntityLabel, GetEntityLabelValue(input.Value) }
}
},
Spec = new V1DeploymentSpec
{
Strategy = new V1DeploymentStrategy
{
RollingUpdate = new V1RollingUpdateDeployment
{
MaxSurge = 2,
MaxUnavailable = 1
}
},
Replicas = 2,
Selector = new V1LabelSelector
{
MatchLabels = new Dictionary<string, string>
{
{ Routing.GeneratedLabel, "true" },
{ Constants.EntityLabel, envoyDeploymentName }
}
},
Template = new V1PodTemplateSpec
{
Metadata = new V1ObjectMeta
{
Name = GetEnvoyPodName(input.Key.Metadata.Name),
NamespaceProperty = input.Key.Metadata.NamespaceProperty,
Labels = new Dictionary<string, string>
{
{ Routing.GeneratedLabel, "true" },
{ Constants.EntityLabel, envoyDeploymentName }
},
Annotations = new Dictionary<string, string>
{
{ Annotations.IstioInjection, "false"}
}
},
Spec = new V1PodSpec
{
TerminationGracePeriodSeconds = 0,
Volumes = new List<V1Volume>
{
{
new V1Volume
{
Name = GetEnvoyConfigMapVolumeName(),
ConfigMap = new V1ConfigMapVolumeSource
{
Name = GetEnvoyConfigMapName(input.Key.Metadata.Name),
Items = new List<V1KeyToPath>
{
{
new V1KeyToPath
{
Key = "config",
Path = "envoy.yaml"
}
}
}
}
}
}
},
Containers = new List<V1Container>
{
new V1Container
{
Name = "envoy",
Image = Constants.EnvoyImageName,
Command = new List<string> { "/bin/bash" },
Args = new List<string>
{
"-c",
"touch envoy-logs.txt && /usr/local/bin/envoy --log-path envoy-logs.txt --log-level trace --config-path /etc/envoy/envoy.yaml"
},
Ports = containerPorts,
VolumeMounts = new List<V1VolumeMount>
{
{
new V1VolumeMount()
{
Name = "config",
MountPath = "/etc/envoy",
ReadOnlyProperty = true
}
}
}
}
},
NodeSelector = new Dictionary<string, string>() { { KubernetesConstants.Labels.OS, KubernetesConstants.Labels.Values.Linux } }
}
}
}
};
// If both pod trigger and ingress trigger are not null, then they should mostly contain the same value,
// but just in case they don't, give more priority to ingress trigger's probes for AGIC case
if (input.Value.IngressTriggers != null && input.Value.IngressTriggers.Any(i => i.IsAgicIngress))
{
// There will only be one container - running the envoy image
// But there could potentially be multiple pods getting debugged at the same time under this envoy pod
// i.e. if multiple people are debugging the same service at the same time.
// Since kubernetes only supports a single liveness or readiness probe to be added to a pod, we will default to the first one
envoyDeployment.Spec.Template.Spec.Containers.First().ReadinessProbe = input.Value.IngressTriggers.First().HttpReadinessProbe;
envoyDeployment.Spec.Template.Spec.Containers.First().LivenessProbe = input.Value.IngressTriggers.First().HttpLivenessProbe;
}
return envoyDeployment;
}