From 5b8cc67a780a4a10118992e238f89b3e79eeff0a Mon Sep 17 00:00:00 2001 From: Neko Ayaka Date: Tue, 16 Apr 2024 18:03:50 +0800 Subject: [PATCH] docs: added detailed docs, updated gitignore, fixed incorrect copy in Dockerfile Signed-off-by: Neko Ayaka --- .gitignore | 3 + CONTRIBUTING.md | 74 +++++- Dockerfile | 2 +- dist/install.yaml | 588 ---------------------------------------------- 4 files changed, 77 insertions(+), 590 deletions(-) delete mode 100644 dist/install.yaml diff --git a/.gitignore b/.gitignore index 466f484..8e71281 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,9 @@ bin/* Dockerfile.cross +# Built application files +dist/ + # Test binary, built with `go test -c` *.test diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e935e07..41d4853 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -7,14 +7,53 @@ - `kubectl` version `v1.11.3+`. - Access to a Kubernetes `v1.11.3+` cluster (Either kind, minikube is suitable for local development). +## Development + ### Develop with `kind` We have pre-defined `kind` configurations in the `hack` directory to help you get started with the development environment. +> [!NOTE] +> Install kind if you haven't already. You can install it using the following command: +> +> ```shell +> go install sigs.k8s.io/kind@latest +> ``` + +To create a `kind` cluster with the configurations defined in `hack/kind-config.yaml`, run the following command: + ```sh -kind create cluster --config hack/kind.yaml +kind create cluster --config hack/kind-config.yaml +``` + +### Test controller locally + +#### Build and install CRD to local cluster + +```shell +make manifests && make install +``` + +#### Run the controller locally + +```shell +make run +``` + +#### Create a CRD to test the controller + +```shell +kubectl apply -f hack/ollama-model-phi-kind-cluster.yaml ``` +#### Verify the resources is reconciling + +```shell +kubectl describe models +``` + +## Deployment + ### To Deploy on the cluster **Build and push your image to the location specified by `IMG`:** @@ -79,6 +118,39 @@ make undeploy ## Project Distribution +### Test your build locally + +Developers should test their builds locally before pushing the changes to the repository. + +#### Test the build of `kollama` locally + +This reporsitory has been configured to build and release by using [GoReleaser](https://goreleaser.com/): + +> [!NOTE] +> Install GoReleaser if you haven't already by going through the steps in [GoReleaser Install](https://goreleaser.com/install/) + +```shell +goreleaser release --snapshot --clean +``` + +#### Test the build of `ollama-operator` locally + +To build the image for `ollama-operator` locally, run the following command: + +```shell +docker buildx build --platform linux/amd64,linux/arm64 . +``` + +#### Test the release of `kollama` to `krew` locally + +Please replace `` with the tag you want to release. + +```shell +docker run -v $(pwd)/.krew.yaml:/tmp/template-file.yaml ghcr.io/rajatjindal/krew-release-bot:v0.0.46 krew-release-bot template --tag --template-file /tmp/template-file.yaml +``` + +### Build and distribute the project + Following are the steps to build the installer and distribute this project to users. 1. Build the installer for the image built and published in the registry: diff --git a/Dockerfile b/Dockerfile index 002d478..745b86c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,7 +17,7 @@ RUN go mod download # Copy the go source COPY cmd/ cmd/ COPY api/ api/ -COPY internal/controller/ internal/controller/ +COPY internal/ internal/ COPY pkg/ pkg/ # Build diff --git a/dist/install.yaml b/dist/install.yaml deleted file mode 100644 index b420bda..0000000 --- a/dist/install.yaml +++ /dev/null @@ -1,588 +0,0 @@ -apiVersion: v1 -kind: Namespace -metadata: - labels: - app.kubernetes.io/component: manager - app.kubernetes.io/created-by: ollama-operator - app.kubernetes.io/instance: system - app.kubernetes.io/managed-by: kustomize - app.kubernetes.io/name: namespace - app.kubernetes.io/part-of: ollama-operator - control-plane: controller-manager - name: ollama-operator-system ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - name: models.ollama.ayaka.io -spec: - group: ollama.ayaka.io - names: - kind: Model - listKind: ModelList - plural: models - singular: model - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .spec.image - name: Model - type: string - - jsonPath: .status.conditions[0].type - name: Status - type: string - name: v1 - schema: - openAPIV3Schema: - description: Model is the Schema for the models API - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: ModelSpec defines the desired state of Model - properties: - image: - description: |- - Container image name. - More info: https://kubernetes.io/docs/concepts/containers/images - This field is optional to allow higher level config management to default or override - container images in workload controllers like Deployments and StatefulSets. - type: string - imagePullPolicy: - description: |- - Image pull policy. - One of Always, Never, IfNotPresent. - Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/containers/images#updating-images - type: string - imagePullSecrets: - description: |- - ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images used by this PodSpec. - If specified, these secrets will be passed to individual puller implementations for them to use. - More info: https://kubernetes.io/docs/concepts/containers/images#specifying-imagepullsecrets-on-a-pod - items: - description: |- - LocalObjectReference contains enough information to let you locate the - referenced object inside the same namespace. - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - type: object - x-kubernetes-map-type: atomic - type: array - persistentVolume: - description: |- - spec defines a specification of a persistent volume owned by the cluster. - Provisioned by an administrator. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistent-volumes - properties: - accessMode: - description: |- - accessModes contains all ways the volume can be mounted. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes - type: string - type: object - persistentVolumeClaim: - description: |- - persistentVolumeClaimVolumeSource represents a reference to a - PersistentVolumeClaim in the same namespace. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims - properties: - claimName: - description: |- - claimName is the name of a PersistentVolumeClaim in the same namespace as the pod using this volume. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims - type: string - readOnly: - description: |- - readOnly Will force the ReadOnly setting in VolumeMounts. - Default false. - type: boolean - required: - - claimName - type: object - replicas: - description: |- - Number of desired pods. This is a pointer to distinguish between explicit - zero and not specified. Defaults to 1. - format: int32 - type: integer - storageClassName: - description: |- - storageClassName is the name of StorageClass to which this persistent volume belongs. Empty value - means that this volume does not belong to any StorageClass. - type: string - required: - - image - type: object - status: - description: ModelStatus defines the observed state of Model - properties: - availableReplicas: - description: Total number of available pods (ready for at least minReadySeconds) - targeted by this deployment. - format: int32 - type: integer - conditions: - items: - properties: - lastTransitionTime: - description: Last time the condition transitioned from one status - to another. - format: date-time - type: string - lastUpdateTime: - description: The last time this condition was updated. - format: date-time - type: string - message: - description: A human readable message indicating details about - the transition. - type: string - reason: - description: The reason for the condition's last transition. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: Type of deployment condition. - type: string - required: - - status - - type - type: object - type: array - readyReplicas: - description: readyReplicas is the number of pods targeted by this - Deployment with a Ready Condition. - format: int32 - type: integer - replicas: - description: Total number of non-terminated pods targeted by this - deployment (their labels match the selector). - format: int32 - type: integer - unavailableReplicas: - description: |- - Total number of unavailable pods targeted by this deployment. This is the total number of - pods that are still required for the deployment to have 100% available capacity. They may - either be pods that are running but not yet available or pods that still have not been created. - format: int32 - type: integer - type: object - type: object - served: true - storage: true - subresources: - status: {} ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - labels: - app.kubernetes.io/managed-by: kustomize - app.kubernetes.io/name: ollama-operator - name: ollama-operator-controller-manager - namespace: ollama-operator-system ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - labels: - app.kubernetes.io/component: rbac - app.kubernetes.io/created-by: ollama-operator - app.kubernetes.io/instance: leader-election-role - app.kubernetes.io/managed-by: kustomize - app.kubernetes.io/name: role - app.kubernetes.io/part-of: ollama-operator - name: ollama-operator-leader-election-role - namespace: ollama-operator-system -rules: -- apiGroups: - - "" - resources: - - configmaps - verbs: - - get - - list - - watch - - create - - update - - patch - - delete -- apiGroups: - - coordination.k8s.io - resources: - - leases - verbs: - - get - - list - - watch - - create - - update - - patch - - delete -- apiGroups: - - "" - resources: - - events - verbs: - - create - - patch ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: ollama-operator-manager-role -rules: -- apiGroups: - - apps - resources: - - deployments - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - apps - resources: - - statefulsets - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - batch - resources: - - jobs - verbs: - - create - - delete - - deletecollection - - get - - list - - patch - - update - - watch -- apiGroups: - - batch - resources: - - jobs/status - verbs: - - get -- apiGroups: - - "" - resources: - - namespaces - verbs: - - get - - list - - watch -- apiGroups: - - "" - resources: - - persistentvolumeclaims - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - "" - resources: - - persistentvolumes - verbs: - - get - - list - - watch -- apiGroups: - - "" - resources: - - services - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - "" - resources: - - storageclasses - verbs: - - get - - list - - watch -- apiGroups: - - ollama.ayaka.io - resources: - - models - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - ollama.ayaka.io - resources: - - models/finalizers - verbs: - - update -- apiGroups: - - ollama.ayaka.io - resources: - - models/status - verbs: - - get - - patch - - update ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - labels: - app.kubernetes.io/component: kube-rbac-proxy - app.kubernetes.io/created-by: ollama-operator - app.kubernetes.io/instance: metrics-reader - app.kubernetes.io/managed-by: kustomize - app.kubernetes.io/name: clusterrole - app.kubernetes.io/part-of: ollama-operator - name: ollama-operator-metrics-reader -rules: -- nonResourceURLs: - - /metrics - verbs: - - get ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - labels: - app.kubernetes.io/component: kube-rbac-proxy - app.kubernetes.io/created-by: ollama-operator - app.kubernetes.io/instance: proxy-role - app.kubernetes.io/managed-by: kustomize - app.kubernetes.io/name: clusterrole - app.kubernetes.io/part-of: ollama-operator - name: ollama-operator-proxy-role -rules: -- apiGroups: - - authentication.k8s.io - resources: - - tokenreviews - verbs: - - create -- apiGroups: - - authorization.k8s.io - resources: - - subjectaccessreviews - verbs: - - create ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - labels: - app.kubernetes.io/component: rbac - app.kubernetes.io/created-by: ollama-operator - app.kubernetes.io/instance: leader-election-rolebinding - app.kubernetes.io/managed-by: kustomize - app.kubernetes.io/name: rolebinding - app.kubernetes.io/part-of: ollama-operator - name: ollama-operator-leader-election-rolebinding - namespace: ollama-operator-system -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: ollama-operator-leader-election-role -subjects: -- kind: ServiceAccount - name: ollama-operator-controller-manager - namespace: ollama-operator-system ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - labels: - app.kubernetes.io/component: rbac - app.kubernetes.io/created-by: ollama-operator - app.kubernetes.io/instance: manager-rolebinding - app.kubernetes.io/managed-by: kustomize - app.kubernetes.io/name: clusterrolebinding - app.kubernetes.io/part-of: ollama-operator - name: ollama-operator-manager-rolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: ollama-operator-manager-role -subjects: -- kind: ServiceAccount - name: ollama-operator-controller-manager - namespace: ollama-operator-system ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - labels: - app.kubernetes.io/component: kube-rbac-proxy - app.kubernetes.io/created-by: ollama-operator - app.kubernetes.io/instance: proxy-rolebinding - app.kubernetes.io/managed-by: kustomize - app.kubernetes.io/name: clusterrolebinding - app.kubernetes.io/part-of: ollama-operator - name: ollama-operator-proxy-rolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: ollama-operator-proxy-role -subjects: -- kind: ServiceAccount - name: ollama-operator-controller-manager - namespace: ollama-operator-system ---- -apiVersion: v1 -kind: Service -metadata: - labels: - app.kubernetes.io/component: kube-rbac-proxy - app.kubernetes.io/created-by: ollama-operator - app.kubernetes.io/instance: controller-manager-metrics-service - app.kubernetes.io/managed-by: kustomize - app.kubernetes.io/name: service - app.kubernetes.io/part-of: ollama-operator - control-plane: controller-manager - name: ollama-operator-controller-manager-metrics-service - namespace: ollama-operator-system -spec: - ports: - - name: https - port: 8443 - protocol: TCP - targetPort: https - selector: - control-plane: controller-manager ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app.kubernetes.io/component: manager - app.kubernetes.io/created-by: ollama-operator - app.kubernetes.io/instance: controller-manager - app.kubernetes.io/managed-by: kustomize - app.kubernetes.io/name: deployment - app.kubernetes.io/part-of: ollama-operator - control-plane: controller-manager - name: ollama-operator-controller-manager - namespace: ollama-operator-system -spec: - replicas: 1 - selector: - matchLabels: - control-plane: controller-manager - template: - metadata: - annotations: - kubectl.kubernetes.io/default-container: manager - labels: - control-plane: controller-manager - spec: - containers: - - args: - - --secure-listen-address=0.0.0.0:8443 - - --upstream=http://127.0.0.1:8080/ - - --logtostderr=true - - --v=0 - image: gcr.io/kubebuilder/kube-rbac-proxy:v0.15.0 - name: kube-rbac-proxy - ports: - - containerPort: 8443 - name: https - protocol: TCP - resources: - limits: - cpu: 500m - memory: 128Mi - requests: - cpu: 5m - memory: 64Mi - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - - args: - - --health-probe-bind-address=:8081 - - --metrics-bind-address=127.0.0.1:8080 - - --leader-elect - command: - - /manager - image: ghcr.io/nekomeowww/ollama-operator:latest - livenessProbe: - httpGet: - path: /healthz - port: 8081 - initialDelaySeconds: 15 - periodSeconds: 20 - name: manager - readinessProbe: - httpGet: - path: /readyz - port: 8081 - initialDelaySeconds: 5 - periodSeconds: 10 - resources: - limits: - cpu: 500m - memory: 128Mi - requests: - cpu: 10m - memory: 64Mi - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - securityContext: - runAsNonRoot: true - serviceAccountName: ollama-operator-controller-manager - terminationGracePeriodSeconds: 10