mirror of
https://github.com/outbackdingo/kamaji.git
synced 2026-01-27 10:19:29 +00:00
212 lines
6.4 KiB
Go
212 lines
6.4 KiB
Go
// Copyright 2022 Clastix Labs
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package konnectivity
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
appsv1 "k8s.io/api/apps/v1"
|
|
corev1 "k8s.io/api/core/v1"
|
|
k8serrors "k8s.io/apimachinery/pkg/api/errors"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/apimachinery/pkg/util/intstr"
|
|
"k8s.io/utils/pointer"
|
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
|
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
|
|
|
|
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
|
|
"github.com/clastix/kamaji/internal/utilities"
|
|
)
|
|
|
|
const (
|
|
agentNamespace = "kube-system"
|
|
)
|
|
|
|
type Agent struct {
|
|
resource *appsv1.DaemonSet
|
|
Client client.Client
|
|
Name string
|
|
tenantClient client.Client
|
|
}
|
|
|
|
func (r *Agent) ShouldStatusBeUpdated(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) bool {
|
|
return tenantControlPlane.Status.Addons.Konnectivity.Agent.Checksum != r.resource.GetAnnotations()["checksum"]
|
|
}
|
|
|
|
func (r *Agent) ShouldCleanup(tenantControlPlane *kamajiv1alpha1.TenantControlPlane) bool {
|
|
return tenantControlPlane.Spec.Addons.Konnectivity == nil
|
|
}
|
|
|
|
func (r *Agent) CleanUp(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (bool, error) {
|
|
if err := r.tenantClient.Delete(ctx, r.resource); err != nil {
|
|
if !k8serrors.IsNotFound(err) {
|
|
return false, err
|
|
}
|
|
|
|
return false, nil
|
|
}
|
|
|
|
return true, nil
|
|
}
|
|
|
|
func (r *Agent) Define(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) error {
|
|
r.resource = &appsv1.DaemonSet{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: AgentName,
|
|
Namespace: agentNamespace,
|
|
},
|
|
}
|
|
|
|
client, err := utilities.GetTenantClient(ctx, r.Client, tenantControlPlane)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
r.tenantClient = client
|
|
|
|
return nil
|
|
}
|
|
|
|
func (r *Agent) CreateOrUpdate(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (controllerutil.OperationResult, error) {
|
|
return controllerutil.CreateOrUpdate(ctx, r.tenantClient, r.resource, r.mutate(tenantControlPlane))
|
|
}
|
|
|
|
func (r *Agent) GetName() string {
|
|
return r.Name
|
|
}
|
|
|
|
func (r *Agent) UpdateTenantControlPlaneStatus(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) error {
|
|
if tenantControlPlane.Spec.Addons.Konnectivity != nil {
|
|
tenantControlPlane.Status.Addons.Konnectivity.Agent = kamajiv1alpha1.ExternalKubernetesObjectStatus{
|
|
Name: r.resource.GetName(),
|
|
Namespace: r.resource.GetNamespace(),
|
|
Checksum: r.resource.GetAnnotations()["checksum"],
|
|
LastUpdate: metav1.Now(),
|
|
}
|
|
tenantControlPlane.Status.Addons.Konnectivity.Enabled = true
|
|
|
|
return nil
|
|
}
|
|
|
|
tenantControlPlane.Status.Addons.Konnectivity.Enabled = false
|
|
tenantControlPlane.Status.Addons.Konnectivity.Agent = kamajiv1alpha1.ExternalKubernetesObjectStatus{}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (r *Agent) mutate(tenantControlPlane *kamajiv1alpha1.TenantControlPlane) controllerutil.MutateFn {
|
|
return func() error {
|
|
address, _, err := tenantControlPlane.AssignedControlPlaneAddress()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
r.resource.SetLabels(utilities.MergeMaps(
|
|
utilities.KamajiLabels(),
|
|
map[string]string{
|
|
"k8s-app": AgentName,
|
|
"addonmanager.kubernetes.io/mode": "Reconcile",
|
|
},
|
|
))
|
|
|
|
if r.resource.Spec.Selector == nil {
|
|
r.resource.Spec.Selector = &metav1.LabelSelector{}
|
|
}
|
|
r.resource.Spec.Selector.MatchLabels = map[string]string{
|
|
"k8s-app": AgentName,
|
|
}
|
|
|
|
r.resource.Spec.Template.SetLabels(utilities.MergeMaps(
|
|
r.resource.Spec.Template.GetLabels(),
|
|
map[string]string{
|
|
"k8s-app": AgentName,
|
|
},
|
|
))
|
|
|
|
r.resource.Spec.Template.Spec.PriorityClassName = "system-cluster-critical"
|
|
r.resource.Spec.Template.Spec.Tolerations = []corev1.Toleration{
|
|
{
|
|
Key: "CriticalAddonsOnly",
|
|
Operator: "Exists",
|
|
},
|
|
}
|
|
r.resource.Spec.Template.Spec.NodeSelector = map[string]string{
|
|
"kubernetes.io/os": "linux",
|
|
}
|
|
r.resource.Spec.Template.Spec.ServiceAccountName = AgentName
|
|
r.resource.Spec.Template.Spec.Volumes = []corev1.Volume{
|
|
{
|
|
Name: agentTokenName,
|
|
VolumeSource: corev1.VolumeSource{
|
|
Projected: &corev1.ProjectedVolumeSource{
|
|
Sources: []corev1.VolumeProjection{
|
|
{
|
|
ServiceAccountToken: &corev1.ServiceAccountTokenProjection{
|
|
Path: agentTokenName,
|
|
Audience: tenantControlPlane.Status.Addons.Konnectivity.ClusterRoleBinding.Name,
|
|
ExpirationSeconds: pointer.Int64(3600),
|
|
},
|
|
},
|
|
},
|
|
DefaultMode: pointer.Int32Ptr(420),
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
if len(r.resource.Spec.Template.Spec.Containers) != 1 {
|
|
r.resource.Spec.Template.Spec.Containers = make([]corev1.Container, 1)
|
|
}
|
|
|
|
r.resource.Spec.Template.Spec.Containers[0].Image = fmt.Sprintf("%s:%s", tenantControlPlane.Spec.Addons.Konnectivity.AgentImage, tenantControlPlane.Spec.Addons.Konnectivity.Version)
|
|
r.resource.Spec.Template.Spec.Containers[0].Name = AgentName
|
|
r.resource.Spec.Template.Spec.Containers[0].Command = []string{"/proxy-agent"}
|
|
r.resource.Spec.Template.Spec.Containers[0].Args = []string{
|
|
"-v=8",
|
|
"--logtostderr=true",
|
|
"--ca-cert=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt",
|
|
fmt.Sprintf("--proxy-server-host=%s", address),
|
|
fmt.Sprintf("--proxy-server-port=%d", tenantControlPlane.Spec.Addons.Konnectivity.ProxyPort),
|
|
"--admin-server-port=8133",
|
|
"--health-server-port=8134",
|
|
"--service-account-token-path=/var/run/secrets/tokens/konnectivity-agent-token",
|
|
}
|
|
r.resource.Spec.Template.Spec.Containers[0].VolumeMounts = []corev1.VolumeMount{
|
|
{
|
|
MountPath: "/var/run/secrets/tokens",
|
|
Name: agentTokenName,
|
|
},
|
|
}
|
|
r.resource.Spec.Template.Spec.Containers[0].LivenessProbe = &corev1.Probe{
|
|
ProbeHandler: corev1.ProbeHandler{
|
|
HTTPGet: &corev1.HTTPGetAction{
|
|
Path: "/healthz",
|
|
Port: intstr.FromInt(8134),
|
|
Scheme: corev1.URISchemeHTTP,
|
|
},
|
|
},
|
|
InitialDelaySeconds: 15,
|
|
TimeoutSeconds: 15,
|
|
PeriodSeconds: 10,
|
|
SuccessThreshold: 1,
|
|
FailureThreshold: 3,
|
|
}
|
|
// Creating a copy to remove the metadata that would be changed at every reconciliation
|
|
c := r.resource.DeepCopy()
|
|
c.SetAnnotations(nil)
|
|
c.SetResourceVersion("")
|
|
|
|
yaml, _ := utilities.EncondeToYaml(c)
|
|
annotations := r.resource.GetAnnotations()
|
|
if annotations == nil {
|
|
annotations = map[string]string{}
|
|
}
|
|
annotations["checksum"] = utilities.MD5Checksum(yaml)
|
|
r.resource.SetAnnotations(annotations)
|
|
|
|
return nil
|
|
}
|
|
}
|