github.com/caos/orbos@v1.5.14-0.20221103111702-e6cd0cea7ad4/pkg/kubernetes/networking.go (about)

     1  package kubernetes
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/caos/orbos/mntr"
     7  	"github.com/caos/orbos/pkg/labels"
     8  	"gopkg.in/yaml.v3"
     9  	apps "k8s.io/api/apps/v1"
    10  	core "k8s.io/api/core/v1"
    11  	rbac "k8s.io/api/rbac/v1"
    12  	"k8s.io/apimachinery/pkg/api/resource"
    13  	mach "k8s.io/apimachinery/pkg/apis/meta/v1"
    14  	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
    15  )
    16  
    17  func EnsureNetworkingArtifacts(
    18  	monitor mntr.Monitor,
    19  	apiLabels *labels.API,
    20  	client ClientInt,
    21  	version string,
    22  	nodeselector map[string]string,
    23  	tolerations []core.Toleration,
    24  	imageRegistry string,
    25  	gitops bool,
    26  ) error {
    27  
    28  	monitor.WithFields(map[string]interface{}{
    29  		"networking": version,
    30  	}).Debug("Ensuring networking artifacts")
    31  
    32  	if version == "" {
    33  		return nil
    34  	}
    35  
    36  	nameLabels := toNameLabels(apiLabels, "networking-operator")
    37  	k8sNameLabels := labels.MustK8sMap(nameLabels)
    38  
    39  	if err := client.ApplyServiceAccount(&core.ServiceAccount{
    40  		ObjectMeta: mach.ObjectMeta{
    41  			Name:      nameLabels.Name(),
    42  			Namespace: "caos-system",
    43  			Labels:    k8sNameLabels,
    44  		},
    45  	}); err != nil {
    46  		return err
    47  	}
    48  
    49  	if err := client.ApplyClusterRole(&rbac.ClusterRole{
    50  		ObjectMeta: mach.ObjectMeta{
    51  			Name:   nameLabels.Name(),
    52  			Labels: k8sNameLabels,
    53  		},
    54  		Rules: []rbac.PolicyRule{{
    55  			APIGroups: []string{"*"},
    56  			Resources: []string{"*"},
    57  			Verbs:     []string{"*"},
    58  		}},
    59  	}); err != nil {
    60  		return err
    61  	}
    62  
    63  	if err := client.ApplyClusterRoleBinding(&rbac.ClusterRoleBinding{
    64  		ObjectMeta: mach.ObjectMeta{
    65  			Name:   nameLabels.Name(),
    66  			Labels: k8sNameLabels,
    67  		},
    68  
    69  		RoleRef: rbac.RoleRef{
    70  			APIGroup: "rbac.authorization.k8s.io",
    71  			Kind:     "ClusterRole",
    72  			Name:     nameLabels.Name(),
    73  		},
    74  		Subjects: []rbac.Subject{{
    75  			Kind:      "ServiceAccount",
    76  			Name:      nameLabels.Name(),
    77  			Namespace: "caos-system",
    78  		}},
    79  	}); err != nil {
    80  		return err
    81  	}
    82  
    83  	if !gitops {
    84  		crd := `apiVersion: apiextensions.k8s.io/v1beta1
    85  kind: CustomResourceDefinition
    86  metadata:
    87    annotations:
    88      controller-gen.kubebuilder.io/version: v0.2.2
    89    creationTimestamp: null
    90    name: networkings.caos.ch
    91  spec:
    92    group: caos.ch
    93    names:
    94      kind: Networking
    95      listKind: NetworkingList
    96      plural: networkings
    97      singular: networking
    98    scope: ""
    99    validation:
   100      openAPIV3Schema:
   101        properties:
   102          apiVersion:
   103            description: 'APIVersion defines the versioned schema of this representation
   104              of an object. Servers should convert recognized schemas to the latest
   105              internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
   106            type: string
   107          kind:
   108            description: 'Kind is a string value representing the REST resource this
   109              object represents. Servers may infer this from the endpoint the client
   110              submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
   111            type: string
   112          metadata:
   113            type: object
   114          spec:
   115            properties:
   116              kind:
   117                type: string
   118              networking:
   119                type: object
   120              spec:
   121                properties:
   122                  customImageRegistry:
   123                    description: 'Use this registry to pull the Networking-operator
   124                      image from @default: ghcr.io'
   125                    type: string
   126                  gitOps:
   127                    type: boolean
   128                  nodeSelector:
   129                    additionalProperties:
   130                      type: string
   131                    type: object
   132                  selfReconciling:
   133                    type: boolean
   134                  tolerations:
   135                    items:
   136                      description: The pod this Toleration is attached to tolerates
   137                        any taint that matches the triple <key,value,effect> using the
   138                        matching operator <operator>.
   139                      properties:
   140                        effect:
   141                          description: Effect indicates the taint effect to match. Empty
   142                            means match all taint effects. When specified, allowed values
   143                            are NoSchedule, PreferNoSchedule and NoExecute.
   144                          type: string
   145                        key:
   146                          description: Key is the taint key that the toleration applies
   147                            to. Empty means match all taint keys. If the key is empty,
   148                            operator must be Exists; this combination means to match
   149                            all values and all keys.
   150                          type: string
   151                        operator:
   152                          description: Operator represents a key's relationship to the
   153                            value. Valid operators are Exists and Equal. Defaults to
   154                            Equal. Exists is equivalent to wildcard for value, so that
   155                            a pod can tolerate all taints of a particular category.
   156                          type: string
   157                        tolerationSeconds:
   158                          description: TolerationSeconds represents the period of time
   159                            the toleration (which must be of effect NoExecute, otherwise
   160                            this field is ignored) tolerates the taint. By default,
   161                            it is not set, which means tolerate the taint forever (do
   162                            not evict). Zero and negative values will be treated as
   163                            0 (evict immediately) by the system.
   164                          format: int64
   165                          type: integer
   166                        value:
   167                          description: Value is the taint value the toleration matches
   168                            to. If the operator is Exists, the value should be empty,
   169                            otherwise just a regular string.
   170                          type: string
   171                      type: object
   172                    type: array
   173                  verbose:
   174                    type: boolean
   175                  version:
   176                    type: string
   177                required:
   178                - selfReconciling
   179                - verbose
   180                type: object
   181              version:
   182                type: string
   183            required:
   184            - kind
   185            - networking
   186            - spec
   187            - version
   188            type: object
   189          status:
   190            type: object
   191        type: object
   192    version: v1
   193    versions:
   194    - name: v1
   195      served: true
   196      storage: true
   197  status:
   198    acceptedNames:
   199      kind: ""
   200      plural: ""
   201    conditions: []
   202    storedVersions: []`
   203  
   204  		crdDefinition := &unstructured.Unstructured{}
   205  		if err := yaml.Unmarshal([]byte(crd), &crdDefinition.Object); err != nil {
   206  			return err
   207  		}
   208  
   209  		if err := client.ApplyCRDResource(
   210  			crdDefinition,
   211  		); err != nil {
   212  			return err
   213  		}
   214  		monitor.WithFields(map[string]interface{}{
   215  			"version": version,
   216  		}).Debug("Networking Operator crd ensured")
   217  	}
   218  
   219  	var (
   220  		cmd          = []string{"/orbctl", "start", "networking", "--kubeconfig", ""}
   221  		volumes      []core.Volume
   222  		volumeMounts []core.VolumeMount
   223  	)
   224  	if gitops {
   225  		cmd = append(cmd, "--gitops", "-f", "/secrets/orbconfig")
   226  		volumes = []core.Volume{{
   227  			Name: "orbconfig",
   228  			VolumeSource: core.VolumeSource{
   229  				Secret: &core.SecretVolumeSource{
   230  					SecretName: "caos",
   231  				},
   232  			},
   233  		}}
   234  		volumeMounts = []core.VolumeMount{{
   235  			Name:      "orbconfig",
   236  			ReadOnly:  true,
   237  			MountPath: "/secrets",
   238  		}}
   239  	}
   240  
   241  	if _, _, analyticsEnabled := mntr.Environment(); !analyticsEnabled {
   242  		cmd = append(cmd, "--disable-analytics")
   243  	}
   244  
   245  	deployment := &apps.Deployment{
   246  		ObjectMeta: mach.ObjectMeta{
   247  			Name:      nameLabels.Name(),
   248  			Namespace: "caos-system",
   249  			Labels:    k8sNameLabels,
   250  		},
   251  		Spec: apps.DeploymentSpec{
   252  			Replicas: int32Ptr(1),
   253  			Selector: &mach.LabelSelector{
   254  				MatchLabels: labels.MustK8sMap(labels.DeriveNameSelector(nameLabels, false)),
   255  			},
   256  			Template: core.PodTemplateSpec{
   257  				ObjectMeta: mach.ObjectMeta{
   258  					Labels: labels.MustK8sMap(labels.AsSelectable(nameLabels)),
   259  				},
   260  				Spec: core.PodSpec{
   261  					ServiceAccountName: nameLabels.Name(),
   262  					Containers: []core.Container{{
   263  						Name:            "networking",
   264  						ImagePullPolicy: core.PullIfNotPresent,
   265  						Image:           fmt.Sprintf("%s/caos/orbos:%s", imageRegistry, version),
   266  						Command:         cmd,
   267  						Args:            []string{},
   268  						Ports: []core.ContainerPort{{
   269  							Name:          "metrics",
   270  							ContainerPort: 2112,
   271  							Protocol:      "TCP",
   272  						}},
   273  						Resources: core.ResourceRequirements{
   274  							Limits: core.ResourceList{
   275  								"cpu":    resource.MustParse("500m"),
   276  								"memory": resource.MustParse("500Mi"),
   277  							},
   278  							Requests: core.ResourceList{
   279  								"cpu":    resource.MustParse("250m"),
   280  								"memory": resource.MustParse("250Mi"),
   281  							},
   282  						},
   283  						VolumeMounts: volumeMounts,
   284  					}},
   285  					NodeSelector:                  nodeselector,
   286  					Tolerations:                   tolerations,
   287  					Volumes:                       volumes,
   288  					TerminationGracePeriodSeconds: int64Ptr(10),
   289  				},
   290  			},
   291  		},
   292  	}
   293  	if err := client.ApplyDeployment(deployment, true); err != nil {
   294  		return err
   295  	}
   296  	monitor.WithFields(map[string]interface{}{
   297  		"version": version,
   298  	}).Debug("Networking Operator deployment ensured")
   299  
   300  	return nil
   301  }