diff --git a/config/default/kustomization.yaml b/config/default/kustomization.yaml index 74d6d17..0639d7c 100644 --- a/config/default/kustomization.yaml +++ b/config/default/kustomization.yaml @@ -16,6 +16,7 @@ bases: - ../crd - ../rbac - ../manager +- ../nginx # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in # crd/kustomization.yaml #- ../webhook diff --git a/config/manager/kustomization.yaml b/config/manager/kustomization.yaml index 7a33ce9..f121b11 100644 --- a/config/manager/kustomization.yaml +++ b/config/manager/kustomization.yaml @@ -1,6 +1,8 @@ resources: - manager.yaml +namespace: system + generatorOptions: disableNameSuffixHash: true diff --git a/config/manager/manager.yaml b/config/manager/manager.yaml index 7874768..26eef16 100644 --- a/config/manager/manager.yaml +++ b/config/manager/manager.yaml @@ -1,15 +1,7 @@ -apiVersion: v1 -kind: Namespace -metadata: - labels: - control-plane: controller-manager - name: system ---- apiVersion: apps/v1 kind: Deployment metadata: name: controller-manager - namespace: system labels: control-plane: controller-manager spec: diff --git a/config/nginx/deployment.yaml b/config/nginx/deployment.yaml new file mode 100644 index 0000000..97700f9 --- /dev/null +++ b/config/nginx/deployment.yaml @@ -0,0 +1,41 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: nginx-public +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 3Gi +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx + labels: + app.kubernetes.io/name: osbuilder-nginx +spec: + selector: + matchLabels: + app.kubernetes.io/name: osbuilder-nginx + replicas: 1 + template: + metadata: + labels: + app.kubernetes.io/name: osbuilder-nginx + spec: + containers: + - image: nginx + name: nginx + volumeMounts: + - mountPath: "/usr/share/nginx/html" + name: nginx-public + ports: + - containerPort: 80 + serviceAccountName: controller-manager + terminationGracePeriodSeconds: 10 + volumes: + - name: nginx-public + persistentVolumeClaim: + claimName: nginx-public diff --git a/config/nginx/kustomization.yaml b/config/nginx/kustomization.yaml new file mode 100644 index 0000000..a944d00 --- /dev/null +++ b/config/nginx/kustomization.yaml @@ -0,0 +1,3 @@ +resources: +- deployment.yaml +- service.yaml diff --git a/config/nginx/service.yaml b/config/nginx/service.yaml new file mode 100644 index 0000000..f2ac78b --- /dev/null +++ b/config/nginx/service.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Service +metadata: + name: osbuilder-nginx +spec: + type: NodePort + selector: + app.kubernetes.io/name: osbuilder-nginx + ports: + - protocol: TCP + port: 80 + targetPort: 80 diff --git a/config/rbac/role_custom.yaml b/config/rbac/role_custom.yaml index d3f8bd2..53e0dbd 100644 --- a/config/rbac/role_custom.yaml +++ b/config/rbac/role_custom.yaml @@ -47,9 +47,9 @@ rules: - create - update - apiGroups: - - "apps" + - "batch" resources: - - deployments + - jobs verbs: - get - create diff --git a/controllers/deployment.go b/controllers/job.go similarity index 82% rename from controllers/deployment.go rename to controllers/job.go index d5dbc7b..3eaf1be 100644 --- a/controllers/deployment.go +++ b/controllers/job.go @@ -20,13 +20,13 @@ import ( "fmt" buildv1alpha1 "github.com/kairos-io/osbuilder/api/v1alpha1" - appsv1 "k8s.io/api/apps/v1" + batchv1 "k8s.io/api/batch/v1" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -func genDeploymentLabel(s string) map[string]string { +func genJobLabel(s string) map[string]string { return map[string]string{ "osbuild": "workload" + s, } @@ -64,7 +64,7 @@ func createImageContainer(containerImage string, pushOptions buildv1alpha1.Push) Command: []string{"/bin/bash", "-cxe"}, Args: []string{ fmt.Sprintf( - "tar -czvpf test.tar -C /rootfs . && luet util pack %s test.tar image.tar && mv image.tar /public", + "tar -czvpf test.tar -C /rootfs . && luet util pack %s test.tar image.tar && mv image.tar /artifacts", pushOptions.ImageName, ), }, @@ -74,8 +74,8 @@ func createImageContainer(containerImage string, pushOptions buildv1alpha1.Push) MountPath: "/rootfs", }, { - Name: "public", - MountPath: "/public", + Name: "artifacts", + MountPath: "/artifacts", }, }, } @@ -104,8 +104,7 @@ func osReleaseContainer(containerImage string) v1.Container { } } -func (r *OSArtifactReconciler) genDeployment(artifact buildv1alpha1.OSArtifact, svc *v1.Service) *appsv1.Deployment { - // TODO: svc is unused, but could be used in the future to generate the Netboot URL +func (r *OSArtifactReconciler) genJob(artifact buildv1alpha1.OSArtifact) *batchv1.Job { objMeta := metav1.ObjectMeta{ Name: artifact.Name, Namespace: artifact.Namespace, @@ -118,14 +117,14 @@ func (r *OSArtifactReconciler) genDeployment(artifact buildv1alpha1.OSArtifact, serviceAccount := false cmd := fmt.Sprintf( - "/entrypoint.sh --debug --name %s build-iso --date=false --output /public dir:/rootfs", + "/entrypoint.sh --debug --name %s build-iso --date=false --output /artifacts dir:/rootfs", artifact.Name, ) volumeMounts := []v1.VolumeMount{ { - Name: "public", - MountPath: "/public", + Name: "artifacts", + MountPath: "/artifacts", }, { Name: "rootfs", @@ -142,7 +141,7 @@ func (r *OSArtifactReconciler) genDeployment(artifact buildv1alpha1.OSArtifact, } cloudImgCmd := fmt.Sprintf( - "/raw-images.sh /rootfs /public/%s.raw", + "/raw-images.sh /rootfs /artifacts/%s.raw", artifact.Name, ) @@ -158,7 +157,7 @@ func (r *OSArtifactReconciler) genDeployment(artifact buildv1alpha1.OSArtifact, if artifact.Spec.CloudConfig != "" || artifact.Spec.GRUBConfig != "" { cmd = fmt.Sprintf( - "/entrypoint.sh --debug --name %s build-iso --date=false --overlay-iso /iso/iso-overlay --output /public dir:/rootfs", + "/entrypoint.sh --debug --name %s build-iso --date=false --overlay-iso /iso/iso-overlay --output /artifacts dir:/rootfs", artifact.Name, ) } @@ -207,7 +206,7 @@ func (r *OSArtifactReconciler) genDeployment(artifact buildv1alpha1.OSArtifact, }}, Args: []string{ fmt.Sprintf( - "/netboot.sh /public/%s.iso /public/%s", + "/netboot.sh /artifacts/%s.iso /artifacts/%s", artifact.Name, artifact.Name, ), @@ -223,7 +222,7 @@ func (r *OSArtifactReconciler) genDeployment(artifact buildv1alpha1.OSArtifact, Command: []string{"/bin/bash", "-cxe"}, Args: []string{ fmt.Sprintf( - "/azure.sh /public/%s.raw /public/%s.vhd", + "/azure.sh /artifacts/%s.raw /artifacts/%s.vhd", artifact.Name, artifact.Name, ), @@ -239,7 +238,7 @@ func (r *OSArtifactReconciler) genDeployment(artifact buildv1alpha1.OSArtifact, Command: []string{"/bin/bash", "-cxe"}, Args: []string{ fmt.Sprintf( - "/gce.sh /public/%s.raw /public/%s.gce.raw", + "/gce.sh /artifacts/%s.raw /artifacts/%s.gce.raw", artifact.Name, artifact.Name, ), @@ -247,20 +246,6 @@ func (r *OSArtifactReconciler) genDeployment(artifact buildv1alpha1.OSArtifact, VolumeMounts: volumeMounts, } - servingContainer := v1.Container{ - ImagePullPolicy: v1.PullAlways, - SecurityContext: &v1.SecurityContext{Privileged: &privileged}, - Name: "serve", - Ports: []v1.ContainerPort{v1.ContainerPort{Name: "http", ContainerPort: 80}}, - Image: r.ServingImage, - VolumeMounts: []v1.VolumeMount{ - { - Name: "public", - MountPath: "/usr/share/nginx/html", - }, - }, - } - pod := v1.PodSpec{ AutomountServiceAccountToken: &serviceAccount, Volumes: []v1.Volume{ @@ -313,26 +298,25 @@ func (r *OSArtifactReconciler) genDeployment(artifact buildv1alpha1.OSArtifact, } if pushImage { - pod.InitContainers = append(pod.InitContainers, createImageContainer(r.ToolImage, artifact.Spec.PushOptions)) + pod.Containers = []v1.Container{ + createImageContainer(r.ToolImage, artifact.Spec.PushOptions), + } } - pod.Containers = []v1.Container{servingContainer} + jobLabels := genJobLabel(artifact.Name) - deploymentLabels := genDeploymentLabel(artifact.Name) - replicas := int32(1) - - return &appsv1.Deployment{ + job := batchv1.Job{ ObjectMeta: objMeta, - - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: deploymentLabels}, - Replicas: &replicas, + Spec: batchv1.JobSpec{ + Selector: &metav1.LabelSelector{MatchLabels: jobLabels}, Template: v1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ - Labels: deploymentLabels, + Labels: jobLabels, }, Spec: pod, }, }, } + + return &job } diff --git a/controllers/osartifact_controller.go b/controllers/osartifact_controller.go index b10a7d7..4d8514b 100644 --- a/controllers/osartifact_controller.go +++ b/controllers/osartifact_controller.go @@ -98,34 +98,16 @@ func (r *OSArtifactReconciler) Reconcile(ctx context.Context, req ctrl.Request) return ctrl.Result{Requeue: true}, err } - desiredService := genService(osbuild) - logger.Info(fmt.Sprintf("Checking service %v", osbuild)) - - svc, err := r.clientSet.CoreV1().Services(req.Namespace).Get(ctx, desiredService.Name, v1.GetOptions{}) - if svc == nil || apierrors.IsNotFound(err) { - logger.Info(fmt.Sprintf("Creating service %v", desiredService)) - - svc, err = r.clientSet.CoreV1().Services(req.Namespace).Create(ctx, desiredService, v1.CreateOptions{}) - if err != nil { - logger.Error(err, "Failed while creating svc") - return ctrl.Result{}, err - } - - return ctrl.Result{Requeue: true}, err - } - if err != nil { - return ctrl.Result{Requeue: true}, err - } logger.Info(fmt.Sprintf("Checking deployment %v", osbuild)) - desiredDeployment := r.genDeployment(osbuild, svc) - deployment, err := r.clientSet.AppsV1().Deployments(req.Namespace).Get(ctx, desiredDeployment.Name, v1.GetOptions{}) - if deployment == nil || apierrors.IsNotFound(err) { - logger.Info(fmt.Sprintf("Creating Deployment %v", deployment)) + desiredJob := r.genJob(osbuild) + job, err := r.clientSet.BatchV1().Jobs(req.Namespace).Get(ctx, desiredJob.Name, v1.GetOptions{}) + if job == nil || apierrors.IsNotFound(err) { + logger.Info(fmt.Sprintf("Creating Job %v", job)) - deployment, err = r.clientSet.AppsV1().Deployments(req.Namespace).Create(ctx, desiredDeployment, v1.CreateOptions{}) + job, err = r.clientSet.BatchV1().Jobs(req.Namespace).Create(ctx, desiredJob, v1.CreateOptions{}) if err != nil { - logger.Error(err, "Failed while creating deployment") + logger.Error(err, "Failed while creating job") return ctrl.Result{}, nil } @@ -143,7 +125,7 @@ func (r *OSArtifactReconciler) Reconcile(ctx context.Context, req ctrl.Request) if err != nil { return ctrl.Result{}, err } - if deployment.Status.ReadyReplicas == deployment.Status.Replicas { + if job.Status.Succeeded > 0 { copy.Status.Phase = "Ready" } else if copy.Status.Phase != "Building" { copy.Status.Phase = "Building" diff --git a/controllers/service.go b/controllers/service.go deleted file mode 100644 index 21f805c..0000000 --- a/controllers/service.go +++ /dev/null @@ -1,39 +0,0 @@ -/* -Copyright 2022. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package controllers - -import ( - buildv1alpha1 "github.com/kairos-io/osbuilder/api/v1alpha1" - v1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -func genService(artifact buildv1alpha1.OSArtifact) *v1.Service { - objMeta := metav1.ObjectMeta{ - Name: artifact.Name, - Namespace: artifact.Namespace, - OwnerReferences: genOwner(artifact), - } - return &v1.Service{ - ObjectMeta: objMeta, - Spec: v1.ServiceSpec{ - Type: v1.ServiceTypeNodePort, - Ports: []v1.ServicePort{{Name: "http", Port: int32(80)}}, - Selector: genDeploymentLabel(artifact.Name), - }, - } -}