Skip to content

Commit

Permalink
Run Envoy Gateway like DaemonSet (#3092)
Browse files Browse the repository at this point in the history
implement daemonset logic

Signed-off-by: zvlb <vl.zemtsov@gmail.com>
  • Loading branch information
zvlb authored Apr 20, 2024
1 parent fcfeefd commit c42e3bf
Show file tree
Hide file tree
Showing 36 changed files with 9,173 additions and 44 deletions.
13 changes: 11 additions & 2 deletions api/v1alpha1/envoyproxy_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,20 @@ func (r *EnvoyProxyProvider) GetEnvoyProxyKubeProvider() *EnvoyProxyKubernetesPr
return r.Kubernetes
}

if r.Kubernetes.EnvoyDeployment == nil {
// if EnvoyDeployment and EnvoyDaemonSet are both nil, use EnvoyDeployment
if r.Kubernetes.EnvoyDeployment == nil && r.Kubernetes.EnvoyDaemonSet == nil {
r.Kubernetes.EnvoyDeployment = DefaultKubernetesDeployment(DefaultEnvoyProxyImage)
}

r.Kubernetes.EnvoyDeployment.defaultKubernetesDeploymentSpec(DefaultEnvoyProxyImage)
// if use EnvoyDeployment, set default values
if r.Kubernetes.EnvoyDeployment != nil {
r.Kubernetes.EnvoyDeployment.defaultKubernetesDeploymentSpec(DefaultEnvoyProxyImage)
}

// if use EnvoyDaemonSet, set default values
if r.Kubernetes.EnvoyDaemonSet != nil {
r.Kubernetes.EnvoyDaemonSet.defaultKubernetesDaemonSetSpec(DefaultEnvoyProxyImage)
}

if r.Kubernetes.EnvoyService == nil {
r.Kubernetes.EnvoyService = DefaultKubernetesService()
Expand Down
9 changes: 9 additions & 0 deletions api/v1alpha1/envoyproxy_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,9 @@ type ShutdownConfig struct {
MinDrainDuration *metav1.Duration `json:"minDrainDuration,omitempty"`
}

// +kubebuilder:validation:XValidation:rule="((has(self.envoyDeployment) && !has(self.envoyDaemonSet)) || (!has(self.envoyDeployment) && has(self.envoyDaemonSet))) || (!has(self.envoyDeployment) && !has(self.envoyDaemonSet))",message="only one of envoyDeployment or envoyDaemonSet can be specified"
// +kubebuilder:validation:XValidation:rule="((has(self.envoyHpa) && !has(self.envoyDaemonSet)) || (!has(self.envoyHpa) && has(self.envoyDaemonSet))) || (!has(self.envoyHpa) && !has(self.envoyDaemonSet))",message="cannot use envoyHpa if envoyDaemonSet is used"
//
// EnvoyProxyKubernetesProvider defines configuration for the Kubernetes resource
// provider.
type EnvoyProxyKubernetesProvider struct {
Expand All @@ -228,6 +231,12 @@ type EnvoyProxyKubernetesProvider struct {
// +optional
EnvoyDeployment *KubernetesDeploymentSpec `json:"envoyDeployment,omitempty"`

// EnvoyDaemonSet defines the desired state of the Envoy daemonset resource.
// Disabled by default, a deployment resource is used instead to provision the Envoy Proxy fleet
//
// +optional
EnvoyDaemonSet *KubernetesDaemonSetSpec `json:"envoyDaemonSet,omitempty"`

// EnvoyService defines the desired state of the Envoy service resource.
// If unspecified, default settings for the managed Envoy service resource
// are applied.
Expand Down
75 changes: 75 additions & 0 deletions api/v1alpha1/kubernetes_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@ func DefaultKubernetesDeploymentStrategy() *appv1.DeploymentStrategy {
}
}

// DefaultKubernetesDaemonSetStrategy returns the default daemonset strategy settings.
func DefaultKubernetesDaemonSetStrategy() *appv1.DaemonSetUpdateStrategy {
return &appv1.DaemonSetUpdateStrategy{
Type: appv1.RollingUpdateDaemonSetStrategyType,
}
}

// DefaultKubernetesContainerImage returns the default envoyproxy image.
func DefaultKubernetesContainerImage(image string) *string {
return ptr.To(image)
Expand All @@ -38,6 +45,15 @@ func DefaultKubernetesDeployment(image string) *KubernetesDeploymentSpec {
}
}

// DefaultKubernetesDaemonSet returns a new DefaultKubernetesDaemonSet with default settings.
func DefaultKubernetesDaemonSet(image string) *KubernetesDaemonSetSpec {
return &KubernetesDaemonSetSpec{
Strategy: DefaultKubernetesDaemonSetStrategy(),
Pod: DefaultKubernetesPod(),
Container: DefaultKubernetesContainer(image),
}
}

// DefaultKubernetesPod returns a new KubernetesPodSpec with default settings.
func DefaultKubernetesPod() *KubernetesPodSpec {
return &KubernetesPodSpec{}
Expand Down Expand Up @@ -110,6 +126,29 @@ func (deployment *KubernetesDeploymentSpec) defaultKubernetesDeploymentSpec(imag
}
}

// defaultKubernetesDaemonSetSpec fill a default KubernetesDaemonSetSpec if unspecified.
func (daemonset *KubernetesDaemonSetSpec) defaultKubernetesDaemonSetSpec(image string) {
if daemonset.Strategy == nil {
daemonset.Strategy = DefaultKubernetesDaemonSetStrategy()
}

if daemonset.Pod == nil {
daemonset.Pod = DefaultKubernetesPod()
}

if daemonset.Container == nil {
daemonset.Container = DefaultKubernetesContainer(image)
}

if daemonset.Container.Resources == nil {
daemonset.Container.Resources = DefaultResourceRequirements()
}

if daemonset.Container.Image == nil {
daemonset.Container.Image = DefaultKubernetesContainerImage(image)
}
}

// setDefault fill a default HorizontalPodAutoscalerSpec if unspecified
func (hpa *KubernetesHorizontalPodAutoscalerSpec) setDefault() {
if len(hpa.Metrics) == 0 {
Expand Down Expand Up @@ -153,6 +192,42 @@ func (deployment *KubernetesDeploymentSpec) ApplyMergePatch(old *appv1.Deploymen
return &patchedDeployment, nil
}

// ApplyMergePatch applies a merge patch to a daemonset based on the merge type
func (daemonset *KubernetesDaemonSetSpec) ApplyMergePatch(old *appv1.DaemonSet) (*appv1.DaemonSet, error) {
if daemonset.Patch == nil {
return old, nil
}

var patchedJSON []byte
var err error

// Serialize the current daemonset to JSON
originalJSON, err := json.Marshal(old)
if err != nil {
return nil, fmt.Errorf("error marshaling original daemonset: %w", err)
}

switch {
case daemonset.Patch.Type == nil || *daemonset.Patch.Type == StrategicMerge:
patchedJSON, err = strategicpatch.StrategicMergePatch(originalJSON, daemonset.Patch.Value.Raw, appv1.DaemonSet{})
case *daemonset.Patch.Type == JSONMerge:
patchedJSON, err = jsonpatch.MergePatch(originalJSON, daemonset.Patch.Value.Raw)
default:
return nil, fmt.Errorf("unsupported merge type: %s", *daemonset.Patch.Type)
}
if err != nil {
return nil, fmt.Errorf("error applying merge patch: %w", err)
}

// Deserialize the patched JSON into a new daemonset object
var patchedDaemonSet appv1.DaemonSet
if err := json.Unmarshal(patchedJSON, &patchedDaemonSet); err != nil {
return nil, fmt.Errorf("error unmarshaling patched daemonset: %w", err)
}

return &patchedDaemonSet, nil
}

// ApplyMergePatch applies a merge patch to a service based on the merge type
func (service *KubernetesServiceSpec) ApplyMergePatch(old *corev1.Service) (*corev1.Service, error) {
if service.Patch == nil {
Expand Down
22 changes: 22 additions & 0 deletions api/v1alpha1/shared_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,28 @@ type KubernetesDeploymentSpec struct {
// TODO: Expose config as use cases are better understood, e.g. labels.
}

// KubernetesDaemonsetSpec defines the desired state of the Kubernetes daemonset resource.
type KubernetesDaemonSetSpec struct {
// Patch defines how to perform the patch operation to daemonset
//
// +optional
Patch *KubernetesPatchSpec `json:"patch,omitempty"`

// The daemonset strategy to use to replace existing pods with new ones.
// +optional
Strategy *appv1.DaemonSetUpdateStrategy `json:"strategy,omitempty"`

// Pod defines the desired specification of pod.
//
// +optional
Pod *KubernetesPodSpec `json:"pod,omitempty"`

// Container defines the desired specification of main container.
//
// +optional
Container *KubernetesContainerSpec `json:"container,omitempty"`
}

// KubernetesPodSpec defines the desired state of the Kubernetes pod resource.
type KubernetesPodSpec struct {
// Annotations are the annotations that should be appended to the pods.
Expand Down
40 changes: 40 additions & 0 deletions api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit c42e3bf

Please sign in to comment.